diff --git a/Package.swift b/Package.swift index 9a9c69d..fd99f00 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,12 @@ import PackageDescription +#if os(Linux) +let sqlitePkg = "sqlite3" +#else +let sqlitePkg: String? = nil +#endif + let package = Package( name: "DataLiteC", platforms: [ @@ -13,58 +19,9 @@ let package = Package( .library(name: "DataLiteC", targets: ["DataLiteC"]) ], targets: [ - .target( - name: "DataLiteC", - sources: ["libtomcrypt", "sqlcipher"], - publicHeadersPath: "sqlcipher", - cSettings: [ - .headerSearchPath("libtomcrypt/headers"), - .define("MIN(x,y)", to: "(((x)<(y))?(x):(y))"), - .define("MAX(x,y)", to: "(((x)>(y))?(x):(y))"), - .define("SQLCIPHER_CRYPTO_LIBTOMCRYPT"), - .define("SQLITE_HOMEGROWN_RECURSIVE_MUTEX"), - .define("SQLITE_HAS_CODEC"), - .define("SQLITE_EXTRA_INIT", to: "sqlcipher_extra_init"), - .define("SQLITE_EXTRA_SHUTDOWN", to: "sqlcipher_extra_shutdown"), - .define("SQLITE_THREADSAFE", to: "1"), - .define("SQLITE_TEMP_STORE", to: "2"), - .define("SQLITE_SECURE_DELETE"), - .define("SQLITE_ENABLE_COLUMN_METADATA"), - .define("SQLITE_ENABLE_DBSTAT_VTAB", .when(configuration: .debug)), - .define("SQLITE_ENABLE_STMTVTAB", .when(configuration: .debug)), - .define("SQLITE_ENABLE_API_ARMOR", .when(configuration: .debug)), - .define("SQLITE_DQS", to: "0"), - .define("SQLITE_ENABLE_PREUPDATE_HOOK"), - .define("SQLITE_LIKE_DOESNT_MATCH_BLOBS"), - .define("SQLITE_OMIT_DEPRECATED"), - .define("SQLITE_OMIT_SHARED_CACHE"), - .define("SQLITE_USE_URI"), - .define("HAVE_GETHOSTUUID", to: "0"), - .define("HAVE_STDINT_H"), - .define("LTC_NO_TEST"), - .define("LTC_NO_FILE"), - .define("LTC_NO_HASHES"), - .define("LTC_NO_PKCS"), - .define("LTC_NO_MISC"), - .define("LTC_NO_PK"), - .define("LTC_NO_MACS"), - .define("LTC_MINIMAL"), - .define("LTC_SHA512"), - .define("LTC_SHA1"), - .define("LTC_HMAC"), - .define("LTC_PKCS_5"), - .define("LTC_HASH_HELPERS") - ], - linkerSettings: [ - .linkedLibrary("log", .when(platforms: [.android])) - ] - ), - .testTarget( - name: "DataLiteCTests", - dependencies: ["DataLiteC"], - cSettings: [ - .define("SQLITE_HAS_CODEC") - ] - ) + .systemLibrary(name: "DataLiteC", pkgConfig: sqlitePkg, providers: [ + .apt(["sqlite3", "libsqlite3-dev"]), + .brew(["sqlite"]) + ]) ] ) diff --git a/README.md b/README.md index 733ad9a..d111167 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ -# DataLiteC +# DataLiteC Package -**DataLiteC** is a Swift package that provides low-level access to an embedded, fully-encrypted SQLite engine. It includes [SQLCipher](https://github.com/sqlcipher/sqlcipher) and [LibTomCrypt](https://github.com/libtom/libtomcrypt) as source dependencies, with no external installation required. +**DataLiteC** is a Swift package that provides a system interface to the SQLite C library. It supports **macOS**, **iOS**, and **Linux** platforms, using the system SQLite library via `pkg-config`. ## Overview -**DataLiteC** provides direct access to the C API of SQLCipher, a fully encrypted drop-in replacement for SQLite. It is designed for Swift projects that require precise, low-level control over encrypted database operations without relying on system-installed libraries. - -The package statically includes both SQLCipher and LibTomCrypt as source code, making it fully self-contained and portable across **macOS**, **iOS**, and **Linux** platforms. - -DataLiteC does not introduce any abstractions or Swift-specific layers — it simply exposes the raw C interface, allowing complete control and maximum compatibility with the underlying engine. +DataLiteC is a Swift system library wrapper that links directly to the SQLite C API. It does not add any abstractions and enables direct usage of SQLite's C functions within Swift code. ## Installation -To add **DataLiteC** to your project, include it in the `dependencies` section of your `Package.swift` file: +### Adding DataLiteC to Your Project + +To use DataLiteC in your Swift project, add it to the dependencies section of your `Package.swift` file: ```swift // swift-tools-version: 5.10 @@ -22,21 +20,38 @@ import PackageDescription let package = Package( name: "YourProject", dependencies: [ - .package(url: "https://github.com/angd-dev/data-lite-c.git", from: "2.0.0") + .package(url: "https://github.com/angd-dev/data-lite-c.git", from: "1.0.0") ], targets: [ - .target(name: "YourTarget", dependencies: [ - .product(name: "DataLiteC", package: "data-lite-c") - ]) + .target( + name: "YourTarget", + dependencies: [ + .product(name: "DataLiteC", package: "data-lite-c") + ] + ) ] ) ``` -No additional setup or system packages are required — all dependencies are bundled and built automatically. +### System Requirements + +DataLiteC requires SQLite to be installed on your system: + +- **Linux**: Install `sqlite3` and development headers: + + ```bash + sudo apt-get install sqlite3 libsqlite3-dev + ``` + +- **macOS**: Install SQLite using Homebrew: + + ```bash + brew install sqlite + ``` ## Usage -Once the package is added, you can import `DataLiteC` and use the raw SQLCipher C API directly in Swift: +Once the package is added, you can import it and use SQLite's C API directly: ```swift import DataLiteC @@ -50,86 +65,20 @@ if sqlite3_open(":memory:", &db) == SQLITE_OK { } ``` -To use encryption with SQLCipher, set the encryption key immediately after opening the database: +## Troubleshooting -```swift -if sqlite3_open("secure.db", &db) == SQLITE_OK { - let key = "your-secret-passphrase" - sqlite3_key(db, key, Int32(key.utf8.count)) +If you encounter build errors such as missing `sqlite3.h`, ensure that `pkg-config` can locate SQLite: - // It's good practice to verify key correctness - if sqlite3_exec(db, "SELECT count(*) FROM sqlite_master;", nil, nil, nil) == SQLITE_OK { - print("Successfully opened encrypted database.") - } else { - print("Invalid encryption key or corrupted database.") - } +```bash +pkg-config --cflags sqlite3 +``` - sqlite3_close(db) -} +If the command returns nothing, manually set the `PKG_CONFIG_PATH`: + +```bash +export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" ``` ## License -### DataLiteC - This project is licensed under the MIT License. See the `LICENSE` file for details. - -### SQLCipher - -``` -Copyright (c) 2025, 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. -``` - -### LibTomCrypt - -``` - The LibTom license - -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to -``` diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes.c b/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes.c deleted file mode 100644 index ea65a6b..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes.c +++ /dev/null @@ -1,738 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* AES implementation by Tom St Denis - * - * Derived from the Public Domain source code by - ---- - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto ---- - */ -/** - @file aes.c - Implementation of AES -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_RIJNDAEL - -#ifndef ENCRYPT_ONLY - -#define SETUP rijndael_setup -#define ECB_ENC rijndael_ecb_encrypt -#define ECB_DEC rijndael_ecb_decrypt -#define ECB_DONE rijndael_done -#define ECB_TEST rijndael_test -#define ECB_KS rijndael_keysize - -const struct ltc_cipher_descriptor rijndael_desc = -{ - "rijndael", - 6, - 16, 32, 16, 10, - SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#else - -#define SETUP rijndael_enc_setup -#define ECB_ENC rijndael_enc_ecb_encrypt -#define ECB_KS rijndael_enc_keysize -#define ECB_DONE rijndael_enc_done - -const struct ltc_cipher_descriptor rijndael_enc_desc = -{ - "rijndael", - 6, - 16, 32, 16, 10, - SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#endif - -#ifndef LTC_AES_TAB_C -#define LTC_AES_TAB_C -#include "aes_tab.c" -#endif - -static ulong32 setup_mix(ulong32 temp) -{ - return (Te4_3[LTC_BYTE(temp, 2)]) ^ - (Te4_2[LTC_BYTE(temp, 1)]) ^ - (Te4_1[LTC_BYTE(temp, 0)]) ^ - (Te4_0[LTC_BYTE(temp, 3)]); -} - -#ifndef ENCRYPT_ONLY -#ifdef LTC_SMALL_CODE -static ulong32 setup_mix2(ulong32 temp) -{ - return Td0(255 & Te4[LTC_BYTE(temp, 3)]) ^ - Td1(255 & Te4[LTC_BYTE(temp, 2)]) ^ - Td2(255 & Te4[LTC_BYTE(temp, 1)]) ^ - Td3(255 & Te4[LTC_BYTE(temp, 0)]); -} -#endif -#endif - - /** - Initialize the AES (Rijndael) block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int i; - ulong32 temp, *rk, *K; -#ifndef ENCRYPT_ONLY - ulong32 *rrk; -#endif - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 16 && keylen != 24 && keylen != 32) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) { - return CRYPT_INVALID_ROUNDS; - } - - skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; - K = LTC_ALIGN_BUF(skey->rijndael.K, 16); - skey->rijndael.eK = K; - K += 60; - skey->rijndael.dK = K; - - /* setup the forward key */ - i = 0; - rk = skey->rijndael.eK; - LOAD32H(rk[0], key ); - LOAD32H(rk[1], key + 4); - LOAD32H(rk[2], key + 8); - LOAD32H(rk[3], key + 12); - if (keylen == 16) { - for (;;) { - temp = rk[3]; - rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - break; - } - rk += 4; - } - } else if (keylen == 24) { - LOAD32H(rk[4], key + 16); - LOAD32H(rk[5], key + 20); - for (;;) { - #ifdef _MSC_VER - temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; - #else - temp = rk[5]; - #endif - rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) { - break; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } else if (keylen == 32) { - LOAD32H(rk[4], key + 16); - LOAD32H(rk[5], key + 20); - LOAD32H(rk[6], key + 24); - LOAD32H(rk[7], key + 28); - for (;;) { - #ifdef _MSC_VER - temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; - #else - temp = rk[7]; - #endif - rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - break; - } - temp = rk[11]; - rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8)); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - rk += 8; - } - } else { - /* this can't happen */ - /* coverity[dead_error_line] */ - return CRYPT_ERROR; - } - -#ifndef ENCRYPT_ONLY - /* setup the inverse key now */ - rk = skey->rijndael.dK; - rrk = skey->rijndael.eK + (28 + keylen) - 4; - - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - /* copy first */ - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk = *rrk; - rk -= 3; rrk -= 3; - - for (i = 1; i < skey->rijndael.Nr; i++) { - rrk -= 4; - rk += 4; - #ifdef LTC_SMALL_CODE - temp = rrk[0]; - rk[0] = setup_mix2(temp); - temp = rrk[1]; - rk[1] = setup_mix2(temp); - temp = rrk[2]; - rk[2] = setup_mix2(temp); - temp = rrk[3]; - rk[3] = setup_mix2(temp); - #else - temp = rrk[0]; - rk[0] = - Tks0[LTC_BYTE(temp, 3)] ^ - Tks1[LTC_BYTE(temp, 2)] ^ - Tks2[LTC_BYTE(temp, 1)] ^ - Tks3[LTC_BYTE(temp, 0)]; - temp = rrk[1]; - rk[1] = - Tks0[LTC_BYTE(temp, 3)] ^ - Tks1[LTC_BYTE(temp, 2)] ^ - Tks2[LTC_BYTE(temp, 1)] ^ - Tks3[LTC_BYTE(temp, 0)]; - temp = rrk[2]; - rk[2] = - Tks0[LTC_BYTE(temp, 3)] ^ - Tks1[LTC_BYTE(temp, 2)] ^ - Tks2[LTC_BYTE(temp, 1)] ^ - Tks3[LTC_BYTE(temp, 0)]; - temp = rrk[3]; - rk[3] = - Tks0[LTC_BYTE(temp, 3)] ^ - Tks1[LTC_BYTE(temp, 2)] ^ - Tks2[LTC_BYTE(temp, 1)] ^ - Tks3[LTC_BYTE(temp, 0)]; - #endif - - } - - /* copy last */ - rrk -= 4; - rk += 4; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk = *rrk; -#endif /* ENCRYPT_ONLY */ - - return CRYPT_OK; -} - -/** - Encrypts a block of text with AES - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 s0, s1, s2, s3, t0, t1, t2, t3; - const ulong32 *rk; - int Nr, r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - Nr = skey->rijndael.Nr; - - if (Nr < 2 || Nr > 16) - return CRYPT_INVALID_ROUNDS; - - rk = skey->rijndael.eK; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - LOAD32H(s0, pt ); s0 ^= rk[0]; - LOAD32H(s1, pt + 4); s1 ^= rk[1]; - LOAD32H(s2, pt + 8); s2 ^= rk[2]; - LOAD32H(s3, pt + 12); s3 ^= rk[3]; - -#ifdef LTC_SMALL_CODE - - for (r = 0; ; r++) { - rk += 4; - t0 = - Te0(LTC_BYTE(s0, 3)) ^ - Te1(LTC_BYTE(s1, 2)) ^ - Te2(LTC_BYTE(s2, 1)) ^ - Te3(LTC_BYTE(s3, 0)) ^ - rk[0]; - t1 = - Te0(LTC_BYTE(s1, 3)) ^ - Te1(LTC_BYTE(s2, 2)) ^ - Te2(LTC_BYTE(s3, 1)) ^ - Te3(LTC_BYTE(s0, 0)) ^ - rk[1]; - t2 = - Te0(LTC_BYTE(s2, 3)) ^ - Te1(LTC_BYTE(s3, 2)) ^ - Te2(LTC_BYTE(s0, 1)) ^ - Te3(LTC_BYTE(s1, 0)) ^ - rk[2]; - t3 = - Te0(LTC_BYTE(s3, 3)) ^ - Te1(LTC_BYTE(s0, 2)) ^ - Te2(LTC_BYTE(s1, 1)) ^ - Te3(LTC_BYTE(s2, 0)) ^ - rk[3]; - if (r == Nr-2) { - break; - } - s0 = t0; s1 = t1; s2 = t2; s3 = t3; - } - rk += 4; - -#else - - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Te0(LTC_BYTE(s0, 3)) ^ - Te1(LTC_BYTE(s1, 2)) ^ - Te2(LTC_BYTE(s2, 1)) ^ - Te3(LTC_BYTE(s3, 0)) ^ - rk[4]; - t1 = - Te0(LTC_BYTE(s1, 3)) ^ - Te1(LTC_BYTE(s2, 2)) ^ - Te2(LTC_BYTE(s3, 1)) ^ - Te3(LTC_BYTE(s0, 0)) ^ - rk[5]; - t2 = - Te0(LTC_BYTE(s2, 3)) ^ - Te1(LTC_BYTE(s3, 2)) ^ - Te2(LTC_BYTE(s0, 1)) ^ - Te3(LTC_BYTE(s1, 0)) ^ - rk[6]; - t3 = - Te0(LTC_BYTE(s3, 3)) ^ - Te1(LTC_BYTE(s0, 2)) ^ - Te2(LTC_BYTE(s1, 1)) ^ - Te3(LTC_BYTE(s2, 0)) ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Te0(LTC_BYTE(t0, 3)) ^ - Te1(LTC_BYTE(t1, 2)) ^ - Te2(LTC_BYTE(t2, 1)) ^ - Te3(LTC_BYTE(t3, 0)) ^ - rk[0]; - s1 = - Te0(LTC_BYTE(t1, 3)) ^ - Te1(LTC_BYTE(t2, 2)) ^ - Te2(LTC_BYTE(t3, 1)) ^ - Te3(LTC_BYTE(t0, 0)) ^ - rk[1]; - s2 = - Te0(LTC_BYTE(t2, 3)) ^ - Te1(LTC_BYTE(t3, 2)) ^ - Te2(LTC_BYTE(t0, 1)) ^ - Te3(LTC_BYTE(t1, 0)) ^ - rk[2]; - s3 = - Te0(LTC_BYTE(t3, 3)) ^ - Te1(LTC_BYTE(t0, 2)) ^ - Te2(LTC_BYTE(t1, 1)) ^ - Te3(LTC_BYTE(t2, 0)) ^ - rk[3]; - } - -#endif - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4_3[LTC_BYTE(t0, 3)]) ^ - (Te4_2[LTC_BYTE(t1, 2)]) ^ - (Te4_1[LTC_BYTE(t2, 1)]) ^ - (Te4_0[LTC_BYTE(t3, 0)]) ^ - rk[0]; - STORE32H(s0, ct); - s1 = - (Te4_3[LTC_BYTE(t1, 3)]) ^ - (Te4_2[LTC_BYTE(t2, 2)]) ^ - (Te4_1[LTC_BYTE(t3, 1)]) ^ - (Te4_0[LTC_BYTE(t0, 0)]) ^ - rk[1]; - STORE32H(s1, ct+4); - s2 = - (Te4_3[LTC_BYTE(t2, 3)]) ^ - (Te4_2[LTC_BYTE(t3, 2)]) ^ - (Te4_1[LTC_BYTE(t0, 1)]) ^ - (Te4_0[LTC_BYTE(t1, 0)]) ^ - rk[2]; - STORE32H(s2, ct+8); - s3 = - (Te4_3[LTC_BYTE(t3, 3)]) ^ - (Te4_2[LTC_BYTE(t0, 2)]) ^ - (Te4_1[LTC_BYTE(t1, 1)]) ^ - (Te4_0[LTC_BYTE(t2, 0)]) ^ - rk[3]; - STORE32H(s3, ct+12); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_rijndael_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); - return err; -} -#endif - -#ifndef ENCRYPT_ONLY - -/** - Decrypts a block of text with AES - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 s0, s1, s2, s3, t0, t1, t2, t3; - const ulong32 *rk; - int Nr, r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - Nr = skey->rijndael.Nr; - - if (Nr < 2 || Nr > 16) - return CRYPT_INVALID_ROUNDS; - - rk = skey->rijndael.dK; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - LOAD32H(s0, ct ); s0 ^= rk[0]; - LOAD32H(s1, ct + 4); s1 ^= rk[1]; - LOAD32H(s2, ct + 8); s2 ^= rk[2]; - LOAD32H(s3, ct + 12); s3 ^= rk[3]; - -#ifdef LTC_SMALL_CODE - for (r = 0; ; r++) { - rk += 4; - t0 = - Td0(LTC_BYTE(s0, 3)) ^ - Td1(LTC_BYTE(s3, 2)) ^ - Td2(LTC_BYTE(s2, 1)) ^ - Td3(LTC_BYTE(s1, 0)) ^ - rk[0]; - t1 = - Td0(LTC_BYTE(s1, 3)) ^ - Td1(LTC_BYTE(s0, 2)) ^ - Td2(LTC_BYTE(s3, 1)) ^ - Td3(LTC_BYTE(s2, 0)) ^ - rk[1]; - t2 = - Td0(LTC_BYTE(s2, 3)) ^ - Td1(LTC_BYTE(s1, 2)) ^ - Td2(LTC_BYTE(s0, 1)) ^ - Td3(LTC_BYTE(s3, 0)) ^ - rk[2]; - t3 = - Td0(LTC_BYTE(s3, 3)) ^ - Td1(LTC_BYTE(s2, 2)) ^ - Td2(LTC_BYTE(s1, 1)) ^ - Td3(LTC_BYTE(s0, 0)) ^ - rk[3]; - if (r == Nr-2) { - break; - } - s0 = t0; s1 = t1; s2 = t2; s3 = t3; - } - rk += 4; - -#else - - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - - t0 = - Td0(LTC_BYTE(s0, 3)) ^ - Td1(LTC_BYTE(s3, 2)) ^ - Td2(LTC_BYTE(s2, 1)) ^ - Td3(LTC_BYTE(s1, 0)) ^ - rk[4]; - t1 = - Td0(LTC_BYTE(s1, 3)) ^ - Td1(LTC_BYTE(s0, 2)) ^ - Td2(LTC_BYTE(s3, 1)) ^ - Td3(LTC_BYTE(s2, 0)) ^ - rk[5]; - t2 = - Td0(LTC_BYTE(s2, 3)) ^ - Td1(LTC_BYTE(s1, 2)) ^ - Td2(LTC_BYTE(s0, 1)) ^ - Td3(LTC_BYTE(s3, 0)) ^ - rk[6]; - t3 = - Td0(LTC_BYTE(s3, 3)) ^ - Td1(LTC_BYTE(s2, 2)) ^ - Td2(LTC_BYTE(s1, 1)) ^ - Td3(LTC_BYTE(s0, 0)) ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - - s0 = - Td0(LTC_BYTE(t0, 3)) ^ - Td1(LTC_BYTE(t3, 2)) ^ - Td2(LTC_BYTE(t2, 1)) ^ - Td3(LTC_BYTE(t1, 0)) ^ - rk[0]; - s1 = - Td0(LTC_BYTE(t1, 3)) ^ - Td1(LTC_BYTE(t0, 2)) ^ - Td2(LTC_BYTE(t3, 1)) ^ - Td3(LTC_BYTE(t2, 0)) ^ - rk[1]; - s2 = - Td0(LTC_BYTE(t2, 3)) ^ - Td1(LTC_BYTE(t1, 2)) ^ - Td2(LTC_BYTE(t0, 1)) ^ - Td3(LTC_BYTE(t3, 0)) ^ - rk[2]; - s3 = - Td0(LTC_BYTE(t3, 3)) ^ - Td1(LTC_BYTE(t2, 2)) ^ - Td2(LTC_BYTE(t1, 1)) ^ - Td3(LTC_BYTE(t0, 0)) ^ - rk[3]; - } -#endif - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Td4[LTC_BYTE(t0, 3)] & 0xff000000) ^ - (Td4[LTC_BYTE(t3, 2)] & 0x00ff0000) ^ - (Td4[LTC_BYTE(t2, 1)] & 0x0000ff00) ^ - (Td4[LTC_BYTE(t1, 0)] & 0x000000ff) ^ - rk[0]; - STORE32H(s0, pt); - s1 = - (Td4[LTC_BYTE(t1, 3)] & 0xff000000) ^ - (Td4[LTC_BYTE(t0, 2)] & 0x00ff0000) ^ - (Td4[LTC_BYTE(t3, 1)] & 0x0000ff00) ^ - (Td4[LTC_BYTE(t2, 0)] & 0x000000ff) ^ - rk[1]; - STORE32H(s1, pt+4); - s2 = - (Td4[LTC_BYTE(t2, 3)] & 0xff000000) ^ - (Td4[LTC_BYTE(t1, 2)] & 0x00ff0000) ^ - (Td4[LTC_BYTE(t0, 1)] & 0x0000ff00) ^ - (Td4[LTC_BYTE(t3, 0)] & 0x000000ff) ^ - rk[2]; - STORE32H(s2, pt+8); - s3 = - (Td4[LTC_BYTE(t3, 3)] & 0xff000000) ^ - (Td4[LTC_BYTE(t2, 2)] & 0x00ff0000) ^ - (Td4[LTC_BYTE(t1, 1)] & 0x0000ff00) ^ - (Td4[LTC_BYTE(t0, 0)] & 0x000000ff) ^ - rk[3]; - STORE32H(s3, pt+12); - - return CRYPT_OK; -} - - -#ifdef LTC_CLEAN_STACK -int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_rijndael_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); - return err; -} -#endif - -/** - Performs a self-test of the AES block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int ECB_TEST(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - int err; - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { 16, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, - 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } - }, { - 24, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, - 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } - }, { - 32, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, - 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } - } - }; - - symmetric_key key; - unsigned char tmp[2][16]; - int i, y; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - zeromem(&key, sizeof(key)); - if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - - rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key); - rijndael_ecb_decrypt(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - -#endif /* ENCRYPT_ONLY */ - - -/** Terminate the context - @param skey The scheduled key -*/ -void ECB_DONE(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int ECB_KS(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - return CRYPT_OK; - } - if (*keysize < 32) { - *keysize = 24; - return CRYPT_OK; - } - *keysize = 32; - return CRYPT_OK; -} - -#undef SETUP -#undef ECB_ENC -#undef ECB_DEC -#undef ECB_DONE -#undef ECB_TEST -#undef ECB_KS - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_desc.c b/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_desc.c deleted file mode 100644 index 5b13dc2..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_desc.c +++ /dev/null @@ -1,263 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* Auto-detection of AES implementation by Steffen Jaeckel */ -/** - @file aes_desc.c - Run-time detection of correct AES implementation -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_RIJNDAEL) - -#ifndef ENCRYPT_ONLY - -#define AES_SETUP aes_setup -#define AES_ENC aes_ecb_encrypt -#define AES_DEC aes_ecb_decrypt -#define AES_DONE aes_done -#define AES_TEST aes_test -#define AES_KS aes_keysize - -const struct ltc_cipher_descriptor aes_desc = -{ - "aes", - 6, - 16, 32, 16, 10, - AES_SETUP, AES_ENC, AES_DEC, AES_TEST, AES_DONE, AES_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#else - -#define AES_SETUP aes_enc_setup -#define AES_ENC aes_enc_ecb_encrypt -#define AES_DONE aes_enc_done -#define AES_TEST aes_enc_test -#define AES_KS aes_enc_keysize - -const struct ltc_cipher_descriptor aes_enc_desc = -{ - "aes", - 6, - 16, 32, 16, 10, - AES_SETUP, AES_ENC, NULL, NULL, AES_DONE, AES_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#endif - -/* Code partially borrowed from https://software.intel.com/content/www/us/en/develop/articles/intel-sha-extensions.html */ -#if defined(LTC_AES_NI) -static LTC_INLINE int s_aesni_is_supported(void) -{ - static int initialized = 0, is_supported = 0; - - if (initialized == 0) { - int a, b, c, d; - - /* Look for CPUID.1.0.ECX[19] (SSE4.1) and CPUID.1.0.ECX[25] (AES-NI) - * EAX = 1, ECX = 0 - */ - a = 1; - c = 0; - -#if defined(_MSC_VER) && !defined(__clang__) - int arr[4]; - __cpuidex(arr, a, c); - a = arr[0]; - b = arr[1]; - c = arr[2]; - d = arr[3]; -#else - __asm__ volatile ("cpuid" - :"=a"(a), "=b"(b), "=c"(c), "=d"(d) - :"a"(a), "c"(c) - ); -#endif - - is_supported = ((c >> 19) & 1) && ((c >> 25) & 1); - initialized = 1; - } - - return is_supported; -} - -#ifndef ENCRYPT_ONLY -int aesni_is_supported(void) -{ - return s_aesni_is_supported(); -} -#endif -#endif - - /** - Initialize the AES (Rijndael) block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ -#ifdef LTC_AES_NI - if (s_aesni_is_supported()) { - return aesni_setup(key, keylen, num_rounds, skey); - } -#endif - /* Last resort, software AES */ - return rijndael_setup(key, keylen, num_rounds, skey); -} - -/** - Encrypts a block of text with AES - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ -#ifdef LTC_AES_NI - if (s_aesni_is_supported()) { - return aesni_ecb_encrypt(pt, ct, skey); - } -#endif - return rijndael_ecb_encrypt(pt, ct, skey); -} - - -#ifndef ENCRYPT_ONLY -/** - Decrypts a block of text with AES - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ -#ifdef LTC_AES_NI - if (s_aesni_is_supported()) { - return aesni_ecb_decrypt(ct, pt, skey); - } -#endif - return rijndael_ecb_decrypt(ct, pt, skey); -} -#endif /* ENCRYPT_ONLY */ - -/** - Performs a self-test of the AES block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int AES_TEST(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - int err; - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { 16, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, - 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } - }, { - 24, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, - 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } - }, { - 32, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, - 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } - } - }; - - symmetric_key key; - unsigned char tmp[2][16]; - int i; -#ifndef ENCRYPT_ONLY - int y; -#endif - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - zeromem(&key, sizeof(key)); - if ((err = AES_SETUP(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - - AES_ENC(tests[i].pt, tmp[0], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } -#ifndef ENCRYPT_ONLY - AES_DEC(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) AES_ENC(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) AES_DEC(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; -#endif - } - return CRYPT_OK; - #endif -} - - -/** Terminate the context - @param skey The scheduled key -*/ -void AES_DONE(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int AES_KS(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - return CRYPT_OK; - } - if (*keysize < 32) { - *keysize = 24; - return CRYPT_OK; - } - *keysize = 32; - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_tab.c b/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_tab.c deleted file mode 100644 index 5e59004..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aes_tab.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/* The precomputed tables for AES */ -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -#ifdef LTC_AES_TAB_C - -/** - @file aes_tab.c - AES tables -*/ -static const ulong32 TE0[256] = { - 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, - 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, - 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, - 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, - 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, - 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, - 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, - 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, - 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, - 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, - 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, - 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, - 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, - 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, - 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, - 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, - 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, - 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, - 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, - 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, - 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, - 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, - 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, - 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, - 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, - 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, - 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, - 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, - 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, - 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, - 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, - 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, - 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, - 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, - 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, - 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, - 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, - 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, - 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, - 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, - 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, - 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, - 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, - 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, - 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, - 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, - 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, - 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, - 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, - 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, - 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, - 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, - 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, - 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, - 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, - 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, - 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, - 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, - 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, - 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, - 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, - 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, - 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, - 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, -}; - -#if !defined(PELI_TAB) && defined(LTC_SMALL_CODE) -static const ulong32 Te4[256] = { - 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, - 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, - 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, - 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, - 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, - 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, - 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, - 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, - 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, - 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, - 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, - 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, - 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, - 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, - 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, - 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, - 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, - 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, - 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, - 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, - 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, - 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, - 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, - 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, - 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, - 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, - 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, - 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, - 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, - 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, - 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, - 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, - 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, - 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, - 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, - 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, - 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, - 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, - 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, - 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, - 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, - 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, - 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, - 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, - 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, - 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, - 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, - 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, - 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, - 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, - 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, - 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, - 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, - 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, - 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, - 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, - 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, - 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, - 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, - 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, - 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, - 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, - 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, - 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, -}; -#endif - -#ifndef ENCRYPT_ONLY - -static const ulong32 TD0[256] = { - 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, - 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, - 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, - 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, - 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, - 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, - 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, - 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, - 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, - 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, - 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, - 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, - 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, - 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, - 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, - 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, - 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, - 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, - 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, - 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, - 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, - 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, - 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, - 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, - 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, - 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, - 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, - 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, - 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, - 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, - 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, - 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, - 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, - 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, - 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, - 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, - 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, - 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, - 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, - 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, - 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, - 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, - 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, - 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, - 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, - 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, - 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, - 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, - 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, - 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, - 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, - 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, - 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, - 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, - 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, - 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, - 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, - 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, - 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, - 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, - 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, - 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, - 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, - 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, -}; - -static const ulong32 Td4[256] = { - 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, - 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, - 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, - 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, - 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, - 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, - 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, - 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, - 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, - 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, - 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, - 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, - 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, - 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, - 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, - 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, - 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, - 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, - 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, - 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, - 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, - 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, - 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, - 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, - 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, - 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, - 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, - 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, - 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, - 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, - 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, - 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, - 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, - 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, - 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, - 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, - 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, - 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, - 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, - 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, - 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, - 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, - 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, - 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, - 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, - 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, - 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, - 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, - 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, - 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, - 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, - 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, - 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, - 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, - 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, - 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, - 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, - 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, - 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, - 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, - 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, - 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, - 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, - 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, -}; - -#endif /* ENCRYPT_ONLY */ - -#ifdef LTC_SMALL_CODE - -#define Te0(x) TE0[x] -#define Te1(x) RORc(TE0[x], 8) -#define Te2(x) RORc(TE0[x], 16) -#define Te3(x) RORc(TE0[x], 24) - -#define Td0(x) TD0[x] -#define Td1(x) RORc(TD0[x], 8) -#define Td2(x) RORc(TD0[x], 16) -#define Td3(x) RORc(TD0[x], 24) - -#define Te4_0 0x000000FF & Te4 -#define Te4_1 0x0000FF00 & Te4 -#define Te4_2 0x00FF0000 & Te4 -#define Te4_3 0xFF000000 & Te4 - -#else - -#define Te0(x) TE0[x] -#define Te1(x) TE1[x] -#define Te2(x) TE2[x] -#define Te3(x) TE3[x] - -#define Td0(x) TD0[x] -#define Td1(x) TD1[x] -#define Td2(x) TD2[x] -#define Td3(x) TD3[x] - -static const ulong32 TE1[256] = { - 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, - 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, - 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, - 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, - 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, - 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, - 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, - 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, - 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, - 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, - 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, - 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, - 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, - 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, - 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, - 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, - 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, - 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, - 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, - 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, - 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, - 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, - 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, - 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, - 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, - 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, - 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, - 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, - 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, - 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, - 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, - 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, - 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, - 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, - 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, - 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, - 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, - 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, - 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, - 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, - 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, - 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, - 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, - 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, - 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, - 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, - 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, - 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, - 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, - 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, - 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, - 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, - 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, - 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, - 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, - 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, - 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, - 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, - 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, - 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, - 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, - 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, - 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, - 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, -}; -static const ulong32 TE2[256] = { - 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, - 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, - 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, - 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, - 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, - 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, - 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, - 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, - 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, - 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, - 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, - 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, - 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, - 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, - 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, - 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, - 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, - 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, - 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, - 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, - 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, - 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, - 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, - 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, - 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, - 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, - 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, - 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, - 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, - 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, - 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, - 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, - 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, - 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, - 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, - 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, - 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, - 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, - 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, - 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, - 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, - 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, - 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, - 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, - 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, - 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, - 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, - 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, - 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, - 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, - 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, - 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, - 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, - 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, - 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, - 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, - 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, - 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, - 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, - 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, - 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, - 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, - 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, - 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, -}; -static const ulong32 TE3[256] = { - - 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, - 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, - 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, - 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, - 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, - 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, - 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, - 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, - 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, - 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, - 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, - 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, - 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, - 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, - 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, - 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, - 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, - 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, - 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, - 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, - 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, - 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, - 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, - 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, - 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, - 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, - 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, - 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, - 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, - 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, - 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, - 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, - 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, - 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, - 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, - 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, - 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, - 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, - 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, - 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, - 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, - 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, - 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, - 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, - 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, - 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, - 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, - 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, - 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, - 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, - 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, - 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, - 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, - 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, - 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, - 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, - 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, - 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, - 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, - 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, - 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, - 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, - 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, - 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, -}; - -#ifndef PELI_TAB -static const ulong32 Te4_0[] = { -0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, -0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, -0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, -0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, -0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, -0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, -0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, -0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, -0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, -0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, -0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, -0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, -0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, -0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, -0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, -0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, -0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, -0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, -0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, -0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, -0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, -0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, -0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, -0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, -0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, -0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, -0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, -0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, -0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, -0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, -0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, -0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL -}; - -static const ulong32 Te4_1[] = { -0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, -0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, -0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, -0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, -0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, -0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, -0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, -0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, -0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, -0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, -0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, -0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, -0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, -0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, -0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, -0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, -0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, -0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, -0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, -0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, -0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, -0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, -0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, -0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, -0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, -0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, -0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, -0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, -0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, -0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, -0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, -0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL -}; - -static const ulong32 Te4_2[] = { -0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, -0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, -0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, -0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, -0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, -0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, -0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, -0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, -0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, -0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, -0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, -0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, -0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, -0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, -0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, -0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, -0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, -0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, -0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, -0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, -0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, -0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, -0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, -0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, -0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, -0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, -0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, -0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, -0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, -0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, -0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, -0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL -}; - -static const ulong32 Te4_3[] = { -0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, -0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, -0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, -0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, -0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, -0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, -0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, -0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, -0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, -0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, -0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, -0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, -0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, -0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, -0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, -0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, -0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, -0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, -0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, -0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, -0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, -0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, -0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, -0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, -0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, -0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, -0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, -0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, -0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, -0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, -0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, -0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL -}; -#endif /* pelimac */ - -#ifndef ENCRYPT_ONLY - -static const ulong32 TD1[256] = { - 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, - 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, - 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, - 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, - 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, - 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, - 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, - 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, - 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, - 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, - 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, - 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, - 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, - 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, - 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, - 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, - 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, - 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, - 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, - 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, - 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, - 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, - 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, - 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, - 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, - 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, - 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, - 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, - 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, - 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, - 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, - 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, - 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, - 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, - 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, - 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, - 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, - 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, - 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, - 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, - 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, - 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, - 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, - 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, - 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, - 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, - 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, - 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, - 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, - 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, - 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, - 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, - 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, - 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, - 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, - 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, - 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, - 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, - 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, - 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, - 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, - 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, - 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, - 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, -}; -static const ulong32 TD2[256] = { - 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, - 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, - 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, - 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, - 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, - 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, - 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, - 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, - 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, - 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, - 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, - 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, - 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, - 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, - 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, - 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, - 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, - 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, - 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, - 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, - 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, - 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, - 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, - 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, - 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, - 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, - 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, - 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, - 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, - 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, - 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, - 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, - 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, - 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, - 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, - 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, - 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, - 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, - 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, - 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, - 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, - 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, - 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, - 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, - 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, - 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, - 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, - 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, - 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, - 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, - 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, - 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, - 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, - 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, - 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, - 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, - 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, - 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, - 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, - 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, - 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, - 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, - 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, - 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, -}; -static const ulong32 TD3[256] = { - 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, - 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, - 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, - 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, - 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, - 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, - 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, - 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, - 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, - 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, - 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, - 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, - 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, - 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, - 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, - 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, - 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, - 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, - 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, - 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, - 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, - 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, - 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, - 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, - 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, - 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, - 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, - 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, - 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, - 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, - 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, - 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, - 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, - 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, - 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, - 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, - 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, - 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, - 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, - 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, - 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, - 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, - 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, - 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, - 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, - 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, - 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, - 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, - 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, - 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, - 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, - 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, - 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, - 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, - 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, - 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, - 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, - 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, - 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, - 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, - 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, - 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, - 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, - 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, -}; - -static const ulong32 Tks0[] = { -0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, -0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, -0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, -0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, -0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, -0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, -0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, -0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, -0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, -0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, -0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, -0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, -0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, -0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, -0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, -0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, -0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, -0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, -0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, -0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, -0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, -0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, -0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, -0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, -0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, -0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, -0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, -0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, -0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, -0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, -0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, -0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL -}; - -static const ulong32 Tks1[] = { -0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, -0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, -0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, -0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, -0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, -0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, -0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, -0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, -0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, -0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, -0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, -0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, -0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, -0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, -0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, -0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, -0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, -0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, -0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, -0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, -0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, -0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, -0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, -0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, -0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, -0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, -0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, -0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, -0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, -0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, -0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, -0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL -}; - -static const ulong32 Tks2[] = { -0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, -0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, -0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, -0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, -0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, -0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, -0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, -0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, -0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, -0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, -0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, -0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, -0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, -0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, -0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, -0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, -0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, -0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, -0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, -0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, -0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, -0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, -0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, -0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, -0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, -0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, -0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, -0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, -0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, -0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, -0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, -0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL -}; - -static const ulong32 Tks3[] = { -0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, -0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, -0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, -0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, -0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, -0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, -0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, -0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, -0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, -0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, -0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, -0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, -0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, -0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, -0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, -0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, -0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, -0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, -0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, -0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, -0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, -0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, -0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, -0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, -0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, -0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, -0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, -0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, -0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, -0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, -0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, -0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL -}; - -#endif /* ENCRYPT_ONLY */ - -#endif /* SMALL CODE */ - -#ifndef PELI_TAB -static const ulong32 rcon[] = { - 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, - 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, - 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#endif - -#endif /* LTC_AES_TAB_C */ diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aesni.c b/Sources/DataLiteC/libtomcrypt/ciphers/aes/aesni.c deleted file mode 100644 index 723ad27..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/aes/aesni.c +++ /dev/null @@ -1,374 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* AES-NI implementation by Steffen Jaeckel */ -/** - @file aesni.c - Implementation of AES via the AES-NI instruction on x86_64 -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_AES_NI) - -const struct ltc_cipher_descriptor aesni_desc = -{ - "aes", - 6, - 16, 32, 16, 10, - aesni_setup, aesni_ecb_encrypt, aesni_ecb_decrypt, aesni_test, aesni_done, aesni_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#include -#include -#include - -#define setup_mix(t, c) _mm_extract_epi32(_mm_aeskeygenassist_si128(t, 0), c) -#define temp_load(k) _mm_loadu_si128((__m128i*)(k)) -#define temp_update(t, k) _mm_insert_epi32(t, k, 3) -#define temp_invert(k) _mm_aesimc_si128(*((__m128i*)(k))) - - -static const ulong32 rcon[] = { - 0x01UL, 0x02UL, 0x04UL, 0x08UL, 0x10UL, 0x20UL, 0x40UL, 0x80UL, 0x1BUL, 0x36UL -}; - - /** - Initialize the AES (Rijndael) block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -LTC_ATTRIBUTE((__target__("aes,sse4.1"))) -int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int i; - __m128i temp; - ulong32 *rk, *K; - ulong32 *rrk; - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 16 && keylen != 24 && keylen != 32) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 0 && num_rounds != (keylen / 4 + 6)) { - return CRYPT_INVALID_ROUNDS; - } - - skey->rijndael.Nr = keylen / 4 + 6; - K = LTC_ALIGN_BUF(skey->rijndael.K, 16); - skey->rijndael.eK = K; - K += 60; - skey->rijndael.dK = K; - - /* setup the forward key */ - i = 0; - rk = skey->rijndael.eK; - LOAD32L(rk[0], key); - LOAD32L(rk[1], key + 4); - LOAD32L(rk[2], key + 8); - LOAD32L(rk[3], key + 12); - if (keylen == 16) { - temp = temp_load(key); - for (;;) { - rk[4] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - break; - } - temp = temp_update(temp, rk[7]); - rk += 4; - } - } else if (keylen == 24) { - LOAD32L(rk[4], key + 16); - LOAD32L(rk[5], key + 20); - temp = temp_load(key + 8); - for (;;) { - rk[6] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; - rk[7] = rk[1] ^ rk[6]; - rk[8] = rk[2] ^ rk[7]; - rk[9] = rk[3] ^ rk[8]; - if (++i == 8) { - break; - } - rk[10] = rk[4] ^ rk[9]; - rk[11] = rk[5] ^ rk[10]; - temp = temp_update(temp, rk[11]); - rk += 6; - } - } else if (keylen == 32) { - LOAD32L(rk[4], key + 16); - LOAD32L(rk[5], key + 20); - LOAD32L(rk[6], key + 24); - LOAD32L(rk[7], key + 28); - temp = temp_load(key + 16); - for (;;) { - rk[8] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; - rk[9] = rk[1] ^ rk[8]; - rk[10] = rk[2] ^ rk[9]; - rk[11] = rk[3] ^ rk[10]; - if (++i == 7) { - break; - } - temp = temp_update(temp, rk[11]); - rk[12] = rk[4] ^ setup_mix(temp, 2); - rk[13] = rk[5] ^ rk[12]; - rk[14] = rk[6] ^ rk[13]; - rk[15] = rk[7] ^ rk[14]; - temp = temp_update(temp, rk[15]); - rk += 8; - } - } else { - /* this can't happen */ - /* coverity[dead_error_line] */ - return CRYPT_ERROR; - } - - /* setup the inverse key now */ - rk = skey->rijndael.dK; - rrk = skey->rijndael.eK + skey->rijndael.Nr * 4; - - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - /* copy first */ - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk = *rrk; - rk -= 3; - rrk -= 3; - - for (i = 1; i < skey->rijndael.Nr; i++) { - rrk -= 4; - rk += 4; - temp = temp_invert(rk); - *((__m128i*) rk) = temp_invert(rrk); - } - - /* copy last */ - rrk -= 4; - rk += 4; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk++ = *rrk++; - *rk = *rrk; - - return CRYPT_OK; -} - -/** - Encrypts a block of text with AES - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -LTC_ATTRIBUTE((__target__("aes"))) -#ifdef LTC_CLEAN_STACK -static int s_aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - int Nr, r; - const __m128i *skeys; - __m128i block; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - Nr = skey->rijndael.Nr; - - if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; - - skeys = (__m128i*) skey->rijndael.eK; - block = _mm_loadu_si128((const __m128i*) (pt)); - - block = _mm_xor_si128(block, skeys[0]); - for (r = 1; r < Nr - 1; r += 2) { - block = _mm_aesenc_si128(block, skeys[r]); - block = _mm_aesenc_si128(block, skeys[r + 1]); - } - block = _mm_aesenc_si128(block, skeys[Nr - 1]); - block = _mm_aesenclast_si128(block, skeys[Nr]); - - _mm_storeu_si128((__m128i*) ct, block); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_aesni_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); - return err; -} -#endif - - -/** - Decrypts a block of text with AES - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -LTC_ATTRIBUTE((__target__("aes"))) -#ifdef LTC_CLEAN_STACK -static int s_aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - int Nr, r; - const __m128i *skeys; - __m128i block; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - Nr = skey->rijndael.Nr; - - if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; - - skeys = (__m128i*) skey->rijndael.dK; - block = _mm_loadu_si128((const __m128i*) (ct)); - - block = _mm_xor_si128(block, skeys[0]); - for (r = 1; r < Nr - 1; r += 2) { - block = _mm_aesdec_si128(block, skeys[r]); - block = _mm_aesdec_si128(block, skeys[r + 1]); - } - block = _mm_aesdec_si128(block, skeys[Nr - 1]); - block = _mm_aesdeclast_si128(block, skeys[Nr]); - - _mm_storeu_si128((__m128i*) pt, block); - - return CRYPT_OK; -} - - -#ifdef LTC_CLEAN_STACK -int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_aesni_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); - return err; -} -#endif - -/** - Performs a self-test of the AES block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int aesni_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - int err; - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { 16, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, - 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } - }, { - 24, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, - 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } - }, { - 32, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, - 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } - } - }; - - symmetric_key key; - unsigned char tmp[2][16]; - int i, y; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - zeromem(&key, sizeof(key)); - if ((err = aesni_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - - aesni_ecb_encrypt(tests[i].pt, tmp[0], &key); - aesni_ecb_decrypt(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES-NI Encrypt", i) || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES-NI Decrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) aesni_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) aesni_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - - -/** Terminate the context - @param skey The scheduled key -*/ -void aesni_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int aesni_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - return CRYPT_OK; - } - if (*keysize < 32) { - *keysize = 24; - return CRYPT_OK; - } - *keysize = 32; - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/anubis.c b/Sources/DataLiteC/libtomcrypt/ciphers/anubis.c deleted file mode 100644 index 128b16c..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/anubis.c +++ /dev/null @@ -1,1567 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file anubis.c - Anubis implementation derived from public domain source - Authors: Paulo S.L.M. Barreto and Vincent Rijmen. -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_ANUBIS - -const struct ltc_cipher_descriptor anubis_desc = { - "anubis", - 19, - 16, 40, 16, 12, - &anubis_setup, - &anubis_ecb_encrypt, - &anubis_ecb_decrypt, - &anubis_test, - &anubis_done, - &anubis_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define MAX_N 10 - - -#define T0 anubis_T0 -#define T1 anubis_T1 -#define T2 anubis_T2 -#define T3 anubis_T3 -#define T4 anubis_T4 -#define T5 anubis_T5 -#define rc anubis_rc -/* - * Though Anubis is endianness-neutral, the encryption tables are listed - * in BIG-ENDIAN format, which is adopted throughout this implementation - * (but little-endian notation would be equally suitable if consistently - * employed). - */ -#if defined(LTC_ANUBIS_TWEAK) - -static const ulong32 T0[256] = { - 0xba69d2bbU, 0x54a84de5U, 0x2f5ebce2U, 0x74e8cd25U, - 0x53a651f7U, 0xd3bb6bd0U, 0xd2b96fd6U, 0x4d9a29b3U, - 0x50a05dfdU, 0xac458acfU, 0x8d070e09U, 0xbf63c6a5U, - 0x70e0dd3dU, 0x52a455f1U, 0x9a29527bU, 0x4c982db5U, - 0xeac98f46U, 0xd5b773c4U, 0x97336655U, 0xd1bf63dcU, - 0x3366ccaaU, 0x51a259fbU, 0x5bb671c7U, 0xa651a2f3U, - 0xdea15ffeU, 0x48903dadU, 0xa84d9ad7U, 0x992f5e71U, - 0xdbab4be0U, 0x3264c8acU, 0xb773e695U, 0xfce5d732U, - 0xe3dbab70U, 0x9e214263U, 0x913f7e41U, 0x9b2b567dU, - 0xe2d9af76U, 0xbb6bd6bdU, 0x4182199bU, 0x6edca579U, - 0xa557aef9U, 0xcb8b0b80U, 0x6bd6b167U, 0x95376e59U, - 0xa15fbee1U, 0xf3fbeb10U, 0xb17ffe81U, 0x0204080cU, - 0xcc851792U, 0xc49537a2U, 0x1d3a744eU, 0x14285078U, - 0xc39b2bb0U, 0x63c69157U, 0xdaa94fe6U, 0x5dba69d3U, - 0x5fbe61dfU, 0xdca557f2U, 0x7dfae913U, 0xcd871394U, - 0x7ffee11fU, 0x5ab475c1U, 0x6cd8ad75U, 0x5cb86dd5U, - 0xf7f3fb08U, 0x264c98d4U, 0xffe3db38U, 0xedc79354U, - 0xe8cd874aU, 0x9d274e69U, 0x6fdea17fU, 0x8e010203U, - 0x19326456U, 0xa05dbae7U, 0xf0fde71aU, 0x890f1e11U, - 0x0f1e3c22U, 0x070e1c12U, 0xaf4386c5U, 0xfbebcb20U, - 0x08102030U, 0x152a547eU, 0x0d1a342eU, 0x04081018U, - 0x01020406U, 0x64c88d45U, 0xdfa35bf8U, 0x76ecc529U, - 0x79f2f90bU, 0xdda753f4U, 0x3d7af48eU, 0x162c5874U, - 0x3f7efc82U, 0x376edcb2U, 0x6ddaa973U, 0x3870e090U, - 0xb96fdeb1U, 0x73e6d137U, 0xe9cf834cU, 0x356ad4beU, - 0x55aa49e3U, 0x71e2d93bU, 0x7bf6f107U, 0x8c050a0fU, - 0x72e4d531U, 0x880d1a17U, 0xf6f1ff0eU, 0x2a54a8fcU, - 0x3e7cf884U, 0x5ebc65d9U, 0x274e9cd2U, 0x468c0589U, - 0x0c183028U, 0x65ca8943U, 0x68d0bd6dU, 0x61c2995bU, - 0x03060c0aU, 0xc19f23bcU, 0x57ae41efU, 0xd6b17fceU, - 0xd9af43ecU, 0x58b07dcdU, 0xd8ad47eaU, 0x66cc8549U, - 0xd7b37bc8U, 0x3a74e89cU, 0xc88d078aU, 0x3c78f088U, - 0xfae9cf26U, 0x96316253U, 0xa753a6f5U, 0x982d5a77U, - 0xecc59752U, 0xb86ddab7U, 0xc7933ba8U, 0xae4182c3U, - 0x69d2b96bU, 0x4b9631a7U, 0xab4b96ddU, 0xa94f9ed1U, - 0x67ce814fU, 0x0a14283cU, 0x478e018fU, 0xf2f9ef16U, - 0xb577ee99U, 0x224488ccU, 0xe5d7b364U, 0xeec19f5eU, - 0xbe61c2a3U, 0x2b56acfaU, 0x811f3e21U, 0x1224486cU, - 0x831b362dU, 0x1b366c5aU, 0x0e1c3824U, 0x23468ccaU, - 0xf5f7f304U, 0x458a0983U, 0x214284c6U, 0xce811f9eU, - 0x499239abU, 0x2c58b0e8U, 0xf9efc32cU, 0xe6d1bf6eU, - 0xb671e293U, 0x2850a0f0U, 0x172e5c72U, 0x8219322bU, - 0x1a34685cU, 0x8b0b161dU, 0xfee1df3eU, 0x8a09121bU, - 0x09122436U, 0xc98f038cU, 0x87132635U, 0x4e9c25b9U, - 0xe1dfa37cU, 0x2e5cb8e4U, 0xe4d5b762U, 0xe0dda77aU, - 0xebcb8b40U, 0x903d7a47U, 0xa455aaffU, 0x1e3c7844U, - 0x85172e39U, 0x60c09d5dU, 0x00000000U, 0x254a94deU, - 0xf4f5f702U, 0xf1ffe31cU, 0x94356a5fU, 0x0b162c3aU, - 0xe7d3bb68U, 0x75eac923U, 0xefc39b58U, 0x3468d0b8U, - 0x3162c4a6U, 0xd4b577c2U, 0xd0bd67daU, 0x86112233U, - 0x7efce519U, 0xad478ec9U, 0xfde7d334U, 0x2952a4f6U, - 0x3060c0a0U, 0x3b76ec9aU, 0x9f234665U, 0xf8edc72aU, - 0xc6913faeU, 0x13264c6aU, 0x060c1814U, 0x050a141eU, - 0xc59733a4U, 0x11224466U, 0x77eec12fU, 0x7cf8ed15U, - 0x7af4f501U, 0x78f0fd0dU, 0x366cd8b4U, 0x1c387048U, - 0x3972e496U, 0x59b279cbU, 0x18306050U, 0x56ac45e9U, - 0xb37bf68dU, 0xb07dfa87U, 0x244890d8U, 0x204080c0U, - 0xb279f28bU, 0x9239724bU, 0xa35bb6edU, 0xc09d27baU, - 0x44880d85U, 0x62c49551U, 0x10204060U, 0xb475ea9fU, - 0x84152a3fU, 0x43861197U, 0x933b764dU, 0xc2992fb6U, - 0x4a9435a1U, 0xbd67cea9U, 0x8f030605U, 0x2d5ab4eeU, - 0xbc65caafU, 0x9c254a6fU, 0x6ad4b561U, 0x40801d9dU, - 0xcf831b98U, 0xa259b2ebU, 0x801d3a27U, 0x4f9e21bfU, - 0x1f3e7c42U, 0xca890f86U, 0xaa4992dbU, 0x42841591U, -}; - -static const ulong32 T1[256] = { - 0x69babbd2U, 0xa854e54dU, 0x5e2fe2bcU, 0xe87425cdU, - 0xa653f751U, 0xbbd3d06bU, 0xb9d2d66fU, 0x9a4db329U, - 0xa050fd5dU, 0x45accf8aU, 0x078d090eU, 0x63bfa5c6U, - 0xe0703dddU, 0xa452f155U, 0x299a7b52U, 0x984cb52dU, - 0xc9ea468fU, 0xb7d5c473U, 0x33975566U, 0xbfd1dc63U, - 0x6633aaccU, 0xa251fb59U, 0xb65bc771U, 0x51a6f3a2U, - 0xa1defe5fU, 0x9048ad3dU, 0x4da8d79aU, 0x2f99715eU, - 0xabdbe04bU, 0x6432acc8U, 0x73b795e6U, 0xe5fc32d7U, - 0xdbe370abU, 0x219e6342U, 0x3f91417eU, 0x2b9b7d56U, - 0xd9e276afU, 0x6bbbbdd6U, 0x82419b19U, 0xdc6e79a5U, - 0x57a5f9aeU, 0x8bcb800bU, 0xd66b67b1U, 0x3795596eU, - 0x5fa1e1beU, 0xfbf310ebU, 0x7fb181feU, 0x04020c08U, - 0x85cc9217U, 0x95c4a237U, 0x3a1d4e74U, 0x28147850U, - 0x9bc3b02bU, 0xc6635791U, 0xa9dae64fU, 0xba5dd369U, - 0xbe5fdf61U, 0xa5dcf257U, 0xfa7d13e9U, 0x87cd9413U, - 0xfe7f1fe1U, 0xb45ac175U, 0xd86c75adU, 0xb85cd56dU, - 0xf3f708fbU, 0x4c26d498U, 0xe3ff38dbU, 0xc7ed5493U, - 0xcde84a87U, 0x279d694eU, 0xde6f7fa1U, 0x018e0302U, - 0x32195664U, 0x5da0e7baU, 0xfdf01ae7U, 0x0f89111eU, - 0x1e0f223cU, 0x0e07121cU, 0x43afc586U, 0xebfb20cbU, - 0x10083020U, 0x2a157e54U, 0x1a0d2e34U, 0x08041810U, - 0x02010604U, 0xc864458dU, 0xa3dff85bU, 0xec7629c5U, - 0xf2790bf9U, 0xa7ddf453U, 0x7a3d8ef4U, 0x2c167458U, - 0x7e3f82fcU, 0x6e37b2dcU, 0xda6d73a9U, 0x703890e0U, - 0x6fb9b1deU, 0xe67337d1U, 0xcfe94c83U, 0x6a35bed4U, - 0xaa55e349U, 0xe2713bd9U, 0xf67b07f1U, 0x058c0f0aU, - 0xe47231d5U, 0x0d88171aU, 0xf1f60effU, 0x542afca8U, - 0x7c3e84f8U, 0xbc5ed965U, 0x4e27d29cU, 0x8c468905U, - 0x180c2830U, 0xca654389U, 0xd0686dbdU, 0xc2615b99U, - 0x06030a0cU, 0x9fc1bc23U, 0xae57ef41U, 0xb1d6ce7fU, - 0xafd9ec43U, 0xb058cd7dU, 0xadd8ea47U, 0xcc664985U, - 0xb3d7c87bU, 0x743a9ce8U, 0x8dc88a07U, 0x783c88f0U, - 0xe9fa26cfU, 0x31965362U, 0x53a7f5a6U, 0x2d98775aU, - 0xc5ec5297U, 0x6db8b7daU, 0x93c7a83bU, 0x41aec382U, - 0xd2696bb9U, 0x964ba731U, 0x4babdd96U, 0x4fa9d19eU, - 0xce674f81U, 0x140a3c28U, 0x8e478f01U, 0xf9f216efU, - 0x77b599eeU, 0x4422cc88U, 0xd7e564b3U, 0xc1ee5e9fU, - 0x61bea3c2U, 0x562bfaacU, 0x1f81213eU, 0x24126c48U, - 0x1b832d36U, 0x361b5a6cU, 0x1c0e2438U, 0x4623ca8cU, - 0xf7f504f3U, 0x8a458309U, 0x4221c684U, 0x81ce9e1fU, - 0x9249ab39U, 0x582ce8b0U, 0xeff92cc3U, 0xd1e66ebfU, - 0x71b693e2U, 0x5028f0a0U, 0x2e17725cU, 0x19822b32U, - 0x341a5c68U, 0x0b8b1d16U, 0xe1fe3edfU, 0x098a1b12U, - 0x12093624U, 0x8fc98c03U, 0x13873526U, 0x9c4eb925U, - 0xdfe17ca3U, 0x5c2ee4b8U, 0xd5e462b7U, 0xdde07aa7U, - 0xcbeb408bU, 0x3d90477aU, 0x55a4ffaaU, 0x3c1e4478U, - 0x1785392eU, 0xc0605d9dU, 0x00000000U, 0x4a25de94U, - 0xf5f402f7U, 0xfff11ce3U, 0x35945f6aU, 0x160b3a2cU, - 0xd3e768bbU, 0xea7523c9U, 0xc3ef589bU, 0x6834b8d0U, - 0x6231a6c4U, 0xb5d4c277U, 0xbdd0da67U, 0x11863322U, - 0xfc7e19e5U, 0x47adc98eU, 0xe7fd34d3U, 0x5229f6a4U, - 0x6030a0c0U, 0x763b9aecU, 0x239f6546U, 0xedf82ac7U, - 0x91c6ae3fU, 0x26136a4cU, 0x0c061418U, 0x0a051e14U, - 0x97c5a433U, 0x22116644U, 0xee772fc1U, 0xf87c15edU, - 0xf47a01f5U, 0xf0780dfdU, 0x6c36b4d8U, 0x381c4870U, - 0x723996e4U, 0xb259cb79U, 0x30185060U, 0xac56e945U, - 0x7bb38df6U, 0x7db087faU, 0x4824d890U, 0x4020c080U, - 0x79b28bf2U, 0x39924b72U, 0x5ba3edb6U, 0x9dc0ba27U, - 0x8844850dU, 0xc4625195U, 0x20106040U, 0x75b49feaU, - 0x15843f2aU, 0x86439711U, 0x3b934d76U, 0x99c2b62fU, - 0x944aa135U, 0x67bda9ceU, 0x038f0506U, 0x5a2deeb4U, - 0x65bcafcaU, 0x259c6f4aU, 0xd46a61b5U, 0x80409d1dU, - 0x83cf981bU, 0x59a2ebb2U, 0x1d80273aU, 0x9e4fbf21U, - 0x3e1f427cU, 0x89ca860fU, 0x49aadb92U, 0x84429115U, -}; - -static const ulong32 T2[256] = { - 0xd2bbba69U, 0x4de554a8U, 0xbce22f5eU, 0xcd2574e8U, - 0x51f753a6U, 0x6bd0d3bbU, 0x6fd6d2b9U, 0x29b34d9aU, - 0x5dfd50a0U, 0x8acfac45U, 0x0e098d07U, 0xc6a5bf63U, - 0xdd3d70e0U, 0x55f152a4U, 0x527b9a29U, 0x2db54c98U, - 0x8f46eac9U, 0x73c4d5b7U, 0x66559733U, 0x63dcd1bfU, - 0xccaa3366U, 0x59fb51a2U, 0x71c75bb6U, 0xa2f3a651U, - 0x5ffedea1U, 0x3dad4890U, 0x9ad7a84dU, 0x5e71992fU, - 0x4be0dbabU, 0xc8ac3264U, 0xe695b773U, 0xd732fce5U, - 0xab70e3dbU, 0x42639e21U, 0x7e41913fU, 0x567d9b2bU, - 0xaf76e2d9U, 0xd6bdbb6bU, 0x199b4182U, 0xa5796edcU, - 0xaef9a557U, 0x0b80cb8bU, 0xb1676bd6U, 0x6e599537U, - 0xbee1a15fU, 0xeb10f3fbU, 0xfe81b17fU, 0x080c0204U, - 0x1792cc85U, 0x37a2c495U, 0x744e1d3aU, 0x50781428U, - 0x2bb0c39bU, 0x915763c6U, 0x4fe6daa9U, 0x69d35dbaU, - 0x61df5fbeU, 0x57f2dca5U, 0xe9137dfaU, 0x1394cd87U, - 0xe11f7ffeU, 0x75c15ab4U, 0xad756cd8U, 0x6dd55cb8U, - 0xfb08f7f3U, 0x98d4264cU, 0xdb38ffe3U, 0x9354edc7U, - 0x874ae8cdU, 0x4e699d27U, 0xa17f6fdeU, 0x02038e01U, - 0x64561932U, 0xbae7a05dU, 0xe71af0fdU, 0x1e11890fU, - 0x3c220f1eU, 0x1c12070eU, 0x86c5af43U, 0xcb20fbebU, - 0x20300810U, 0x547e152aU, 0x342e0d1aU, 0x10180408U, - 0x04060102U, 0x8d4564c8U, 0x5bf8dfa3U, 0xc52976ecU, - 0xf90b79f2U, 0x53f4dda7U, 0xf48e3d7aU, 0x5874162cU, - 0xfc823f7eU, 0xdcb2376eU, 0xa9736ddaU, 0xe0903870U, - 0xdeb1b96fU, 0xd13773e6U, 0x834ce9cfU, 0xd4be356aU, - 0x49e355aaU, 0xd93b71e2U, 0xf1077bf6U, 0x0a0f8c05U, - 0xd53172e4U, 0x1a17880dU, 0xff0ef6f1U, 0xa8fc2a54U, - 0xf8843e7cU, 0x65d95ebcU, 0x9cd2274eU, 0x0589468cU, - 0x30280c18U, 0x894365caU, 0xbd6d68d0U, 0x995b61c2U, - 0x0c0a0306U, 0x23bcc19fU, 0x41ef57aeU, 0x7fced6b1U, - 0x43ecd9afU, 0x7dcd58b0U, 0x47ead8adU, 0x854966ccU, - 0x7bc8d7b3U, 0xe89c3a74U, 0x078ac88dU, 0xf0883c78U, - 0xcf26fae9U, 0x62539631U, 0xa6f5a753U, 0x5a77982dU, - 0x9752ecc5U, 0xdab7b86dU, 0x3ba8c793U, 0x82c3ae41U, - 0xb96b69d2U, 0x31a74b96U, 0x96ddab4bU, 0x9ed1a94fU, - 0x814f67ceU, 0x283c0a14U, 0x018f478eU, 0xef16f2f9U, - 0xee99b577U, 0x88cc2244U, 0xb364e5d7U, 0x9f5eeec1U, - 0xc2a3be61U, 0xacfa2b56U, 0x3e21811fU, 0x486c1224U, - 0x362d831bU, 0x6c5a1b36U, 0x38240e1cU, 0x8cca2346U, - 0xf304f5f7U, 0x0983458aU, 0x84c62142U, 0x1f9ece81U, - 0x39ab4992U, 0xb0e82c58U, 0xc32cf9efU, 0xbf6ee6d1U, - 0xe293b671U, 0xa0f02850U, 0x5c72172eU, 0x322b8219U, - 0x685c1a34U, 0x161d8b0bU, 0xdf3efee1U, 0x121b8a09U, - 0x24360912U, 0x038cc98fU, 0x26358713U, 0x25b94e9cU, - 0xa37ce1dfU, 0xb8e42e5cU, 0xb762e4d5U, 0xa77ae0ddU, - 0x8b40ebcbU, 0x7a47903dU, 0xaaffa455U, 0x78441e3cU, - 0x2e398517U, 0x9d5d60c0U, 0x00000000U, 0x94de254aU, - 0xf702f4f5U, 0xe31cf1ffU, 0x6a5f9435U, 0x2c3a0b16U, - 0xbb68e7d3U, 0xc92375eaU, 0x9b58efc3U, 0xd0b83468U, - 0xc4a63162U, 0x77c2d4b5U, 0x67dad0bdU, 0x22338611U, - 0xe5197efcU, 0x8ec9ad47U, 0xd334fde7U, 0xa4f62952U, - 0xc0a03060U, 0xec9a3b76U, 0x46659f23U, 0xc72af8edU, - 0x3faec691U, 0x4c6a1326U, 0x1814060cU, 0x141e050aU, - 0x33a4c597U, 0x44661122U, 0xc12f77eeU, 0xed157cf8U, - 0xf5017af4U, 0xfd0d78f0U, 0xd8b4366cU, 0x70481c38U, - 0xe4963972U, 0x79cb59b2U, 0x60501830U, 0x45e956acU, - 0xf68db37bU, 0xfa87b07dU, 0x90d82448U, 0x80c02040U, - 0xf28bb279U, 0x724b9239U, 0xb6eda35bU, 0x27bac09dU, - 0x0d854488U, 0x955162c4U, 0x40601020U, 0xea9fb475U, - 0x2a3f8415U, 0x11974386U, 0x764d933bU, 0x2fb6c299U, - 0x35a14a94U, 0xcea9bd67U, 0x06058f03U, 0xb4ee2d5aU, - 0xcaafbc65U, 0x4a6f9c25U, 0xb5616ad4U, 0x1d9d4080U, - 0x1b98cf83U, 0xb2eba259U, 0x3a27801dU, 0x21bf4f9eU, - 0x7c421f3eU, 0x0f86ca89U, 0x92dbaa49U, 0x15914284U, -}; - -static const ulong32 T3[256] = { - 0xbbd269baU, 0xe54da854U, 0xe2bc5e2fU, 0x25cde874U, - 0xf751a653U, 0xd06bbbd3U, 0xd66fb9d2U, 0xb3299a4dU, - 0xfd5da050U, 0xcf8a45acU, 0x090e078dU, 0xa5c663bfU, - 0x3ddde070U, 0xf155a452U, 0x7b52299aU, 0xb52d984cU, - 0x468fc9eaU, 0xc473b7d5U, 0x55663397U, 0xdc63bfd1U, - 0xaacc6633U, 0xfb59a251U, 0xc771b65bU, 0xf3a251a6U, - 0xfe5fa1deU, 0xad3d9048U, 0xd79a4da8U, 0x715e2f99U, - 0xe04babdbU, 0xacc86432U, 0x95e673b7U, 0x32d7e5fcU, - 0x70abdbe3U, 0x6342219eU, 0x417e3f91U, 0x7d562b9bU, - 0x76afd9e2U, 0xbdd66bbbU, 0x9b198241U, 0x79a5dc6eU, - 0xf9ae57a5U, 0x800b8bcbU, 0x67b1d66bU, 0x596e3795U, - 0xe1be5fa1U, 0x10ebfbf3U, 0x81fe7fb1U, 0x0c080402U, - 0x921785ccU, 0xa23795c4U, 0x4e743a1dU, 0x78502814U, - 0xb02b9bc3U, 0x5791c663U, 0xe64fa9daU, 0xd369ba5dU, - 0xdf61be5fU, 0xf257a5dcU, 0x13e9fa7dU, 0x941387cdU, - 0x1fe1fe7fU, 0xc175b45aU, 0x75add86cU, 0xd56db85cU, - 0x08fbf3f7U, 0xd4984c26U, 0x38dbe3ffU, 0x5493c7edU, - 0x4a87cde8U, 0x694e279dU, 0x7fa1de6fU, 0x0302018eU, - 0x56643219U, 0xe7ba5da0U, 0x1ae7fdf0U, 0x111e0f89U, - 0x223c1e0fU, 0x121c0e07U, 0xc58643afU, 0x20cbebfbU, - 0x30201008U, 0x7e542a15U, 0x2e341a0dU, 0x18100804U, - 0x06040201U, 0x458dc864U, 0xf85ba3dfU, 0x29c5ec76U, - 0x0bf9f279U, 0xf453a7ddU, 0x8ef47a3dU, 0x74582c16U, - 0x82fc7e3fU, 0xb2dc6e37U, 0x73a9da6dU, 0x90e07038U, - 0xb1de6fb9U, 0x37d1e673U, 0x4c83cfe9U, 0xbed46a35U, - 0xe349aa55U, 0x3bd9e271U, 0x07f1f67bU, 0x0f0a058cU, - 0x31d5e472U, 0x171a0d88U, 0x0efff1f6U, 0xfca8542aU, - 0x84f87c3eU, 0xd965bc5eU, 0xd29c4e27U, 0x89058c46U, - 0x2830180cU, 0x4389ca65U, 0x6dbdd068U, 0x5b99c261U, - 0x0a0c0603U, 0xbc239fc1U, 0xef41ae57U, 0xce7fb1d6U, - 0xec43afd9U, 0xcd7db058U, 0xea47add8U, 0x4985cc66U, - 0xc87bb3d7U, 0x9ce8743aU, 0x8a078dc8U, 0x88f0783cU, - 0x26cfe9faU, 0x53623196U, 0xf5a653a7U, 0x775a2d98U, - 0x5297c5ecU, 0xb7da6db8U, 0xa83b93c7U, 0xc38241aeU, - 0x6bb9d269U, 0xa731964bU, 0xdd964babU, 0xd19e4fa9U, - 0x4f81ce67U, 0x3c28140aU, 0x8f018e47U, 0x16eff9f2U, - 0x99ee77b5U, 0xcc884422U, 0x64b3d7e5U, 0x5e9fc1eeU, - 0xa3c261beU, 0xfaac562bU, 0x213e1f81U, 0x6c482412U, - 0x2d361b83U, 0x5a6c361bU, 0x24381c0eU, 0xca8c4623U, - 0x04f3f7f5U, 0x83098a45U, 0xc6844221U, 0x9e1f81ceU, - 0xab399249U, 0xe8b0582cU, 0x2cc3eff9U, 0x6ebfd1e6U, - 0x93e271b6U, 0xf0a05028U, 0x725c2e17U, 0x2b321982U, - 0x5c68341aU, 0x1d160b8bU, 0x3edfe1feU, 0x1b12098aU, - 0x36241209U, 0x8c038fc9U, 0x35261387U, 0xb9259c4eU, - 0x7ca3dfe1U, 0xe4b85c2eU, 0x62b7d5e4U, 0x7aa7dde0U, - 0x408bcbebU, 0x477a3d90U, 0xffaa55a4U, 0x44783c1eU, - 0x392e1785U, 0x5d9dc060U, 0x00000000U, 0xde944a25U, - 0x02f7f5f4U, 0x1ce3fff1U, 0x5f6a3594U, 0x3a2c160bU, - 0x68bbd3e7U, 0x23c9ea75U, 0x589bc3efU, 0xb8d06834U, - 0xa6c46231U, 0xc277b5d4U, 0xda67bdd0U, 0x33221186U, - 0x19e5fc7eU, 0xc98e47adU, 0x34d3e7fdU, 0xf6a45229U, - 0xa0c06030U, 0x9aec763bU, 0x6546239fU, 0x2ac7edf8U, - 0xae3f91c6U, 0x6a4c2613U, 0x14180c06U, 0x1e140a05U, - 0xa43397c5U, 0x66442211U, 0x2fc1ee77U, 0x15edf87cU, - 0x01f5f47aU, 0x0dfdf078U, 0xb4d86c36U, 0x4870381cU, - 0x96e47239U, 0xcb79b259U, 0x50603018U, 0xe945ac56U, - 0x8df67bb3U, 0x87fa7db0U, 0xd8904824U, 0xc0804020U, - 0x8bf279b2U, 0x4b723992U, 0xedb65ba3U, 0xba279dc0U, - 0x850d8844U, 0x5195c462U, 0x60402010U, 0x9fea75b4U, - 0x3f2a1584U, 0x97118643U, 0x4d763b93U, 0xb62f99c2U, - 0xa135944aU, 0xa9ce67bdU, 0x0506038fU, 0xeeb45a2dU, - 0xafca65bcU, 0x6f4a259cU, 0x61b5d46aU, 0x9d1d8040U, - 0x981b83cfU, 0xebb259a2U, 0x273a1d80U, 0xbf219e4fU, - 0x427c3e1fU, 0x860f89caU, 0xdb9249aaU, 0x91158442U, -}; - -static const ulong32 T4[256] = { - 0xbabababaU, 0x54545454U, 0x2f2f2f2fU, 0x74747474U, - 0x53535353U, 0xd3d3d3d3U, 0xd2d2d2d2U, 0x4d4d4d4dU, - 0x50505050U, 0xacacacacU, 0x8d8d8d8dU, 0xbfbfbfbfU, - 0x70707070U, 0x52525252U, 0x9a9a9a9aU, 0x4c4c4c4cU, - 0xeaeaeaeaU, 0xd5d5d5d5U, 0x97979797U, 0xd1d1d1d1U, - 0x33333333U, 0x51515151U, 0x5b5b5b5bU, 0xa6a6a6a6U, - 0xdedededeU, 0x48484848U, 0xa8a8a8a8U, 0x99999999U, - 0xdbdbdbdbU, 0x32323232U, 0xb7b7b7b7U, 0xfcfcfcfcU, - 0xe3e3e3e3U, 0x9e9e9e9eU, 0x91919191U, 0x9b9b9b9bU, - 0xe2e2e2e2U, 0xbbbbbbbbU, 0x41414141U, 0x6e6e6e6eU, - 0xa5a5a5a5U, 0xcbcbcbcbU, 0x6b6b6b6bU, 0x95959595U, - 0xa1a1a1a1U, 0xf3f3f3f3U, 0xb1b1b1b1U, 0x02020202U, - 0xccccccccU, 0xc4c4c4c4U, 0x1d1d1d1dU, 0x14141414U, - 0xc3c3c3c3U, 0x63636363U, 0xdadadadaU, 0x5d5d5d5dU, - 0x5f5f5f5fU, 0xdcdcdcdcU, 0x7d7d7d7dU, 0xcdcdcdcdU, - 0x7f7f7f7fU, 0x5a5a5a5aU, 0x6c6c6c6cU, 0x5c5c5c5cU, - 0xf7f7f7f7U, 0x26262626U, 0xffffffffU, 0xededededU, - 0xe8e8e8e8U, 0x9d9d9d9dU, 0x6f6f6f6fU, 0x8e8e8e8eU, - 0x19191919U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x89898989U, - 0x0f0f0f0fU, 0x07070707U, 0xafafafafU, 0xfbfbfbfbU, - 0x08080808U, 0x15151515U, 0x0d0d0d0dU, 0x04040404U, - 0x01010101U, 0x64646464U, 0xdfdfdfdfU, 0x76767676U, - 0x79797979U, 0xddddddddU, 0x3d3d3d3dU, 0x16161616U, - 0x3f3f3f3fU, 0x37373737U, 0x6d6d6d6dU, 0x38383838U, - 0xb9b9b9b9U, 0x73737373U, 0xe9e9e9e9U, 0x35353535U, - 0x55555555U, 0x71717171U, 0x7b7b7b7bU, 0x8c8c8c8cU, - 0x72727272U, 0x88888888U, 0xf6f6f6f6U, 0x2a2a2a2aU, - 0x3e3e3e3eU, 0x5e5e5e5eU, 0x27272727U, 0x46464646U, - 0x0c0c0c0cU, 0x65656565U, 0x68686868U, 0x61616161U, - 0x03030303U, 0xc1c1c1c1U, 0x57575757U, 0xd6d6d6d6U, - 0xd9d9d9d9U, 0x58585858U, 0xd8d8d8d8U, 0x66666666U, - 0xd7d7d7d7U, 0x3a3a3a3aU, 0xc8c8c8c8U, 0x3c3c3c3cU, - 0xfafafafaU, 0x96969696U, 0xa7a7a7a7U, 0x98989898U, - 0xececececU, 0xb8b8b8b8U, 0xc7c7c7c7U, 0xaeaeaeaeU, - 0x69696969U, 0x4b4b4b4bU, 0xababababU, 0xa9a9a9a9U, - 0x67676767U, 0x0a0a0a0aU, 0x47474747U, 0xf2f2f2f2U, - 0xb5b5b5b5U, 0x22222222U, 0xe5e5e5e5U, 0xeeeeeeeeU, - 0xbebebebeU, 0x2b2b2b2bU, 0x81818181U, 0x12121212U, - 0x83838383U, 0x1b1b1b1bU, 0x0e0e0e0eU, 0x23232323U, - 0xf5f5f5f5U, 0x45454545U, 0x21212121U, 0xcecececeU, - 0x49494949U, 0x2c2c2c2cU, 0xf9f9f9f9U, 0xe6e6e6e6U, - 0xb6b6b6b6U, 0x28282828U, 0x17171717U, 0x82828282U, - 0x1a1a1a1aU, 0x8b8b8b8bU, 0xfefefefeU, 0x8a8a8a8aU, - 0x09090909U, 0xc9c9c9c9U, 0x87878787U, 0x4e4e4e4eU, - 0xe1e1e1e1U, 0x2e2e2e2eU, 0xe4e4e4e4U, 0xe0e0e0e0U, - 0xebebebebU, 0x90909090U, 0xa4a4a4a4U, 0x1e1e1e1eU, - 0x85858585U, 0x60606060U, 0x00000000U, 0x25252525U, - 0xf4f4f4f4U, 0xf1f1f1f1U, 0x94949494U, 0x0b0b0b0bU, - 0xe7e7e7e7U, 0x75757575U, 0xefefefefU, 0x34343434U, - 0x31313131U, 0xd4d4d4d4U, 0xd0d0d0d0U, 0x86868686U, - 0x7e7e7e7eU, 0xadadadadU, 0xfdfdfdfdU, 0x29292929U, - 0x30303030U, 0x3b3b3b3bU, 0x9f9f9f9fU, 0xf8f8f8f8U, - 0xc6c6c6c6U, 0x13131313U, 0x06060606U, 0x05050505U, - 0xc5c5c5c5U, 0x11111111U, 0x77777777U, 0x7c7c7c7cU, - 0x7a7a7a7aU, 0x78787878U, 0x36363636U, 0x1c1c1c1cU, - 0x39393939U, 0x59595959U, 0x18181818U, 0x56565656U, - 0xb3b3b3b3U, 0xb0b0b0b0U, 0x24242424U, 0x20202020U, - 0xb2b2b2b2U, 0x92929292U, 0xa3a3a3a3U, 0xc0c0c0c0U, - 0x44444444U, 0x62626262U, 0x10101010U, 0xb4b4b4b4U, - 0x84848484U, 0x43434343U, 0x93939393U, 0xc2c2c2c2U, - 0x4a4a4a4aU, 0xbdbdbdbdU, 0x8f8f8f8fU, 0x2d2d2d2dU, - 0xbcbcbcbcU, 0x9c9c9c9cU, 0x6a6a6a6aU, 0x40404040U, - 0xcfcfcfcfU, 0xa2a2a2a2U, 0x80808080U, 0x4f4f4f4fU, - 0x1f1f1f1fU, 0xcacacacaU, 0xaaaaaaaaU, 0x42424242U, -}; - -static const ulong32 T5[256] = { - 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, - 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, - 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, - 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, - 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, - 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, - 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, - 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, - 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, - 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, - 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, - 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, - 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, - 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, - 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, - 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, - 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, - 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, - 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, - 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, - 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, - 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, - 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, - 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, - 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, - 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, - 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, - 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, - 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, - 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, - 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, - 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, - 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, - 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, - 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, - 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, - 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, - 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, - 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, - 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, - 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, - 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, - 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, - 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, - 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, - 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, - 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, - 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, - 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, - 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, - 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, - 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, - 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, - 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, - 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, - 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, - 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, - 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, - 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, - 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, - 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, - 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, - 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, - 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, -}; - -/** - * The round constants. - */ -static const ulong32 rc[] = { - 0xba542f74U, 0x53d3d24dU, 0x50ac8dbfU, 0x70529a4cU, - 0xead597d1U, 0x33515ba6U, 0xde48a899U, 0xdb32b7fcU, - 0xe39e919bU, 0xe2bb416eU, 0xa5cb6b95U, 0xa1f3b102U, - 0xccc41d14U, 0xc363da5dU, 0x5fdc7dcdU, 0x7f5a6c5cU, - 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U, -}; - - - -#else - - -static const ulong32 T0[256] = { - 0xa753a6f5U, 0xd3bb6bd0U, 0xe6d1bf6eU, 0x71e2d93bU, - 0xd0bd67daU, 0xac458acfU, 0x4d9a29b3U, 0x79f2f90bU, - 0x3a74e89cU, 0xc98f038cU, 0x913f7e41U, 0xfce5d732U, - 0x1e3c7844U, 0x478e018fU, 0x54a84de5U, 0xbd67cea9U, - 0x8c050a0fU, 0xa557aef9U, 0x7af4f501U, 0xfbebcb20U, - 0x63c69157U, 0xb86ddab7U, 0xdda753f4U, 0xd4b577c2U, - 0xe5d7b364U, 0xb37bf68dU, 0xc59733a4U, 0xbe61c2a3U, - 0xa94f9ed1U, 0x880d1a17U, 0x0c183028U, 0xa259b2ebU, - 0x3972e496U, 0xdfa35bf8U, 0x2952a4f6U, 0xdaa94fe6U, - 0x2b56acfaU, 0xa84d9ad7U, 0xcb8b0b80U, 0x4c982db5U, - 0x4b9631a7U, 0x224488ccU, 0xaa4992dbU, 0x244890d8U, - 0x4182199bU, 0x70e0dd3dU, 0xa651a2f3U, 0xf9efc32cU, - 0x5ab475c1U, 0xe2d9af76U, 0xb07dfa87U, 0x366cd8b4U, - 0x7dfae913U, 0xe4d5b762U, 0x3366ccaaU, 0xffe3db38U, - 0x60c09d5dU, 0x204080c0U, 0x08102030U, 0x8b0b161dU, - 0x5ebc65d9U, 0xab4b96ddU, 0x7ffee11fU, 0x78f0fd0dU, - 0x7cf8ed15U, 0x2c58b0e8U, 0x57ae41efU, 0xd2b96fd6U, - 0xdca557f2U, 0x6ddaa973U, 0x7efce519U, 0x0d1a342eU, - 0x53a651f7U, 0x94356a5fU, 0xc39b2bb0U, 0x2850a0f0U, - 0x274e9cd2U, 0x060c1814U, 0x5fbe61dfU, 0xad478ec9U, - 0x67ce814fU, 0x5cb86dd5U, 0x55aa49e3U, 0x48903dadU, - 0x0e1c3824U, 0x52a455f1U, 0xeac98f46U, 0x42841591U, - 0x5bb671c7U, 0x5dba69d3U, 0x3060c0a0U, 0x58b07dcdU, - 0x51a259fbU, 0x59b279cbU, 0x3c78f088U, 0x4e9c25b9U, - 0x3870e090U, 0x8a09121bU, 0x72e4d531U, 0x14285078U, - 0xe7d3bb68U, 0xc6913faeU, 0xdea15ffeU, 0x50a05dfdU, - 0x8e010203U, 0x9239724bU, 0xd1bf63dcU, 0x77eec12fU, - 0x933b764dU, 0x458a0983U, 0x9a29527bU, 0xce811f9eU, - 0x2d5ab4eeU, 0x03060c0aU, 0x62c49551U, 0xb671e293U, - 0xb96fdeb1U, 0xbf63c6a5U, 0x96316253U, 0x6bd6b167U, - 0x3f7efc82U, 0x070e1c12U, 0x1224486cU, 0xae4182c3U, - 0x40801d9dU, 0x3468d0b8U, 0x468c0589U, 0x3e7cf884U, - 0xdbab4be0U, 0xcf831b98U, 0xecc59752U, 0xcc851792U, - 0xc19f23bcU, 0xa15fbee1U, 0xc09d27baU, 0xd6b17fceU, - 0x1d3a744eU, 0xf4f5f702U, 0x61c2995bU, 0x3b76ec9aU, - 0x10204060U, 0xd8ad47eaU, 0x68d0bd6dU, 0xa05dbae7U, - 0xb17ffe81U, 0x0a14283cU, 0x69d2b96bU, 0x6cd8ad75U, - 0x499239abU, 0xfae9cf26U, 0x76ecc529U, 0xc49537a2U, - 0x9e214263U, 0x9b2b567dU, 0x6edca579U, 0x992f5e71U, - 0xc2992fb6U, 0xb773e695U, 0x982d5a77U, 0xbc65caafU, - 0x8f030605U, 0x85172e39U, 0x1f3e7c42U, 0xb475ea9fU, - 0xf8edc72aU, 0x11224466U, 0x2e5cb8e4U, 0x00000000U, - 0x254a94deU, 0x1c387048U, 0x2a54a8fcU, 0x3d7af48eU, - 0x050a141eU, 0x4f9e21bfU, 0x7bf6f107U, 0xb279f28bU, - 0x3264c8acU, 0x903d7a47U, 0xaf4386c5U, 0x19326456U, - 0xa35bb6edU, 0xf7f3fb08U, 0x73e6d137U, 0x9d274e69U, - 0x152a547eU, 0x74e8cd25U, 0xeec19f5eU, 0xca890f86U, - 0x9f234665U, 0x0f1e3c22U, 0x1b366c5aU, 0x75eac923U, - 0x86112233U, 0x84152a3fU, 0x9c254a6fU, 0x4a9435a1U, - 0x97336655U, 0x1a34685cU, 0x65ca8943U, 0xf6f1ff0eU, - 0xedc79354U, 0x09122436U, 0xbb6bd6bdU, 0x264c98d4U, - 0x831b362dU, 0xebcb8b40U, 0x6fdea17fU, 0x811f3e21U, - 0x04081018U, 0x6ad4b561U, 0x43861197U, 0x01020406U, - 0x172e5c72U, 0xe1dfa37cU, 0x87132635U, 0xf5f7f304U, - 0x8d070e09U, 0xe3dbab70U, 0x23468ccaU, 0x801d3a27U, - 0x44880d85U, 0x162c5874U, 0x66cc8549U, 0x214284c6U, - 0xfee1df3eU, 0xd5b773c4U, 0x3162c4a6U, 0xd9af43ecU, - 0x356ad4beU, 0x18306050U, 0x0204080cU, 0x64c88d45U, - 0xf2f9ef16U, 0xf1ffe31cU, 0x56ac45e9U, 0xcd871394U, - 0x8219322bU, 0xc88d078aU, 0xba69d2bbU, 0xf0fde71aU, - 0xefc39b58U, 0xe9cf834cU, 0xe8cd874aU, 0xfde7d334U, - 0x890f1e11U, 0xd7b37bc8U, 0xc7933ba8U, 0xb577ee99U, - 0xa455aaffU, 0x2f5ebce2U, 0x95376e59U, 0x13264c6aU, - 0x0b162c3aU, 0xf3fbeb10U, 0xe0dda77aU, 0x376edcb2U, -}; - -static const ulong32 T1[256] = { - 0x53a7f5a6U, 0xbbd3d06bU, 0xd1e66ebfU, 0xe2713bd9U, - 0xbdd0da67U, 0x45accf8aU, 0x9a4db329U, 0xf2790bf9U, - 0x743a9ce8U, 0x8fc98c03U, 0x3f91417eU, 0xe5fc32d7U, - 0x3c1e4478U, 0x8e478f01U, 0xa854e54dU, 0x67bda9ceU, - 0x058c0f0aU, 0x57a5f9aeU, 0xf47a01f5U, 0xebfb20cbU, - 0xc6635791U, 0x6db8b7daU, 0xa7ddf453U, 0xb5d4c277U, - 0xd7e564b3U, 0x7bb38df6U, 0x97c5a433U, 0x61bea3c2U, - 0x4fa9d19eU, 0x0d88171aU, 0x180c2830U, 0x59a2ebb2U, - 0x723996e4U, 0xa3dff85bU, 0x5229f6a4U, 0xa9dae64fU, - 0x562bfaacU, 0x4da8d79aU, 0x8bcb800bU, 0x984cb52dU, - 0x964ba731U, 0x4422cc88U, 0x49aadb92U, 0x4824d890U, - 0x82419b19U, 0xe0703dddU, 0x51a6f3a2U, 0xeff92cc3U, - 0xb45ac175U, 0xd9e276afU, 0x7db087faU, 0x6c36b4d8U, - 0xfa7d13e9U, 0xd5e462b7U, 0x6633aaccU, 0xe3ff38dbU, - 0xc0605d9dU, 0x4020c080U, 0x10083020U, 0x0b8b1d16U, - 0xbc5ed965U, 0x4babdd96U, 0xfe7f1fe1U, 0xf0780dfdU, - 0xf87c15edU, 0x582ce8b0U, 0xae57ef41U, 0xb9d2d66fU, - 0xa5dcf257U, 0xda6d73a9U, 0xfc7e19e5U, 0x1a0d2e34U, - 0xa653f751U, 0x35945f6aU, 0x9bc3b02bU, 0x5028f0a0U, - 0x4e27d29cU, 0x0c061418U, 0xbe5fdf61U, 0x47adc98eU, - 0xce674f81U, 0xb85cd56dU, 0xaa55e349U, 0x9048ad3dU, - 0x1c0e2438U, 0xa452f155U, 0xc9ea468fU, 0x84429115U, - 0xb65bc771U, 0xba5dd369U, 0x6030a0c0U, 0xb058cd7dU, - 0xa251fb59U, 0xb259cb79U, 0x783c88f0U, 0x9c4eb925U, - 0x703890e0U, 0x098a1b12U, 0xe47231d5U, 0x28147850U, - 0xd3e768bbU, 0x91c6ae3fU, 0xa1defe5fU, 0xa050fd5dU, - 0x018e0302U, 0x39924b72U, 0xbfd1dc63U, 0xee772fc1U, - 0x3b934d76U, 0x8a458309U, 0x299a7b52U, 0x81ce9e1fU, - 0x5a2deeb4U, 0x06030a0cU, 0xc4625195U, 0x71b693e2U, - 0x6fb9b1deU, 0x63bfa5c6U, 0x31965362U, 0xd66b67b1U, - 0x7e3f82fcU, 0x0e07121cU, 0x24126c48U, 0x41aec382U, - 0x80409d1dU, 0x6834b8d0U, 0x8c468905U, 0x7c3e84f8U, - 0xabdbe04bU, 0x83cf981bU, 0xc5ec5297U, 0x85cc9217U, - 0x9fc1bc23U, 0x5fa1e1beU, 0x9dc0ba27U, 0xb1d6ce7fU, - 0x3a1d4e74U, 0xf5f402f7U, 0xc2615b99U, 0x763b9aecU, - 0x20106040U, 0xadd8ea47U, 0xd0686dbdU, 0x5da0e7baU, - 0x7fb181feU, 0x140a3c28U, 0xd2696bb9U, 0xd86c75adU, - 0x9249ab39U, 0xe9fa26cfU, 0xec7629c5U, 0x95c4a237U, - 0x219e6342U, 0x2b9b7d56U, 0xdc6e79a5U, 0x2f99715eU, - 0x99c2b62fU, 0x73b795e6U, 0x2d98775aU, 0x65bcafcaU, - 0x038f0506U, 0x1785392eU, 0x3e1f427cU, 0x75b49feaU, - 0xedf82ac7U, 0x22116644U, 0x5c2ee4b8U, 0x00000000U, - 0x4a25de94U, 0x381c4870U, 0x542afca8U, 0x7a3d8ef4U, - 0x0a051e14U, 0x9e4fbf21U, 0xf67b07f1U, 0x79b28bf2U, - 0x6432acc8U, 0x3d90477aU, 0x43afc586U, 0x32195664U, - 0x5ba3edb6U, 0xf3f708fbU, 0xe67337d1U, 0x279d694eU, - 0x2a157e54U, 0xe87425cdU, 0xc1ee5e9fU, 0x89ca860fU, - 0x239f6546U, 0x1e0f223cU, 0x361b5a6cU, 0xea7523c9U, - 0x11863322U, 0x15843f2aU, 0x259c6f4aU, 0x944aa135U, - 0x33975566U, 0x341a5c68U, 0xca654389U, 0xf1f60effU, - 0xc7ed5493U, 0x12093624U, 0x6bbbbdd6U, 0x4c26d498U, - 0x1b832d36U, 0xcbeb408bU, 0xde6f7fa1U, 0x1f81213eU, - 0x08041810U, 0xd46a61b5U, 0x86439711U, 0x02010604U, - 0x2e17725cU, 0xdfe17ca3U, 0x13873526U, 0xf7f504f3U, - 0x078d090eU, 0xdbe370abU, 0x4623ca8cU, 0x1d80273aU, - 0x8844850dU, 0x2c167458U, 0xcc664985U, 0x4221c684U, - 0xe1fe3edfU, 0xb7d5c473U, 0x6231a6c4U, 0xafd9ec43U, - 0x6a35bed4U, 0x30185060U, 0x04020c08U, 0xc864458dU, - 0xf9f216efU, 0xfff11ce3U, 0xac56e945U, 0x87cd9413U, - 0x19822b32U, 0x8dc88a07U, 0x69babbd2U, 0xfdf01ae7U, - 0xc3ef589bU, 0xcfe94c83U, 0xcde84a87U, 0xe7fd34d3U, - 0x0f89111eU, 0xb3d7c87bU, 0x93c7a83bU, 0x77b599eeU, - 0x55a4ffaaU, 0x5e2fe2bcU, 0x3795596eU, 0x26136a4cU, - 0x160b3a2cU, 0xfbf310ebU, 0xdde07aa7U, 0x6e37b2dcU, -}; - -static const ulong32 T2[256] = { - 0xa6f5a753U, 0x6bd0d3bbU, 0xbf6ee6d1U, 0xd93b71e2U, - 0x67dad0bdU, 0x8acfac45U, 0x29b34d9aU, 0xf90b79f2U, - 0xe89c3a74U, 0x038cc98fU, 0x7e41913fU, 0xd732fce5U, - 0x78441e3cU, 0x018f478eU, 0x4de554a8U, 0xcea9bd67U, - 0x0a0f8c05U, 0xaef9a557U, 0xf5017af4U, 0xcb20fbebU, - 0x915763c6U, 0xdab7b86dU, 0x53f4dda7U, 0x77c2d4b5U, - 0xb364e5d7U, 0xf68db37bU, 0x33a4c597U, 0xc2a3be61U, - 0x9ed1a94fU, 0x1a17880dU, 0x30280c18U, 0xb2eba259U, - 0xe4963972U, 0x5bf8dfa3U, 0xa4f62952U, 0x4fe6daa9U, - 0xacfa2b56U, 0x9ad7a84dU, 0x0b80cb8bU, 0x2db54c98U, - 0x31a74b96U, 0x88cc2244U, 0x92dbaa49U, 0x90d82448U, - 0x199b4182U, 0xdd3d70e0U, 0xa2f3a651U, 0xc32cf9efU, - 0x75c15ab4U, 0xaf76e2d9U, 0xfa87b07dU, 0xd8b4366cU, - 0xe9137dfaU, 0xb762e4d5U, 0xccaa3366U, 0xdb38ffe3U, - 0x9d5d60c0U, 0x80c02040U, 0x20300810U, 0x161d8b0bU, - 0x65d95ebcU, 0x96ddab4bU, 0xe11f7ffeU, 0xfd0d78f0U, - 0xed157cf8U, 0xb0e82c58U, 0x41ef57aeU, 0x6fd6d2b9U, - 0x57f2dca5U, 0xa9736ddaU, 0xe5197efcU, 0x342e0d1aU, - 0x51f753a6U, 0x6a5f9435U, 0x2bb0c39bU, 0xa0f02850U, - 0x9cd2274eU, 0x1814060cU, 0x61df5fbeU, 0x8ec9ad47U, - 0x814f67ceU, 0x6dd55cb8U, 0x49e355aaU, 0x3dad4890U, - 0x38240e1cU, 0x55f152a4U, 0x8f46eac9U, 0x15914284U, - 0x71c75bb6U, 0x69d35dbaU, 0xc0a03060U, 0x7dcd58b0U, - 0x59fb51a2U, 0x79cb59b2U, 0xf0883c78U, 0x25b94e9cU, - 0xe0903870U, 0x121b8a09U, 0xd53172e4U, 0x50781428U, - 0xbb68e7d3U, 0x3faec691U, 0x5ffedea1U, 0x5dfd50a0U, - 0x02038e01U, 0x724b9239U, 0x63dcd1bfU, 0xc12f77eeU, - 0x764d933bU, 0x0983458aU, 0x527b9a29U, 0x1f9ece81U, - 0xb4ee2d5aU, 0x0c0a0306U, 0x955162c4U, 0xe293b671U, - 0xdeb1b96fU, 0xc6a5bf63U, 0x62539631U, 0xb1676bd6U, - 0xfc823f7eU, 0x1c12070eU, 0x486c1224U, 0x82c3ae41U, - 0x1d9d4080U, 0xd0b83468U, 0x0589468cU, 0xf8843e7cU, - 0x4be0dbabU, 0x1b98cf83U, 0x9752ecc5U, 0x1792cc85U, - 0x23bcc19fU, 0xbee1a15fU, 0x27bac09dU, 0x7fced6b1U, - 0x744e1d3aU, 0xf702f4f5U, 0x995b61c2U, 0xec9a3b76U, - 0x40601020U, 0x47ead8adU, 0xbd6d68d0U, 0xbae7a05dU, - 0xfe81b17fU, 0x283c0a14U, 0xb96b69d2U, 0xad756cd8U, - 0x39ab4992U, 0xcf26fae9U, 0xc52976ecU, 0x37a2c495U, - 0x42639e21U, 0x567d9b2bU, 0xa5796edcU, 0x5e71992fU, - 0x2fb6c299U, 0xe695b773U, 0x5a77982dU, 0xcaafbc65U, - 0x06058f03U, 0x2e398517U, 0x7c421f3eU, 0xea9fb475U, - 0xc72af8edU, 0x44661122U, 0xb8e42e5cU, 0x00000000U, - 0x94de254aU, 0x70481c38U, 0xa8fc2a54U, 0xf48e3d7aU, - 0x141e050aU, 0x21bf4f9eU, 0xf1077bf6U, 0xf28bb279U, - 0xc8ac3264U, 0x7a47903dU, 0x86c5af43U, 0x64561932U, - 0xb6eda35bU, 0xfb08f7f3U, 0xd13773e6U, 0x4e699d27U, - 0x547e152aU, 0xcd2574e8U, 0x9f5eeec1U, 0x0f86ca89U, - 0x46659f23U, 0x3c220f1eU, 0x6c5a1b36U, 0xc92375eaU, - 0x22338611U, 0x2a3f8415U, 0x4a6f9c25U, 0x35a14a94U, - 0x66559733U, 0x685c1a34U, 0x894365caU, 0xff0ef6f1U, - 0x9354edc7U, 0x24360912U, 0xd6bdbb6bU, 0x98d4264cU, - 0x362d831bU, 0x8b40ebcbU, 0xa17f6fdeU, 0x3e21811fU, - 0x10180408U, 0xb5616ad4U, 0x11974386U, 0x04060102U, - 0x5c72172eU, 0xa37ce1dfU, 0x26358713U, 0xf304f5f7U, - 0x0e098d07U, 0xab70e3dbU, 0x8cca2346U, 0x3a27801dU, - 0x0d854488U, 0x5874162cU, 0x854966ccU, 0x84c62142U, - 0xdf3efee1U, 0x73c4d5b7U, 0xc4a63162U, 0x43ecd9afU, - 0xd4be356aU, 0x60501830U, 0x080c0204U, 0x8d4564c8U, - 0xef16f2f9U, 0xe31cf1ffU, 0x45e956acU, 0x1394cd87U, - 0x322b8219U, 0x078ac88dU, 0xd2bbba69U, 0xe71af0fdU, - 0x9b58efc3U, 0x834ce9cfU, 0x874ae8cdU, 0xd334fde7U, - 0x1e11890fU, 0x7bc8d7b3U, 0x3ba8c793U, 0xee99b577U, - 0xaaffa455U, 0xbce22f5eU, 0x6e599537U, 0x4c6a1326U, - 0x2c3a0b16U, 0xeb10f3fbU, 0xa77ae0ddU, 0xdcb2376eU, -}; - -static const ulong32 T3[256] = { - 0xf5a653a7U, 0xd06bbbd3U, 0x6ebfd1e6U, 0x3bd9e271U, - 0xda67bdd0U, 0xcf8a45acU, 0xb3299a4dU, 0x0bf9f279U, - 0x9ce8743aU, 0x8c038fc9U, 0x417e3f91U, 0x32d7e5fcU, - 0x44783c1eU, 0x8f018e47U, 0xe54da854U, 0xa9ce67bdU, - 0x0f0a058cU, 0xf9ae57a5U, 0x01f5f47aU, 0x20cbebfbU, - 0x5791c663U, 0xb7da6db8U, 0xf453a7ddU, 0xc277b5d4U, - 0x64b3d7e5U, 0x8df67bb3U, 0xa43397c5U, 0xa3c261beU, - 0xd19e4fa9U, 0x171a0d88U, 0x2830180cU, 0xebb259a2U, - 0x96e47239U, 0xf85ba3dfU, 0xf6a45229U, 0xe64fa9daU, - 0xfaac562bU, 0xd79a4da8U, 0x800b8bcbU, 0xb52d984cU, - 0xa731964bU, 0xcc884422U, 0xdb9249aaU, 0xd8904824U, - 0x9b198241U, 0x3ddde070U, 0xf3a251a6U, 0x2cc3eff9U, - 0xc175b45aU, 0x76afd9e2U, 0x87fa7db0U, 0xb4d86c36U, - 0x13e9fa7dU, 0x62b7d5e4U, 0xaacc6633U, 0x38dbe3ffU, - 0x5d9dc060U, 0xc0804020U, 0x30201008U, 0x1d160b8bU, - 0xd965bc5eU, 0xdd964babU, 0x1fe1fe7fU, 0x0dfdf078U, - 0x15edf87cU, 0xe8b0582cU, 0xef41ae57U, 0xd66fb9d2U, - 0xf257a5dcU, 0x73a9da6dU, 0x19e5fc7eU, 0x2e341a0dU, - 0xf751a653U, 0x5f6a3594U, 0xb02b9bc3U, 0xf0a05028U, - 0xd29c4e27U, 0x14180c06U, 0xdf61be5fU, 0xc98e47adU, - 0x4f81ce67U, 0xd56db85cU, 0xe349aa55U, 0xad3d9048U, - 0x24381c0eU, 0xf155a452U, 0x468fc9eaU, 0x91158442U, - 0xc771b65bU, 0xd369ba5dU, 0xa0c06030U, 0xcd7db058U, - 0xfb59a251U, 0xcb79b259U, 0x88f0783cU, 0xb9259c4eU, - 0x90e07038U, 0x1b12098aU, 0x31d5e472U, 0x78502814U, - 0x68bbd3e7U, 0xae3f91c6U, 0xfe5fa1deU, 0xfd5da050U, - 0x0302018eU, 0x4b723992U, 0xdc63bfd1U, 0x2fc1ee77U, - 0x4d763b93U, 0x83098a45U, 0x7b52299aU, 0x9e1f81ceU, - 0xeeb45a2dU, 0x0a0c0603U, 0x5195c462U, 0x93e271b6U, - 0xb1de6fb9U, 0xa5c663bfU, 0x53623196U, 0x67b1d66bU, - 0x82fc7e3fU, 0x121c0e07U, 0x6c482412U, 0xc38241aeU, - 0x9d1d8040U, 0xb8d06834U, 0x89058c46U, 0x84f87c3eU, - 0xe04babdbU, 0x981b83cfU, 0x5297c5ecU, 0x921785ccU, - 0xbc239fc1U, 0xe1be5fa1U, 0xba279dc0U, 0xce7fb1d6U, - 0x4e743a1dU, 0x02f7f5f4U, 0x5b99c261U, 0x9aec763bU, - 0x60402010U, 0xea47add8U, 0x6dbdd068U, 0xe7ba5da0U, - 0x81fe7fb1U, 0x3c28140aU, 0x6bb9d269U, 0x75add86cU, - 0xab399249U, 0x26cfe9faU, 0x29c5ec76U, 0xa23795c4U, - 0x6342219eU, 0x7d562b9bU, 0x79a5dc6eU, 0x715e2f99U, - 0xb62f99c2U, 0x95e673b7U, 0x775a2d98U, 0xafca65bcU, - 0x0506038fU, 0x392e1785U, 0x427c3e1fU, 0x9fea75b4U, - 0x2ac7edf8U, 0x66442211U, 0xe4b85c2eU, 0x00000000U, - 0xde944a25U, 0x4870381cU, 0xfca8542aU, 0x8ef47a3dU, - 0x1e140a05U, 0xbf219e4fU, 0x07f1f67bU, 0x8bf279b2U, - 0xacc86432U, 0x477a3d90U, 0xc58643afU, 0x56643219U, - 0xedb65ba3U, 0x08fbf3f7U, 0x37d1e673U, 0x694e279dU, - 0x7e542a15U, 0x25cde874U, 0x5e9fc1eeU, 0x860f89caU, - 0x6546239fU, 0x223c1e0fU, 0x5a6c361bU, 0x23c9ea75U, - 0x33221186U, 0x3f2a1584U, 0x6f4a259cU, 0xa135944aU, - 0x55663397U, 0x5c68341aU, 0x4389ca65U, 0x0efff1f6U, - 0x5493c7edU, 0x36241209U, 0xbdd66bbbU, 0xd4984c26U, - 0x2d361b83U, 0x408bcbebU, 0x7fa1de6fU, 0x213e1f81U, - 0x18100804U, 0x61b5d46aU, 0x97118643U, 0x06040201U, - 0x725c2e17U, 0x7ca3dfe1U, 0x35261387U, 0x04f3f7f5U, - 0x090e078dU, 0x70abdbe3U, 0xca8c4623U, 0x273a1d80U, - 0x850d8844U, 0x74582c16U, 0x4985cc66U, 0xc6844221U, - 0x3edfe1feU, 0xc473b7d5U, 0xa6c46231U, 0xec43afd9U, - 0xbed46a35U, 0x50603018U, 0x0c080402U, 0x458dc864U, - 0x16eff9f2U, 0x1ce3fff1U, 0xe945ac56U, 0x941387cdU, - 0x2b321982U, 0x8a078dc8U, 0xbbd269baU, 0x1ae7fdf0U, - 0x589bc3efU, 0x4c83cfe9U, 0x4a87cde8U, 0x34d3e7fdU, - 0x111e0f89U, 0xc87bb3d7U, 0xa83b93c7U, 0x99ee77b5U, - 0xffaa55a4U, 0xe2bc5e2fU, 0x596e3795U, 0x6a4c2613U, - 0x3a2c160bU, 0x10ebfbf3U, 0x7aa7dde0U, 0xb2dc6e37U, -}; - -static const ulong32 T4[256] = { - 0xa7a7a7a7U, 0xd3d3d3d3U, 0xe6e6e6e6U, 0x71717171U, - 0xd0d0d0d0U, 0xacacacacU, 0x4d4d4d4dU, 0x79797979U, - 0x3a3a3a3aU, 0xc9c9c9c9U, 0x91919191U, 0xfcfcfcfcU, - 0x1e1e1e1eU, 0x47474747U, 0x54545454U, 0xbdbdbdbdU, - 0x8c8c8c8cU, 0xa5a5a5a5U, 0x7a7a7a7aU, 0xfbfbfbfbU, - 0x63636363U, 0xb8b8b8b8U, 0xddddddddU, 0xd4d4d4d4U, - 0xe5e5e5e5U, 0xb3b3b3b3U, 0xc5c5c5c5U, 0xbebebebeU, - 0xa9a9a9a9U, 0x88888888U, 0x0c0c0c0cU, 0xa2a2a2a2U, - 0x39393939U, 0xdfdfdfdfU, 0x29292929U, 0xdadadadaU, - 0x2b2b2b2bU, 0xa8a8a8a8U, 0xcbcbcbcbU, 0x4c4c4c4cU, - 0x4b4b4b4bU, 0x22222222U, 0xaaaaaaaaU, 0x24242424U, - 0x41414141U, 0x70707070U, 0xa6a6a6a6U, 0xf9f9f9f9U, - 0x5a5a5a5aU, 0xe2e2e2e2U, 0xb0b0b0b0U, 0x36363636U, - 0x7d7d7d7dU, 0xe4e4e4e4U, 0x33333333U, 0xffffffffU, - 0x60606060U, 0x20202020U, 0x08080808U, 0x8b8b8b8bU, - 0x5e5e5e5eU, 0xababababU, 0x7f7f7f7fU, 0x78787878U, - 0x7c7c7c7cU, 0x2c2c2c2cU, 0x57575757U, 0xd2d2d2d2U, - 0xdcdcdcdcU, 0x6d6d6d6dU, 0x7e7e7e7eU, 0x0d0d0d0dU, - 0x53535353U, 0x94949494U, 0xc3c3c3c3U, 0x28282828U, - 0x27272727U, 0x06060606U, 0x5f5f5f5fU, 0xadadadadU, - 0x67676767U, 0x5c5c5c5cU, 0x55555555U, 0x48484848U, - 0x0e0e0e0eU, 0x52525252U, 0xeaeaeaeaU, 0x42424242U, - 0x5b5b5b5bU, 0x5d5d5d5dU, 0x30303030U, 0x58585858U, - 0x51515151U, 0x59595959U, 0x3c3c3c3cU, 0x4e4e4e4eU, - 0x38383838U, 0x8a8a8a8aU, 0x72727272U, 0x14141414U, - 0xe7e7e7e7U, 0xc6c6c6c6U, 0xdedededeU, 0x50505050U, - 0x8e8e8e8eU, 0x92929292U, 0xd1d1d1d1U, 0x77777777U, - 0x93939393U, 0x45454545U, 0x9a9a9a9aU, 0xcecececeU, - 0x2d2d2d2dU, 0x03030303U, 0x62626262U, 0xb6b6b6b6U, - 0xb9b9b9b9U, 0xbfbfbfbfU, 0x96969696U, 0x6b6b6b6bU, - 0x3f3f3f3fU, 0x07070707U, 0x12121212U, 0xaeaeaeaeU, - 0x40404040U, 0x34343434U, 0x46464646U, 0x3e3e3e3eU, - 0xdbdbdbdbU, 0xcfcfcfcfU, 0xececececU, 0xccccccccU, - 0xc1c1c1c1U, 0xa1a1a1a1U, 0xc0c0c0c0U, 0xd6d6d6d6U, - 0x1d1d1d1dU, 0xf4f4f4f4U, 0x61616161U, 0x3b3b3b3bU, - 0x10101010U, 0xd8d8d8d8U, 0x68686868U, 0xa0a0a0a0U, - 0xb1b1b1b1U, 0x0a0a0a0aU, 0x69696969U, 0x6c6c6c6cU, - 0x49494949U, 0xfafafafaU, 0x76767676U, 0xc4c4c4c4U, - 0x9e9e9e9eU, 0x9b9b9b9bU, 0x6e6e6e6eU, 0x99999999U, - 0xc2c2c2c2U, 0xb7b7b7b7U, 0x98989898U, 0xbcbcbcbcU, - 0x8f8f8f8fU, 0x85858585U, 0x1f1f1f1fU, 0xb4b4b4b4U, - 0xf8f8f8f8U, 0x11111111U, 0x2e2e2e2eU, 0x00000000U, - 0x25252525U, 0x1c1c1c1cU, 0x2a2a2a2aU, 0x3d3d3d3dU, - 0x05050505U, 0x4f4f4f4fU, 0x7b7b7b7bU, 0xb2b2b2b2U, - 0x32323232U, 0x90909090U, 0xafafafafU, 0x19191919U, - 0xa3a3a3a3U, 0xf7f7f7f7U, 0x73737373U, 0x9d9d9d9dU, - 0x15151515U, 0x74747474U, 0xeeeeeeeeU, 0xcacacacaU, - 0x9f9f9f9fU, 0x0f0f0f0fU, 0x1b1b1b1bU, 0x75757575U, - 0x86868686U, 0x84848484U, 0x9c9c9c9cU, 0x4a4a4a4aU, - 0x97979797U, 0x1a1a1a1aU, 0x65656565U, 0xf6f6f6f6U, - 0xededededU, 0x09090909U, 0xbbbbbbbbU, 0x26262626U, - 0x83838383U, 0xebebebebU, 0x6f6f6f6fU, 0x81818181U, - 0x04040404U, 0x6a6a6a6aU, 0x43434343U, 0x01010101U, - 0x17171717U, 0xe1e1e1e1U, 0x87878787U, 0xf5f5f5f5U, - 0x8d8d8d8dU, 0xe3e3e3e3U, 0x23232323U, 0x80808080U, - 0x44444444U, 0x16161616U, 0x66666666U, 0x21212121U, - 0xfefefefeU, 0xd5d5d5d5U, 0x31313131U, 0xd9d9d9d9U, - 0x35353535U, 0x18181818U, 0x02020202U, 0x64646464U, - 0xf2f2f2f2U, 0xf1f1f1f1U, 0x56565656U, 0xcdcdcdcdU, - 0x82828282U, 0xc8c8c8c8U, 0xbabababaU, 0xf0f0f0f0U, - 0xefefefefU, 0xe9e9e9e9U, 0xe8e8e8e8U, 0xfdfdfdfdU, - 0x89898989U, 0xd7d7d7d7U, 0xc7c7c7c7U, 0xb5b5b5b5U, - 0xa4a4a4a4U, 0x2f2f2f2fU, 0x95959595U, 0x13131313U, - 0x0b0b0b0bU, 0xf3f3f3f3U, 0xe0e0e0e0U, 0x37373737U, -}; - -static const ulong32 T5[256] = { - 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, - 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, - 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, - 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, - 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, - 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, - 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, - 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, - 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, - 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, - 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, - 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, - 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, - 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, - 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, - 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, - 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, - 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, - 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, - 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, - 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, - 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, - 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, - 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, - 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, - 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, - 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, - 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, - 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, - 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, - 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, - 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, - 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, - 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, - 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, - 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, - 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, - 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, - 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, - 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, - 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, - 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, - 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, - 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, - 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, - 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, - 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, - 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, - 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, - 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, - 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, - 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, - 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, - 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, - 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, - 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, - 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, - 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, - 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, - 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, - 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, - 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, - 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, - 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, -}; - -/** - * The round constants. - */ -static const ulong32 rc[] = { - 0xa7d3e671U, 0xd0ac4d79U, 0x3ac991fcU, 0x1e4754bdU, - 0x8ca57afbU, 0x63b8ddd4U, 0xe5b3c5beU, 0xa9880ca2U, - 0x39df29daU, 0x2ba8cb4cU, 0x4b22aa24U, 0x4170a6f9U, - 0x5ae2b036U, 0x7de433ffU, 0x6020088bU, 0x5eab7f78U, - 0x7c2c57d2U, 0xdc6d7e0dU, 0x5394c328U, -}; - -#endif - - /** - Initialize the Anubis block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -#ifdef LTC_CLEAN_STACK -static int s_anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#else -int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#endif -{ - int N, R, i, pos, r; - ulong32 kappa[MAX_N]; - ulong32 inter[MAX_N] = { 0 }; /* initialize as all zeroes */ - ulong32 v, K0, K1, K2, K3; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */ - if ((keylen & 3) || (keylen < 16) || (keylen > 40)) { - return CRYPT_INVALID_KEYSIZE; - } - skey->anubis.keyBits = keylen*8; - - /* - * determine the N length parameter: - * (N.B. it is assumed that the key length is valid!) - */ - N = skey->anubis.keyBits >> 5; - - /* - * determine number of rounds from key size: - */ - skey->anubis.R = R = 8 + N; - - if (num_rounds != 0 && num_rounds != skey->anubis.R) { - return CRYPT_INVALID_ROUNDS; - } - - /* - * map cipher key to initial key state (mu): - */ - for (i = 0, pos = 0; i < N; i++, pos += 4) { - kappa[i] = - (((ulong32)key[pos ]) << 24) ^ - (((ulong32)key[pos + 1]) << 16) ^ - (((ulong32)key[pos + 2]) << 8) ^ - (((ulong32)key[pos + 3]) ); - } - - /* - * generate R + 1 round keys: - */ - for (r = 0; r <= R; r++) { - /* - * generate r-th round key K^r: - */ - K0 = T4[(kappa[N - 1] >> 24) & 0xff]; - K1 = T4[(kappa[N - 1] >> 16) & 0xff]; - K2 = T4[(kappa[N - 1] >> 8) & 0xff]; - K3 = T4[(kappa[N - 1] ) & 0xff]; - for (i = N - 2; i >= 0; i--) { - K0 = T4[(kappa[i] >> 24) & 0xff] ^ - (T5[(K0 >> 24) & 0xff] & 0xff000000U) ^ - (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^ - (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^ - (T5[(K0 ) & 0xff] & 0x000000ffU); - K1 = T4[(kappa[i] >> 16) & 0xff] ^ - (T5[(K1 >> 24) & 0xff] & 0xff000000U) ^ - (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^ - (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^ - (T5[(K1 ) & 0xff] & 0x000000ffU); - K2 = T4[(kappa[i] >> 8) & 0xff] ^ - (T5[(K2 >> 24) & 0xff] & 0xff000000U) ^ - (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^ - (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^ - (T5[(K2 ) & 0xff] & 0x000000ffU); - K3 = T4[(kappa[i] ) & 0xff] ^ - (T5[(K3 >> 24) & 0xff] & 0xff000000U) ^ - (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^ - (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^ - (T5[(K3 ) & 0xff] & 0x000000ffU); - } - /* - -- this is the code to use with the large U tables: - K0 = K1 = K2 = K3 = 0; - for (i = 0; i < N; i++) { - K0 ^= U[i][(kappa[i] >> 24) & 0xff]; - K1 ^= U[i][(kappa[i] >> 16) & 0xff]; - K2 ^= U[i][(kappa[i] >> 8) & 0xff]; - K3 ^= U[i][(kappa[i] ) & 0xff]; - } - */ - skey->anubis.roundKeyEnc[r][0] = K0; - skey->anubis.roundKeyEnc[r][1] = K1; - skey->anubis.roundKeyEnc[r][2] = K2; - skey->anubis.roundKeyEnc[r][3] = K3; - - /* - * compute kappa^{r+1} from kappa^r: - */ - if (r == R) { - break; - } - for (i = 0; i < N; i++) { - int j = i; - inter[i] = T0[(kappa[j--] >> 24) & 0xff]; if (j < 0) j = N - 1; - inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1; - inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1; - inter[i] ^= T3[(kappa[j ] ) & 0xff]; - } - kappa[0] = inter[0] ^ rc[r]; - for (i = 1; i < N; i++) { - kappa[i] = inter[i]; - } - } - - /* - * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}): - */ - for (i = 0; i < 4; i++) { - skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i]; - skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i]; - } - for (r = 1; r < R; r++) { - for (i = 0; i < 4; i++) { - v = skey->anubis.roundKeyEnc[R - r][i]; - skey->anubis.roundKeyDec[r][i] = - T0[T4[(v >> 24) & 0xff] & 0xff] ^ - T1[T4[(v >> 16) & 0xff] & 0xff] ^ - T2[T4[(v >> 8) & 0xff] & 0xff] ^ - T3[T4[(v ) & 0xff] & 0xff]; - } - } - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int err; - err = s_anubis_setup(key, keylen, num_rounds, skey); - burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5)); - return err; -} -#endif - - -static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext, - const ulong32 roundKey[18 + 1][4], int R) { - int i, pos, r; - ulong32 state[4]; - ulong32 inter[4]; - - /* - * map plaintext block to cipher state (mu) - * and add initial round key (sigma[K^0]): - */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - state[i] = - (((ulong32)plaintext[pos ]) << 24) ^ - (((ulong32)plaintext[pos + 1]) << 16) ^ - (((ulong32)plaintext[pos + 2]) << 8) ^ - (((ulong32)plaintext[pos + 3]) ) ^ - roundKey[0][i]; - } - - /* - * R - 1 full rounds: - */ - for (r = 1; r < R; r++) { - inter[0] = - T0[(state[0] >> 24) & 0xff] ^ - T1[(state[1] >> 24) & 0xff] ^ - T2[(state[2] >> 24) & 0xff] ^ - T3[(state[3] >> 24) & 0xff] ^ - roundKey[r][0]; - inter[1] = - T0[(state[0] >> 16) & 0xff] ^ - T1[(state[1] >> 16) & 0xff] ^ - T2[(state[2] >> 16) & 0xff] ^ - T3[(state[3] >> 16) & 0xff] ^ - roundKey[r][1]; - inter[2] = - T0[(state[0] >> 8) & 0xff] ^ - T1[(state[1] >> 8) & 0xff] ^ - T2[(state[2] >> 8) & 0xff] ^ - T3[(state[3] >> 8) & 0xff] ^ - roundKey[r][2]; - inter[3] = - T0[(state[0] ) & 0xff] ^ - T1[(state[1] ) & 0xff] ^ - T2[(state[2] ) & 0xff] ^ - T3[(state[3] ) & 0xff] ^ - roundKey[r][3]; - state[0] = inter[0]; - state[1] = inter[1]; - state[2] = inter[2]; - state[3] = inter[3]; - } - - /* - * last round: - */ - inter[0] = - (T0[(state[0] >> 24) & 0xff] & 0xff000000U) ^ - (T1[(state[1] >> 24) & 0xff] & 0x00ff0000U) ^ - (T2[(state[2] >> 24) & 0xff] & 0x0000ff00U) ^ - (T3[(state[3] >> 24) & 0xff] & 0x000000ffU) ^ - roundKey[R][0]; - inter[1] = - (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^ - (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^ - (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^ - (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^ - roundKey[R][1]; - inter[2] = - (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^ - (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^ - (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^ - (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^ - roundKey[R][2]; - inter[3] = - (T0[(state[0] ) & 0xff] & 0xff000000U) ^ - (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^ - (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^ - (T3[(state[3] ) & 0xff] & 0x000000ffU) ^ - roundKey[R][3]; - - /* - * map cipher state to ciphertext block (mu^{-1}): - */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - ulong32 w = inter[i]; - ciphertext[pos ] = (unsigned char)(w >> 24); - ciphertext[pos + 1] = (unsigned char)(w >> 16); - ciphertext[pos + 2] = (unsigned char)(w >> 8); - ciphertext[pos + 3] = (unsigned char)(w ); - } -} - -/** - Encrypts a block of text with Anubis - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - if (skey->anubis.R < 12 || skey->anubis.R > 18) { - return CRYPT_INVALID_ROUNDS; - } - - anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R); - return CRYPT_OK; -} - -/** - Decrypts a block of text with Anubis - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - if (skey->anubis.R < 12 || skey->anubis.R > 18) { - return CRYPT_INVALID_ROUNDS; - } - - anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R); - return CRYPT_OK; -} - -/** - Performs a self-test of the Anubis block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int anubis_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct test { - int keylen; - unsigned char pt[16], ct[16], key[40]; - } tests[] = { -#ifndef LTC_ANUBIS_TWEAK - /**** ORIGINAL LTC_ANUBIS ****/ - /* 128 bit keys */ -{ - 16, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xF0, 0x68, 0x60, 0xFC, 0x67, 0x30, 0xE8, 0x18, - 0xF1, 0x32, 0xC7, 0x8A, 0xF4, 0x13, 0x2A, 0xFE }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 16, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA8, 0x66, 0x84, 0x80, 0x07, 0x74, 0x5C, 0x89, - 0xFC, 0x5E, 0xB5, 0xBA, 0xD4, 0xFE, 0x32, 0x6D }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 160-bit keys */ -{ - 20, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xBD, 0x5E, 0x32, 0xBE, 0x51, 0x67, 0xA8, 0xE2, - 0x72, 0xD7, 0x95, 0x0F, 0x83, 0xC6, 0x8C, 0x31 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 20, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x4C, 0x1F, 0x86, 0x2E, 0x11, 0xEB, 0xCE, 0xEB, - 0xFE, 0xB9, 0x73, 0xC9, 0xDF, 0xEF, 0x7A, 0xDB }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 192-bit keys */ -{ - 24, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x17, 0xAC, 0x57, 0x44, 0x9D, 0x59, 0x61, 0x66, - 0xD0, 0xC7, 0x9E, 0x04, 0x7C, 0xC7, 0x58, 0xF0 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 24, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x71, 0x52, 0xB4, 0xEB, 0x1D, 0xAA, 0x36, 0xFD, - 0x57, 0x14, 0x5F, 0x57, 0x04, 0x9F, 0x70, 0x74 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 224-bit keys */ -{ - 28, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA2, 0xF0, 0xA6, 0xB9, 0x17, 0x93, 0x2A, 0x3B, - 0xEF, 0x08, 0xE8, 0x7A, 0x58, 0xD6, 0xF8, 0x53 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 28, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xF0, 0xCA, 0xFC, 0x78, 0x8B, 0x4B, 0x4E, 0x53, - 0x8B, 0xC4, 0x32, 0x6A, 0xF5, 0xB9, 0x1B, 0x5F }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 256-bit keys */ -{ - 32, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xE0, 0x86, 0xAC, 0x45, 0x6B, 0x3C, 0xE5, 0x13, - 0xED, 0xF5, 0xDF, 0xDD, 0xD6, 0x3B, 0x71, 0x93 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 32, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x50, 0x01, 0xB9, 0xF5, 0x21, 0xC1, 0xC1, 0x29, - 0x00, 0xD5, 0xEC, 0x98, 0x2B, 0x9E, 0xE8, 0x21 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 288-bit keys */ -{ - 36, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xE8, 0xF4, 0xAF, 0x2B, 0x21, 0xA0, 0x87, 0x9B, - 0x41, 0x95, 0xB9, 0x71, 0x75, 0x79, 0x04, 0x7C }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 36, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xE6, 0xA6, 0xA5, 0xBC, 0x8B, 0x63, 0x6F, 0xE2, - 0xBD, 0xA7, 0xA7, 0x53, 0xAB, 0x40, 0x22, 0xE0 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 320-bit keys */ -{ - 40, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x17, 0x04, 0xD7, 0x2C, 0xC6, 0x85, 0x76, 0x02, - 0x4B, 0xCC, 0x39, 0x80, 0xD8, 0x22, 0xEA, 0xA4 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 40, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x7A, 0x41, 0xE6, 0x7D, 0x4F, 0xD8, 0x64, 0xF0, - 0x44, 0xA8, 0x3C, 0x73, 0x81, 0x7E, 0x53, 0xD8 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -} -#else - /**** Tweaked LTC_ANUBIS ****/ - /* 128 bit keys */ -{ - 16, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB8, 0x35, 0xBD, 0xC3, 0x34, 0x82, 0x9D, 0x83, - 0x71, 0xBF, 0xA3, 0x71, 0xE4, 0xB3, 0xC4, 0xFD }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 16, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xE6, 0x14, 0x1E, 0xAF, 0xEB, 0xE0, 0x59, 0x3C, - 0x48, 0xE1, 0xCD, 0xF2, 0x1B, 0xBA, 0xA1, 0x89 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 160-bit keys */ -{ - 20, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x97, 0x59, 0x79, 0x4B, 0x5C, 0xA0, 0x70, 0x73, - 0x24, 0xEF, 0xB3, 0x58, 0x67, 0xCA, 0xD4, 0xB3 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 20, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB8, 0x0D, 0xFB, 0x9B, 0xE4, 0xA1, 0x58, 0x87, - 0xB3, 0x76, 0xD5, 0x02, 0x18, 0x95, 0xC1, 0x2E }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 192-bit keys */ -{ - 24, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x7D, 0x62, 0x3B, 0x52, 0xC7, 0x4C, 0x64, 0xD8, - 0xEB, 0xC7, 0x2D, 0x57, 0x97, 0x85, 0x43, 0x8F }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 24, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB1, 0x0A, 0x59, 0xDD, 0x5D, 0x5D, 0x8D, 0x67, - 0xEC, 0xEE, 0x4A, 0xC4, 0xBE, 0x4F, 0xA8, 0x4F }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 224-bit keys */ -{ - 28, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x68, 0x9E, 0x05, 0x94, 0x6A, 0x94, 0x43, 0x8F, - 0xE7, 0x8E, 0x37, 0x3D, 0x24, 0x97, 0x92, 0xF5 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 28, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xDD, 0xB7, 0xB0, 0xB4, 0xE9, 0xB4, 0x9B, 0x9C, - 0x38, 0x20, 0x25, 0x0B, 0x47, 0xC2, 0x1F, 0x89 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 256-bit keys */ -{ - 32, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x96, 0x00, 0xF0, 0x76, 0x91, 0x69, 0x29, 0x87, - 0xF5, 0xE5, 0x97, 0xDB, 0xDB, 0xAF, 0x1B, 0x0A }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 32, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x69, 0x9C, 0xAF, 0xDD, 0x94, 0xC7, 0xBC, 0x60, - 0x44, 0xFE, 0x02, 0x05, 0x8A, 0x6E, 0xEF, 0xBD }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, - - /* 288-bit keys */ -{ - 36, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x0F, 0xC7, 0xA2, 0xC0, 0x11, 0x17, 0xAC, 0x43, - 0x52, 0x5E, 0xDF, 0x6C, 0xF3, 0x96, 0x33, 0x6C }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}, { - 36, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xAD, 0x08, 0x4F, 0xED, 0x55, 0xA6, 0x94, 0x3E, - 0x7E, 0x5E, 0xED, 0x05, 0xA1, 0x9D, 0x41, 0xB4 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 } -}, - - /* 320-bit keys */ -{ - 40, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFE, 0xE2, 0x0E, 0x2A, 0x9D, 0xC5, 0x83, 0xBA, - 0xA3, 0xA6, 0xD6, 0xA6, 0xF2, 0xE8, 0x06, 0xA5 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - 40, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x86, 0x3D, 0xCC, 0x4A, 0x60, 0x34, 0x9C, 0x28, - 0xA7, 0xDA, 0xA4, 0x3B, 0x0A, 0xD7, 0xFD, 0xC7 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -} -#endif -}; - int x, y; - unsigned char buf[2][16]; - symmetric_key skey; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - anubis_setup(tests[x].key, tests[x].keylen, 0, &skey); - anubis_ecb_encrypt(tests[x].pt, buf[0], &skey); - anubis_ecb_decrypt(buf[0], buf[1], &skey); - if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis Encrypt", x) || - compare_testvector(buf[1], 16, tests[x].pt, 16, "Anubis Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - for (y = 0; y < 1000; y++) anubis_ecb_encrypt(buf[0], buf[0], &skey); - for (y = 0; y < 1000; y++) anubis_ecb_decrypt(buf[0], buf[0], &skey); - if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis 1000", 1000)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void anubis_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int anubis_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize >= 40) { - *keysize = 40; - } else if (*keysize >= 36) { - *keysize = 36; - } else if (*keysize >= 32) { - *keysize = 32; - } else if (*keysize >= 28) { - *keysize = 28; - } else if (*keysize >= 24) { - *keysize = 24; - } else if (*keysize >= 20) { - *keysize = 20; - } else if (*keysize >= 16) { - *keysize = 16; - } else { - return CRYPT_INVALID_KEYSIZE; - } - return CRYPT_OK; -} - -#undef MAX_N -#undef T0 -#undef T1 -#undef T2 -#undef T3 -#undef T4 -#undef T5 -#undef rc - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/blowfish.c b/Sources/DataLiteC/libtomcrypt/ciphers/blowfish.c deleted file mode 100644 index a2cd392..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/blowfish.c +++ /dev/null @@ -1,660 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @file blowfish.c - Implementation of the Blowfish block cipher, Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_BLOWFISH - -const struct ltc_cipher_descriptor blowfish_desc = -{ - "blowfish", - 0, - 8, 72, 8, 16, - &blowfish_setup, - &blowfish_ecb_encrypt, - &blowfish_ecb_decrypt, - &blowfish_test, - &blowfish_done, - &blowfish_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 ORIG_P[16 + 2] = { - 0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL, - 0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL, - 0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL, - 0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL, - 0x9216D5D9UL, 0x8979FB1BUL -}; - -static const ulong32 ORIG_S[4][256] = { - { 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL, - 0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL, - 0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL, - 0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL, - 0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL, - 0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL, - 0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL, - 0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL, - 0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL, - 0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL, - 0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL, - 0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL, - 0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL, - 0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL, - 0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL, - 0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL, - 0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL, - 0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL, - 0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL, - 0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL, - 0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL, - 0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL, - 0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL, - 0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL, - 0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL, - 0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL, - 0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL, - 0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL, - 0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL, - 0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL, - 0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL, - 0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL, - 0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL, - 0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL, - 0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL, - 0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL, - 0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL, - 0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL, - 0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL, - 0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL, - 0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL, - 0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL, - 0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL, - 0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL, - 0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL, - 0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL, - 0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL, - 0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL, - 0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL, - 0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL, - 0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL, - 0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL, - 0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL, - 0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL, - 0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL, - 0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL, - 0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL, - 0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL, - 0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL, - 0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL, - 0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL, - 0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL, - 0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL, - 0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL }, - { 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL, - 0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL, - 0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL, - 0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL, - 0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL, - 0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL, - 0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL, - 0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL, - 0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL, - 0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL, - 0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL, - 0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL, - 0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL, - 0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL, - 0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL, - 0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL, - 0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL, - 0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL, - 0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL, - 0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL, - 0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL, - 0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL, - 0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL, - 0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL, - 0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL, - 0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL, - 0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL, - 0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL, - 0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL, - 0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL, - 0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL, - 0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL, - 0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL, - 0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL, - 0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL, - 0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL, - 0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL, - 0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL, - 0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL, - 0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL, - 0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL, - 0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL, - 0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL, - 0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL, - 0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL, - 0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL, - 0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL, - 0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL, - 0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL, - 0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL, - 0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL, - 0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL, - 0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL, - 0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL, - 0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL, - 0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL, - 0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL, - 0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL, - 0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL, - 0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL, - 0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL, - 0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL, - 0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL, - 0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL }, - { 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL, - 0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL, - 0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL, - 0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL, - 0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL, - 0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL, - 0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL, - 0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL, - 0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL, - 0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL, - 0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL, - 0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL, - 0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL, - 0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL, - 0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL, - 0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL, - 0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL, - 0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL, - 0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL, - 0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL, - 0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL, - 0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL, - 0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL, - 0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL, - 0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL, - 0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL, - 0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL, - 0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL, - 0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL, - 0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL, - 0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL, - 0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL, - 0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL, - 0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL, - 0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL, - 0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL, - 0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL, - 0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL, - 0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL, - 0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL, - 0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL, - 0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL, - 0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL, - 0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL, - 0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL, - 0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL, - 0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL, - 0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL, - 0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL, - 0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL, - 0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL, - 0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL, - 0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL, - 0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL, - 0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL, - 0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL, - 0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL, - 0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL, - 0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL, - 0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL, - 0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL, - 0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL, - 0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL, - 0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL }, - { 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL, - 0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL, - 0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL, - 0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL, - 0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL, - 0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL, - 0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL, - 0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL, - 0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL, - 0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL, - 0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL, - 0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL, - 0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL, - 0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL, - 0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL, - 0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL, - 0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL, - 0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL, - 0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL, - 0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL, - 0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL, - 0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL, - 0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL, - 0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL, - 0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL, - 0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL, - 0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL, - 0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL, - 0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL, - 0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL, - 0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL, - 0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL, - 0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL, - 0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL, - 0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL, - 0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL, - 0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL, - 0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL, - 0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL, - 0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL, - 0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL, - 0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL, - 0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL, - 0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL, - 0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL, - 0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL, - 0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL, - 0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL, - 0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL, - 0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL, - 0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL, - 0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL, - 0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL, - 0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL, - 0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL, - 0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL, - 0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL, - 0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL, - 0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL, - 0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL, - 0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL, - 0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL, - 0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL, - 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL } -}; - -#ifndef __GNUC__ -#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] -#else -#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] -#endif - -static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey) -{ - int rounds; - - ulong32 l, r; -#ifndef __GNUC__ - const ulong32 *S1, *S2, *S3, *S4; - - S1 = skey->blowfish.S[0]; - S2 = skey->blowfish.S[1]; - S3 = skey->blowfish.S[2]; - S4 = skey->blowfish.S[3]; -#endif - - l = *L; - r = *R; - - /* do 16 rounds */ - for (rounds = 0; rounds < 16; ) { - l ^= skey->blowfish.K[rounds++]; r ^= F(l); - r ^= skey->blowfish.K[rounds++]; l ^= F(r); - l ^= skey->blowfish.K[rounds++]; r ^= F(l); - r ^= skey->blowfish.K[rounds++]; l ^= F(r); - } - - /* last keying */ - l ^= skey->blowfish.K[16]; - r ^= skey->blowfish.K[17]; - - *L = r; - *R = l; -} - -void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey) -{ - unsigned long i; - ulong32 *d = data; - - for (i = 0; i < blocks; ++i) { - s_blowfish_encipher(d, d + 1, skey); - d += 2; - } -} - -static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur) -{ - unsigned int z; - int y = *cur; - ulong32 ret = 0; - - for (z = 0; z < 4; z++) { - ret = (ret << 8) | ((ulong32)d[y++] & 255); - if (y == dlen) { - y = 0; - } - } - - *cur = y; - return ret; -} - - /** - Expand the Blowfish internal state - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param data The additional data you wish to pass (can be NULL) - @param datalen The additional data length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int blowfish_expand(const unsigned char *key, int keylen, - const unsigned char *data, int datalen, - symmetric_key *skey) -{ - ulong32 x, y, A, B[2]; - int i; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* load in key bytes (Supplied by David Hopwood) */ - i = 0; - for (x = 0; x < 18; x++) { - A = s_blowfish_stream2word(key, keylen, &i); - skey->blowfish.K[x] ^= A; - } - - - i = 0; - B[0] = 0; - B[1] = 0; - for (x = 0; x < 18; x += 2) { - if (data != NULL) { - B[0] ^= s_blowfish_stream2word(data, datalen, &i); - B[1] ^= s_blowfish_stream2word(data, datalen, &i); - } - /* encrypt it */ - s_blowfish_encipher(&B[0], &B[1], skey); - /* copy it */ - skey->blowfish.K[x] = B[0]; - skey->blowfish.K[x+1] = B[1]; - } - - /* encrypt S array */ - for (x = 0; x < 4; x++) { - for (y = 0; y < 256; y += 2) { - if (data != NULL) { - B[0] ^= s_blowfish_stream2word(data, datalen, &i); - B[1] ^= s_blowfish_stream2word(data, datalen, &i); - } - /* encrypt it */ - s_blowfish_encipher(&B[0], &B[1], skey); - /* copy it */ - skey->blowfish.S[x][y] = B[0]; - skey->blowfish.S[x][y+1] = B[1]; - } - } - -#ifdef LTC_CLEAN_STACK - zeromem(B, sizeof(B)); -#endif - - return CRYPT_OK; -} - -/** - Initialize the Blowfish block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful -*/ -int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, - symmetric_key *skey) -{ - /* check key length */ - if (keylen < 8 || keylen > 72) { - return CRYPT_INVALID_KEYSIZE; - } - /* check rounds */ - if (num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - - return blowfish_setup_with_data(key, keylen, NULL, 0, skey); -} - -/** - Alternative initialize of the Blowfish block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param data The additional data you wish to pass (can be NULL) - @param datalen The additional data length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful -*/ - -int blowfish_setup_with_data(const unsigned char *key, int keylen, - const unsigned char *data, int datalen, - symmetric_key *skey) -{ - XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P)); - XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S)); - return blowfish_expand(key, keylen, data, datalen, skey); -} - -/** - Encrypts a block of text with Blowfish - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 L, R; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - /* load it */ - LOAD32H(L, &pt[0]); - LOAD32H(R, &pt[4]); - - s_blowfish_encipher(&L, &R, skey); - - /* store */ - STORE32H(L, &ct[0]); - STORE32H(R, &ct[4]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_blowfish_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(ulong32) * 2 + sizeof(int)); - return err; -} -#endif - -/** - Decrypts a block of text with Blowfish - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 L, R; - int r; -#ifndef __GNUC__ - const ulong32 *S1, *S2, *S3, *S4; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - -#ifndef __GNUC__ - S1 = skey->blowfish.S[0]; - S2 = skey->blowfish.S[1]; - S3 = skey->blowfish.S[2]; - S4 = skey->blowfish.S[3]; -#endif - - /* load it */ - LOAD32H(R, &ct[0]); - LOAD32H(L, &ct[4]); - - /* undo last keying */ - R ^= skey->blowfish.K[17]; - L ^= skey->blowfish.K[16]; - - /* do 16 rounds */ - for (r = 15; r > 0; ) { - L ^= F(R); R ^= skey->blowfish.K[r--]; - R ^= F(L); L ^= skey->blowfish.K[r--]; - L ^= F(R); R ^= skey->blowfish.K[r--]; - R ^= F(L); L ^= skey->blowfish.K[r--]; - } - - /* store */ - STORE32H(L, &pt[0]); - STORE32H(R, &pt[4]); - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_blowfish_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(ulong32) * 2 + sizeof(int)); - return err; -} -#endif - - -/** - Performs a self-test of the Blowfish block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int blowfish_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - int err; - symmetric_key key; - static const struct { - unsigned char key[8], pt[8], ct[8]; - } tests[] = { - { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78} - }, - { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A} - }, - { - { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2} - } - }; - unsigned char tmp[2][8]; - int x, y; - - for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { - /* setup key */ - if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) { - return err; - } - - /* encrypt and decrypt */ - blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key); - blowfish_ecb_decrypt(tmp[0], tmp[1], &key); - - /* compare */ - if ((compare_testvector(tmp[0], 8, tests[x].ct, 8, "Blowfish Encrypt", x) != 0) || - (compare_testvector(tmp[1], 8, tests[x].pt, 8, "Blowfish Decrypt", x) != 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void blowfish_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int blowfish_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize < 8) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 72) { - *keysize = 72; - } - return CRYPT_OK; -} - -#undef F - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/camellia.c b/Sources/DataLiteC/libtomcrypt/ciphers/camellia.c deleted file mode 100644 index ee40284..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/camellia.c +++ /dev/null @@ -1,722 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file camellia.c - Implementation by Tom St Denis of Elliptic Semiconductor -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_CAMELLIA - -const struct ltc_cipher_descriptor camellia_desc = { - "camellia", - 23, - 16, 32, 16, 18, - &camellia_setup, - &camellia_ecb_encrypt, - &camellia_ecb_decrypt, - &camellia_test, - &camellia_done, - &camellia_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 SP1110[] = { -0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500, -0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, -0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, -0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00, -0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, -0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, -0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00, -0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, -0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, -0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900, -0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, -0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, -0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00, -0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, -0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, -0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000, -0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, -0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, -0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00, -0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, -0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, -0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200, -0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, -0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, -0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00, -0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, -0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, -0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00, -0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, -0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, -0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100, -0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00, -}; - -static const ulong32 SP0222[] = { -0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb, -0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, -0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, -0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b, -0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, -0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, -0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a, -0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, -0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, -0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333, -0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, -0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, -0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838, -0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, -0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, -0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0, -0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, -0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, -0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7, -0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, -0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, -0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5, -0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, -0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, -0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d, -0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, -0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, -0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5, -0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, -0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, -0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, 0x00868686, 0x00838383, -0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d, -}; - -static const ulong32 SP3033[] = { -0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2, -0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, -0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, -0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede, -0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, -0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, -0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e, -0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, -0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, -0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc, -0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, -0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, -0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e, -0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, -0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, -0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828, -0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, -0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, -0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded, -0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, -0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, -0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171, -0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, -0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, -0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747, -0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, -0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, -0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d, -0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, -0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, -0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0, -0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f, -}; - -static const ulong32 SP4404[] = { -0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae, -0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, -0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, -0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c, -0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, -0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, -0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2, -0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, -0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, -0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd, -0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, -0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, -0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4, -0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, -0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, -0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, 0x77770077, 0x80800080, -0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, -0xefef00ef, 0x93930093, 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, -0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a, -0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, -0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, -0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7, -0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, -0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, -0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2, -0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, -0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, -0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e, -0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, -0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, -0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4, -0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e, -}; - -static const ulong64 key_sigma[] = { - CONST64(0xA09E667F3BCC908B), - CONST64(0xB67AE8584CAA73B2), - CONST64(0xC6EF372FE94F82BE), - CONST64(0x54FF53A5F1D36F1C), - CONST64(0x10E527FADE682D1D), - CONST64(0xB05688C2B3E6C1FD) -}; - -static ulong64 F(ulong64 x) -{ - ulong32 D, U; - -#define loc(i) ((8-i)*8) - - D = SP1110[(x >> loc(8)) & 0xFF] ^ SP0222[(x >> loc(5)) & 0xFF] ^ SP3033[(x >> loc(6)) & 0xFF] ^ SP4404[(x >> loc(7)) & 0xFF]; - U = SP1110[(x >> loc(1)) & 0xFF] ^ SP0222[(x >> loc(2)) & 0xFF] ^ SP3033[(x >> loc(3)) & 0xFF] ^ SP4404[(x >> loc(4)) & 0xFF]; - - D ^= U; - U = D ^ RORc(U, 8); - - return ((ulong64)U) | (((ulong64)D) << CONST64(32)); -} - -static void rot_128(const unsigned char *in, unsigned count, unsigned char *out) -{ - unsigned x, w, b; - - w = count >> 3; - b = count & 7; - - for (x = 0; x < 16; x++) { - out[x] = (in[(x+w)&15] << b) | (in[(x+w+1)&15] >> (8 - b)); - } -} - -int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - unsigned char T[48], kA[16], kB[16], kR[16], kL[16]; - int x; - ulong64 A, B; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* Valid sizes (in bytes) are 16, 24, 32 */ - if (keylen != 16 && keylen != 24 && keylen != 32) { - return CRYPT_INVALID_KEYSIZE; - } - - /* number of rounds */ - skey->camellia.R = (keylen == 16) ? 18 : 24; - - if (num_rounds != 0 && num_rounds != skey->camellia.R) { - return CRYPT_INVALID_ROUNDS; - } - - /* expand key */ - if (keylen == 16) { - for (x = 0; x < 16; x++) { - T[x] = key[x]; - T[x + 16] = 0; - } - } else if (keylen == 24) { - for (x = 0; x < 24; x++) { - T[x] = key[x]; - } - for (x = 24; x < 32; x++) { - T[x] = key[x-8] ^ 0xFF; - } - } else { - for (x = 0; x < 32; x++) { - T[x] = key[x]; - } - } - - for (x = 0; x < 16; x++) { - kL[x] = T[x]; - kR[x] = T[x + 16]; - } - - for (x = 32; x < 48; x++) { - T[x] = T[x - 32] ^ T[x - 16]; - } - - /* first two rounds */ - LOAD64H(A, T+32); LOAD64H(B, T+40); - B ^= F(A ^ key_sigma[0]); - A ^= F(B ^ key_sigma[1]); - STORE64H(A, T+32); STORE64H(B, T+40); - - /* xor kL in */ - for (x = 0; x < 16; x++) { T[x+32] ^= kL[x]; } - - /* next two rounds */ - LOAD64H(A, T+32); LOAD64H(B, T+40); - B ^= F(A ^ key_sigma[2]); - A ^= F(B ^ key_sigma[3]); - STORE64H(A, T+32); STORE64H(B, T+40); - - /* grab KA */ - for (x = 0; x < 16; x++) { kA[x] = T[x+32]; } - - /* xor kR in */ - for (x = 0; x < 16; x++) { T[x+32] ^= kR[x]; } - - if (keylen == 16) { - /* grab whitening keys kw1 and kw2 */ - LOAD64H(skey->camellia.kw[0], kL); - LOAD64H(skey->camellia.kw[1], kL+8); - - /* k1-k2 */ - LOAD64H(skey->camellia.k[0], kA); - LOAD64H(skey->camellia.k[1], kA+8); - - /* rotate kL by 15, k3/k4 */ - rot_128(kL, 15, T+32); - LOAD64H(skey->camellia.k[2], T+32); - LOAD64H(skey->camellia.k[3], T+40); - - /* rotate kA by 15, k5/k6 */ - rot_128(kA, 15, T+32); - LOAD64H(skey->camellia.k[4], T+32); - LOAD64H(skey->camellia.k[5], T+40); - - /* rotate kA by 30, kl1, kl2 */ - rot_128(kA, 30, T+32); - LOAD64H(skey->camellia.kl[0], T+32); - LOAD64H(skey->camellia.kl[1], T+40); - - /* rotate kL by 45, k7/k8 */ - rot_128(kL, 45, T+32); - LOAD64H(skey->camellia.k[6], T+32); - LOAD64H(skey->camellia.k[7], T+40); - - /* rotate kA by 45, k9/k10 */ - rot_128(kA, 45, T+32); - LOAD64H(skey->camellia.k[8], T+32); - rot_128(kL, 60, T+32); - LOAD64H(skey->camellia.k[9], T+40); - - /* rotate kA by 60, k11/k12 */ - rot_128(kA, 60, T+32); - LOAD64H(skey->camellia.k[10], T+32); - LOAD64H(skey->camellia.k[11], T+40); - - /* rotate kL by 77, kl3, kl4 */ - rot_128(kL, 77, T+32); - LOAD64H(skey->camellia.kl[2], T+32); - LOAD64H(skey->camellia.kl[3], T+40); - - /* rotate kL by 94, k13/k14 */ - rot_128(kL, 94, T+32); - LOAD64H(skey->camellia.k[12], T+32); - LOAD64H(skey->camellia.k[13], T+40); - - /* rotate kA by 94, k15/k16 */ - rot_128(kA, 94, T+32); - LOAD64H(skey->camellia.k[14], T+32); - LOAD64H(skey->camellia.k[15], T+40); - - /* rotate kL by 111, k17/k18 */ - rot_128(kL, 111, T+32); - LOAD64H(skey->camellia.k[16], T+32); - LOAD64H(skey->camellia.k[17], T+40); - - /* rotate kA by 111, kw3/kw4 */ - rot_128(kA, 111, T+32); - LOAD64H(skey->camellia.kw[2], T+32); - LOAD64H(skey->camellia.kw[3], T+40); - } else { - /* last two rounds */ - LOAD64H(A, T+32); LOAD64H(B, T+40); - B ^= F(A ^ key_sigma[4]); - A ^= F(B ^ key_sigma[5]); - STORE64H(A, T+32); STORE64H(B, T+40); - - /* grab kB */ - for (x = 0; x < 16; x++) { kB[x] = T[x+32]; } - - /* kw1/2 from kL*/ - LOAD64H(skey->camellia.kw[0], kL); - LOAD64H(skey->camellia.kw[1], kL+8); - - /* k1/k2 = kB */ - LOAD64H(skey->camellia.k[0], kB); - LOAD64H(skey->camellia.k[1], kB+8); - - /* k3/k4 = kR by 15 */ - rot_128(kR, 15, T+32); - LOAD64H(skey->camellia.k[2], T+32); - LOAD64H(skey->camellia.k[3], T+40); - - /* k5/k7 = kA by 15 */ - rot_128(kA, 15, T+32); - LOAD64H(skey->camellia.k[4], T+32); - LOAD64H(skey->camellia.k[5], T+40); - - /* kl1/2 = kR by 30 */ - rot_128(kR, 30, T+32); - LOAD64H(skey->camellia.kl[0], T+32); - LOAD64H(skey->camellia.kl[1], T+40); - - /* k7/k8 = kB by 30 */ - rot_128(kB, 30, T+32); - LOAD64H(skey->camellia.k[6], T+32); - LOAD64H(skey->camellia.k[7], T+40); - - /* k9/k10 = kL by 45 */ - rot_128(kL, 45, T+32); - LOAD64H(skey->camellia.k[8], T+32); - LOAD64H(skey->camellia.k[9], T+40); - - /* k11/k12 = kA by 45 */ - rot_128(kA, 45, T+32); - LOAD64H(skey->camellia.k[10], T+32); - LOAD64H(skey->camellia.k[11], T+40); - - /* kl3/4 = kL by 60 */ - rot_128(kL, 60, T+32); - LOAD64H(skey->camellia.kl[2], T+32); - LOAD64H(skey->camellia.kl[3], T+40); - - /* k13/k14 = kR by 60 */ - rot_128(kR, 60, T+32); - LOAD64H(skey->camellia.k[12], T+32); - LOAD64H(skey->camellia.k[13], T+40); - - /* k15/k16 = kB by 15 */ - rot_128(kB, 60, T+32); - LOAD64H(skey->camellia.k[14], T+32); - LOAD64H(skey->camellia.k[15], T+40); - - /* k17/k18 = kL by 77 */ - rot_128(kL, 77, T+32); - LOAD64H(skey->camellia.k[16], T+32); - LOAD64H(skey->camellia.k[17], T+40); - - /* kl5/6 = kA by 77 */ - rot_128(kA, 77, T+32); - LOAD64H(skey->camellia.kl[4], T+32); - LOAD64H(skey->camellia.kl[5], T+40); - - /* k19/k20 = kR by 94 */ - rot_128(kR, 94, T+32); - LOAD64H(skey->camellia.k[18], T+32); - LOAD64H(skey->camellia.k[19], T+40); - - /* k21/k22 = kA by 94 */ - rot_128(kA, 94, T+32); - LOAD64H(skey->camellia.k[20], T+32); - LOAD64H(skey->camellia.k[21], T+40); - - /* k23/k24 = kL by 111 */ - rot_128(kL, 111, T+32); - LOAD64H(skey->camellia.k[22], T+32); - LOAD64H(skey->camellia.k[23], T+40); - - /* kw2/kw3 = kB by 111 */ - rot_128(kB, 111, T+32); - LOAD64H(skey->camellia.kw[2], T+32); - LOAD64H(skey->camellia.kw[3], T+40); - } - - return CRYPT_OK; -} - -int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong64 L, R; - ulong32 a, b; - - LOAD64H(L, pt+0); LOAD64H(R, pt+8); - L ^= skey->camellia.kw[0]; - R ^= skey->camellia.kw[1]; - - /* first 6 rounds */ - R ^= F(L ^ skey->camellia.k[0]); - L ^= F(R ^ skey->camellia.k[1]); - R ^= F(L ^ skey->camellia.k[2]); - L ^= F(R ^ skey->camellia.k[3]); - R ^= F(L ^ skey->camellia.k[4]); - L ^= F(R ^ skey->camellia.k[5]); - - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); - a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); - R = (((ulong64)a) << 32) | b; - - /* second 6 rounds */ - R ^= F(L ^ skey->camellia.k[6]); - L ^= F(R ^ skey->camellia.k[7]); - R ^= F(L ^ skey->camellia.k[8]); - L ^= F(R ^ skey->camellia.k[9]); - R ^= F(L ^ skey->camellia.k[10]); - L ^= F(R ^ skey->camellia.k[11]); - - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); - a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); - R = (((ulong64)a) << 32) | b; - - /* third 6 rounds */ - R ^= F(L ^ skey->camellia.k[12]); - L ^= F(R ^ skey->camellia.k[13]); - R ^= F(L ^ skey->camellia.k[14]); - L ^= F(R ^ skey->camellia.k[15]); - R ^= F(L ^ skey->camellia.k[16]); - L ^= F(R ^ skey->camellia.k[17]); - - /* next FL */ - if (skey->camellia.R == 24) { - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); - a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); - R = (((ulong64)a) << 32) | b; - - /* fourth 6 rounds */ - R ^= F(L ^ skey->camellia.k[18]); - L ^= F(R ^ skey->camellia.k[19]); - R ^= F(L ^ skey->camellia.k[20]); - L ^= F(R ^ skey->camellia.k[21]); - R ^= F(L ^ skey->camellia.k[22]); - L ^= F(R ^ skey->camellia.k[23]); - } - - L ^= skey->camellia.kw[3]; - R ^= skey->camellia.kw[2]; - - STORE64H(R, ct+0); STORE64H(L, ct+8); - - return CRYPT_OK; -} - -int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong64 L, R; - ulong32 a, b; - - LOAD64H(R, ct+0); LOAD64H(L, ct+8); - L ^= skey->camellia.kw[3]; - R ^= skey->camellia.kw[2]; - - /* next FL */ - if (skey->camellia.R == 24) { - /* fourth 6 rounds */ - L ^= F(R ^ skey->camellia.k[23]); - R ^= F(L ^ skey->camellia.k[22]); - L ^= F(R ^ skey->camellia.k[21]); - R ^= F(L ^ skey->camellia.k[20]); - L ^= F(R ^ skey->camellia.k[19]); - R ^= F(L ^ skey->camellia.k[18]); - - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); - a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); - R = (((ulong64)a) << 32) | b; - - } - - /* third 6 rounds */ - L ^= F(R ^ skey->camellia.k[17]); - R ^= F(L ^ skey->camellia.k[16]); - L ^= F(R ^ skey->camellia.k[15]); - R ^= F(L ^ skey->camellia.k[14]); - L ^= F(R ^ skey->camellia.k[13]); - R ^= F(L ^ skey->camellia.k[12]); - - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); - a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); - R = (((ulong64)a) << 32) | b; - - /* second 6 rounds */ - L ^= F(R ^ skey->camellia.k[11]); - R ^= F(L ^ skey->camellia.k[10]); - L ^= F(R ^ skey->camellia.k[9]); - R ^= F(L ^ skey->camellia.k[8]); - L ^= F(R ^ skey->camellia.k[7]); - R ^= F(L ^ skey->camellia.k[6]); - - /* FL */ - a = (ulong32)(L >> 32); - b = (ulong32)(L & 0xFFFFFFFFUL); - a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); - b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); - L = (((ulong64)a) << 32) | b; - - /* FL^-1 */ - a = (ulong32)(R >> 32); - b = (ulong32)(R & 0xFFFFFFFFUL); - b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); - a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); - R = (((ulong64)a) << 32) | b; - - /* first 6 rounds */ - L ^= F(R ^ skey->camellia.k[5]); - R ^= F(L ^ skey->camellia.k[4]); - L ^= F(R ^ skey->camellia.k[3]); - R ^= F(L ^ skey->camellia.k[2]); - L ^= F(R ^ skey->camellia.k[1]); - R ^= F(L ^ skey->camellia.k[0]); - - R ^= skey->camellia.kw[1]; - L ^= skey->camellia.kw[0]; - - STORE64H(R, pt+8); STORE64H(L, pt+0); - - return CRYPT_OK; -} - -int camellia_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - -{ - 16, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, - 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 } -}, - -{ - 24, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, - 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 } -}, - - -{ - 32, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, - 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 } -}, - -{ - 32, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }, - { 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }, - { 0x79, 0x60, 0x10, 0x9F, 0xB6, 0xDC, 0x42, 0x94, - 0x7F, 0xCF, 0xE5, 0x9E, 0xA3, 0xC5, 0xEB, 0x6B } -} -}; - unsigned char buf[2][16]; - symmetric_key skey; - int err; - unsigned int x; - - for (x = 0; x < LTC_ARRAY_SIZE(tests); x++) { - zeromem(&skey, sizeof(skey)); - if ((err = camellia_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { - return err; - } - if ((err = camellia_ecb_encrypt(tests[x].pt, buf[0], &skey)) != CRYPT_OK) { - camellia_done(&skey); - return err; - } - if ((err = camellia_ecb_decrypt(tests[x].ct, buf[1], &skey)) != CRYPT_OK) { - camellia_done(&skey); - return err; - } - camellia_done(&skey); - if (compare_testvector(tests[x].ct, 16, buf[0], 16, "Camellia Encrypt", x) || - compare_testvector(tests[x].pt, 16, buf[1], 16, "Camellia Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -void camellia_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -int camellia_keysize(int *keysize) -{ - if (*keysize >= 32) { *keysize = 32; } - else if (*keysize >= 24) { *keysize = 24; } - else if (*keysize >= 16) { *keysize = 16; } - else return CRYPT_INVALID_KEYSIZE; - return CRYPT_OK; -} - -#undef loc - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/cast5.c b/Sources/DataLiteC/libtomcrypt/ciphers/cast5.c deleted file mode 100644 index e55d8ab..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/cast5.c +++ /dev/null @@ -1,709 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - - /** - @file cast5.c - Implementation of LTC_CAST5 (RFC 2144) by Tom St Denis - */ -#include "tomcrypt_private.h" - -#ifdef LTC_CAST5 - -const struct ltc_cipher_descriptor cast5_desc = { - "cast5", - 15, - 5, 16, 8, 16, - &cast5_setup, - &cast5_ecb_encrypt, - &cast5_ecb_decrypt, - &cast5_test, - &cast5_done, - &cast5_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 S1[256] = { -0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL, -0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL, -0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL, -0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL, -0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL, -0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL, -0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL, -0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL, -0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL, -0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL, -0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL, -0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL, -0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL, -0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL, -0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL, -0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL, -0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL, -0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL, -0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL, -0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL, -0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL, -0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL, -0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL, -0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL, -0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL, -0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL, -0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL, -0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL, -0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL, -0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL, -0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL, -0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL, -0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL, -0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL, -0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL, -0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL, -0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL, -0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL, -0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL, -0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL, -0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL, -0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL, -0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL}; - -static const ulong32 S2[256] = { -0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL, -0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL, -0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL, -0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL, -0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL, -0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL, -0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL, -0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL, -0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL, -0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL, -0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL, -0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL, -0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL, -0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL, -0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL, -0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL, -0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL, -0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL, -0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL, -0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL, -0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL, -0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL, -0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL, -0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL, -0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL, -0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL, -0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL, -0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL, -0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL, -0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL, -0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL, -0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL, -0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL, -0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL, -0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL, -0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL, -0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL, -0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL, -0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL, -0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL, -0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL, -0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL, -0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL}; - -static const ulong32 S3[256] = { -0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL, -0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL, -0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL, -0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL, -0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL, -0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL, -0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL, -0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL, -0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL, -0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL, -0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL, -0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL, -0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL, -0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL, -0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL, -0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL, -0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL, -0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL, -0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL, -0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL, -0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL, -0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL, -0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL, -0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL, -0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL, -0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL, -0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL, -0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL, -0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL, -0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL, -0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL, -0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL, -0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL, -0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL, -0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL, -0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL, -0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL, -0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL, -0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL, -0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL, -0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL, -0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL, -0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL}; - -static const ulong32 S4[256] = { -0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL, -0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL, -0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL, -0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL, -0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL, -0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL, -0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL, -0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL, -0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL, -0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL, -0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL, -0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL, -0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL, -0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL, -0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL, -0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL, -0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL, -0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL, -0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL, -0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL, -0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL, -0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL, -0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL, -0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL, -0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL, -0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL, -0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL, -0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL, -0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL, -0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL, -0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL, -0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL, -0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL, -0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL, -0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL, -0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL, -0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL, -0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL, -0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL, -0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL, -0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL, -0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL, -0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL}; - -static const ulong32 S5[256] = { -0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL, -0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL, -0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL, -0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL, -0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL, -0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL, -0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL, -0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL, -0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL, -0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL, -0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL, -0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL, -0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL, -0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL, -0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL, -0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL, -0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL, -0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL, -0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL, -0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL, -0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL, -0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL, -0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL, -0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL, -0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL, -0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL, -0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL, -0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL, -0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL, -0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL, -0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL, -0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL, -0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL, -0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL, -0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL, -0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL, -0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL, -0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL, -0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL, -0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL, -0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL, -0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL, -0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL}; - -static const ulong32 S6[256] = { -0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL, -0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL, -0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL, -0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL, -0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL, -0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL, -0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL, -0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL, -0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL, -0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL, -0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL, -0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL, -0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL, -0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL, -0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL, -0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL, -0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL, -0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL, -0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL, -0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL, -0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL, -0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL, -0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL, -0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL, -0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL, -0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL, -0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL, -0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL, -0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL, -0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL, -0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL, -0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL, -0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL, -0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL, -0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL, -0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL, -0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL, -0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL, -0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL, -0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL, -0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL, -0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL, -0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL}; - -static const ulong32 S7[256] = { -0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL, -0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL, -0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL, -0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL, -0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL, -0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL, -0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL, -0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL, -0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL, -0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL, -0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL, -0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL, -0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL, -0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL, -0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL, -0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL, -0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL, -0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL, -0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL, -0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL, -0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL, -0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL, -0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL, -0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL, -0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL, -0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL, -0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL, -0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL, -0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL, -0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL, -0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL, -0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL, -0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL, -0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL, -0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL, -0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL, -0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL, -0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL, -0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL, -0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL, -0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL, -0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL, -0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL}; - -static const ulong32 S8[256] = { -0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL, -0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL, -0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL, -0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL, -0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL, -0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL, -0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL, -0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL, -0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL, -0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL, -0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL, -0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL, -0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL, -0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL, -0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL, -0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL, -0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL, -0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL, -0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL, -0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL, -0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL, -0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL, -0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL, -0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL, -0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL, -0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL, -0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL, -0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL, -0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL, -0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL, -0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL, -0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL, -0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL, -0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL, -0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL, -0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL, -0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL, -0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL, -0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL, -0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL, -0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL, -0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL, -0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL}; - -/* returns the i'th byte of a variable */ -#ifdef _MSC_VER - #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))) -#else - #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255) -#endif - - /** - Initialize the LTC_CAST5 block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -#ifdef LTC_CLEAN_STACK -static int s_cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#else -int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#endif -{ - ulong32 x[4], z[4]; - unsigned char buf[16]; - int y, i; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - if (num_rounds == 12 && keylen > 10) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen < 5 || keylen > 16) { - return CRYPT_INVALID_KEYSIZE; - } - - /* extend the key as required */ - zeromem(buf, sizeof(buf)); - XMEMCPY(buf, key, (size_t)keylen); - - /* load and start the awful looking network */ - for (y = 0; y < 4; y++) { - LOAD32H(x[3-y],buf+4*y); - } - - for (i = y = 0; y < 2; y++) { - z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; - z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; - z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; - z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; - skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)]; - skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)]; - skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)]; - skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)]; - - x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; - x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; - x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; - x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; - skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)]; - skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)]; - skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)]; - skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)]; - - /* second half */ - z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; - z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; - z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; - z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; - skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)]; - skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)]; - skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)]; - skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)]; - - x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; - x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; - x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; - x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; - skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)]; - skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)]; - skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)]; - skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)]; - } - - skey->cast5.keylen = keylen; - -#ifdef LTC_CLEAN_STACK - zeromem(buf, sizeof(buf)); - zeromem(x, sizeof(x)); - zeromem(z, sizeof(z)); -#endif - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int z; - z = s_cast5_setup(key, keylen, num_rounds, skey); - burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2); - return z; -} -#endif - -#define FI cast5_FI -static LTC_INLINE ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr) -{ - ulong32 I; - I = (Km + R); - I = ROL(I, Kr); - return ((S1[LTC_BYTE(I, 3)] ^ S2[LTC_BYTE(I,2)]) - S3[LTC_BYTE(I,1)]) + S4[LTC_BYTE(I,0)]; -} - -static LTC_INLINE ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr) -{ - ulong32 I; - I = (Km ^ R); - I = ROL(I, Kr); - return ((S1[LTC_BYTE(I, 3)] - S2[LTC_BYTE(I,2)]) + S3[LTC_BYTE(I,1)]) ^ S4[LTC_BYTE(I,0)]; -} - -static LTC_INLINE ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr) -{ - ulong32 I; - I = (Km - R); - I = ROL(I, Kr); - return ((S1[LTC_BYTE(I, 3)] + S2[LTC_BYTE(I,2)]) ^ S3[LTC_BYTE(I,1)]) - S4[LTC_BYTE(I,0)]; -} - -/** - Encrypts a block of text with LTC_CAST5 - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled -*/ -#ifdef LTC_CLEAN_STACK -static int s_cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 R, L; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(L,&pt[0]); - LOAD32H(R,&pt[4]); - L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); - R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); - L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); - R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); - L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); - R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); - L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); - R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); - L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); - R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); - L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); - R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); - if (skey->cast5.keylen > 10) { - L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); - R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); - L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); - R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); - } - STORE32H(R,&ct[0]); - STORE32H(L,&ct[4]); - return CRYPT_OK; -} - - -#ifdef LTC_CLEAN_STACK -int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_cast5_ecb_encrypt(pt,ct,skey); - burn_stack(sizeof(ulong32)*3); - return err; -} -#endif - -/** - Decrypts a block of text with LTC_CAST5 - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled -*/ -#ifdef LTC_CLEAN_STACK -static int s_cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 R, L; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(R,&ct[0]); - LOAD32H(L,&ct[4]); - if (skey->cast5.keylen > 10) { - R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); - L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); - R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); - L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); - } - R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); - L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); - R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); - L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); - R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); - L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); - R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); - L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); - R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); - L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); - R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); - L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); - STORE32H(L,&pt[0]); - STORE32H(R,&pt[4]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_cast5_ecb_decrypt(ct,pt,skey); - burn_stack(sizeof(ulong32)*3); - return err; -} -#endif - -/** - Performs a self-test of the LTC_CAST5 block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int cast5_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen; - unsigned char key[16]; - unsigned char pt[8]; - unsigned char ct[8]; - } tests[] = { - { 16, - {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, - {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, - {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2} - }, - { 10, - {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, - {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B}, - }, - { 5, - {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, - {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E} - } - }; - int i, y, err; - symmetric_key key; - unsigned char tmp[2][8]; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - cast5_ecb_encrypt(tests[i].pt, tmp[0], &key); - cast5_ecb_decrypt(tmp[0], tmp[1], &key); - if ((compare_testvector(tmp[0], 8, tests[i].ct, 8, "CAST5 Encrypt", i) != 0) || - (compare_testvector(tmp[1], 8, tests[i].pt, 8, "CAST5 Decrypt", i) != 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - - } - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void cast5_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int cast5_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 5) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 16) { - *keysize = 16; - } - return CRYPT_OK; -} - -#undef GB -#undef FI - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/des.c b/Sources/DataLiteC/libtomcrypt/ciphers/des.c deleted file mode 100644 index 2c03666..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/des.c +++ /dev/null @@ -1,2250 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file des.c - DES code submitted by Dobes Vandermeer -*/ - -#ifdef LTC_DES - -#define EN0 0 -#define DE1 1 - -const struct ltc_cipher_descriptor des_desc = -{ - "des", - 13, - 8, 8, 8, 16, - &des_setup, - &des_ecb_encrypt, - &des_ecb_decrypt, - &des_test, - &des_done, - &des_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -const struct ltc_cipher_descriptor des3_desc = -{ - "3des", - 14, - 16, 24, 8, 16, - &des3_setup, - &des3_ecb_encrypt, - &des3_ecb_decrypt, - &des3_test, - &des3_done, - &des3_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -const struct ltc_cipher_descriptor desx_desc = -{ - "desx", - 27, - 24, 24, 8, 16, - &desx_setup, - &desx_ecb_encrypt, - &desx_ecb_decrypt, - &desx_test, - &desx_done, - &desx_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 bytebit[8] = -{ - 0200, 0100, 040, 020, 010, 04, 02, 01 -}; - -static const ulong32 bigbyte[24] = -{ - 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, - 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, - 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, - 0x800UL, 0x400UL, 0x200UL, 0x100UL, - 0x80UL, 0x40UL, 0x20UL, 0x10UL, - 0x8UL, 0x4UL, 0x2UL, 0x1L -}; - -/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ - -static const unsigned char pc1[56] = { - 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, - 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, - 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, - 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 -}; - -static const unsigned char totrot[16] = { - 1, 2, 4, 6, - 8, 10, 12, 14, - 15, 17, 19, 21, - 23, 25, 27, 28 -}; - -static const unsigned char pc2[48] = { - 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, - 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, - 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 -}; - - -static const ulong32 SP1[64] = -{ - 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, - 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, - 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, - 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, - 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, - 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, - 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, - 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, - 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, - 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, - 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, - 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, - 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, - 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL -}; - -static const ulong32 SP2[64] = -{ - 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, - 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, - 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, - 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, - 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, - 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, - 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, - 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, - 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, - 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, - 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, - 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, - 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, - 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, - 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, - 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL -}; - -static const ulong32 SP3[64] = -{ - 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, - 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, - 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, - 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, - 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, - 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, - 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, - 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, - 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, - 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, - 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, - 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, - 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, - 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, - 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, - 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL -}; - -static const ulong32 SP4[64] = -{ - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, - 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, - 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, - 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, - 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, - 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, - 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, - 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, - 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL -}; - -static const ulong32 SP5[64] = -{ - 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, - 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, - 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, - 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, - 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, - 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, - 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, - 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, - 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, - 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, - 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, - 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, - 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, - 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, - 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, - 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL -}; - -static const ulong32 SP6[64] = -{ - 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, - 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, - 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, - 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, - 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, - 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, - 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, - 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, - 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, - 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, - 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, - 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, - 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, - 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL -}; - -static const ulong32 SP7[64] = -{ - 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, - 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, - 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, - 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, - 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, - 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, - 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, - 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, - 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, - 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, - 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, - 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, - 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, - 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, - 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, - 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL -}; - -static const ulong32 SP8[64] = -{ - 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, - 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, - 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, - 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, - 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, - 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, - 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, - 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, - 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, - 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, - 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, - 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, - 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, - 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, - 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, - 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL -}; - -#ifndef LTC_SMALL_CODE - -static const ulong64 des_ip[8][256] = { - -{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), - CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), - CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), - CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), - CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), - CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), - CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), - CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), - CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), - CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), - CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), - CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), - CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), - CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), - CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), - CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), - CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), - CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), - CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), - CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), - CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), - CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), - CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), - CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), - CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), - CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), - CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), - CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), - CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), - CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), - CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), - CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), - CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), - CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), - CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), - CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), - CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), - CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), - CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), - CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), - CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), - CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), - CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), - CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), - CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), - CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), - CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), - CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), - CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), - CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), - CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), - CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), - CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), - CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), - CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), - CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), - CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), - CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), - CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), - CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), - CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), - CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), - CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), - CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), - CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), - CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), - CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), - CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), - CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), - CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), - CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), - CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), - CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), - CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), - CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), - CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), - CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), - CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), - CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), - CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), - CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), - CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), - CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), - CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), - CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), - CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), - CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), - CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), - CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), - CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), - CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), - CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), - CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), - CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), - CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), - CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), - CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), - CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), - CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), - CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), - CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), - CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), - CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), - CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), - CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), - CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), - CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), - CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), - CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), - CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), - CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), - CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), - CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), - CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), - CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), - CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), - CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), - CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), - CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), - CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), - CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), - CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), - CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), - CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), - CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), - CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), - CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), - CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), - CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), - CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), - CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), - CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), - CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), - CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), - CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), - CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), - CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), - CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), - CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), - CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), - CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), - CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), - CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), - CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), - CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), - CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), - CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), - CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), - CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), - CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), - CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), - CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), - CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), - CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), - CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), - CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), - CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), - CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), - CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), - CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), - CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), - CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), - CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), - CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), - CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), - CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), - CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), - CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), - CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), - CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), - CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), - CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), - CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), - CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), - CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), - CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), - CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), - CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), - CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), - CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), - CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), - CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), - CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), - CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), - CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), - CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), - CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), - CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), - CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), - CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), - CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), - CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), - CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), - CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), - CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), - CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), - CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), - CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), - CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), - CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), - CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), - CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), - CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), - CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), - CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), - CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), - CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), - CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), - CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), - CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), - CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), - CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), - CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), - CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), - CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), - CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), - CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), - CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), - CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), - CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), - CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), - CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), - CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), - CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), - CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), - CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), - CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), - CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), - CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), - CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), - CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), - CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), - CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), - CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), - CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), - CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), - CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), - CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), - CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), - CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), - CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), - CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), - CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), - CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), - CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), - CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), - CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), - CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), - CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), - CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), - CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), - CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), - CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), - CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), - CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), - CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), - CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), - CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), - CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), - CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), - CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), - CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), - CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), - CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), - CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), - CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), - CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), - CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), - CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), - CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), - CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), - CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), - CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), - CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), - CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), - CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), - CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), - CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), - CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), - CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), - CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), - CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), - CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), - CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), - CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), - CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), - CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), - CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), - CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), - CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), - CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), - CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), - CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), - CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), - CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), - CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), - CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), - CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), - CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), - CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), - CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), - CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), - CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), - CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), - CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), - CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), - CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), - CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), - CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), - CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), - CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), - CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), - CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), - CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), - CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), - CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), - CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), - CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), - CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), - CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), - CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), - CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), - CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), - CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), - CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), - CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), - CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), - CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), - CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), - CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), - CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), - CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), - CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), - CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), - CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), - CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), - CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), - CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), - CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), - CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), - CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), - CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), - CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), - CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), - CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), - CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), - CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), - CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), - CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), - CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), - CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), - CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), - CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), - CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), - CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), - CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), - CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), - CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), - CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), - CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), - CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), - CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), - CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), - CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), - CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), - CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), - CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), - CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), - CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), - CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), - CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), - CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), - CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), - CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), - CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), - CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), - CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), - CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), - CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), - CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), - CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), - CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), - CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), - CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), - CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), - CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), - CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), - CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), - CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), - CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), - CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), - CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), - CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), - CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), - CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), - CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), - CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), - CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), - CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), - CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), - CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), - CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), - CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), - CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), - CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), - CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), - CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), - CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), - CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), - CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), - CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), - CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), - CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), - CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), - CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), - CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), - CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), - CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), - CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), - CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), - CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), - CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), - CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), - CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), - CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), - CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), - CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), - CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), - CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), - CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), - CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), - CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), - CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), - CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), - CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), - CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), - CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), - CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), - CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), - CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), - CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), - CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), - CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), - CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), - CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), - CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), - CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), - CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), - CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), - CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), - CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), - CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), - CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), - CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), - CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), - CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), - CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), - CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), - CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), - CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), - CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), - CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), - CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), - CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), - CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), - CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), - CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), - CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), - CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), - CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), - CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), - CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), - CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), - CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), - CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), - CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), - CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), - CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), - CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), - CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), - CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), - CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), - CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), - CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), - CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), - CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), - CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), - CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), - CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), - CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), - CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), - CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), - CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), - CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), - CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), - CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), - CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), - CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), - CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), - CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), - CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), - CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), - CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), - CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), - CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020) - }}; - -static const ulong64 des_fp[8][256] = { - -{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), - CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), - CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), - CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), - CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), - CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), - CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), - CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), - CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), - CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), - CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), - CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), - CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), - CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), - CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), - CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), - CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), - CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), - CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), - CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), - CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), - CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), - CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), - CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), - CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), - CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), - CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), - CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), - CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), - CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), - CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), - CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), - CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), - CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), - CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), - CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), - CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), - CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), - CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), - CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), - CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), - CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), - CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), - CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), - CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), - CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), - CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), - CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), - CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), - CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), - CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), - CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), - CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), - CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), - CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), - CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), - CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), - CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), - CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), - CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), - CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), - CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), - CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), - CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), - CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), - CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), - CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), - CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), - CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), - CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), - CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), - CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), - CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), - CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), - CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), - CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), - CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), - CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), - CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), - CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), - CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), - CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), - CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), - CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), - CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), - CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), - CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), - CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), - CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), - CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), - CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), - CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), - CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), - CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), - CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), - CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), - CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), - CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), - CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), - CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), - CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), - CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), - CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), - CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), - CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), - CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), - CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), - CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), - CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), - CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), - CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), - CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), - CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), - CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), - CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), - CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), - CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), - CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), - CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), - CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), - CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), - CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), - CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), - CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), - CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), - CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), - CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), - CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), - CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), - CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), - CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), - CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), - CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), - CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), - CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), - CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), - CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), - CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), - CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), - CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), - CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), - CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), - CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), - CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), - CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), - CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), - CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), - CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), - CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), - CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), - CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), - CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), - CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), - CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), - CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), - CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), - CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), - CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), - CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), - CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), - CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), - CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), - CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), - CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), - CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), - CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), - CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), - CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), - CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), - CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), - CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), - CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), - CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), - CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), - CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), - CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), - CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), - CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), - CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), - CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), - CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), - CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), - CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), - CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), - CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), - CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), - CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), - CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), - CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), - CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), - CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), - CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), - CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), - CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), - CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), - CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), - CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), - CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), - CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), - CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), - CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), - CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), - CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), - CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), - CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), - CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), - CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), - CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), - CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), - CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), - CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), - CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), - CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), - CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), - CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), - CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), - CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), - CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), - CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), - CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), - CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), - CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), - CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), - CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), - CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), - CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), - CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), - CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), - CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), - CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), - CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), - CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), - CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), - CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), - CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), - CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), - CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), - CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), - CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), - CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), - CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), - CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), - CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), - CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), - CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), - CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), - CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), - CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), - CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), - CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), - CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), - CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), - CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), - CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), - CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), - CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), - CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), - CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), - CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), - CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), - CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), - CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), - CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), - CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), - CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), - CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), - CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), - CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), - CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), - CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), - CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), - CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), - CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), - CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), - CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), - CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), - CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), - CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), - CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), - CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), - CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), - CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), - CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), - CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), - CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), - CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), - CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), - CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), - CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), - CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), - CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), - CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), - CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), - CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), - CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), - CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), - CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), - CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), - CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), - CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), - CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), - CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), - CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), - CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), - CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), - CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), - CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), - CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), - CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), - CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), - CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), - CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), - CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), - CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), - CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), - CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), - CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), - CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), - CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), - CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), - CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), - CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), - CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), - CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), - CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), - CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), - CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), - CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), - CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), - CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), - CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), - CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), - CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), - CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), - CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), - CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), - CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), - CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), - CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), - CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), - CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), - CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), - CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), - CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), - CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), - CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), - CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), - CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), - CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), - CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), - CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), - CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), - CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), - CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), - CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), - CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), - CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), - CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), - CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), - CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), - CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), - CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), - CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), - CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), - CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), - CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), - CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), - CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), - CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), - CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), - CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), - CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), - CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), - CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), - CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), - CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), - CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), - CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), - CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), - CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), - CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), - CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), - CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), - CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), - CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), - CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), - CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), - CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), - CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), - CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), - CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), - CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), - CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), - CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), - CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), - CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), - CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), - CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), - CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), - CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), - CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), - CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), - CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), - CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), - CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), - CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), - CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), - CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), - CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), - CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), - CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), - CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), - CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), - CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), - CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), - CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), - CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), - CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), - CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), - CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), - CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), - CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), - CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), - CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), - CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), - CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), - CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), - CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), - CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), - CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), - CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), - CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), - CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), - CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), - CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), - CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), - CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), - CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), - CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), - CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), - CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), - CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010) - }, -{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), - CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), - CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), - CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), - CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), - CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), - CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), - CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), - CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), - CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), - CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), - CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), - CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), - CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), - CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), - CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), - CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), - CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), - CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), - CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), - CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), - CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), - CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), - CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), - CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), - CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), - CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), - CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), - CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), - CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), - CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), - CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), - CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), - CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), - CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), - CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), - CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), - CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), - CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), - CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), - CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), - CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), - CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), - CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), - CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), - CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), - CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), - CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), - CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), - CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), - CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), - CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), - CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), - CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), - CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), - CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), - CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), - CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), - CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), - CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), - CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), - CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), - CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), - CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040) - }}; - -#endif - - -static void cookey(const ulong32 *raw1, ulong32 *keyout); - -#ifdef LTC_CLEAN_STACK -static void s_deskey(const unsigned char *key, short edf, ulong32 *keyout) -#else -static void deskey(const unsigned char *key, short edf, ulong32 *keyout) -#endif -{ - ulong32 i, j, l, m, n, kn[32]; - unsigned char pc1m[56], pcr[56]; - - for (j=0; j < 56; j++) { - l = (ulong32)pc1[j]; - m = l & 7; - pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); - } - - for (i=0; i < 16; i++) { - if (edf == DE1) { - m = (15 - i) << 1; - } else { - m = i << 1; - } - n = m + 1; - kn[m] = kn[n] = 0L; - for (j=0; j < 28; j++) { - l = j + (ulong32)totrot[i]; - if (l < 28) { - pcr[j] = pc1m[l]; - } else { - pcr[j] = pc1m[l - 28]; - } - } - for (/*j = 28*/; j < 56; j++) { - l = j + (ulong32)totrot[i]; - if (l < 56) { - pcr[j] = pc1m[l]; - } else { - pcr[j] = pc1m[l - 28]; - } - } - for (j=0; j < 24; j++) { - if ((int)pcr[(int)pc2[j]] != 0) { - kn[m] |= bigbyte[j]; - } - if ((int)pcr[(int)pc2[j+24]] != 0) { - kn[n] |= bigbyte[j]; - } - } - } - - cookey(kn, keyout); -} - -#ifdef LTC_CLEAN_STACK -static void deskey(const unsigned char *key, short edf, ulong32 *keyout) -{ - s_deskey(key, edf, keyout); - burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112); -} -#endif - -#ifdef LTC_CLEAN_STACK -static void s_cookey(const ulong32 *raw1, ulong32 *keyout) -#else -static void cookey(const ulong32 *raw1, ulong32 *keyout) -#endif -{ - ulong32 *cook; - const ulong32 *raw0; - ulong32 dough[32]; - int i; - - cook = dough; - for(i=0; i < 16; i++, raw1++) - { - raw0 = raw1++; - *cook = (*raw0 & 0x00fc0000L) << 6; - *cook |= (*raw0 & 0x00000fc0L) << 10; - *cook |= (*raw1 & 0x00fc0000L) >> 10; - *cook++ |= (*raw1 & 0x00000fc0L) >> 6; - *cook = (*raw0 & 0x0003f000L) << 12; - *cook |= (*raw0 & 0x0000003fL) << 16; - *cook |= (*raw1 & 0x0003f000L) >> 4; - *cook++ |= (*raw1 & 0x0000003fL); - } - - XMEMCPY(keyout, dough, sizeof(dough)); -} - -#ifdef LTC_CLEAN_STACK -static void cookey(const ulong32 *raw1, ulong32 *keyout) -{ - s_cookey(raw1, keyout); - burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int)); -} -#endif - -#ifndef LTC_CLEAN_STACK -static void desfunc(ulong32 *block, const ulong32 *keys) -#else -static void s_desfunc(ulong32 *block, const ulong32 *keys) -#endif -{ - ulong32 work, right, leftt; - int cur_round; - - leftt = block[0]; - right = block[1]; - -#ifdef LTC_SMALL_CODE - work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; - right ^= work; - leftt ^= (work << 4); - - work = ((leftt >> 16) ^ right) & 0x0000ffffL; - right ^= work; - leftt ^= (work << 16); - - work = ((right >> 2) ^ leftt) & 0x33333333L; - leftt ^= work; - right ^= (work << 2); - - work = ((right >> 8) ^ leftt) & 0x00ff00ffL; - leftt ^= work; - right ^= (work << 8); - - right = ROLc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - - leftt ^= work; - right ^= work; - leftt = ROLc(leftt, 1); -#else - { - ulong64 tmp; - tmp = des_ip[0][LTC_BYTE(leftt, 0)] ^ - des_ip[1][LTC_BYTE(leftt, 1)] ^ - des_ip[2][LTC_BYTE(leftt, 2)] ^ - des_ip[3][LTC_BYTE(leftt, 3)] ^ - des_ip[4][LTC_BYTE(right, 0)] ^ - des_ip[5][LTC_BYTE(right, 1)] ^ - des_ip[6][LTC_BYTE(right, 2)] ^ - des_ip[7][LTC_BYTE(right, 3)]; - leftt = (ulong32)(tmp >> 32); - right = (ulong32)(tmp & 0xFFFFFFFFUL); - } -#endif - - for (cur_round = 0; cur_round < 8; cur_round++) { - work = RORc(right, 4) ^ *keys++; - leftt ^= SP7[work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = right ^ *keys++; - leftt ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - - work = RORc(leftt, 4) ^ *keys++; - right ^= SP7[ work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = leftt ^ *keys++; - right ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - } - -#ifdef LTC_SMALL_CODE - right = RORc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - leftt ^= work; - right ^= work; - leftt = RORc(leftt, 1); - work = ((leftt >> 8) ^ right) & 0x00ff00ffL; - right ^= work; - leftt ^= (work << 8); - /* -- */ - work = ((leftt >> 2) ^ right) & 0x33333333L; - right ^= work; - leftt ^= (work << 2); - work = ((right >> 16) ^ leftt) & 0x0000ffffL; - leftt ^= work; - right ^= (work << 16); - work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; - leftt ^= work; - right ^= (work << 4); -#else - { - ulong64 tmp; - tmp = des_fp[0][LTC_BYTE(leftt, 0)] ^ - des_fp[1][LTC_BYTE(leftt, 1)] ^ - des_fp[2][LTC_BYTE(leftt, 2)] ^ - des_fp[3][LTC_BYTE(leftt, 3)] ^ - des_fp[4][LTC_BYTE(right, 0)] ^ - des_fp[5][LTC_BYTE(right, 1)] ^ - des_fp[6][LTC_BYTE(right, 2)] ^ - des_fp[7][LTC_BYTE(right, 3)]; - leftt = (ulong32)(tmp >> 32); - right = (ulong32)(tmp & 0xFFFFFFFFUL); - } -#endif - - block[0] = right; - block[1] = leftt; -} - -#ifdef LTC_CLEAN_STACK -static void desfunc(ulong32 *block, const ulong32 *keys) -{ - s_desfunc(block, keys); - burn_stack(sizeof(ulong32) * 4 + sizeof(int)); -} -#endif - - /** - Initialize the DES block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 8) { - return CRYPT_INVALID_KEYSIZE; - } - - deskey(key, EN0, skey->des.ek); - deskey(key, DE1, skey->des.dk); - - return CRYPT_OK; -} - - /** - Initialize the DES-X block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int desx_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - if(num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 24) { - return CRYPT_INVALID_KEYSIZE; - } - - deskey(key, EN0, skey->desx.ek); - deskey(key, DE1, skey->desx.dk); - - LOAD32H(skey->desx.k[0][0], key + 8); - LOAD32H(skey->desx.k[0][1], key + 12); - LOAD32H(skey->desx.k[1][0], key + 16); - LOAD32H(skey->desx.k[1][1], key + 20); - - return CRYPT_OK; -} - - /** - Initialize the 3DES-EDE block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if(num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 24 && keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - deskey(key, EN0, skey->des3.ek[0]); - deskey(key+8, DE1, skey->des3.ek[1]); - if (keylen == 24) { - deskey(key+16, EN0, skey->des3.ek[2]); - } else { - /* two-key 3DES: K3=K1 */ - deskey(key, EN0, skey->des3.ek[2]); - } - - deskey(key, DE1, skey->des3.dk[2]); - deskey(key+8, EN0, skey->des3.dk[1]); - if (keylen == 24) { - deskey(key+16, DE1, skey->des3.dk[0]); - } else { - /* two-key 3DES: K3=K1 */ - deskey(key, DE1, skey->des3.dk[0]); - } - - return CRYPT_OK; -} - -/** - Encrypts a block of text with DES - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 work[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], pt+0); - LOAD32H(work[1], pt+4); - desfunc(work, skey->des.ek); - STORE32H(work[0],ct+0); - STORE32H(work[1],ct+4); - return CRYPT_OK; -} - -/** - Decrypts a block of text with DES - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 work[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], ct+0); - LOAD32H(work[1], ct+4); - desfunc(work, skey->des.dk); - STORE32H(work[0],pt+0); - STORE32H(work[1],pt+4); - return CRYPT_OK; -} - -/** - Encrypts a block of text with DES-X - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int desx_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 work[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], pt+0); - LOAD32H(work[1], pt+4); - work[0] ^= skey->desx.k[0][0]; - work[1] ^= skey->desx.k[0][1]; - desfunc(work, skey->desx.ek); - work[0] ^= skey->desx.k[1][0]; - work[1] ^= skey->desx.k[1][1]; - STORE32H(work[0],ct+0); - STORE32H(work[1],ct+4); - return CRYPT_OK; -} - -/** - Decrypts a block of text with DES-X - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int desx_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 work[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], ct+0); - LOAD32H(work[1], ct+4); - work[0] ^= skey->desx.k[1][0]; - work[1] ^= skey->desx.k[1][1]; - desfunc(work, skey->des.dk); - work[0] ^= skey->desx.k[0][0]; - work[1] ^= skey->desx.k[0][1]; - STORE32H(work[0],pt+0); - STORE32H(work[1],pt+4); - return CRYPT_OK; -} - -/** - Encrypts a block of text with 3DES-EDE - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 work[2]; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], pt+0); - LOAD32H(work[1], pt+4); - desfunc(work, skey->des3.ek[0]); - desfunc(work, skey->des3.ek[1]); - desfunc(work, skey->des3.ek[2]); - STORE32H(work[0],ct+0); - STORE32H(work[1],ct+4); - return CRYPT_OK; -} - -/** - Decrypts a block of text with 3DES-EDE - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 work[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(work[0], ct+0); - LOAD32H(work[1], ct+4); - desfunc(work, skey->des3.dk[0]); - desfunc(work, skey->des3.dk[1]); - desfunc(work, skey->des3.dk[2]); - STORE32H(work[0],pt+0); - STORE32H(work[1],pt+4); - return CRYPT_OK; -} - -/** - Performs a self-test of the DES block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int des_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct des_test_case { - unsigned char key[8], txt[8], out[8]; - } cases[] = { - { { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, - { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, - { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, - { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, - { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, - { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, - { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, - { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - - { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } }, - { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } }, - { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } }, - { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } }, - { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } }, - { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } }, - { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } }, - { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } }, - { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } }, - { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } }, - { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } }, - { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } }, - { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } }, - { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } }, - { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } }, - { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } }, - { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } }, - { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } }, - { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } }, - { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } }, - { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } }, - { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } }, - { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } }, - { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } }, - { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } }, - { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } }, - { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } }, - { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } }, - { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } }, - { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } }, - { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } }, - - /*** more test cases you could add if you are not convinced (the above test cases aren't really too good): - - key plaintext ciphertext - 0000000000000000 0000000000000000 8CA64DE9C1B123A7 - FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 - 3000000000000000 1000000000000001 958E6E627A05557B - 1111111111111111 1111111111111111 F40379AB9E0EC533 - 0123456789ABCDEF 1111111111111111 17668DFC7292532D - 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD - 0000000000000000 0000000000000000 8CA64DE9C1B123A7 - FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 - 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B - 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 - 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A - 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A - 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 - 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B - 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 - 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A - 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F - 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 - 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 - 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A - 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 - 025816164629B007 480D39006EE762F2 A1F9915541020B56 - 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 - 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC - 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A - 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 - 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 - 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 - 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 - E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 - 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 - FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE - 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D - FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 - - http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt - ***/ - }; - unsigned char key[8], pt[8], ct[8], tmp[8]; - symmetric_key skey; - int i, err; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(cases); i++) - { - if ((err = des_setup(cases[i].key, 8, 0, &skey)) != CRYPT_OK) { - return err; - } - - des_ecb_encrypt(cases[i].txt, ct, &skey); - - if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "DES Encrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - des_ecb_decrypt(ct, pt, &skey); - - if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "DES Decrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ - - for (i = 0; i < 8; i++) key[i] = i; - - if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) { - return err; - } - - for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; - for (i = 0; i < 1000; i++) des_ecb_encrypt(tmp, tmp, &skey); - for (i = 0; i < 1000; i++) des_ecb_decrypt(tmp, tmp, &skey); - - if (compare_testvector(tmp, 8, pt, 8, "DES", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - -int desx_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - unsigned char key[24], pt[8], tmp[8]; - symmetric_key skey; - int i, err; - - if ((err = des_test()) != CRYPT_OK) { - return err; - } - - /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ - - for (i = 0; i < 24; i++) key[i] = i; - - if ((err = desx_setup(key, 24, 0, &skey)) != CRYPT_OK) { - return err; - } - - for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; - for (i = 0; i < 1000; i++) desx_ecb_encrypt(tmp, tmp, &skey); - for (i = 0; i < 1000; i++) desx_ecb_decrypt(tmp, tmp, &skey); - - if (compare_testvector(tmp, 8, pt, 8, "DES-X", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - -int des3_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct des3_test_case { - unsigned char key[16], txt[8], out[8]; - } cases[] = { - /* - https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-2-Key-128-64.unverified.test-vectors - */ - { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFA, 0xFD, 0x50, 0x84, 0x37, 0x4F, 0xCE, 0x34 } }, - { { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x60, 0xCC, 0x37, 0xB7, 0xB5, 0x37, 0xA1, 0xDC } }, - { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xBE, 0x3E, 0x73, 0x04, 0xFE, 0x92, 0xC2, 0xBC } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, - { 0xE5, 0xA9, 0xE3, 0x80, 0x03, 0xA5, 0xA0, 0xFD }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0xE4, 0xFC, 0x19, 0xD6, 0x94, 0x63, 0xB7, 0x83 }, - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } }, - }; - unsigned char key[24], pt[8], ct[8], tmp[8]; - symmetric_key skey; - int i, err; - - if ((err = des_test()) != CRYPT_OK) { - return err; - } - - for (i = 0; i < (int)LTC_ARRAY_SIZE(cases); i++) - { - if ((err = des3_setup(cases[i].key, 16, 0, &skey)) != CRYPT_OK) { - return err; - } - - des3_ecb_encrypt(cases[i].txt, ct, &skey); - - if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "3DES Encrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - des3_ecb_decrypt(ct, pt, &skey); - - if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "3DES Decrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ - - for (i = 0; i < 24; i++) key[i] = i; - - if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) { - return err; - } - - for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; - for (i = 0; i < 1000; i++) des3_ecb_encrypt(tmp, tmp, &skey); - for (i = 0; i < 1000; i++) des3_ecb_decrypt(tmp, tmp, &skey); - - if (compare_testvector(tmp, 8, pt, 8, "3DES", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void des_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** Terminate the context - @param skey The scheduled key -*/ -void desx_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** Terminate the context - @param skey The scheduled key -*/ -void des3_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int des_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if(*keysize < 8) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 8; - return CRYPT_OK; -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int desx_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if(*keysize < 24) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 24; - return CRYPT_OK; -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int des3_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - return CRYPT_OK; - } - *keysize = 24; - return CRYPT_OK; -} - -#undef EN0 -#undef DE1 - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/idea.c b/Sources/DataLiteC/libtomcrypt/ciphers/idea.c deleted file mode 100644 index f663b48..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/idea.c +++ /dev/null @@ -1,258 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* Based on idea.cpp - originally written and placed in the public domain by Wei Dai - https://github.com/weidai11/cryptopp/blob/master/idea.cpp - - Patents should be expired. On 2017-10-16 wikipedia says: - https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm - - A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990, - then an international patent application was filed under the Patent Cooperation Treaty on - May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands, - Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European - patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011), - the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012) - and Japan (JP 3225440) (expired May 16, 2011). - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_IDEA - -const struct ltc_cipher_descriptor idea_desc = { - "idea", - 24, /* cipher_ID */ - 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */ - &idea_setup, - &idea_ecb_encrypt, - &idea_ecb_decrypt, - &idea_test, - &idea_done, - &idea_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -typedef unsigned short int ushort16; - -#define LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */ -#define HIGH16(x) ((x)>>16) -#define MUL(a,b) { \ - ulong32 p = (ulong32)LOW16(a) * b; \ - if (p) { \ - p = LOW16(p) - HIGH16(p); \ - a = (ushort16)p - (ushort16)HIGH16(p); \ - } \ - else \ - a = 1 - a - b; \ - } -#define STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); } -#define LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); } - -static ushort16 s_mul_inv(ushort16 x) -{ - ushort16 y = x; - unsigned i; - - for (i = 0; i < 15; i++) { - MUL(y, LOW16(y)); - MUL(y, x); - } - return LOW16(y); -} - -static ushort16 s_add_inv(ushort16 x) -{ - return LOW16(0 - x); -} - -#define s_setup_key s_idea_setup_key -static int s_setup_key(const unsigned char *key, symmetric_key *skey) -{ - int i, j; - ushort16 *e_key = skey->idea.ek; - ushort16 *d_key = skey->idea.dk; - - /* prepare enc key */ - for (i = 0; i < 8; i++) { - LOAD16(e_key[i], key + 2 * i); - } - for (; i < LTC_IDEA_KEYLEN; i++) { - j = (i - i % 8) - 8; - e_key[i] = LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7)); - } - - /* prepare dec key */ - for (i = 0; i < LTC_IDEA_ROUNDS; i++) { - d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); - d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]); - d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]); - d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); - d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4]; - d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5]; - } - d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); - d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]); - d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]); - d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); - - return CRYPT_OK; -} - -static int s_process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key) -{ - int i; - ushort16 x0, x1, x2, x3, t0, t1; - - LOAD16(x0, in + 0); - LOAD16(x1, in + 2); - LOAD16(x2, in + 4); - LOAD16(x3, in + 6); - - for (i = 0; i < LTC_IDEA_ROUNDS; i++) { - MUL(x0, m_key[i*6+0]); - x1 += m_key[i*6+1]; - x2 += m_key[i*6+2]; - MUL(x3, m_key[i*6+3]); - t0 = x0^x2; - MUL(t0, m_key[i*6+4]); - t1 = t0 + (x1^x3); - MUL(t1, m_key[i*6+5]); - t0 += t1; - x0 ^= t1; - x3 ^= t0; - t0 ^= x1; - x1 = x2^t1; - x2 = t0; - } - - MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]); - x2 += m_key[LTC_IDEA_ROUNDS*6+1]; - x1 += m_key[LTC_IDEA_ROUNDS*6+2]; - MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]); - - STORE16(x0, out + 0); - STORE16(x2, out + 2); - STORE16(x1, out + 4); - STORE16(x3, out + 6); - - return CRYPT_OK; -} - -int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS; - if (keylen != 16) return CRYPT_INVALID_KEYSIZE; - - return s_setup_key(key, skey); -} - -int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_process_block(pt, ct, skey->idea.ek); -#ifdef LTC_CLEAN_STACK - burn_stack(sizeof(ushort16) * 6 + sizeof(int)); -#endif - return err; -} - -int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_process_block(ct, pt, skey->idea.dk); -#ifdef LTC_CLEAN_STACK - burn_stack(sizeof(ushort16) * 6 + sizeof(int)); -#endif - return err; -} - -void idea_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -int idea_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - -int idea_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char key[16], pt[8], ct[8]; - } tests[] = { - { - /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F } - }, - { - /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 } - }, - { - /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 } - }, - { - /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA } - }, - { - /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C } - }, - }; - - unsigned char buf[2][8]; - symmetric_key key; - int err, x; - - if (sizeof(ushort16) != 2) { - return CRYPT_FAIL_TESTVECTOR; - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) { - return err; - } - if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - return CRYPT_OK; -#endif -} - -#undef LOW16 -#undef HIGH16 -#undef MUL -#undef STORE16 -#undef LOAD16 -#undef s_setup_key - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/kasumi.c b/Sources/DataLiteC/libtomcrypt/ciphers/kasumi.c deleted file mode 100644 index 7f25b34..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/kasumi.c +++ /dev/null @@ -1,311 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file kasumi.c - Implementation of the 3GPP Kasumi block cipher - Derived from the 3GPP standard source code -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_KASUMI - -typedef unsigned u16; - -#define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF) - -const struct ltc_cipher_descriptor kasumi_desc = { - "kasumi", - 21, - 16, 16, 8, 8, - &kasumi_setup, - &kasumi_ecb_encrypt, - &kasumi_ecb_decrypt, - &kasumi_test, - &kasumi_done, - &kasumi_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define FI kasumi_FI -static u16 FI( u16 in, u16 subkey ) -{ - u16 nine, seven; - static const u16 S7[128] = { - 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33, - 55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81, - 53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43, - 20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98, - 117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87, - 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66, - 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44, - 64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 }; - static const u16 S9[512] = { - 167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397, - 183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177, - 175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400, - 95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76, - 165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223, - 501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163, - 232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135, - 344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27, - 487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124, - 475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364, - 363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229, - 439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277, - 465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282, - 173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330, - 280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454, - 132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374, - 35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285, - 50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32, - 72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355, - 185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190, - 1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111, - 336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18, - 47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84, - 414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201, - 266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133, - 311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404, - 485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127, - 312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398, - 284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451, - 97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402, - 438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380, - 43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461}; - - /* The sixteen bit input is split into two unequal halves, * - * nine bits and seven bits - as is the subkey */ - - nine = (u16)(in>>7)&0x1FF; - seven = (u16)(in&0x7F); - - /* Now run the various operations */ - nine = (u16)(S9[nine] ^ seven); - seven = (u16)(S7[seven] ^ (nine & 0x7F)); - seven ^= (subkey>>9); - nine ^= (subkey&0x1FF); - nine = (u16)(S9[nine] ^ seven); - seven = (u16)(S7[seven] ^ (nine & 0x7F)); - return (u16)(seven<<9) + nine; -} - -static ulong32 FO( ulong32 in, int round_no, const symmetric_key *key) -{ - u16 left, right; - - /* Split the input into two 16-bit words */ - left = (u16)(in>>16); - right = (u16) in&0xFFFF; - - /* Now apply the same basic transformation three times */ - left ^= key->kasumi.KOi1[round_no]; - left = FI( left, key->kasumi.KIi1[round_no] ); - left ^= right; - - right ^= key->kasumi.KOi2[round_no]; - right = FI( right, key->kasumi.KIi2[round_no] ); - right ^= left; - - left ^= key->kasumi.KOi3[round_no]; - left = FI( left, key->kasumi.KIi3[round_no] ); - left ^= right; - - return (((ulong32)right)<<16)+left; -} - -static ulong32 FL( ulong32 in, int round_no, const symmetric_key *key ) -{ - u16 l, r, a, b; - /* split out the left and right halves */ - l = (u16)(in>>16); - r = (u16)(in)&0xFFFF; - /* do the FL() operations */ - a = (u16) (l & key->kasumi.KLi1[round_no]); - r ^= ROL16(a,1); - b = (u16)(r | key->kasumi.KLi2[round_no]); - l ^= ROL16(b,1); - /* put the two halves back together */ - - return (((ulong32)l)<<16) + r; -} - -int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 left, right, temp; - int n; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(left, pt); - LOAD32H(right, pt+4); - - for (n = 0; n <= 7; ) { - temp = FL(left, n, skey); - temp = FO(temp, n++, skey); - right ^= temp; - temp = FO(right, n, skey); - temp = FL(temp, n++, skey); - left ^= temp; - } - - STORE32H(left, ct); - STORE32H(right, ct+4); - - return CRYPT_OK; -} - -int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 left, right, temp; - int n; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(left, ct); - LOAD32H(right, ct+4); - - for (n = 7; n >= 0; ) { - temp = FO(right, n, skey); - temp = FL(temp, n--, skey); - left ^= temp; - temp = FL(left, n, skey); - temp = FO(temp, n--, skey); - right ^= temp; - } - - STORE32H(left, pt); - STORE32H(right, pt+4); - - return CRYPT_OK; -} - -int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 }; - u16 ukey[8], Kprime[8]; - int n; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 0 && num_rounds != 8) { - return CRYPT_INVALID_ROUNDS; - } - - /* Start by ensuring the subkeys are endian correct on a 16-bit basis */ - for (n = 0; n < 8; n++ ) { - ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1]; - } - - /* Now build the K'[] keys */ - for (n = 0; n < 8; n++) { - Kprime[n] = ukey[n] ^ C[n]; - } - - /* Finally construct the various sub keys */ - for(n = 0; n < 8; n++) { - skey->kasumi.KLi1[n] = ROL16(ukey[n],1); - skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7]; - skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5); - skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8); - skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13); - skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7]; - skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7]; - skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7]; - } - - return CRYPT_OK; -} - -void kasumi_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -int kasumi_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize >= 16) { - *keysize = 16; - return CRYPT_OK; - } - return CRYPT_INVALID_KEYSIZE; -} - -int kasumi_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char key[16], pt[8], ct[8]; - } tests[] = { - -{ - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 } -}, - -{ - { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 } -}, - -{ - { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 }, -}, - -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D } -}, - -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 } -}, - -}; - unsigned char buf[2][8]; - symmetric_key key; - int err, x; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) { - return err; - } - if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { - return err; - } - if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf[1], 8, tests[x].pt, 8, "Kasumi Decrypt", x) || - compare_testvector(buf[0], 8, tests[x].ct, 8, "Kasumi Encrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#undef ROL16 -#undef FI - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/khazad.c b/Sources/DataLiteC/libtomcrypt/ciphers/khazad.c deleted file mode 100644 index 0f1327d..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/khazad.c +++ /dev/null @@ -1,842 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file khazad.c - Khazad implementation derived from public domain source - Authors: Paulo S.L.M. Barreto and Vincent Rijmen. -*/ - -#ifdef LTC_KHAZAD - -const struct ltc_cipher_descriptor khazad_desc = { - "khazad", - 18, - 16, 16, 8, 8, - &khazad_setup, - &khazad_ecb_encrypt, - &khazad_ecb_decrypt, - &khazad_test, - &khazad_done, - &khazad_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define R 8 - -static const ulong64 T0[256] = { - CONST64(0xbad3d268bbb96a01), CONST64(0x54fc4d19e59a66b1), CONST64(0x2f71bc93e26514cd), CONST64(0x749ccdb925871b51), - CONST64(0x53f55102f7a257a4), CONST64(0xd3686bb8d0d6be03), CONST64(0xd26b6fbdd6deb504), CONST64(0x4dd72964b35285fe), - CONST64(0x50f05d0dfdba4aad), CONST64(0xace98a26cf09e063), CONST64(0x8d8a0e83091c9684), CONST64(0xbfdcc679a5914d1a), - CONST64(0x7090ddad3da7374d), CONST64(0x52f65507f1aa5ca3), CONST64(0x9ab352c87ba417e1), CONST64(0x4cd42d61b55a8ef9), - CONST64(0xea238f65460320ac), CONST64(0xd56273a6c4e68411), CONST64(0x97a466f155cc68c2), CONST64(0xd16e63b2dcc6a80d), - CONST64(0x3355ccffaa85d099), CONST64(0x51f35908fbb241aa), CONST64(0x5bed712ac7e20f9c), CONST64(0xa6f7a204f359ae55), - CONST64(0xde7f5f81febec120), CONST64(0x48d83d75ad7aa2e5), CONST64(0xa8e59a32d729cc7f), CONST64(0x99b65ec771bc0ae8), - CONST64(0xdb704b90e096e63b), CONST64(0x3256c8faac8ddb9e), CONST64(0xb7c4e65195d11522), CONST64(0xfc19d72b32b3aace), - CONST64(0xe338ab48704b7393), CONST64(0x9ebf42dc63843bfd), CONST64(0x91ae7eef41fc52d0), CONST64(0x9bb056cd7dac1ce6), - CONST64(0xe23baf4d76437894), CONST64(0xbbd0d66dbdb16106), CONST64(0x41c319589b32f1da), CONST64(0x6eb2a5cb7957e517), - CONST64(0xa5f2ae0bf941b35c), CONST64(0xcb400bc08016564b), CONST64(0x6bbdb1da677fc20c), CONST64(0x95a26efb59dc7ecc), - CONST64(0xa1febe1fe1619f40), CONST64(0xf308eb1810cbc3e3), CONST64(0xb1cefe4f81e12f30), CONST64(0x0206080a0c10160e), - CONST64(0xcc4917db922e675e), CONST64(0xc45137f3a26e3f66), CONST64(0x1d2774694ee8cf53), CONST64(0x143c504478a09c6c), - CONST64(0xc3582be8b0560e73), CONST64(0x63a591f2573f9a34), CONST64(0xda734f95e69eed3c), CONST64(0x5de76934d3d2358e), - CONST64(0x5fe1613edfc22380), CONST64(0xdc79578bf2aed72e), CONST64(0x7d87e99413cf486e), CONST64(0xcd4a13de94266c59), - CONST64(0x7f81e19e1fdf5e60), CONST64(0x5aee752fc1ea049b), CONST64(0x6cb4adc17547f319), CONST64(0x5ce46d31d5da3e89), - CONST64(0xf704fb0c08ebefff), CONST64(0x266a98bed42d47f2), CONST64(0xff1cdb2438abb7c7), CONST64(0xed2a937e543b11b9), - CONST64(0xe825876f4a1336a2), CONST64(0x9dba4ed3699c26f4), CONST64(0x6fb1a1ce7f5fee10), CONST64(0x8e8f028c03048b8d), - CONST64(0x192b647d56c8e34f), CONST64(0xa0fdba1ae7699447), CONST64(0xf00de7171ad3deea), CONST64(0x89861e97113cba98), - CONST64(0x0f113c332278692d), CONST64(0x07091c1b12383115), CONST64(0xafec8629c511fd6a), CONST64(0xfb10cb30208b9bdb), - CONST64(0x0818202830405838), CONST64(0x153f54417ea8976b), CONST64(0x0d1734392e687f23), CONST64(0x040c101418202c1c), - CONST64(0x0103040506080b07), CONST64(0x64ac8de94507ab21), CONST64(0xdf7c5b84f8b6ca27), CONST64(0x769ac5b329970d5f), - CONST64(0x798bf9800bef6472), CONST64(0xdd7a538ef4a6dc29), CONST64(0x3d47f4c98ef5b2b3), CONST64(0x163a584e74b08a62), - CONST64(0x3f41fcc382e5a4bd), CONST64(0x3759dcebb2a5fc85), CONST64(0x6db7a9c4734ff81e), CONST64(0x3848e0d890dd95a8), - CONST64(0xb9d6de67b1a17708), CONST64(0x7395d1a237bf2a44), CONST64(0xe926836a4c1b3da5), CONST64(0x355fd4e1beb5ea8b), - CONST64(0x55ff491ce3926db6), CONST64(0x7193d9a83baf3c4a), CONST64(0x7b8df18a07ff727c), CONST64(0x8c890a860f149d83), - CONST64(0x7296d5a731b72143), CONST64(0x88851a921734b19f), CONST64(0xf607ff090ee3e4f8), CONST64(0x2a7ea882fc4d33d6), - CONST64(0x3e42f8c684edafba), CONST64(0x5ee2653bd9ca2887), CONST64(0x27699cbbd2254cf5), CONST64(0x46ca0543890ac0cf), - CONST64(0x0c14303c28607424), CONST64(0x65af89ec430fa026), CONST64(0x68b8bdd56d67df05), CONST64(0x61a399f85b2f8c3a), - CONST64(0x03050c0f0a181d09), CONST64(0xc15e23e2bc46187d), CONST64(0x57f94116ef827bb8), CONST64(0xd6677fa9cefe9918), - CONST64(0xd976439aec86f035), CONST64(0x58e87d25cdfa1295), CONST64(0xd875479fea8efb32), CONST64(0x66aa85e34917bd2f), - CONST64(0xd7647bacc8f6921f), CONST64(0x3a4ee8d29ccd83a6), CONST64(0xc84507cf8a0e4b42), CONST64(0x3c44f0cc88fdb9b4), - CONST64(0xfa13cf35268390dc), CONST64(0x96a762f453c463c5), CONST64(0xa7f4a601f551a552), CONST64(0x98b55ac277b401ef), - CONST64(0xec29977b52331abe), CONST64(0xb8d5da62b7a97c0f), CONST64(0xc7543bfca876226f), CONST64(0xaeef822cc319f66d), - CONST64(0x69bbb9d06b6fd402), CONST64(0x4bdd317aa762bfec), CONST64(0xabe0963ddd31d176), CONST64(0xa9e69e37d121c778), - CONST64(0x67a981e64f1fb628), CONST64(0x0a1e28223c504e36), CONST64(0x47c901468f02cbc8), CONST64(0xf20bef1d16c3c8e4), - CONST64(0xb5c2ee5b99c1032c), CONST64(0x226688aacc0d6bee), CONST64(0xe532b356647b4981), CONST64(0xee2f9f715e230cb0), - CONST64(0xbedfc27ca399461d), CONST64(0x2b7dac87fa4538d1), CONST64(0x819e3ebf217ce2a0), CONST64(0x1236485a6c90a67e), - CONST64(0x839836b52d6cf4ae), CONST64(0x1b2d6c775ad8f541), CONST64(0x0e1238362470622a), CONST64(0x23658cafca0560e9), - CONST64(0xf502f30604fbf9f1), CONST64(0x45cf094c8312ddc6), CONST64(0x216384a5c61576e7), CONST64(0xce4f1fd19e3e7150), - CONST64(0x49db3970ab72a9e2), CONST64(0x2c74b09ce87d09c4), CONST64(0xf916c33a2c9b8dd5), CONST64(0xe637bf596e635488), - CONST64(0xb6c7e25493d91e25), CONST64(0x2878a088f05d25d8), CONST64(0x17395c4b72b88165), CONST64(0x829b32b02b64ffa9), - CONST64(0x1a2e68725cd0fe46), CONST64(0x8b80169d1d2cac96), CONST64(0xfe1fdf213ea3bcc0), CONST64(0x8a8312981b24a791), - CONST64(0x091b242d3648533f), CONST64(0xc94603ca8c064045), CONST64(0x879426a1354cd8b2), CONST64(0x4ed2256bb94a98f7), - CONST64(0xe13ea3427c5b659d), CONST64(0x2e72b896e46d1fca), CONST64(0xe431b75362734286), CONST64(0xe03da7477a536e9a), - CONST64(0xeb208b60400b2bab), CONST64(0x90ad7aea47f459d7), CONST64(0xa4f1aa0eff49b85b), CONST64(0x1e22786644f0d25a), - CONST64(0x85922eab395ccebc), CONST64(0x60a09dfd5d27873d), CONST64(0x0000000000000000), CONST64(0x256f94b1de355afb), - CONST64(0xf401f70302f3f2f6), CONST64(0xf10ee3121cdbd5ed), CONST64(0x94a16afe5fd475cb), CONST64(0x0b1d2c273a584531), - CONST64(0xe734bb5c686b5f8f), CONST64(0x759fc9bc238f1056), CONST64(0xef2c9b74582b07b7), CONST64(0x345cd0e4b8bde18c), - CONST64(0x3153c4f5a695c697), CONST64(0xd46177a3c2ee8f16), CONST64(0xd06d67b7dacea30a), CONST64(0x869722a43344d3b5), - CONST64(0x7e82e59b19d75567), CONST64(0xadea8e23c901eb64), CONST64(0xfd1ad32e34bba1c9), CONST64(0x297ba48df6552edf), - CONST64(0x3050c0f0a09dcd90), CONST64(0x3b4decd79ac588a1), CONST64(0x9fbc46d9658c30fa), CONST64(0xf815c73f2a9386d2), - CONST64(0xc6573ff9ae7e2968), CONST64(0x13354c5f6a98ad79), CONST64(0x060a181e14303a12), CONST64(0x050f14111e28271b), - CONST64(0xc55233f6a4663461), CONST64(0x113344556688bb77), CONST64(0x7799c1b62f9f0658), CONST64(0x7c84ed9115c74369), - CONST64(0x7a8ef58f01f7797b), CONST64(0x7888fd850de76f75), CONST64(0x365ad8eeb4adf782), CONST64(0x1c24706c48e0c454), - CONST64(0x394be4dd96d59eaf), CONST64(0x59eb7920cbf21992), CONST64(0x1828607850c0e848), CONST64(0x56fa4513e98a70bf), - CONST64(0xb3c8f6458df1393e), CONST64(0xb0cdfa4a87e92437), CONST64(0x246c90b4d83d51fc), CONST64(0x206080a0c01d7de0), - CONST64(0xb2cbf2408bf93239), CONST64(0x92ab72e04be44fd9), CONST64(0xa3f8b615ed71894e), CONST64(0xc05d27e7ba4e137a), - CONST64(0x44cc0d49851ad6c1), CONST64(0x62a695f751379133), CONST64(0x103040506080b070), CONST64(0xb4c1ea5e9fc9082b), - CONST64(0x84912aae3f54c5bb), CONST64(0x43c511529722e7d4), CONST64(0x93a876e54dec44de), CONST64(0xc25b2fedb65e0574), - CONST64(0x4ade357fa16ab4eb), CONST64(0xbddace73a9815b14), CONST64(0x8f8c0689050c808a), CONST64(0x2d77b499ee7502c3), - CONST64(0xbcd9ca76af895013), CONST64(0x9cb94ad66f942df3), CONST64(0x6abeb5df6177c90b), CONST64(0x40c01d5d9d3afadd), - CONST64(0xcf4c1bd498367a57), CONST64(0xa2fbb210eb798249), CONST64(0x809d3aba2774e9a7), CONST64(0x4fd1216ebf4293f0), - CONST64(0x1f217c6342f8d95d), CONST64(0xca430fc5861e5d4c), CONST64(0xaae39238db39da71), CONST64(0x42c61557912aecd3), -}; - -static const ulong64 T1[256] = { - CONST64(0xd3ba68d2b9bb016a), CONST64(0xfc54194d9ae5b166), CONST64(0x712f93bc65e2cd14), CONST64(0x9c74b9cd8725511b), - CONST64(0xf5530251a2f7a457), CONST64(0x68d3b86bd6d003be), CONST64(0x6bd2bd6fded604b5), CONST64(0xd74d642952b3fe85), - CONST64(0xf0500d5dbafdad4a), CONST64(0xe9ac268a09cf63e0), CONST64(0x8a8d830e1c098496), CONST64(0xdcbf79c691a51a4d), - CONST64(0x9070addda73d4d37), CONST64(0xf6520755aaf1a35c), CONST64(0xb39ac852a47be117), CONST64(0xd44c612d5ab5f98e), - CONST64(0x23ea658f0346ac20), CONST64(0x62d5a673e6c41184), CONST64(0xa497f166cc55c268), CONST64(0x6ed1b263c6dc0da8), - CONST64(0x5533ffcc85aa99d0), CONST64(0xf3510859b2fbaa41), CONST64(0xed5b2a71e2c79c0f), CONST64(0xf7a604a259f355ae), - CONST64(0x7fde815fbefe20c1), CONST64(0xd848753d7aade5a2), CONST64(0xe5a8329a29d77fcc), CONST64(0xb699c75ebc71e80a), - CONST64(0x70db904b96e03be6), CONST64(0x5632fac88dac9edb), CONST64(0xc4b751e6d1952215), CONST64(0x19fc2bd7b332ceaa), - CONST64(0x38e348ab4b709373), CONST64(0xbf9edc428463fd3b), CONST64(0xae91ef7efc41d052), CONST64(0xb09bcd56ac7de61c), - CONST64(0x3be24daf43769478), CONST64(0xd0bb6dd6b1bd0661), CONST64(0xc3415819329bdaf1), CONST64(0xb26ecba5577917e5), - CONST64(0xf2a50bae41f95cb3), CONST64(0x40cbc00b16804b56), CONST64(0xbd6bdab17f670cc2), CONST64(0xa295fb6edc59cc7e), - CONST64(0xfea11fbe61e1409f), CONST64(0x08f318ebcb10e3c3), CONST64(0xceb14ffee181302f), CONST64(0x06020a08100c0e16), - CONST64(0x49ccdb172e925e67), CONST64(0x51c4f3376ea2663f), CONST64(0x271d6974e84e53cf), CONST64(0x3c144450a0786c9c), - CONST64(0x58c3e82b56b0730e), CONST64(0xa563f2913f57349a), CONST64(0x73da954f9ee63ced), CONST64(0xe75d3469d2d38e35), - CONST64(0xe15f3e61c2df8023), CONST64(0x79dc8b57aef22ed7), CONST64(0x877d94e9cf136e48), CONST64(0x4acdde132694596c), - CONST64(0x817f9ee1df1f605e), CONST64(0xee5a2f75eac19b04), CONST64(0xb46cc1ad477519f3), CONST64(0xe45c316ddad5893e), - CONST64(0x04f70cfbeb08ffef), CONST64(0x6a26be982dd4f247), CONST64(0x1cff24dbab38c7b7), CONST64(0x2aed7e933b54b911), - CONST64(0x25e86f87134aa236), CONST64(0xba9dd34e9c69f426), CONST64(0xb16fcea15f7f10ee), CONST64(0x8f8e8c0204038d8b), - CONST64(0x2b197d64c8564fe3), CONST64(0xfda01aba69e74794), CONST64(0x0df017e7d31aeade), CONST64(0x8689971e3c1198ba), - CONST64(0x110f333c78222d69), CONST64(0x09071b1c38121531), CONST64(0xecaf298611c56afd), CONST64(0x10fb30cb8b20db9b), - CONST64(0x1808282040303858), CONST64(0x3f154154a87e6b97), CONST64(0x170d3934682e237f), CONST64(0x0c04141020181c2c), - CONST64(0x030105040806070b), CONST64(0xac64e98d074521ab), CONST64(0x7cdf845bb6f827ca), CONST64(0x9a76b3c597295f0d), - CONST64(0x8b7980f9ef0b7264), CONST64(0x7add8e53a6f429dc), CONST64(0x473dc9f4f58eb3b2), CONST64(0x3a164e58b074628a), - CONST64(0x413fc3fce582bda4), CONST64(0x5937ebdca5b285fc), CONST64(0xb76dc4a94f731ef8), CONST64(0x4838d8e0dd90a895), - CONST64(0xd6b967dea1b10877), CONST64(0x9573a2d1bf37442a), CONST64(0x26e96a831b4ca53d), CONST64(0x5f35e1d4b5be8bea), - CONST64(0xff551c4992e3b66d), CONST64(0x9371a8d9af3b4a3c), CONST64(0x8d7b8af1ff077c72), CONST64(0x898c860a140f839d), - CONST64(0x9672a7d5b7314321), CONST64(0x8588921a34179fb1), CONST64(0x07f609ffe30ef8e4), CONST64(0x7e2a82a84dfcd633), - CONST64(0x423ec6f8ed84baaf), CONST64(0xe25e3b65cad98728), CONST64(0x6927bb9c25d2f54c), CONST64(0xca4643050a89cfc0), - CONST64(0x140c3c3060282474), CONST64(0xaf65ec890f4326a0), CONST64(0xb868d5bd676d05df), CONST64(0xa361f8992f5b3a8c), - CONST64(0x05030f0c180a091d), CONST64(0x5ec1e22346bc7d18), CONST64(0xf957164182efb87b), CONST64(0x67d6a97ffece1899), - CONST64(0x76d99a4386ec35f0), CONST64(0xe858257dfacd9512), CONST64(0x75d89f478eea32fb), CONST64(0xaa66e38517492fbd), - CONST64(0x64d7ac7bf6c81f92), CONST64(0x4e3ad2e8cd9ca683), CONST64(0x45c8cf070e8a424b), CONST64(0x443cccf0fd88b4b9), - CONST64(0x13fa35cf8326dc90), CONST64(0xa796f462c453c563), CONST64(0xf4a701a651f552a5), CONST64(0xb598c25ab477ef01), - CONST64(0x29ec7b973352be1a), CONST64(0xd5b862daa9b70f7c), CONST64(0x54c7fc3b76a86f22), CONST64(0xefae2c8219c36df6), - CONST64(0xbb69d0b96f6b02d4), CONST64(0xdd4b7a3162a7ecbf), CONST64(0xe0ab3d9631dd76d1), CONST64(0xe6a9379e21d178c7), - CONST64(0xa967e6811f4f28b6), CONST64(0x1e0a2228503c364e), CONST64(0xc9474601028fc8cb), CONST64(0x0bf21defc316e4c8), - CONST64(0xc2b55beec1992c03), CONST64(0x6622aa880dccee6b), CONST64(0x32e556b37b648149), CONST64(0x2fee719f235eb00c), - CONST64(0xdfbe7cc299a31d46), CONST64(0x7d2b87ac45fad138), CONST64(0x9e81bf3e7c21a0e2), CONST64(0x36125a48906c7ea6), - CONST64(0x9883b5366c2daef4), CONST64(0x2d1b776cd85a41f5), CONST64(0x120e363870242a62), CONST64(0x6523af8c05cae960), - CONST64(0x02f506f3fb04f1f9), CONST64(0xcf454c091283c6dd), CONST64(0x6321a58415c6e776), CONST64(0x4fced11f3e9e5071), - CONST64(0xdb49703972abe2a9), CONST64(0x742c9cb07de8c409), CONST64(0x16f93ac39b2cd58d), CONST64(0x37e659bf636e8854), - CONST64(0xc7b654e2d993251e), CONST64(0x782888a05df0d825), CONST64(0x39174b5cb8726581), CONST64(0x9b82b032642ba9ff), - CONST64(0x2e1a7268d05c46fe), CONST64(0x808b9d162c1d96ac), CONST64(0x1ffe21dfa33ec0bc), CONST64(0x838a9812241b91a7), - CONST64(0x1b092d2448363f53), CONST64(0x46c9ca03068c4540), CONST64(0x9487a1264c35b2d8), CONST64(0xd24e6b254ab9f798), - CONST64(0x3ee142a35b7c9d65), CONST64(0x722e96b86de4ca1f), CONST64(0x31e453b773628642), CONST64(0x3de047a7537a9a6e), - CONST64(0x20eb608b0b40ab2b), CONST64(0xad90ea7af447d759), CONST64(0xf1a40eaa49ff5bb8), CONST64(0x221e6678f0445ad2), - CONST64(0x9285ab2e5c39bcce), CONST64(0xa060fd9d275d3d87), CONST64(0x0000000000000000), CONST64(0x6f25b19435defb5a), - CONST64(0x01f403f7f302f6f2), CONST64(0x0ef112e3db1cedd5), CONST64(0xa194fe6ad45fcb75), CONST64(0x1d0b272c583a3145), - CONST64(0x34e75cbb6b688f5f), CONST64(0x9f75bcc98f235610), CONST64(0x2cef749b2b58b707), CONST64(0x5c34e4d0bdb88ce1), - CONST64(0x5331f5c495a697c6), CONST64(0x61d4a377eec2168f), CONST64(0x6dd0b767ceda0aa3), CONST64(0x9786a4224433b5d3), - CONST64(0x827e9be5d7196755), CONST64(0xeaad238e01c964eb), CONST64(0x1afd2ed3bb34c9a1), CONST64(0x7b298da455f6df2e), - CONST64(0x5030f0c09da090cd), CONST64(0x4d3bd7ecc59aa188), CONST64(0xbc9fd9468c65fa30), CONST64(0x15f83fc7932ad286), - CONST64(0x57c6f93f7eae6829), CONST64(0x35135f4c986a79ad), CONST64(0x0a061e183014123a), CONST64(0x0f051114281e1b27), - CONST64(0x52c5f63366a46134), CONST64(0x33115544886677bb), CONST64(0x9977b6c19f2f5806), CONST64(0x847c91edc7156943), - CONST64(0x8e7a8ff5f7017b79), CONST64(0x887885fde70d756f), CONST64(0x5a36eed8adb482f7), CONST64(0x241c6c70e04854c4), - CONST64(0x4b39dde4d596af9e), CONST64(0xeb592079f2cb9219), CONST64(0x28187860c05048e8), CONST64(0xfa5613458ae9bf70), - CONST64(0xc8b345f6f18d3e39), CONST64(0xcdb04afae9873724), CONST64(0x6c24b4903dd8fc51), CONST64(0x6020a0801dc0e07d), - CONST64(0xcbb240f2f98b3932), CONST64(0xab92e072e44bd94f), CONST64(0xf8a315b671ed4e89), CONST64(0x5dc0e7274eba7a13), - CONST64(0xcc44490d1a85c1d6), CONST64(0xa662f79537513391), CONST64(0x30105040806070b0), CONST64(0xc1b45eeac99f2b08), - CONST64(0x9184ae2a543fbbc5), CONST64(0xc54352112297d4e7), CONST64(0xa893e576ec4dde44), CONST64(0x5bc2ed2f5eb67405), - CONST64(0xde4a7f356aa1ebb4), CONST64(0xdabd73ce81a9145b), CONST64(0x8c8f89060c058a80), CONST64(0x772d99b475eec302), - CONST64(0xd9bc76ca89af1350), CONST64(0xb99cd64a946ff32d), CONST64(0xbe6adfb577610bc9), CONST64(0xc0405d1d3a9dddfa), - CONST64(0x4ccfd41b3698577a), CONST64(0xfba210b279eb4982), CONST64(0x9d80ba3a7427a7e9), CONST64(0xd14f6e2142bff093), - CONST64(0x211f637cf8425dd9), CONST64(0x43cac50f1e864c5d), CONST64(0xe3aa389239db71da), CONST64(0xc64257152a91d3ec), -}; - -static const ulong64 T2[256] = { - CONST64(0xd268bad36a01bbb9), CONST64(0x4d1954fc66b1e59a), CONST64(0xbc932f7114cde265), CONST64(0xcdb9749c1b512587), - CONST64(0x510253f557a4f7a2), CONST64(0x6bb8d368be03d0d6), CONST64(0x6fbdd26bb504d6de), CONST64(0x29644dd785feb352), - CONST64(0x5d0d50f04aadfdba), CONST64(0x8a26ace9e063cf09), CONST64(0x0e838d8a9684091c), CONST64(0xc679bfdc4d1aa591), - CONST64(0xddad7090374d3da7), CONST64(0x550752f65ca3f1aa), CONST64(0x52c89ab317e17ba4), CONST64(0x2d614cd48ef9b55a), - CONST64(0x8f65ea2320ac4603), CONST64(0x73a6d5628411c4e6), CONST64(0x66f197a468c255cc), CONST64(0x63b2d16ea80ddcc6), - CONST64(0xccff3355d099aa85), CONST64(0x590851f341aafbb2), CONST64(0x712a5bed0f9cc7e2), CONST64(0xa204a6f7ae55f359), - CONST64(0x5f81de7fc120febe), CONST64(0x3d7548d8a2e5ad7a), CONST64(0x9a32a8e5cc7fd729), CONST64(0x5ec799b60ae871bc), - CONST64(0x4b90db70e63be096), CONST64(0xc8fa3256db9eac8d), CONST64(0xe651b7c4152295d1), CONST64(0xd72bfc19aace32b3), - CONST64(0xab48e3387393704b), CONST64(0x42dc9ebf3bfd6384), CONST64(0x7eef91ae52d041fc), CONST64(0x56cd9bb01ce67dac), - CONST64(0xaf4de23b78947643), CONST64(0xd66dbbd06106bdb1), CONST64(0x195841c3f1da9b32), CONST64(0xa5cb6eb2e5177957), - CONST64(0xae0ba5f2b35cf941), CONST64(0x0bc0cb40564b8016), CONST64(0xb1da6bbdc20c677f), CONST64(0x6efb95a27ecc59dc), - CONST64(0xbe1fa1fe9f40e161), CONST64(0xeb18f308c3e310cb), CONST64(0xfe4fb1ce2f3081e1), CONST64(0x080a0206160e0c10), - CONST64(0x17dbcc49675e922e), CONST64(0x37f3c4513f66a26e), CONST64(0x74691d27cf534ee8), CONST64(0x5044143c9c6c78a0), - CONST64(0x2be8c3580e73b056), CONST64(0x91f263a59a34573f), CONST64(0x4f95da73ed3ce69e), CONST64(0x69345de7358ed3d2), - CONST64(0x613e5fe12380dfc2), CONST64(0x578bdc79d72ef2ae), CONST64(0xe9947d87486e13cf), CONST64(0x13decd4a6c599426), - CONST64(0xe19e7f815e601fdf), CONST64(0x752f5aee049bc1ea), CONST64(0xadc16cb4f3197547), CONST64(0x6d315ce43e89d5da), - CONST64(0xfb0cf704efff08eb), CONST64(0x98be266a47f2d42d), CONST64(0xdb24ff1cb7c738ab), CONST64(0x937eed2a11b9543b), - CONST64(0x876fe82536a24a13), CONST64(0x4ed39dba26f4699c), CONST64(0xa1ce6fb1ee107f5f), CONST64(0x028c8e8f8b8d0304), - CONST64(0x647d192be34f56c8), CONST64(0xba1aa0fd9447e769), CONST64(0xe717f00ddeea1ad3), CONST64(0x1e978986ba98113c), - CONST64(0x3c330f11692d2278), CONST64(0x1c1b070931151238), CONST64(0x8629afecfd6ac511), CONST64(0xcb30fb109bdb208b), - CONST64(0x2028081858383040), CONST64(0x5441153f976b7ea8), CONST64(0x34390d177f232e68), CONST64(0x1014040c2c1c1820), - CONST64(0x040501030b070608), CONST64(0x8de964acab214507), CONST64(0x5b84df7cca27f8b6), CONST64(0xc5b3769a0d5f2997), - CONST64(0xf980798b64720bef), CONST64(0x538edd7adc29f4a6), CONST64(0xf4c93d47b2b38ef5), CONST64(0x584e163a8a6274b0), - CONST64(0xfcc33f41a4bd82e5), CONST64(0xdceb3759fc85b2a5), CONST64(0xa9c46db7f81e734f), CONST64(0xe0d8384895a890dd), - CONST64(0xde67b9d67708b1a1), CONST64(0xd1a273952a4437bf), CONST64(0x836ae9263da54c1b), CONST64(0xd4e1355fea8bbeb5), - CONST64(0x491c55ff6db6e392), CONST64(0xd9a871933c4a3baf), CONST64(0xf18a7b8d727c07ff), CONST64(0x0a868c899d830f14), - CONST64(0xd5a77296214331b7), CONST64(0x1a928885b19f1734), CONST64(0xff09f607e4f80ee3), CONST64(0xa8822a7e33d6fc4d), - CONST64(0xf8c63e42afba84ed), CONST64(0x653b5ee22887d9ca), CONST64(0x9cbb27694cf5d225), CONST64(0x054346cac0cf890a), - CONST64(0x303c0c1474242860), CONST64(0x89ec65afa026430f), CONST64(0xbdd568b8df056d67), CONST64(0x99f861a38c3a5b2f), - CONST64(0x0c0f03051d090a18), CONST64(0x23e2c15e187dbc46), CONST64(0x411657f97bb8ef82), CONST64(0x7fa9d6679918cefe), - CONST64(0x439ad976f035ec86), CONST64(0x7d2558e81295cdfa), CONST64(0x479fd875fb32ea8e), CONST64(0x85e366aabd2f4917), - CONST64(0x7bacd764921fc8f6), CONST64(0xe8d23a4e83a69ccd), CONST64(0x07cfc8454b428a0e), CONST64(0xf0cc3c44b9b488fd), - CONST64(0xcf35fa1390dc2683), CONST64(0x62f496a763c553c4), CONST64(0xa601a7f4a552f551), CONST64(0x5ac298b501ef77b4), - CONST64(0x977bec291abe5233), CONST64(0xda62b8d57c0fb7a9), CONST64(0x3bfcc754226fa876), CONST64(0x822caeeff66dc319), - CONST64(0xb9d069bbd4026b6f), CONST64(0x317a4bddbfeca762), CONST64(0x963dabe0d176dd31), CONST64(0x9e37a9e6c778d121), - CONST64(0x81e667a9b6284f1f), CONST64(0x28220a1e4e363c50), CONST64(0x014647c9cbc88f02), CONST64(0xef1df20bc8e416c3), - CONST64(0xee5bb5c2032c99c1), CONST64(0x88aa22666beecc0d), CONST64(0xb356e5324981647b), CONST64(0x9f71ee2f0cb05e23), - CONST64(0xc27cbedf461da399), CONST64(0xac872b7d38d1fa45), CONST64(0x3ebf819ee2a0217c), CONST64(0x485a1236a67e6c90), - CONST64(0x36b58398f4ae2d6c), CONST64(0x6c771b2df5415ad8), CONST64(0x38360e12622a2470), CONST64(0x8caf236560e9ca05), - CONST64(0xf306f502f9f104fb), CONST64(0x094c45cfddc68312), CONST64(0x84a5216376e7c615), CONST64(0x1fd1ce4f71509e3e), - CONST64(0x397049dba9e2ab72), CONST64(0xb09c2c7409c4e87d), CONST64(0xc33af9168dd52c9b), CONST64(0xbf59e63754886e63), - CONST64(0xe254b6c71e2593d9), CONST64(0xa088287825d8f05d), CONST64(0x5c4b1739816572b8), CONST64(0x32b0829bffa92b64), - CONST64(0x68721a2efe465cd0), CONST64(0x169d8b80ac961d2c), CONST64(0xdf21fe1fbcc03ea3), CONST64(0x12988a83a7911b24), - CONST64(0x242d091b533f3648), CONST64(0x03cac94640458c06), CONST64(0x26a18794d8b2354c), CONST64(0x256b4ed298f7b94a), - CONST64(0xa342e13e659d7c5b), CONST64(0xb8962e721fcae46d), CONST64(0xb753e43142866273), CONST64(0xa747e03d6e9a7a53), - CONST64(0x8b60eb202bab400b), CONST64(0x7aea90ad59d747f4), CONST64(0xaa0ea4f1b85bff49), CONST64(0x78661e22d25a44f0), - CONST64(0x2eab8592cebc395c), CONST64(0x9dfd60a0873d5d27), CONST64(0x0000000000000000), CONST64(0x94b1256f5afbde35), - CONST64(0xf703f401f2f602f3), CONST64(0xe312f10ed5ed1cdb), CONST64(0x6afe94a175cb5fd4), CONST64(0x2c270b1d45313a58), - CONST64(0xbb5ce7345f8f686b), CONST64(0xc9bc759f1056238f), CONST64(0x9b74ef2c07b7582b), CONST64(0xd0e4345ce18cb8bd), - CONST64(0xc4f53153c697a695), CONST64(0x77a3d4618f16c2ee), CONST64(0x67b7d06da30adace), CONST64(0x22a48697d3b53344), - CONST64(0xe59b7e82556719d7), CONST64(0x8e23adeaeb64c901), CONST64(0xd32efd1aa1c934bb), CONST64(0xa48d297b2edff655), - CONST64(0xc0f03050cd90a09d), CONST64(0xecd73b4d88a19ac5), CONST64(0x46d99fbc30fa658c), CONST64(0xc73ff81586d22a93), - CONST64(0x3ff9c6572968ae7e), CONST64(0x4c5f1335ad796a98), CONST64(0x181e060a3a121430), CONST64(0x1411050f271b1e28), - CONST64(0x33f6c5523461a466), CONST64(0x44551133bb776688), CONST64(0xc1b6779906582f9f), CONST64(0xed917c84436915c7), - CONST64(0xf58f7a8e797b01f7), CONST64(0xfd8578886f750de7), CONST64(0xd8ee365af782b4ad), CONST64(0x706c1c24c45448e0), - CONST64(0xe4dd394b9eaf96d5), CONST64(0x792059eb1992cbf2), CONST64(0x60781828e84850c0), CONST64(0x451356fa70bfe98a), - CONST64(0xf645b3c8393e8df1), CONST64(0xfa4ab0cd243787e9), CONST64(0x90b4246c51fcd83d), CONST64(0x80a020607de0c01d), - CONST64(0xf240b2cb32398bf9), CONST64(0x72e092ab4fd94be4), CONST64(0xb615a3f8894eed71), CONST64(0x27e7c05d137aba4e), - CONST64(0x0d4944ccd6c1851a), CONST64(0x95f762a691335137), CONST64(0x40501030b0706080), CONST64(0xea5eb4c1082b9fc9), - CONST64(0x2aae8491c5bb3f54), CONST64(0x115243c5e7d49722), CONST64(0x76e593a844de4dec), CONST64(0x2fedc25b0574b65e), - CONST64(0x357f4adeb4eba16a), CONST64(0xce73bdda5b14a981), CONST64(0x06898f8c808a050c), CONST64(0xb4992d7702c3ee75), - CONST64(0xca76bcd95013af89), CONST64(0x4ad69cb92df36f94), CONST64(0xb5df6abec90b6177), CONST64(0x1d5d40c0fadd9d3a), - CONST64(0x1bd4cf4c7a579836), CONST64(0xb210a2fb8249eb79), CONST64(0x3aba809de9a72774), CONST64(0x216e4fd193f0bf42), - CONST64(0x7c631f21d95d42f8), CONST64(0x0fc5ca435d4c861e), CONST64(0x9238aae3da71db39), CONST64(0x155742c6ecd3912a), -}; - -static const ulong64 T3[256] = { - CONST64(0x68d2d3ba016ab9bb), CONST64(0x194dfc54b1669ae5), CONST64(0x93bc712fcd1465e2), CONST64(0xb9cd9c74511b8725), - CONST64(0x0251f553a457a2f7), CONST64(0xb86b68d303bed6d0), CONST64(0xbd6f6bd204b5ded6), CONST64(0x6429d74dfe8552b3), - CONST64(0x0d5df050ad4abafd), CONST64(0x268ae9ac63e009cf), CONST64(0x830e8a8d84961c09), CONST64(0x79c6dcbf1a4d91a5), - CONST64(0xaddd90704d37a73d), CONST64(0x0755f652a35caaf1), CONST64(0xc852b39ae117a47b), CONST64(0x612dd44cf98e5ab5), - CONST64(0x658f23eaac200346), CONST64(0xa67362d51184e6c4), CONST64(0xf166a497c268cc55), CONST64(0xb2636ed10da8c6dc), - CONST64(0xffcc553399d085aa), CONST64(0x0859f351aa41b2fb), CONST64(0x2a71ed5b9c0fe2c7), CONST64(0x04a2f7a655ae59f3), - CONST64(0x815f7fde20c1befe), CONST64(0x753dd848e5a27aad), CONST64(0x329ae5a87fcc29d7), CONST64(0xc75eb699e80abc71), - CONST64(0x904b70db3be696e0), CONST64(0xfac856329edb8dac), CONST64(0x51e6c4b72215d195), CONST64(0x2bd719fcceaab332), - CONST64(0x48ab38e393734b70), CONST64(0xdc42bf9efd3b8463), CONST64(0xef7eae91d052fc41), CONST64(0xcd56b09be61cac7d), - CONST64(0x4daf3be294784376), CONST64(0x6dd6d0bb0661b1bd), CONST64(0x5819c341daf1329b), CONST64(0xcba5b26e17e55779), - CONST64(0x0baef2a55cb341f9), CONST64(0xc00b40cb4b561680), CONST64(0xdab1bd6b0cc27f67), CONST64(0xfb6ea295cc7edc59), - CONST64(0x1fbefea1409f61e1), CONST64(0x18eb08f3e3c3cb10), CONST64(0x4ffeceb1302fe181), CONST64(0x0a0806020e16100c), - CONST64(0xdb1749cc5e672e92), CONST64(0xf33751c4663f6ea2), CONST64(0x6974271d53cfe84e), CONST64(0x44503c146c9ca078), - CONST64(0xe82b58c3730e56b0), CONST64(0xf291a563349a3f57), CONST64(0x954f73da3ced9ee6), CONST64(0x3469e75d8e35d2d3), - CONST64(0x3e61e15f8023c2df), CONST64(0x8b5779dc2ed7aef2), CONST64(0x94e9877d6e48cf13), CONST64(0xde134acd596c2694), - CONST64(0x9ee1817f605edf1f), CONST64(0x2f75ee5a9b04eac1), CONST64(0xc1adb46c19f34775), CONST64(0x316de45c893edad5), - CONST64(0x0cfb04f7ffefeb08), CONST64(0xbe986a26f2472dd4), CONST64(0x24db1cffc7b7ab38), CONST64(0x7e932aedb9113b54), - CONST64(0x6f8725e8a236134a), CONST64(0xd34eba9df4269c69), CONST64(0xcea1b16f10ee5f7f), CONST64(0x8c028f8e8d8b0403), - CONST64(0x7d642b194fe3c856), CONST64(0x1abafda0479469e7), CONST64(0x17e70df0eaded31a), CONST64(0x971e868998ba3c11), - CONST64(0x333c110f2d697822), CONST64(0x1b1c090715313812), CONST64(0x2986ecaf6afd11c5), CONST64(0x30cb10fbdb9b8b20), - CONST64(0x2820180838584030), CONST64(0x41543f156b97a87e), CONST64(0x3934170d237f682e), CONST64(0x14100c041c2c2018), - CONST64(0x05040301070b0806), CONST64(0xe98dac6421ab0745), CONST64(0x845b7cdf27cab6f8), CONST64(0xb3c59a765f0d9729), - CONST64(0x80f98b797264ef0b), CONST64(0x8e537add29dca6f4), CONST64(0xc9f4473db3b2f58e), CONST64(0x4e583a16628ab074), - CONST64(0xc3fc413fbda4e582), CONST64(0xebdc593785fca5b2), CONST64(0xc4a9b76d1ef84f73), CONST64(0xd8e04838a895dd90), - CONST64(0x67ded6b90877a1b1), CONST64(0xa2d19573442abf37), CONST64(0x6a8326e9a53d1b4c), CONST64(0xe1d45f358beab5be), - CONST64(0x1c49ff55b66d92e3), CONST64(0xa8d993714a3caf3b), CONST64(0x8af18d7b7c72ff07), CONST64(0x860a898c839d140f), - CONST64(0xa7d596724321b731), CONST64(0x921a85889fb13417), CONST64(0x09ff07f6f8e4e30e), CONST64(0x82a87e2ad6334dfc), - CONST64(0xc6f8423ebaafed84), CONST64(0x3b65e25e8728cad9), CONST64(0xbb9c6927f54c25d2), CONST64(0x4305ca46cfc00a89), - CONST64(0x3c30140c24746028), CONST64(0xec89af6526a00f43), CONST64(0xd5bdb86805df676d), CONST64(0xf899a3613a8c2f5b), - CONST64(0x0f0c0503091d180a), CONST64(0xe2235ec17d1846bc), CONST64(0x1641f957b87b82ef), CONST64(0xa97f67d61899fece), - CONST64(0x9a4376d935f086ec), CONST64(0x257de8589512facd), CONST64(0x9f4775d832fb8eea), CONST64(0xe385aa662fbd1749), - CONST64(0xac7b64d71f92f6c8), CONST64(0xd2e84e3aa683cd9c), CONST64(0xcf0745c8424b0e8a), CONST64(0xccf0443cb4b9fd88), - CONST64(0x35cf13fadc908326), CONST64(0xf462a796c563c453), CONST64(0x01a6f4a752a551f5), CONST64(0xc25ab598ef01b477), - CONST64(0x7b9729ecbe1a3352), CONST64(0x62dad5b80f7ca9b7), CONST64(0xfc3b54c76f2276a8), CONST64(0x2c82efae6df619c3), - CONST64(0xd0b9bb6902d46f6b), CONST64(0x7a31dd4becbf62a7), CONST64(0x3d96e0ab76d131dd), CONST64(0x379ee6a978c721d1), - CONST64(0xe681a96728b61f4f), CONST64(0x22281e0a364e503c), CONST64(0x4601c947c8cb028f), CONST64(0x1def0bf2e4c8c316), - CONST64(0x5beec2b52c03c199), CONST64(0xaa886622ee6b0dcc), CONST64(0x56b332e581497b64), CONST64(0x719f2feeb00c235e), - CONST64(0x7cc2dfbe1d4699a3), CONST64(0x87ac7d2bd13845fa), CONST64(0xbf3e9e81a0e27c21), CONST64(0x5a4836127ea6906c), - CONST64(0xb5369883aef46c2d), CONST64(0x776c2d1b41f5d85a), CONST64(0x3638120e2a627024), CONST64(0xaf8c6523e96005ca), - CONST64(0x06f302f5f1f9fb04), CONST64(0x4c09cf45c6dd1283), CONST64(0xa5846321e77615c6), CONST64(0xd11f4fce50713e9e), - CONST64(0x7039db49e2a972ab), CONST64(0x9cb0742cc4097de8), CONST64(0x3ac316f9d58d9b2c), CONST64(0x59bf37e68854636e), - CONST64(0x54e2c7b6251ed993), CONST64(0x88a07828d8255df0), CONST64(0x4b5c39176581b872), CONST64(0xb0329b82a9ff642b), - CONST64(0x72682e1a46fed05c), CONST64(0x9d16808b96ac2c1d), CONST64(0x21df1ffec0bca33e), CONST64(0x9812838a91a7241b), - CONST64(0x2d241b093f534836), CONST64(0xca0346c94540068c), CONST64(0xa1269487b2d84c35), CONST64(0x6b25d24ef7984ab9), - CONST64(0x42a33ee19d655b7c), CONST64(0x96b8722eca1f6de4), CONST64(0x53b731e486427362), CONST64(0x47a73de09a6e537a), - CONST64(0x608b20ebab2b0b40), CONST64(0xea7aad90d759f447), CONST64(0x0eaaf1a45bb849ff), CONST64(0x6678221e5ad2f044), - CONST64(0xab2e9285bcce5c39), CONST64(0xfd9da0603d87275d), CONST64(0x0000000000000000), CONST64(0xb1946f25fb5a35de), - CONST64(0x03f701f4f6f2f302), CONST64(0x12e30ef1edd5db1c), CONST64(0xfe6aa194cb75d45f), CONST64(0x272c1d0b3145583a), - CONST64(0x5cbb34e78f5f6b68), CONST64(0xbcc99f7556108f23), CONST64(0x749b2cefb7072b58), CONST64(0xe4d05c348ce1bdb8), - CONST64(0xf5c4533197c695a6), CONST64(0xa37761d4168feec2), CONST64(0xb7676dd00aa3ceda), CONST64(0xa4229786b5d34433), - CONST64(0x9be5827e6755d719), CONST64(0x238eeaad64eb01c9), CONST64(0x2ed31afdc9a1bb34), CONST64(0x8da47b29df2e55f6), - CONST64(0xf0c0503090cd9da0), CONST64(0xd7ec4d3ba188c59a), CONST64(0xd946bc9ffa308c65), CONST64(0x3fc715f8d286932a), - CONST64(0xf93f57c668297eae), CONST64(0x5f4c351379ad986a), CONST64(0x1e180a06123a3014), CONST64(0x11140f051b27281e), - CONST64(0xf63352c5613466a4), CONST64(0x5544331177bb8866), CONST64(0xb6c1997758069f2f), CONST64(0x91ed847c6943c715), - CONST64(0x8ff58e7a7b79f701), CONST64(0x85fd8878756fe70d), CONST64(0xeed85a3682f7adb4), CONST64(0x6c70241c54c4e048), - CONST64(0xdde44b39af9ed596), CONST64(0x2079eb599219f2cb), CONST64(0x7860281848e8c050), CONST64(0x1345fa56bf708ae9), - CONST64(0x45f6c8b33e39f18d), CONST64(0x4afacdb03724e987), CONST64(0xb4906c24fc513dd8), CONST64(0xa0806020e07d1dc0), - CONST64(0x40f2cbb23932f98b), CONST64(0xe072ab92d94fe44b), CONST64(0x15b6f8a34e8971ed), CONST64(0xe7275dc07a134eba), - CONST64(0x490dcc44c1d61a85), CONST64(0xf795a66233913751), CONST64(0x5040301070b08060), CONST64(0x5eeac1b42b08c99f), - CONST64(0xae2a9184bbc5543f), CONST64(0x5211c543d4e72297), CONST64(0xe576a893de44ec4d), CONST64(0xed2f5bc274055eb6), - CONST64(0x7f35de4aebb46aa1), CONST64(0x73cedabd145b81a9), CONST64(0x89068c8f8a800c05), CONST64(0x99b4772dc30275ee), - CONST64(0x76cad9bc135089af), CONST64(0xd64ab99cf32d946f), CONST64(0xdfb5be6a0bc97761), CONST64(0x5d1dc040ddfa3a9d), - CONST64(0xd41b4ccf577a3698), CONST64(0x10b2fba2498279eb), CONST64(0xba3a9d80a7e97427), CONST64(0x6e21d14ff09342bf), - CONST64(0x637c211f5dd9f842), CONST64(0xc50f43ca4c5d1e86), CONST64(0x3892e3aa71da39db), CONST64(0x5715c642d3ec2a91), -}; - -static const ulong64 T4[256] = { - CONST64(0xbbb96a01bad3d268), CONST64(0xe59a66b154fc4d19), CONST64(0xe26514cd2f71bc93), CONST64(0x25871b51749ccdb9), - CONST64(0xf7a257a453f55102), CONST64(0xd0d6be03d3686bb8), CONST64(0xd6deb504d26b6fbd), CONST64(0xb35285fe4dd72964), - CONST64(0xfdba4aad50f05d0d), CONST64(0xcf09e063ace98a26), CONST64(0x091c96848d8a0e83), CONST64(0xa5914d1abfdcc679), - CONST64(0x3da7374d7090ddad), CONST64(0xf1aa5ca352f65507), CONST64(0x7ba417e19ab352c8), CONST64(0xb55a8ef94cd42d61), - CONST64(0x460320acea238f65), CONST64(0xc4e68411d56273a6), CONST64(0x55cc68c297a466f1), CONST64(0xdcc6a80dd16e63b2), - CONST64(0xaa85d0993355ccff), CONST64(0xfbb241aa51f35908), CONST64(0xc7e20f9c5bed712a), CONST64(0xf359ae55a6f7a204), - CONST64(0xfebec120de7f5f81), CONST64(0xad7aa2e548d83d75), CONST64(0xd729cc7fa8e59a32), CONST64(0x71bc0ae899b65ec7), - CONST64(0xe096e63bdb704b90), CONST64(0xac8ddb9e3256c8fa), CONST64(0x95d11522b7c4e651), CONST64(0x32b3aacefc19d72b), - CONST64(0x704b7393e338ab48), CONST64(0x63843bfd9ebf42dc), CONST64(0x41fc52d091ae7eef), CONST64(0x7dac1ce69bb056cd), - CONST64(0x76437894e23baf4d), CONST64(0xbdb16106bbd0d66d), CONST64(0x9b32f1da41c31958), CONST64(0x7957e5176eb2a5cb), - CONST64(0xf941b35ca5f2ae0b), CONST64(0x8016564bcb400bc0), CONST64(0x677fc20c6bbdb1da), CONST64(0x59dc7ecc95a26efb), - CONST64(0xe1619f40a1febe1f), CONST64(0x10cbc3e3f308eb18), CONST64(0x81e12f30b1cefe4f), CONST64(0x0c10160e0206080a), - CONST64(0x922e675ecc4917db), CONST64(0xa26e3f66c45137f3), CONST64(0x4ee8cf531d277469), CONST64(0x78a09c6c143c5044), - CONST64(0xb0560e73c3582be8), CONST64(0x573f9a3463a591f2), CONST64(0xe69eed3cda734f95), CONST64(0xd3d2358e5de76934), - CONST64(0xdfc223805fe1613e), CONST64(0xf2aed72edc79578b), CONST64(0x13cf486e7d87e994), CONST64(0x94266c59cd4a13de), - CONST64(0x1fdf5e607f81e19e), CONST64(0xc1ea049b5aee752f), CONST64(0x7547f3196cb4adc1), CONST64(0xd5da3e895ce46d31), - CONST64(0x08ebeffff704fb0c), CONST64(0xd42d47f2266a98be), CONST64(0x38abb7c7ff1cdb24), CONST64(0x543b11b9ed2a937e), - CONST64(0x4a1336a2e825876f), CONST64(0x699c26f49dba4ed3), CONST64(0x7f5fee106fb1a1ce), CONST64(0x03048b8d8e8f028c), - CONST64(0x56c8e34f192b647d), CONST64(0xe7699447a0fdba1a), CONST64(0x1ad3deeaf00de717), CONST64(0x113cba9889861e97), - CONST64(0x2278692d0f113c33), CONST64(0x1238311507091c1b), CONST64(0xc511fd6aafec8629), CONST64(0x208b9bdbfb10cb30), - CONST64(0x3040583808182028), CONST64(0x7ea8976b153f5441), CONST64(0x2e687f230d173439), CONST64(0x18202c1c040c1014), - CONST64(0x06080b0701030405), CONST64(0x4507ab2164ac8de9), CONST64(0xf8b6ca27df7c5b84), CONST64(0x29970d5f769ac5b3), - CONST64(0x0bef6472798bf980), CONST64(0xf4a6dc29dd7a538e), CONST64(0x8ef5b2b33d47f4c9), CONST64(0x74b08a62163a584e), - CONST64(0x82e5a4bd3f41fcc3), CONST64(0xb2a5fc853759dceb), CONST64(0x734ff81e6db7a9c4), CONST64(0x90dd95a83848e0d8), - CONST64(0xb1a17708b9d6de67), CONST64(0x37bf2a447395d1a2), CONST64(0x4c1b3da5e926836a), CONST64(0xbeb5ea8b355fd4e1), - CONST64(0xe3926db655ff491c), CONST64(0x3baf3c4a7193d9a8), CONST64(0x07ff727c7b8df18a), CONST64(0x0f149d838c890a86), - CONST64(0x31b721437296d5a7), CONST64(0x1734b19f88851a92), CONST64(0x0ee3e4f8f607ff09), CONST64(0xfc4d33d62a7ea882), - CONST64(0x84edafba3e42f8c6), CONST64(0xd9ca28875ee2653b), CONST64(0xd2254cf527699cbb), CONST64(0x890ac0cf46ca0543), - CONST64(0x286074240c14303c), CONST64(0x430fa02665af89ec), CONST64(0x6d67df0568b8bdd5), CONST64(0x5b2f8c3a61a399f8), - CONST64(0x0a181d0903050c0f), CONST64(0xbc46187dc15e23e2), CONST64(0xef827bb857f94116), CONST64(0xcefe9918d6677fa9), - CONST64(0xec86f035d976439a), CONST64(0xcdfa129558e87d25), CONST64(0xea8efb32d875479f), CONST64(0x4917bd2f66aa85e3), - CONST64(0xc8f6921fd7647bac), CONST64(0x9ccd83a63a4ee8d2), CONST64(0x8a0e4b42c84507cf), CONST64(0x88fdb9b43c44f0cc), - CONST64(0x268390dcfa13cf35), CONST64(0x53c463c596a762f4), CONST64(0xf551a552a7f4a601), CONST64(0x77b401ef98b55ac2), - CONST64(0x52331abeec29977b), CONST64(0xb7a97c0fb8d5da62), CONST64(0xa876226fc7543bfc), CONST64(0xc319f66daeef822c), - CONST64(0x6b6fd40269bbb9d0), CONST64(0xa762bfec4bdd317a), CONST64(0xdd31d176abe0963d), CONST64(0xd121c778a9e69e37), - CONST64(0x4f1fb62867a981e6), CONST64(0x3c504e360a1e2822), CONST64(0x8f02cbc847c90146), CONST64(0x16c3c8e4f20bef1d), - CONST64(0x99c1032cb5c2ee5b), CONST64(0xcc0d6bee226688aa), CONST64(0x647b4981e532b356), CONST64(0x5e230cb0ee2f9f71), - CONST64(0xa399461dbedfc27c), CONST64(0xfa4538d12b7dac87), CONST64(0x217ce2a0819e3ebf), CONST64(0x6c90a67e1236485a), - CONST64(0x2d6cf4ae839836b5), CONST64(0x5ad8f5411b2d6c77), CONST64(0x2470622a0e123836), CONST64(0xca0560e923658caf), - CONST64(0x04fbf9f1f502f306), CONST64(0x8312ddc645cf094c), CONST64(0xc61576e7216384a5), CONST64(0x9e3e7150ce4f1fd1), - CONST64(0xab72a9e249db3970), CONST64(0xe87d09c42c74b09c), CONST64(0x2c9b8dd5f916c33a), CONST64(0x6e635488e637bf59), - CONST64(0x93d91e25b6c7e254), CONST64(0xf05d25d82878a088), CONST64(0x72b8816517395c4b), CONST64(0x2b64ffa9829b32b0), - CONST64(0x5cd0fe461a2e6872), CONST64(0x1d2cac968b80169d), CONST64(0x3ea3bcc0fe1fdf21), CONST64(0x1b24a7918a831298), - CONST64(0x3648533f091b242d), CONST64(0x8c064045c94603ca), CONST64(0x354cd8b2879426a1), CONST64(0xb94a98f74ed2256b), - CONST64(0x7c5b659de13ea342), CONST64(0xe46d1fca2e72b896), CONST64(0x62734286e431b753), CONST64(0x7a536e9ae03da747), - CONST64(0x400b2babeb208b60), CONST64(0x47f459d790ad7aea), CONST64(0xff49b85ba4f1aa0e), CONST64(0x44f0d25a1e227866), - CONST64(0x395ccebc85922eab), CONST64(0x5d27873d60a09dfd), CONST64(0x0000000000000000), CONST64(0xde355afb256f94b1), - CONST64(0x02f3f2f6f401f703), CONST64(0x1cdbd5edf10ee312), CONST64(0x5fd475cb94a16afe), CONST64(0x3a5845310b1d2c27), - CONST64(0x686b5f8fe734bb5c), CONST64(0x238f1056759fc9bc), CONST64(0x582b07b7ef2c9b74), CONST64(0xb8bde18c345cd0e4), - CONST64(0xa695c6973153c4f5), CONST64(0xc2ee8f16d46177a3), CONST64(0xdacea30ad06d67b7), CONST64(0x3344d3b5869722a4), - CONST64(0x19d755677e82e59b), CONST64(0xc901eb64adea8e23), CONST64(0x34bba1c9fd1ad32e), CONST64(0xf6552edf297ba48d), - CONST64(0xa09dcd903050c0f0), CONST64(0x9ac588a13b4decd7), CONST64(0x658c30fa9fbc46d9), CONST64(0x2a9386d2f815c73f), - CONST64(0xae7e2968c6573ff9), CONST64(0x6a98ad7913354c5f), CONST64(0x14303a12060a181e), CONST64(0x1e28271b050f1411), - CONST64(0xa4663461c55233f6), CONST64(0x6688bb7711334455), CONST64(0x2f9f06587799c1b6), CONST64(0x15c743697c84ed91), - CONST64(0x01f7797b7a8ef58f), CONST64(0x0de76f757888fd85), CONST64(0xb4adf782365ad8ee), CONST64(0x48e0c4541c24706c), - CONST64(0x96d59eaf394be4dd), CONST64(0xcbf2199259eb7920), CONST64(0x50c0e84818286078), CONST64(0xe98a70bf56fa4513), - CONST64(0x8df1393eb3c8f645), CONST64(0x87e92437b0cdfa4a), CONST64(0xd83d51fc246c90b4), CONST64(0xc01d7de0206080a0), - CONST64(0x8bf93239b2cbf240), CONST64(0x4be44fd992ab72e0), CONST64(0xed71894ea3f8b615), CONST64(0xba4e137ac05d27e7), - CONST64(0x851ad6c144cc0d49), CONST64(0x5137913362a695f7), CONST64(0x6080b07010304050), CONST64(0x9fc9082bb4c1ea5e), - CONST64(0x3f54c5bb84912aae), CONST64(0x9722e7d443c51152), CONST64(0x4dec44de93a876e5), CONST64(0xb65e0574c25b2fed), - CONST64(0xa16ab4eb4ade357f), CONST64(0xa9815b14bddace73), CONST64(0x050c808a8f8c0689), CONST64(0xee7502c32d77b499), - CONST64(0xaf895013bcd9ca76), CONST64(0x6f942df39cb94ad6), CONST64(0x6177c90b6abeb5df), CONST64(0x9d3afadd40c01d5d), - CONST64(0x98367a57cf4c1bd4), CONST64(0xeb798249a2fbb210), CONST64(0x2774e9a7809d3aba), CONST64(0xbf4293f04fd1216e), - CONST64(0x42f8d95d1f217c63), CONST64(0x861e5d4cca430fc5), CONST64(0xdb39da71aae39238), CONST64(0x912aecd342c61557), -}; - -static const ulong64 T5[256] = { - CONST64(0xb9bb016ad3ba68d2), CONST64(0x9ae5b166fc54194d), CONST64(0x65e2cd14712f93bc), CONST64(0x8725511b9c74b9cd), - CONST64(0xa2f7a457f5530251), CONST64(0xd6d003be68d3b86b), CONST64(0xded604b56bd2bd6f), CONST64(0x52b3fe85d74d6429), - CONST64(0xbafdad4af0500d5d), CONST64(0x09cf63e0e9ac268a), CONST64(0x1c0984968a8d830e), CONST64(0x91a51a4ddcbf79c6), - CONST64(0xa73d4d379070addd), CONST64(0xaaf1a35cf6520755), CONST64(0xa47be117b39ac852), CONST64(0x5ab5f98ed44c612d), - CONST64(0x0346ac2023ea658f), CONST64(0xe6c4118462d5a673), CONST64(0xcc55c268a497f166), CONST64(0xc6dc0da86ed1b263), - CONST64(0x85aa99d05533ffcc), CONST64(0xb2fbaa41f3510859), CONST64(0xe2c79c0fed5b2a71), CONST64(0x59f355aef7a604a2), - CONST64(0xbefe20c17fde815f), CONST64(0x7aade5a2d848753d), CONST64(0x29d77fcce5a8329a), CONST64(0xbc71e80ab699c75e), - CONST64(0x96e03be670db904b), CONST64(0x8dac9edb5632fac8), CONST64(0xd1952215c4b751e6), CONST64(0xb332ceaa19fc2bd7), - CONST64(0x4b70937338e348ab), CONST64(0x8463fd3bbf9edc42), CONST64(0xfc41d052ae91ef7e), CONST64(0xac7de61cb09bcd56), - CONST64(0x437694783be24daf), CONST64(0xb1bd0661d0bb6dd6), CONST64(0x329bdaf1c3415819), CONST64(0x577917e5b26ecba5), - CONST64(0x41f95cb3f2a50bae), CONST64(0x16804b5640cbc00b), CONST64(0x7f670cc2bd6bdab1), CONST64(0xdc59cc7ea295fb6e), - CONST64(0x61e1409ffea11fbe), CONST64(0xcb10e3c308f318eb), CONST64(0xe181302fceb14ffe), CONST64(0x100c0e1606020a08), - CONST64(0x2e925e6749ccdb17), CONST64(0x6ea2663f51c4f337), CONST64(0xe84e53cf271d6974), CONST64(0xa0786c9c3c144450), - CONST64(0x56b0730e58c3e82b), CONST64(0x3f57349aa563f291), CONST64(0x9ee63ced73da954f), CONST64(0xd2d38e35e75d3469), - CONST64(0xc2df8023e15f3e61), CONST64(0xaef22ed779dc8b57), CONST64(0xcf136e48877d94e9), CONST64(0x2694596c4acdde13), - CONST64(0xdf1f605e817f9ee1), CONST64(0xeac19b04ee5a2f75), CONST64(0x477519f3b46cc1ad), CONST64(0xdad5893ee45c316d), - CONST64(0xeb08ffef04f70cfb), CONST64(0x2dd4f2476a26be98), CONST64(0xab38c7b71cff24db), CONST64(0x3b54b9112aed7e93), - CONST64(0x134aa23625e86f87), CONST64(0x9c69f426ba9dd34e), CONST64(0x5f7f10eeb16fcea1), CONST64(0x04038d8b8f8e8c02), - CONST64(0xc8564fe32b197d64), CONST64(0x69e74794fda01aba), CONST64(0xd31aeade0df017e7), CONST64(0x3c1198ba8689971e), - CONST64(0x78222d69110f333c), CONST64(0x3812153109071b1c), CONST64(0x11c56afdecaf2986), CONST64(0x8b20db9b10fb30cb), - CONST64(0x4030385818082820), CONST64(0xa87e6b973f154154), CONST64(0x682e237f170d3934), CONST64(0x20181c2c0c041410), - CONST64(0x0806070b03010504), CONST64(0x074521abac64e98d), CONST64(0xb6f827ca7cdf845b), CONST64(0x97295f0d9a76b3c5), - CONST64(0xef0b72648b7980f9), CONST64(0xa6f429dc7add8e53), CONST64(0xf58eb3b2473dc9f4), CONST64(0xb074628a3a164e58), - CONST64(0xe582bda4413fc3fc), CONST64(0xa5b285fc5937ebdc), CONST64(0x4f731ef8b76dc4a9), CONST64(0xdd90a8954838d8e0), - CONST64(0xa1b10877d6b967de), CONST64(0xbf37442a9573a2d1), CONST64(0x1b4ca53d26e96a83), CONST64(0xb5be8bea5f35e1d4), - CONST64(0x92e3b66dff551c49), CONST64(0xaf3b4a3c9371a8d9), CONST64(0xff077c728d7b8af1), CONST64(0x140f839d898c860a), - CONST64(0xb73143219672a7d5), CONST64(0x34179fb18588921a), CONST64(0xe30ef8e407f609ff), CONST64(0x4dfcd6337e2a82a8), - CONST64(0xed84baaf423ec6f8), CONST64(0xcad98728e25e3b65), CONST64(0x25d2f54c6927bb9c), CONST64(0x0a89cfc0ca464305), - CONST64(0x60282474140c3c30), CONST64(0x0f4326a0af65ec89), CONST64(0x676d05dfb868d5bd), CONST64(0x2f5b3a8ca361f899), - CONST64(0x180a091d05030f0c), CONST64(0x46bc7d185ec1e223), CONST64(0x82efb87bf9571641), CONST64(0xfece189967d6a97f), - CONST64(0x86ec35f076d99a43), CONST64(0xfacd9512e858257d), CONST64(0x8eea32fb75d89f47), CONST64(0x17492fbdaa66e385), - CONST64(0xf6c81f9264d7ac7b), CONST64(0xcd9ca6834e3ad2e8), CONST64(0x0e8a424b45c8cf07), CONST64(0xfd88b4b9443cccf0), - CONST64(0x8326dc9013fa35cf), CONST64(0xc453c563a796f462), CONST64(0x51f552a5f4a701a6), CONST64(0xb477ef01b598c25a), - CONST64(0x3352be1a29ec7b97), CONST64(0xa9b70f7cd5b862da), CONST64(0x76a86f2254c7fc3b), CONST64(0x19c36df6efae2c82), - CONST64(0x6f6b02d4bb69d0b9), CONST64(0x62a7ecbfdd4b7a31), CONST64(0x31dd76d1e0ab3d96), CONST64(0x21d178c7e6a9379e), - CONST64(0x1f4f28b6a967e681), CONST64(0x503c364e1e0a2228), CONST64(0x028fc8cbc9474601), CONST64(0xc316e4c80bf21def), - CONST64(0xc1992c03c2b55bee), CONST64(0x0dccee6b6622aa88), CONST64(0x7b64814932e556b3), CONST64(0x235eb00c2fee719f), - CONST64(0x99a31d46dfbe7cc2), CONST64(0x45fad1387d2b87ac), CONST64(0x7c21a0e29e81bf3e), CONST64(0x906c7ea636125a48), - CONST64(0x6c2daef49883b536), CONST64(0xd85a41f52d1b776c), CONST64(0x70242a62120e3638), CONST64(0x05cae9606523af8c), - CONST64(0xfb04f1f902f506f3), CONST64(0x1283c6ddcf454c09), CONST64(0x15c6e7766321a584), CONST64(0x3e9e50714fced11f), - CONST64(0x72abe2a9db497039), CONST64(0x7de8c409742c9cb0), CONST64(0x9b2cd58d16f93ac3), CONST64(0x636e885437e659bf), - CONST64(0xd993251ec7b654e2), CONST64(0x5df0d825782888a0), CONST64(0xb872658139174b5c), CONST64(0x642ba9ff9b82b032), - CONST64(0xd05c46fe2e1a7268), CONST64(0x2c1d96ac808b9d16), CONST64(0xa33ec0bc1ffe21df), CONST64(0x241b91a7838a9812), - CONST64(0x48363f531b092d24), CONST64(0x068c454046c9ca03), CONST64(0x4c35b2d89487a126), CONST64(0x4ab9f798d24e6b25), - CONST64(0x5b7c9d653ee142a3), CONST64(0x6de4ca1f722e96b8), CONST64(0x7362864231e453b7), CONST64(0x537a9a6e3de047a7), - CONST64(0x0b40ab2b20eb608b), CONST64(0xf447d759ad90ea7a), CONST64(0x49ff5bb8f1a40eaa), CONST64(0xf0445ad2221e6678), - CONST64(0x5c39bcce9285ab2e), CONST64(0x275d3d87a060fd9d), CONST64(0x0000000000000000), CONST64(0x35defb5a6f25b194), - CONST64(0xf302f6f201f403f7), CONST64(0xdb1cedd50ef112e3), CONST64(0xd45fcb75a194fe6a), CONST64(0x583a31451d0b272c), - CONST64(0x6b688f5f34e75cbb), CONST64(0x8f2356109f75bcc9), CONST64(0x2b58b7072cef749b), CONST64(0xbdb88ce15c34e4d0), - CONST64(0x95a697c65331f5c4), CONST64(0xeec2168f61d4a377), CONST64(0xceda0aa36dd0b767), CONST64(0x4433b5d39786a422), - CONST64(0xd7196755827e9be5), CONST64(0x01c964ebeaad238e), CONST64(0xbb34c9a11afd2ed3), CONST64(0x55f6df2e7b298da4), - CONST64(0x9da090cd5030f0c0), CONST64(0xc59aa1884d3bd7ec), CONST64(0x8c65fa30bc9fd946), CONST64(0x932ad28615f83fc7), - CONST64(0x7eae682957c6f93f), CONST64(0x986a79ad35135f4c), CONST64(0x3014123a0a061e18), CONST64(0x281e1b270f051114), - CONST64(0x66a4613452c5f633), CONST64(0x886677bb33115544), CONST64(0x9f2f58069977b6c1), CONST64(0xc7156943847c91ed), - CONST64(0xf7017b798e7a8ff5), CONST64(0xe70d756f887885fd), CONST64(0xadb482f75a36eed8), CONST64(0xe04854c4241c6c70), - CONST64(0xd596af9e4b39dde4), CONST64(0xf2cb9219eb592079), CONST64(0xc05048e828187860), CONST64(0x8ae9bf70fa561345), - CONST64(0xf18d3e39c8b345f6), CONST64(0xe9873724cdb04afa), CONST64(0x3dd8fc516c24b490), CONST64(0x1dc0e07d6020a080), - CONST64(0xf98b3932cbb240f2), CONST64(0xe44bd94fab92e072), CONST64(0x71ed4e89f8a315b6), CONST64(0x4eba7a135dc0e727), - CONST64(0x1a85c1d6cc44490d), CONST64(0x37513391a662f795), CONST64(0x806070b030105040), CONST64(0xc99f2b08c1b45eea), - CONST64(0x543fbbc59184ae2a), CONST64(0x2297d4e7c5435211), CONST64(0xec4dde44a893e576), CONST64(0x5eb674055bc2ed2f), - CONST64(0x6aa1ebb4de4a7f35), CONST64(0x81a9145bdabd73ce), CONST64(0x0c058a808c8f8906), CONST64(0x75eec302772d99b4), - CONST64(0x89af1350d9bc76ca), CONST64(0x946ff32db99cd64a), CONST64(0x77610bc9be6adfb5), CONST64(0x3a9dddfac0405d1d), - CONST64(0x3698577a4ccfd41b), CONST64(0x79eb4982fba210b2), CONST64(0x7427a7e99d80ba3a), CONST64(0x42bff093d14f6e21), - CONST64(0xf8425dd9211f637c), CONST64(0x1e864c5d43cac50f), CONST64(0x39db71dae3aa3892), CONST64(0x2a91d3ecc6425715), -}; - -static const ulong64 T6[256] = { - CONST64(0x6a01bbb9d268bad3), CONST64(0x66b1e59a4d1954fc), CONST64(0x14cde265bc932f71), CONST64(0x1b512587cdb9749c), - CONST64(0x57a4f7a2510253f5), CONST64(0xbe03d0d66bb8d368), CONST64(0xb504d6de6fbdd26b), CONST64(0x85feb35229644dd7), - CONST64(0x4aadfdba5d0d50f0), CONST64(0xe063cf098a26ace9), CONST64(0x9684091c0e838d8a), CONST64(0x4d1aa591c679bfdc), - CONST64(0x374d3da7ddad7090), CONST64(0x5ca3f1aa550752f6), CONST64(0x17e17ba452c89ab3), CONST64(0x8ef9b55a2d614cd4), - CONST64(0x20ac46038f65ea23), CONST64(0x8411c4e673a6d562), CONST64(0x68c255cc66f197a4), CONST64(0xa80ddcc663b2d16e), - CONST64(0xd099aa85ccff3355), CONST64(0x41aafbb2590851f3), CONST64(0x0f9cc7e2712a5bed), CONST64(0xae55f359a204a6f7), - CONST64(0xc120febe5f81de7f), CONST64(0xa2e5ad7a3d7548d8), CONST64(0xcc7fd7299a32a8e5), CONST64(0x0ae871bc5ec799b6), - CONST64(0xe63be0964b90db70), CONST64(0xdb9eac8dc8fa3256), CONST64(0x152295d1e651b7c4), CONST64(0xaace32b3d72bfc19), - CONST64(0x7393704bab48e338), CONST64(0x3bfd638442dc9ebf), CONST64(0x52d041fc7eef91ae), CONST64(0x1ce67dac56cd9bb0), - CONST64(0x78947643af4de23b), CONST64(0x6106bdb1d66dbbd0), CONST64(0xf1da9b32195841c3), CONST64(0xe5177957a5cb6eb2), - CONST64(0xb35cf941ae0ba5f2), CONST64(0x564b80160bc0cb40), CONST64(0xc20c677fb1da6bbd), CONST64(0x7ecc59dc6efb95a2), - CONST64(0x9f40e161be1fa1fe), CONST64(0xc3e310cbeb18f308), CONST64(0x2f3081e1fe4fb1ce), CONST64(0x160e0c10080a0206), - CONST64(0x675e922e17dbcc49), CONST64(0x3f66a26e37f3c451), CONST64(0xcf534ee874691d27), CONST64(0x9c6c78a05044143c), - CONST64(0x0e73b0562be8c358), CONST64(0x9a34573f91f263a5), CONST64(0xed3ce69e4f95da73), CONST64(0x358ed3d269345de7), - CONST64(0x2380dfc2613e5fe1), CONST64(0xd72ef2ae578bdc79), CONST64(0x486e13cfe9947d87), CONST64(0x6c59942613decd4a), - CONST64(0x5e601fdfe19e7f81), CONST64(0x049bc1ea752f5aee), CONST64(0xf3197547adc16cb4), CONST64(0x3e89d5da6d315ce4), - CONST64(0xefff08ebfb0cf704), CONST64(0x47f2d42d98be266a), CONST64(0xb7c738abdb24ff1c), CONST64(0x11b9543b937eed2a), - CONST64(0x36a24a13876fe825), CONST64(0x26f4699c4ed39dba), CONST64(0xee107f5fa1ce6fb1), CONST64(0x8b8d0304028c8e8f), - CONST64(0xe34f56c8647d192b), CONST64(0x9447e769ba1aa0fd), CONST64(0xdeea1ad3e717f00d), CONST64(0xba98113c1e978986), - CONST64(0x692d22783c330f11), CONST64(0x311512381c1b0709), CONST64(0xfd6ac5118629afec), CONST64(0x9bdb208bcb30fb10), - CONST64(0x5838304020280818), CONST64(0x976b7ea85441153f), CONST64(0x7f232e6834390d17), CONST64(0x2c1c18201014040c), - CONST64(0x0b07060804050103), CONST64(0xab2145078de964ac), CONST64(0xca27f8b65b84df7c), CONST64(0x0d5f2997c5b3769a), - CONST64(0x64720beff980798b), CONST64(0xdc29f4a6538edd7a), CONST64(0xb2b38ef5f4c93d47), CONST64(0x8a6274b0584e163a), - CONST64(0xa4bd82e5fcc33f41), CONST64(0xfc85b2a5dceb3759), CONST64(0xf81e734fa9c46db7), CONST64(0x95a890dde0d83848), - CONST64(0x7708b1a1de67b9d6), CONST64(0x2a4437bfd1a27395), CONST64(0x3da54c1b836ae926), CONST64(0xea8bbeb5d4e1355f), - CONST64(0x6db6e392491c55ff), CONST64(0x3c4a3bafd9a87193), CONST64(0x727c07fff18a7b8d), CONST64(0x9d830f140a868c89), - CONST64(0x214331b7d5a77296), CONST64(0xb19f17341a928885), CONST64(0xe4f80ee3ff09f607), CONST64(0x33d6fc4da8822a7e), - CONST64(0xafba84edf8c63e42), CONST64(0x2887d9ca653b5ee2), CONST64(0x4cf5d2259cbb2769), CONST64(0xc0cf890a054346ca), - CONST64(0x74242860303c0c14), CONST64(0xa026430f89ec65af), CONST64(0xdf056d67bdd568b8), CONST64(0x8c3a5b2f99f861a3), - CONST64(0x1d090a180c0f0305), CONST64(0x187dbc4623e2c15e), CONST64(0x7bb8ef82411657f9), CONST64(0x9918cefe7fa9d667), - CONST64(0xf035ec86439ad976), CONST64(0x1295cdfa7d2558e8), CONST64(0xfb32ea8e479fd875), CONST64(0xbd2f491785e366aa), - CONST64(0x921fc8f67bacd764), CONST64(0x83a69ccde8d23a4e), CONST64(0x4b428a0e07cfc845), CONST64(0xb9b488fdf0cc3c44), - CONST64(0x90dc2683cf35fa13), CONST64(0x63c553c462f496a7), CONST64(0xa552f551a601a7f4), CONST64(0x01ef77b45ac298b5), - CONST64(0x1abe5233977bec29), CONST64(0x7c0fb7a9da62b8d5), CONST64(0x226fa8763bfcc754), CONST64(0xf66dc319822caeef), - CONST64(0xd4026b6fb9d069bb), CONST64(0xbfeca762317a4bdd), CONST64(0xd176dd31963dabe0), CONST64(0xc778d1219e37a9e6), - CONST64(0xb6284f1f81e667a9), CONST64(0x4e363c5028220a1e), CONST64(0xcbc88f02014647c9), CONST64(0xc8e416c3ef1df20b), - CONST64(0x032c99c1ee5bb5c2), CONST64(0x6beecc0d88aa2266), CONST64(0x4981647bb356e532), CONST64(0x0cb05e239f71ee2f), - CONST64(0x461da399c27cbedf), CONST64(0x38d1fa45ac872b7d), CONST64(0xe2a0217c3ebf819e), CONST64(0xa67e6c90485a1236), - CONST64(0xf4ae2d6c36b58398), CONST64(0xf5415ad86c771b2d), CONST64(0x622a247038360e12), CONST64(0x60e9ca058caf2365), - CONST64(0xf9f104fbf306f502), CONST64(0xddc68312094c45cf), CONST64(0x76e7c61584a52163), CONST64(0x71509e3e1fd1ce4f), - CONST64(0xa9e2ab72397049db), CONST64(0x09c4e87db09c2c74), CONST64(0x8dd52c9bc33af916), CONST64(0x54886e63bf59e637), - CONST64(0x1e2593d9e254b6c7), CONST64(0x25d8f05da0882878), CONST64(0x816572b85c4b1739), CONST64(0xffa92b6432b0829b), - CONST64(0xfe465cd068721a2e), CONST64(0xac961d2c169d8b80), CONST64(0xbcc03ea3df21fe1f), CONST64(0xa7911b2412988a83), - CONST64(0x533f3648242d091b), CONST64(0x40458c0603cac946), CONST64(0xd8b2354c26a18794), CONST64(0x98f7b94a256b4ed2), - CONST64(0x659d7c5ba342e13e), CONST64(0x1fcae46db8962e72), CONST64(0x42866273b753e431), CONST64(0x6e9a7a53a747e03d), - CONST64(0x2bab400b8b60eb20), CONST64(0x59d747f47aea90ad), CONST64(0xb85bff49aa0ea4f1), CONST64(0xd25a44f078661e22), - CONST64(0xcebc395c2eab8592), CONST64(0x873d5d279dfd60a0), CONST64(0x0000000000000000), CONST64(0x5afbde3594b1256f), - CONST64(0xf2f602f3f703f401), CONST64(0xd5ed1cdbe312f10e), CONST64(0x75cb5fd46afe94a1), CONST64(0x45313a582c270b1d), - CONST64(0x5f8f686bbb5ce734), CONST64(0x1056238fc9bc759f), CONST64(0x07b7582b9b74ef2c), CONST64(0xe18cb8bdd0e4345c), - CONST64(0xc697a695c4f53153), CONST64(0x8f16c2ee77a3d461), CONST64(0xa30adace67b7d06d), CONST64(0xd3b5334422a48697), - CONST64(0x556719d7e59b7e82), CONST64(0xeb64c9018e23adea), CONST64(0xa1c934bbd32efd1a), CONST64(0x2edff655a48d297b), - CONST64(0xcd90a09dc0f03050), CONST64(0x88a19ac5ecd73b4d), CONST64(0x30fa658c46d99fbc), CONST64(0x86d22a93c73ff815), - CONST64(0x2968ae7e3ff9c657), CONST64(0xad796a984c5f1335), CONST64(0x3a121430181e060a), CONST64(0x271b1e281411050f), - CONST64(0x3461a46633f6c552), CONST64(0xbb77668844551133), CONST64(0x06582f9fc1b67799), CONST64(0x436915c7ed917c84), - CONST64(0x797b01f7f58f7a8e), CONST64(0x6f750de7fd857888), CONST64(0xf782b4add8ee365a), CONST64(0xc45448e0706c1c24), - CONST64(0x9eaf96d5e4dd394b), CONST64(0x1992cbf2792059eb), CONST64(0xe84850c060781828), CONST64(0x70bfe98a451356fa), - CONST64(0x393e8df1f645b3c8), CONST64(0x243787e9fa4ab0cd), CONST64(0x51fcd83d90b4246c), CONST64(0x7de0c01d80a02060), - CONST64(0x32398bf9f240b2cb), CONST64(0x4fd94be472e092ab), CONST64(0x894eed71b615a3f8), CONST64(0x137aba4e27e7c05d), - CONST64(0xd6c1851a0d4944cc), CONST64(0x9133513795f762a6), CONST64(0xb070608040501030), CONST64(0x082b9fc9ea5eb4c1), - CONST64(0xc5bb3f542aae8491), CONST64(0xe7d49722115243c5), CONST64(0x44de4dec76e593a8), CONST64(0x0574b65e2fedc25b), - CONST64(0xb4eba16a357f4ade), CONST64(0x5b14a981ce73bdda), CONST64(0x808a050c06898f8c), CONST64(0x02c3ee75b4992d77), - CONST64(0x5013af89ca76bcd9), CONST64(0x2df36f944ad69cb9), CONST64(0xc90b6177b5df6abe), CONST64(0xfadd9d3a1d5d40c0), - CONST64(0x7a5798361bd4cf4c), CONST64(0x8249eb79b210a2fb), CONST64(0xe9a727743aba809d), CONST64(0x93f0bf42216e4fd1), - CONST64(0xd95d42f87c631f21), CONST64(0x5d4c861e0fc5ca43), CONST64(0xda71db399238aae3), CONST64(0xecd3912a155742c6), -}; - -static const ulong64 T7[256] = { - CONST64(0x016ab9bb68d2d3ba), CONST64(0xb1669ae5194dfc54), CONST64(0xcd1465e293bc712f), CONST64(0x511b8725b9cd9c74), - CONST64(0xa457a2f70251f553), CONST64(0x03bed6d0b86b68d3), CONST64(0x04b5ded6bd6f6bd2), CONST64(0xfe8552b36429d74d), - CONST64(0xad4abafd0d5df050), CONST64(0x63e009cf268ae9ac), CONST64(0x84961c09830e8a8d), CONST64(0x1a4d91a579c6dcbf), - CONST64(0x4d37a73daddd9070), CONST64(0xa35caaf10755f652), CONST64(0xe117a47bc852b39a), CONST64(0xf98e5ab5612dd44c), - CONST64(0xac200346658f23ea), CONST64(0x1184e6c4a67362d5), CONST64(0xc268cc55f166a497), CONST64(0x0da8c6dcb2636ed1), - CONST64(0x99d085aaffcc5533), CONST64(0xaa41b2fb0859f351), CONST64(0x9c0fe2c72a71ed5b), CONST64(0x55ae59f304a2f7a6), - CONST64(0x20c1befe815f7fde), CONST64(0xe5a27aad753dd848), CONST64(0x7fcc29d7329ae5a8), CONST64(0xe80abc71c75eb699), - CONST64(0x3be696e0904b70db), CONST64(0x9edb8dacfac85632), CONST64(0x2215d19551e6c4b7), CONST64(0xceaab3322bd719fc), - CONST64(0x93734b7048ab38e3), CONST64(0xfd3b8463dc42bf9e), CONST64(0xd052fc41ef7eae91), CONST64(0xe61cac7dcd56b09b), - CONST64(0x947843764daf3be2), CONST64(0x0661b1bd6dd6d0bb), CONST64(0xdaf1329b5819c341), CONST64(0x17e55779cba5b26e), - CONST64(0x5cb341f90baef2a5), CONST64(0x4b561680c00b40cb), CONST64(0x0cc27f67dab1bd6b), CONST64(0xcc7edc59fb6ea295), - CONST64(0x409f61e11fbefea1), CONST64(0xe3c3cb1018eb08f3), CONST64(0x302fe1814ffeceb1), CONST64(0x0e16100c0a080602), - CONST64(0x5e672e92db1749cc), CONST64(0x663f6ea2f33751c4), CONST64(0x53cfe84e6974271d), CONST64(0x6c9ca07844503c14), - CONST64(0x730e56b0e82b58c3), CONST64(0x349a3f57f291a563), CONST64(0x3ced9ee6954f73da), CONST64(0x8e35d2d33469e75d), - CONST64(0x8023c2df3e61e15f), CONST64(0x2ed7aef28b5779dc), CONST64(0x6e48cf1394e9877d), CONST64(0x596c2694de134acd), - CONST64(0x605edf1f9ee1817f), CONST64(0x9b04eac12f75ee5a), CONST64(0x19f34775c1adb46c), CONST64(0x893edad5316de45c), - CONST64(0xffefeb080cfb04f7), CONST64(0xf2472dd4be986a26), CONST64(0xc7b7ab3824db1cff), CONST64(0xb9113b547e932aed), - CONST64(0xa236134a6f8725e8), CONST64(0xf4269c69d34eba9d), CONST64(0x10ee5f7fcea1b16f), CONST64(0x8d8b04038c028f8e), - CONST64(0x4fe3c8567d642b19), CONST64(0x479469e71abafda0), CONST64(0xeaded31a17e70df0), CONST64(0x98ba3c11971e8689), - CONST64(0x2d697822333c110f), CONST64(0x153138121b1c0907), CONST64(0x6afd11c52986ecaf), CONST64(0xdb9b8b2030cb10fb), - CONST64(0x3858403028201808), CONST64(0x6b97a87e41543f15), CONST64(0x237f682e3934170d), CONST64(0x1c2c201814100c04), - CONST64(0x070b080605040301), CONST64(0x21ab0745e98dac64), CONST64(0x27cab6f8845b7cdf), CONST64(0x5f0d9729b3c59a76), - CONST64(0x7264ef0b80f98b79), CONST64(0x29dca6f48e537add), CONST64(0xb3b2f58ec9f4473d), CONST64(0x628ab0744e583a16), - CONST64(0xbda4e582c3fc413f), CONST64(0x85fca5b2ebdc5937), CONST64(0x1ef84f73c4a9b76d), CONST64(0xa895dd90d8e04838), - CONST64(0x0877a1b167ded6b9), CONST64(0x442abf37a2d19573), CONST64(0xa53d1b4c6a8326e9), CONST64(0x8beab5bee1d45f35), - CONST64(0xb66d92e31c49ff55), CONST64(0x4a3caf3ba8d99371), CONST64(0x7c72ff078af18d7b), CONST64(0x839d140f860a898c), - CONST64(0x4321b731a7d59672), CONST64(0x9fb13417921a8588), CONST64(0xf8e4e30e09ff07f6), CONST64(0xd6334dfc82a87e2a), - CONST64(0xbaafed84c6f8423e), CONST64(0x8728cad93b65e25e), CONST64(0xf54c25d2bb9c6927), CONST64(0xcfc00a894305ca46), - CONST64(0x247460283c30140c), CONST64(0x26a00f43ec89af65), CONST64(0x05df676dd5bdb868), CONST64(0x3a8c2f5bf899a361), - CONST64(0x091d180a0f0c0503), CONST64(0x7d1846bce2235ec1), CONST64(0xb87b82ef1641f957), CONST64(0x1899fecea97f67d6), - CONST64(0x35f086ec9a4376d9), CONST64(0x9512facd257de858), CONST64(0x32fb8eea9f4775d8), CONST64(0x2fbd1749e385aa66), - CONST64(0x1f92f6c8ac7b64d7), CONST64(0xa683cd9cd2e84e3a), CONST64(0x424b0e8acf0745c8), CONST64(0xb4b9fd88ccf0443c), - CONST64(0xdc90832635cf13fa), CONST64(0xc563c453f462a796), CONST64(0x52a551f501a6f4a7), CONST64(0xef01b477c25ab598), - CONST64(0xbe1a33527b9729ec), CONST64(0x0f7ca9b762dad5b8), CONST64(0x6f2276a8fc3b54c7), CONST64(0x6df619c32c82efae), - CONST64(0x02d46f6bd0b9bb69), CONST64(0xecbf62a77a31dd4b), CONST64(0x76d131dd3d96e0ab), CONST64(0x78c721d1379ee6a9), - CONST64(0x28b61f4fe681a967), CONST64(0x364e503c22281e0a), CONST64(0xc8cb028f4601c947), CONST64(0xe4c8c3161def0bf2), - CONST64(0x2c03c1995beec2b5), CONST64(0xee6b0dccaa886622), CONST64(0x81497b6456b332e5), CONST64(0xb00c235e719f2fee), - CONST64(0x1d4699a37cc2dfbe), CONST64(0xd13845fa87ac7d2b), CONST64(0xa0e27c21bf3e9e81), CONST64(0x7ea6906c5a483612), - CONST64(0xaef46c2db5369883), CONST64(0x41f5d85a776c2d1b), CONST64(0x2a6270243638120e), CONST64(0xe96005caaf8c6523), - CONST64(0xf1f9fb0406f302f5), CONST64(0xc6dd12834c09cf45), CONST64(0xe77615c6a5846321), CONST64(0x50713e9ed11f4fce), - CONST64(0xe2a972ab7039db49), CONST64(0xc4097de89cb0742c), CONST64(0xd58d9b2c3ac316f9), CONST64(0x8854636e59bf37e6), - CONST64(0x251ed99354e2c7b6), CONST64(0xd8255df088a07828), CONST64(0x6581b8724b5c3917), CONST64(0xa9ff642bb0329b82), - CONST64(0x46fed05c72682e1a), CONST64(0x96ac2c1d9d16808b), CONST64(0xc0bca33e21df1ffe), CONST64(0x91a7241b9812838a), - CONST64(0x3f5348362d241b09), CONST64(0x4540068cca0346c9), CONST64(0xb2d84c35a1269487), CONST64(0xf7984ab96b25d24e), - CONST64(0x9d655b7c42a33ee1), CONST64(0xca1f6de496b8722e), CONST64(0x8642736253b731e4), CONST64(0x9a6e537a47a73de0), - CONST64(0xab2b0b40608b20eb), CONST64(0xd759f447ea7aad90), CONST64(0x5bb849ff0eaaf1a4), CONST64(0x5ad2f0446678221e), - CONST64(0xbcce5c39ab2e9285), CONST64(0x3d87275dfd9da060), CONST64(0x0000000000000000), CONST64(0xfb5a35deb1946f25), - CONST64(0xf6f2f30203f701f4), CONST64(0xedd5db1c12e30ef1), CONST64(0xcb75d45ffe6aa194), CONST64(0x3145583a272c1d0b), - CONST64(0x8f5f6b685cbb34e7), CONST64(0x56108f23bcc99f75), CONST64(0xb7072b58749b2cef), CONST64(0x8ce1bdb8e4d05c34), - CONST64(0x97c695a6f5c45331), CONST64(0x168feec2a37761d4), CONST64(0x0aa3cedab7676dd0), CONST64(0xb5d34433a4229786), - CONST64(0x6755d7199be5827e), CONST64(0x64eb01c9238eeaad), CONST64(0xc9a1bb342ed31afd), CONST64(0xdf2e55f68da47b29), - CONST64(0x90cd9da0f0c05030), CONST64(0xa188c59ad7ec4d3b), CONST64(0xfa308c65d946bc9f), CONST64(0xd286932a3fc715f8), - CONST64(0x68297eaef93f57c6), CONST64(0x79ad986a5f4c3513), CONST64(0x123a30141e180a06), CONST64(0x1b27281e11140f05), - CONST64(0x613466a4f63352c5), CONST64(0x77bb886655443311), CONST64(0x58069f2fb6c19977), CONST64(0x6943c71591ed847c), - CONST64(0x7b79f7018ff58e7a), CONST64(0x756fe70d85fd8878), CONST64(0x82f7adb4eed85a36), CONST64(0x54c4e0486c70241c), - CONST64(0xaf9ed596dde44b39), CONST64(0x9219f2cb2079eb59), CONST64(0x48e8c05078602818), CONST64(0xbf708ae91345fa56), - CONST64(0x3e39f18d45f6c8b3), CONST64(0x3724e9874afacdb0), CONST64(0xfc513dd8b4906c24), CONST64(0xe07d1dc0a0806020), - CONST64(0x3932f98b40f2cbb2), CONST64(0xd94fe44be072ab92), CONST64(0x4e8971ed15b6f8a3), CONST64(0x7a134ebae7275dc0), - CONST64(0xc1d61a85490dcc44), CONST64(0x33913751f795a662), CONST64(0x70b0806050403010), CONST64(0x2b08c99f5eeac1b4), - CONST64(0xbbc5543fae2a9184), CONST64(0xd4e722975211c543), CONST64(0xde44ec4de576a893), CONST64(0x74055eb6ed2f5bc2), - CONST64(0xebb46aa17f35de4a), CONST64(0x145b81a973cedabd), CONST64(0x8a800c0589068c8f), CONST64(0xc30275ee99b4772d), - CONST64(0x135089af76cad9bc), CONST64(0xf32d946fd64ab99c), CONST64(0x0bc97761dfb5be6a), CONST64(0xddfa3a9d5d1dc040), - CONST64(0x577a3698d41b4ccf), CONST64(0x498279eb10b2fba2), CONST64(0xa7e97427ba3a9d80), CONST64(0xf09342bf6e21d14f), - CONST64(0x5dd9f842637c211f), CONST64(0x4c5d1e86c50f43ca), CONST64(0x71da39db3892e3aa), CONST64(0xd3ec2a915715c642), -}; - -static const ulong64 c[R + 1] = { - CONST64(0xba542f7453d3d24d), - CONST64(0x50ac8dbf70529a4c), - CONST64(0xead597d133515ba6), - CONST64(0xde48a899db32b7fc), - CONST64(0xe39e919be2bb416e), - CONST64(0xa5cb6b95a1f3b102), - CONST64(0xccc41d14c363da5d), - CONST64(0x5fdc7dcd7f5a6c5c), - CONST64(0xf726ffede89d6f8e), -}; - - /** - Initialize the Khazad block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int r; - const ulong64 *S; - ulong64 K2, K1; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (num_rounds != 8 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - /* use 7th table */ - S = T7; - - /* - * map unsigned char array cipher key to initial key state (mu): - */ - K2 = - ((ulong64)key[ 0] << 56) ^ - ((ulong64)key[ 1] << 48) ^ - ((ulong64)key[ 2] << 40) ^ - ((ulong64)key[ 3] << 32) ^ - ((ulong64)key[ 4] << 24) ^ - ((ulong64)key[ 5] << 16) ^ - ((ulong64)key[ 6] << 8) ^ - ((ulong64)key[ 7] ); - K1 = - ((ulong64)key[ 8] << 56) ^ - ((ulong64)key[ 9] << 48) ^ - ((ulong64)key[10] << 40) ^ - ((ulong64)key[11] << 32) ^ - ((ulong64)key[12] << 24) ^ - ((ulong64)key[13] << 16) ^ - ((ulong64)key[14] << 8) ^ - ((ulong64)key[15] ); - - /* - * compute the round keys: - */ - for (r = 0; r <= R; r++) { - /* - * K[r] = rho(c[r], K1) ^ K2; - */ - skey->khazad.roundKeyEnc[r] = - T0[(int)(K1 >> 56) ] ^ - T1[(int)(K1 >> 48) & 0xff] ^ - T2[(int)(K1 >> 40) & 0xff] ^ - T3[(int)(K1 >> 32) & 0xff] ^ - T4[(int)(K1 >> 24) & 0xff] ^ - T5[(int)(K1 >> 16) & 0xff] ^ - T6[(int)(K1 >> 8) & 0xff] ^ - T7[(int)(K1 ) & 0xff] ^ - c[r] ^ K2; - K2 = K1; K1 = skey->khazad.roundKeyEnc[r]; - } - /* - * compute the inverse key schedule: - * K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}) - */ - skey->khazad.roundKeyDec[0] = skey->khazad.roundKeyEnc[R]; - for (r = 1; r < R; r++) { - K1 = skey->khazad.roundKeyEnc[R - r]; - skey->khazad.roundKeyDec[r] = - T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ - T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ - T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ - T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ - T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ - T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ - T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ - T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; - } - skey->khazad.roundKeyDec[R] = skey->khazad.roundKeyEnc[0]; - - return CRYPT_OK; -} - -static void khazad_crypt(const unsigned char *plaintext, unsigned char *ciphertext, - const ulong64 *roundKey) { - int r; - ulong64 state; - /* - * map plaintext block to cipher state (mu) - * and add initial round key (sigma[K^0]): - */ - state = - ((ulong64)plaintext[0] << 56) ^ - ((ulong64)plaintext[1] << 48) ^ - ((ulong64)plaintext[2] << 40) ^ - ((ulong64)plaintext[3] << 32) ^ - ((ulong64)plaintext[4] << 24) ^ - ((ulong64)plaintext[5] << 16) ^ - ((ulong64)plaintext[6] << 8) ^ - ((ulong64)plaintext[7] ) ^ - roundKey[0]; - - /* - * R - 1 full rounds: - */ - for (r = 1; r < R; r++) { - state = - T0[(int)(state >> 56) ] ^ - T1[(int)(state >> 48) & 0xff] ^ - T2[(int)(state >> 40) & 0xff] ^ - T3[(int)(state >> 32) & 0xff] ^ - T4[(int)(state >> 24) & 0xff] ^ - T5[(int)(state >> 16) & 0xff] ^ - T6[(int)(state >> 8) & 0xff] ^ - T7[(int)(state ) & 0xff] ^ - roundKey[r]; - } - - /* - * last round: - */ - state = - (T0[(int)(state >> 56) ] & CONST64(0xff00000000000000)) ^ - (T1[(int)(state >> 48) & 0xff] & CONST64(0x00ff000000000000)) ^ - (T2[(int)(state >> 40) & 0xff] & CONST64(0x0000ff0000000000)) ^ - (T3[(int)(state >> 32) & 0xff] & CONST64(0x000000ff00000000)) ^ - (T4[(int)(state >> 24) & 0xff] & CONST64(0x00000000ff000000)) ^ - (T5[(int)(state >> 16) & 0xff] & CONST64(0x0000000000ff0000)) ^ - (T6[(int)(state >> 8) & 0xff] & CONST64(0x000000000000ff00)) ^ - (T7[(int)(state ) & 0xff] & CONST64(0x00000000000000ff)) ^ - roundKey[R]; - - /* - * map cipher state to ciphertext block (mu^{-1}): - */ - ciphertext[0] = (unsigned char)(state >> 56); - ciphertext[1] = (unsigned char)(state >> 48); - ciphertext[2] = (unsigned char)(state >> 40); - ciphertext[3] = (unsigned char)(state >> 32); - ciphertext[4] = (unsigned char)(state >> 24); - ciphertext[5] = (unsigned char)(state >> 16); - ciphertext[6] = (unsigned char)(state >> 8); - ciphertext[7] = (unsigned char)(state ); -} - -/** - Encrypts a block of text with Khazad - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - khazad_crypt(pt, ct, skey->khazad.roundKeyEnc); - return CRYPT_OK; -} - -/** - Decrypts a block of text with Khazad - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - khazad_crypt(ct, pt, skey->khazad.roundKeyDec); - return CRYPT_OK; -} - -/** - Performs a self-test of the Khazad block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int khazad_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct test { - unsigned char pt[8], ct[8], key[16]; - } tests[] = { -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x49, 0xA4, 0xCE, 0x32, 0xAC, 0x19, 0x0E, 0x3F }, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x64, 0x5D, 0x77, 0x3E, 0x40, 0xAB, 0xDD, 0x53 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } -}, { - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x9E, 0x39, 0x98, 0x64, 0xF7, 0x8E, 0xCA, 0x02 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}, { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0xA9, 0xDF, 0x3D, 0x2C, 0x64, 0xD3, 0xEA, 0x28 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -} -}; - int x, y; - unsigned char buf[2][8]; - symmetric_key skey; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - khazad_setup(tests[x].key, 16, 0, &skey); - khazad_ecb_encrypt(tests[x].pt, buf[0], &skey); - khazad_ecb_decrypt(buf[0], buf[1], &skey); - if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad Encrypt", x) || - compare_testvector(buf[1], 8, tests[x].pt, 8, "Khazad Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - for (y = 0; y < 1000; y++) khazad_ecb_encrypt(buf[0], buf[0], &skey); - for (y = 0; y < 1000; y++) khazad_ecb_decrypt(buf[0], buf[0], &skey); - if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad 1000", 1000)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void khazad_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int khazad_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize >= 16) { - *keysize = 16; - return CRYPT_OK; - } - return CRYPT_INVALID_KEYSIZE; -} - -#undef R - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/kseed.c b/Sources/DataLiteC/libtomcrypt/ciphers/kseed.c deleted file mode 100644 index be8ec63..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/kseed.c +++ /dev/null @@ -1,369 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file kseed.c - seed implementation of SEED derived from RFC4269 - Tom St Denis -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_KSEED - -const struct ltc_cipher_descriptor kseed_desc = { - "seed", - 20, - 16, 16, 16, 16, - &kseed_setup, - &kseed_ecb_encrypt, - &kseed_ecb_decrypt, - &kseed_test, - &kseed_done, - &kseed_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 SS0[256] = { -0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL, -0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL, -0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL, -0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL, -0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL, -0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL, -0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL, -0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL, -0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL, -0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL, -0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL, -0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL, -0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL, -0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL, -0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL, -0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL, -0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL, -0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL, -0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL, -0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL, -0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL, -0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL, -0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL, -0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL, -0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL, -0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL, -0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL, -0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL, -0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL, -0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL, -0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL, -0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL -}; - -static const ulong32 SS1[256] = { -0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL, -0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL, -0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL, -0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL, -0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL, -0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL, -0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL, -0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL, -0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL, -0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL, -0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL, -0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL, -0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL, -0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL, -0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL, -0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL, -0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL, -0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL, -0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL, -0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL, -0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL, -0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL, -0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL, -0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL, -0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL, -0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL, -0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL, -0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL, -0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL, -0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL, -0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL, -0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL -}; - -static const ulong32 SS2[256] = { -0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL, -0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL, -0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL, -0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL, -0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL, -0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL, -0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL, -0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL, -0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL, -0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL, -0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL, -0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL, -0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL, -0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL, -0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL, -0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL, -0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL, -0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL, -0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL, -0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL, -0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL, -0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL, -0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL, -0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL, -0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL, -0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL, -0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL, -0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL, -0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL, -0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL, -0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL, -0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL -}; - -static const ulong32 SS3[256] = { -0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL, -0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL, -0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL, -0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL, -0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL, -0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL, -0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL, -0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL, -0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL, -0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL, -0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL, -0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL, -0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL, -0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL, -0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL, -0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL, -0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL, -0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL, -0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL, -0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL, -0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL, -0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL, -0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL, -0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL, -0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL, -0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL, -0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL, -0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL, -0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL, -0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL, -0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL, -0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL -}; - -static const ulong32 KCi[16] = { -0x9E3779B9,0x3C6EF373, -0x78DDE6E6,0xF1BBCDCC, -0xE3779B99,0xC6EF3733, -0x8DDE6E67,0x1BBCDCCF, -0x3779B99E,0x6EF3733C, -0xDDE6E678,0xBBCDCCF1, -0x779B99E3,0xEF3733C6, -0xDE6E678D,0xBCDCCF1B -}; - -#define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255]) - -#define F(L1, L2, R1, R2, K1, K2) \ - T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \ - T = G( G(T2 + (R1 ^ K1)) + T2); \ - L2 ^= T; \ - L1 ^= (T + G(T2 + (R1 ^ K1))); \ - - /** - Initialize the SEED block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int i; - ulong32 tmp, k1, k2, k3, k4; - - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 16 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - /* load key */ - LOAD32H(k1, key); - LOAD32H(k2, key+4); - LOAD32H(k3, key+8); - LOAD32H(k4, key+12); - - for (i = 0; i < 16; i++) { - skey->kseed.K[2*i+0] = G(k1 + k3 - KCi[i]); - skey->kseed.K[2*i+1] = G(k2 - k4 + KCi[i]); - if (i&1) { - tmp = k3; - k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF; - k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF; - } else { - tmp = k1; - k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF; - k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF; - } - /* reverse keys for decrypt */ - skey->kseed.dK[2*(15-i)+0] = skey->kseed.K[2*i+0]; - skey->kseed.dK[2*(15-i)+1] = skey->kseed.K[2*i+1]; - } - - return CRYPT_OK; -} - -static void rounds(ulong32 *P, const ulong32 *K) -{ - ulong32 T, T2; - int i; - for (i = 0; i < 16; i += 2) { - F(P[0], P[1], P[2], P[3], K[0], K[1]); - F(P[2], P[3], P[0], P[1], K[2], K[3]); - K += 4; - } -} - -/** - Encrypts a block of text with SEED - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 P[4]; - LOAD32H(P[0], pt); - LOAD32H(P[1], pt+4); - LOAD32H(P[2], pt+8); - LOAD32H(P[3], pt+12); - rounds(P, skey->kseed.K); - STORE32H(P[2], ct); - STORE32H(P[3], ct+4); - STORE32H(P[0], ct+8); - STORE32H(P[1], ct+12); - return CRYPT_OK; -} - -/** - Decrypts a block of text with SEED - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 P[4]; - LOAD32H(P[0], ct); - LOAD32H(P[1], ct+4); - LOAD32H(P[2], ct+8); - LOAD32H(P[3], ct+12); - rounds(P, skey->kseed.dK); - STORE32H(P[2], pt); - STORE32H(P[3], pt+4); - STORE32H(P[0], pt+8); - STORE32H(P[1], pt+12); - return CRYPT_OK; -} - -/** Terminate the context - @param skey The scheduled key -*/ -void kseed_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Performs a self-test of the SEED block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int kseed_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct test { - unsigned char pt[16], ct[16], key[16]; - } tests[] = { - -{ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, - { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB }, - { 0 }, -}, - -{ - { 0 }, - { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 }, - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, -}, - -{ - { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D }, - { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A }, - { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 }, -}, - -{ - { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 }, - { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 }, - { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 }, -} -}; - int x; - unsigned char buf[2][16]; - symmetric_key skey; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - kseed_setup(tests[x].key, 16, 0, &skey); - kseed_ecb_encrypt(tests[x].pt, buf[0], &skey); - kseed_ecb_decrypt(buf[0], buf[1], &skey); - if (compare_testvector(buf[0], 16, tests[x].ct, 16, "KSEED Encrypt", x) || - compare_testvector(buf[1], 16, tests[x].pt, 16, "KSEED Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int kseed_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize >= 16) { - *keysize = 16; - } else { - return CRYPT_INVALID_KEYSIZE; - } - return CRYPT_OK; -} - -#undef G -#undef F - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/multi2.c b/Sources/DataLiteC/libtomcrypt/ciphers/multi2.c deleted file mode 100644 index 2ef7ff0..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/multi2.c +++ /dev/null @@ -1,309 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file multi2.c - Multi-2 implementation (not public domain, hence the default disable) -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_MULTI2 - -static void s_pi1(ulong32 *p) -{ - p[1] ^= p[0]; -} - -static void s_pi2(ulong32 *p, const ulong32 *k) -{ - ulong32 t; - t = (p[1] + k[0]) & 0xFFFFFFFFUL; - t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL; - t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL; - p[0] ^= t; -} - -static void s_pi3(ulong32 *p, const ulong32 *k) -{ - ulong32 t; - t = p[0] + k[1]; - t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; - t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL; - t = (t + k[2]) & 0xFFFFFFFFUL; - t = (ROL(t, 1) - t) & 0xFFFFFFFFUL; - t = ROL(t, 16) ^ (p[0] | t); - p[1] ^= t; -} - -static void s_pi4(ulong32 *p, const ulong32 *k) -{ - ulong32 t; - t = (p[1] + k[3]) & 0xFFFFFFFFUL; - t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; - p[0] ^= t; -} - -static void s_setup(const ulong32 *dk, const ulong32 *k, ulong32 *uk) -{ - int n, t; - ulong32 p[2]; - - p[0] = dk[0]; p[1] = dk[1]; - - t = 4; - n = 0; - s_pi1(p); - s_pi2(p, k); - uk[n++] = p[0]; - s_pi3(p, k); - uk[n++] = p[1]; - s_pi4(p, k); - uk[n++] = p[0]; - s_pi1(p); - uk[n++] = p[1]; - s_pi2(p, k+t); - uk[n++] = p[0]; - s_pi3(p, k+t); - uk[n++] = p[1]; - s_pi4(p, k+t); - uk[n++] = p[0]; - s_pi1(p); - uk[n++] = p[1]; -} - -static void s_encrypt(ulong32 *p, int N, const ulong32 *uk) -{ - int n, t; - for (t = n = 0; ; ) { - s_pi1(p); if (++n == N) break; - s_pi2(p, uk+t); if (++n == N) break; - s_pi3(p, uk+t); if (++n == N) break; - s_pi4(p, uk+t); if (++n == N) break; - t ^= 4; - } -} - -static void s_decrypt(ulong32 *p, int N, const ulong32 *uk) -{ - int n, t; - for (t = 4*(((N-1)>>2)&1), n = N; ; ) { - switch (n<=4 ? n : ((n-1)%4)+1) { - case 4: s_pi4(p, uk+t); --n; /* FALLTHROUGH */ - case 3: s_pi3(p, uk+t); --n; /* FALLTHROUGH */ - case 2: s_pi2(p, uk+t); --n; /* FALLTHROUGH */ - case 1: s_pi1(p); --n; break; - case 0: return; - } - t ^= 4; - } -} - -const struct ltc_cipher_descriptor multi2_desc = { - "multi2", - 22, - 40, 40, 8, 128, - &multi2_setup, - &multi2_ecb_encrypt, - &multi2_ecb_decrypt, - &multi2_test, - &multi2_done, - &multi2_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - ulong32 sk[8], dk[2]; - int x; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 40) return CRYPT_INVALID_KEYSIZE; - if (num_rounds == 0) num_rounds = 128; - - skey->multi2.N = num_rounds; - for (x = 0; x < 8; x++) { - LOAD32H(sk[x], key + x*4); - } - LOAD32H(dk[0], key + 32); - LOAD32H(dk[1], key + 36); - s_setup(dk, sk, skey->multi2.uk); - - zeromem(sk, sizeof(sk)); - zeromem(dk, sizeof(dk)); - return CRYPT_OK; -} - -/** - Encrypts a block of text with multi2 - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 p[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(p[0], pt); - LOAD32H(p[1], pt+4); - s_encrypt(p, skey->multi2.N, skey->multi2.uk); - STORE32H(p[0], ct); - STORE32H(p[1], ct+4); - return CRYPT_OK; -} - -/** - Decrypts a block of text with multi2 - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 p[2]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - LOAD32H(p[0], ct); - LOAD32H(p[1], ct+4); - s_decrypt(p, skey->multi2.N, skey->multi2.uk); - STORE32H(p[0], pt); - STORE32H(p[1], pt+4); - return CRYPT_OK; -} - -/** - Performs a self-test of the multi2 block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int multi2_test(void) -{ - static const struct { - unsigned char key[40]; - unsigned char pt[8], ct[8]; - int rounds; - } tests[] = { -{ - { - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x01, 0x23, 0x45, 0x67, - 0x89, 0xAB, 0xCD, 0xEF - }, - { - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - }, - { - 0xf8, 0x94, 0x40, 0x84, - 0x5e, 0x11, 0xcf, 0x89 - }, - 128, -}, -{ - { - 0x35, 0x91, 0x9d, 0x96, - 0x07, 0x02, 0xe2, 0xce, - 0x8d, 0x0b, 0x58, 0x3c, - 0xc9, 0xc8, 0x9d, 0x59, - 0xa2, 0xae, 0x96, 0x4e, - 0x87, 0x82, 0x45, 0xed, - 0x3f, 0x2e, 0x62, 0xd6, - 0x36, 0x35, 0xd0, 0x67, - - 0xb1, 0x27, 0xb9, 0x06, - 0xe7, 0x56, 0x22, 0x38, - }, - { - 0x1f, 0xb4, 0x60, 0x60, - 0xd0, 0xb3, 0x4f, 0xa5 - }, - { - 0xca, 0x84, 0xa9, 0x34, - 0x75, 0xc8, 0x60, 0xe5 - }, - 216, -} -}; - unsigned char buf[8]; - symmetric_key skey; - int err, x; - - for (x = 1; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) { - return err; - } - if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - for (x = 128; x < 256; ++x) { - unsigned char ct[8]; - - if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) { - return err; - } - if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) { - return err; - } - if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - return CRYPT_OK; -} - -/** Terminate the context - @param skey The scheduled key -*/ -void multi2_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int multi2_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize >= 40) { - *keysize = 40; - } else { - return CRYPT_INVALID_KEYSIZE; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/noekeon.c b/Sources/DataLiteC/libtomcrypt/ciphers/noekeon.c deleted file mode 100644 index e5b4ded..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/noekeon.c +++ /dev/null @@ -1,324 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @file noekeon.c - Implementation of the Noekeon block cipher by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_NOEKEON - -const struct ltc_cipher_descriptor noekeon_desc = -{ - "noekeon", - 16, - 16, 16, 16, 16, - &noekeon_setup, - &noekeon_ecb_encrypt, - &noekeon_ecb_decrypt, - &noekeon_test, - &noekeon_done, - &noekeon_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const ulong32 RC[] = { - 0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL, - 0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL, - 0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL, - 0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL, - 0x000000d4UL -}; - -#define kTHETA(a, b, c, d) \ - temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ - b ^= temp; d ^= temp; \ - temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ - a ^= temp; c ^= temp; - -#define THETA(k, a, b, c, d) \ - temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ - b ^= temp ^ k[1]; d ^= temp ^ k[3]; \ - temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ - a ^= temp ^ k[0]; c ^= temp ^ k[2]; - -#define GAMMA(a, b, c, d) \ - b ^= ~(d|c); \ - a ^= c&b; \ - temp = d; d = a; a = temp;\ - c ^= a ^ b ^ d; \ - b ^= ~(d|c); \ - a ^= c&b; - -#define PI1(a, b, c, d) \ - b = ROLc(b, 1); c = ROLc(c, 5); d = ROLc(d, 2); - -#define PI2(a, b, c, d) \ - b = RORc(b, 1); c = RORc(c, 5); d = RORc(d, 2); - - /** - Initialize the Noekeon block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - ulong32 temp; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 16 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - LOAD32H(skey->noekeon.K[0],&key[0]); - LOAD32H(skey->noekeon.K[1],&key[4]); - LOAD32H(skey->noekeon.K[2],&key[8]); - LOAD32H(skey->noekeon.K[3],&key[12]); - - LOAD32H(skey->noekeon.dK[0],&key[0]); - LOAD32H(skey->noekeon.dK[1],&key[4]); - LOAD32H(skey->noekeon.dK[2],&key[8]); - LOAD32H(skey->noekeon.dK[3],&key[12]); - - kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]); - - return CRYPT_OK; -} - -/** - Encrypts a block of text with Noekeon - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d,temp; - int r; - - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]); - LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]); - -#define ROUND(i) \ - a ^= RC[i]; \ - THETA(skey->noekeon.K, a,b,c,d); \ - PI1(a,b,c,d); \ - GAMMA(a,b,c,d); \ - PI2(a,b,c,d); - - for (r = 0; r < 16; ++r) { - ROUND(r); - } - -#undef ROUND - - a ^= RC[16]; - THETA(skey->noekeon.K, a, b, c, d); - - STORE32H(a,&ct[0]); STORE32H(b,&ct[4]); - STORE32H(c,&ct[8]); STORE32H(d,&ct[12]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_noekeon_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(ulong32) * 5 + sizeof(int)); - return err; -} -#endif - -/** - Decrypts a block of text with Noekeon - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d, temp; - int r; - - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]); - LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]); - - -#define ROUND(i) \ - THETA(skey->noekeon.dK, a,b,c,d); \ - a ^= RC[i]; \ - PI1(a,b,c,d); \ - GAMMA(a,b,c,d); \ - PI2(a,b,c,d); - - for (r = 16; r > 0; --r) { - ROUND(r); - } - -#undef ROUND - - THETA(skey->noekeon.dK, a,b,c,d); - a ^= RC[0]; - STORE32H(a,&pt[0]); STORE32H(b, &pt[4]); - STORE32H(c,&pt[8]); STORE32H(d, &pt[12]); - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_noekeon_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(ulong32) * 5 + sizeof(int)); - return err; -} -#endif - -/** - Performs a self-test of the Noekeon block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int noekeon_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen; - unsigned char key[16], pt[16], ct[16]; - } tests[] = { - { - 16, - { 0xAA, 0x3C, 0x8C, 0x86, 0xD9, 0x8B, 0xF8, 0xBE, 0x21, 0xE0, 0x36, 0x09, 0x78, 0xFB, 0xE4, 0x90 }, - { 0xE4, 0x96, 0x6C, 0xD3, 0x13, 0xA0, 0x6C, 0xAF, 0xD0, 0x23, 0xC9, 0xFD, 0x45, 0x32, 0x23, 0x16 }, - { 0xA6, 0xEC, 0xB8, 0xA8, 0x61, 0xFD, 0x62, 0xD9, 0x13, 0x02, 0xFE, 0x9E, 0x47, 0x01, 0x3F, 0xC3 } - }, - { - 16, - { 0xED, 0x43, 0xD1, 0x87, 0x21, 0x7E, 0xE0, 0x97, 0x3D, 0x76, 0xC3, 0x37, 0x2E, 0x7D, 0xAE, 0xD3 }, - { 0xE3, 0x38, 0x32, 0xCC, 0xF2, 0x2F, 0x2F, 0x0A, 0x4A, 0x8B, 0x8F, 0x18, 0x12, 0x20, 0x17, 0xD3 }, - { 0x94, 0xA5, 0xDF, 0xF5, 0xAE, 0x1C, 0xBB, 0x22, 0xAD, 0xEB, 0xA7, 0x0D, 0xB7, 0x82, 0x90, 0xA0 } - }, - { - 16, - { 0x6F, 0xDC, 0x23, 0x38, 0xF2, 0x10, 0xFB, 0xD3, 0xC1, 0x8C, 0x02, 0xF6, 0xB4, 0x6A, 0xD5, 0xA8 }, - { 0xDB, 0x29, 0xED, 0xB5, 0x5F, 0xB3, 0x60, 0x3A, 0x92, 0xA8, 0xEB, 0x9C, 0x6D, 0x9D, 0x3E, 0x8F }, - { 0x78, 0xF3, 0x6F, 0xF8, 0x9E, 0xBB, 0x8C, 0x6A, 0xE8, 0x10, 0xF7, 0x00, 0x22, 0x15, 0x30, 0x3D } - }, - { - 16, - { 0x2C, 0x0C, 0x02, 0xEF, 0x6B, 0xC4, 0xF2, 0x0B, 0x2E, 0xB9, 0xE0, 0xBF, 0xD9, 0x36, 0xC2, 0x4E }, - { 0x84, 0xE2, 0xFE, 0x64, 0xB1, 0xB9, 0xFE, 0x76, 0xA8, 0x3F, 0x45, 0xC7, 0x40, 0x7A, 0xAF, 0xEE }, - { 0x2A, 0x08, 0xD6, 0xA2, 0x1C, 0x63, 0x08, 0xB0, 0xF8, 0xBC, 0xB3, 0xA1, 0x66, 0xF7, 0xAE, 0xCF } - }, - { - 16, - { 0x6F, 0x30, 0xF8, 0x9F, 0xDA, 0x6E, 0xA0, 0x91, 0x04, 0x0F, 0x6C, 0x8B, 0x7D, 0xF7, 0x2A, 0x4B }, - { 0x65, 0xB6, 0xA6, 0xD0, 0x42, 0x14, 0x08, 0x60, 0x34, 0x8D, 0x37, 0x2F, 0x01, 0xF0, 0x46, 0xBE }, - { 0x66, 0xAC, 0x0B, 0x62, 0x1D, 0x68, 0x11, 0xF5, 0x27, 0xB1, 0x13, 0x5D, 0xF3, 0x2A, 0xE9, 0x18 } - }, - { - 16, - { 0xCA, 0xA4, 0x16, 0xB7, 0x1C, 0x92, 0x2E, 0xAD, 0xEB, 0xA7, 0xDB, 0x69, 0x92, 0xCB, 0x35, 0xEF }, - { 0x81, 0x6F, 0x8E, 0x4D, 0x96, 0xC6, 0xB3, 0x67, 0x83, 0xF5, 0x63, 0xC7, 0x20, 0x6D, 0x40, 0x23 }, - { 0x44, 0xF7, 0x63, 0x62, 0xF0, 0x43, 0xBB, 0x67, 0x4A, 0x75, 0x12, 0x42, 0x46, 0x29, 0x28, 0x19 } - }, - { - 16, - { 0x6B, 0xCF, 0x22, 0x2F, 0xE0, 0x1B, 0xB0, 0xAA, 0xD8, 0x3C, 0x91, 0x99, 0x18, 0xB2, 0x28, 0xE8 }, - { 0x7C, 0x37, 0xC7, 0xD0, 0xAC, 0x92, 0x29, 0xF1, 0x60, 0x82, 0x93, 0x89, 0xAA, 0x61, 0xAA, 0xA9 }, - { 0xE5, 0x89, 0x1B, 0xB3, 0xFE, 0x8B, 0x0C, 0xA1, 0xA6, 0xC7, 0xBE, 0x12, 0x73, 0x0F, 0xC1, 0x19 } - }, - { - 16, - { 0xE6, 0xD0, 0xF1, 0x03, 0x2E, 0xDE, 0x70, 0x8D, 0xD8, 0x9E, 0x36, 0x5C, 0x05, 0x52, 0xE7, 0x0D }, - { 0xE2, 0x42, 0xE7, 0x92, 0x0E, 0xF7, 0x82, 0xA2, 0xB8, 0x21, 0x8D, 0x26, 0xBA, 0x2D, 0xE6, 0x32 }, - { 0x1E, 0xDD, 0x75, 0x22, 0xB9, 0x36, 0x8A, 0x0F, 0x32, 0xFD, 0xD4, 0x48, 0x65, 0x12, 0x5A, 0x2F } - } - }; - symmetric_key key; - unsigned char tmp[2][16]; - int err, i, y; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - zeromem(&key, sizeof(key)); - if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - - noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key); - noekeon_ecb_decrypt(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Noekeon Encrypt", i) || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "Noekeon Decrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void noekeon_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int noekeon_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - -#undef kTHETA -#undef THETA -#undef GAMMA -#undef PI1 -#undef PI2 -#undef ROUND - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/rc2.c b/Sources/DataLiteC/libtomcrypt/ciphers/rc2.c deleted file mode 100644 index 4832424..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/rc2.c +++ /dev/null @@ -1,408 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/**********************************************************************\ -* To commemorate the 1996 RSA Data Security Conference, the following * -* code is released into the public domain by its author. Prost! * -* * -* This cipher uses 16-bit words and little-endian byte ordering. * -* I wonder which processor it was optimized for? * -* * -* Thanks to CodeView, SoftIce, and D86 for helping bring this code to * -* the public. * -\**********************************************************************/ -#include "tomcrypt_private.h" - -/** - @file rc2.c - Implementation of RC2 with fixed effective key length of 64bits -*/ - -#ifdef LTC_RC2 - -const struct ltc_cipher_descriptor rc2_desc = { - "rc2", - 12, 8, 128, 8, 16, - &rc2_setup, - &rc2_ecb_encrypt, - &rc2_ecb_decrypt, - &rc2_test, - &rc2_done, - &rc2_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -/* 256-entry permutation table, probably derived somehow from pi */ -static const unsigned char permute[256] = { - 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, - 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, - 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, - 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, - 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, - 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, - 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, - 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, - 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, - 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, - 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, - 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, - 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, - 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, - 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, - 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 -}; - - /** - Initialize the RC2 block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param bits The effective key length in bits - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey) -{ - unsigned *xkey = skey->rc2.xkey; - unsigned char tmp[128]; - unsigned T8, TM; - int i; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen == 0 || keylen > 128 || bits > 1024) { - return CRYPT_INVALID_KEYSIZE; - } - if (bits == 0) { - bits = 1024; - } - - if (num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - - for (i = 0; i < keylen; i++) { - tmp[i] = key[i] & 255; - } - - /* Phase 1: Expand input key to 128 bytes */ - if (keylen < 128) { - for (i = keylen; i < 128; i++) { - tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; - } - } - - /* Phase 2 - reduce effective key size to "bits" */ - T8 = (unsigned)(bits+7)>>3; - TM = (255 >> (unsigned)(7 & -bits)); - tmp[128 - T8] = permute[tmp[128 - T8] & TM]; - for (i = 127 - T8; i >= 0; i--) { - tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; - } - - /* Phase 3 - copy to xkey in little-endian order */ - for (i = 0; i < 64; i++) { - xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8); - } - -#ifdef LTC_CLEAN_STACK - zeromem(tmp, sizeof(tmp)); -#endif - - return CRYPT_OK; -} - -/** - Initialize the RC2 block cipher - - The effective key length is here always keylen * 8 - - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful -*/ -int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey); -} - -/**********************************************************************\ -* Encrypt an 8-byte block of plaintext using the given key. * -\**********************************************************************/ -/** - Encrypts a block of text with RC2 - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc2_ecb_encrypt( const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -#else -int rc2_ecb_encrypt( const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -#endif -{ - const unsigned *xkey; - unsigned x76, x54, x32, x10, i; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - xkey = skey->rc2.xkey; - - x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6]; - x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4]; - x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2]; - x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0]; - - for (i = 0; i < 16; i++) { - x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; - x10 = ((x10 << 1) | (x10 >> 15)); - - x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; - x32 = ((x32 << 2) | (x32 >> 14)); - - x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; - x54 = ((x54 << 3) | (x54 >> 13)); - - x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; - x76 = ((x76 << 5) | (x76 >> 11)); - - if (i == 4 || i == 10) { - x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; - x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; - x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; - x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; - } - } - - ct[0] = (unsigned char)x10; - ct[1] = (unsigned char)(x10 >> 8); - ct[2] = (unsigned char)x32; - ct[3] = (unsigned char)(x32 >> 8); - ct[4] = (unsigned char)x54; - ct[5] = (unsigned char)(x54 >> 8); - ct[6] = (unsigned char)x76; - ct[7] = (unsigned char)(x76 >> 8); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc2_ecb_encrypt( const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -{ - int err = s_rc2_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5); - return err; -} -#endif - -/**********************************************************************\ -* Decrypt an 8-byte block of ciphertext using the given key. * -\**********************************************************************/ -/** - Decrypts a block of text with RC2 - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc2_ecb_decrypt( const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -#else -int rc2_ecb_decrypt( const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -#endif -{ - unsigned x76, x54, x32, x10; - const unsigned *xkey; - int i; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - xkey = skey->rc2.xkey; - - x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6]; - x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4]; - x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2]; - x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0]; - - for (i = 15; i >= 0; i--) { - if (i == 4 || i == 10) { - x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; - x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; - x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; - x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; - } - - x76 = ((x76 << 11) | (x76 >> 5)); - x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; - - x54 = ((x54 << 13) | (x54 >> 3)); - x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; - - x32 = ((x32 << 14) | (x32 >> 2)); - x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; - - x10 = ((x10 << 15) | (x10 >> 1)); - x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; - } - - pt[0] = (unsigned char)x10; - pt[1] = (unsigned char)(x10 >> 8); - pt[2] = (unsigned char)x32; - pt[3] = (unsigned char)(x32 >> 8); - pt[4] = (unsigned char)x54; - pt[5] = (unsigned char)(x54 >> 8); - pt[6] = (unsigned char)x76; - pt[7] = (unsigned char)(x76 >> 8); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc2_ecb_decrypt( const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -{ - int err = s_rc2_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int)); - return err; -} -#endif - -/** - Performs a self-test of the RC2 block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int rc2_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen, bits; - unsigned char key[16], pt[8], ct[8]; - } tests[] = { - - { 8, 63, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff } - }, - { 8, 64, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 } - }, - { 8, 64, - { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 } - }, - { 1, 64, - { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 } - }, - { 7, 64, - { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f } - }, - { 16, 64, - { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, - 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 } - }, - { 16, 128, - { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, - 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 } - } - }; - int x, y, err; - symmetric_key skey; - unsigned char tmp[2][8]; - - for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { - zeromem(tmp, sizeof(tmp)); - if (tests[x].bits == (tests[x].keylen * 8)) { - if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { - return err; - } - } - else { - if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) { - return err; - } - } - - rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey); - rc2_ecb_decrypt(tmp[0], tmp[1], &skey); - - if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) || - compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void rc2_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int rc2_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 1) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 128) { - *keysize = 128; - } - return CRYPT_OK; -} - -#endif - - - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/rc5.c b/Sources/DataLiteC/libtomcrypt/ciphers/rc5.c deleted file mode 100644 index 4f01fc0..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/rc5.c +++ /dev/null @@ -1,326 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file rc5.c - LTC_RC5 code by Tom St Denis -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_RC5 - -const struct ltc_cipher_descriptor rc5_desc = -{ - "rc5", - 2, - 8, 128, 8, 12, - &rc5_setup, - &rc5_ecb_encrypt, - &rc5_ecb_decrypt, - &rc5_test, - &rc5_done, - &rc5_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define stab rc5_stab -static const ulong32 stab[50] = { -0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, -0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, -0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, -0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, -0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, -0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL, -0x62482413UL, 0x007f9dccUL -}; - - /** - Initialize the LTC_RC5 block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -#ifdef LTC_CLEAN_STACK -static int s_rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#else -int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#endif -{ - ulong32 L[64], *S, A, B, i, j, v, s, t, l; - - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(key != NULL); - - /* test parameters */ - if (num_rounds == 0) { - num_rounds = rc5_desc.default_rounds; - } - - if (num_rounds < 12 || num_rounds > 24) { - return CRYPT_INVALID_ROUNDS; - } - - /* key must be between 64 and 1024 bits */ - if (keylen < 8 || keylen > 128) { - return CRYPT_INVALID_KEYSIZE; - } - - skey->rc5.rounds = num_rounds; - S = skey->rc5.K; - - /* copy the key into the L array */ - for (A = i = j = 0; i < (ulong32)keylen; ) { - A = (A << 8) | ((ulong32)(key[i++] & 255)); - if ((i & 3) == 0) { - L[j++] = BSWAP(A); - A = 0; - } - } - - if ((keylen & 3) != 0) { - A <<= (ulong32)((8 * (4 - (keylen&3)))); - L[j++] = BSWAP(A); - } - - /* setup the S array */ - t = (ulong32)(2 * (num_rounds + 1)); - XMEMCPY(S, stab, t * sizeof(*S)); - - /* mix buffer */ - s = 3 * MAX(t, j); - l = j; - for (A = B = i = j = v = 0; v < s; v++) { - A = S[i] = ROLc(S[i] + A + B, 3); - B = L[j] = ROL(L[j] + A + B, (A+B)); - if (++i == t) { i = 0; } - if (++j == l) { j = 0; } - } - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int x; - x = s_rc5_setup(key, keylen, num_rounds, skey); - burn_stack(sizeof(ulong32) * 122 + sizeof(int)); - return x; -} -#endif - -/** - Encrypts a block of text with LTC_RC5 - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 A, B; - const ulong32 *K; - int r; - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { - return CRYPT_INVALID_ROUNDS; - } - - LOAD32L(A, &pt[0]); - LOAD32L(B, &pt[4]); - A += skey->rc5.K[0]; - B += skey->rc5.K[1]; - K = skey->rc5.K + 2; - - if ((skey->rc5.rounds & 1) == 0) { - for (r = 0; r < skey->rc5.rounds; r += 2) { - A = ROL(A ^ B, B) + K[0]; - B = ROL(B ^ A, A) + K[1]; - A = ROL(A ^ B, B) + K[2]; - B = ROL(B ^ A, A) + K[3]; - K += 4; - } - } else { - for (r = 0; r < skey->rc5.rounds; r++) { - A = ROL(A ^ B, B) + K[0]; - B = ROL(B ^ A, A) + K[1]; - K += 2; - } - } - STORE32L(A, &ct[0]); - STORE32L(B, &ct[4]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_rc5_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(ulong32) * 2 + sizeof(int)); - return err; -} -#endif - -/** - Decrypts a block of text with LTC_RC5 - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 A, B; - const ulong32 *K; - int r; - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { - return CRYPT_INVALID_ROUNDS; - } - - LOAD32L(A, &ct[0]); - LOAD32L(B, &ct[4]); - K = skey->rc5.K + (skey->rc5.rounds << 1); - - if ((skey->rc5.rounds & 1) == 0) { - K -= 2; - for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) { - B = ROR(B - K[3], A) ^ A; - A = ROR(A - K[2], B) ^ B; - B = ROR(B - K[1], A) ^ A; - A = ROR(A - K[0], B) ^ B; - K -= 4; - } - } else { - for (r = skey->rc5.rounds - 1; r >= 0; r--) { - B = ROR(B - K[1], A) ^ A; - A = ROR(A - K[0], B) ^ B; - K -= 2; - } - } - A -= skey->rc5.K[0]; - B -= skey->rc5.K[1]; - STORE32L(A, &pt[0]); - STORE32L(B, &pt[4]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_rc5_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(ulong32) * 2 + sizeof(int)); - return err; -} -#endif - -/** - Performs a self-test of the LTC_RC5 block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int rc5_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - unsigned char key[16], pt[8], ct[8]; - } tests[] = { - { - { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51, - 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 }, - { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d }, - { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 } - }, - { - { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f, - 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 }, - { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 }, - { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } - }, - { - { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f, - 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf }, - { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }, - { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc } - } - }; - unsigned char tmp[2][8]; - int x, y, err; - symmetric_key key; - - for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { - /* setup key */ - if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) { - return err; - } - - /* encrypt and decrypt */ - rc5_ecb_encrypt(tests[x].pt, tmp[0], &key); - rc5_ecb_decrypt(tmp[0], tmp[1], &key); - - /* compare */ - if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC5 Encrypt", x) != 0 || - compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC5 Decrypt", x) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void rc5_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int rc5_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 8) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 128) { - *keysize = 128; - } - return CRYPT_OK; -} - -#undef stab - -#endif - - - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/rc6.c b/Sources/DataLiteC/libtomcrypt/ciphers/rc6.c deleted file mode 100644 index 06c52aa..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/rc6.c +++ /dev/null @@ -1,326 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file rc6.c - LTC_RC6 code by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_RC6 - -const struct ltc_cipher_descriptor rc6_desc = -{ - "rc6", - 3, - 8, 128, 16, 20, - &rc6_setup, - &rc6_ecb_encrypt, - &rc6_ecb_decrypt, - &rc6_test, - &rc6_done, - &rc6_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define stab rc6_stab -static const ulong32 stab[44] = { -0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, -0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, -0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, -0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, -0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, -0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL }; - - /** - Initialize the LTC_RC6 block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -#ifdef LTC_CLEAN_STACK -static int s_rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#else -int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#endif -{ - ulong32 L[64], S[50], A, B, i, j, v, s, l; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* test parameters */ - if (num_rounds != 0 && num_rounds != 20) { - return CRYPT_INVALID_ROUNDS; - } - - /* key must be between 64 and 1024 bits */ - if (keylen < 8 || keylen > 128) { - return CRYPT_INVALID_KEYSIZE; - } - - /* copy the key into the L array */ - for (A = i = j = 0; i < (ulong32)keylen; ) { - A = (A << 8) | ((ulong32)(key[i++] & 255)); - if (!(i & 3)) { - L[j++] = BSWAP(A); - A = 0; - } - } - - /* handle odd sized keys */ - if (keylen & 3) { - A <<= (8 * (4 - (keylen&3))); - L[j++] = BSWAP(A); - } - - /* setup the S array */ - XMEMCPY(S, stab, 44 * sizeof(stab[0])); - - /* mix buffer */ - s = 3 * MAX(44, j); - l = j; - for (A = B = i = j = v = 0; v < s; v++) { - A = S[i] = ROLc(S[i] + A + B, 3); - B = L[j] = ROL(L[j] + A + B, (A+B)); - if (++i == 44) { i = 0; } - if (++j == l) { j = 0; } - } - - /* copy to key */ - for (i = 0; i < 44; i++) { - skey->rc6.K[i] = S[i]; - } - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int x; - x = s_rc6_setup(key, keylen, num_rounds, skey); - burn_stack(sizeof(ulong32) * 122); - return x; -} -#endif - -/** - Encrypts a block of text with LTC_RC6 - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d,t,u; - const ulong32 *K; - int r; - - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); - - b += skey->rc6.K[0]; - d += skey->rc6.K[1]; - -#define RND(a,b,c,d) \ - t = (b * (b + b + 1)); t = ROLc(t, 5); \ - u = (d * (d + d + 1)); u = ROLc(u, 5); \ - a = ROL(a^t,u) + K[0]; \ - c = ROL(c^u,t) + K[1]; K += 2; - - K = skey->rc6.K + 2; - for (r = 0; r < 20; r += 4) { - RND(a,b,c,d); - RND(b,c,d,a); - RND(c,d,a,b); - RND(d,a,b,c); - } - -#undef RND - - a += skey->rc6.K[42]; - c += skey->rc6.K[43]; - STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_rc6_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(ulong32) * 6 + sizeof(int)); - return err; -} -#endif - -/** - Decrypts a block of text with LTC_RC6 - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled -*/ -#ifdef LTC_CLEAN_STACK -static int s_rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d,t,u; - const ulong32 *K; - int r; - - LTC_ARGCHK(skey != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); - a -= skey->rc6.K[42]; - c -= skey->rc6.K[43]; - -#define RND(a,b,c,d) \ - t = (b * (b + b + 1)); t = ROLc(t, 5); \ - u = (d * (d + d + 1)); u = ROLc(u, 5); \ - c = ROR(c - K[1], t) ^ u; \ - a = ROR(a - K[0], u) ^ t; K -= 2; - - K = skey->rc6.K + 40; - - for (r = 0; r < 20; r += 4) { - RND(d,a,b,c); - RND(c,d,a,b); - RND(b,c,d,a); - RND(a,b,c,d); - } - -#undef RND - - b -= skey->rc6.K[0]; - d -= skey->rc6.K[1]; - STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_rc6_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(ulong32) * 6 + sizeof(int)); - return err; -} -#endif - -/** - Performs a self-test of the LTC_RC6 block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int rc6_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { - 16, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, - 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, - { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23, - 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 } - }, - { - 24, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, - 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, - 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, - { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04, - 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 } - }, - { - 32, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, - 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, - 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }, - { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, - 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, - { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89, - 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 } - } - }; - unsigned char tmp[2][16]; - int x, y, err; - symmetric_key key; - - for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { - /* setup key */ - if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - - /* encrypt and decrypt */ - rc6_ecb_encrypt(tests[x].pt, tmp[0], &key); - rc6_ecb_decrypt(tmp[0], tmp[1], &key); - - /* compare */ - if (compare_testvector(tmp[0], 16, tests[x].ct, 16, "RC6 Encrypt", x) || - compare_testvector(tmp[1], 16, tests[x].pt, 16, "RC6 Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) rc6_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) rc6_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void rc6_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int rc6_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 8) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 128) { - *keysize = 128; - } - return CRYPT_OK; -} - -#undef RND -#undef stab - -#endif /*LTC_RC6*/ diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer.c b/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer.c deleted file mode 100644 index f0c4a6b..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer.c +++ /dev/null @@ -1,489 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/******************************************************************************* -* -* FILE: safer.c -* -* LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption -* Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128, -* LTC_SAFER SK-64 and LTC_SAFER SK-128. -* -* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) -* Signal and Information Processing Laboratory -* Swiss Federal Institute of Technology -* CH-8092 Zuerich, Switzerland -* -* DATE: September 9, 1995 -* -* CHANGE HISTORY: -* -*******************************************************************************/ - -#include "tomcrypt_private.h" - -#ifdef LTC_SAFER - -#ifndef LTC_SAFER_TAB_C -#define LTC_SAFER_TAB_C -#include "safer_tab.c" -#endif - -const struct ltc_cipher_descriptor safer_k64_desc = { - "safer-k64", - 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS, - &safer_k64_setup, - &safer_ecb_encrypt, - &safer_ecb_decrypt, - &safer_k64_test, - &safer_done, - &safer_64_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }, - - safer_sk64_desc = { - "safer-sk64", - 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS, - &safer_sk64_setup, - &safer_ecb_encrypt, - &safer_ecb_decrypt, - &safer_sk64_test, - &safer_done, - &safer_64_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }, - - safer_k128_desc = { - "safer-k128", - 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS, - &safer_k128_setup, - &safer_ecb_encrypt, - &safer_ecb_decrypt, - &safer_sk128_test, - &safer_done, - &safer_128_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }, - - safer_sk128_desc = { - "safer-sk128", - 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS, - &safer_sk128_setup, - &safer_ecb_encrypt, - &safer_ecb_decrypt, - &safer_sk128_test, - &safer_done, - &safer_128_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }; - -/******************* Constants ************************************************/ -/* #define TAB_LEN 256 */ - -/******************* Assertions ***********************************************/ - -/******************* Macros ***************************************************/ -#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\ - |(unsigned int)((x) & 0xFF) >> (8 - (n)))) -#define EXP(x) safer_ebox[(x) & 0xFF] -#define LOG(x) safer_lbox[(x) & 0xFF] -#define PHT(x, y) { y += x; x += y; } -#define IPHT(x, y) { x -= y; y -= x; } - -/******************* Types ****************************************************/ - -#ifdef LTC_CLEAN_STACK -static void s_safer_expand_userkey(const unsigned char *userkey_1, - const unsigned char *userkey_2, - unsigned int nof_rounds, - int strengthened, - safer_key_t key) -#else -static void safer_expand_userkey(const unsigned char *userkey_1, - const unsigned char *userkey_2, - unsigned int nof_rounds, - int strengthened, - safer_key_t key) -#endif -{ unsigned int i, j, k; - unsigned char ka[LTC_SAFER_BLOCK_LEN + 1]; - unsigned char kb[LTC_SAFER_BLOCK_LEN + 1]; - - if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) { - nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS; - } - *key++ = (unsigned char)nof_rounds; - ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; - kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; - k = 0; - for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { - ka[j] = ROL8(userkey_1[j], 5); - ka[LTC_SAFER_BLOCK_LEN] ^= ka[j]; - kb[j] = *key++ = userkey_2[j]; - kb[LTC_SAFER_BLOCK_LEN] ^= kb[j]; - } - for (i = 1; i <= nof_rounds; i++) { - for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) { - ka[j] = ROL8(ka[j], 6); - kb[j] = ROL8(kb[j], 6); - } - if (strengthened) { - k = 2 * i - 1; - while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } - } - for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { - if (strengthened) { - *key++ = (ka[k] - + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; - if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } - } else { - *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; - } - } - if (strengthened) { - k = 2 * i; - while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } - } - for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { - if (strengthened) { - *key++ = (kb[k] - + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; - if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } - } else { - *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; - } - } - } - -#ifdef LTC_CLEAN_STACK - zeromem(ka, sizeof(ka)); - zeromem(kb, sizeof(kb)); -#endif -} - -#ifdef LTC_CLEAN_STACK -static void safer_expand_userkey(const unsigned char *userkey_1, - const unsigned char *userkey_2, - unsigned int nof_rounds, - int strengthened, - safer_key_t key) -{ - s_safer_expand_userkey(userkey_1, userkey_2, nof_rounds, strengthened, key); - burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2); -} -#endif - -int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 8) { - return CRYPT_INVALID_KEYSIZE; - } - - safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); - return CRYPT_OK; -} - -int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 8) { - return CRYPT_INVALID_KEYSIZE; - } - - safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); - return CRYPT_OK; -} - -int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); - return CRYPT_OK; -} - -int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_safer_ecb_encrypt(const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -#else -int safer_ecb_encrypt(const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -#endif -{ unsigned char a, b, c, d, e, f, g, h, t; - unsigned int round; - const unsigned char *key; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - key = skey->safer.key; - a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3]; - e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7]; - if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; - while(round-- > 0) - { - a ^= *++key; b += *++key; c += *++key; d ^= *++key; - e ^= *++key; f += *++key; g += *++key; h ^= *++key; - a = EXP(a) + *++key; b = LOG(b) ^ *++key; - c = LOG(c) ^ *++key; d = EXP(d) + *++key; - e = EXP(e) + *++key; f = LOG(f) ^ *++key; - g = LOG(g) ^ *++key; h = EXP(h) + *++key; - PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); - PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); - PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); - t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; - } - a ^= *++key; b += *++key; c += *++key; d ^= *++key; - e ^= *++key; f += *++key; g += *++key; h ^= *++key; - ct[0] = a & 0xFF; ct[1] = b & 0xFF; - ct[2] = c & 0xFF; ct[3] = d & 0xFF; - ct[4] = e & 0xFF; ct[5] = f & 0xFF; - ct[6] = g & 0xFF; ct[7] = h & 0xFF; - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int safer_ecb_encrypt(const unsigned char *pt, - unsigned char *ct, - const symmetric_key *skey) -{ - int err = s_safer_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); - return err; -} -#endif - -#ifdef LTC_CLEAN_STACK -static int s_safer_ecb_decrypt(const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -#else -int safer_ecb_decrypt(const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -#endif -{ unsigned char a, b, c, d, e, f, g, h, t; - unsigned int round; - const unsigned char *key; - - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(skey != NULL); - - key = skey->safer.key; - a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3]; - e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7]; - if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; - key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round); - h ^= *key; g -= *--key; f -= *--key; e ^= *--key; - d ^= *--key; c -= *--key; b -= *--key; a ^= *--key; - while (round--) - { - t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; - IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); - IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); - IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); - h -= *--key; g ^= *--key; f ^= *--key; e -= *--key; - d -= *--key; c ^= *--key; b ^= *--key; a -= *--key; - h = LOG(h) ^ *--key; g = EXP(g) - *--key; - f = EXP(f) - *--key; e = LOG(e) ^ *--key; - d = LOG(d) ^ *--key; c = EXP(c) - *--key; - b = EXP(b) - *--key; a = LOG(a) ^ *--key; - } - pt[0] = a & 0xFF; pt[1] = b & 0xFF; - pt[2] = c & 0xFF; pt[3] = d & 0xFF; - pt[4] = e & 0xFF; pt[5] = f & 0xFF; - pt[6] = g & 0xFF; pt[7] = h & 0xFF; - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int safer_ecb_decrypt(const unsigned char *ct, - unsigned char *pt, - const symmetric_key *skey) -{ - int err = s_safer_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); - return err; -} -#endif - -int safer_64_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 8) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 8; - return CRYPT_OK; -} - -int safer_128_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - -int safer_k64_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, - k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 }, - k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 }; - - symmetric_key skey; - unsigned char buf[2][8]; - int err; - - /* test K64 */ - if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) { - return err; - } - safer_ecb_encrypt(k64_pt, buf[0], &skey); - safer_ecb_decrypt(buf[0], buf[1], &skey); - - if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 || - compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - - -int safer_sk64_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, - sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, - sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 }; - - symmetric_key skey; - unsigned char buf[2][8]; - int err, y; - - /* test SK64 */ - if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) { - return err; - } - - safer_ecb_encrypt(sk64_pt, buf[0], &skey); - safer_ecb_decrypt(buf[0], buf[1], &skey); - - if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 || - compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) buf[0][y] = 0; - for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); - for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); - for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void safer_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -int safer_sk128_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, - sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8, - 0, 0, 0, 0, 0, 0, 0, 0 }, - sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 }; - - symmetric_key skey; - unsigned char buf[2][8]; - int err, y; - - /* test SK128 */ - if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) { - return err; - } - safer_ecb_encrypt(sk128_pt, buf[0], &skey); - safer_ecb_decrypt(buf[0], buf[1], &skey); - - if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 || - compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) buf[0][y] = 0; - for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); - for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); - for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - - return CRYPT_OK; - #endif -} - -#undef ROL8 -#undef EXP -#undef LOG -#undef PHT -#undef IPHT - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer_tab.c b/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer_tab.c deleted file mode 100644 index 4cc0e47..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/safer/safer_tab.c +++ /dev/null @@ -1,54 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file safer_tab.c - Tables for LTC_SAFER block ciphers -*/ - -#ifdef LTC_SAFER_TAB_C - -/* This is the box defined by ebox[x] = 45^x mod 257. - * Its assumed that the value "256" corresponds to zero. */ -static const unsigned char safer_ebox[256] = { - 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, - 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, - 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, -255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, -241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, -129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, - 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, - 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, - 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, -249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, -193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, - 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, - 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, -128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, -253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, -225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40 -}; - -/* This is the inverse of ebox or the base 45 logarithm */ -static const unsigned char safer_lbox[256] = { -128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248, -192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130, -112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37, -201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15, - 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198, -175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84, -121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188, -189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217, -208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158, -210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42, - 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219, -164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29, - 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14, -122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104, -109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66, -184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48 -}; - -#endif /* LTC_SAFER_TAB_C */ - - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/safer/saferp.c b/Sources/DataLiteC/libtomcrypt/ciphers/safer/saferp.c deleted file mode 100644 index 6803d72..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/safer/saferp.c +++ /dev/null @@ -1,576 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file saferp.c - LTC_SAFER+ Implementation by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_SAFERP - -#ifndef LTC_SAFER_TAB_C -#define LTC_SAFER_TAB_C -#include "safer_tab.c" -#endif - -const struct ltc_cipher_descriptor saferp_desc = -{ - "safer+", - 4, - 16, 32, 16, 8, - &saferp_setup, - &saferp_ecb_encrypt, - &saferp_ecb_decrypt, - &saferp_test, - &saferp_done, - &saferp_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -/* ROUND(b,i) - * - * This is one forward key application. Note the basic form is - * key addition, substitution, key addition. The safer_ebox and safer_lbox - * are the exponentiation box and logarithm boxes respectively. - * The value of 'i' is the current round number which allows this - * function to be unrolled massively. Most of LTC_SAFER+'s speed - * comes from not having to compute indirect accesses into the - * array of 16 bytes b[0..15] which is the block of data -*/ - -#define ROUND(b, i) do { \ - b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ - b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ - b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ - b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ - b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ - b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ - b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ - b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ - b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ - b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ - b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ - b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ - b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ - b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ - b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ - b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \ -} while (0) - -/* This is one inverse key application */ -#define iROUND(b, i) do { \ - b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \ - b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \ - b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \ - b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \ - b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \ - b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \ - b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \ - b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \ - b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \ - b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \ - b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \ - b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \ - b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \ - b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \ - b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \ - b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \ -} while (0) - -/* This is a forward single layer PHT transform. */ -#define PHT(b) do { \ - b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \ - b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \ - b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \ - b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \ - b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \ - b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \ - b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \ - b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \ -} while (0) - -/* This is an inverse single layer PHT transform */ -#define iPHT(b) do { \ - b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \ - b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \ - b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \ - b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \ - b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \ - b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \ - b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \ - b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \ - } while (0) - -/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ -#define SHUF(b, b2) do { \ - b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ - b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ - b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ - b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \ -} while (0) - -/* This is the inverse shuffle. It takes from b and gives to b2 */ -#define iSHUF(b, b2) do { \ - b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ - b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ - b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ - b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \ -} while (0) - -/* The complete forward Linear Transform layer. - * Note that alternating usage of b and b2. - * Each round of LT starts in 'b' and ends in 'b2'. - */ -#define LT(b, b2) do { \ - PHT(b); SHUF(b, b2); \ - PHT(b2); SHUF(b2, b); \ - PHT(b); SHUF(b, b2); \ - PHT(b2); \ -} while (0) - -/* This is the inverse linear transform layer. */ -#define iLT(b, b2) do { \ - iPHT(b); \ - iSHUF(b, b2); iPHT(b2); \ - iSHUF(b2, b); iPHT(b); \ - iSHUF(b, b2); iPHT(b2); \ -} while (0) - -#ifdef LTC_SMALL_CODE - -static void s_round(unsigned char *b, int i, const symmetric_key *skey) -{ - ROUND(b, i); -} - -static void s_iround(unsigned char *b, int i, const symmetric_key *skey) -{ - iROUND(b, i); -} - -static void s_lt(unsigned char *b, unsigned char *b2) -{ - LT(b, b2); -} - -static void s_ilt(unsigned char *b, unsigned char *b2) -{ - iLT(b, b2); -} - -#undef ROUND -#define ROUND(b, i) s_round(b, i, skey) - -#undef iROUND -#define iROUND(b, i) s_iround(b, i, skey) - -#undef LT -#define LT(b, b2) s_lt(b, b2) - -#undef iLT -#define iLT(b, b2) s_ilt(b, b2) - -#endif - -/* These are the 33, 128-bit bias words for the key schedule */ -static const unsigned char safer_bias[33][16] = { -{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100}, -{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61}, -{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160}, -{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148}, -{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143}, -{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202}, -{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44}, -{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51}, -{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56}, -{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215}, -{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210}, -{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53}, -{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244}, -{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131}, -{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241}, -{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172}, -{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239}, -{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202}, -{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246}, -{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152}, -{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236}, -{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150}, -{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30}, -{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6}, -{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104}, -{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175}, -{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35}, -{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7}, -{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207}, -{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247}, -{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255}, -{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}}; - - /** - Initialize the LTC_SAFER+ block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - unsigned x, y, z; - unsigned char t[33]; - static const int rounds[3] = { 8, 12, 16 }; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* check arguments */ - if (keylen != 16 && keylen != 24 && keylen != 32) { - return CRYPT_INVALID_KEYSIZE; - } - - /* Is the number of rounds valid? Either use zero for default or - * 8,12,16 rounds for 16,24,32 byte keys - */ - if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) { - return CRYPT_INVALID_ROUNDS; - } - - /* 128 bit key version */ - if (keylen == 16) { - /* copy key into t */ - for (x = y = 0; x < 16; x++) { - t[x] = key[x]; - y ^= key[x]; - } - t[16] = y; - - /* make round keys */ - for (x = 0; x < 16; x++) { - skey->saferp.K[0][x] = t[x]; - } - - /* make the 16 other keys as a transformation of the first key */ - for (x = 1; x < 17; x++) { - /* rotate 3 bits each */ - for (y = 0; y < 17; y++) { - t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; - } - - /* select and add */ - z = x; - for (y = 0; y < 16; y++) { - skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; - if (++z == 17) { z = 0; } - } - } - skey->saferp.rounds = 8; - } else if (keylen == 24) { - /* copy key into t */ - for (x = y = 0; x < 24; x++) { - t[x] = key[x]; - y ^= key[x]; - } - t[24] = y; - - /* make round keys */ - for (x = 0; x < 16; x++) { - skey->saferp.K[0][x] = t[x]; - } - - for (x = 1; x < 25; x++) { - /* rotate 3 bits each */ - for (y = 0; y < 25; y++) { - t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; - } - - /* select and add */ - z = x; - for (y = 0; y < 16; y++) { - skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; - if (++z == 25) { z = 0; } - } - } - skey->saferp.rounds = 12; - } else { - /* copy key into t */ - for (x = y = 0; x < 32; x++) { - t[x] = key[x]; - y ^= key[x]; - } - t[32] = y; - - /* make round keys */ - for (x = 0; x < 16; x++) { - skey->saferp.K[0][x] = t[x]; - } - - for (x = 1; x < 33; x++) { - /* rotate 3 bits each */ - for (y = 0; y < 33; y++) { - t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; - } - - /* select and add */ - z = x; - for (y = 0; y < 16; y++) { - skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; - if (++z == 33) { z = 0; } - } - } - skey->saferp.rounds = 16; - } -#ifdef LTC_CLEAN_STACK - zeromem(t, sizeof(t)); -#endif - return CRYPT_OK; -} - -/** - Encrypts a block of text with LTC_SAFER+ - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - unsigned char b[16]; - int x; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { - return CRYPT_INVALID_ROUNDS; - } - - /* do eight rounds */ - for (x = 0; x < 16; x++) { - b[x] = pt[x]; - } - ROUND(b, 0); LT(b, ct); - ROUND(ct, 2); LT(ct, b); - ROUND(b, 4); LT(b, ct); - ROUND(ct, 6); LT(ct, b); - ROUND(b, 8); LT(b, ct); - ROUND(ct, 10); LT(ct, b); - ROUND(b, 12); LT(b, ct); - ROUND(ct, 14); LT(ct, b); - /* 192-bit key? */ - if (skey->saferp.rounds > 8) { - ROUND(b, 16); LT(b, ct); - ROUND(ct, 18); LT(ct, b); - ROUND(b, 20); LT(b, ct); - ROUND(ct, 22); LT(ct, b); - } - /* 256-bit key? */ - if (skey->saferp.rounds > 12) { - ROUND(b, 24); LT(b, ct); - ROUND(ct, 26); LT(ct, b); - ROUND(b, 28); LT(b, ct); - ROUND(ct, 30); LT(ct, b); - } - ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; - ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; - ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; - ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; - ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; - ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; - ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; - ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; - ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; - ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; - ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; - ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; - ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; - ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; - ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; - ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; -#ifdef LTC_CLEAN_STACK - zeromem(b, sizeof(b)); -#endif - return CRYPT_OK; -} - -/** - Decrypts a block of text with LTC_SAFER+ - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - unsigned char b[16]; - int x; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { - return CRYPT_INVALID_ROUNDS; - } - - /* do eight rounds */ - b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; - b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; - b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; - b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; - b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; - b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; - b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; - b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; - b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; - b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; - b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; - b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; - b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; - b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; - b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; - b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; - /* 256-bit key? */ - if (skey->saferp.rounds > 12) { - iLT(b, pt); iROUND(pt, 30); - iLT(pt, b); iROUND(b, 28); - iLT(b, pt); iROUND(pt, 26); - iLT(pt, b); iROUND(b, 24); - } - /* 192-bit key? */ - if (skey->saferp.rounds > 8) { - iLT(b, pt); iROUND(pt, 22); - iLT(pt, b); iROUND(b, 20); - iLT(b, pt); iROUND(pt, 18); - iLT(pt, b); iROUND(b, 16); - } - iLT(b, pt); iROUND(pt, 14); - iLT(pt, b); iROUND(b, 12); - iLT(b, pt); iROUND(pt,10); - iLT(pt, b); iROUND(b, 8); - iLT(b, pt); iROUND(pt,6); - iLT(pt, b); iROUND(b, 4); - iLT(b, pt); iROUND(pt,2); - iLT(pt, b); iROUND(b, 0); - for (x = 0; x < 16; x++) { - pt[x] = b[x]; - } -#ifdef LTC_CLEAN_STACK - zeromem(b, sizeof(b)); -#endif - return CRYPT_OK; -} - -/** - Performs a self-test of the LTC_SAFER+ block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int saferp_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { - 16, - { 41, 35, 190, 132, 225, 108, 214, 174, - 82, 144, 73, 241, 241, 187, 233, 235 }, - { 179, 166, 219, 60, 135, 12, 62, 153, - 36, 94, 13, 28, 6, 183, 71, 222 }, - { 224, 31, 182, 10, 12, 255, 84, 70, - 127, 13, 89, 249, 9, 57, 165, 220 } - }, { - 24, - { 72, 211, 143, 117, 230, 217, 29, 42, - 229, 192, 247, 43, 120, 129, 135, 68, - 14, 95, 80, 0, 212, 97, 141, 190 }, - { 123, 5, 21, 7, 59, 51, 130, 31, - 24, 112, 146, 218, 100, 84, 206, 177 }, - { 92, 136, 4, 63, 57, 95, 100, 0, - 150, 130, 130, 16, 193, 111, 219, 133 } - }, { - 32, - { 243, 168, 141, 254, 190, 242, 235, 113, - 255, 160, 208, 59, 117, 6, 140, 126, - 135, 120, 115, 77, 208, 190, 130, 190, - 219, 194, 70, 65, 43, 140, 250, 48 }, - { 127, 112, 240, 167, 84, 134, 50, 149, - 170, 91, 104, 19, 11, 230, 252, 245 }, - { 88, 11, 25, 36, 172, 229, 202, 213, - 170, 65, 105, 153, 220, 104, 153, 138 } - } - }; - - unsigned char tmp[2][16]; - symmetric_key skey; - int err, i, y; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { - return err; - } - saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); - saferp_ecb_decrypt(tmp[0], tmp[1], &skey); - - /* compare */ - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void saferp_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int saferp_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - } else if (*keysize < 32) { - *keysize = 24; - } else { - *keysize = 32; - } - return CRYPT_OK; -} - -#undef ROUND -#undef iROUND -#undef PHT -#undef iPHT -#undef SHUF -#undef iSHUF -#undef LT -#undef iLT - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/serpent.c b/Sources/DataLiteC/libtomcrypt/ciphers/serpent.c deleted file mode 100644 index 03661a1..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/serpent.c +++ /dev/null @@ -1,759 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai - https://github.com/weidai11/cryptopp/blob/master/serpent.cpp - - On 2017-10-16 wikipedia says: - "The Serpent cipher algorithm is in the public domain and has not been patented." - https://en.wikipedia.org/wiki/Serpent_(cipher) - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SERPENT - -const struct ltc_cipher_descriptor serpent_desc = { - "serpent", - 25, /* cipher_ID */ - 16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */ - &serpent_setup, - &serpent_ecb_encrypt, - &serpent_ecb_decrypt, - &serpent_test, - &serpent_done, - &serpent_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -/* linear transformation */ -#define s_lt(i,a,b,c,d,e) { \ - a = ROLc(a, 13); \ - c = ROLc(c, 3); \ - d = ROLc(d ^ c ^ (a << 3), 7); \ - b = ROLc(b ^ a ^ c, 1); \ - a = ROLc(a ^ b ^ d, 5); \ - c = ROLc(c ^ d ^ (b << 7), 22); \ - } - -/* inverse linear transformation */ -#define s_ilt(i,a,b,c,d,e) { \ - c = RORc(c, 22); \ - a = RORc(a, 5); \ - c ^= d ^ (b << 7); \ - a ^= b ^ d; \ - b = RORc(b, 1); \ - d = RORc(d, 7) ^ c ^ (a << 3); \ - b ^= a ^ c; \ - c = RORc(c, 3); \ - a = RORc(a, 13); \ - } - -/* order of output from S-box functions */ -#define s_beforeS0(f) f(0,a,b,c,d,e) -#define s_afterS0(f) f(1,b,e,c,a,d) -#define s_afterS1(f) f(2,c,b,a,e,d) -#define s_afterS2(f) f(3,a,e,b,d,c) -#define s_afterS3(f) f(4,e,b,d,c,a) -#define s_afterS4(f) f(5,b,a,e,c,d) -#define s_afterS5(f) f(6,a,c,b,e,d) -#define s_afterS6(f) f(7,a,c,d,b,e) -#define s_afterS7(f) f(8,d,e,b,a,c) - -/* order of output from inverse S-box functions */ -#define s_beforeI7(f) f(8,a,b,c,d,e) -#define s_afterI7(f) f(7,d,a,b,e,c) -#define s_afterI6(f) f(6,a,b,c,e,d) -#define s_afterI5(f) f(5,b,d,e,c,a) -#define s_afterI4(f) f(4,b,c,e,a,d) -#define s_afterI3(f) f(3,a,b,e,c,d) -#define s_afterI2(f) f(2,b,d,e,c,a) -#define s_afterI1(f) f(1,a,b,c,e,d) -#define s_afterI0(f) f(0,a,d,b,e,c) - -/* The instruction sequences for the S-box functions - * come from Dag Arne Osvik's paper "Speeding up Serpent". - */ - -#define s_s0(i, r0, r1, r2, r3, r4) { \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r4 ^= r2; \ - r1 ^= r0; \ - r0 |= r3; \ - r0 ^= r4; \ - r4 ^= r3; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 ^= r4; \ - r4 = ~r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r1 ^= r4; \ - r3 |= r0; \ - r1 ^= r3; \ - r4 ^= r3; \ -} - -#define s_i0(i, r0, r1, r2, r3, r4) { \ - r2 = ~r2; \ - r4 = r1; \ - r1 |= r0; \ - r4 = ~r4; \ - r1 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 &= r3; \ - r4 ^= r0; \ - r0 |= r1; \ - r0 ^= r2; \ - r3 ^= r4; \ - r2 ^= r1; \ - r3 ^= r0; \ - r3 ^= r1; \ - r2 &= r3; \ - r4 ^= r2; \ -} - -#define s_s1(i, r0, r1, r2, r3, r4) { \ - r0 = ~r0; \ - r2 = ~r2; \ - r4 = r0; \ - r0 &= r1; \ - r2 ^= r0; \ - r0 |= r3; \ - r3 ^= r2; \ - r1 ^= r0; \ - r0 ^= r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r2 |= r0; \ - r2 &= r4; \ - r0 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r2; \ - r0 ^= r4; \ -} - -#define s_i1(i, r0, r1, r2, r3, r4) { \ - r4 = r1; \ - r1 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r3 ^= r0; \ - r0 |= r1; \ - r2 ^= r3; \ - r0 ^= r4; \ - r0 |= r2; \ - r1 ^= r3; \ - r0 ^= r1; \ - r1 |= r3; \ - r1 ^= r0; \ - r4 = ~r4; \ - r4 ^= r1; \ - r1 |= r0; \ - r1 ^= r0; \ - r1 |= r4; \ - r3 ^= r1; \ -} - -#define s_s2(i, r0, r1, r2, r3, r4) { \ - r4 = r0; \ - r0 &= r2; \ - r0 ^= r3; \ - r2 ^= r1; \ - r2 ^= r0; \ - r3 |= r4; \ - r3 ^= r1; \ - r4 ^= r2; \ - r1 = r3; \ - r3 |= r4; \ - r3 ^= r0; \ - r0 &= r1; \ - r4 ^= r0; \ - r1 ^= r3; \ - r1 ^= r4; \ - r4 = ~r4; \ -} - -#define s_i2(i, r0, r1, r2, r3, r4) { \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r3; \ - r3 &= r2; \ - r3 ^= r1; \ - r1 |= r2; \ - r1 ^= r4; \ - r4 &= r3; \ - r2 ^= r3; \ - r4 &= r0; \ - r4 ^= r2; \ - r2 &= r1; \ - r2 |= r0; \ - r3 = ~r3; \ - r2 ^= r3; \ - r0 ^= r3; \ - r0 &= r1; \ - r3 ^= r4; \ - r3 ^= r0; \ -} - -#define s_s3(i, r0, r1, r2, r3, r4) { \ - r4 = r0; \ - r0 |= r3; \ - r3 ^= r1; \ - r1 &= r4; \ - r4 ^= r2; \ - r2 ^= r3; \ - r3 &= r0; \ - r4 |= r1; \ - r3 ^= r4; \ - r0 ^= r1; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r2; \ - r1 |= r0; \ - r1 ^= r2; \ - r0 ^= r3; \ - r2 = r1; \ - r1 |= r3; \ - r1 ^= r0; \ -} - -#define s_i3(i, r0, r1, r2, r3, r4) { \ - r4 = r2; \ - r2 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r4; \ - r4 ^= r3; \ - r3 |= r1; \ - r3 ^= r2; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 |= r3; \ - r0 ^= r1; \ - r4 ^= r2; \ - r2 &= r3; \ - r1 |= r3; \ - r1 ^= r2; \ - r4 ^= r0; \ - r2 ^= r4; \ -} - -#define s_s4(i, r0, r1, r2, r3, r4) { \ - r1 ^= r3; \ - r3 = ~r3; \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r1 ^= r2; \ - r4 ^= r3; \ - r0 ^= r4; \ - r2 &= r4; \ - r2 ^= r0; \ - r0 &= r1; \ - r3 ^= r0; \ - r4 |= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r2 &= r3; \ - r0 = ~r0; \ - r4 ^= r2; \ -} - -#define s_i4(i, r0, r1, r2, r3, r4) { \ - r4 = r2; \ - r2 &= r3; \ - r2 ^= r1; \ - r1 |= r3; \ - r1 &= r0; \ - r4 ^= r2; \ - r4 ^= r1; \ - r1 &= r2; \ - r0 = ~r0; \ - r3 ^= r4; \ - r1 ^= r3; \ - r3 &= r0; \ - r3 ^= r2; \ - r0 ^= r1; \ - r2 &= r0; \ - r3 ^= r0; \ - r2 ^= r4; \ - r2 |= r3; \ - r3 ^= r0; \ - r2 ^= r1; \ -} - -#define s_s5(i, r0, r1, r2, r3, r4) { \ - r0 ^= r1; \ - r1 ^= r3; \ - r3 = ~r3; \ - r4 = r1; \ - r1 &= r0; \ - r2 ^= r3; \ - r1 ^= r2; \ - r2 |= r4; \ - r4 ^= r3; \ - r3 &= r1; \ - r3 ^= r0; \ - r4 ^= r1; \ - r4 ^= r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r0 ^= r4; \ - r4 |= r3; \ - r2 ^= r4; \ -} - -#define s_i5(i, r0, r1, r2, r3, r4) { \ - r1 = ~r1; \ - r4 = r3; \ - r2 ^= r1; \ - r3 |= r0; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 ^= r4; \ - r4 |= r0; \ - r4 ^= r1; \ - r1 &= r2; \ - r1 ^= r3; \ - r4 ^= r2; \ - r3 &= r4; \ - r4 ^= r1; \ - r3 ^= r0; \ - r3 ^= r4; \ - r4 = ~r4; \ -} - -#define s_s6(i, r0, r1, r2, r3, r4) { \ - r2 = ~r2; \ - r4 = r3; \ - r3 &= r0; \ - r0 ^= r4; \ - r3 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r2 ^= r0; \ - r0 |= r1; \ - r2 ^= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r4 ^= r3; \ - r4 ^= r0; \ - r3 = ~r3; \ - r2 &= r4; \ - r2 ^= r3; \ -} - -#define s_i6(i, r0, r1, r2, r3, r4) { \ - r0 ^= r2; \ - r4 = r2; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 = ~r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r4 |= r0; \ - r0 ^= r2; \ - r3 ^= r4; \ - r4 ^= r1; \ - r1 &= r3; \ - r1 ^= r0; \ - r0 ^= r3; \ - r0 |= r2; \ - r3 ^= r1; \ - r4 ^= r0; \ -} - -#define s_s7(i, r0, r1, r2, r3, r4) { \ - r4 = r2; \ - r2 &= r1; \ - r2 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r2 ^= r1; \ - r1 ^= r0; \ - r0 |= r4; \ - r0 ^= r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r3 &= r0; \ - r3 ^= r4; \ - r4 ^= r2; \ - r2 &= r0; \ - r4 = ~r4; \ - r2 ^= r4; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r1; \ -} - -#define s_i7(i, r0, r1, r2, r3, r4) { \ - r4 = r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r4 |= r3; \ - r3 ^= r1; \ - r1 |= r0; \ - r0 ^= r2; \ - r2 &= r4; \ - r1 ^= r2; \ - r2 ^= r0; \ - r0 |= r2; \ - r3 &= r4; \ - r0 ^= r3; \ - r4 ^= r1; \ - r3 ^= r4; \ - r4 |= r0; \ - r3 ^= r2; \ - r4 ^= r2; \ -} - -/* key xor */ -#define s_kx(r, a, b, c, d, e) { \ - a ^= k[4 * r + 0]; \ - b ^= k[4 * r + 1]; \ - c ^= k[4 * r + 2]; \ - d ^= k[4 * r + 3]; \ -} - -#define s_lk(r, a, b, c, d, e) { \ - a = k[(8-r)*4 + 0]; \ - b = k[(8-r)*4 + 1]; \ - c = k[(8-r)*4 + 2]; \ - d = k[(8-r)*4 + 3]; \ -} - -#define s_sk(r, a, b, c, d, e) { \ - k[(8-r)*4 + 4] = a; \ - k[(8-r)*4 + 5] = b; \ - k[(8-r)*4 + 6] = c; \ - k[(8-r)*4 + 7] = d; \ -} - -#define s_setup_key s_serpent_setup_key -static int s_setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k) -{ - int i; - ulong32 t; - ulong32 k0[8] = { 0 }; /* zero-initialize */ - ulong32 a, b, c, d, e; - - for (i = 0; i < 8 && i < keylen/4; ++i) { - LOAD32L(k0[i], key + i * 4); - } - if (keylen < 32) { - k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8); - } - - t = k0[7]; - for (i = 0; i < 8; ++i) { - k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); - } - for (i = 8; i < 4*(rounds+1); ++i) { - k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); - } - k -= 20; - - for (i = 0; i < rounds/8; i++) { - s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); - s_afterS1(s_lk); s_afterS1(s_s2); s_afterS2(s_sk); - s_afterS0(s_lk); s_afterS0(s_s1); s_afterS1(s_sk); - s_beforeS0(s_lk); s_beforeS0(s_s0); s_afterS0(s_sk); - k += 8*4; - s_afterS6(s_lk); s_afterS6(s_s7); s_afterS7(s_sk); - s_afterS5(s_lk); s_afterS5(s_s6); s_afterS6(s_sk); - s_afterS4(s_lk); s_afterS4(s_s5); s_afterS5(s_sk); - s_afterS3(s_lk); s_afterS3(s_s4); s_afterS4(s_sk); - } - s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); - - return CRYPT_OK; -} - -static int s_enc_block(const unsigned char *in, unsigned char *out, const ulong32 *k) -{ - ulong32 a, b, c, d, e; - unsigned int i = 1; - - LOAD32L(a, in + 0); - LOAD32L(b, in + 4); - LOAD32L(c, in + 8); - LOAD32L(d, in + 12); - - do { - s_beforeS0(s_kx); s_beforeS0(s_s0); s_afterS0(s_lt); - s_afterS0(s_kx); s_afterS0(s_s1); s_afterS1(s_lt); - s_afterS1(s_kx); s_afterS1(s_s2); s_afterS2(s_lt); - s_afterS2(s_kx); s_afterS2(s_s3); s_afterS3(s_lt); - s_afterS3(s_kx); s_afterS3(s_s4); s_afterS4(s_lt); - s_afterS4(s_kx); s_afterS4(s_s5); s_afterS5(s_lt); - s_afterS5(s_kx); s_afterS5(s_s6); s_afterS6(s_lt); - s_afterS6(s_kx); s_afterS6(s_s7); - - if (i == 4) break; - - ++i; - c = b; - b = e; - e = d; - d = a; - a = e; - k += 32; - s_beforeS0(s_lt); - } while (1); - - s_afterS7(s_kx); - - STORE32L(d, out + 0); - STORE32L(e, out + 4); - STORE32L(b, out + 8); - STORE32L(a, out + 12); - - return CRYPT_OK; -} - -static int s_dec_block(const unsigned char *in, unsigned char *out, const ulong32 *k) -{ - ulong32 a, b, c, d, e; - unsigned int i; - - LOAD32L(a, in + 0); - LOAD32L(b, in + 4); - LOAD32L(c, in + 8); - LOAD32L(d, in + 12); - e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */ - i = 4; - k += 96; - - s_beforeI7(s_kx); - goto start; - - do { - c = b; - b = d; - d = e; - k -= 32; - s_beforeI7(s_ilt); -start: - s_beforeI7(s_i7); s_afterI7(s_kx); - s_afterI7(s_ilt); s_afterI7(s_i6); s_afterI6(s_kx); - s_afterI6(s_ilt); s_afterI6(s_i5); s_afterI5(s_kx); - s_afterI5(s_ilt); s_afterI5(s_i4); s_afterI4(s_kx); - s_afterI4(s_ilt); s_afterI4(s_i3); s_afterI3(s_kx); - s_afterI3(s_ilt); s_afterI3(s_i2); s_afterI2(s_kx); - s_afterI2(s_ilt); s_afterI2(s_i1); s_afterI1(s_kx); - s_afterI1(s_ilt); s_afterI1(s_i0); s_afterI0(s_kx); - } while (--i != 0); - - STORE32L(a, out + 0); - STORE32L(d, out + 4); - STORE32L(b, out + 8); - STORE32L(e, out + 12); - - return CRYPT_OK; -} - -int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS; - if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE; - - err = s_setup_key(key, keylen, 32, skey->serpent.k); -#ifdef LTC_CLEAN_STACK - burn_stack(sizeof(ulong32) * 14 + sizeof(int)); -#endif - return err; -} - -int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_enc_block(pt, ct, skey->serpent.k); -#ifdef LTC_CLEAN_STACK - burn_stack(sizeof(ulong32) * 5 + sizeof(int)); -#endif - return err; -} - -int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_dec_block(ct, pt, skey->serpent.k); -#ifdef LTC_CLEAN_STACK - burn_stack(sizeof(ulong32) * 5 + sizeof(int)); -#endif - return err; -} - -void serpent_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -int serpent_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - - if (*keysize >= 32) { *keysize = 32; } - else if (*keysize >= 24) { *keysize = 24; } - else if (*keysize >= 16) { *keysize = 16; } - else return CRYPT_INVALID_KEYSIZE; - return CRYPT_OK; -} - -int serpent_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char key[32]; - int keylen; - unsigned char pt[16], ct[16]; - } tests[] = { - { - /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 32, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0} - }, - { - /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 32, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59} - }, - { - /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 32, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99} - }, - { - /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 24, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89} - }, - { - /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 24, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82} - }, - { - /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 24, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70} - }, - { - /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 16, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D} - }, - { - /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 16, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24} - }, - { - /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* keylen */ 16, - /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - /* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56} - } - }; - - unsigned char buf[2][16]; - symmetric_key key; - int err, x; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - return CRYPT_OK; -#endif -} - -#undef s_lt -#undef s_ilt -#undef s_beforeS0 -#undef s_afterS0 -#undef s_afterS1 -#undef s_afterS2 -#undef s_afterS3 -#undef s_afterS4 -#undef s_afterS5 -#undef s_afterS6 -#undef s_afterS7 -#undef s_beforeI7 -#undef s_afterI7 -#undef s_afterI6 -#undef s_afterI5 -#undef s_afterI4 -#undef s_afterI3 -#undef s_afterI2 -#undef s_afterI1 -#undef s_afterI0 -#undef s_s0 -#undef s_i0 -#undef s_s1 -#undef s_i1 -#undef s_s2 -#undef s_i2 -#undef s_s3 -#undef s_i3 -#undef s_s4 -#undef s_i4 -#undef s_s5 -#undef s_i5 -#undef s_s6 -#undef s_i6 -#undef s_s7 -#undef s_i7 -#undef s_kx -#undef s_lk -#undef s_sk -#undef s_setup_key - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/skipjack.c b/Sources/DataLiteC/libtomcrypt/ciphers/skipjack.c deleted file mode 100644 index cbcfe70..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/skipjack.c +++ /dev/null @@ -1,339 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file skipjack.c - Skipjack Implementation by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_SKIPJACK - -const struct ltc_cipher_descriptor skipjack_desc = -{ - "skipjack", - 17, - 10, 10, 8, 32, - &skipjack_setup, - &skipjack_ecb_encrypt, - &skipjack_ecb_decrypt, - &skipjack_test, - &skipjack_done, - &skipjack_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static const unsigned char sbox[256] = { - 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, - 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, - 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, - 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, - 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, - 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, - 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, - 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, - 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, - 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, - 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, - 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, - 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, - 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, - 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, - 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 -}; - -/* simple x + 1 (mod 10) in one step. */ -static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; - -/* simple x - 1 (mod 10) in one step */ -static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; - - /** - Initialize the Skipjack block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int x; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - if (keylen != 10) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 32 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - /* make sure the key is in range for platforms where CHAR_BIT != 8 */ - for (x = 0; x < 10; x++) { - skey->skipjack.key[x] = key[x] & 255; - } - - return CRYPT_OK; -} - -#define RULE_A \ - tmp = g_func(w1, &kp, skey->skipjack.key); \ - w1 = tmp ^ w4 ^ x; \ - w4 = w3; w3 = w2; \ - w2 = tmp; - -#define RULE_B \ - tmp = g_func(w1, &kp, skey->skipjack.key); \ - tmp1 = w4; w4 = w3; \ - w3 = w1 ^ w2 ^ x; \ - w1 = tmp1; w2 = tmp; - -#define RULE_A1 \ - tmp = w1 ^ w2 ^ x; \ - w1 = ig_func(w2, &kp, skey->skipjack.key); \ - w2 = w3; w3 = w4; w4 = tmp; - -#define RULE_B1 \ - tmp = ig_func(w2, &kp, skey->skipjack.key); \ - w2 = tmp ^ w3 ^ x; \ - w3 = w4; w4 = w1; w1 = tmp; - -static unsigned g_func(unsigned w, int *kp, const unsigned char *key) -{ - unsigned char g1,g2; - - g1 = (w >> 8) & 255; g2 = w & 255; - g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; - g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; - g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; - g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; - return ((unsigned)g1<<8)|(unsigned)g2; -} - -static unsigned ig_func(unsigned w, int *kp, const unsigned char *key) -{ - unsigned char g1,g2; - - g1 = (w >> 8) & 255; g2 = w & 255; - *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; - *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; - *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; - *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; - return ((unsigned)g1<<8)|(unsigned)g2; -} - -/** - Encrypts a block of text with Skipjack - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - unsigned w1,w2,w3,w4,tmp,tmp1; - int x, kp; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - /* load block */ - w1 = ((unsigned)pt[0]<<8)|pt[1]; - w2 = ((unsigned)pt[2]<<8)|pt[3]; - w3 = ((unsigned)pt[4]<<8)|pt[5]; - w4 = ((unsigned)pt[6]<<8)|pt[7]; - - /* 8 rounds of RULE A */ - for (x = 1, kp = 0; x < 9; x++) { - RULE_A; - } - - /* 8 rounds of RULE B */ - for (; x < 17; x++) { - RULE_B; - } - - /* 8 rounds of RULE A */ - for (; x < 25; x++) { - RULE_A; - } - - /* 8 rounds of RULE B */ - for (; x < 33; x++) { - RULE_B; - } - - /* store block */ - ct[0] = (w1>>8)&255; ct[1] = w1&255; - ct[2] = (w2>>8)&255; ct[3] = w2&255; - ct[4] = (w3>>8)&255; ct[5] = w3&255; - ct[6] = (w4>>8)&255; ct[7] = w4&255; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_skipjack_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2); - return err; -} -#endif - -/** - Decrypts a block of text with Skipjack - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - unsigned w1,w2,w3,w4,tmp; - int x, kp; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - /* load block */ - w1 = ((unsigned)ct[0]<<8)|ct[1]; - w2 = ((unsigned)ct[2]<<8)|ct[3]; - w3 = ((unsigned)ct[4]<<8)|ct[5]; - w4 = ((unsigned)ct[6]<<8)|ct[7]; - - /* 8 rounds of RULE B^-1 - - Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8 - */ - for (x = 32, kp = 8; x > 24; x--) { - RULE_B1; - } - - /* 8 rounds of RULE A^-1 */ - for (; x > 16; x--) { - RULE_A1; - } - - - /* 8 rounds of RULE B^-1 */ - for (; x > 8; x--) { - RULE_B1; - } - - /* 8 rounds of RULE A^-1 */ - for (; x > 0; x--) { - RULE_A1; - } - - /* store block */ - pt[0] = (w1>>8)&255; pt[1] = w1&255; - pt[2] = (w2>>8)&255; pt[3] = w2&255; - pt[4] = (w3>>8)&255; pt[5] = w3&255; - pt[6] = (w4>>8)&255; pt[7] = w4&255; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_skipjack_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2); - return err; -} -#endif - -/** - Performs a self-test of the Skipjack block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int skipjack_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - unsigned char key[10], pt[8], ct[8]; - } tests[] = { - { - { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, - { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa }, - { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 } - } - }; - unsigned char buf[2][8]; - int x, y, err; - symmetric_key key; - - for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { - /* setup key */ - if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) { - return err; - } - - /* encrypt and decrypt */ - skipjack_ecb_encrypt(tests[x].pt, buf[0], &key); - skipjack_ecb_decrypt(buf[0], buf[1], &key); - - /* compare */ - if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Skipjack Encrypt", x) != 0 || - compare_testvector(buf[1], 8, tests[x].pt, 8, "Skipjack Decrypt", x) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) buf[0][y] = 0; - for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key); - for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key); - for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void skipjack_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int skipjack_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 10) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize > 10) { - *keysize = 10; - } - return CRYPT_OK; -} - -#undef RULE_A -#undef RULE_B -#undef RULE_A1 -#undef RULE_B1 - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/sm4.c b/Sources/DataLiteC/libtomcrypt/ciphers/sm4.c deleted file mode 100644 index 2fc68d0..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/sm4.c +++ /dev/null @@ -1,377 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @brief SM4 block cipher algorithm - @date Oct 2018 - @author Chao Wei - - SM4 (formerly SMS4) is a block cipher used in the Chinese National - Standard for Wireless LAN WAPI (Wired Authentication and Privacy - Infrastructure). - --from wikipedia: - https://en.wikipedia.org/wiki/SM4_(cipher) - - This implimentation follows Chinese National Standard - GM/T 0002-2012 - */ -#include "tomcrypt_private.h" - -#ifdef LTC_SM4 - -/*porting to libtomcrypt*/ -/*char always 8bits long*/ -typedef unsigned char sm4_u8_t; -typedef ulong32 sm4_u32_t; - -/* - * S-box defined in section 6.2 - * (1) Nonlinear transformation - */ -static const sm4_u8_t sm4_sbox_table[16][16] = { - {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, - 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05}, - {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, - 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99}, - {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, - 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62}, - {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, - 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6}, - {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, - 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8}, - {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, - 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35}, - {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, - 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87}, - {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, - 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e}, - {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, - 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1}, - {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, - 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3}, - {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, - 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f}, - {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, - 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51}, - {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, - 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8}, - {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, - 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0}, - {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, - 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84}, - {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, - 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48}, -}; - -/* - * S-box - * defined in section 2.6 S-box - */ -static LTC_INLINE sm4_u8_t s_sm4_sbox(sm4_u8_t a) -{ - return sm4_sbox_table[(a >> 4) & 0x0f][a & 0x0f]; -} - -/* - * Nonlinear transformation t - * defined in section 6.2 (1) Nonelinear transformation t - * - * Here should be big endian. - * But we just convert a 32bit word byte by byte. - * So it's OK if we don't convert the endian order - */ -static LTC_INLINE sm4_u32_t s_sm4_t(sm4_u32_t A) -{ - sm4_u8_t a[4]; - sm4_u8_t b[4]; - sm4_u32_t B; - - STORE32H(A, a); - b[0] = s_sm4_sbox(a[0]); - b[1] = s_sm4_sbox(a[1]); - b[2] = s_sm4_sbox(a[2]); - b[3] = s_sm4_sbox(a[3]); - LOAD32H(B, b); - return B; -} - -/* - * defined in section 6.2 (2) Linear transformation L - */ -static LTC_INLINE sm4_u32_t s_sm4_L62(sm4_u32_t B) -{ - return B ^ ROLc(B, 2) ^ ROLc(B, 10) ^ ROLc(B, 18) ^ ROLc(B, 24); -} - -/* - * defined in section 6.2 Permutation T - */ -static LTC_INLINE sm4_u32_t s_sm4_T62(sm4_u32_t Z) -{ - return s_sm4_L62(s_sm4_t(Z)); -} - -/* - * defined in section 7.3 (2) The system parameter FK - */ -static const sm4_u32_t sm4_FK[4] = { - 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc -}; - -/* - * defined in section 7.3 (3) The fixed parameter CK - * The fixed parameter CK is used in the key expansion algorithm - */ -static const sm4_u32_t sm4_CK[32] = -{ - 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, - 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, - 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, - 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, - 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, - 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, - 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, - 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279, -}; - -/* - * defined in section 7.3 (1) L' - */ -static LTC_INLINE sm4_u32_t s_sm4_L73(sm4_u32_t B) -{ - return B ^ ROLc(B, 13) ^ ROLc(B, 23); -} - -/* - * defined in section 7.3 (1) T' - */ -static LTC_INLINE sm4_u32_t s_sm4_T73(sm4_u32_t Z) -{ - return s_sm4_L73(s_sm4_t(Z)); -} - -/* - * defined in section 7.3 Key Expansion - */ -static LTC_INLINE void s_sm4_mk2rk(sm4_u32_t rk[32], sm4_u8_t mk[16]) -{ - sm4_u32_t MK[4] = { 0 }; - sm4_u32_t K[4+32] = { 0 }; - int i; - - LOAD32H(MK[0], mk ); - LOAD32H(MK[1], mk + 4); - LOAD32H(MK[2], mk + 8); - LOAD32H(MK[3], mk + 12); - - for (i = 0; i < 4; ++i) - K[i] = MK[i] ^ sm4_FK[i]; - for (i = 0; i < 32; ++i) - K[i+4] = K[i] ^ s_sm4_T73(K[i+1] ^ K[i+2] ^ K[i+3] ^ sm4_CK[i]); - for (i = 0; i < 32; ++i) - rk[i] = K[i+4]; -} - -/* - * defined in section 6 Round Function F - */ -static LTC_INLINE sm4_u32_t s_sm4_F(sm4_u32_t X[4], sm4_u32_t rk) -{ - return X[0] ^ s_sm4_T62(X[1] ^ X[2] ^ X[3] ^ rk); -} - -/* - * defined in section 7.1 (2) The reverse transformation - */ -static LTC_INLINE void s_sm4_R(sm4_u32_t Y[4], sm4_u32_t X[32+4]) -{ - Y[0] = X[35]; - Y[1] = X[34]; - Y[2] = X[33]; - Y[3] = X[32]; -} - -/* - * defined in section 7.1 (En)cryption - */ -static LTC_INLINE void s_sm4_crypt(sm4_u32_t Y[4], sm4_u32_t X[4+32], const sm4_u32_t rk[32]) -{ - int i; - - for (i = 0; i < 32; ++i) - X[i+4] = s_sm4_F(X+i, rk[i]); - s_sm4_R(Y, X); -} - -static LTC_INLINE void s_sm4_setkey(struct sm4_key *sm4, const unsigned char *key) -{ - int i; - - s_sm4_mk2rk(sm4->ek,(void*)key); - /*swap key sequence when decrypt cipher*/ - for (i = 0; i < 32; ++i) - sm4->dk[i] = sm4->ek[32 - 1 - i]; -} - -int sm4_setup(const unsigned char *key, int keylen, - int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - if (num_rounds != 0 && num_rounds != 32) - return CRYPT_INVALID_ROUNDS; - if (keylen != 16) - return CRYPT_INVALID_KEYSIZE; - s_sm4_setkey(&(skey->sm4), key); - return CRYPT_OK; -} - -/* - * SM4 encryption. - */ -static LTC_INLINE void s_sm4_do(void *output, const void *input, const sm4_u32_t rk[32]) -{ - sm4_u32_t Y[4]; - sm4_u32_t X[32+4]; - - LOAD32H(X[0], (sm4_u8_t *)input ); - LOAD32H(X[1], (sm4_u8_t *)input + 4); - LOAD32H(X[2], (sm4_u8_t *)input + 8); - LOAD32H(X[3], (sm4_u8_t *)input + 12); - - s_sm4_crypt(Y, X, rk); - - STORE32H(Y[0], (sm4_u8_t *)output ); - STORE32H(Y[1], (sm4_u8_t *)output + 4); - STORE32H(Y[2], (sm4_u8_t *)output + 8); - STORE32H(Y[3], (sm4_u8_t *)output + 12); -} - -int sm4_ecb_encrypt(const unsigned char *pt, unsigned char *ct, - const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - s_sm4_do(ct, pt, skey->sm4.ek); - return CRYPT_OK; -} -int sm4_ecb_decrypt(const unsigned char *ct, unsigned char *pt, - const symmetric_key *skey) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - s_sm4_do(pt, ct, skey->sm4.dk); - return CRYPT_OK; -} - -void sm4_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} -int sm4_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if(*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - -/* - * libtomcrypt interface is used - */ - -#ifdef LTC_TEST -static int sm4_self_test_ltc(void) -{ - int result; - int i; - int keysize; - symmetric_key skey; - - sm4_u8_t output[16]; - sm4_u8_t plaintext[] = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - }; - sm4_u8_t key[] = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - }; - sm4_u8_t ciphertext[] = { - 0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E, - 0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46, - }; - sm4_u8_t ciphertext_1000000t[] = { - 0x59, 0x52, 0x98, 0xC7, 0xC6, 0xFD, 0x27, 0x1F, - 0x04, 0x02, 0xF8, 0x04, 0xC3, 0x3D, 0x3F, 0x66, - }; - - result = CRYPT_OK; /* Assume the best */ - - sm4_setup(key, sizeof(key), 32, &skey); - - /*A.1 example 1*/ - sm4_ecb_encrypt(plaintext, output, &skey); - if (compare_testvector(output, 16, ciphertext, 16, "SM4 single encryption", 0) != 0) - result = CRYPT_ERROR; - - sm4_ecb_decrypt(ciphertext, output, &skey); - if (compare_testvector(output, 16, plaintext, 16, "SM4 single decryption", 0) != 0) - result = CRYPT_ERROR; - - /*A.2 example 2*/ - XMEMCPY(output, plaintext, 16); - for (i = 0; i < 1000000; ++i) - sm4_ecb_encrypt(output, output, &skey); - if (compare_testvector(output, 16, ciphertext_1000000t, 16, "SM4 1000000 times encryption", 0) != 0) - result = CRYPT_ERROR; - - XMEMCPY(output, ciphertext_1000000t, 16); - for (i = 0; i < 1000000; ++i) - sm4_ecb_decrypt(output, output, &skey); - if (compare_testvector(output, 16, plaintext, 16, "SM4 1000000 times encryption", 0) != 0) - result = CRYPT_ERROR; - - keysize = 128; - if (sm4_keysize(&keysize) != CRYPT_OK) { - fprintf(stderr, "Getting the max SM4 keysize failed\n"); - result = CRYPT_ERROR; - } else if (keysize != 16) { - fprintf(stderr, "SM4 maximum key size is faulty:\nSHOULD be 16\nIS %d\n", keysize); - result = CRYPT_ERROR; - } - - sm4_done(&skey); - - return result; -} -#endif - -int sm4_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - return sm4_self_test_ltc(); -#endif -} - -const struct ltc_cipher_descriptor sm4_desc = { - "sm4", - 28, - 16, 16, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */ - &sm4_setup, - &sm4_ecb_encrypt, - &sm4_ecb_decrypt, - &sm4_test, - &sm4_done, - &sm4_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -#endif /*LTC_SM4*/ diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/tea.c b/Sources/DataLiteC/libtomcrypt/ciphers/tea.c deleted file mode 100644 index c5419bf..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/tea.c +++ /dev/null @@ -1,212 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file tea.c - Implementation of TEA, Steffen Jaeckel -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_TEA - -const struct ltc_cipher_descriptor tea_desc = -{ - "tea", - 26, - 16, 16, 8, 32, - &tea_setup, - &tea_ecb_encrypt, - &tea_ecb_decrypt, - &tea_test, - &tea_done, - &tea_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -#define DELTA 0x9E3779B9uL -#define SUM 0xC6EF3720uL - -int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* check arguments */ - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 0 && num_rounds != 32) { - return CRYPT_INVALID_ROUNDS; - } - - /* load key */ - LOAD32H(skey->tea.k[0], key+0); - LOAD32H(skey->tea.k[1], key+4); - LOAD32H(skey->tea.k[2], key+8); - LOAD32H(skey->tea.k[3], key+12); - - return CRYPT_OK; -} - -/** - Encrypts a block of text with TEA - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 y, z, sum = 0; - const ulong32 delta = DELTA; - int r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(y, &pt[0]); - LOAD32H(z, &pt[4]); - for (r = 0; r < 32; r++) { - sum += delta; - y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]); - z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]); - } - STORE32H(y, &ct[0]); - STORE32H(z, &ct[4]); - return CRYPT_OK; -} - -/** - Decrypts a block of text with TEA - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 v0, v1, sum = SUM; - const ulong32 delta = DELTA; - int r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(v0, &ct[0]); - LOAD32H(v1, &ct[4]); - - for (r = 0; r < 32; r++) { - v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]); - v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]); - sum -= delta; - } - - STORE32H(v0, &pt[0]); - STORE32H(v1, &pt[4]); - return CRYPT_OK; -} - -/** - Performs a self-test of the TEA block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int tea_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *key, *pt, *ct; - } tests[] = { - { - "00000000000000000000000000000000", - "0000000000000000", - "41ea3a0a94baa940" - }, { - "32a1e65408b63bb9214105744ec5d2e2", - "5ada1d89a9c3801a", - "dd46249e28aa0b4b" - }, { - "60388adadf70a1f5d9cb4e097d2c6c57", - "7a6adb4d69c53e0f", - "44b71215cf25368a" - }, { - "4368d2249bd0321eb7c56d5b63a1bfac", - "5a5d7ca2e186c41a", - "91f56dff7281794f" - }, { - "5c60bff27072d01c4513c5eb8f3a38ab", - "80d9c4adcf899635", - "2bb0f1b3c023ed11" - } - }; - unsigned char ptct[2][8]; - unsigned char tmp[2][8]; - unsigned char key[16]; - unsigned long l; - symmetric_key skey; - size_t i; - int err, y; - for (i = 0; i < LTC_ARRAY_SIZE(tests); i++) { - zeromem(&skey, sizeof(skey)); - - l = sizeof(key); - if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err; - l = sizeof(ptct[0]); - if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err; - l = sizeof(ptct[1]); - if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err; - - if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) { - return err; - } - tea_ecb_encrypt(ptct[0], tmp[0], &skey); - tea_ecb_decrypt(tmp[0], tmp[1], &skey); - - if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 || - compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } /* for */ - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void tea_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int tea_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - -#undef DELTA -#undef SUM - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish.c b/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish.c deleted file mode 100644 index 30478f0..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish.c +++ /dev/null @@ -1,717 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - - /** - @file twofish.c - Implementation of Twofish by Tom St Denis - */ -#include "tomcrypt_private.h" - -#ifdef LTC_TWOFISH - -/* first LTC_TWOFISH_ALL_TABLES must ensure LTC_TWOFISH_TABLES is defined */ -#ifdef LTC_TWOFISH_ALL_TABLES -#ifndef LTC_TWOFISH_TABLES -#define LTC_TWOFISH_TABLES -#endif -#endif - -const struct ltc_cipher_descriptor twofish_desc = -{ - "twofish", - 7, - 16, 32, 16, 16, - &twofish_setup, - &twofish_ecb_encrypt, - &twofish_ecb_decrypt, - &twofish_test, - &twofish_done, - &twofish_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -/* the two polynomials */ -#ifndef LTC_TWOFISH_TABLES -#define MDS_POLY 0x169 -#endif -#ifndef LTC_TWOFISH_ALL_TABLES -#define RS_POLY 0x14D -#endif - -/* The 4x8 RS Linear Transform */ -static const unsigned char RS[4][8] = { - { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E }, - { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 }, - { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 }, - { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 } -}; - -#ifdef LTC_TWOFISH_SMALL -/* sbox usage orderings */ -static const unsigned char qord[4][5] = { - { 1, 1, 0, 0, 1 }, - { 0, 1, 1, 0, 0 }, - { 0, 0, 0, 1, 1 }, - { 1, 0, 1, 1, 0 } -}; -#endif /* LTC_TWOFISH_SMALL */ - -#ifdef LTC_TWOFISH_TABLES - -#define LTC_TWOFISH_TAB_C -#include "twofish_tab.c" - -#define sbox(i, x) ((ulong32)SBOX[i][(x)&255]) - -#else - -/* The Q-box tables */ -static const unsigned char qbox[2][4][16] = { -{ - { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 }, - { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD }, - { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 }, - { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA } -}, -{ - { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 }, - { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 }, - { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF }, - { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA } -} -}; - -/* computes S_i[x] */ -#ifdef LTC_CLEAN_STACK -static ulong32 s_sbox(int i, ulong32 x) -#else -static ulong32 sbox(int i, ulong32 x) -#endif -{ - unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y; - - /* a0,b0 = [x/16], x mod 16 */ - a0 = (unsigned char)((x>>4)&15); - b0 = (unsigned char)((x)&15); - - /* a1 = a0 ^ b0 */ - a1 = a0 ^ b0; - - /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */ - b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15; - - /* a2,b2 = t0[a1], t1[b1] */ - a2 = qbox[i][0][(int)a1]; - b2 = qbox[i][1][(int)b1]; - - /* a3 = a2 ^ b2 */ - a3 = a2 ^ b2; - - /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */ - b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15; - - /* a4,b4 = t2[a3], t3[b3] */ - a4 = qbox[i][2][(int)a3]; - b4 = qbox[i][3][(int)b3]; - - /* y = 16b4 + a4 */ - y = (b4 << 4) + a4; - - /* return result */ - return (ulong32)y; -} - -#ifdef LTC_CLEAN_STACK -static ulong32 sbox(int i, ulong32 x) -{ - ulong32 y; - y = s_sbox(i, x); - burn_stack(sizeof(unsigned char) * 11); - return y; -} -#endif /* LTC_CLEAN_STACK */ - -#endif /* LTC_TWOFISH_TABLES */ - -/* computes ab mod p */ -static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p) -{ - ulong32 result, B[2], P[2]; - - P[1] = p; - B[1] = b; - result = P[0] = B[0] = 0; - - /* unrolled branchless GF multiplier */ - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); - result ^= B[a&1]; - - return result; -} - -/* computes [y0 y1 y2 y3] = MDS . [x0] */ -#ifndef LTC_TWOFISH_TABLES -static ulong32 mds_column_mult(unsigned char in, int col) -{ - ulong32 x01, x5B, xEF; - - x01 = in; - x5B = gf_mult(in, 0x5B, MDS_POLY); - xEF = gf_mult(in, 0xEF, MDS_POLY); - - switch (col) { - case 0: - return (x01 << 0 ) | - (x5B << 8 ) | - (xEF << 16) | - (xEF << 24); - case 1: - return (xEF << 0 ) | - (xEF << 8 ) | - (x5B << 16) | - (x01 << 24); - case 2: - return (x5B << 0 ) | - (xEF << 8 ) | - (x01 << 16) | - (xEF << 24); - case 3: - return (x5B << 0 ) | - (x01 << 8 ) | - (xEF << 16) | - (x5B << 24); - } - /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */ - return 0; -} - -#else /* !LTC_TWOFISH_TABLES */ - -#define mds_column_mult(x, i) mds_tab[i][x] - -#endif /* LTC_TWOFISH_TABLES */ - -/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */ -static void mds_mult(const unsigned char *in, unsigned char *out) -{ - int x; - ulong32 tmp; - for (tmp = x = 0; x < 4; x++) { - tmp ^= mds_column_mult(in[x], x); - } - STORE32L(tmp, out); -} - -#ifdef LTC_TWOFISH_ALL_TABLES -/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ -static void rs_mult(const unsigned char *in, unsigned char *out) -{ - ulong32 tmp; - tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^ - rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]]; - STORE32L(tmp, out); -} - -#else /* !LTC_TWOFISH_ALL_TABLES */ - -/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ -static void rs_mult(const unsigned char *in, unsigned char *out) -{ - int x, y; - for (x = 0; x < 4; x++) { - out[x] = 0; - for (y = 0; y < 8; y++) { - out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY); - } - } -} - -#endif - -/* computes h(x) */ -static void h_func(const unsigned char *in, unsigned char *out, const unsigned char *M, int k, int offset) -{ - int x; - unsigned char y[4]; - for (x = 0; x < 4; x++) { - y[x] = in[x]; - } - switch (k) { - case 4: - y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]); - y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]); - y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]); - y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]); - /* FALLTHROUGH */ - case 3: - y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]); - y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]); - y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]); - y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]); - /* FALLTHROUGH */ - case 2: - y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0])); - y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1])); - y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2])); - y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3])); - /* FALLTHROUGH */ - } - mds_mult(y, out); -} - -#ifndef LTC_TWOFISH_SMALL - -/* for GCC we don't use pointer aliases */ -#if defined(__GNUC__) - #define S1 skey->twofish.S[0] - #define S2 skey->twofish.S[1] - #define S3 skey->twofish.S[2] - #define S4 skey->twofish.S[3] -#endif - -/* the G function */ -#define g_func(x, dum) (S1[LTC_BYTE(x,0)] ^ S2[LTC_BYTE(x,1)] ^ S3[LTC_BYTE(x,2)] ^ S4[LTC_BYTE(x,3)]) -#define g1_func(x, dum) (S2[LTC_BYTE(x,0)] ^ S3[LTC_BYTE(x,1)] ^ S4[LTC_BYTE(x,2)] ^ S1[LTC_BYTE(x,3)]) - -#else - -#ifdef LTC_CLEAN_STACK -static ulong32 s_g_func(ulong32 x, const symmetric_key *key) -#else -static ulong32 g_func(ulong32 x, const symmetric_key *key) -#endif -{ - unsigned char g, i, y, z; - ulong32 res; - - res = 0; - for (y = 0; y < 4; y++) { - z = key->twofish.start; - - /* do unkeyed substitution */ - g = sbox(qord[y][z++], (x >> (8*y)) & 255); - - /* first subkey */ - i = 0; - - /* do key mixing+sbox until z==5 */ - while (z != 5) { - g = g ^ key->twofish.S[4*i++ + y]; - g = sbox(qord[y][z++], g); - } - - /* multiply g by a column of the MDS */ - res ^= mds_column_mult(g, y); - } - return res; -} - -#define g1_func(x, key) g_func(ROLc(x, 8), key) - -#ifdef LTC_CLEAN_STACK -static ulong32 g_func(ulong32 x, const symmetric_key *key) -{ - ulong32 y; - y = s_g_func(x, key); - burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32)); - return y; -} -#endif /* LTC_CLEAN_STACK */ - -#endif /* LTC_TWOFISH_SMALL */ - - /** - Initialize the Twofish block cipher - @param key The symmetric key you wish to pass - @param keylen The key length in bytes - @param num_rounds The number of rounds desired (0 for default) - @param skey The key in as scheduled by this function. - @return CRYPT_OK if successful - */ -#ifdef LTC_CLEAN_STACK -static int s_twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#else -int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -#endif -{ -#ifndef LTC_TWOFISH_SMALL - unsigned char S[4*4], tmpx0, tmpx1; -#endif - int k, x, y; - unsigned char tmp[4], tmp2[4], M[8*4]; - ulong32 A, B; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* invalid arguments? */ - if (num_rounds != 16 && num_rounds != 0) { - return CRYPT_INVALID_ROUNDS; - } - - if (keylen != 16 && keylen != 24 && keylen != 32) { - return CRYPT_INVALID_KEYSIZE; - } - - /* k = keysize/64 [but since our keysize is in bytes...] */ - k = keylen / 8; - - /* copy the key into M */ - for (x = 0; x < keylen; x++) { - M[x] = key[x] & 255; - } - - /* create the S[..] words */ -#ifndef LTC_TWOFISH_SMALL - for (x = 0; x < k; x++) { - rs_mult(M+(x*8), S+(x*4)); - } -#else - for (x = 0; x < k; x++) { - rs_mult(M+(x*8), skey->twofish.S+(x*4)); - } -#endif - - /* make subkeys */ - for (x = 0; x < 20; x++) { - /* A = h(p * 2x, Me) */ - for (y = 0; y < 4; y++) { - tmp[y] = x+x; - } - h_func(tmp, tmp2, M, k, 0); - LOAD32L(A, tmp2); - - /* B = ROL(h(p * (2x + 1), Mo), 8) */ - for (y = 0; y < 4; y++) { - tmp[y] = (unsigned char)(x+x+1); - } - h_func(tmp, tmp2, M, k, 1); - LOAD32L(B, tmp2); - B = ROLc(B, 8); - - /* K[2i] = A + B */ - skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL; - - /* K[2i+1] = (A + 2B) <<< 9 */ - skey->twofish.K[x+x+1] = ROLc(B + B + A, 9); - } - -#ifndef LTC_TWOFISH_SMALL - /* make the sboxes (large ram variant) */ - if (k == 2) { - for (x = 0; x < 256; x++) { - tmpx0 = (unsigned char)sbox(0, x); - tmpx1 = (unsigned char)sbox(1, x); - skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0); - skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1); - skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2); - skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3); - } - } else if (k == 3) { - for (x = 0; x < 256; x++) { - tmpx0 = (unsigned char)sbox(0, x); - tmpx1 = (unsigned char)sbox(1, x); - skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0); - skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1); - skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2); - skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3); - } - } else { - for (x = 0; x < 256; x++) { - tmpx0 = (unsigned char)sbox(0, x); - tmpx1 = (unsigned char)sbox(1, x); - skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0); - skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1); - skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2); - skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3); - } - } -#else - /* where to start in the sbox layers */ - /* small ram variant */ - switch (k) { - case 4 : skey->twofish.start = 0; break; - case 3 : skey->twofish.start = 1; break; - default: skey->twofish.start = 2; break; - } -#endif - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - int x; - x = s_twofish_setup(key, keylen, num_rounds, skey); - burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2); - return x; -} -#endif - -/** - Encrypts a block of text with Twofish - @param pt The input plaintext (16 bytes) - @param ct The output ciphertext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#else -int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; - const ulong32 *k; - int r; -#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) - const ulong32 *S1, *S2, *S3, *S4; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - -#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) - S1 = skey->twofish.S[0]; - S2 = skey->twofish.S[1]; - S3 = skey->twofish.S[2]; - S4 = skey->twofish.S[3]; -#endif - - LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); - LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); - a ^= skey->twofish.K[0]; - b ^= skey->twofish.K[1]; - c ^= skey->twofish.K[2]; - d ^= skey->twofish.K[3]; - - k = skey->twofish.K + 8; - for (r = 8; r != 0; --r) { - t2 = g1_func(b, skey); - t1 = g_func(a, skey) + t2; - c = RORc(c ^ (t1 + k[0]), 1); - d = ROLc(d, 1) ^ (t2 + t1 + k[1]); - - t2 = g1_func(d, skey); - t1 = g_func(c, skey) + t2; - a = RORc(a ^ (t1 + k[2]), 1); - b = ROLc(b, 1) ^ (t2 + t1 + k[3]); - k += 4; - } - - /* output with "undo last swap" */ - ta = c ^ skey->twofish.K[4]; - tb = d ^ skey->twofish.K[5]; - tc = a ^ skey->twofish.K[6]; - td = b ^ skey->twofish.K[7]; - - /* store output */ - STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]); - STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]); - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - int err = s_twofish_ecb_encrypt(pt, ct, skey); - burn_stack(sizeof(ulong32) * 10 + sizeof(int)); - return err; -} -#endif - -/** - Decrypts a block of text with Twofish - @param ct The input ciphertext (16 bytes) - @param pt The output plaintext (16 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -#ifdef LTC_CLEAN_STACK -static int s_twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#else -int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -#endif -{ - ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; - const ulong32 *k; - int r; -#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) - const ulong32 *S1, *S2, *S3, *S4; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - -#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) - S1 = skey->twofish.S[0]; - S2 = skey->twofish.S[1]; - S3 = skey->twofish.S[2]; - S4 = skey->twofish.S[3]; -#endif - - /* load input */ - LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]); - LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]); - - /* undo undo final swap */ - a = tc ^ skey->twofish.K[6]; - b = td ^ skey->twofish.K[7]; - c = ta ^ skey->twofish.K[4]; - d = tb ^ skey->twofish.K[5]; - - k = skey->twofish.K + 36; - for (r = 8; r != 0; --r) { - t2 = g1_func(d, skey); - t1 = g_func(c, skey) + t2; - a = ROLc(a, 1) ^ (t1 + k[2]); - b = RORc(b ^ (t2 + t1 + k[3]), 1); - - t2 = g1_func(b, skey); - t1 = g_func(a, skey) + t2; - c = ROLc(c, 1) ^ (t1 + k[0]); - d = RORc(d ^ (t2 + t1 + k[1]), 1); - k -= 4; - } - - /* pre-white */ - a ^= skey->twofish.K[0]; - b ^= skey->twofish.K[1]; - c ^= skey->twofish.K[2]; - d ^= skey->twofish.K[3]; - - /* store */ - STORE32L(a, &pt[0]); STORE32L(b, &pt[4]); - STORE32L(c, &pt[8]); STORE32L(d, &pt[12]); - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - int err = s_twofish_ecb_decrypt(ct, pt, skey); - burn_stack(sizeof(ulong32) * 10 + sizeof(int)); - return err; -} -#endif - -/** - Performs a self-test of the Twofish block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int twofish_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int keylen; - unsigned char key[32], pt[16], ct[16]; - } tests[] = { - { 16, - { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, - 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }, - { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, - 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }, - { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, - 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 } - }, { - 24, - { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, - 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, - 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 }, - { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, - 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 }, - { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, - 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 } - }, { - 32, - { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, - 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, - 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, - 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }, - { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, - 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }, - { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, - 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA } - } -}; - - - symmetric_key key; - unsigned char tmp[2][16]; - int err, i, y; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { - return err; - } - twofish_ecb_encrypt(tests[i].pt, tmp[0], &key); - twofish_ecb_decrypt(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Twofish Encrypt", i) != 0 || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "Twofish Decrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) twofish_ecb_decrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; -#endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void twofish_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int twofish_keysize(int *keysize) -{ - LTC_ARGCHK(keysize); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - if (*keysize < 24) { - *keysize = 16; - return CRYPT_OK; - } - if (*keysize < 32) { - *keysize = 24; - return CRYPT_OK; - } - *keysize = 32; - return CRYPT_OK; -} - -#undef MDS_POLY -#undef RS_POLY -#undef sbox -#undef mds_column_mult -#undef S1 -#undef S2 -#undef S3 -#undef S4 -#undef g_func -#undef g1_func - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish_tab.c b/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish_tab.c deleted file mode 100644 index e52d284..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/twofish/twofish_tab.c +++ /dev/null @@ -1,486 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - - /** - @file twofish_tab.c - Twofish tables, Tom St Denis - */ -#ifdef LTC_TWOFISH_TABLES -#ifdef LTC_TWOFISH_TAB_C - -/* pre generated 8x8 tables from the four 4x4s */ -static const unsigned char SBOX[2][256] = { -{ - 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, - 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, - 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, - 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, - 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, - 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, - 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, - 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, - 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, - 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, - 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, - 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, - 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, - 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, - 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, - 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, - 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, - 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, - 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, - 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, - 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, - 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, - 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, - 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, - 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, - 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0}, -{ - 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, - 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, - 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, - 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, - 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, - 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, - 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, - 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, - 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, - 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, - 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, - 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, - 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, - 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, - 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, - 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, - 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, - 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, - 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, - 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, - 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, - 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, - 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, - 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, - 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91} -}; - -/* the 4x4 MDS in a nicer format */ -static const ulong32 mds_tab[4][256] = { -{ -0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL, -0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL, -0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL, -0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL, -0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL, -0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL, -0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL, -0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL, -0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL, -0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL, -0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL, -0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL, -0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL, -0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL, -0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL, -0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL, -0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL, -0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL, -0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL, -0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL, -0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL, -0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL, -0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL, -0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL, -0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL, -0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL, -0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL, -0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL, -0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL, -0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL, -0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL, -0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL -}, -{ -0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL, -0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL, -0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL, -0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL, -0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL, -0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL, -0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL, -0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL, -0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL, -0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL, -0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL, -0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL, -0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL, -0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL, -0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL, -0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL, -0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL, -0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL, -0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL, -0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL, -0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL, -0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL, -0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL, -0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL, -0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL, -0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL, -0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL, -0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL, -0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL, -0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL, -0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL, -0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL -}, -{ -0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL, -0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL, -0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL, -0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL, -0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL, -0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL, -0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL, -0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL, -0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL, -0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL, -0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL, -0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL, -0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL, -0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL, -0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL, -0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL, -0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL, -0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL, -0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL, -0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL, -0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL, -0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL, -0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL, -0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL, -0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL, -0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL, -0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL, -0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL, -0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL, -0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL, -0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL, -0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL -}, -{ -0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL, -0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL, -0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL, -0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL, -0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL, -0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL, -0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL, -0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL, -0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL, -0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL, -0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL, -0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL, -0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL, -0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL, -0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL, -0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL, -0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL, -0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL, -0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL, -0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL, -0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL, -0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL, -0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL, -0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL, -0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL, -0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL, -0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL, -0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL, -0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL, -0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL, -0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL, -0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL -}}; - -#ifdef LTC_TWOFISH_ALL_TABLES - -/* the 4x8 RS transform */ -static const ulong32 rs_tab0[256] = { -0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU, -0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU, -0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU, -0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU, -0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU, -0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU, -0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU, -0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU, -0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU, -0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU, -0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU, -0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU, -0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU, -0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU, -0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU, -0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU, -0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU, -0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU, -0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU, -0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU, -0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU, -0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU, -0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU, -0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU, -0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU, -0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU, -0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU, -0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU, -0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU, -0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU, -0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU, -0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU }; - -static const ulong32 rs_tab1[256] = { -0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU, -0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU, -0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU, -0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU, -0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU, -0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU, -0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU, -0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU, -0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU, -0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU, -0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU, -0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU, -0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU, -0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU, -0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU, -0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU, -0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU, -0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU, -0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU, -0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU, -0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU, -0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU, -0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU, -0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU, -0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU, -0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU, -0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU, -0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU, -0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU, -0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU, -0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU, -0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU }; - -static const ulong32 rs_tab2[256] = { -0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU, -0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU, -0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU, -0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU, -0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU, -0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU, -0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU, -0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU, -0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU, -0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU, -0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU, -0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU, -0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU, -0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU, -0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU, -0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU, -0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU, -0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU, -0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU, -0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU, -0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU, -0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU, -0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU, -0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU, -0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU, -0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU, -0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU, -0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU, -0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU, -0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU, -0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU, -0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU }; - -static const ulong32 rs_tab3[256] = { -0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU, -0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU, -0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU, -0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU, -0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU, -0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU, -0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU, -0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU, -0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU, -0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU, -0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU, -0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU, -0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU, -0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU, -0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU, -0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU, -0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU, -0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU, -0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU, -0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU, -0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU, -0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU, -0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU, -0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU, -0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU, -0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU, -0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU, -0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU, -0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU, -0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU, -0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU, -0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU }; - -static const ulong32 rs_tab4[256] = { -0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU, -0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU, -0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU, -0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU, -0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU, -0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU, -0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU, -0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU, -0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU, -0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU, -0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU, -0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU, -0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU, -0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU, -0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU, -0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU, -0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU, -0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU, -0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU, -0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU, -0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU, -0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU, -0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU, -0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU, -0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU, -0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU, -0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU, -0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU, -0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU, -0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU, -0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU, -0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU }; - -static const ulong32 rs_tab5[256] = { -0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU, -0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU, -0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU, -0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU, -0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU, -0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU, -0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU, -0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU, -0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU, -0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU, -0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU, -0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU, -0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU, -0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU, -0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU, -0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU, -0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU, -0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU, -0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU, -0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU, -0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU, -0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU, -0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU, -0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU, -0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU, -0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU, -0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU, -0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU, -0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU, -0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU, -0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU, -0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU }; - -static const ulong32 rs_tab6[256] = { -0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU, -0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU, -0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU, -0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU, -0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU, -0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU, -0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU, -0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU, -0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU, -0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU, -0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU, -0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU, -0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU, -0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU, -0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU, -0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU, -0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU, -0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU, -0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU, -0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU, -0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU, -0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU, -0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU, -0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU, -0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU, -0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU, -0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU, -0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU, -0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU, -0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU, -0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU, -0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU }; - -static const ulong32 rs_tab7[256] = { -0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU, -0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU, -0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU, -0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU, -0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU, -0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU, -0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU, -0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU, -0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU, -0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU, -0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU, -0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU, -0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU, -0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU, -0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU, -0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU, -0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU, -0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU, -0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU, -0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU, -0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU, -0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU, -0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU, -0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU, -0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU, -0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU, -0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU, -0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU, -0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU, -0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU, -0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU, -0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU }; - -#endif /* LTC_TWOFISH_ALL_TABLES */ - -#endif /* LTC_TWOFISH_TAB_C */ -#endif diff --git a/Sources/DataLiteC/libtomcrypt/ciphers/xtea.c b/Sources/DataLiteC/libtomcrypt/ciphers/xtea.c deleted file mode 100644 index 9e86e8d..0000000 --- a/Sources/DataLiteC/libtomcrypt/ciphers/xtea.c +++ /dev/null @@ -1,251 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file xtea.c - Implementation of eXtended TEA, Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_XTEA - -const struct ltc_cipher_descriptor xtea_desc = -{ - "xtea", - 1, - 16, 16, 8, 32, - &xtea_setup, - &xtea_ecb_encrypt, - &xtea_ecb_decrypt, - &xtea_test, - &xtea_done, - &xtea_keysize, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) -{ - ulong32 x, sum, K[4]; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(skey != NULL); - - /* check arguments */ - if (keylen != 16) { - return CRYPT_INVALID_KEYSIZE; - } - - if (num_rounds != 0 && num_rounds != 32) { - return CRYPT_INVALID_ROUNDS; - } - - /* load key */ - LOAD32H(K[0], key+0); - LOAD32H(K[1], key+4); - LOAD32H(K[2], key+8); - LOAD32H(K[3], key+12); - - for (x = sum = 0; x < 32; x++) { - skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL; - sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL; - skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL; - } - -#ifdef LTC_CLEAN_STACK - zeromem(&K, sizeof(K)); -#endif - - return CRYPT_OK; -} - -/** - Encrypts a block of text with LTC_XTEA - @param pt The input plaintext (8 bytes) - @param ct The output ciphertext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) -{ - ulong32 y, z; - int r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(y, &pt[0]); - LOAD32H(z, &pt[4]); - for (r = 0; r < 32; r += 4) { - y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; - z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; - - y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL; - z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL; - - y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL; - z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL; - - y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL; - z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL; - } - STORE32H(y, &ct[0]); - STORE32H(z, &ct[4]); - return CRYPT_OK; -} - -/** - Decrypts a block of text with LTC_XTEA - @param ct The input ciphertext (8 bytes) - @param pt The output plaintext (8 bytes) - @param skey The key as scheduled - @return CRYPT_OK if successful -*/ -int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) -{ - ulong32 y, z; - int r; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); - - LOAD32H(y, &ct[0]); - LOAD32H(z, &ct[4]); - for (r = 31; r >= 0; r -= 4) { - z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; - y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; - - z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL; - y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL; - - z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL; - y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL; - - z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL; - y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL; - } - STORE32H(y, &pt[0]); - STORE32H(z, &pt[4]); - return CRYPT_OK; -} - -/** - Performs a self-test of the LTC_XTEA block cipher - @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled -*/ -int xtea_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - unsigned char key[16], pt[8], ct[8]; - } tests[] = { - { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 } - }, { - { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 } - }, { - { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 }, - { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }, - { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc } - }, { - { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, - 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, - { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, - { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab } - }, { - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 } - }, { - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 } - }, { - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } - }, { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 } - }, { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d } - }, { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } - } - }; - unsigned char tmp[2][8]; - symmetric_key skey; - int i, err, y; - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - zeromem(&skey, sizeof(skey)); - if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK) { - return err; - } - xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey); - xtea_ecb_decrypt(tmp[0], tmp[1], &skey); - - if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 || - compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ - for (y = 0; y < 8; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey); - for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; - } /* for */ - - return CRYPT_OK; - #endif -} - -/** Terminate the context - @param skey The scheduled key -*/ -void xtea_done(symmetric_key *skey) -{ - LTC_UNUSED_PARAM(skey); -} - -/** - Gets suitable key size - @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. - @return CRYPT_OK if the input key size is acceptable. -*/ -int xtea_keysize(int *keysize) -{ - LTC_ARGCHK(keysize != NULL); - if (*keysize < 16) { - return CRYPT_INVALID_KEYSIZE; - } - *keysize = 16; - return CRYPT_OK; -} - - -#endif - - - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_aad.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_aad.c deleted file mode 100644 index 94d2e2b..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_aad.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Add AAD to the CCM state - @param ccm The CCM state - @param adata The additional authentication data to add to the CCM state - @param adatalen The length of the AAD data. - @return CRYPT_OK on success - */ -int ccm_add_aad(ccm_state *ccm, - const unsigned char *adata, unsigned long adatalen) -{ - unsigned long y; - int err; - - LTC_ARGCHK(ccm != NULL); - LTC_ARGCHK(adata != NULL); - - if (ccm->aadlen < ccm->current_aadlen + adatalen) { - return CRYPT_INVALID_ARG; - } - ccm->current_aadlen += adatalen; - - /* now add the data */ - for (y = 0; y < adatalen; y++) { - if (ccm->x == 16) { - /* full block so let's encrypt it */ - if ((err = ecb_encrypt_block(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { - return err; - } - ccm->x = 0; - } - ccm->PAD[ccm->x++] ^= adata[y]; - } - - /* remainder? */ - if (ccm->aadlen == ccm->current_aadlen) { - if (ccm->x != 0) { - if ((err = ecb_encrypt_block(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { - return err; - } - } - ccm->x = 0; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_nonce.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_nonce.c deleted file mode 100644 index 176836b..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_add_nonce.c +++ /dev/null @@ -1,109 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Add nonce data to the CCM state - @param ccm The CCM state - @param nonce The nonce data to add - @param noncelen The length of the nonce - @return CRYPT_OK on success - */ -int ccm_add_nonce(ccm_state *ccm, - const unsigned char *nonce, unsigned long noncelen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(ccm != NULL); - LTC_ARGCHK(nonce != NULL); - - /* increase L to match the nonce len */ - ccm->noncelen = (noncelen > 13) ? 13 : noncelen; - if ((15 - ccm->noncelen) > ccm->L) { - ccm->L = 15 - ccm->noncelen; - } - if (ccm->L > 8) { - return CRYPT_INVALID_ARG; - } - - /* decrease noncelen to match L */ - if ((ccm->noncelen + ccm->L) > 15) { - ccm->noncelen = 15 - ccm->L; - } - - /* form B_0 == flags | Nonce N | l(m) */ - x = 0; - ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) | - (((ccm->taglen - 2)>>1)<<3) | - (ccm->L-1)); - - /* nonce */ - for (y = 0; y < 15 - ccm->L; y++) { - ccm->PAD[x++] = nonce[y]; - } - - /* store len */ - len = ccm->ptlen; - - /* shift len so the upper bytes of len are the contents of the length */ - for (y = ccm->L; y < 4; y++) { - len <<= 8; - } - - /* store l(m) (only store 32-bits) */ - for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) { - ccm->PAD[x++] = 0; - } - for (; y < ccm->L; y++) { - if (x >= sizeof(ccm->PAD)) { - return CRYPT_INVALID_ARG; - } - ccm->PAD[x++] = (unsigned char)((len >> 24) & 255); - len <<= 8; - } - - /* encrypt PAD */ - if ((err = ecb_encrypt_block(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { - return err; - } - - /* handle header */ - ccm->x = 0; - if (ccm->aadlen > 0) { - /* store length */ - if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) { - ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; - ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; - } else { - ccm->PAD[ccm->x++] ^= 0xFF; - ccm->PAD[ccm->x++] ^= 0xFE; - ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255; - ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255; - ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; - ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; - } - } - - /* setup the ctr counter */ - x = 0; - - /* flags */ - ccm->ctr[x++] = (unsigned char)ccm->L-1; - - /* nonce */ - for (y = 0; y < (16 - (ccm->L+1)); ++y) { - ccm->ctr[x++] = nonce[y]; - } - /* offset */ - while (x < 16) { - ccm->ctr[x++] = 0; - } - - ccm->CTRlen = 16; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_done.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_done.c deleted file mode 100644 index 51ce6cc..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_done.c +++ /dev/null @@ -1,55 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Terminate a CCM stream - @param ccm The CCM state - @param tag [out] The destination for the MAC tag - @param taglen [in/out] The length of the MAC tag - @return CRYPT_OK on success - */ -int ccm_done(ccm_state *ccm, - unsigned char *tag, unsigned long *taglen) -{ - unsigned long x, y; - int err; - - LTC_ARGCHK(ccm != NULL); - - /* Check all data have been processed */ - if (ccm->ptlen != ccm->current_ptlen) { - return CRYPT_ERROR; - } - - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - if (ccm->x != 0) { - if ((err = ecb_encrypt_block(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { - return err; - } - } - - /* setup CTR for the TAG (zero the count) */ - for (y = 15; y > 15 - ccm->L; y--) { - ccm->ctr[y] = 0x00; - } - if ((err = ecb_encrypt_block(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { - return err; - } - - ecb_done(&ccm->K); - - /* store the TAG */ - for (x = 0; x < 16 && x < *taglen; x++) { - tag[x] = ccm->PAD[x] ^ ccm->CTRPAD[x]; - } - *taglen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_init.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_init.c deleted file mode 100644 index 3578bcf..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_init.c +++ /dev/null @@ -1,63 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Initialize a CCM state - @param ccm The CCM state to initialize - @param cipher The index of the cipher to use - @param key The secret key - @param keylen The length of the secret key - @param ptlen The length of the plain/cipher text that will be processed - @param taglen The max length of the MAC tag - @param aadlen The length of the AAD - - @return CRYPT_OK on success - */ -int ccm_init(ccm_state *ccm, int cipher, - const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen) -{ - int err; - - LTC_ARGCHK(ccm != NULL); - LTC_ARGCHK(key != NULL); - - XMEMSET(ccm, 0, sizeof(ccm_state)); - - /* check cipher input */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_CIPHER; - } - - /* make sure the taglen is valid */ - if (taglen < 4 || taglen > 16 || (taglen % 2) == 1 || aadlen < 0 || ptlen < 0) { - return CRYPT_INVALID_ARG; - } - ccm->taglen = taglen; - - /* schedule key */ - if ((err = ecb_start(cipher, key, keylen, 0, &ccm->K)) != CRYPT_OK) { - return err; - } - - /* let's get the L value */ - ccm->ptlen = ptlen; - ccm->L = 0; - while (ptlen) { - ++ccm->L; - ptlen >>= 8; - } - if (ccm->L <= 1) { - ccm->L = 2; - } - - ccm->aadlen = aadlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_memory.c deleted file mode 100644 index d239044..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_memory.c +++ /dev/null @@ -1,379 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ccm_memory.c - CCM support, process a block of memory, Tom St Denis -*/ - -#ifdef LTC_CCM_MODE - -/** - CCM encrypt/decrypt and produce an authentication tag - - *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction' - - @param cipher The index of the cipher desired - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param uskey A previously scheduled key [optional can be NULL] - @param nonce The session nonce [use once] - @param noncelen The length of the nonce - @param header The header for the session - @param headerlen The length of the header (octets) - @param pt [*1] The plaintext - @param ptlen The length of the plaintext (octets) - @param ct [*1] The ciphertext - @param tag [*1] The destination tag - @param taglen The max size and resulting size of the authentication tag - @param direction Encrypt or Decrypt direction (0 or 1) - @return CRYPT_OK if successful -*/ -int ccm_memory(int cipher, - const unsigned char *key, unsigned long keylen, - symmetric_ECB *uskey, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction) -{ - unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real; - unsigned char *pt_work = NULL; - symmetric_ECB *skey; - int err; - unsigned long len, L, x, y, z, CTRlen; - - if (uskey == NULL) { - LTC_ARGCHK(key != NULL); - } - LTC_ARGCHK(nonce != NULL); - if (headerlen > 0) { - LTC_ARGCHK(header != NULL); - } - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - pt_real = pt; - -#ifdef LTC_FAST - if (16 % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* check cipher input */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_CIPHER; - } - - /* make sure the taglen is valid */ - if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) { - return CRYPT_INVALID_ARG; - } - if (noncelen < 7) { - return CRYPT_INVALID_ARG; - } - - /* is there an accelerator? */ - if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { - return cipher_descriptor[cipher].accel_ccm_memory( - key, keylen, - &uskey->key, - nonce, noncelen, - header, headerlen, - pt, ptlen, - ct, - tag, taglen, - direction); - } - - /* let's get the L value */ - len = ptlen; - L = 0; - while (len) { - ++L; - len >>= 8; - } - if (L <= 1) { - L = 2; - } - - /* increase L to match the nonce len */ - noncelen = (noncelen > 13) ? 13 : noncelen; - if ((15 - noncelen) > L) { - L = 15 - noncelen; - } - if (L > 8) { - return CRYPT_INVALID_ARG; - } - - /* allocate mem for the symmetric key */ - if (uskey == NULL) { - skey = XMALLOC(sizeof(*skey)); - if (skey == NULL) { - return CRYPT_MEM; - } - - /* initialize the cipher */ - if ((err = ecb_start(cipher, key, keylen, 0, skey)) != CRYPT_OK) { - XFREE(skey); - return err; - } - } else { - skey = uskey; - } - - /* initialize buffer for pt */ - if (direction == CCM_DECRYPT && ptlen > 0) { - pt_work = XMALLOC(ptlen); - if (pt_work == NULL) { - goto error; - } - pt = pt_work; - } - - /* form B_0 == flags | Nonce N | l(m) */ - x = 0; - PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | - (((*taglen - 2)>>1)<<3) | - (L-1)); - - /* nonce */ - for (y = 0; y < noncelen; y++) { - PAD[x++] = nonce[y]; - } - - /* store len */ - len = ptlen; - - /* shift len so the upper bytes of len are the contents of the length */ - for (y = L; y < 4; y++) { - len <<= 8; - } - - /* store l(m) (only store 32-bits) */ - for (y = 0; L > 4 && (L-y)>4; y++) { - PAD[x++] = 0; - } - for (; y < L; y++) { - if (x >= sizeof(PAD)) { - err = CRYPT_INVALID_ARG; - goto error; - } - PAD[x++] = (unsigned char)((len >> 24) & 255); - len <<= 8; - } - - /* encrypt PAD */ - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - - /* handle header */ - if (headerlen > 0) { - x = 0; - - /* store length */ - if (headerlen < ((1UL<<16) - (1UL<<8))) { - PAD[x++] ^= (headerlen>>8) & 255; - PAD[x++] ^= headerlen & 255; - } else { - PAD[x++] ^= 0xFF; - PAD[x++] ^= 0xFE; - PAD[x++] ^= (headerlen>>24) & 255; - PAD[x++] ^= (headerlen>>16) & 255; - PAD[x++] ^= (headerlen>>8) & 255; - PAD[x++] ^= headerlen & 255; - } - - /* now add the data */ - for (y = 0; y < headerlen; y++) { - if (x == 16) { - /* full block so let's encrypt it */ - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - x = 0; - } - PAD[x++] ^= header[y]; - } - - /* remainder */ - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - } - - /* setup the ctr counter */ - x = 0; - - /* flags */ - ctr[x++] = (unsigned char)L-1; - - /* nonce */ - for (y = 0; y < (16 - (L+1)); ++y) { - ctr[x++] = nonce[y]; - } - /* offset */ - while (x < 16) { - ctr[x++] = 0; - } - - x = 0; - CTRlen = 16; - - /* now handle the PT */ - if (ptlen > 0) { - y = 0; -#ifdef LTC_FAST - if (ptlen & ~15) { - if (direction == CCM_ENCRYPT) { - for (; y < (ptlen & ~15); y += 16) { - /* increment the ctr? */ - for (z = 15; z > 15-L; z--) { - ctr[z] = (ctr[z] + 1) & 255; - if (ctr[z]) break; - } - if ((err = ecb_encrypt_block(ctr, CTRPAD, skey)) != CRYPT_OK) { - goto error; - } - - /* xor the PT against the pad first */ - for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); - *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); - } - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - } - } else { /* direction == CCM_DECRYPT */ - for (; y < (ptlen & ~15); y += 16) { - /* increment the ctr? */ - for (z = 15; z > 15-L; z--) { - ctr[z] = (ctr[z] + 1) & 255; - if (ctr[z]) break; - } - if ((err = ecb_encrypt_block(ctr, CTRPAD, skey)) != CRYPT_OK) { - goto error; - } - - /* xor the PT against the pad last */ - for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); - *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); - } - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - } - } - } -#endif - - for (; y < ptlen; y++) { - /* increment the ctr? */ - if (CTRlen == 16) { - for (z = 15; z > 15-L; z--) { - ctr[z] = (ctr[z] + 1) & 255; - if (ctr[z]) break; - } - if ((err = ecb_encrypt_block(ctr, CTRPAD, skey)) != CRYPT_OK) { - goto error; - } - CTRlen = 0; - } - - /* if we encrypt we add the bytes to the MAC first */ - if (direction == CCM_ENCRYPT) { - b = pt[y]; - ct[y] = b ^ CTRPAD[CTRlen++]; - } else { - b = ct[y] ^ CTRPAD[CTRlen++]; - pt[y] = b; - } - - if (x == 16) { - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - x = 0; - } - PAD[x++] ^= b; - } - - if (x != 0) { - if ((err = ecb_encrypt_block(PAD, PAD, skey)) != CRYPT_OK) { - goto error; - } - } - } - - /* setup CTR for the TAG (zero the count) */ - for (y = 15; y > 15 - L; y--) { - ctr[y] = 0x00; - } - if ((err = ecb_encrypt_block(ctr, CTRPAD, skey)) != CRYPT_OK) { - goto error; - } - - if (skey != uskey) { - ecb_done(skey); -#ifdef LTC_CLEAN_STACK - zeromem(skey, sizeof(*skey)); -#endif - } - - if (direction == CCM_ENCRYPT) { - /* store the TAG */ - for (x = 0; x < 16 && x < *taglen; x++) { - tag[x] = PAD[x] ^ CTRPAD[x]; - } - *taglen = x; - } else { /* direction == CCM_DECRYPT */ - /* decrypt the tag */ - for (x = 0; x < 16 && x < *taglen; x++) { - ptTag[x] = tag[x] ^ CTRPAD[x]; - } - *taglen = x; - - /* check validity of the decrypted tag against the computed PAD (in constant time) */ - /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR). - * there should be a better way of setting the correct error code in constant - * time. - */ - err = XMEM_NEQ(ptTag, PAD, *taglen); - - /* Zero the plaintext if the tag was invalid (in constant time) */ - if (ptlen > 0) { - copy_or_zeromem(pt, pt_real, ptlen, err); - } - } - -#ifdef LTC_CLEAN_STACK - zeromem(PAD, sizeof(PAD)); - zeromem(CTRPAD, sizeof(CTRPAD)); - if (pt_work != NULL) { - zeromem(pt_work, ptlen); - } -#endif -error: - if (pt_work) { - XFREE(pt_work); - } - if (skey != uskey) { - XFREE(skey); - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_process.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_process.c deleted file mode 100644 index b5f973d..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_process.c +++ /dev/null @@ -1,78 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Process plaintext/ciphertext through CCM - @param ccm The CCM state - @param pt The plaintext - @param ptlen The plaintext length (ciphertext length is the same) - @param ct The ciphertext - @param direction Encrypt or Decrypt mode (CCM_ENCRYPT or CCM_DECRYPT) - @return CRYPT_OK on success - */ -int ccm_process(ccm_state *ccm, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - int direction) -{ - unsigned char z, b; - unsigned long y; - int err; - - LTC_ARGCHK(ccm != NULL); - - /* Check aad has been correctly added */ - if (ccm->aadlen != ccm->current_aadlen) { - return CRYPT_ERROR; - } - - /* Check we do not process too much data */ - if (ccm->ptlen < ccm->current_ptlen + ptlen) { - return CRYPT_ERROR; - } - ccm->current_ptlen += ptlen; - - /* now handle the PT */ - if (ptlen > 0) { - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - for (y = 0; y < ptlen; y++) { - /* increment the ctr? */ - if (ccm->CTRlen == 16) { - for (z = 15; z > 15-ccm->L; z--) { - ccm->ctr[z] = (ccm->ctr[z] + 1) & 255; - if (ccm->ctr[z]) break; - } - if ((err = ecb_encrypt_block(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { - return err; - } - ccm->CTRlen = 0; - } - - /* if we encrypt we add the bytes to the MAC first */ - if (direction == CCM_ENCRYPT) { - b = pt[y]; - ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++]; - } else { - b = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++]; - pt[y] = b; - } - - if (ccm->x == 16) { - if ((err = ecb_encrypt_block(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { - return err; - } - ccm->x = 0; - } - ccm->PAD[ccm->x++] ^= b; - } - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_reset.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_reset.c deleted file mode 100644 index 93b8fec..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_reset.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_CCM_MODE - -/** - Reset a CCM state to as if you just called ccm_init(). This saves the initialization time. - @param ccm The CCM state to reset - @return CRYPT_OK on success -*/ -int ccm_reset(ccm_state *ccm) -{ - LTC_ARGCHK(ccm != NULL); - zeromem(ccm->PAD, sizeof(ccm->PAD)); - zeromem(ccm->ctr, sizeof(ccm->ctr)); - zeromem(ccm->CTRPAD, sizeof(ccm->CTRPAD)); - ccm->CTRlen = 0; - ccm->current_ptlen = 0; - ccm->current_aadlen = 0; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_test.c b/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_test.c deleted file mode 100644 index d725ecd..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ccm/ccm_test.c +++ /dev/null @@ -1,274 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ccm_test.c - CCM support, process a block of memory, Tom St Denis -*/ - -#ifdef LTC_CCM_MODE - -int ccm_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char key[16]; - unsigned char nonce[16]; - int noncelen; - unsigned char header[64]; - int headerlen; - unsigned char pt[64]; - int ptlen; - unsigned char ct[64]; - unsigned char tag[16]; - unsigned long taglen; - } tests[] = { - -/* 13 byte nonce, 8 byte auth, 23 byte pt */ -{ - { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, - 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, - { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, - 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, - 13, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, - 8, - { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E }, - 23, - { 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, - 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, - 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84 }, - { 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 }, - 8 -}, - -/* 13 byte nonce, 12 byte header, 19 byte pt */ -{ - { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, - 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, - { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, - 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, - 13, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B }, - 12, - { 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1E }, - 19, - { 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, - 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, - 0xCD, 0xAC, 0x8C }, - { 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1 }, - 8 -}, - -/* supplied by Brian Gladman */ -{ - { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }, - { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, - 7, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, - 8, - { 0x20, 0x21, 0x22, 0x23 }, - 4, - { 0x71, 0x62, 0x01, 0x5b }, - { 0x4d, 0xac, 0x25, 0x5d }, - 4 -}, - -{ - { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, - 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f }, - { 0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5, - 0x03, 0x97, 0x76, 0xe7, 0x0c }, - 13, - { 0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c, - 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae, - 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00 }, - 22, - { 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, - 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, - 0x7e, 0x78, 0xa0, 0x50 }, - 20, - { 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, - 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, - 0x3c, 0x04, 0xd0, 0x19 }, - { 0x78, 0x45, 0xce, 0x0b, 0x16, 0xf9, 0x76, 0x23 }, - 8 -}, - -}; - unsigned long taglen, x, y; - unsigned char buf[64], buf2[64], tag[16], tag2[16], tag3[16], zero[64]; - int err, idx; - symmetric_ECB skey; - ccm_state ccm; - - zeromem(zero, 64); - - idx = find_cipher("aes"); - if (idx == -1) { - idx = find_cipher("rijndael"); - if (idx == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < LTC_ARRAY_SIZE(tests); x++) { - for (y = 0; y < 2; y++) { - taglen = tests[x].taglen; - if (y == 0) { - if ((err = ecb_start(idx, tests[x].key, 16, 0, &skey)) != CRYPT_OK) { - return err; - } - - if ((err = ccm_memory(idx, - tests[x].key, 16, - &skey, - tests[x].nonce, tests[x].noncelen, - tests[x].header, tests[x].headerlen, - (unsigned char*)tests[x].pt, tests[x].ptlen, - buf, - tag, &taglen, 0)) != CRYPT_OK) { - return err; - } - /* run a second time to make sure skey is not touched */ - if ((err = ccm_memory(idx, - tests[x].key, 16, - &skey, - tests[x].nonce, tests[x].noncelen, - tests[x].header, tests[x].headerlen, - (unsigned char*)tests[x].pt, tests[x].ptlen, - buf, - tag, &taglen, 0)) != CRYPT_OK) { - return err; - } - } else { - if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_process(&ccm, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, CCM_ENCRYPT)) != CRYPT_OK) { - return err; - } - if ((err = ccm_done(&ccm, tag, &taglen)) != CRYPT_OK) { - return err; - } - } - - if (compare_testvector(buf, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "CCM encrypt data", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - if (compare_testvector(tag, taglen, tests[x].tag, tests[x].taglen, "CCM encrypt tag", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if (y == 0) { - XMEMCPY(tag3, tests[x].tag, tests[x].taglen); - taglen = tests[x].taglen; - if ((err = ccm_memory(idx, - tests[x].key, 16, - NULL, - tests[x].nonce, tests[x].noncelen, - tests[x].header, tests[x].headerlen, - buf2, tests[x].ptlen, - buf, - tag3, &taglen, 1 )) != CRYPT_OK) { - return err; - } - } else { - if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { - return err; - } - if ((err = ccm_process(&ccm, buf2, tests[x].ptlen, buf, CCM_DECRYPT)) != CRYPT_OK) { - return err; - } - if ((err = ccm_done(&ccm, tag2, &taglen)) != CRYPT_OK) { - return err; - } - } - - - if (compare_testvector(buf2, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "CCM decrypt data", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - if (y == 0) { - /* check if decryption with the wrong tag does not reveal the plaintext */ - XMEMCPY(tag3, tests[x].tag, tests[x].taglen); - tag3[0] ^= 0xff; /* set the tag to the wrong value */ - taglen = tests[x].taglen; - if (ccm_memory(idx, - tests[x].key, 16, - NULL, - tests[x].nonce, tests[x].noncelen, - tests[x].header, tests[x].headerlen, - buf2, tests[x].ptlen, - buf, - tag3, &taglen, 1 ) != CRYPT_ERROR) { - return CRYPT_FAIL_TESTVECTOR; - } - if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } else { - if (compare_testvector(tag2, taglen, tests[x].tag, tests[x].taglen, "CCM decrypt tag", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - if (y == 0) { - ecb_done(&skey); - } - } - } - - /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/452 */ - { - unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; - unsigned char iv[] = { 0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51 }; - unsigned char valid_tag[] = { 0x23,0x1a,0x2d,0x8f }; - unsigned char invalid_tag[] = { 0x23,0x1a,0x2d,0x8f,0x6a }; - unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; - unsigned char ct[] = { 0xd3,0xda,0xb1,0xee,0x49,0x4c,0xc2,0x29,0x09,0x9d,0x6c,0xac,0x7d,0xf1,0x4a,0xdd }; - unsigned char pt[20] = { 0 }; - - /* VALID tag */ - taglen = sizeof(valid_tag); - err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, - pt, sizeof(ct), ct, valid_tag, &taglen, CCM_DECRYPT); - if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* INVALID tag */ - taglen = sizeof(invalid_tag); - err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, - pt, sizeof(ct), ct, invalid_tag, &taglen, CCM_DECRYPT); - if (err == CRYPT_OK) { - return CRYPT_FAIL_TESTVECTOR; /* should fail */ - } - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c deleted file mode 100644 index dc6b5bb..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_add_aad.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Add AAD to the ChaCha20Poly1305 state - @param st The ChaCha20Poly1305 state - @param in The additional authentication data to add to the ChaCha20Poly1305 state - @param inlen The length of the ChaCha20Poly1305 data. - @return CRYPT_OK on success - */ -int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen) -{ - int err; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(st != NULL); - - if (st->aadflg == 0) return CRYPT_ERROR; - if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; - st->aadlen += (ulong64)inlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c deleted file mode 100644 index e51322a..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_decrypt.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Decrypt bytes of ciphertext with ChaCha20Poly1305 - @param st The ChaCha20Poly1305 state - @param in The ciphertext - @param inlen The length of the input (octets) - @param out [out] The plaintext (length inlen) - @return CRYPT_OK if successful -*/ -int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char padzero[16] = { 0 }; - unsigned long padlen; - int err; - - LTC_ARGCHK(st != NULL); - - if (st->aadflg) { - padlen = 16 - (unsigned long)(st->aadlen % 16); - if (padlen < 16) { - if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; - } - st->aadflg = 0; /* no more AAD */ - } - if (st->aadflg) st->aadflg = 0; /* no more AAD */ - if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; - st->ctlen += (ulong64)inlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c deleted file mode 100644 index b27ae66..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_done.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Terminate a ChaCha20Poly1305 stream - @param st The ChaCha20Poly1305 state - @param tag [out] The destination for the MAC tag - @param taglen [in/out] The length of the MAC tag - @return CRYPT_OK on success - */ -int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen) -{ - unsigned char padzero[16] = { 0 }; - unsigned long padlen; - unsigned char buf[16]; - int err; - - LTC_ARGCHK(st != NULL); - - if (!st->openssh_compat) { - padlen = 16 - (unsigned long)(st->ctlen % 16); - if (padlen < 16) { - if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; - } - STORE64L(st->aadlen, buf); - STORE64L(st->ctlen, buf + 8); - if ((err = poly1305_process(&st->poly, buf, 16)) != CRYPT_OK) return err; - } - if ((err = poly1305_done(&st->poly, tag, taglen)) != CRYPT_OK) return err; - if ((err = chacha_done(&st->chacha)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c deleted file mode 100644 index 2a4208e..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_encrypt.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Encrypt bytes of ciphertext with ChaCha20Poly1305 - @param st The ChaCha20Poly1305 state - @param in The plaintext - @param inlen The length of the input (octets) - @param out [out] The ciphertext (length inlen) - @return CRYPT_OK if successful -*/ -int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char padzero[16] = { 0 }; - unsigned long padlen; - int err; - - LTC_ARGCHK(st != NULL); - - if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; - if (st->aadflg) { - padlen = 16 - (unsigned long)(st->aadlen % 16); - if (padlen < 16) { - if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; - } - st->aadflg = 0; /* no more AAD */ - } - if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK) return err; - st->ctlen += (ulong64)inlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c deleted file mode 100644 index 14ddb6c..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_init.c +++ /dev/null @@ -1,21 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Initialize an ChaCha20Poly1305 context (only the key) - @param st [out] The destination of the ChaCha20Poly1305 state - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen) -{ - XMEMSET(st, 0, sizeof(*st)); - return chacha_setup(&st->chacha, key, keylen, 20); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c deleted file mode 100644 index e0f4bd9..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_memory.c +++ /dev/null @@ -1,76 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Process an entire ChaCha20Poly1305 packet in one call. - @param key The secret key - @param keylen The length of the secret key - @param iv The initialization vector - @param ivlen The length of the initialization vector - @param aad The additional authentication data (header) - @param aadlen The length of the aad - @param in The plaintext - @param inlen The length of the plaintext (ciphertext length is the same) - @param out The ciphertext - @param tag [out] The MAC tag - @param taglen [in/out] The MAC tag length - @param direction Encrypt or Decrypt mode (CHACHA20POLY1305_ENCRYPT or CHACHA20POLY1305_DECRYPT) - @return CRYPT_OK on success - */ -int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *aad, unsigned long aadlen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, - unsigned char *tag, unsigned long *taglen, - int direction) -{ - chacha20poly1305_state st; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(iv != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - if ((err = chacha20poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - - st.openssh_compat = (direction & CHACHA20POLY1305_OPENSSH_COMPAT) ? 1 : 0; - direction &= ~(CHACHA20POLY1305_OPENSSH_COMPAT); - - if ((err = chacha20poly1305_setiv(&st, iv, ivlen)) != CRYPT_OK) { goto LBL_ERR; } - if (aad && aadlen > 0) { - if ((err = chacha20poly1305_add_aad(&st, aad, aadlen)) != CRYPT_OK) { goto LBL_ERR; } - } - if (direction == CHACHA20POLY1305_ENCRYPT) { - if ((err = chacha20poly1305_encrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = chacha20poly1305_done(&st, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; } - } - else if (direction == CHACHA20POLY1305_DECRYPT) { - unsigned char buf[MAXBLOCKSIZE]; - unsigned long buflen = sizeof(buf); - if ((err = chacha20poly1305_decrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = chacha20poly1305_done(&st, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } - if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { - err = CRYPT_ERROR; - goto LBL_ERR; - } - } - else { - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(chacha20poly1305_state)); -#endif - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c deleted file mode 100644 index d5ec3e6..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv.c +++ /dev/null @@ -1,58 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Set IV + counter data to the ChaCha20Poly1305 state and reset the context - @param st The ChaCha20Poly1305 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 12 or 8) - @return CRYPT_OK on success - */ -int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen) -{ - chacha_state tmp_st; - int i, err; - unsigned char polykey[32]; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - LTC_ARGCHK(ivlen == 12 || ivlen == 8); - - /* set IV for chacha20 */ - if (ivlen == 12) { - /* IV 96bit */ - if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; - } - else { - /* IV 64bit */ - if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; - } - - /* copy chacha20 key to temporary state */ - for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i]; - tmp_st.rounds = 20; - /* set IV */ - if (ivlen == 12) { - /* IV 32bit */ - if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; - } - else { - /* IV 64bit */ - if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; - } - /* (re)generate new poly1305 key */ - if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err; - /* (re)initialise poly1305 */ - if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err; - st->ctlen = 0; - st->aadlen = 0; - st->aadflg = 1; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c deleted file mode 100644 index 75da634..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c +++ /dev/null @@ -1,30 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -/** - Set IV + counter data (with RFC7905-magic) to the ChaCha20Poly1305 state and reset the context - @param st The ChaCha20Poly1305 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 12 or 8) - @param sequence_number 64bit sequence number which is incorporated into IV as described in RFC7905 - @return CRYPT_OK on success - */ -int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number) -{ - int i; - unsigned char combined_iv[12] = { 0 }; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - LTC_ARGCHK(ivlen == 12); - - STORE64L(sequence_number, combined_iv + 4); - for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i]; - return chacha20poly1305_setiv(st, combined_iv, 12); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c b/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c deleted file mode 100644 index 30d4973..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/chachapoly/chacha20poly1305_test.c +++ /dev/null @@ -1,159 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20POLY1305_MODE - -int chacha20poly1305_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - chacha20poly1305_state st1, st2; - unsigned char k[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }; - unsigned char i12[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; - unsigned char i8[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43 }; - unsigned char aad[] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; - unsigned char enc[] = { 0xD3, 0x1A, 0x8D, 0x34, 0x64, 0x8E, 0x60, 0xDB, 0x7B, 0x86, 0xAF, 0xBC, 0x53, 0xEF, 0x7E, 0xC2, - 0xA4, 0xAD, 0xED, 0x51, 0x29, 0x6E, 0x08, 0xFE, 0xA9, 0xE2, 0xB5, 0xA7, 0x36, 0xEE, 0x62, 0xD6, - 0x3D, 0xBE, 0xA4, 0x5E, 0x8C, 0xA9, 0x67, 0x12, 0x82, 0xFA, 0xFB, 0x69, 0xDA, 0x92, 0x72, 0x8B, - 0x1A, 0x71, 0xDE, 0x0A, 0x9E, 0x06, 0x0B, 0x29, 0x05, 0xD6, 0xA5, 0xB6, 0x7E, 0xCD, 0x3B, 0x36, - 0x92, 0xDD, 0xBD, 0x7F, 0x2D, 0x77, 0x8B, 0x8C, 0x98, 0x03, 0xAE, 0xE3, 0x28, 0x09, 0x1B, 0x58, - 0xFA, 0xB3, 0x24, 0xE4, 0xFA, 0xD6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8B, 0x48, 0x31, 0xD7, 0xBC, - 0x3F, 0xF4, 0xDE, 0xF0, 0x8E, 0x4B, 0x7A, 0x9D, 0xE5, 0x76, 0xD2, 0x65, 0x86, 0xCE, 0xC6, 0x4B, - 0x61, 0x16 }; - unsigned char tag[] = { 0x1A, 0xE1, 0x0B, 0x59, 0x4F, 0x09, 0xE2, 0x6A, 0x7E, 0x90, 0x2E, 0xCB, 0xD0, 0x60, 0x06, 0x91 }; - char m[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; - unsigned long mlen = XSTRLEN(m); - unsigned long len; - unsigned char rfc7905_pt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; - unsigned char rfc7905_enc[] = { 0xE4, 0x62, 0x85, 0xB4, 0x29, 0x95, 0x34, 0x96, 0xAB, 0xFB, 0x67, 0xCD, 0xAE, 0xAC, 0x94, 0x1E }; - unsigned char rfc7905_tag[] = { 0x16, 0x2C, 0x92, 0x48, 0x2A, 0xDB, 0xD3, 0x5D, 0x48, 0xBE, 0xC6, 0xFF, 0x10, 0x9C, 0xBA, 0xE4 }; - unsigned char ct[1000], pt[1000], emac[16], dmac[16]; - int err; - - /* encrypt IV 96bit */ - if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv(&st1, i12, sizeof(i12))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; - /* encrypt piece by piece */ - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, 25, ct)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 25, 10, ct + 25)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 35, 35, ct + 35)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 70, 5, ct + 70)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 75, 5, ct + 75)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 80, mlen - 80, ct + 80)) != CRYPT_OK) return err; - len = sizeof(emac); - if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; - - if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* decrypt IV 96bit */ - if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv(&st2, i12, sizeof(i12))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_decrypt(&st2, ct, 21, pt)) != CRYPT_OK) return err; - if ((err = chacha20poly1305_decrypt(&st2, ct + 21, mlen - 21, pt + 21)) != CRYPT_OK) return err; - len = sizeof(dmac); - if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; - - if (compare_testvector(pt, mlen, m, mlen, "DEC-PT", 3) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(dmac, len, tag, sizeof(tag), "DEC-TAG", 4) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* chacha20poly1305_memory - encrypt */ - len = sizeof(emac); - if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), (unsigned char *)m, - mlen, ct, emac, &len, CHACHA20POLY1305_ENCRYPT)) != CRYPT_OK) return err; - if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG2", 2) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* chacha20poly1305_memory - decrypt */ - len = sizeof(dmac); - XMEMCPY(dmac, tag, sizeof(tag)); - if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), - ct, mlen, pt, dmac, &len, CHACHA20POLY1305_DECRYPT)) != CRYPT_OK) return err; - if (compare_testvector(pt, mlen, m, mlen, "DEC-PT2", 3) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* encrypt - rfc7905 */ - if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, rfc7905_pt, 16, ct)) != CRYPT_OK) return err; - len = sizeof(emac); - if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; - - if (compare_testvector(ct, 16, rfc7905_enc, 16, "ENC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(emac, len, rfc7905_tag, 16, "ENC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* decrypt - rfc7905 */ - if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_decrypt(&st1, ct, 16, pt)) != CRYPT_OK) return err; - len = sizeof(dmac); - if ((err = chacha20poly1305_done(&st1, dmac, &len)) != CRYPT_OK) return err; - - if (compare_testvector(pt, 16, rfc7905_pt, 16, "DEC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(dmac, len, rfc7905_tag, 16, "DEC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* encrypt IV 64bit */ - if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv(&st1, i8, sizeof(i8))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, mlen, ct)) != CRYPT_OK) return err; - len = sizeof(emac); - if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; - - /* decrypt IV 64bit */ - if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_setiv(&st2, i8, sizeof(i8))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; - if ((err = chacha20poly1305_decrypt(&st2, ct, mlen, pt)) != CRYPT_OK) return err; - len = sizeof(dmac); - if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; - - if (compare_testvector(pt, mlen, m, mlen, "DEC-PT4", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(dmac, len, emac, len, "DEC-TAG4", 2) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ - { - unsigned char key[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, - 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; - unsigned char iv[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b }; - unsigned char valid_tag[] = { 0xa3,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; - unsigned char invalid_tag[] = { 0xa2,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; - unsigned char waad[] = { 0x61,0x61,0x64 }; - unsigned char wct[] = { 0x00 }; - unsigned char wpt[20] = { 0 }; - unsigned char wtag[20] = { 0 }; - unsigned long taglen; - - /* encrypt */ - taglen = sizeof(wtag); - err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), - wpt, 0, wct, wtag, &taglen, CHACHA20POLY1305_ENCRYPT); - if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(wtag, taglen, valid_tag, sizeof(valid_tag), "WYCH", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - - /* VALID tag */ - taglen = sizeof(valid_tag); - err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), - wpt, 0, wct, valid_tag, &taglen, CHACHA20POLY1305_DECRYPT); - if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; - - /* INVALID tag */ - taglen = sizeof(invalid_tag); - err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), - wpt, 0, wct, invalid_tag, &taglen, CHACHA20POLY1305_DECRYPT); - if (err == CRYPT_OK) { - return CRYPT_FAIL_TESTVECTOR; /* should fail */ - } - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_addheader.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_addheader.c deleted file mode 100644 index a6b8f76..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_addheader.c +++ /dev/null @@ -1,26 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @file eax_addheader.c - EAX implementation, add meta-data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - add header (metadata) to the stream - @param eax The current EAX state - @param header The header (meta-data) data you wish to add to the state - @param length The length of the header data - @return CRYPT_OK if successful -*/ -int eax_addheader(eax_state *eax, const unsigned char *header, - unsigned long length) -{ - LTC_ARGCHK(eax != NULL); - LTC_ARGCHK(header != NULL); - return omac_process(&eax->headeromac, header, length); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt.c deleted file mode 100644 index cc03c5c..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_decrypt.c - EAX implementation, decrypt block, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - Decrypt data with the EAX protocol - @param eax The EAX state - @param ct The ciphertext - @param pt [out] The plaintext - @param length The length (octets) of the ciphertext - @return CRYPT_OK if successful -*/ -int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, - unsigned long length) -{ - int err; - - LTC_ARGCHK(eax != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - /* omac ciphertext */ - if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { - return err; - } - - /* decrypt */ - return ctr_decrypt(ct, pt, length, &eax->ctr); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c deleted file mode 100644 index 5429d4a..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_decrypt_verify_memory.c +++ /dev/null @@ -1,99 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_decrypt_verify_memory.c - EAX implementation, decrypt block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - Decrypt a block of memory and verify the provided MAC tag with EAX - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the key (octets) - @param nonce The nonce data (use once) for the session - @param noncelen The length of the nonce data. - @param header The session header data - @param headerlen The length of the header (octets) - @param ct The ciphertext - @param ctlen The length of the ciphertext (octets) - @param pt [out] The plaintext - @param tag The authentication tag provided by the encoder - @param taglen [in/out] The length of the tag (octets) - @param stat [out] The result of the decryption (1==valid tag, 0==invalid) - @return CRYPT_OK if successful regardless of the resulting tag comparison -*/ -int eax_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat) -{ - int err; - eax_state *eax; - unsigned char *buf; - unsigned long buflen; - - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - - /* default to zero */ - *stat = 0; - - /* limit taglen */ - taglen = MIN(taglen, MAXBLOCKSIZE); - - /* allocate ram */ - buf = XMALLOC(taglen); - eax = XMALLOC(sizeof(*eax)); - if (eax == NULL || buf == NULL) { - if (eax != NULL) { - XFREE(eax); - } - if (buf != NULL) { - XFREE(buf); - } - return CRYPT_MEM; - } - - if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - buflen = taglen; - if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* compare tags */ - if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { - *stat = 1; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf, taglen); - zeromem(eax, sizeof(*eax)); -#endif - - XFREE(eax); - XFREE(buf); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_done.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_done.c deleted file mode 100644 index f2362cf..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_done.c +++ /dev/null @@ -1,82 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_done.c - EAX implementation, terminate session, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - Terminate an EAX session and get the tag. - @param eax The EAX state - @param tag [out] The destination of the authentication tag - @param taglen [in/out] The max length and resulting length of the authentication tag - @return CRYPT_OK if successful -*/ -int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) -{ - int err; - unsigned char *headermac, *ctmac; - unsigned long x, len; - - LTC_ARGCHK(eax != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - /* allocate ram */ - headermac = XMALLOC(MAXBLOCKSIZE); - ctmac = XMALLOC(MAXBLOCKSIZE); - - if (headermac == NULL || ctmac == NULL) { - if (headermac != NULL) { - XFREE(headermac); - } - if (ctmac != NULL) { - XFREE(ctmac); - } - return CRYPT_MEM; - } - - /* finish ctomac */ - len = MAXBLOCKSIZE; - if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* finish headeromac */ - - /* note we specifically don't reset len so the two lens are minimal */ - - if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* terminate the CTR chain */ - if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* compute N xor H xor C */ - for (x = 0; x < len && x < *taglen; x++) { - tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; - } - *taglen = x; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(ctmac, MAXBLOCKSIZE); - zeromem(headermac, MAXBLOCKSIZE); - zeromem(eax, sizeof(*eax)); -#endif - - XFREE(ctmac); - XFREE(headermac); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt.c deleted file mode 100644 index dba3239..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt.c +++ /dev/null @@ -1,39 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_encrypt.c - EAX implementation, encrypt block by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - Encrypt with EAX a block of data. - @param eax The EAX state - @param pt The plaintext to encrypt - @param ct [out] The ciphertext as encrypted - @param length The length of the plaintext (octets) - @return CRYPT_OK if successful -*/ -int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, - unsigned long length) -{ - int err; - - LTC_ARGCHK(eax != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - /* encrypt */ - if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { - return err; - } - - /* omac ciphertext */ - return omac_process(&eax->ctomac, ct, length); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c deleted file mode 100644 index 76aeec2..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_encrypt_authenticate_memory.c +++ /dev/null @@ -1,70 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_encrypt_authenticate_memory.c - EAX implementation, encrypt a block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - EAX encrypt and produce an authentication tag - @param cipher The index of the cipher desired - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param nonce The session nonce [use once] - @param noncelen The length of the nonce - @param header The header for the session - @param headerlen The length of the header (octets) - @param pt The plaintext - @param ptlen The length of the plaintext (octets) - @param ct [out] The ciphertext - @param tag [out] The destination tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int eax_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen) -{ - int err; - eax_state *eax; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - eax = XMALLOC(sizeof(*eax)); - - if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(eax, sizeof(*eax)); -#endif - - XFREE(eax); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_init.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_init.c deleted file mode 100644 index dfa11c3..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_init.c +++ /dev/null @@ -1,138 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_init.c - EAX implementation, initialized EAX state, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_EAX_MODE - -/** - Initialized an EAX state - @param eax [out] The EAX state to initialize - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The use-once nonce for the session - @param noncelen The length of the nonce (octets) - @param header The header for the EAX state - @param headerlen The header length (octets) - @return CRYPT_OK if successful -*/ -int eax_init(eax_state *eax, int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen) -{ - unsigned char *buf; - int err, blklen; - omac_state *omac; - unsigned long len; - - - LTC_ARGCHK(eax != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(nonce != NULL); - if (headerlen > 0) { - LTC_ARGCHK(header != NULL); - } - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - blklen = cipher_descriptor[cipher].block_length; - - /* allocate ram */ - buf = XMALLOC(MAXBLOCKSIZE); - omac = XMALLOC(sizeof(*omac)); - - if (buf == NULL || omac == NULL) { - if (buf != NULL) { - XFREE(buf); - } - if (omac != NULL) { - XFREE(omac); - } - return CRYPT_MEM; - } - - /* N = LTC_OMAC_0K(nonce) */ - zeromem(buf, MAXBLOCKSIZE); - if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* omac the [0]_n */ - if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* omac the nonce */ - if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* store result */ - len = sizeof(eax->N); - if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* H = LTC_OMAC_1K(header) */ - zeromem(buf, MAXBLOCKSIZE); - buf[blklen - 1] = 1; - - if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* omac the [1]_n */ - if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* omac the header */ - if (headerlen != 0) { - if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* note we don't finish the headeromac, this allows us to add more header later */ - - /* setup the CTR mode */ - if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* setup the LTC_OMAC for the ciphertext */ - if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* omac [2]_n */ - zeromem(buf, MAXBLOCKSIZE); - buf[blklen-1] = 2; - if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf, MAXBLOCKSIZE); - zeromem(omac, sizeof(*omac)); -#endif - - XFREE(omac); - XFREE(buf); - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_test.c b/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_test.c deleted file mode 100644 index adfa879..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/eax/eax_test.c +++ /dev/null @@ -1,249 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file eax_test.c - EAX implementation, self-test, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_EAX_MODE - -/** - Test the EAX implementation - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int eax_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - int keylen, - noncelen, - headerlen, - msglen; - - unsigned char key[MAXBLOCKSIZE], - nonce[MAXBLOCKSIZE], - header[MAXBLOCKSIZE], - plaintext[MAXBLOCKSIZE], - ciphertext[MAXBLOCKSIZE], - tag[MAXBLOCKSIZE]; - } tests[] = { - -/* NULL message */ -{ - 16, 0, 0, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0 }, - /* header */ - { 0 }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, - 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } -}, - -/* test with nonce */ -{ - 16, 16, 0, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* header */ - { 0 }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, - 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } -}, - -/* test with header [no nonce] */ -{ - 16, 0, 16, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0 }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, - 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } -}, - -/* test with header + nonce + plaintext */ -{ - 16, 16, 16, 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* plaintext */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* ciphertext */ - { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, - 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, - 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, - 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, - /* tag */ - { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, - 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } -}, - -/* test with header + nonce + plaintext [not even sizes!] */ -{ - 16, 15, 14, 29, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, - /* plaintext */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c }, - /* ciphertext */ - { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, - 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, - 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, - 0x8a, 0x24, 0xdb, 0x86, 0x8b }, - /* tag */ - { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, - 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } -}, - -/* Vectors from Brian Gladman */ - -{ - 16, 16, 8, 0, - /* key */ - { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, - 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, - /* nonce */ - { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, - 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, - /* header */ - { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, - /* PT */ - { 0x00 }, - /* CT */ - { 0x00 }, - /* tag */ - { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, - 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } -}, - -{ - 16, 16, 8, 2, - /* key */ - { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, - 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, - /* nonce */ - { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, - 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, - /* header */ - { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, - /* PT */ - { 0xf7, 0xfb }, - /* CT */ - { 0x19, 0xdd }, - /* tag */ - { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, - 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } -}, - -{ - 16, 16, 8, 5, - /* key */ - { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, - 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, - /* nonce */ - { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, - 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, - /* header */ - { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, - /* PT */ - { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, - /* CT */ - { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, - /* Tag */ - { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, - 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } -} - -}; - int err, x, idx, res; - unsigned long len; - unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - len = sizeof(outtag); - if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, - tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, - tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { - return err; - } - if (compare_testvector(outtag, len, tests[x].tag, len, "EAX Tag", x) || - compare_testvector(outct, tests[x].msglen, tests[x].ciphertext, tests[x].msglen, "EAX CT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* test decrypt */ - if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, - tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, - outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { - return err; - } - if ((res != 1) || compare_testvector(outct, tests[x].msglen, tests[x].plaintext, tests[x].msglen, "EAX", x)) { -#ifdef LTC_TEST_DBG - printf("\n\nEAX: Failure-decrypt - res = %d\n", res); -#endif - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* LTC_EAX_MODE */ diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_aad.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_aad.c deleted file mode 100644 index 67a86fe..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_aad.c +++ /dev/null @@ -1,109 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_add_aad.c - GCM implementation, Add AAD data to the stream, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Add AAD to the GCM state - @param gcm The GCM state - @param adata The additional authentication data to add to the GCM state - @param adatalen The length of the AAD data. - @return CRYPT_OK on success - */ -int gcm_add_aad(gcm_state *gcm, - const unsigned char *adata, unsigned long adatalen) -{ - unsigned long x; -#ifdef LTC_FAST - unsigned long y; -#endif - - LTC_ARGCHK(gcm != NULL); - if (adatalen > 0) { - LTC_ARGCHK(adata != NULL); - } - - if (gcm->buflen > 16 || gcm->buflen < 0) { - return CRYPT_INVALID_ARG; - } - - /* in IV mode? */ - if (gcm->mode == LTC_GCM_MODE_IV) { - /* IV length must be > 0 */ - if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR; - /* let's process the IV */ - if (gcm->ivmode || gcm->buflen != 12) { - for (x = 0; x < (unsigned long)gcm->buflen; x++) { - gcm->X[x] ^= gcm->buf[x]; - } - if (gcm->buflen) { - gcm->totlen += gcm->buflen * CONST64(8); - gcm_mult_h(gcm, gcm->X); - } - - /* mix in the length */ - zeromem(gcm->buf, 8); - STORE64H(gcm->totlen, gcm->buf+8); - for (x = 0; x < 16; x++) { - gcm->X[x] ^= gcm->buf[x]; - } - gcm_mult_h(gcm, gcm->X); - - /* copy counter out */ - XMEMCPY(gcm->Y, gcm->X, 16); - zeromem(gcm->X, 16); - } else { - XMEMCPY(gcm->Y, gcm->buf, 12); - gcm->Y[12] = 0; - gcm->Y[13] = 0; - gcm->Y[14] = 0; - gcm->Y[15] = 1; - } - XMEMCPY(gcm->Y_0, gcm->Y, 16); - zeromem(gcm->buf, 16); - gcm->buflen = 0; - gcm->totlen = 0; - gcm->mode = LTC_GCM_MODE_AAD; - } - - if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) { - return CRYPT_INVALID_ARG; - } - - x = 0; -#ifdef LTC_FAST - if (gcm->buflen == 0 && adatalen > 15) { - for (x = 0; x < (adatalen & ~15); x += 16) { - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y])); - } - gcm_mult_h(gcm, gcm->X); - gcm->totlen += 128; - } - adata += x; - } -#endif - - - /* start adding AAD data to the state */ - for (; x < adatalen; x++) { - gcm->X[gcm->buflen++] ^= *adata++; - - if (gcm->buflen == 16) { - /* GF mult it */ - gcm_mult_h(gcm, gcm->X); - gcm->buflen = 0; - gcm->totlen += 128; - } - } - - return CRYPT_OK; -} -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_iv.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_iv.c deleted file mode 100644 index b37a55b..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_add_iv.c +++ /dev/null @@ -1,76 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_add_iv.c - GCM implementation, add IV data to the state, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Add IV data to the GCM state - @param gcm The GCM state - @param IV The initial value data to add - @param IVlen The length of the IV - @return CRYPT_OK on success - */ -int gcm_add_iv(gcm_state *gcm, - const unsigned char *IV, unsigned long IVlen) -{ - unsigned long x, y; - - LTC_ARGCHK(gcm != NULL); - if (IVlen > 0) { - LTC_ARGCHK(IV != NULL); - } - - /* must be in IV mode */ - if (gcm->mode != LTC_GCM_MODE_IV) { - return CRYPT_INVALID_ARG; - } - - if (gcm->buflen >= 16 || gcm->buflen < 0) { - return CRYPT_INVALID_ARG; - } - - /* trip the ivmode flag */ - if (IVlen + gcm->buflen > 12) { - gcm->ivmode |= 1; - } - - x = 0; -#ifdef LTC_FAST - if (gcm->buflen == 0) { - for (x = 0; x < (IVlen & ~15); x += 16) { - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&IV[x + y])); - } - gcm_mult_h(gcm, gcm->X); - gcm->totlen += 128; - } - IV += x; - } -#endif - - /* start adding IV data to the state */ - for (; x < IVlen; x++) { - gcm->buf[gcm->buflen++] = *IV++; - - if (gcm->buflen == 16) { - /* GF mult it */ - for (y = 0; y < 16; y++) { - gcm->X[y] ^= gcm->buf[y]; - } - gcm_mult_h(gcm, gcm->X); - gcm->buflen = 0; - gcm->totlen += 128; - } - } - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_done.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_done.c deleted file mode 100644 index 5e135d1..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_done.c +++ /dev/null @@ -1,76 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_done.c - GCM implementation, Terminate the stream, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Terminate a GCM stream - @param gcm The GCM state - @param tag [out] The destination for the MAC tag - @param taglen [in/out] The length of the MAC tag - @return CRYPT_OK on success - */ -int gcm_done(gcm_state *gcm, - unsigned char *tag, unsigned long *taglen) -{ - unsigned long x; - int err; - - LTC_ARGCHK(gcm != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - if (gcm->buflen > 16 || gcm->buflen < 0) { - return CRYPT_INVALID_ARG; - } - - if (gcm->mode == LTC_GCM_MODE_IV) { - /* let's process the IV */ - if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; - } - - if (gcm->mode == LTC_GCM_MODE_AAD) { - /* let's process the AAD */ - if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err; - } - - if (gcm->mode != LTC_GCM_MODE_TEXT) { - return CRYPT_INVALID_ARG; - } - - /* handle remaining ciphertext */ - if (gcm->buflen) { - gcm->pttotlen += gcm->buflen * CONST64(8); - gcm_mult_h(gcm, gcm->X); - } - - /* length */ - STORE64H(gcm->totlen, gcm->buf); - STORE64H(gcm->pttotlen, gcm->buf+8); - for (x = 0; x < 16; x++) { - gcm->X[x] ^= gcm->buf[x]; - } - gcm_mult_h(gcm, gcm->X); - - /* encrypt original counter */ - if ((err = ecb_encrypt_block(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) { - return err; - } - for (x = 0; x < 16 && x < *taglen; x++) { - tag[x] = gcm->buf[x] ^ gcm->X[x]; - } - *taglen = x; - - ecb_done(&gcm->K); - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_gf_mult.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_gf_mult.c deleted file mode 100644 index f2669ec..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_gf_mult.c +++ /dev/null @@ -1,213 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_gf_mult.c - GCM implementation, do the GF mult, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (defined(LTC_GCM_MODE) && defined(LTC_FAST)) - -/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the - * lower 16 bits are not zero'ed I removed the upper 14 bytes */ -const unsigned char gcm_shift_table[256*2] = { -0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e, -0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e, -0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e, -0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e, -0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e, -0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e, -0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e, -0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e, -0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce, -0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde, -0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee, -0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe, -0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e, -0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e, -0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae, -0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe, -0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e, -0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e, -0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e, -0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e, -0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e, -0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e, -0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e, -0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e, -0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce, -0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde, -0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee, -0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe, -0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e, -0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e, -0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae, -0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe }; - -#endif - - -#if defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE) - -#ifndef LTC_FAST -/* right shift */ -static void s_gcm_rightshift(unsigned char *a) -{ - int x; - for (x = 15; x > 0; x--) { - a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80); - } - a[0] >>= 1; -} - -/* c = b*a */ -static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; -static const unsigned char poly[] = { 0x00, 0xE1 }; - - -/** - GCM GF multiplier (internal use only) bitserial - @param a First value - @param b Second value - @param c Destination for a * b - */ -void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) -{ - unsigned char Z[16], V[16]; - unsigned char x, y, z; - - zeromem(Z, 16); - XMEMCPY(V, a, 16); - for (x = 0; x < 128; x++) { - if (b[x>>3] & mask[x&7]) { - for (y = 0; y < 16; y++) { - Z[y] ^= V[y]; - } - } - z = V[15] & 0x01; - s_gcm_rightshift(V); - V[0] ^= poly[z]; - } - XMEMCPY(c, Z, 16); -} - -#else - -/* map normal numbers to "ieee" way ... e.g. bit reversed */ -#define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) ) - -#define BPD (sizeof(LTC_FAST_TYPE) * 8) -#define WPV (1 + (16 / sizeof(LTC_FAST_TYPE))) - -/** - GCM GF multiplier (internal use only) word oriented - @param a First value - @param b Second value - @param c Destination for a * b - */ -void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) -{ - int i, j, k, u; - LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z; - unsigned char pTmp[32]; - - /* create simple tables */ - zeromem(B[0], sizeof(B[0])); - zeromem(B[M(1)], sizeof(B[M(1)])); - -#ifdef ENDIAN_32BITWORD - for (i = 0; i < 4; i++) { - LOAD32H(B[M(1)][i], a + (i<<2)); - LOAD32L(pB[i], b + (i<<2)); - } -#else - for (i = 0; i < 2; i++) { - LOAD64H(B[M(1)][i], a + (i<<3)); - LOAD64L(pB[i], b + (i<<3)); - } -#endif - - /* now create 2, 4 and 8 */ - B[M(2)][0] = B[M(1)][0] >> 1; - B[M(4)][0] = B[M(1)][0] >> 2; - B[M(8)][0] = B[M(1)][0] >> 3; - for (i = 1; i < (int)WPV; i++) { - B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1); - B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2); - B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3); - } - - /* now all values with two bits which are 3, 5, 6, 9, 10, 12 */ - for (i = 0; i < (int)WPV; i++) { - B[M(3)][i] = B[M(1)][i] ^ B[M(2)][i]; - B[M(5)][i] = B[M(1)][i] ^ B[M(4)][i]; - B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i]; - B[M(9)][i] = B[M(1)][i] ^ B[M(8)][i]; - B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i]; - B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i]; - - /* now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */ - B[M(7)][i] = B[M(3)][i] ^ B[M(4)][i]; - B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i]; - B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i]; - B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i]; - B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i]; - } - - zeromem(tmp, sizeof(tmp)); - - /* compute product four bits of each word at a time */ - /* for each nibble */ - for (i = (BPD/4)-1; i >= 0; i--) { - /* for each word */ - for (j = 0; j < (int)(WPV-1); j++) { - /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */ - u = (pB[j] >> ((i^1)<<2)) & 15; - - /* add offset by the word count the table looked up value to the result */ - for (k = 0; k < (int)WPV; k++) { - tmp[k+j] ^= B[u][k]; - } - } - /* shift result up by 4 bits */ - if (i != 0) { - for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) { - zz = tmp[j] << (BPD-4); - tmp[j] = (tmp[j] >> 4) | z; - z = zz; - } - } - } - - /* store product */ -#ifdef ENDIAN_32BITWORD - for (i = 0; i < 8; i++) { - STORE32H(tmp[i], pTmp + (i<<2)); - } -#else - for (i = 0; i < 4; i++) { - STORE64H(tmp[i], pTmp + (i<<3)); - } -#endif - - /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */ - for (i = 31; i >= 16; i--) { - pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)]; - pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1]; - } - - for (i = 0; i < 16; i++) { - c[i] = pTmp[i]; - } - -} - -#undef M -#undef BPD -#undef WPV - -#endif - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_init.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_init.c deleted file mode 100644 index 96abfe2..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_init.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_init.c - GCM implementation, initialize state, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Initialize a GCM state - @param gcm The GCM state to initialize - @param cipher The index of the cipher to use - @param key The secret key - @param keylen The length of the secret key - @return CRYPT_OK on success - */ -int gcm_init(gcm_state *gcm, int cipher, - const unsigned char *key, int keylen) -{ - int err; - unsigned char B[16]; -#ifdef LTC_GCM_TABLES - int x, y, z, t; -#endif - - LTC_ARGCHK(gcm != NULL); - LTC_ARGCHK(key != NULL); - -#ifdef LTC_FAST - if (16 % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* is cipher valid? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_CIPHER; - } - - /* schedule key */ - if ((err = ecb_start(cipher, key, keylen, 0, &gcm->K)) != CRYPT_OK) { - return err; - } - - /* H = E(0) */ - zeromem(B, 16); - if ((err = ecb_encrypt_block(B, gcm->H, &gcm->K)) != CRYPT_OK) { - return err; - } - - /* setup state */ - zeromem(gcm->buf, sizeof(gcm->buf)); - zeromem(gcm->X, sizeof(gcm->X)); - gcm->mode = LTC_GCM_MODE_IV; - gcm->ivmode = 0; - gcm->buflen = 0; - gcm->totlen = 0; - gcm->pttotlen = 0; - -#ifdef LTC_GCM_TABLES - /* setup tables */ - - /* generate the first table as it has no shifting (from which we make the other tables) */ - zeromem(B, 16); - for (y = 0; y < 256; y++) { - B[0] = y; - gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); - } - - /* now generate the rest of the tables based the previous table */ - for (x = 1; x < 16; x++) { - for (y = 0; y < 256; y++) { - /* now shift it right by 8 bits */ - t = gcm->PC[x-1][y][15]; - for (z = 15; z > 0; z--) { - gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; - } - gcm->PC[x][y][0] = gcm_shift_table[t<<1]; - gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; - } - } - -#endif - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_memory.c deleted file mode 100644 index 2889adb..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_memory.c +++ /dev/null @@ -1,117 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_memory.c - GCM implementation, process a packet, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_GCM_MODE - -/** - Process an entire GCM packet in one call. - @param cipher Index of cipher to use - @param key The secret key - @param keylen The length of the secret key - @param IV The initialization vector - @param IVlen The length of the initialization vector - @param adata The additional authentication data (header) - @param adatalen The length of the adata - @param pt The plaintext - @param ptlen The length of the plaintext (ciphertext length is the same) - @param ct The ciphertext - @param tag [out] The MAC tag - @param taglen [in/out] The MAC tag length - @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) - @return CRYPT_OK on success - */ -int gcm_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *IV, unsigned long IVlen, - const unsigned char *adata, unsigned long adatalen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction) -{ - void *orig; - gcm_state *gcm; - int err; - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - if (cipher_descriptor[cipher].accel_gcm_memory != NULL) { - return cipher_descriptor[cipher].accel_gcm_memory - (key, keylen, - IV, IVlen, - adata, adatalen, - pt, ptlen, - ct, - tag, taglen, - direction); - } - - - -#ifndef LTC_GCM_TABLES_SSE2 - orig = gcm = XMALLOC(sizeof(*gcm)); -#else - orig = gcm = XMALLOC(sizeof(*gcm) + 16); -#endif - if (gcm == NULL) { - return CRYPT_MEM; - } - - /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations - * note that we only modify gcm and keep orig intact. This code is not portable - * but again it's only for SSE2 anyways, so who cares? - */ -#ifdef LTC_GCM_TABLES_SSE2 - gcm = LTC_ALIGN_BUF(gcm, 16); -#endif - - if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { - goto LTC_ERR; - } - if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { - goto LTC_ERR; - } - if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { - goto LTC_ERR; - } - if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) { - goto LTC_ERR; - } - if (direction == GCM_ENCRYPT) { - if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) { - goto LTC_ERR; - } - } - else if (direction == GCM_DECRYPT) { - unsigned char buf[MAXBLOCKSIZE]; - unsigned long buflen = sizeof(buf); - if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) { - goto LTC_ERR; - } - if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { - err = CRYPT_ERROR; - } - } - else { - err = CRYPT_INVALID_ARG; - } -LTC_ERR: - gcm_reset(gcm); - XFREE(orig); - return err; -} -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_mult_h.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_mult_h.c deleted file mode 100644 index c0fd9c5..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_mult_h.c +++ /dev/null @@ -1,47 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_mult_h.c - GCM implementation, do the GF mult, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#if defined(LTC_GCM_MODE) -/** - GCM multiply by H - @param gcm The GCM state which holds the H value - @param I The value to multiply H by - */ -void gcm_mult_h(const gcm_state *gcm, unsigned char *I) -{ - unsigned char T[16]; -#ifdef LTC_GCM_TABLES - int x; -#ifdef LTC_GCM_TABLES_SSE2 - __asm__("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0])); - for (x = 1; x < 16; x++) { - __asm__("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0])); - } - __asm__("movdqa %%xmm0,(%0)"::"r"(&T)); -#else - int y; - XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); - for (x = 1; x < 16; x++) { -#ifdef LTC_FAST - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&gcm->PC[x][I[x]][y])); - } -#else - for (y = 0; y < 16; y++) { - T[y] ^= gcm->PC[x][I[x]][y]; - } -#endif /* LTC_FAST */ - } -#endif /* LTC_GCM_TABLES_SSE2 */ -#else - gcm_gf_mult(gcm->H, I, T); -#endif - XMEMCPY(I, T, 16); -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_process.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_process.c deleted file mode 100644 index b75c1d0..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_process.c +++ /dev/null @@ -1,146 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_process.c - GCM implementation, process message data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Process plaintext/ciphertext through GCM - @param gcm The GCM state - @param pt The plaintext - @param ptlen The plaintext length (ciphertext length is the same) - @param ct The ciphertext - @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) - @return CRYPT_OK on success - */ -int gcm_process(gcm_state *gcm, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - int direction) -{ - unsigned long x; - int y, err; - unsigned char b; - - LTC_ARGCHK(gcm != NULL); - if (ptlen > 0) { - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - } - - if (gcm->buflen > 16 || gcm->buflen < 0) { - return CRYPT_INVALID_ARG; - } - - /* 0xFFFFFFFE0 = ((2^39)-256)/8 */ - if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) { - return CRYPT_INVALID_ARG; - } - - if (gcm->mode == LTC_GCM_MODE_IV) { - /* let's process the IV */ - if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; - } - - /* in AAD mode? */ - if (gcm->mode == LTC_GCM_MODE_AAD) { - /* let's process the AAD */ - if (gcm->buflen) { - gcm->totlen += gcm->buflen * CONST64(8); - gcm_mult_h(gcm, gcm->X); - } - - /* increment counter */ - for (y = 15; y >= 12; y--) { - if (++gcm->Y[y] & 255) { break; } - } - /* encrypt the counter */ - if ((err = ecb_encrypt_block(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { - return err; - } - - gcm->buflen = 0; - gcm->mode = LTC_GCM_MODE_TEXT; - } - - if (gcm->mode != LTC_GCM_MODE_TEXT) { - return CRYPT_INVALID_ARG; - } - - x = 0; -#ifdef LTC_FAST - if (gcm->buflen == 0) { - if (direction == GCM_ENCRYPT) { - for (x = 0; x < (ptlen & ~15); x += 16) { - /* ctr encrypt */ - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&ct[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); - *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); - } - /* GMAC it */ - gcm->pttotlen += 128; - gcm_mult_h(gcm, gcm->X); - /* increment counter */ - for (y = 15; y >= 12; y--) { - if (++gcm->Y[y] & 255) { break; } - } - if ((err = ecb_encrypt_block(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { - return err; - } - } - } else { - for (x = 0; x < (ptlen & ~15); x += 16) { - /* ctr encrypt */ - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); - *(LTC_FAST_TYPE_PTR_CAST(&pt[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); - } - /* GMAC it */ - gcm->pttotlen += 128; - gcm_mult_h(gcm, gcm->X); - /* increment counter */ - for (y = 15; y >= 12; y--) { - if (++gcm->Y[y] & 255) { break; } - } - if ((err = ecb_encrypt_block(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { - return err; - } - } - } - } -#endif - - /* process text */ - for (; x < ptlen; x++) { - if (gcm->buflen == 16) { - gcm->pttotlen += 128; - gcm_mult_h(gcm, gcm->X); - - /* increment counter */ - for (y = 15; y >= 12; y--) { - if (++gcm->Y[y] & 255) { break; } - } - if ((err = ecb_encrypt_block(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { - return err; - } - gcm->buflen = 0; - } - - if (direction == GCM_ENCRYPT) { - b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; - } else { - b = ct[x]; - pt[x] = ct[x] ^ gcm->buf[gcm->buflen]; - } - gcm->X[gcm->buflen++] ^= b; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_reset.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_reset.c deleted file mode 100644 index a071dcd..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_reset.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_reset.c - GCM implementation, reset a used state so it can accept IV data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Reset a GCM state to as if you just called gcm_init(). This saves the initialization time. - @param gcm The GCM state to reset - @return CRYPT_OK on success -*/ -int gcm_reset(gcm_state *gcm) -{ - LTC_ARGCHK(gcm != NULL); - - zeromem(gcm->buf, sizeof(gcm->buf)); - zeromem(gcm->X, sizeof(gcm->X)); - gcm->mode = LTC_GCM_MODE_IV; - gcm->ivmode = 0; - gcm->buflen = 0; - gcm->totlen = 0; - gcm->pttotlen = 0; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_test.c b/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_test.c deleted file mode 100644 index aa24122..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/gcm/gcm_test.c +++ /dev/null @@ -1,407 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file gcm_test.c - GCM implementation, testing, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_GCM_MODE - -/** - Test the GCM code - @return CRYPT_OK on success - */ -int gcm_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char K[32]; - int keylen; - unsigned char P[128]; - unsigned long ptlen; - unsigned char A[128]; - unsigned long alen; - unsigned char IV[128]; - unsigned long IVlen; - unsigned char C[128]; - unsigned char T[16]; - } tests[] = { - -/* test case #1 */ -{ - /* key */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 16, - - /* plaintext */ - { 0 }, - 0, - - /* AAD data */ - { 0 }, - 0, - - /* IV */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - 12, - - /* ciphertext */ - { 0 }, - - /* tag */ - { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, - 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a } -}, - -/* test case #2 */ -{ - /* key */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 16, - - /* PT */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 16, - - /* ADATA */ - { 0 }, - 0, - - /* IV */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - 12, - - /* CT */ - { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, - 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, - - /* TAG */ - { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, - 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf } -}, - -/* test case #3 */ -{ - /* key */ - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, - 16, - - /* PT */ - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, }, - 64, - - /* ADATA */ - { 0 }, - 0, - - /* IV */ - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88, }, - 12, - - /* CT */ - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, }, - - /* TAG */ - { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, - 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, } -}, - -/* test case #4 */ -{ - /* key */ - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, - 16, - - /* PT */ - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, }, - 60, - - /* ADATA */ - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2, }, - 20, - - /* IV */ - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88, }, - 12, - - /* CT */ - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, }, - - /* TAG */ - { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, - 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, } - -}, - -/* test case #5 */ -{ - /* key */ - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, - 16, - - /* PT */ - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, }, - 60, - - /* ADATA */ - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2, }, - 20, - - /* IV */ - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, }, - 8, - - /* CT */ - { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, - 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, - 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, - 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, - 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, - 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, - 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, - 0xc2, 0x3f, 0x45, 0x98, }, - - /* TAG */ - { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, - 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, } -}, - -/* test case #6 */ -{ - /* key */ - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, - 16, - - /* PT */ - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, }, - 60, - - /* ADATA */ - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2, }, - 20, - - /* IV */ - { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, - 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, - 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, - 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, - 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, - 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, - 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, - 0xa6, 0x37, 0xb3, 0x9b, }, - 60, - - /* CT */ - { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, - 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, - 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, - 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, - 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, - 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, - 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, - 0x4c, 0x34, 0xae, 0xe5, }, - - /* TAG */ - { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, - 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, } -}, - -/* test case #46 from BG (catches the LTC bug of v1.15) */ -{ - /* key */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 16, - - /* PT */ - { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd, - 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7, - 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7, - 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53, - 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7, - 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29, - 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4, - 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd, - 0x75, 0x8d, 0x2c }, - 67, - - /* ADATA */ - { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d, - 0xc7, 0xb4, 0xc4, 0x7f, 0x44 }, - 13, - - /* IV */ - { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07, - 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 }, - 16, - - /* CT */ - { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc, - 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56, - 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec, - 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b, - 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7, - 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31, - 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f, - 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8, - 0xb2, 0x97, 0xa8 }, - - /* TAG */ - { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b, - 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf } -} - -/* rest of test cases are the same except AES key size changes... ignored... */ -}; - int idx, err; - unsigned long x, y; - unsigned char out[2][128], T[2][16]; - gcm_state gcm; - - /* find aes */ - idx = find_cipher("aes"); - if (idx == -1) { - idx = find_cipher("rijndael"); - if (idx == -1) { - return CRYPT_NOP; - } - } - - /* Special test case for empty AAD + empty PT */ - y = sizeof(T[0]); - if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err; - if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err; - /* intentionally skip gcm_add_aad + gcm_process */ - if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err; - if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - y = sizeof(T[0]); - if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, - tests[x].IV, tests[x].IVlen, - tests[x].A, tests[x].alen, - (unsigned char*)tests[x].P, tests[x].ptlen, - out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - y = sizeof(T[1]); - XMEMCPY(T[1], tests[x].T, 16); - if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, - tests[x].IV, tests[x].IVlen, - tests[x].A, tests[x].alen, - out[1], tests[x].ptlen, - out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ - { - unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; - unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b }; - unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; - unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; - unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; - unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 }; - unsigned char pt[20] = { 0 }; - unsigned long taglen; - - /* VALID tag */ - taglen = sizeof(valid_tag); - err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, - pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT); - if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* INVALID tag */ - taglen = sizeof(invalid_tag); - err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, - pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT); - if (err == CRYPT_OK) { - return CRYPT_FAIL_TESTVECTOR; /* should fail */ - } - } - - return CRYPT_OK; -#endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt.c deleted file mode 100644 index 98f36e4..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_decrypt.c - OCB implementation, decrypt data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Decrypt a block with OCB. - @param ocb The OCB state - @param ct The ciphertext (length of the block size of the block cipher) - @param pt [out] The plaintext (length of ct) - @return CRYPT_OK if successful -*/ -int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) -{ - unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; - int err, x; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - /* can't use a encrypt-only descriptor */ - LTC_ARGCHK(cipher_descriptor[ocb->key.cipher].ecb_decrypt != NULL); - - /* Get Z[i] value */ - ocb_shift_xor(ocb, Z); - - /* xor ct in, encrypt, xor Z out */ - for (x = 0; x < ocb->block_len; x++) { - tmp[x] = ct[x] ^ Z[x]; - } - if ((err = ecb_decrypt_block(tmp, pt, &ocb->key)) != CRYPT_OK) { - return err; - } - for (x = 0; x < ocb->block_len; x++) { - pt[x] ^= Z[x]; - } - - /* compute checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= pt[x]; - } - - -#ifdef LTC_CLEAN_STACK - zeromem(Z, sizeof(Z)); - zeromem(tmp, sizeof(tmp)); -#endif - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c deleted file mode 100644 index 0f4dcb7..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_decrypt_verify_memory.c +++ /dev/null @@ -1,74 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_decrypt_verify_memory.c - OCB implementation, helper to decrypt block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Decrypt and compare the tag with OCB. - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce (length of the block size of the block cipher) - @param ct The ciphertext - @param ctlen The length of the ciphertext (octets) - @param pt [out] The plaintext - @param tag The tag to compare against - @param taglen The length of the tag (octets) - @param stat [out] The result of the tag comparison (1==valid, 0==invalid) - @return CRYPT_OK if successful regardless of the tag comparison -*/ -int ocb_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat) -{ - int err; - ocb_state *ocb; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(nonce != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(stat != NULL); - - /* allocate memory */ - ocb = XMALLOC(sizeof(ocb_state)); - if (ocb == NULL) { - return CRYPT_MEM; - } - - if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { - goto LBL_ERR; - } - - while (ctlen > (unsigned long)ocb->block_len) { - if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) { - goto LBL_ERR; - } - ctlen -= ocb->block_len; - pt += ocb->block_len; - ct += ocb->block_len; - } - - err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, stat); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(ocb, sizeof(ocb_state)); -#endif - - XFREE(ocb); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_decrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_decrypt.c deleted file mode 100644 index 3d516c9..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_decrypt.c +++ /dev/null @@ -1,68 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_done_decrypt.c - OCB implementation, terminate decryption, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Terminate a decrypting OCB state - @param ocb The OCB state - @param ct The ciphertext (if any) - @param ctlen The length of the ciphertext (octets) - @param pt [out] The plaintext - @param tag The authentication tag (to compare against) - @param taglen The length of the authentication tag provided - @param stat [out] The result of the tag comparison - @return CRYPT_OK if the process was successful regardless if the tag is valid -*/ -int ocb_done_decrypt(ocb_state *ocb, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, int *stat) -{ - int err; - unsigned char *tagbuf; - unsigned long tagbuflen; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(stat != NULL); - - /* default to failed */ - *stat = 0; - - /* allocate memory */ - tagbuf = XMALLOC(MAXBLOCKSIZE); - if (tagbuf == NULL) { - return CRYPT_MEM; - } - - tagbuflen = MAXBLOCKSIZE; - if ((err = s_ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { - goto LBL_ERR; - } - - if (taglen <= tagbuflen && XMEM_NEQ(tagbuf, tag, taglen) == 0) { - *stat = 1; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(tagbuf, MAXBLOCKSIZE); -#endif - - XFREE(tagbuf); - - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_encrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_encrypt.c deleted file mode 100644 index 5cd39ad..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_done_encrypt.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_done_encrypt.c - OCB implementation, terminate encryption, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Terminate an encryption OCB state - @param ocb The OCB state - @param pt Remaining plaintext (if any) - @param ptlen The length of the plaintext (octets) - @param ct [out] The ciphertext (if any) - @param tag [out] The tag for the OCB stream - @param taglen [in/out] The max size and resulting size of the tag - @return CRYPT_OK if successful -*/ -int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned char *tag, unsigned long *taglen) -{ - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - return s_ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt.c deleted file mode 100644 index a38765a..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt.c +++ /dev/null @@ -1,54 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_encrypt.c - OCB implementation, encrypt data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Encrypt a block of data with OCB. - @param ocb The OCB state - @param pt The plaintext (length of the block size of the block cipher) - @param ct [out] The ciphertext (same size as the pt) - @return CRYPT_OK if successful -*/ -int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) -{ - unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; - int err, x; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - /* compute checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= pt[x]; - } - - /* Get Z[i] value */ - ocb_shift_xor(ocb, Z); - - /* xor pt in, encrypt, xor Z out */ - for (x = 0; x < ocb->block_len; x++) { - tmp[x] = pt[x] ^ Z[x]; - } - if ((err = ecb_encrypt_block(tmp, ct, &ocb->key)) != CRYPT_OK) { - return err; - } - for (x = 0; x < ocb->block_len; x++) { - ct[x] ^= Z[x]; - } - -#ifdef LTC_CLEAN_STACK - zeromem(Z, sizeof(Z)); - zeromem(tmp, sizeof(tmp)); -#endif - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c deleted file mode 100644 index 7560a6e..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_encrypt_authenticate_memory.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_encrypt_authenticate_memory.c - OCB implementation, encrypt block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Encrypt and generate an authentication code for a buffer of memory - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce (length of the block ciphers block size) - @param pt The plaintext - @param ptlen The length of the plaintext (octets) - @param ct [out] The ciphertext - @param tag [out] The authentication tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int ocb_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen) -{ - int err; - ocb_state *ocb; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(nonce != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - /* allocate ram */ - ocb = XMALLOC(sizeof(ocb_state)); - if (ocb == NULL) { - return CRYPT_MEM; - } - - if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { - goto LBL_ERR; - } - - while (ptlen > (unsigned long)ocb->block_len) { - if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) { - goto LBL_ERR; - } - ptlen -= ocb->block_len; - pt += ocb->block_len; - ct += ocb->block_len; - } - - err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(ocb, sizeof(ocb_state)); -#endif - - XFREE(ocb); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_init.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_init.c deleted file mode 100644 index 056605c..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_init.c +++ /dev/null @@ -1,137 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_init.c - OCB implementation, initialize state, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB_MODE - -#define polys ocb_polys -static const struct { - int len; - unsigned char poly_div[MAXBLOCKSIZE], - poly_mul[MAXBLOCKSIZE]; -} polys[] = { -{ - 8, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } -}, { - 16, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } -} -}; - -/** - Initialize an OCB context. - @param ocb [out] The destination of the OCB state - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce (length of the block size of the cipher) - @return CRYPT_OK if successful -*/ -int ocb_init(ocb_state *ocb, int cipher, - const unsigned char *key, unsigned long keylen, const unsigned char *nonce) -{ - int poly, x, y, m, err; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(nonce != NULL); - - /* valid cipher? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* determine which polys to use */ - ocb->block_len = cipher_descriptor[cipher].block_length; - x = (int)LTC_ARRAY_SIZE(polys); - for (poly = 0; poly < x; poly++) { - if (polys[poly].len == ocb->block_len) { - break; - } - } - if (poly == x) { - return CRYPT_INVALID_ARG; /* block_len not found in polys */ - } - if (polys[poly].len != ocb->block_len) { - return CRYPT_INVALID_ARG; - } - - /* schedule the key */ - if ((err = ecb_start(cipher, key, keylen, 0, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* find L = E[0] */ - zeromem(ocb->L, ocb->block_len); - if ((err = ecb_encrypt_block(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* find R = E[N xor L] */ - for (x = 0; x < ocb->block_len; x++) { - ocb->R[x] = ocb->L[x] ^ nonce[x]; - } - if ((err = ecb_encrypt_block(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* find Ls[i] = L << i for i == 0..31 */ - XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len); - for (x = 1; x < 32; x++) { - m = ocb->Ls[x-1][0] >> 7; - for (y = 0; y < ocb->block_len-1; y++) { - ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; - } - ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; - - if (m == 1) { - for (y = 0; y < ocb->block_len; y++) { - ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; - } - } - } - - /* find Lr = L / x */ - m = ocb->L[ocb->block_len-1] & 1; - - /* shift right */ - for (x = ocb->block_len - 1; x > 0; x--) { - ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; - } - ocb->Lr[0] = ocb->L[0] >> 1; - - if (m == 1) { - for (x = 0; x < ocb->block_len; x++) { - ocb->Lr[x] ^= polys[poly].poly_div[x]; - } - } - - /* set Li, checksum */ - zeromem(ocb->Li, ocb->block_len); - zeromem(ocb->checksum, ocb->block_len); - - /* set other params */ - ocb->block_index = 1; - - return CRYPT_OK; -} - -#undef polys - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_ntz.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_ntz.c deleted file mode 100644 index bf933fd..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_ntz.c +++ /dev/null @@ -1,36 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_ntz.c - OCB implementation, internal function, by Tom St Denis -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Returns the number of leading zero bits [from lsb up] - @param x The 32-bit value to observe - @return The number of bits [from the lsb up] that are zero -*/ -int ocb_ntz(unsigned long x) -{ -#if defined(LTC_HAVE_CTZL_BUILTIN) - if (x == 0) - return sizeof(unsigned long) * CHAR_BIT; - return __builtin_ctzl(x); -#else - int c; - x &= 0xFFFFFFFFUL; - c = 0; - while ((x & 1) == 0) { - ++c; - x >>= 1; - } - return c; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_shift_xor.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_shift_xor.c deleted file mode 100644 index 2f7bb3b..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_shift_xor.c +++ /dev/null @@ -1,27 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_shift_xor.c - OCB implementation, internal function, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Compute the shift/xor for OCB (internal function) - @param ocb The OCB state - @param Z The destination of the shift -*/ -void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) -{ - int x, y; - y = ocb_ntz(ocb->block_index++); - for (x = 0; x < ocb->block_len; x++) { - ocb->Li[x] ^= ocb->Ls[y][x]; - Z[x] = ocb->Li[x] ^ ocb->R[x]; - } -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_test.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_test.c deleted file mode 100644 index 12942b5..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/ocb_test.c +++ /dev/null @@ -1,205 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb_test.c - OCB implementation, self-test by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/** - Test the OCB protocol - @return CRYPT_OK if successful -*/ -int ocb_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - int ptlen; - unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; - } tests[] = { - - /* OCB-AES-128-0B */ -{ - 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0 }, - /* ct */ - { 0 }, - /* tag */ - { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, - 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, -}, - - - /* OCB-AES-128-3B */ -{ - 3, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02 }, - /* ct */ - { 0xfc, 0xd3, 0x7d }, - /* tag */ - { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, - 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, -}, - - /* OCB-AES-128-16B */ -{ - 16, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* ct */ - { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, - 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, - /* tag */ - { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, - 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, -}, - - /* OCB-AES-128-20B */ -{ - 20, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0x70, 0x03, 0xeb, 0x55}, - /* tag */ - { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, - 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, -}, - - /* OCB-AES-128-32B */ -{ - 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, - 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, - - /* tag */ - { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, - 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, -}, - - /* OCB-AES-128-34B */ -{ - 34, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21 }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, - 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, - 0xa9, 0x5d }, - - /* tag */ - { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, - 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, -}, - -}; - - int err, x, idx, res; - unsigned long len; - unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - len = sizeof(outtag); - if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, - tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB Tag", x) || - compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB CT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, - outct, tests[x].tag, len, &res)) != CRYPT_OK) { - return err; - } - if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB", x)) { -#ifdef LTC_TEST_DBG - printf("\n\nOCB: Failure-decrypt - res = %d\n", res); -#endif - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* LTC_OCB_MODE */ - - -/* some comments - - -- it's hard to seek - -- hard to stream [you can't emit ciphertext until full block] - -- The setup is somewhat complicated... -*/ diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb/s_ocb_done.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb/s_ocb_done.c deleted file mode 100644 index 9336b75..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb/s_ocb_done.c +++ /dev/null @@ -1,132 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file s_ocb_done.c - OCB implementation, internal helper, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB_MODE - -/* Since the last block is encrypted in CTR mode the same code can - * be used to finish a decrypt or encrypt stream. The only difference - * is we XOR the final ciphertext into the checksum so we have to xor it - * before we CTR [decrypt] or after [encrypt] - * - * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... - */ - -/** - Shared code to finish an OCB stream - @param ocb The OCB state - @param pt The remaining plaintext [or input] - @param ptlen The length of the input (octets) - @param ct [out] The output buffer - @param tag [out] The destination for the authentication tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @param mode The mode we are terminating, 0==encrypt, 1==decrypt - @return CRYPT_OK if successful -*/ -int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) - -{ - unsigned char *Z, *Y, *X; - int err, x; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - if ((int)ptlen > ocb->block_len || (int)ptlen < 0) { - return CRYPT_INVALID_ARG; - } - - /* allocate ram */ - Z = XMALLOC(MAXBLOCKSIZE); - Y = XMALLOC(MAXBLOCKSIZE); - X = XMALLOC(MAXBLOCKSIZE); - if (X == NULL || Y == NULL || Z == NULL) { - if (X != NULL) { - XFREE(X); - } - if (Y != NULL) { - XFREE(Y); - } - if (Z != NULL) { - XFREE(Z); - } - return CRYPT_MEM; - } - - /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ - ocb_shift_xor(ocb, X); - XMEMCPY(Z, X, ocb->block_len); - - X[ocb->block_len-1] ^= (ptlen*8)&255; - X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; - for (x = 0; x < ocb->block_len; x++) { - X[x] ^= ocb->Lr[x]; - } - - /* Y[m] = E(X[m])) */ - if ((err = ecb_encrypt_block(X, Y, &ocb->key)) != CRYPT_OK) { - goto error; - } - - if (mode == 1) { - /* decrypt mode, so let's xor it first */ - /* xor C[m] into checksum */ - for (x = 0; x < (int)ptlen; x++) { - ocb->checksum[x] ^= ct[x]; - } - } - - /* C[m] = P[m] xor Y[m] */ - for (x = 0; x < (int)ptlen; x++) { - ct[x] = pt[x] ^ Y[x]; - } - - if (mode == 0) { - /* encrypt mode */ - /* xor C[m] into checksum */ - for (x = 0; x < (int)ptlen; x++) { - ocb->checksum[x] ^= ct[x]; - } - } - - /* xor Y[m] and Z[m] into checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= Y[x] ^ Z[x]; - } - - /* encrypt checksum, er... tag!! */ - if ((err = ecb_encrypt_block(ocb->checksum, X, &ocb->key)) != CRYPT_OK) { - goto error; - } - ecb_done(&ocb->key); - - /* now store it */ - for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { - tag[x] = X[x]; - } - *taglen = x; - -#ifdef LTC_CLEAN_STACK - zeromem(X, MAXBLOCKSIZE); - zeromem(Y, MAXBLOCKSIZE); - zeromem(Z, MAXBLOCKSIZE); - zeromem(ocb, sizeof(*ocb)); -#endif -error: - XFREE(X); - XFREE(Y); - XFREE(Z); - - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_add_aad.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_add_aad.c deleted file mode 100644 index 1c08423..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_add_aad.c +++ /dev/null @@ -1,102 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_add_aad.c - OCB implementation, add AAD data, by Karel Miko -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -/** - Add one block of AAD data (internal function) - @param ocb The OCB state - @param aad_block [in] AAD data (block_len size) - @return CRYPT_OK if successful -*/ -static int s_ocb3_int_aad_add_block(ocb3_state *ocb, const unsigned char *aad_block) -{ - unsigned char tmp[MAXBLOCKSIZE]; - int err; - - /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_[ocb3_int_ntz(ocb->ablock_index)], ocb->block_len); - - /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - ocb3_int_xor_blocks(tmp, aad_block, ocb->aOffset_current, ocb->block_len); - if ((err = ecb_encrypt_block(tmp, tmp, &ocb->key)) != CRYPT_OK) { - return err; - } - ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); - - ocb->ablock_index++; - - return CRYPT_OK; -} - -/** - Add AAD - additional associated data - @param ocb The OCB state - @param aad The AAD data - @param aadlen The size of AAD data (octets) - @return CRYPT_OK if successful -*/ -int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen) -{ - int err, x, full_blocks, full_blocks_len, last_block_len; - unsigned char *data; - unsigned long datalen, l; - - LTC_ARGCHK(ocb != NULL); - if (aadlen == 0) return CRYPT_OK; - LTC_ARGCHK(aad != NULL); - - if (ocb->adata_buffer_bytes > 0) { - l = ocb->block_len - ocb->adata_buffer_bytes; - if (l > aadlen) l = aadlen; - XMEMCPY(ocb->adata_buffer+ocb->adata_buffer_bytes, aad, l); - ocb->adata_buffer_bytes += l; - - if (ocb->adata_buffer_bytes == ocb->block_len) { - if ((err = s_ocb3_int_aad_add_block(ocb, ocb->adata_buffer)) != CRYPT_OK) { - return err; - } - ocb->adata_buffer_bytes = 0; - } - - data = (unsigned char *)aad + l; - datalen = aadlen - l; - } - else { - data = (unsigned char *)aad; - datalen = aadlen; - } - - if (datalen == 0) return CRYPT_OK; - - full_blocks = datalen/ocb->block_len; - full_blocks_len = full_blocks * ocb->block_len; - last_block_len = datalen - full_blocks_len; - - for (x=0; xblock_len)) != CRYPT_OK) { - return err; - } - } - - if (last_block_len>0) { - XMEMCPY(ocb->adata_buffer, data+full_blocks_len, last_block_len); - ocb->adata_buffer_bytes = last_block_len; - } - - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt.c deleted file mode 100644 index 15a3175..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt.c +++ /dev/null @@ -1,75 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_decrypt.c - OCB implementation, decrypt data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -/** - Decrypt blocks of ciphertext with OCB - @param ocb The OCB state - @param ct The ciphertext (length multiple of the block size of the block cipher) - @param ctlen The length of the input (octets) - @param pt [out] The plaintext (length of ct) - @return CRYPT_OK if successful -*/ -int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) -{ - unsigned char tmp[MAXBLOCKSIZE]; - int err, i, full_blocks; - unsigned char *pt_b, *ct_b; - - LTC_ARGCHK(ocb != NULL); - if (ctlen == 0) return CRYPT_OK; /* no data, nothing to do */ - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(pt != NULL); - - if (ctlen % ocb->block_len) { /* ctlen has to be multiple of block_len */ - return CRYPT_INVALID_ARG; - } - - full_blocks = ctlen/ocb->block_len; - for(i=0; iblock_len; - ct_b = (unsigned char *)ct+i*ocb->block_len; - - /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ - ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); - - /* tmp[] = ct[] XOR ocb->Offset_current[] */ - ocb3_int_xor_blocks(tmp, ct_b, ocb->Offset_current, ocb->block_len); - - /* decrypt */ - if ((err = ecb_decrypt_block(tmp, tmp, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* pt[] = tmp[] XOR ocb->Offset_current[] */ - ocb3_int_xor_blocks(pt_b, tmp, ocb->Offset_current, ocb->block_len); - - /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ - ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); - - ocb->block_index++; - } - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(tmp, sizeof(tmp)); -#endif - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c deleted file mode 100644 index 9ef69f7..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_last.c +++ /dev/null @@ -1,103 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_decrypt_last.c - OCB implementation, internal helper, by Karel Miko -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -/** - Finish an OCB (decryption) stream - @param ocb The OCB state - @param ct The remaining ciphertext - @param ctlen The length of the ciphertext (octets) - @param pt [out] The output buffer - @return CRYPT_OK if successful -*/ -int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) -{ - unsigned char iOffset_star[MAXBLOCKSIZE]; - unsigned char iPad[MAXBLOCKSIZE]; - int err, x, full_blocks, full_blocks_len, last_block_len; - - LTC_ARGCHK(ocb != NULL); - if (ct == NULL) LTC_ARGCHK(ctlen == 0); - if (ctlen != 0) { - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(pt != NULL); - } - - full_blocks = ctlen/ocb->block_len; - full_blocks_len = full_blocks * ocb->block_len; - last_block_len = ctlen - full_blocks_len; - - /* process full blocks first */ - if (full_blocks>0) { - if ((err = ocb3_decrypt(ocb, ct, full_blocks_len, pt)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - if (last_block_len>0) { - /* Offset_* = Offset_m xor L_* */ - ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); - - /* Pad = ENCIPHER(K, Offset_*) */ - if ((err = ecb_encrypt_block(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* P_* = C_* xor Pad[1..bitlen(C_*)] */ - ocb3_int_xor_blocks(pt+full_blocks_len, (unsigned char *)ct+full_blocks_len, iPad, last_block_len); - - /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ - ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); - for(x=last_block_len; xblock_len; x++) { - if (x == last_block_len) { - ocb->checksum[x] ^= 0x80; - } else { - ocb->checksum[x] ^= 0x00; - } - } - - /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ - /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ - for(x=0; xblock_len; x++) { - ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; - } - if ((err = ecb_encrypt_block(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - } - else { - /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ - /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ - for(x=0; xblock_len; x++) { - ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; - } - if ((err = ecb_encrypt_block(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(iOffset_star, MAXBLOCKSIZE); - zeromem(iPad, MAXBLOCKSIZE); -#endif - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c deleted file mode 100644 index 03d33b2..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_decrypt_verify_memory.c +++ /dev/null @@ -1,100 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_decrypt_verify_memory.c - OCB implementation, helper to decrypt block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Decrypt and compare the tag with OCB - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce (length of the block size of the block cipher) - @param noncelen The length of the nonce (octets) - @param adata The AAD - additional associated data - @param adatalen The length of AAD (octets) - @param ct The ciphertext - @param ctlen The length of the ciphertext (octets) - @param pt [out] The plaintext - @param tag The tag to compare against - @param taglen The length of the tag (octets) - @param stat [out] The result of the tag comparison (1==valid, 0==invalid) - @return CRYPT_OK if successful regardless of the tag comparison -*/ -int ocb3_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *adata, unsigned long adatalen, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat) -{ - int err; - ocb3_state *ocb; - unsigned char *buf; - unsigned long buflen; - - LTC_ARGCHK(stat != NULL); - - /* default to zero */ - *stat = 0; - - /* limit taglen */ - taglen = MIN(taglen, MAXBLOCKSIZE); - - /* allocate memory */ - buf = XMALLOC(taglen); - ocb = XMALLOC(sizeof(ocb3_state)); - if (ocb == NULL || buf == NULL) { - if (ocb != NULL) { - XFREE(ocb); - } - if (buf != NULL) { - XFREE(buf); - } - return CRYPT_MEM; - } - - if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, taglen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if (adata != NULL || adatalen != 0) { - if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - if ((err = ocb3_decrypt_last(ocb, ct, ctlen, pt)) != CRYPT_OK) { - goto LBL_ERR; - } - - buflen = taglen; - if ((err = ocb3_done(ocb, buf, &buflen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* compare tags */ - if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { - *stat = 1; - } - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(ocb, sizeof(ocb3_state)); -#endif - - XFREE(ocb); - XFREE(buf); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_done.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_done.c deleted file mode 100644 index 00a8c29..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_done.c +++ /dev/null @@ -1,79 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_done.c - OCB implementation, INTERNAL ONLY helper, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Finish OCB processing and compute the tag - @param ocb The OCB state - @param tag [out] The destination for the authentication tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen) -{ - unsigned char tmp[MAXBLOCKSIZE]; - int err, x; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(tag != NULL); - LTC_ARGCHK(taglen != NULL); - - /* check taglen */ - if ((int)*taglen < ocb->tag_len) { - *taglen = (unsigned long)ocb->tag_len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* finalize AAD processing */ - - if (ocb->adata_buffer_bytes>0) { - /* Offset_* = Offset_m xor L_* */ - ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len); - - /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ - ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes); - for(x=ocb->adata_buffer_bytes; xblock_len; x++) { - if (x == ocb->adata_buffer_bytes) { - tmp[x] = 0x80 ^ ocb->aOffset_current[x]; - } - else { - tmp[x] = 0x00 ^ ocb->aOffset_current[x]; - } - } - - /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ - if ((err = ecb_encrypt_block(tmp, tmp, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); - } - - /* finalize TAG computing */ - - /* at this point ocb->aSum_current = HASH(K, A) */ - /* tag = tag ^ HASH(K, A) */ - ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len); - - /* copy tag bytes */ - for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x]; - *taglen = (unsigned long)ocb->tag_len; - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(tmp, MAXBLOCKSIZE); - zeromem(ocb, sizeof(*ocb)); -#endif - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt.c deleted file mode 100644 index 152c1b5..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt.c +++ /dev/null @@ -1,75 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_encrypt.c - OCB implementation, encrypt data, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -/** - Encrypt blocks of data with OCB - @param ocb The OCB state - @param pt The plaintext (length multiple of the block size of the block cipher) - @param ptlen The length of the input (octets) - @param ct [out] The ciphertext (same size as the pt) - @return CRYPT_OK if successful -*/ -int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) -{ - unsigned char tmp[MAXBLOCKSIZE]; - int err, i, full_blocks; - unsigned char *pt_b, *ct_b; - - LTC_ARGCHK(ocb != NULL); - if (ptlen == 0) return CRYPT_OK; /* no data, nothing to do */ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - - if (ptlen % ocb->block_len) { /* ptlen has to be multiple of block_len */ - return CRYPT_INVALID_ARG; - } - - full_blocks = ptlen/ocb->block_len; - for(i=0; iblock_len; - ct_b = (unsigned char *)ct+i*ocb->block_len; - - /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ - ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); - - /* tmp[] = pt[] XOR ocb->Offset_current[] */ - ocb3_int_xor_blocks(tmp, pt_b, ocb->Offset_current, ocb->block_len); - - /* encrypt */ - if ((err = ecb_encrypt_block(tmp, tmp, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* ct[] = tmp[] XOR ocb->Offset_current[] */ - ocb3_int_xor_blocks(ct_b, tmp, ocb->Offset_current, ocb->block_len); - - /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ - ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); - - ocb->block_index++; - } - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(tmp, sizeof(tmp)); -#endif - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c deleted file mode 100644 index b118925..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_authenticate_memory.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_encrypt_authenticate_memory.c - OCB implementation, encrypt block of memory, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Encrypt and generate an authentication code for a buffer of memory - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce (length of the block ciphers block size) - @param noncelen The length of the nonce (octets) - @param adata The AAD - additional associated data - @param adatalen The length of AAD (octets) - @param pt The plaintext - @param ptlen The length of the plaintext (octets) - @param ct [out] The ciphertext - @param tag [out] The authentication tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int ocb3_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *adata, unsigned long adatalen, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen) -{ - int err; - ocb3_state *ocb; - - LTC_ARGCHK(taglen != NULL); - - /* allocate memory */ - ocb = XMALLOC(sizeof(ocb3_state)); - if (ocb == NULL) { - return CRYPT_MEM; - } - - if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, *taglen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if (adata != NULL || adatalen != 0) { - if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - if ((err = ocb3_encrypt_last(ocb, pt, ptlen, ct)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = ocb3_done(ocb, tag, taglen); - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(ocb, sizeof(ocb3_state)); -#endif - - XFREE(ocb); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c deleted file mode 100644 index 81bfa5c..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_encrypt_last.c +++ /dev/null @@ -1,104 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_encrypt_last.c - OCB implementation, internal helper, by Karel Miko -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -/** - Finish an OCB (encryption) stream - @param ocb The OCB state - @param pt The remaining plaintext - @param ptlen The length of the plaintext (octets) - @param ct [out] The output buffer - @return CRYPT_OK if successful -*/ -int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) -{ - unsigned char iOffset_star[MAXBLOCKSIZE]; - unsigned char iPad[MAXBLOCKSIZE]; - int err, x, full_blocks, full_blocks_len, last_block_len; - - LTC_ARGCHK(ocb != NULL); - if (pt == NULL) LTC_ARGCHK(ptlen == 0); - if (ptlen != 0) { - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - } - - full_blocks = ptlen/ocb->block_len; - full_blocks_len = full_blocks * ocb->block_len; - last_block_len = ptlen - full_blocks_len; - - /* process full blocks first */ - if (full_blocks>0) { - if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */ - - if (last_block_len>0) { - /* Offset_* = Offset_m xor L_* */ - ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); - - /* Pad = ENCIPHER(K, Offset_*) */ - if ((err = ecb_encrypt_block(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* C_* = P_* xor Pad[1..bitlen(P_*)] */ - ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len); - - /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ - ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); - for(x=last_block_len; xblock_len; x++) { - if (x == last_block_len) { - ocb->checksum[x] ^= 0x80; - } else { - ocb->checksum[x] ^= 0x00; - } - } - - /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ - /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ - for(x=0; xblock_len; x++) { - ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; - } - if ((err = ecb_encrypt_block(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - } else { - /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ - /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ - for(x=0; xblock_len; x++) { - ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; - } - if ((err = ecb_encrypt_block(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - err = CRYPT_OK; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(iOffset_star, MAXBLOCKSIZE); - zeromem(iPad, MAXBLOCKSIZE); -#endif - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_init.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_init.c deleted file mode 100644 index 51279a2..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_init.c +++ /dev/null @@ -1,194 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_init.c - OCB implementation, initialize state, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_OCB3_MODE - -static void s_ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen) -{ - int x, y, bottom; - int idx, shift; - unsigned char iNonce[MAXBLOCKSIZE]; - unsigned char iKtop[MAXBLOCKSIZE]; - unsigned char iStretch[MAXBLOCKSIZE+8]; - - /* Nonce = zeros(127-bitlen(N)) || 1 || N */ - zeromem(iNonce, sizeof(iNonce)); - for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) { - iNonce[x] = nonce[noncelen-y-1]; - } - iNonce[x] = 0x01; - iNonce[0] |= ((taglen*8) % 128) << 1; - - /* bottom = str2num(Nonce[123..128]) */ - bottom = iNonce[ocb->block_len-1] & 0x3F; - - /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ - iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0; - if ((ecb_encrypt_block(iNonce, iKtop, &ocb->key)) != CRYPT_OK) { - zeromem(ocb->Offset_current, ocb->block_len); - return; - } - - /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ - for (x = 0; x < ocb->block_len; x++) { - iStretch[x] = iKtop[x]; - } - for (y = 0; y < 8; y++) { - iStretch[x+y] = iKtop[y] ^ iKtop[y+1]; - } - - /* Offset_0 = Stretch[1+bottom..128+bottom] */ - idx = bottom / 8; - shift = (bottom % 8); - for (x = 0; x < ocb->block_len; x++) { - ocb->Offset_current[x] = iStretch[idx+x] << shift; - if (shift > 0) { - ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift); - } - } -} - -#define polys ocb3_polys -static const struct { - int len; - unsigned char poly_mul[MAXBLOCKSIZE]; -} polys[] = { -{ - 8, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } -}, { - 16, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } -} -}; - -/** - Initialize an OCB context - @param ocb [out] The destination of the OCB state - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param nonce The session nonce - @param noncelen The length of the session nonce (octets, up to 15) - @param taglen The length of the tag (octets, up to 16) - @return CRYPT_OK if successful -*/ -int ocb3_init(ocb3_state *ocb, int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - unsigned long taglen) -{ - int poly, x, y, m, err; - unsigned char *previous, *current; - - LTC_ARGCHK(ocb != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(nonce != NULL); - - /* valid cipher? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* Valid Nonce? - * As of RFC7253: "string of no more than 120 bits" */ - if (noncelen > (120/8)) { - return CRYPT_INVALID_ARG; - } - - /* The blockcipher must have a 128-bit blocksize */ - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_ARG; - } - - /* The TAGLEN may be any value up to 128 (bits) */ - if (taglen > 16) { - return CRYPT_INVALID_ARG; - } - ocb->tag_len = taglen; - - /* determine which polys to use */ - ocb->block_len = cipher_descriptor[cipher].block_length; - x = (int)LTC_ARRAY_SIZE(polys); - for (poly = 0; poly < x; poly++) { - if (polys[poly].len == ocb->block_len) { - break; - } - } - if (poly == x) { - return CRYPT_INVALID_ARG; /* block_len not found in polys */ - } - if (polys[poly].len != ocb->block_len) { - return CRYPT_INVALID_ARG; - } - - /* schedule the key */ - if ((err = ecb_start(cipher, key, keylen, 0, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* L_* = ENCIPHER(K, zeros(128)) */ - zeromem(ocb->L_star, ocb->block_len); - if ((err = ecb_encrypt_block(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* compute L_$, L_0, L_1, ... */ - for (x = -1; x < 32; x++) { - if (x == -1) { /* gonna compute: L_$ = double(L_*) */ - current = ocb->L_dollar; - previous = ocb->L_star; - } - else if (x == 0) { /* gonna compute: L_0 = double(L_$) */ - current = ocb->L_[0]; - previous = ocb->L_dollar; - } - else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */ - current = ocb->L_[x]; - previous = ocb->L_[x-1]; - } - m = previous[0] >> 7; - for (y = 0; y < ocb->block_len-1; y++) { - current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255; - } - current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255; - if (m == 1) { - /* current[] = current[] XOR polys[poly].poly_mul[]*/ - ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len); - } - } - - /* initialize ocb->Offset_current = Offset_0 */ - s_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen); - - /* initialize checksum to all zeros */ - zeromem(ocb->checksum, ocb->block_len); - - /* set block index */ - ocb->block_index = 1; - - /* initialize AAD related stuff */ - ocb->ablock_index = 1; - ocb->adata_buffer_bytes = 0; - zeromem(ocb->aOffset_current, ocb->block_len); - zeromem(ocb->aSum_current, ocb->block_len); - - return CRYPT_OK; -} - -#undef polys - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c deleted file mode 100644 index a667ff6..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_ntz.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_int_ntz.c - OCB implementation, INTERNAL ONLY helper, by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Returns the number of leading zero bits [from lsb up] (internal function) - @param x The 32-bit value to observe - @return The number of bits [from the lsb up] that are zero -*/ -int ocb3_int_ntz(unsigned long x) -{ -#if defined(LTC_HAVE_CTZL_BUILTIN) - if (x == 0) - return sizeof(unsigned long) * CHAR_BIT; - return __builtin_ctzl(x); -#else - int c; - x &= 0xFFFFFFFFUL; - c = 0; - while ((x & 1) == 0) { - ++c; - x >>= 1; - } - return c; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c deleted file mode 100644 index f9f342a..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_int_xor_blocks.c +++ /dev/null @@ -1,30 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_int_xor_blocks.c - OCB implementation, INTERNAL ONLY helper, by Karel Miko -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Compute xor for two blocks of bytes 'out = block_a XOR block_b' (internal function) - @param out The block of bytes (output) - @param block_a The block of bytes (input) - @param block_b The block of bytes (input) - @param block_len The size of block_a, block_b, out -*/ -void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len) -{ - int x; - if (out == block_a) { - for (x = 0; x < (int)block_len; x++) out[x] ^= block_b[x]; - } - else { - for (x = 0; x < (int)block_len; x++) out[x] = block_a[x] ^ block_b[x]; - } -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_test.c b/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_test.c deleted file mode 100644 index 3c6cfe5..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/ocb3/ocb3_test.c +++ /dev/null @@ -1,299 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file ocb3_test.c - OCB implementation, self-test by Tom St Denis -*/ -#include "tomcrypt_private.h" - -#ifdef LTC_OCB3_MODE - -/** - Test the OCB protocol - @return CRYPT_OK if successful -*/ -int ocb3_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - /* test vectors from: http://tools.ietf.org/html/draft-krovetz-ocb-03 */ - unsigned char key[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; - unsigned char nonce[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B }; - const struct { - int ptlen; - int aadlen; - unsigned char pt[64], aad[64], ct[64], tag[16]; - } tests[] = { - - { /* index:0 */ - 0, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0x19,0x7b,0x9c,0x3c,0x44,0x1d,0x3c,0x83,0xea,0xfb,0x2b,0xef,0x63,0x3b,0x91,0x82 }, /* TAG */ - }, - { /* index:1 */ - 8, /* PLAINTEXT length */ - 8, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ - { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ - { 0x16,0xdc,0x76,0xa4,0x6d,0x47,0xe1,0xea,0xd5,0x37,0x20,0x9e,0x8a,0x96,0xd1,0x4e }, /* TAG */ - }, - { /* index:2 */ - 0, /* PLAINTEXT length */ - 8, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0x98,0xb9,0x15,0x52,0xc8,0xc0,0x09,0x18,0x50,0x44,0xe3,0x0a,0x6e,0xb2,0xfe,0x21 }, /* TAG */ - }, - { /* index:3 */ - 8, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ - { 0x97,0x1e,0xff,0xca,0xe1,0x9a,0xd4,0x71,0x6f,0x88,0xe8,0x7b,0x87,0x1f,0xbe,0xed }, /* TAG */ - }, - { /* index:4 */ - 16, /* PLAINTEXT length */ - 16, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ - { 0x77,0x6c,0x99,0x24,0xd6,0x72,0x3a,0x1f,0xc4,0x52,0x45,0x32,0xac,0x3e,0x5b,0xeb }, /* TAG */ - }, - { /* index:5 */ - 0, /* PLAINTEXT length */ - 16, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0x7d,0xdb,0x8e,0x6c,0xea,0x68,0x14,0x86,0x62,0x12,0x50,0x96,0x19,0xb1,0x9c,0xc6 }, /* TAG */ - }, - { /* index:6 */ - 16, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ - { 0x13,0xcc,0x8b,0x74,0x78,0x07,0x12,0x1a,0x4c,0xbb,0x3e,0x4b,0xd6,0xb4,0x56,0xaf }, /* TAG */ - }, - { /* index:7 */ - 24, /* PLAINTEXT length */ - 24, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ - { 0x5f,0xa9,0x4f,0xc3,0xf3,0x88,0x20,0xf1,0xdc,0x3f,0x3d,0x1f,0xd4,0xe5,0x5e,0x1c }, /* TAG */ - }, - { /* index:8 */ - 0, /* PLAINTEXT length */ - 24, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0x28,0x20,0x26,0xda,0x30,0x68,0xbc,0x9f,0xa1,0x18,0x68,0x1d,0x55,0x9f,0x10,0xf6 }, /* TAG */ - }, - { /* index:9 */ - 24, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ - { 0x6e,0xf2,0xf5,0x25,0x87,0xfd,0xa0,0xed,0x97,0xdc,0x7e,0xed,0xe2,0x41,0xdf,0x68 }, /* TAG */ - }, - { /* index:10 */ - 32, /* PLAINTEXT length */ - 32, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ - { 0xb2,0xa0,0x40,0xdd,0x3b,0xd5,0x16,0x43,0x72,0xd7,0x6d,0x7b,0xb6,0x82,0x42,0x40 }, /* TAG */ - }, - { /* index:11 */ - 0, /* PLAINTEXT length */ - 32, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0xe1,0xe0,0x72,0x63,0x3b,0xad,0xe5,0x1a,0x60,0xe8,0x59,0x51,0xd9,0xc4,0x2a,0x1b }, /* TAG */ - }, - { /* index:12 */ - 32, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ - { 0x4a,0x3b,0xae,0x82,0x44,0x65,0xcf,0xda,0xf8,0xc4,0x1f,0xc5,0x0c,0x7d,0xf9,0xd9 }, /* TAG */ - }, - { /* index:13 */ - 40, /* PLAINTEXT length */ - 40, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ - { 0x65,0x9c,0x62,0x32,0x11,0xde,0xea,0x0d,0xe3,0x0d,0x2c,0x38,0x18,0x79,0xf4,0xc8 }, /* TAG */ - }, - { /* index:14 */ - 0, /* PLAINTEXT length */ - 40, /* AAD length */ - { 0 }, /* PLAINTEXT */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ - { 0 }, /* CIPHERTEXT */ - { 0x7a,0xeb,0x7a,0x69,0xa1,0x68,0x7d,0xd0,0x82,0xca,0x27,0xb0,0xd9,0xa3,0x70,0x96 }, /* TAG */ - }, - { /* index:15 */ - 40, /* PLAINTEXT length */ - 0, /* AAD length */ - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ - { 0 }, /* AAD */ - { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ - { 0x06,0x0c,0x84,0x67,0xf4,0xab,0xab,0x5e,0x8b,0x3c,0x20,0x67,0xa2,0xe1,0x15,0xdc }, /* TAG */ - }, - -}; - /* As of RFC 7253 - 'Appendix A. Sample Results' - * The next tuple shows a result with a tag length of 96 bits and a - different key. - - K: 0F0E0D0C0B0A09080706050403020100 - - N: BBAA9988776655443322110D - A: 000102030405060708090A0B0C0D0E0F1011121314151617 - 18191A1B1C1D1E1F2021222324252627 - P: 000102030405060708090A0B0C0D0E0F1011121314151617 - 18191A1B1C1D1E1F2021222324252627 - C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1 - A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD - AC4F02AA - - The C has been split up in C and T (tag) - */ - const unsigned char K[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, - 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 }; - const unsigned char N[] = { 0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44, - 0x33,0x22,0x11,0x0D }; - const unsigned char A[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; - const unsigned char P[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; - const unsigned char C[] = { 0x17,0x92,0xA4,0xE3,0x1E,0x07,0x55,0xFB, - 0x03,0xE3,0x1B,0x22,0x11,0x6E,0x6C,0x2D, - 0xDF,0x9E,0xFD,0x6E,0x33,0xD5,0x36,0xF1, - 0xA0,0x12,0x4B,0x0A,0x55,0xBA,0xE8,0x84, - 0xED,0x93,0x48,0x15,0x29,0xC7,0x6B,0x6A }; - const unsigned char T[] = { 0xD0,0xC5,0x15,0xF4,0xD1,0xCD,0xD4,0xFD, - 0xAC,0x4F,0x02,0xAA }; - - int err, x, idx, res; - unsigned long len; - unsigned char outct[MAXBLOCKSIZE] = { 0 }; - unsigned char outtag[MAXBLOCKSIZE] = { 0 }; - ocb3_state ocb; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - len = 16; /* must be the same as the required taglen */ - if ((err = ocb3_encrypt_authenticate_memory(idx, - key, sizeof(key), - nonce, sizeof(nonce), - tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, - tests[x].ptlen != 0 ? tests[x].pt : NULL, tests[x].ptlen, - tests[x].ptlen != 0 ? outct : NULL, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB3 Tag", x) || - compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB3 CT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if ((err = ocb3_decrypt_verify_memory(idx, - key, sizeof(key), - nonce, sizeof(nonce), - tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, - tests[x].ptlen != 0 ? outct : NULL, tests[x].ptlen, - tests[x].ptlen != 0 ? outct : NULL, tests[x].tag, len, &res)) != CRYPT_OK) { - return err; - } - if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB3", x)) { -#ifdef LTC_TEST_DBG - printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); -#endif - return CRYPT_FAIL_TESTVECTOR; - } - } - - /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */ - x = 99; - len = 12; - if ((err = ocb3_encrypt_authenticate_memory(idx, - K, sizeof(K), - N, sizeof(N), - A, sizeof(A), - P, sizeof(P), - outct, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag", x) || - compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - - if ((err = ocb3_decrypt_verify_memory(idx, - K, sizeof(K), - N, sizeof(N), - A, sizeof(A), - C, sizeof(C), - outct, T, sizeof(T), &res)) != CRYPT_OK) { - return err; - } - if ((res != 1) || compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3", x)) { -#ifdef LTC_TEST_DBG - printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); -#endif - return CRYPT_FAIL_TESTVECTOR; - } - - /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */ - x = 100; - if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; - if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; - if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK) return err; - if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err; - len = sizeof(outtag); /* intentionally more than 12 */ - if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; - if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x)) return CRYPT_FAIL_TESTVECTOR; - if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; - if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; - if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK) return err; - if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err; - len = sizeof(outtag); /* intentionally more than 12 */ - if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; - if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x)) return CRYPT_FAIL_TESTVECTOR; - if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x)) return CRYPT_FAIL_TESTVECTOR; - - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* LTC_OCB3_MODE */ diff --git a/Sources/DataLiteC/libtomcrypt/encauth/siv/siv.c b/Sources/DataLiteC/libtomcrypt/encauth/siv/siv.c deleted file mode 100644 index d3dd578..0000000 --- a/Sources/DataLiteC/libtomcrypt/encauth/siv/siv.c +++ /dev/null @@ -1,752 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file siv.c - RFC 5297 SIV - Synthetic Initialization Vector, Steffen Jaeckel -*/ - -#ifdef LTC_SIV_MODE - -/* RFC 5297 - Chapter 7 - Security Considerations - * - * [...] S2V must not be - * passed more than 127 components. Since SIV includes the plaintext as - * a component to S2V, that limits the number of components of - * associated data that can be safely passed to SIV to 126. - */ -static const unsigned long s_siv_max_aad_components = 126; - -static LTC_INLINE void s_siv_dbl(unsigned char *inout) -{ - int y, mask, msb, len; - - /* setup the system */ - mask = 0x87; - len = 16; - - /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ - msb = inout[0] >> 7; - - /* shift left */ - for (y = 0; y < (len - 1); y++) { - inout[y] = ((inout[y] << 1) | (inout[y + 1] >> 7)) & 255; - } - inout[len - 1] = ((inout[len - 1] << 1) ^ (msb ? mask : 0)) & 255; -} - -static LTC_INLINE int s_siv_S2V_one(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *V, unsigned long *Vlen) -{ - /* if n = 0 then - * return V = AES-CMAC(K, ) - */ - unsigned char zero_or_one[16] = {0}; - zero_or_one[0] = 1; - return omac_memory(cipher, key, keylen, zero_or_one, sizeof(zero_or_one), V, Vlen); -} - -typedef struct siv_omac_ctx_t { - omac_state omac; - int cipher; -} siv_omac_ctx_t; - -static LTC_INLINE int s_siv_ctx_init(int cipher, - const unsigned char *key, unsigned long keylen, - siv_omac_ctx_t *ctx) -{ - ctx->cipher = cipher; - return omac_init(&ctx->omac, cipher, key, keylen); -} - -static LTC_INLINE int s_siv_omac_memory(siv_omac_ctx_t *ctx, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - int err; - omac_state omac = ctx->omac; - if ((err = omac_process(&omac, in, inlen)) != CRYPT_OK) { - return err; - } - err = omac_done(&omac, out, outlen); - zeromem(&omac, sizeof(omac)); - return err; -} - -static LTC_INLINE int s_siv_S2V_zero(siv_omac_ctx_t *ctx, - unsigned char *D, unsigned long *Dlen) -{ - /* D = AES-CMAC(K, ) */ - const unsigned char zero_or_one[16] = {0}; - return s_siv_omac_memory(ctx, zero_or_one, sizeof(zero_or_one), D, Dlen); -} - -static LTC_INLINE int s_siv_S2V_dbl_xor_cmac(siv_omac_ctx_t *ctx, - const unsigned char *aad, unsigned long aadlen, - unsigned char *D, unsigned long Dlen) -{ - /* for i = 1 to n-1 do - * D = dbl(D) xor AES-CMAC(K, Si) - * done - */ - int err; - unsigned char TMP[16]; - unsigned long i, TMPlen = sizeof(TMP); - s_siv_dbl(D); - if ((err = s_siv_omac_memory(ctx, aad, aadlen, TMP, &TMPlen)) != CRYPT_OK) { - return err; - } - for (i = 0; i < Dlen; ++i) { - D[i] ^= TMP[i]; - } - return err; -} - -static LTC_INLINE int s_siv_omac_memory_multi(siv_omac_ctx_t *ctx, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, - ...) -{ - int err; - va_list args; - omac_state omac = ctx->omac; - va_start(args, inlen); - - if ((err = omac_vprocess(&omac, in, inlen, args)) != CRYPT_OK) { - return err; - } - err = omac_done(&omac, out, outlen); - zeromem(&omac, sizeof(omac)); - return err; -} - -static LTC_INLINE int s_siv_S2V_T(siv_omac_ctx_t *ctx, - const unsigned char *in, unsigned long inlen, - unsigned char *D, - unsigned char *V, unsigned long *Vlen) -{ - int err; - unsigned long i; - unsigned char T[16]; - - /* if len(Sn) >= 128 then - * T = Sn xorend D - * else - * T = dbl(D) xor pad(Sn) - * fi - */ - if (inlen >= 16) { - XMEMCPY(T, &in[inlen - 16], 16); - for(i = 0; i < 16; ++i) { - T[i] ^= D[i]; - } - err = s_siv_omac_memory_multi(ctx, V, Vlen, in, inlen - 16, T, 16uL, NULL); - } else { - s_siv_dbl(D); - XMEMCPY(T, in, inlen); - T[inlen] = 0x80; - for (i = inlen + 1; i < 16; ++i) { - T[i] = 0x0; - } - for(i = 0; i < 16; ++i) { - T[i] ^= D[i]; - } - - err = s_siv_omac_memory(ctx, T, 16, V, Vlen); - } - return err; -} - -static int s_siv_S2V(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char **ad, unsigned long *adlen, - const unsigned char *in, unsigned long inlen, - unsigned char *V, unsigned long *Vlen) -{ - int err; - unsigned char D[16]; - unsigned long Dlen = sizeof(D), n = 0; - siv_omac_ctx_t ctx; - - if(ad == NULL || adlen == NULL || ad[0] == NULL || adlen[0] == 0) { - err = s_siv_S2V_one(cipher, key, keylen, V, Vlen); - } else { - if ((err = s_siv_ctx_init(cipher, key, keylen, &ctx)) != CRYPT_OK) { - return err; - } - Dlen = sizeof(D); - if ((err = s_siv_S2V_zero(&ctx, D, &Dlen)) != CRYPT_OK) { - return err; - } - - while(ad[n] != NULL && adlen[n] != 0) { - if (n >= s_siv_max_aad_components) { - return CRYPT_INPUT_TOO_LONG; - } - if ((err = s_siv_S2V_dbl_xor_cmac(&ctx, ad[n], adlen[n], D, Dlen)) != CRYPT_OK) { - return err; - } - n++; - } - - err = s_siv_S2V_T(&ctx, in, inlen, D, V, Vlen); - } - - return err; -} - -static LTC_INLINE void s_siv_bitand(const unsigned char* V, unsigned char* Q) -{ - int n; - XMEMSET(Q, 0xff, 16); - Q[8] = Q[12] = 0x7f; - for (n = 0; n < 16; ++n) { - Q[n] &= V[n]; - } -} - -static LTC_INLINE int s_ctr_crypt_memory(int cipher, - const unsigned char *IV, - const unsigned char *key, int keylen, - const unsigned char *in, - unsigned char *out, unsigned long len) -{ - int err; - symmetric_CTR ctr; - - if ((err = ctr_start(cipher, IV, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN | 16, &ctr)) != CRYPT_OK) { - goto out; - } - if ((err = ctr_encrypt(in, out, len, &ctr)) != CRYPT_OK) { - goto out; - } - if ((err = ctr_done(&ctr)) != CRYPT_OK) { - goto out; - } - -out: - zeromem(&ctr, sizeof(ctr)); - return err; -} - -typedef struct { - unsigned char Q[16], V[16]; -} siv_state; - -/** - SIV encrypt - - @param cipher The index of the cipher desired - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param ad An array of Associated Data pointers (must be NULL terminated) - @param adlen An array with the lengths of the Associated Data - @param pt The plaintext - @param ptlen The length of the plaintext - @param ct The ciphertext - @param ctlen [in/out] The length of the ciphertext - @return CRYPT_OK if successful -*/ -int siv_encrypt_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *ad[], unsigned long adlen[], - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned long *ctlen) -{ - int err; - const unsigned char *K1, *K2; - unsigned long Vlen; - siv_state siv; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ad != NULL); - LTC_ARGCHK(adlen != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ctlen != NULL); - - if (ptlen + 16 < ptlen) { - return CRYPT_OVERFLOW; - } - if (*ctlen < ptlen + 16) { - *ctlen = ptlen + 16; - return CRYPT_BUFFER_OVERFLOW; - } - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - - K1 = key; - K2 = &key[keylen/2]; - - Vlen = sizeof(siv.V); - err = s_siv_S2V(cipher, K1, keylen/2, ad, adlen, pt, ptlen, siv.V, &Vlen); -#ifdef LTC_CLEAN_STACK - burn_stack(3 * 16 + 7 * sizeof(unsigned long) + 1 * sizeof(void*)); -#endif - if (err != CRYPT_OK) { - return err; - } - - s_siv_bitand(siv.V, siv.Q); - XMEMCPY(ct, siv.V, 16); - ct += 16; - - if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, pt, ct, ptlen)) != CRYPT_OK) { - zeromem(ct, ptlen + 16); - goto out; - } - *ctlen = ptlen + 16; - -out: -#ifdef LTC_CLEAN_STACK - zeromem(&siv, sizeof(siv)); -#endif - - return err; -} - -/** - SIV decrypt - - @param cipher The index of the cipher desired - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param ad An array of Associated Data pointers (must be NULL terminated) - @param adlen An array with the lengths of the Associated Data - @param ct The ciphertext - @param ctlen The length of the ciphertext - @param pt The plaintext - @param ptlen [in/out] The length of the plaintext - @return CRYPT_OK if successful -*/ -int siv_decrypt_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *ad[], unsigned long adlen[], - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, unsigned long *ptlen) -{ - int err; - unsigned char *pt_work; - const unsigned char *K1, *K2, *ct_work; - unsigned long Vlen; - siv_state siv; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ad != NULL); - LTC_ARGCHK(adlen != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ptlen != NULL); - - if (ctlen < 16) { - return CRYPT_INVALID_ARG; - } - if (*ptlen < (ctlen - 16)) { - *ptlen = ctlen - 16; - return CRYPT_BUFFER_OVERFLOW; - } - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - *ptlen = ctlen - 16; - pt_work = XMALLOC(*ptlen); - if (pt_work == NULL) { - return CRYPT_MEM; - } - - K1 = key; - K2 = &key[keylen/2]; - - ct_work = ct; - s_siv_bitand(ct_work, siv.Q); - ct_work += 16; - - if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, ct_work, pt_work, *ptlen)) != CRYPT_OK) { - goto out; - } - Vlen = sizeof(siv.V); - if ((err = s_siv_S2V(cipher, K1, keylen/2, ad, adlen, pt_work, *ptlen, siv.V, &Vlen)) != CRYPT_OK) { - goto out; - } - - err = XMEM_NEQ(siv.V, ct, Vlen); - copy_or_zeromem(pt_work, pt, *ptlen, err); -out: -#ifdef LTC_CLEAN_STACK - zeromem(&siv, sizeof(siv)); -#endif - zeromem(pt_work, *ptlen); - XFREE(pt_work); - - return err; -} - -/** - Process an entire SIV packet in one call. - - @param cipher The index of the cipher desired - @param direction Encrypt or Decrypt mode (LTC_ENCRYPT or LTC_DECRYPT) - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param in The input - @param inlen The length of the input - @param out The output - @param outlen [in/out] The max size and resulting size of the output - @remark <...> is of the form (void*, unsigned long) and contains the Associated Data - @return CRYPT_OK on success - */ -int siv_memory( int cipher, int direction, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - ...) -{ - int err; - va_list args; - siv_state siv; - unsigned char D[16], *in_buf = NULL, *out_work; - const unsigned char *aad, *K1, *K2, *in_work; - unsigned long n = 0, aadlen, Dlen = sizeof(D), Vlen = sizeof(siv.V), in_work_len; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - if (direction == LTC_ENCRYPT && *outlen < inlen + 16) { - *outlen = inlen + 16; - return CRYPT_BUFFER_OVERFLOW; - } else if (direction == LTC_DECRYPT && (inlen < 16 || *outlen < inlen - 16)) { - *outlen = inlen - 16; - return CRYPT_BUFFER_OVERFLOW; - } - - K1 = key; - K2 = &key[keylen/2]; - in_work = in; - in_work_len = inlen; - out_work = out; - - if (direction == LTC_DECRYPT) { - in_work_len -= 16; - in_buf = XMALLOC(in_work_len); - if (in_buf == NULL) - return CRYPT_MEM; - s_siv_bitand(in_work, siv.Q); - in_work += 16; - - if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, in_work, in_buf, in_work_len)) != CRYPT_OK) { - goto err_out; - } - in_work = in_buf; - } - - va_start(args, outlen); - aad = va_arg(args, const unsigned char*); - aadlen = aad ? va_arg(args, unsigned long) : 0; - if (aad == NULL || aadlen == 0) { - if ((err = s_siv_S2V_one(cipher, K1, keylen/2, siv.V, &Vlen)) != CRYPT_OK) { - goto err_out; - } - } else { - siv_omac_ctx_t ctx; - if ((err = s_siv_ctx_init(cipher, K1, keylen/2, &ctx)) != CRYPT_OK) { - goto err_out; - } - if ((err = s_siv_S2V_zero(&ctx, D, &Dlen)) != CRYPT_OK) { - goto err_out; - } - - do { - if (n >= s_siv_max_aad_components) { - err = CRYPT_INPUT_TOO_LONG; - goto err_out; - } - if ((err = s_siv_S2V_dbl_xor_cmac(&ctx, aad, aadlen, D, Dlen)) != CRYPT_OK) { - goto err_out; - } - aad = va_arg(args, const unsigned char*); - if (aad == NULL) - break; - aadlen = va_arg(args, unsigned long); - n++; - } while (aadlen); - - if ((err = s_siv_S2V_T(&ctx, in_work, in_work_len, D, siv.V, &Vlen)) != CRYPT_OK) { - goto err_out; - } - } - - if (direction == LTC_DECRYPT) { - err = XMEM_NEQ(siv.V, in, Vlen); - copy_or_zeromem(in_work, out, in_work_len, err); - *outlen = in_work_len; - } else { - s_siv_bitand(siv.V, siv.Q); - XMEMCPY(out_work, siv.V, 16); - out_work += 16; - - if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, in, out_work, inlen)) != CRYPT_OK) { - zeromem(out, inlen + 16); - goto err_out; - } - *outlen = inlen + 16; - } -err_out: - if (in_buf) { - zeromem(in_buf, in_work_len); - XFREE(in_buf); - } - va_end(args); -#ifdef LTC_CLEAN_STACK - zeromem(D, sizeof(D)); - zeromem(&siv, sizeof(siv)); -#endif - return err; -} - -int siv_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - /* - * RFC5297 - A.1. Deterministic Authenticated Encryption Example - */ - const unsigned char Key_A1[] = - { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, - 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; - const unsigned char AD_A1[] = - { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; - const unsigned char Plaintext_A1[] = - { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; - const unsigned char output_A1[] = - { 0x85, 0x63, 0x2d, 0x07, 0xc6, 0xe8, 0xf3, 0x7f, - 0x95, 0x0a, 0xcd, 0x32, 0x0a, 0x2e, 0xcc, 0x93, - 0x40, 0xc0, 0x2b, 0x96, 0x90, 0xc4, 0xdc, 0x04, - 0xda, 0xef, 0x7f, 0x6a, 0xfe, 0x5c }; - const unsigned char *ad_A1[] = - { AD_A1, NULL }; - unsigned long adlen_A1[] = - { sizeof(AD_A1), 0 }; - - const unsigned char Key_A2[] = - { 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, - 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; - const unsigned char AD1_A2[] = - { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, - 0xde, 0xad, 0xda, 0xda, 0xde, 0xad, 0xda, 0xda, - 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, - 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; - const unsigned char AD2_A2[] = - { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, - 0x90, 0xa0 }; - const unsigned char AD3_A2[] = - { 0x09, 0xf9, 0x11, 0x02, 0x9d, 0x74, 0xe3, 0x5b, - 0xd8, 0x41, 0x56, 0xc5, 0x63, 0x56, 0x88, 0xc0 }; - const unsigned char Plaintext_A2[] = - { 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x6c, 0x61, - 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x74, - 0x6f, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, - 0x53, 0x49, 0x56, 0x2d, 0x41, 0x45, 0x53 }; - const unsigned char output_A2[] = - { 0x7b, 0xdb, 0x6e, 0x3b, 0x43, 0x26, 0x67, 0xeb, - 0x06, 0xf4, 0xd1, 0x4b, 0xff, 0x2f, 0xbd, 0x0f, - 0xcb, 0x90, 0x0f, 0x2f, 0xdd, 0xbe, 0x40, 0x43, - 0x26, 0x60, 0x19, 0x65, 0xc8, 0x89, 0xbf, 0x17, - 0xdb, 0xa7, 0x7c, 0xeb, 0x09, 0x4f, 0xa6, 0x63, - 0xb7, 0xa3, 0xf7, 0x48, 0xba, 0x8a, 0xf8, 0x29, - 0xea, 0x64, 0xad, 0x54, 0x4a, 0x27, 0x2e, 0x9c, - 0x48, 0x5b, 0x62, 0xa3, 0xfd, 0x5c, 0x0d }; - const unsigned char *ad_A2[] = - { AD1_A2, AD2_A2, AD3_A2, NULL }; - unsigned long adlen_A2[] = - { sizeof(AD1_A2), sizeof(AD2_A2), sizeof(AD3_A2), 0 }; - -#define PL_PAIR(n) n, sizeof(n) - struct { - const unsigned char* Key; - unsigned long Keylen; - const unsigned char* Plaintext; - unsigned long Plaintextlen; - const void* ADs; - void* ADlens; - const unsigned char* output; - unsigned long outputlen; - const char* name; - } siv_tests[] = { - { PL_PAIR(Key_A1), PL_PAIR(Plaintext_A1), &ad_A1, &adlen_A1, PL_PAIR(output_A1), "RFC5297 - A.1. Deterministic Authenticated Encryption Example" }, - { PL_PAIR(Key_A2), PL_PAIR(Plaintext_A2), &ad_A2, &adlen_A2, PL_PAIR(output_A2), "RFC5297 - A.2. Nonce-Based Authenticated Encryption Example" } - }; -#undef PL_PAIR - - int err, cipher; - unsigned n; - unsigned long buflen, tmplen; - unsigned char buf[MAX(sizeof(output_A1), sizeof(output_A2))]; - const unsigned long niter = 1000; - unsigned char *tmpe, *tmpd; - const unsigned long tmpmax = 16 + niter * 16; - - cipher = find_cipher("aes"); - - for (n = 0; n < LTC_ARRAY_SIZE(siv_tests); ++n) { - buflen = sizeof(buf); - if ((err = siv_encrypt_memory(cipher, - siv_tests[n].Key, siv_tests[n].Keylen, - (const unsigned char **)siv_tests[n].ADs, siv_tests[n].ADlens, - siv_tests[n].Plaintext, siv_tests[n].Plaintextlen, - buf, &buflen)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[n].output, siv_tests[n].outputlen, siv_tests[n].name, n) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - buflen = sizeof(buf); - if ((err = siv_decrypt_memory(cipher, - siv_tests[n].Key, siv_tests[n].Keylen, - (const unsigned char **)siv_tests[n].ADs, siv_tests[n].ADlens, - siv_tests[n].output, siv_tests[n].outputlen, - buf, &buflen)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[n].Plaintext, siv_tests[n].Plaintextlen, siv_tests[n].name, n + 0x1000) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - /* Testcase 0x2 */ - buflen = sizeof(buf); - if ((err = siv_memory(cipher, LTC_ENCRYPT, - siv_tests[0].Key, siv_tests[0].Keylen, - siv_tests[0].Plaintext, siv_tests[0].Plaintextlen, - buf, &buflen, - AD_A1, sizeof(AD_A1), - NULL)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[0].output, siv_tests[0].outputlen, siv_tests[0].name, n) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - /* Testcase 0x1002 */ - buflen = sizeof(buf); - if ((err = siv_memory(cipher, LTC_DECRYPT, - siv_tests[0].Key, siv_tests[0].Keylen, - siv_tests[0].output, siv_tests[0].outputlen, - buf, &buflen, - AD_A1, sizeof(AD_A1), - NULL)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[0].Plaintext, siv_tests[0].Plaintextlen, siv_tests[0].name, n + 0x1000) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - n++; - - /* Testcase 0x3 */ - buflen = sizeof(buf); - if ((err = siv_memory(cipher, LTC_ENCRYPT, - siv_tests[1].Key, siv_tests[1].Keylen, - siv_tests[1].Plaintext, siv_tests[1].Plaintextlen, - buf, &buflen, - ad_A2[0], adlen_A2[0], - ad_A2[1], adlen_A2[1], - ad_A2[2], adlen_A2[2], - NULL)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[1].output, siv_tests[1].outputlen, siv_tests[1].name, n) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - /* Testcase 0x1003 */ - buflen = sizeof(buf); - if ((err = siv_memory(cipher, LTC_DECRYPT, - siv_tests[1].Key, siv_tests[1].Keylen, - siv_tests[1].output, siv_tests[1].outputlen, - buf, &buflen, - ad_A2[0], adlen_A2[0], - ad_A2[1], adlen_A2[1], - ad_A2[2], adlen_A2[2], - NULL)) != CRYPT_OK) { - return err; - } - if (compare_testvector(buf, buflen, siv_tests[1].Plaintext, siv_tests[1].Plaintextlen, siv_tests[1].name, n + 0x1000) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - tmpe = XCALLOC(1, tmpmax); - if (tmpe == NULL) { - return CRYPT_MEM; - } - tmpd = XCALLOC(1, tmpmax); - if (tmpd == NULL) { - err = CRYPT_MEM; - goto out_tmpd; - } - tmplen = 16; - for (n = 0; n < niter; ++n) { - buflen = tmpmax; - if ((err = siv_memory(cipher, LTC_ENCRYPT, - siv_tests[0].Key, siv_tests[0].Keylen, - tmpe, tmplen, - tmpe, &buflen, - NULL)) != CRYPT_OK) { - goto out; - } - tmplen = buflen; - } - if (compare_testvector(&buflen, sizeof(buflen), &tmpmax, sizeof(tmpmax), "Multiple encrypt length", -(int)niter)) { - err = CRYPT_FAIL_TESTVECTOR; - goto out; - } - XMEMCPY(tmpd, tmpe, buflen); - for (n = 0; n < niter; ++n) { - buflen = tmpmax; - if ((err = siv_memory(cipher, LTC_DECRYPT, - siv_tests[0].Key, siv_tests[0].Keylen, - tmpd, tmplen, - tmpd, &buflen, - NULL)) != CRYPT_OK) { - goto out; - } - tmplen = buflen; - } - if (compare_testvector(tmpd, tmplen, tmpe, tmplen, "Multi decrypt", niter + 0x2000)) { - err = CRYPT_FAIL_TESTVECTOR; - } - -out: - XFREE(tmpd); -out_tmpd: - XFREE(tmpe); - - return err; -#endif -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/hashes/blake2b.c b/Sources/DataLiteC/libtomcrypt/hashes/blake2b.c deleted file mode 100644 index 73f50f7..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/blake2b.c +++ /dev/null @@ -1,628 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ -/* see also https://www.ietf.org/rfc/rfc7693.txt */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2B - -enum blake2b_constant { - BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, - BLAKE2B_PERSONALBYTES = 16, - BLAKE2B_PARAM_SIZE = 64 -}; - -/* param offsets */ -enum { - BLAKE2B_O_DIGEST_LENGTH = 0, - BLAKE2B_O_KEY_LENGTH = 1, - BLAKE2B_O_FANOUT = 2, - BLAKE2B_O_DEPTH = 3, - BLAKE2B_O_LEAF_LENGTH = 4, - BLAKE2B_O_NODE_OFFSET = 8, - BLAKE2B_O_XOF_LENGTH = 12, - BLAKE2B_O_NODE_DEPTH = 16, - BLAKE2B_O_INNER_LENGTH = 17, - BLAKE2B_O_RESERVED = 18, - BLAKE2B_O_SALT = 32, - BLAKE2B_O_PERSONAL = 48 -}; - -/* -struct blake2b_param { - unsigned char digest_length; - unsigned char key_length; - unsigned char fanout; - unsigned char depth; - ulong32 leaf_length; - ulong32 node_offset; - ulong32 xof_length; - unsigned char node_depth; - unsigned char inner_length; - unsigned char reserved[14]; - unsigned char salt[BLAKE2B_SALTBYTES]; - unsigned char personal[BLAKE2B_PERSONALBYTES]; -}; -*/ - -const struct ltc_hash_descriptor blake2b_160_desc = -{ - "blake2b-160", - 25, - 20, - 128, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 }, - 11, - &blake2b_160_init, - &blake2b_process, - &blake2b_done, - &blake2b_160_test, - NULL -}; - -const struct ltc_hash_descriptor blake2b_256_desc = -{ - "blake2b-256", - 26, - 32, - 128, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 }, - 11, - &blake2b_256_init, - &blake2b_process, - &blake2b_done, - &blake2b_256_test, - NULL -}; - -const struct ltc_hash_descriptor blake2b_384_desc = -{ - "blake2b-384", - 27, - 48, - 128, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 }, - 11, - &blake2b_384_init, - &blake2b_process, - &blake2b_done, - &blake2b_384_test, - NULL -}; - -const struct ltc_hash_descriptor blake2b_512_desc = -{ - "blake2b-512", - 28, - 64, - 128, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 }, - 11, - &blake2b_512_init, - &blake2b_process, - &blake2b_done, - &blake2b_512_test, - NULL -}; - -static const ulong64 blake2b_IV[8] = -{ - CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b), - CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1), - CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f), - CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179) -}; - -static const unsigned char blake2b_sigma[12][16] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } -}; - -static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); } - -/* Some helper functions, not necessarily useful */ -static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; } - -static void s_blake2b_set_lastblock(hash_state *md) -{ - if (md->blake2b.last_node) { - s_blake2b_set_lastnode(md); - } - md->blake2b.f[0] = CONST64(0xffffffffffffffff); -} - -static void s_blake2b_increment_counter(hash_state *md, ulong64 inc) -{ - md->blake2b.t[0] += inc; - if (md->blake2b.t[0] < inc) md->blake2b.t[1]++; -} - -static void s_blake2b_init0(hash_state *md) -{ - unsigned long i; - XMEMSET(&md->blake2b, 0, sizeof(md->blake2b)); - - for (i = 0; i < 8; ++i) { - md->blake2b.h[i] = blake2b_IV[i]; - } -} - -/* init xors IV with input parameter block */ -static int s_blake2b_init_param(hash_state *md, const unsigned char *P) -{ - unsigned long i; - - s_blake2b_init0(md); - - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) { - ulong64 tmp; - LOAD64L(tmp, P + i * 8); - md->blake2b.h[i] ^= tmp; - } - - md->blake2b.outlen = P[BLAKE2B_O_DIGEST_LENGTH]; - return CRYPT_OK; -} - -/** - Initialize the hash/MAC state - - Use this function to init for arbitrary sizes. - - Give a key and keylen to init for MAC mode. - - @param md The hash state you wish to initialize - @param outlen The desired output-length - @param key The key of the MAC - @param keylen The length of the key - @return CRYPT_OK if successful -*/ -int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) -{ - unsigned char P[BLAKE2B_PARAM_SIZE]; - int err; - - LTC_ARGCHK(md != NULL); - - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { - return CRYPT_INVALID_ARG; - } - if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) { - return CRYPT_INVALID_ARG; - } - - XMEMSET(P, 0, sizeof(P)); - - P[BLAKE2B_O_DIGEST_LENGTH] = (unsigned char)outlen; - P[BLAKE2B_O_KEY_LENGTH] = (unsigned char)keylen; - P[BLAKE2B_O_FANOUT] = 1; - P[BLAKE2B_O_DEPTH] = 1; - - err = s_blake2b_init_param(md, P); - if (err != CRYPT_OK) return err; - - if (key) { - unsigned char block[BLAKE2B_BLOCKBYTES]; - - XMEMSET(block, 0, BLAKE2B_BLOCKBYTES); - XMEMCPY(block, key, keylen); - blake2b_process(md, block, BLAKE2B_BLOCKBYTES); - -#ifdef LTC_CLEAN_STACK - zeromem(block, sizeof(block)); -#endif - } - - return CRYPT_OK; -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); } - -#define G(r, i, a, b, c, d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ - d = ROR64(d ^ a, 32); \ - c = c + d; \ - b = ROR64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ - d = ROR64(d ^ a, 16); \ - c = c + d; \ - b = ROR64(b ^ c, 63); \ - } while (0) - -#define ROUND(r) \ - do { \ - G(r, 0, v[0], v[4], v[8], v[12]); \ - G(r, 1, v[1], v[5], v[9], v[13]); \ - G(r, 2, v[2], v[6], v[10], v[14]); \ - G(r, 3, v[3], v[7], v[11], v[15]); \ - G(r, 4, v[0], v[5], v[10], v[15]); \ - G(r, 5, v[1], v[6], v[11], v[12]); \ - G(r, 6, v[2], v[7], v[8], v[13]); \ - G(r, 7, v[3], v[4], v[9], v[14]); \ - } while (0) - -#ifdef LTC_CLEAN_STACK -static int ss_blake2b_compress(hash_state *md, const unsigned char *buf) -#else -static int s_blake2b_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong64 m[16]; - ulong64 v[16]; - unsigned long i; - - for (i = 0; i < 16; ++i) { - LOAD64L(m[i], buf + i * sizeof(m[i])); - } - - for (i = 0; i < 8; ++i) { - v[i] = md->blake2b.h[i]; - } - - v[8] = blake2b_IV[0]; - v[9] = blake2b_IV[1]; - v[10] = blake2b_IV[2]; - v[11] = blake2b_IV[3]; - v[12] = blake2b_IV[4] ^ md->blake2b.t[0]; - v[13] = blake2b_IV[5] ^ md->blake2b.t[1]; - v[14] = blake2b_IV[6] ^ md->blake2b.f[0]; - v[15] = blake2b_IV[7] ^ md->blake2b.f[1]; - - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); - ROUND(10); - ROUND(11); - - for (i = 0; i < 8; ++i) { - md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8]; - } - return CRYPT_OK; -} - -#undef G -#undef ROUND - -#ifdef LTC_CLEAN_STACK -static int s_blake2b_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_blake2b_compress(md, buf); - burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long)); - return err; -} -#endif - -/** - Process a block of memory through the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen) -{ - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - - if (md->blake2b.curlen > sizeof(md->blake2b.buf)) { - return CRYPT_INVALID_ARG; - } - - if (inlen > 0) { - unsigned long left = md->blake2b.curlen; - unsigned long fill = BLAKE2B_BLOCKBYTES - left; - if (inlen > fill) { - md->blake2b.curlen = 0; - XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */ - s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); - s_blake2b_compress(md, md->blake2b.buf); /* Compress */ - in += fill; - inlen -= fill; - while (inlen > BLAKE2B_BLOCKBYTES) { - s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); - s_blake2b_compress(md, in); - in += BLAKE2B_BLOCKBYTES; - inlen -= BLAKE2B_BLOCKBYTES; - } - } - XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen); - md->blake2b.curlen += inlen; - } - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (size depending on the length used on init) - @return CRYPT_OK if successful -*/ -int blake2b_done(hash_state *md, unsigned char *out) -{ - unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 }; - unsigned long i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */ - - if (s_blake2b_is_lastblock(md)) { - return CRYPT_ERROR; - } - - s_blake2b_increment_counter(md, md->blake2b.curlen); - s_blake2b_set_lastblock(md); - XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */ - s_blake2b_compress(md, md->blake2b.buf); - - for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ - STORE64L(md->blake2b.h[i], buffer + i * 8); - } - - XMEMCPY(out, buffer, md->blake2b.outlen); - zeromem(md, sizeof(hash_state)); -#ifdef LTC_CLEAN_STACK - zeromem(buffer, sizeof(buffer)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2b_512_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[64]; - } tests[] = { - { "", - { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, - 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72, - 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, - 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, - 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, - 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b, - 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, - 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } }, - { "abc", - { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, - 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9, - 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7, - 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, - 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, - 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95, - 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, - 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[64]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2b_512_init(&md); - blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2b_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2b_384_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[48]; - } tests[] = { - { "", - { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d, - 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5, - 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a, - 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24, - 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73, - 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } }, - { "abc", - { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26, - 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb, - 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd, - 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6, - 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d, - 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[48]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2b_384_init(&md); - blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2b_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2b_256_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[32]; - } tests[] = { - { "", - { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2, - 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1, - 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87, - 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } }, - { "abc", - { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72, - 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b, - 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42, - 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } }, - { "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890", - { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08, - 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41, - 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3, - 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[32]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2b_256_init(&md); - blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2b_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2b_160_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[20]; - } tests[] = { - { "", - { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18, - 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41, - 0x79, 0x0b, 0x6c, 0xf2 } }, - { "abc", - { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36, - 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc, - 0x68, 0xb6, 0x84, 0x6b } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[20]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2b_160_init(&md); - blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2b_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/blake2s.c b/Sources/DataLiteC/libtomcrypt/hashes/blake2s.c deleted file mode 100644 index 840f8ee..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/blake2s.c +++ /dev/null @@ -1,609 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ -/* see also https://www.ietf.org/rfc/rfc7693.txt */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_BLAKE2S - -enum blake2s_constant { - BLAKE2S_BLOCKBYTES = 64, - BLAKE2S_OUTBYTES = 32, - BLAKE2S_KEYBYTES = 32, - BLAKE2S_SALTBYTES = 8, - BLAKE2S_PERSONALBYTES = 8, - BLAKE2S_PARAM_SIZE = 32 -}; - -/* param offsets */ -enum { - BLAKE2S_O_DIGEST_LENGTH = 0, - BLAKE2S_O_KEY_LENGTH = 1, - BLAKE2S_O_FANOUT = 2, - BLAKE2S_O_DEPTH = 3, - BLAKE2S_O_LEAF_LENGTH = 4, - BLAKE2S_O_NODE_OFFSET = 8, - BLAKE2S_O_XOF_LENGTH = 12, - BLAKE2S_O_NODE_DEPTH = 14, - BLAKE2S_O_INNER_LENGTH = 15, - BLAKE2S_O_SALT = 16, - BLAKE2S_O_PERSONAL = 24 -}; - -/* -struct blake2s_param { - unsigned char digest_length; - unsigned char key_length; - unsigned char fanout; - unsigned char depth; - ulong32 leaf_length; - ulong32 node_offset; - ushort16 xof_length; - unsigned char node_depth; - unsigned char inner_length; - unsigned char salt[BLAKE2S_SALTBYTES]; - unsigned char personal[BLAKE2S_PERSONALBYTES]; -}; -*/ - -const struct ltc_hash_descriptor blake2s_128_desc = -{ - "blake2s-128", - 21, - 16, - 64, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 }, - 11, - &blake2s_128_init, - &blake2s_process, - &blake2s_done, - &blake2s_128_test, - NULL -}; - -const struct ltc_hash_descriptor blake2s_160_desc = -{ - "blake2s-160", - 22, - 20, - 64, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 }, - 11, - &blake2s_160_init, - &blake2s_process, - &blake2s_done, - &blake2s_160_test, - NULL -}; - -const struct ltc_hash_descriptor blake2s_224_desc = -{ - "blake2s-224", - 23, - 28, - 64, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 }, - 11, - &blake2s_224_init, - &blake2s_process, - &blake2s_done, - &blake2s_224_test, - NULL -}; - -const struct ltc_hash_descriptor blake2s_256_desc = -{ - "blake2s-256", - 24, - 32, - 64, - { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 }, - 11, - &blake2s_256_init, - &blake2s_process, - &blake2s_done, - &blake2s_256_test, - NULL -}; - -static const ulong32 blake2s_IV[8] = { - 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, - 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL -}; - -static const unsigned char blake2s_sigma[10][16] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, -}; - -static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; } - -/* Some helper functions, not necessarily useful */ -static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; } - -static void s_blake2s_set_lastblock(hash_state *md) -{ - if (md->blake2s.last_node) { - s_blake2s_set_lastnode(md); - } - md->blake2s.f[0] = 0xffffffffUL; -} - -static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc) -{ - md->blake2s.t[0] += inc; - if (md->blake2s.t[0] < inc) md->blake2s.t[1]++; -} - -static int s_blake2s_init0(hash_state *md) -{ - int i; - XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state)); - - for (i = 0; i < 8; ++i) { - md->blake2s.h[i] = blake2s_IV[i]; - } - - return CRYPT_OK; -} - -/* init2 xors IV with input parameter block */ -static int s_blake2s_init_param(hash_state *md, const unsigned char *P) -{ - unsigned long i; - - s_blake2s_init0(md); - - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) { - ulong32 tmp; - LOAD32L(tmp, P + i * 4); - md->blake2s.h[i] ^= tmp; - } - - md->blake2s.outlen = P[BLAKE2S_O_DIGEST_LENGTH]; - return CRYPT_OK; -} - -/** - Initialize the hash/MAC state - - Use this function to init for arbitrary sizes. - - Give a key and keylen to init for MAC mode. - - @param md The hash state you wish to initialize - @param outlen The desired output-length - @param key The key of the MAC - @param keylen The length of the key - @return CRYPT_OK if successful -*/ -int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) -{ - unsigned char P[BLAKE2S_PARAM_SIZE]; - int err; - - LTC_ARGCHK(md != NULL); - - if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) { - return CRYPT_INVALID_ARG; - } - if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) { - return CRYPT_INVALID_ARG; - } - - XMEMSET(P, 0, sizeof(P)); - - P[BLAKE2S_O_DIGEST_LENGTH] = (unsigned char)outlen; - P[BLAKE2S_O_KEY_LENGTH] = (unsigned char)keylen; - P[BLAKE2S_O_FANOUT] = 1; - P[BLAKE2S_O_DEPTH] = 1; - - err = s_blake2s_init_param(md, P); - if (err != CRYPT_OK) return err; - - if (key) { - unsigned char block[BLAKE2S_BLOCKBYTES]; - - XMEMSET(block, 0, BLAKE2S_BLOCKBYTES); - XMEMCPY(block, key, keylen); - blake2s_process(md, block, BLAKE2S_BLOCKBYTES); - -#ifdef LTC_CLEAN_STACK - zeromem(block, sizeof(block)); -#endif - } - return CRYPT_OK; -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); } - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); } - -#define G(r, i, a, b, c, d) \ - do { \ - a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \ - d = ROR(d ^ a, 16); \ - c = c + d; \ - b = ROR(b ^ c, 12); \ - a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \ - d = ROR(d ^ a, 8); \ - c = c + d; \ - b = ROR(b ^ c, 7); \ - } while (0) -#define ROUND(r) \ - do { \ - G(r, 0, v[0], v[4], v[8], v[12]); \ - G(r, 1, v[1], v[5], v[9], v[13]); \ - G(r, 2, v[2], v[6], v[10], v[14]); \ - G(r, 3, v[3], v[7], v[11], v[15]); \ - G(r, 4, v[0], v[5], v[10], v[15]); \ - G(r, 5, v[1], v[6], v[11], v[12]); \ - G(r, 6, v[2], v[7], v[8], v[13]); \ - G(r, 7, v[3], v[4], v[9], v[14]); \ - } while (0) - -#ifdef LTC_CLEAN_STACK -static int ss_blake2s_compress(hash_state *md, const unsigned char *buf) -#else -static int s_blake2s_compress(hash_state *md, const unsigned char *buf) -#endif -{ - unsigned long i; - ulong32 m[16]; - ulong32 v[16]; - - for (i = 0; i < 16; ++i) { - LOAD32L(m[i], buf + i * sizeof(m[i])); - } - - for (i = 0; i < 8; ++i) { - v[i] = md->blake2s.h[i]; - } - - v[8] = blake2s_IV[0]; - v[9] = blake2s_IV[1]; - v[10] = blake2s_IV[2]; - v[11] = blake2s_IV[3]; - v[12] = md->blake2s.t[0] ^ blake2s_IV[4]; - v[13] = md->blake2s.t[1] ^ blake2s_IV[5]; - v[14] = md->blake2s.f[0] ^ blake2s_IV[6]; - v[15] = md->blake2s.f[1] ^ blake2s_IV[7]; - - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); - - for (i = 0; i < 8; ++i) { - md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8]; - } - return CRYPT_OK; -} -#undef G -#undef ROUND - -#ifdef LTC_CLEAN_STACK -static int s_blake2s_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_blake2s_compress(md, buf); - burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long)); - return err; -} -#endif - -/** - Process a block of memory through the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen) -{ - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - - if (md->blake2s.curlen > sizeof(md->blake2s.buf)) { - return CRYPT_INVALID_ARG; - } - - if (inlen > 0) { - unsigned long left = md->blake2s.curlen; - unsigned long fill = BLAKE2S_BLOCKBYTES - left; - if (inlen > fill) { - md->blake2s.curlen = 0; - XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */ - s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); - s_blake2s_compress(md, md->blake2s.buf); /* Compress */ - in += fill; - inlen -= fill; - while (inlen > BLAKE2S_BLOCKBYTES) { - s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); - s_blake2s_compress(md, in); - in += BLAKE2S_BLOCKBYTES; - inlen -= BLAKE2S_BLOCKBYTES; - } - } - XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen); - md->blake2s.curlen += inlen; - } - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (size depending on the length used on init) - @return CRYPT_OK if successful -*/ -int blake2s_done(hash_state *md, unsigned char *out) -{ - unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 }; - unsigned long i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */ - - if (s_blake2s_is_lastblock(md)) { - return CRYPT_ERROR; - } - s_blake2s_increment_counter(md, md->blake2s.curlen); - s_blake2s_set_lastblock(md); - XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */ - s_blake2s_compress(md, md->blake2s.buf); - - for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ - STORE32L(md->blake2s.h[i], buffer + i * 4); - } - - XMEMCPY(out, buffer, md->blake2s.outlen); - zeromem(md, sizeof(hash_state)); -#ifdef LTC_CLEAN_STACK - zeromem(buffer, sizeof(buffer)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2s_256_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[32]; - } tests[] = { - { "", - { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, - 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c, - 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, - 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } }, - { "abc", - { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2, - 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f, - 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29, - 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } }, - { "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890" - "12345678901234567890123456789012345678901234567890", - { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41, - 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41, - 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70, - 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[32]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2s_256_init(&md); - blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2s_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2s_224_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[28]; - } tests[] = { - { "", - { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37, - 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63, - 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34, - 0xe7, 0xbc, 0x1e, 0xf4 } }, - { "abc", - { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd, - 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c, - 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87, - 0x40, 0x7f, 0xbd, 0x55 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[28]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2s_224_init(&md); - blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2s_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2s_160_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[20]; - } tests[] = { - { "", - { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24, - 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42, - 0x9c, 0x34, 0x91, 0x6f} }, - { "abc", - { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83, - 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04, - 0x38, 0xf8, 0xde, 0x17 } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[20]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2s_160_init(&md); - blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2s_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int blake2s_128_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[16]; - } tests[] = { - { "", - { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01, - 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } }, - { "abc", - { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8, - 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } }, - - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[16]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - blake2s_128_init(&md); - blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - blake2s_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/hashes/chc/chc.c b/Sources/DataLiteC/libtomcrypt/hashes/chc/chc.c deleted file mode 100644 index 3a394d4..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/chc/chc.c +++ /dev/null @@ -1,302 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file chc.c - CHC support. (Tom St Denis) -*/ - -#ifdef LTC_CHC_HASH - -#define UNDEFED_HASH -17 - -/* chc settings */ -static int cipher_idx=UNDEFED_HASH, /* which cipher */ - cipher_blocksize; /* blocksize of cipher */ - - -const struct ltc_hash_descriptor chc_desc = { - "chc_hash", 12, 0, 0, { 0 }, 0, - &chc_init, - &chc_process, - &chc_done, - &chc_test, - NULL -}; - -/** - Initialize the CHC state with a given cipher - @param cipher The index of the cipher you wish to bind - @return CRYPT_OK if successful -*/ -int chc_register(int cipher) -{ - int err, kl, idx; - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* will it be valid? */ - kl = cipher_descriptor[cipher].block_length; - - /* must be >64 bit block */ - if (kl <= 8) { - return CRYPT_INVALID_CIPHER; - } - - /* can we use the ideal keysize? */ - if ((err = cipher_descriptor[cipher].keysize(&kl)) != CRYPT_OK) { - return err; - } - /* we require that key size == block size be a valid choice */ - if (kl != cipher_descriptor[cipher].block_length) { - return CRYPT_INVALID_CIPHER; - } - - /* determine if chc_hash has been register_hash'ed already */ - if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) { - return err; - } - - /* store into descriptor */ - hash_descriptor[idx].hashsize = - hash_descriptor[idx].blocksize = cipher_descriptor[cipher].block_length; - - /* store the idx and block size */ - cipher_idx = cipher; - cipher_blocksize = cipher_descriptor[cipher].block_length; - return CRYPT_OK; -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int chc_init(hash_state *md) -{ - symmetric_key *key; - unsigned char buf[MAXBLOCKSIZE]; - int err; - - LTC_ARGCHK(md != NULL); - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { - return err; - } - - if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { - return CRYPT_INVALID_CIPHER; - } - - if ((key = XMALLOC(sizeof(*key))) == NULL) { - return CRYPT_MEM; - } - - /* zero key and what not */ - zeromem(buf, cipher_blocksize); - if ((err = cipher_descriptor[cipher_idx].setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) { - XFREE(key); - return err; - } - - /* encrypt zero block */ - cipher_descriptor[cipher_idx].ecb_encrypt(buf, md->chc.state, key); - - /* zero other members */ - md->chc.length = 0; - md->chc.curlen = 0; - zeromem(md->chc.buf, sizeof(md->chc.buf)); - XFREE(key); - return CRYPT_OK; -} - -/* - key <= state - T0,T1 <= block - T0 <= encrypt T0 - state <= state xor T0 xor T1 -*/ -static int s_chc_compress(hash_state *md, const unsigned char *buf) -{ - unsigned char T[2][MAXBLOCKSIZE]; - symmetric_key *key; - int err, x; - - if ((key = XMALLOC(sizeof(*key))) == NULL) { - return CRYPT_MEM; - } - if ((err = cipher_descriptor[cipher_idx].setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) { - XFREE(key); - return err; - } - XMEMCPY(T[1], buf, cipher_blocksize); - cipher_descriptor[cipher_idx].ecb_encrypt(buf, T[0], key); - for (x = 0; x < cipher_blocksize; x++) { - md->chc.state[x] ^= T[0][x] ^ T[1][x]; - } -#ifdef LTC_CLEAN_STACK - zeromem(T, sizeof(T)); - zeromem(key, sizeof(*key)); -#endif - XFREE(key); - return CRYPT_OK; -} - -/** - Function for processing blocks - @param md The hash state - @param buf The data to hash - @param len The length of the data (octets) - @return CRYPT_OK if successful -*/ -static int ss_chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); -static HASH_PROCESS(ss_chc_process, s_chc_compress, chc, (unsigned long)cipher_blocksize) - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen) -{ - int err; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { - return err; - } - if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { - return CRYPT_INVALID_CIPHER; - } - - return ss_chc_process(md, in, inlen); -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (length of the block size of the block cipher) - @return CRYPT_OK if successful -*/ -int chc_done(hash_state *md, unsigned char *out) -{ - int err; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { - return err; - } - if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { - return CRYPT_INVALID_CIPHER; - } - - if (md->chc.curlen >= sizeof(md->chc.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->chc.length += md->chc.curlen * 8; - - /* append the '1' bit */ - md->chc.buf[md->chc.curlen++] = (unsigned char)0x80; - - /* if the length is currently above l-8 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) { - while (md->chc.curlen < (unsigned long)cipher_blocksize) { - md->chc.buf[md->chc.curlen++] = (unsigned char)0; - } - s_chc_compress(md, md->chc.buf); - md->chc.curlen = 0; - } - - /* pad upto l-8 bytes of zeroes */ - while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) { - md->chc.buf[md->chc.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8)); - s_chc_compress(md, md->chc.buf); - - /* copy output */ - XMEMCPY(out, md->chc.state, cipher_blocksize); - -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int chc_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char *msg, - hash[MAXBLOCKSIZE]; - int len; - } tests[] = { -{ - (unsigned char *)"hello world", - { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, - 0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e }, - 16 -} -}; - int i, oldhashidx, idx, err; - unsigned char tmp[MAXBLOCKSIZE]; - hash_state md; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - oldhashidx = cipher_idx; - chc_register(idx); - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - if ((err = chc_init(&md)) != CRYPT_OK) { - return err; - } - if ((err = chc_process(&md, tests[i].msg, XSTRLEN((char *)tests[i].msg))) != CRYPT_OK) { - return err; - } - if ((err = chc_done(&md, tmp)) != CRYPT_OK) { - return err; - } - if (compare_testvector(tmp, tests[i].len, tests[i].hash, tests[i].len, "CHC", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - if (oldhashidx != UNDEFED_HASH) { - chc_register(oldhashidx); - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_file.c b/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_file.c deleted file mode 100644 index d2711db..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_file.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifndef LTC_NO_FILE -/** - @file hash_file.c - Hash a file, Tom St Denis -*/ - -/** - @param hash The index of the hash desired - @param fname The name of the file you wish to hash - @param out [out] The destination of the digest - @param outlen [in/out] The max size and resulting size of the message digest - @result CRYPT_OK if successful -*/ -int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) -{ - FILE *in; - int err; - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - return CRYPT_FILE_NOTFOUND; - } - - err = hash_filehandle(hash, in, out, outlen); - if (fclose(in) != 0) { - return CRYPT_ERROR; - } - - return err; -} -#endif /* #ifndef LTC_NO_FILE */ - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_filehandle.c b/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_filehandle.c deleted file mode 100644 index f4eee7f..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_filehandle.c +++ /dev/null @@ -1,64 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifndef LTC_NO_FILE -/** - @file hash_filehandle.c - Hash open files, Tom St Denis -*/ - -/** - Hash data from an open file handle. - @param hash The index of the hash you want to use - @param in The FILE* handle of the file you want to hash - @param out [out] The destination of the digest - @param outlen [in/out] The max size and resulting size of the digest - @result CRYPT_OK if successful -*/ -int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) -{ - hash_state md; - unsigned char *buf; - size_t x; - int err; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(in != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - goto LBL_ERR; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - *outlen = hash_descriptor[hash].hashsize; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) { - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = hash_descriptor[hash].process(&md, buf, (unsigned long)x)) != CRYPT_OK) { - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - if ((err = hash_descriptor[hash].done(&md, out)) == CRYPT_OK) { - *outlen = hash_descriptor[hash].hashsize; - } - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: - XFREE(buf); - return err; -} -#endif /* #ifndef LTC_NO_FILE */ - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory.c b/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory.c deleted file mode 100644 index f38f51c..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_HASH_HELPERS -/** - @file hash_memory.c - Hash memory helper, Tom St Denis -*/ - -/** - Hash a block of memory and store the digest. - @param hash The index of the hash you wish to use - @param in The data you wish to hash - @param inlen The length of the data to hash (octets) - @param out [out] Where to store the digest - @param outlen [in/out] Max size and resulting size of the digest - @return CRYPT_OK if successful -*/ -int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) -{ - hash_state *md; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - *outlen = hash_descriptor[hash].hashsize; - return CRYPT_BUFFER_OVERFLOW; - } - - md = XMALLOC(sizeof(hash_state)); - if (md == NULL) { - return CRYPT_MEM; - } - - if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) { - goto LBL_ERR; - } - err = hash_descriptor[hash].done(md, out); - *outlen = hash_descriptor[hash].hashsize; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - XFREE(md); - - return err; -} -#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory_multi.c b/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory_multi.c deleted file mode 100644 index 4c72efc..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/helper/hash_memory_multi.c +++ /dev/null @@ -1,77 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_HASH_HELPERS -/** - @file hash_memory_multi.c - Hash (multiple buffers) memory helper, Tom St Denis -*/ - -/** - Hash multiple (non-adjacent) blocks of memory at once. - @param hash The index of the hash you wish to use - @param out [out] Where to store the digest - @param outlen [in/out] Max size and resulting size of the digest - @param in The data you wish to hash - @param inlen The length of the data to hash (octets) - @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) -{ - hash_state *md; - int err; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - *outlen = hash_descriptor[hash].hashsize; - return CRYPT_BUFFER_OVERFLOW; - } - - md = XMALLOC(sizeof(hash_state)); - if (md == NULL) { - return CRYPT_MEM; - } - - if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { - goto LBL_ERR; - } - - va_start(args, inlen); - curptr = in; - curlen = inlen; - for (;;) { - /* process buf */ - if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - err = hash_descriptor[hash].done(md, out); - *outlen = hash_descriptor[hash].hashsize; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - XFREE(md); - va_end(args); - return err; -} -#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/Sources/DataLiteC/libtomcrypt/hashes/md2.c b/Sources/DataLiteC/libtomcrypt/hashes/md2.c deleted file mode 100644 index 6cf0a65..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/md2.c +++ /dev/null @@ -1,240 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @param md2.c - LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis -*/ - -#ifdef LTC_MD2 - -const struct ltc_hash_descriptor md2_desc = -{ - "md2", - 7, - 16, - 16, - - /* OID */ - { 1, 2, 840, 113549, 2, 2, }, - 6, - - &md2_init, - &md2_process, - &md2_done, - &md2_test, - NULL -}; - -static const unsigned char PI_SUBST[256] = { - 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, - 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, - 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, - 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, - 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, - 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, - 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, - 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, - 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, - 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, - 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, - 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, - 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, - 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, - 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, - 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, - 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, - 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 -}; - -/* adds 16 bytes to the checksum */ -static void s_md2_update_chksum(hash_state *md) -{ - int j; - unsigned char L; - L = md->md2.chksum[15]; - for (j = 0; j < 16; j++) { - -/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say - otherwise. -*/ - L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255); - } -} - -static void s_md2_compress(hash_state *md) -{ - int j, k; - unsigned char t; - - /* copy block */ - for (j = 0; j < 16; j++) { - md->md2.X[16+j] = md->md2.buf[j]; - md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j]; - } - - t = (unsigned char)0; - - /* do 18 rounds */ - for (j = 0; j < 18; j++) { - for (k = 0; k < 48; k++) { - t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]); - } - t = (t + (unsigned char)j) & 255; - } -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int md2_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - - /* LTC_MD2 uses a zero'ed state... */ - zeromem(md->md2.X, sizeof(md->md2.X)); - zeromem(md->md2.chksum, sizeof(md->md2.chksum)); - zeromem(md->md2.buf, sizeof(md->md2.buf)); - md->md2.curlen = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen) -{ - unsigned long n; - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - if (md-> md2 .curlen > sizeof(md-> md2 .buf)) { - return CRYPT_INVALID_ARG; - } - while (inlen > 0) { - n = MIN(inlen, (16 - md->md2.curlen)); - XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n); - md->md2.curlen += n; - in += n; - inlen -= n; - - /* is 16 bytes full? */ - if (md->md2.curlen == 16) { - s_md2_compress(md); - s_md2_update_chksum(md); - md->md2.curlen = 0; - } - } - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (16 bytes) - @return CRYPT_OK if successful -*/ -int md2_done(hash_state * md, unsigned char *out) -{ - unsigned long i, k; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->md2.curlen >= sizeof(md->md2.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* pad the message */ - k = 16 - md->md2.curlen; - for (i = md->md2.curlen; i < 16; i++) { - md->md2.buf[i] = (unsigned char)k; - } - - /* hash and update */ - s_md2_compress(md); - s_md2_update_chksum(md); - - /* hash checksum */ - XMEMCPY(md->md2.buf, md->md2.chksum, 16); - s_md2_compress(md); - - /* output is lower 16 bytes of X */ - XMEMCPY(out, md->md2.X, 16); - -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int md2_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[16]; - } tests[] = { - { "", - {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, - 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73 - } - }, - { "a", - {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, - 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1 - } - }, - { "message digest", - {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, - 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0 - } - }, - { "abcdefghijklmnopqrstuvwxyz", - {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, - 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b - } - }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, - 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd - } - }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, - 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8 - } - } - }; - - int i; - unsigned char tmp[16]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - md2_init(&md); - md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - md2_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/md4.c b/Sources/DataLiteC/libtomcrypt/hashes/md4.c deleted file mode 100644 index 4fba8ba..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/md4.c +++ /dev/null @@ -1,316 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @param md4.c - Submitted by Dobes Vandermeer (dobes@smartt.com) -*/ - -#ifdef LTC_MD4 - -const struct ltc_hash_descriptor md4_desc = -{ - "md4", - 6, - 16, - 64, - - /* OID */ - { 1, 2, 840, 113549, 2, 4, }, - 6, - - &md4_init, - &md4_process, - &md4_done, - &md4_test, - NULL -}; - -#define S11 3 -#define S12 7 -#define S13 11 -#define S14 19 -#define S21 3 -#define S22 5 -#define S23 9 -#define S24 13 -#define S31 3 -#define S32 9 -#define S33 11 -#define S34 15 - -/* F, G and H are basic LTC_MD4 functions. */ -#define F(x, y, z) (z ^ (x & (y ^ z))) -#define G(x, y, z) ((x & y) | (z & (x | y))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x, n) ROLc(x, n) - -/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ -/* Rotation is separate from addition to prevent recomputation */ - -#define FF(a, b, c, d, x, s) { \ - (a) += F ((b), (c), (d)) + (x); \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define GG(a, b, c, d, x, s) { \ - (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define HH(a, b, c, d, x, s) { \ - (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } - -#ifdef LTC_CLEAN_STACK -static int ss_md4_compress(hash_state *md, const unsigned char *buf) -#else -static int s_md4_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 x[16], a, b, c, d; - int i; - - /* copy state */ - a = md->md4.state[0]; - b = md->md4.state[1]; - c = md->md4.state[2]; - d = md->md4.state[3]; - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32L(x[i], buf + (4*i)); - } - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11); /* 1 */ - FF (d, a, b, c, x[ 1], S12); /* 2 */ - FF (c, d, a, b, x[ 2], S13); /* 3 */ - FF (b, c, d, a, x[ 3], S14); /* 4 */ - FF (a, b, c, d, x[ 4], S11); /* 5 */ - FF (d, a, b, c, x[ 5], S12); /* 6 */ - FF (c, d, a, b, x[ 6], S13); /* 7 */ - FF (b, c, d, a, x[ 7], S14); /* 8 */ - FF (a, b, c, d, x[ 8], S11); /* 9 */ - FF (d, a, b, c, x[ 9], S12); /* 10 */ - FF (c, d, a, b, x[10], S13); /* 11 */ - FF (b, c, d, a, x[11], S14); /* 12 */ - FF (a, b, c, d, x[12], S11); /* 13 */ - FF (d, a, b, c, x[13], S12); /* 14 */ - FF (c, d, a, b, x[14], S13); /* 15 */ - FF (b, c, d, a, x[15], S14); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 0], S21); /* 17 */ - GG (d, a, b, c, x[ 4], S22); /* 18 */ - GG (c, d, a, b, x[ 8], S23); /* 19 */ - GG (b, c, d, a, x[12], S24); /* 20 */ - GG (a, b, c, d, x[ 1], S21); /* 21 */ - GG (d, a, b, c, x[ 5], S22); /* 22 */ - GG (c, d, a, b, x[ 9], S23); /* 23 */ - GG (b, c, d, a, x[13], S24); /* 24 */ - GG (a, b, c, d, x[ 2], S21); /* 25 */ - GG (d, a, b, c, x[ 6], S22); /* 26 */ - GG (c, d, a, b, x[10], S23); /* 27 */ - GG (b, c, d, a, x[14], S24); /* 28 */ - GG (a, b, c, d, x[ 3], S21); /* 29 */ - GG (d, a, b, c, x[ 7], S22); /* 30 */ - GG (c, d, a, b, x[11], S23); /* 31 */ - GG (b, c, d, a, x[15], S24); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 0], S31); /* 33 */ - HH (d, a, b, c, x[ 8], S32); /* 34 */ - HH (c, d, a, b, x[ 4], S33); /* 35 */ - HH (b, c, d, a, x[12], S34); /* 36 */ - HH (a, b, c, d, x[ 2], S31); /* 37 */ - HH (d, a, b, c, x[10], S32); /* 38 */ - HH (c, d, a, b, x[ 6], S33); /* 39 */ - HH (b, c, d, a, x[14], S34); /* 40 */ - HH (a, b, c, d, x[ 1], S31); /* 41 */ - HH (d, a, b, c, x[ 9], S32); /* 42 */ - HH (c, d, a, b, x[ 5], S33); /* 43 */ - HH (b, c, d, a, x[13], S34); /* 44 */ - HH (a, b, c, d, x[ 3], S31); /* 45 */ - HH (d, a, b, c, x[11], S32); /* 46 */ - HH (c, d, a, b, x[ 7], S33); /* 47 */ - HH (b, c, d, a, x[15], S34); /* 48 */ - - - /* Update our state */ - md->md4.state[0] = md->md4.state[0] + a; - md->md4.state[1] = md->md4.state[1] + b; - md->md4.state[2] = md->md4.state[2] + c; - md->md4.state[3] = md->md4.state[3] + d; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_md4_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_md4_compress(md, buf); - burn_stack(sizeof(ulong32) * 20 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int md4_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->md4.state[0] = 0x67452301UL; - md->md4.state[1] = 0xefcdab89UL; - md->md4.state[2] = 0x98badcfeUL; - md->md4.state[3] = 0x10325476UL; - md->md4.length = 0; - md->md4.curlen = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(md4_process, s_md4_compress, md4, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (16 bytes) - @return CRYPT_OK if successful -*/ -int md4_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->md4.curlen >= sizeof(md->md4.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->md4.length += md->md4.curlen * 8; - - /* append the '1' bit */ - md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->md4.curlen > 56) { - while (md->md4.curlen < 64) { - md->md4.buf[md->md4.curlen++] = (unsigned char)0; - } - s_md4_compress(md, md->md4.buf); - md->md4.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->md4.curlen < 56) { - md->md4.buf[md->md4.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->md4.length, md->md4.buf+56); - s_md4_compress(md, md->md4.buf); - - /* copy output */ - for (i = 0; i < 4; i++) { - STORE32L(md->md4.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int md4_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct md4_test_case { - const char *input; - unsigned char hash[16]; - } tests[] = { - { "", - {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, - 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} }, - { "a", - {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, - 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} }, - { "abc", - {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, - 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} }, - { "message digest", - {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, - 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} }, - { "abcdefghijklmnopqrstuvwxyz", - {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, - 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, - 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, - 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} }, - }; - - int i; - unsigned char tmp[16]; - hash_state md; - - for(i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - md4_init(&md); - md4_process(&md, (unsigned char *)tests[i].input, (unsigned long)XSTRLEN(tests[i].input)); - md4_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD4", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; - #endif -} - -#undef F -#undef G -#undef H -#undef FF -#undef GG -#undef HH -#undef S11 -#undef S12 -#undef S13 -#undef S14 -#undef S21 -#undef S22 -#undef S23 -#undef S24 -#undef S31 -#undef S32 -#undef S33 -#undef S34 -#undef ROTATE_LEFT - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/md5.c b/Sources/DataLiteC/libtomcrypt/hashes/md5.c deleted file mode 100644 index 912933e..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/md5.c +++ /dev/null @@ -1,363 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -/** - @file md5.c - LTC_MD5 hash function by Tom St Denis -*/ - -#ifdef LTC_MD5 - -const struct ltc_hash_descriptor md5_desc = -{ - "md5", - 3, - 16, - 64, - - /* OID */ - { 1, 2, 840, 113549, 2, 5, }, - 6, - - &md5_init, - &md5_process, - &md5_done, - &md5_test, - NULL -}; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define G(x,y,z) (y ^ (z & (y ^ x))) -#define H(x,y,z) (x^y^z) -#define I(x,y,z) (y^(x|(~z))) - -#ifdef LTC_SMALL_CODE - -#define FF(a,b,c,d,M,s,t) \ - a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; - -#define GG(a,b,c,d,M,s,t) \ - a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; - -#define HH(a,b,c,d,M,s,t) \ - a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; - -#define II(a,b,c,d,M,s,t) \ - a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; - -static const unsigned char Worder[64] = { - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, - 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, - 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 -}; - -static const unsigned char Rorder[64] = { - 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, - 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, - 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, - 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 -}; - -static const ulong32 Korder[64] = { -0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, -0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, -0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, -0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, -0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, -0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, -0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, -0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL -}; - -#else - -#define FF(a,b,c,d,M,s,t) \ - a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define GG(a,b,c,d,M,s,t) \ - a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define HH(a,b,c,d,M,s,t) \ - a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define II(a,b,c,d,M,s,t) \ - a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; - - -#endif - -#ifdef LTC_CLEAN_STACK -static int ss_md5_compress(hash_state *md, const unsigned char *buf) -#else -static int s_md5_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 i, W[16], a, b, c, d; -#ifdef LTC_SMALL_CODE - ulong32 t; -#endif - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32L(W[i], buf + (4*i)); - } - - /* copy state */ - a = md->md5.state[0]; - b = md->md5.state[1]; - c = md->md5.state[2]; - d = md->md5.state[3]; - -#ifdef LTC_SMALL_CODE - for (i = 0; i < 16; ++i) { - FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); - t = d; d = c; c = b; b = a; a = t; - } - - for (; i < 32; ++i) { - GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); - t = d; d = c; c = b; b = a; a = t; - } - - for (; i < 48; ++i) { - HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); - t = d; d = c; c = b; b = a; a = t; - } - - for (; i < 64; ++i) { - II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); - t = d; d = c; c = b; b = a; a = t; - } - -#else - FF(a,b,c,d,W[0],7,0xd76aa478UL) - FF(d,a,b,c,W[1],12,0xe8c7b756UL) - FF(c,d,a,b,W[2],17,0x242070dbUL) - FF(b,c,d,a,W[3],22,0xc1bdceeeUL) - FF(a,b,c,d,W[4],7,0xf57c0fafUL) - FF(d,a,b,c,W[5],12,0x4787c62aUL) - FF(c,d,a,b,W[6],17,0xa8304613UL) - FF(b,c,d,a,W[7],22,0xfd469501UL) - FF(a,b,c,d,W[8],7,0x698098d8UL) - FF(d,a,b,c,W[9],12,0x8b44f7afUL) - FF(c,d,a,b,W[10],17,0xffff5bb1UL) - FF(b,c,d,a,W[11],22,0x895cd7beUL) - FF(a,b,c,d,W[12],7,0x6b901122UL) - FF(d,a,b,c,W[13],12,0xfd987193UL) - FF(c,d,a,b,W[14],17,0xa679438eUL) - FF(b,c,d,a,W[15],22,0x49b40821UL) - GG(a,b,c,d,W[1],5,0xf61e2562UL) - GG(d,a,b,c,W[6],9,0xc040b340UL) - GG(c,d,a,b,W[11],14,0x265e5a51UL) - GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) - GG(a,b,c,d,W[5],5,0xd62f105dUL) - GG(d,a,b,c,W[10],9,0x02441453UL) - GG(c,d,a,b,W[15],14,0xd8a1e681UL) - GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) - GG(a,b,c,d,W[9],5,0x21e1cde6UL) - GG(d,a,b,c,W[14],9,0xc33707d6UL) - GG(c,d,a,b,W[3],14,0xf4d50d87UL) - GG(b,c,d,a,W[8],20,0x455a14edUL) - GG(a,b,c,d,W[13],5,0xa9e3e905UL) - GG(d,a,b,c,W[2],9,0xfcefa3f8UL) - GG(c,d,a,b,W[7],14,0x676f02d9UL) - GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) - HH(a,b,c,d,W[5],4,0xfffa3942UL) - HH(d,a,b,c,W[8],11,0x8771f681UL) - HH(c,d,a,b,W[11],16,0x6d9d6122UL) - HH(b,c,d,a,W[14],23,0xfde5380cUL) - HH(a,b,c,d,W[1],4,0xa4beea44UL) - HH(d,a,b,c,W[4],11,0x4bdecfa9UL) - HH(c,d,a,b,W[7],16,0xf6bb4b60UL) - HH(b,c,d,a,W[10],23,0xbebfbc70UL) - HH(a,b,c,d,W[13],4,0x289b7ec6UL) - HH(d,a,b,c,W[0],11,0xeaa127faUL) - HH(c,d,a,b,W[3],16,0xd4ef3085UL) - HH(b,c,d,a,W[6],23,0x04881d05UL) - HH(a,b,c,d,W[9],4,0xd9d4d039UL) - HH(d,a,b,c,W[12],11,0xe6db99e5UL) - HH(c,d,a,b,W[15],16,0x1fa27cf8UL) - HH(b,c,d,a,W[2],23,0xc4ac5665UL) - II(a,b,c,d,W[0],6,0xf4292244UL) - II(d,a,b,c,W[7],10,0x432aff97UL) - II(c,d,a,b,W[14],15,0xab9423a7UL) - II(b,c,d,a,W[5],21,0xfc93a039UL) - II(a,b,c,d,W[12],6,0x655b59c3UL) - II(d,a,b,c,W[3],10,0x8f0ccc92UL) - II(c,d,a,b,W[10],15,0xffeff47dUL) - II(b,c,d,a,W[1],21,0x85845dd1UL) - II(a,b,c,d,W[8],6,0x6fa87e4fUL) - II(d,a,b,c,W[15],10,0xfe2ce6e0UL) - II(c,d,a,b,W[6],15,0xa3014314UL) - II(b,c,d,a,W[13],21,0x4e0811a1UL) - II(a,b,c,d,W[4],6,0xf7537e82UL) - II(d,a,b,c,W[11],10,0xbd3af235UL) - II(c,d,a,b,W[2],15,0x2ad7d2bbUL) - II(b,c,d,a,W[9],21,0xeb86d391UL) -#endif - - md->md5.state[0] = md->md5.state[0] + a; - md->md5.state[1] = md->md5.state[1] + b; - md->md5.state[2] = md->md5.state[2] + c; - md->md5.state[3] = md->md5.state[3] + d; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_md5_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_md5_compress(md, buf); - burn_stack(sizeof(ulong32) * 21); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int md5_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->md5.state[0] = 0x67452301UL; - md->md5.state[1] = 0xefcdab89UL; - md->md5.state[2] = 0x98badcfeUL; - md->md5.state[3] = 0x10325476UL; - md->md5.curlen = 0; - md->md5.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(md5_process, s_md5_compress, md5, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (16 bytes) - @return CRYPT_OK if successful -*/ -int md5_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->md5.curlen >= sizeof(md->md5.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->md5.length += md->md5.curlen * 8; - - /* append the '1' bit */ - md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->md5.curlen > 56) { - while (md->md5.curlen < 64) { - md->md5.buf[md->md5.curlen++] = (unsigned char)0; - } - s_md5_compress(md, md->md5.buf); - md->md5.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->md5.curlen < 56) { - md->md5.buf[md->md5.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->md5.length, md->md5.buf+56); - s_md5_compress(md, md->md5.buf); - - /* copy output */ - for (i = 0; i < 4; i++) { - STORE32L(md->md5.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int md5_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[16]; - } tests[] = { - { "", - { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, - 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, - { "a", - {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, - 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, - { "abc", - { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, - 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, - { "message digest", - { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, - 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, - { "abcdefghijklmnopqrstuvwxyz", - { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, - 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, - 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, - 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, - { NULL, { 0 } } - }; - - int i; - unsigned char tmp[16]; - hash_state md; - - for (i = 0; tests[i].msg != NULL; i++) { - md5_init(&md); - md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - md5_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#undef F -#undef G -#undef H -#undef I -#undef FF -#undef GG -#undef HH -#undef II - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/rmd128.c b/Sources/DataLiteC/libtomcrypt/hashes/rmd128.c deleted file mode 100644 index cc894e1..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/rmd128.c +++ /dev/null @@ -1,408 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @param rmd128.c - RMD128 Hash function -*/ - -/* Implementation of LTC_RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC - * - * This source has been radically overhauled to be portable and work within - * the LibTomCrypt API by Tom St Denis - */ - -#ifdef LTC_RIPEMD128 - -const struct ltc_hash_descriptor rmd128_desc = -{ - "rmd128", - 8, - 16, - 64, - - /* OID */ - { 1, 0, 10118, 3, 0, 50 }, - 6, - - &rmd128_init, - &rmd128_process, - &rmd128_done, - &rmd128_test, - NULL -}; - -/* the four basic functions F(), G() and H() */ -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) - -/* the eight basic operations FF() through III() */ -#define FF(a, b, c, d, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)); - -#define GG(a, b, c, d, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = ROLc((a), (s)); - -#define HH(a, b, c, d, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = ROLc((a), (s)); - -#define II(a, b, c, d, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = ROLc((a), (s)); - -#define FFF(a, b, c, d, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)); - -#define GGG(a, b, c, d, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = ROLc((a), (s)); - -#define HHH(a, b, c, d, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = ROLc((a), (s)); - -#define III(a, b, c, d, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = ROLc((a), (s)); - -#ifdef LTC_CLEAN_STACK -static int ss_rmd128_compress(hash_state *md, const unsigned char *buf) -#else -static int s_rmd128_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->rmd128.state[0]; - bb = bbb = md->rmd128.state[1]; - cc = ccc = md->rmd128.state[2]; - dd = ddd = md->rmd128.state[3]; - - /* round 1 */ - FF(aa, bb, cc, dd, X[ 0], 11); - FF(dd, aa, bb, cc, X[ 1], 14); - FF(cc, dd, aa, bb, X[ 2], 15); - FF(bb, cc, dd, aa, X[ 3], 12); - FF(aa, bb, cc, dd, X[ 4], 5); - FF(dd, aa, bb, cc, X[ 5], 8); - FF(cc, dd, aa, bb, X[ 6], 7); - FF(bb, cc, dd, aa, X[ 7], 9); - FF(aa, bb, cc, dd, X[ 8], 11); - FF(dd, aa, bb, cc, X[ 9], 13); - FF(cc, dd, aa, bb, X[10], 14); - FF(bb, cc, dd, aa, X[11], 15); - FF(aa, bb, cc, dd, X[12], 6); - FF(dd, aa, bb, cc, X[13], 7); - FF(cc, dd, aa, bb, X[14], 9); - FF(bb, cc, dd, aa, X[15], 8); - - /* round 2 */ - GG(aa, bb, cc, dd, X[ 7], 7); - GG(dd, aa, bb, cc, X[ 4], 6); - GG(cc, dd, aa, bb, X[13], 8); - GG(bb, cc, dd, aa, X[ 1], 13); - GG(aa, bb, cc, dd, X[10], 11); - GG(dd, aa, bb, cc, X[ 6], 9); - GG(cc, dd, aa, bb, X[15], 7); - GG(bb, cc, dd, aa, X[ 3], 15); - GG(aa, bb, cc, dd, X[12], 7); - GG(dd, aa, bb, cc, X[ 0], 12); - GG(cc, dd, aa, bb, X[ 9], 15); - GG(bb, cc, dd, aa, X[ 5], 9); - GG(aa, bb, cc, dd, X[ 2], 11); - GG(dd, aa, bb, cc, X[14], 7); - GG(cc, dd, aa, bb, X[11], 13); - GG(bb, cc, dd, aa, X[ 8], 12); - - /* round 3 */ - HH(aa, bb, cc, dd, X[ 3], 11); - HH(dd, aa, bb, cc, X[10], 13); - HH(cc, dd, aa, bb, X[14], 6); - HH(bb, cc, dd, aa, X[ 4], 7); - HH(aa, bb, cc, dd, X[ 9], 14); - HH(dd, aa, bb, cc, X[15], 9); - HH(cc, dd, aa, bb, X[ 8], 13); - HH(bb, cc, dd, aa, X[ 1], 15); - HH(aa, bb, cc, dd, X[ 2], 14); - HH(dd, aa, bb, cc, X[ 7], 8); - HH(cc, dd, aa, bb, X[ 0], 13); - HH(bb, cc, dd, aa, X[ 6], 6); - HH(aa, bb, cc, dd, X[13], 5); - HH(dd, aa, bb, cc, X[11], 12); - HH(cc, dd, aa, bb, X[ 5], 7); - HH(bb, cc, dd, aa, X[12], 5); - - /* round 4 */ - II(aa, bb, cc, dd, X[ 1], 11); - II(dd, aa, bb, cc, X[ 9], 12); - II(cc, dd, aa, bb, X[11], 14); - II(bb, cc, dd, aa, X[10], 15); - II(aa, bb, cc, dd, X[ 0], 14); - II(dd, aa, bb, cc, X[ 8], 15); - II(cc, dd, aa, bb, X[12], 9); - II(bb, cc, dd, aa, X[ 4], 8); - II(aa, bb, cc, dd, X[13], 9); - II(dd, aa, bb, cc, X[ 3], 14); - II(cc, dd, aa, bb, X[ 7], 5); - II(bb, cc, dd, aa, X[15], 6); - II(aa, bb, cc, dd, X[14], 8); - II(dd, aa, bb, cc, X[ 5], 6); - II(cc, dd, aa, bb, X[ 6], 5); - II(bb, cc, dd, aa, X[ 2], 12); - - /* parallel round 1 */ - III(aaa, bbb, ccc, ddd, X[ 5], 8); - III(ddd, aaa, bbb, ccc, X[14], 9); - III(ccc, ddd, aaa, bbb, X[ 7], 9); - III(bbb, ccc, ddd, aaa, X[ 0], 11); - III(aaa, bbb, ccc, ddd, X[ 9], 13); - III(ddd, aaa, bbb, ccc, X[ 2], 15); - III(ccc, ddd, aaa, bbb, X[11], 15); - III(bbb, ccc, ddd, aaa, X[ 4], 5); - III(aaa, bbb, ccc, ddd, X[13], 7); - III(ddd, aaa, bbb, ccc, X[ 6], 7); - III(ccc, ddd, aaa, bbb, X[15], 8); - III(bbb, ccc, ddd, aaa, X[ 8], 11); - III(aaa, bbb, ccc, ddd, X[ 1], 14); - III(ddd, aaa, bbb, ccc, X[10], 14); - III(ccc, ddd, aaa, bbb, X[ 3], 12); - III(bbb, ccc, ddd, aaa, X[12], 6); - - /* parallel round 2 */ - HHH(aaa, bbb, ccc, ddd, X[ 6], 9); - HHH(ddd, aaa, bbb, ccc, X[11], 13); - HHH(ccc, ddd, aaa, bbb, X[ 3], 15); - HHH(bbb, ccc, ddd, aaa, X[ 7], 7); - HHH(aaa, bbb, ccc, ddd, X[ 0], 12); - HHH(ddd, aaa, bbb, ccc, X[13], 8); - HHH(ccc, ddd, aaa, bbb, X[ 5], 9); - HHH(bbb, ccc, ddd, aaa, X[10], 11); - HHH(aaa, bbb, ccc, ddd, X[14], 7); - HHH(ddd, aaa, bbb, ccc, X[15], 7); - HHH(ccc, ddd, aaa, bbb, X[ 8], 12); - HHH(bbb, ccc, ddd, aaa, X[12], 7); - HHH(aaa, bbb, ccc, ddd, X[ 4], 6); - HHH(ddd, aaa, bbb, ccc, X[ 9], 15); - HHH(ccc, ddd, aaa, bbb, X[ 1], 13); - HHH(bbb, ccc, ddd, aaa, X[ 2], 11); - - /* parallel round 3 */ - GGG(aaa, bbb, ccc, ddd, X[15], 9); - GGG(ddd, aaa, bbb, ccc, X[ 5], 7); - GGG(ccc, ddd, aaa, bbb, X[ 1], 15); - GGG(bbb, ccc, ddd, aaa, X[ 3], 11); - GGG(aaa, bbb, ccc, ddd, X[ 7], 8); - GGG(ddd, aaa, bbb, ccc, X[14], 6); - GGG(ccc, ddd, aaa, bbb, X[ 6], 6); - GGG(bbb, ccc, ddd, aaa, X[ 9], 14); - GGG(aaa, bbb, ccc, ddd, X[11], 12); - GGG(ddd, aaa, bbb, ccc, X[ 8], 13); - GGG(ccc, ddd, aaa, bbb, X[12], 5); - GGG(bbb, ccc, ddd, aaa, X[ 2], 14); - GGG(aaa, bbb, ccc, ddd, X[10], 13); - GGG(ddd, aaa, bbb, ccc, X[ 0], 13); - GGG(ccc, ddd, aaa, bbb, X[ 4], 7); - GGG(bbb, ccc, ddd, aaa, X[13], 5); - - /* parallel round 4 */ - FFF(aaa, bbb, ccc, ddd, X[ 8], 15); - FFF(ddd, aaa, bbb, ccc, X[ 6], 5); - FFF(ccc, ddd, aaa, bbb, X[ 4], 8); - FFF(bbb, ccc, ddd, aaa, X[ 1], 11); - FFF(aaa, bbb, ccc, ddd, X[ 3], 14); - FFF(ddd, aaa, bbb, ccc, X[11], 14); - FFF(ccc, ddd, aaa, bbb, X[15], 6); - FFF(bbb, ccc, ddd, aaa, X[ 0], 14); - FFF(aaa, bbb, ccc, ddd, X[ 5], 6); - FFF(ddd, aaa, bbb, ccc, X[12], 9); - FFF(ccc, ddd, aaa, bbb, X[ 2], 12); - FFF(bbb, ccc, ddd, aaa, X[13], 9); - FFF(aaa, bbb, ccc, ddd, X[ 9], 12); - FFF(ddd, aaa, bbb, ccc, X[ 7], 5); - FFF(ccc, ddd, aaa, bbb, X[10], 15); - FFF(bbb, ccc, ddd, aaa, X[14], 8); - - /* combine results */ - ddd += cc + md->rmd128.state[1]; /* final result for MDbuf[0] */ - md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa; - md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb; - md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc; - md->rmd128.state[0] = ddd; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_rmd128_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_rmd128_compress(md, buf); - burn_stack(sizeof(ulong32) * 24 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int rmd128_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->rmd128.state[0] = 0x67452301UL; - md->rmd128.state[1] = 0xefcdab89UL; - md->rmd128.state[2] = 0x98badcfeUL; - md->rmd128.state[3] = 0x10325476UL; - md->rmd128.curlen = 0; - md->rmd128.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(rmd128_process, s_rmd128_compress, rmd128, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (16 bytes) - @return CRYPT_OK if successful -*/ -int rmd128_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->rmd128.length += md->rmd128.curlen * 8; - - /* append the '1' bit */ - md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->rmd128.curlen > 56) { - while (md->rmd128.curlen < 64) { - md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; - } - s_rmd128_compress(md, md->rmd128.buf); - md->rmd128.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->rmd128.curlen < 56) { - md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->rmd128.length, md->rmd128.buf+56); - s_rmd128_compress(md, md->rmd128.buf); - - /* copy output */ - for (i = 0; i < 4; i++) { - STORE32L(md->rmd128.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int rmd128_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[16]; - } tests[] = { - { "", - { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e, - 0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 } - }, - { "a", - { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7, - 0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 } - }, - { "abc", - { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba, - 0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 } - }, - { "message digest", - { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62, - 0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 } - }, - { "abcdefghijklmnopqrstuvwxyz", - { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5, - 0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e } - }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f, - 0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 } - } - }; - - int i; - unsigned char tmp[16]; - hash_state md; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - rmd128_init(&md); - rmd128_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); - rmd128_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD128", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#undef F -#undef G -#undef H -#undef I -#undef FF -#undef GG -#undef HH -#undef II -#undef FFF -#undef GGG -#undef HHH -#undef III - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/rmd160.c b/Sources/DataLiteC/libtomcrypt/hashes/rmd160.c deleted file mode 100644 index d4cba27..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/rmd160.c +++ /dev/null @@ -1,470 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rmd160.c - RMD160 hash function -*/ - -/* Implementation of LTC_RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC - * - * This source has been radically overhauled to be portable and work within - * the LibTomCrypt API by Tom St Denis - */ - -#ifdef LTC_RIPEMD160 - -const struct ltc_hash_descriptor rmd160_desc = -{ - "rmd160", - 9, - 20, - 64, - - /* OID */ - { 1, 3, 36, 3, 2, 1, }, - 6, - - &rmd160_init, - &rmd160_process, - &rmd160_done, - &rmd160_test, - NULL -}; - -/* the five basic functions F(), G() and H() */ -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ - (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ - (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - - -#ifdef LTC_CLEAN_STACK -static int ss_rmd160_compress(hash_state *md, const unsigned char *buf) -#else -static int s_rmd160_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->rmd160.state[0]; - bb = bbb = md->rmd160.state[1]; - cc = ccc = md->rmd160.state[2]; - dd = ddd = md->rmd160.state[3]; - ee = eee = md->rmd160.state[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - /* combine results */ - ddd += cc + md->rmd160.state[1]; /* final result for md->rmd160.state[0] */ - md->rmd160.state[1] = md->rmd160.state[2] + dd + eee; - md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa; - md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb; - md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc; - md->rmd160.state[0] = ddd; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_rmd160_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_rmd160_compress(md, buf); - burn_stack(sizeof(ulong32) * 26 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int rmd160_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->rmd160.state[0] = 0x67452301UL; - md->rmd160.state[1] = 0xefcdab89UL; - md->rmd160.state[2] = 0x98badcfeUL; - md->rmd160.state[3] = 0x10325476UL; - md->rmd160.state[4] = 0xc3d2e1f0UL; - md->rmd160.curlen = 0; - md->rmd160.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(rmd160_process, s_rmd160_compress, rmd160, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return CRYPT_OK if successful -*/ -int rmd160_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->rmd160.length += md->rmd160.curlen * 8; - - /* append the '1' bit */ - md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->rmd160.curlen > 56) { - while (md->rmd160.curlen < 64) { - md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; - } - s_rmd160_compress(md, md->rmd160.buf); - md->rmd160.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->rmd160.curlen < 56) { - md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->rmd160.length, md->rmd160.buf+56); - s_rmd160_compress(md, md->rmd160.buf); - - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32L(md->rmd160.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int rmd160_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[20]; - } tests[] = { - { "", - { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, - 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 } - }, - { "a", - { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, - 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe } - }, - { "abc", - { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, - 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc } - }, - { "message digest", - { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, - 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 } - }, - { "abcdefghijklmnopqrstuvwxyz", - { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, - 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc } - }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, - 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b } - } - }; - - int i; - unsigned char tmp[20]; - hash_state md; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - rmd160_init(&md); - rmd160_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); - rmd160_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD160", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#undef F -#undef G -#undef H -#undef I -#undef J -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/rmd256.c b/Sources/DataLiteC/libtomcrypt/hashes/rmd256.c deleted file mode 100644 index 4eecd3f..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/rmd256.c +++ /dev/null @@ -1,433 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @param rmd256.c - RLTC_MD256 Hash function -*/ - -#ifdef LTC_RIPEMD256 - -const struct ltc_hash_descriptor rmd256_desc = -{ - "rmd256", - 13, - 32, - 64, - - /* OID */ - { 1, 3, 36, 3, 2, 3 }, - 6, - - &rmd256_init, - &rmd256_process, - &rmd256_done, - &rmd256_test, - NULL -}; - -/* the four basic functions F(), G() and H() */ -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) - -/* the eight basic operations FF() through III() */ -#define FF(a, b, c, d, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)); - -#define GG(a, b, c, d, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = ROLc((a), (s)); - -#define HH(a, b, c, d, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = ROLc((a), (s)); - -#define II(a, b, c, d, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = ROLc((a), (s)); - -#define FFF(a, b, c, d, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)); - -#define GGG(a, b, c, d, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = ROLc((a), (s)); - -#define HHH(a, b, c, d, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = ROLc((a), (s)); - -#define III(a, b, c, d, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = ROLc((a), (s)); - -#ifdef LTC_CLEAN_STACK -static int ss_rmd256_compress(hash_state *md, const unsigned char *buf) -#else -static int s_rmd256_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,tmp,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = md->rmd256.state[0]; - bb = md->rmd256.state[1]; - cc = md->rmd256.state[2]; - dd = md->rmd256.state[3]; - aaa = md->rmd256.state[4]; - bbb = md->rmd256.state[5]; - ccc = md->rmd256.state[6]; - ddd = md->rmd256.state[7]; - - /* round 1 */ - FF(aa, bb, cc, dd, X[ 0], 11); - FF(dd, aa, bb, cc, X[ 1], 14); - FF(cc, dd, aa, bb, X[ 2], 15); - FF(bb, cc, dd, aa, X[ 3], 12); - FF(aa, bb, cc, dd, X[ 4], 5); - FF(dd, aa, bb, cc, X[ 5], 8); - FF(cc, dd, aa, bb, X[ 6], 7); - FF(bb, cc, dd, aa, X[ 7], 9); - FF(aa, bb, cc, dd, X[ 8], 11); - FF(dd, aa, bb, cc, X[ 9], 13); - FF(cc, dd, aa, bb, X[10], 14); - FF(bb, cc, dd, aa, X[11], 15); - FF(aa, bb, cc, dd, X[12], 6); - FF(dd, aa, bb, cc, X[13], 7); - FF(cc, dd, aa, bb, X[14], 9); - FF(bb, cc, dd, aa, X[15], 8); - - /* parallel round 1 */ - III(aaa, bbb, ccc, ddd, X[ 5], 8); - III(ddd, aaa, bbb, ccc, X[14], 9); - III(ccc, ddd, aaa, bbb, X[ 7], 9); - III(bbb, ccc, ddd, aaa, X[ 0], 11); - III(aaa, bbb, ccc, ddd, X[ 9], 13); - III(ddd, aaa, bbb, ccc, X[ 2], 15); - III(ccc, ddd, aaa, bbb, X[11], 15); - III(bbb, ccc, ddd, aaa, X[ 4], 5); - III(aaa, bbb, ccc, ddd, X[13], 7); - III(ddd, aaa, bbb, ccc, X[ 6], 7); - III(ccc, ddd, aaa, bbb, X[15], 8); - III(bbb, ccc, ddd, aaa, X[ 8], 11); - III(aaa, bbb, ccc, ddd, X[ 1], 14); - III(ddd, aaa, bbb, ccc, X[10], 14); - III(ccc, ddd, aaa, bbb, X[ 3], 12); - III(bbb, ccc, ddd, aaa, X[12], 6); - - tmp = aa; aa = aaa; aaa = tmp; - - /* round 2 */ - GG(aa, bb, cc, dd, X[ 7], 7); - GG(dd, aa, bb, cc, X[ 4], 6); - GG(cc, dd, aa, bb, X[13], 8); - GG(bb, cc, dd, aa, X[ 1], 13); - GG(aa, bb, cc, dd, X[10], 11); - GG(dd, aa, bb, cc, X[ 6], 9); - GG(cc, dd, aa, bb, X[15], 7); - GG(bb, cc, dd, aa, X[ 3], 15); - GG(aa, bb, cc, dd, X[12], 7); - GG(dd, aa, bb, cc, X[ 0], 12); - GG(cc, dd, aa, bb, X[ 9], 15); - GG(bb, cc, dd, aa, X[ 5], 9); - GG(aa, bb, cc, dd, X[ 2], 11); - GG(dd, aa, bb, cc, X[14], 7); - GG(cc, dd, aa, bb, X[11], 13); - GG(bb, cc, dd, aa, X[ 8], 12); - - /* parallel round 2 */ - HHH(aaa, bbb, ccc, ddd, X[ 6], 9); - HHH(ddd, aaa, bbb, ccc, X[11], 13); - HHH(ccc, ddd, aaa, bbb, X[ 3], 15); - HHH(bbb, ccc, ddd, aaa, X[ 7], 7); - HHH(aaa, bbb, ccc, ddd, X[ 0], 12); - HHH(ddd, aaa, bbb, ccc, X[13], 8); - HHH(ccc, ddd, aaa, bbb, X[ 5], 9); - HHH(bbb, ccc, ddd, aaa, X[10], 11); - HHH(aaa, bbb, ccc, ddd, X[14], 7); - HHH(ddd, aaa, bbb, ccc, X[15], 7); - HHH(ccc, ddd, aaa, bbb, X[ 8], 12); - HHH(bbb, ccc, ddd, aaa, X[12], 7); - HHH(aaa, bbb, ccc, ddd, X[ 4], 6); - HHH(ddd, aaa, bbb, ccc, X[ 9], 15); - HHH(ccc, ddd, aaa, bbb, X[ 1], 13); - HHH(bbb, ccc, ddd, aaa, X[ 2], 11); - - tmp = bb; bb = bbb; bbb = tmp; - - /* round 3 */ - HH(aa, bb, cc, dd, X[ 3], 11); - HH(dd, aa, bb, cc, X[10], 13); - HH(cc, dd, aa, bb, X[14], 6); - HH(bb, cc, dd, aa, X[ 4], 7); - HH(aa, bb, cc, dd, X[ 9], 14); - HH(dd, aa, bb, cc, X[15], 9); - HH(cc, dd, aa, bb, X[ 8], 13); - HH(bb, cc, dd, aa, X[ 1], 15); - HH(aa, bb, cc, dd, X[ 2], 14); - HH(dd, aa, bb, cc, X[ 7], 8); - HH(cc, dd, aa, bb, X[ 0], 13); - HH(bb, cc, dd, aa, X[ 6], 6); - HH(aa, bb, cc, dd, X[13], 5); - HH(dd, aa, bb, cc, X[11], 12); - HH(cc, dd, aa, bb, X[ 5], 7); - HH(bb, cc, dd, aa, X[12], 5); - - /* parallel round 3 */ - GGG(aaa, bbb, ccc, ddd, X[15], 9); - GGG(ddd, aaa, bbb, ccc, X[ 5], 7); - GGG(ccc, ddd, aaa, bbb, X[ 1], 15); - GGG(bbb, ccc, ddd, aaa, X[ 3], 11); - GGG(aaa, bbb, ccc, ddd, X[ 7], 8); - GGG(ddd, aaa, bbb, ccc, X[14], 6); - GGG(ccc, ddd, aaa, bbb, X[ 6], 6); - GGG(bbb, ccc, ddd, aaa, X[ 9], 14); - GGG(aaa, bbb, ccc, ddd, X[11], 12); - GGG(ddd, aaa, bbb, ccc, X[ 8], 13); - GGG(ccc, ddd, aaa, bbb, X[12], 5); - GGG(bbb, ccc, ddd, aaa, X[ 2], 14); - GGG(aaa, bbb, ccc, ddd, X[10], 13); - GGG(ddd, aaa, bbb, ccc, X[ 0], 13); - GGG(ccc, ddd, aaa, bbb, X[ 4], 7); - GGG(bbb, ccc, ddd, aaa, X[13], 5); - - tmp = cc; cc = ccc; ccc = tmp; - - /* round 4 */ - II(aa, bb, cc, dd, X[ 1], 11); - II(dd, aa, bb, cc, X[ 9], 12); - II(cc, dd, aa, bb, X[11], 14); - II(bb, cc, dd, aa, X[10], 15); - II(aa, bb, cc, dd, X[ 0], 14); - II(dd, aa, bb, cc, X[ 8], 15); - II(cc, dd, aa, bb, X[12], 9); - II(bb, cc, dd, aa, X[ 4], 8); - II(aa, bb, cc, dd, X[13], 9); - II(dd, aa, bb, cc, X[ 3], 14); - II(cc, dd, aa, bb, X[ 7], 5); - II(bb, cc, dd, aa, X[15], 6); - II(aa, bb, cc, dd, X[14], 8); - II(dd, aa, bb, cc, X[ 5], 6); - II(cc, dd, aa, bb, X[ 6], 5); - II(bb, cc, dd, aa, X[ 2], 12); - - /* parallel round 4 */ - FFF(aaa, bbb, ccc, ddd, X[ 8], 15); - FFF(ddd, aaa, bbb, ccc, X[ 6], 5); - FFF(ccc, ddd, aaa, bbb, X[ 4], 8); - FFF(bbb, ccc, ddd, aaa, X[ 1], 11); - FFF(aaa, bbb, ccc, ddd, X[ 3], 14); - FFF(ddd, aaa, bbb, ccc, X[11], 14); - FFF(ccc, ddd, aaa, bbb, X[15], 6); - FFF(bbb, ccc, ddd, aaa, X[ 0], 14); - FFF(aaa, bbb, ccc, ddd, X[ 5], 6); - FFF(ddd, aaa, bbb, ccc, X[12], 9); - FFF(ccc, ddd, aaa, bbb, X[ 2], 12); - FFF(bbb, ccc, ddd, aaa, X[13], 9); - FFF(aaa, bbb, ccc, ddd, X[ 9], 12); - FFF(ddd, aaa, bbb, ccc, X[ 7], 5); - FFF(ccc, ddd, aaa, bbb, X[10], 15); - FFF(bbb, ccc, ddd, aaa, X[14], 8); - - tmp = dd; dd = ddd; ddd = tmp; - - /* combine results */ - md->rmd256.state[0] += aa; - md->rmd256.state[1] += bb; - md->rmd256.state[2] += cc; - md->rmd256.state[3] += dd; - md->rmd256.state[4] += aaa; - md->rmd256.state[5] += bbb; - md->rmd256.state[6] += ccc; - md->rmd256.state[7] += ddd; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_rmd256_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_rmd256_compress(md, buf); - burn_stack(sizeof(ulong32) * 25 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int rmd256_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->rmd256.state[0] = 0x67452301UL; - md->rmd256.state[1] = 0xefcdab89UL; - md->rmd256.state[2] = 0x98badcfeUL; - md->rmd256.state[3] = 0x10325476UL; - md->rmd256.state[4] = 0x76543210UL; - md->rmd256.state[5] = 0xfedcba98UL; - md->rmd256.state[6] = 0x89abcdefUL; - md->rmd256.state[7] = 0x01234567UL; - md->rmd256.curlen = 0; - md->rmd256.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(rmd256_process, s_rmd256_compress, rmd256, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (16 bytes) - @return CRYPT_OK if successful -*/ -int rmd256_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->rmd256.curlen >= sizeof(md->rmd256.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->rmd256.length += md->rmd256.curlen * 8; - - /* append the '1' bit */ - md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->rmd256.curlen > 56) { - while (md->rmd256.curlen < 64) { - md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; - } - s_rmd256_compress(md, md->rmd256.buf); - md->rmd256.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->rmd256.curlen < 56) { - md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->rmd256.length, md->rmd256.buf+56); - s_rmd256_compress(md, md->rmd256.buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE32L(md->rmd256.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int rmd256_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[32]; - } tests[] = { - { "", - { 0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18, - 0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a, - 0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63, - 0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d } - }, - { "a", - { 0xf9, 0x33, 0x3e, 0x45, 0xd8, 0x57, 0xf5, 0xd9, - 0x0a, 0x91, 0xba, 0xb7, 0x0a, 0x1e, 0xba, 0x0c, - 0xfb, 0x1b, 0xe4, 0xb0, 0x78, 0x3c, 0x9a, 0xcf, - 0xcd, 0x88, 0x3a, 0x91, 0x34, 0x69, 0x29, 0x25 } - }, - { "abc", - { 0xaf, 0xbd, 0x6e, 0x22, 0x8b, 0x9d, 0x8c, 0xbb, - 0xce, 0xf5, 0xca, 0x2d, 0x03, 0xe6, 0xdb, 0xa1, - 0x0a, 0xc0, 0xbc, 0x7d, 0xcb, 0xe4, 0x68, 0x0e, - 0x1e, 0x42, 0xd2, 0xe9, 0x75, 0x45, 0x9b, 0x65 } - }, - { "message digest", - { 0x87, 0xe9, 0x71, 0x75, 0x9a, 0x1c, 0xe4, 0x7a, - 0x51, 0x4d, 0x5c, 0x91, 0x4c, 0x39, 0x2c, 0x90, - 0x18, 0xc7, 0xc4, 0x6b, 0xc1, 0x44, 0x65, 0x55, - 0x4a, 0xfc, 0xdf, 0x54, 0xa5, 0x07, 0x0c, 0x0e } - }, - { "abcdefghijklmnopqrstuvwxyz", - { 0x64, 0x9d, 0x30, 0x34, 0x75, 0x1e, 0xa2, 0x16, - 0x77, 0x6b, 0xf9, 0xa1, 0x8a, 0xcc, 0x81, 0xbc, - 0x78, 0x96, 0x11, 0x8a, 0x51, 0x97, 0x96, 0x87, - 0x82, 0xdd, 0x1f, 0xd9, 0x7d, 0x8d, 0x51, 0x33 } - }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - { 0x57, 0x40, 0xa4, 0x08, 0xac, 0x16, 0xb7, 0x20, - 0xb8, 0x44, 0x24, 0xae, 0x93, 0x1c, 0xbb, 0x1f, - 0xe3, 0x63, 0xd1, 0xd0, 0xbf, 0x40, 0x17, 0xf1, - 0xa8, 0x9f, 0x7e, 0xa6, 0xde, 0x77, 0xa0, 0xb8 } - } - }; - - int i; - unsigned char tmp[32]; - hash_state md; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - rmd256_init(&md); - rmd256_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); - rmd256_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD256", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#undef F -#undef G -#undef H -#undef I -#undef FF -#undef GG -#undef HH -#undef II -#undef FFF -#undef GGG -#undef HHH -#undef III - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/rmd320.c b/Sources/DataLiteC/libtomcrypt/hashes/rmd320.c deleted file mode 100644 index 1148b42..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/rmd320.c +++ /dev/null @@ -1,501 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rmd320.c - RMD320 hash function -*/ - -#ifdef LTC_RIPEMD320 - -const struct ltc_hash_descriptor rmd320_desc = -{ - "rmd320", - 14, - 40, - 64, - - /* OID ... does not exist - * http://oid-info.com/get/1.3.36.3.2 */ - { 0 }, - 0, - - &rmd320_init, - &rmd320_process, - &rmd320_done, - &rmd320_test, - NULL -}; - -/* the five basic functions F(), G() and H() */ -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ - (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ - (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ - (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ - (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ - (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = ROLc((a), (s)) + (e);\ - (c) = ROLc((c), 10); - - -#ifdef LTC_CLEAN_STACK -static int ss_rmd320_compress(hash_state *md, const unsigned char *buf) -#else -static int s_rmd320_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = md->rmd320.state[0]; - bb = md->rmd320.state[1]; - cc = md->rmd320.state[2]; - dd = md->rmd320.state[3]; - ee = md->rmd320.state[4]; - aaa = md->rmd320.state[5]; - bbb = md->rmd320.state[6]; - ccc = md->rmd320.state[7]; - ddd = md->rmd320.state[8]; - eee = md->rmd320.state[9]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - tmp = aa; aa = aaa; aaa = tmp; - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - tmp = bb; bb = bbb; bbb = tmp; - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - tmp = cc; cc = ccc; ccc = tmp; - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - tmp = dd; dd = ddd; ddd = tmp; - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - tmp = ee; ee = eee; eee = tmp; - - /* combine results */ - md->rmd320.state[0] += aa; - md->rmd320.state[1] += bb; - md->rmd320.state[2] += cc; - md->rmd320.state[3] += dd; - md->rmd320.state[4] += ee; - md->rmd320.state[5] += aaa; - md->rmd320.state[6] += bbb; - md->rmd320.state[7] += ccc; - md->rmd320.state[8] += ddd; - md->rmd320.state[9] += eee; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_rmd320_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_rmd320_compress(md, buf); - burn_stack(sizeof(ulong32) * 27 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int rmd320_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->rmd320.state[0] = 0x67452301UL; - md->rmd320.state[1] = 0xefcdab89UL; - md->rmd320.state[2] = 0x98badcfeUL; - md->rmd320.state[3] = 0x10325476UL; - md->rmd320.state[4] = 0xc3d2e1f0UL; - md->rmd320.state[5] = 0x76543210UL; - md->rmd320.state[6] = 0xfedcba98UL; - md->rmd320.state[7] = 0x89abcdefUL; - md->rmd320.state[8] = 0x01234567UL; - md->rmd320.state[9] = 0x3c2d1e0fUL; - md->rmd320.curlen = 0; - md->rmd320.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(rmd320_process, s_rmd320_compress, rmd320, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return CRYPT_OK if successful -*/ -int rmd320_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->rmd320.length += md->rmd320.curlen * 8; - - /* append the '1' bit */ - md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->rmd320.curlen > 56) { - while (md->rmd320.curlen < 64) { - md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; - } - s_rmd320_compress(md, md->rmd320.buf); - md->rmd320.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->rmd320.curlen < 56) { - md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->rmd320.length, md->rmd320.buf+56); - s_rmd320_compress(md, md->rmd320.buf); - - /* copy output */ - for (i = 0; i < 10; i++) { - STORE32L(md->rmd320.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int rmd320_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - const char *msg; - unsigned char hash[40]; - } tests[] = { - { "", - { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1, - 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25, - 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e, - 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 } - }, - { "a", - { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5, - 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57, - 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54, - 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d } - }, - { "abc", - { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d, - 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08, - 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74, - 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d } - }, - { "message digest", - { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68, - 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa, - 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d, - 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 } - }, - { "abcdefghijklmnopqrstuvwxyz", - { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93, - 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4, - 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed, - 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 } - }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4, - 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59, - 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b, - 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac } - } - }; - - int i; - unsigned char tmp[40]; - hash_state md; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - rmd320_init(&md); - rmd320_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); - rmd320_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#undef F -#undef G -#undef H -#undef I -#undef J -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha1.c b/Sources/DataLiteC/libtomcrypt/hashes/sha1.c deleted file mode 100644 index a00c7f7..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha1.c +++ /dev/null @@ -1,285 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file sha1.c - LTC_SHA1 code by Tom St Denis -*/ - - -#ifdef LTC_SHA1 - -const struct ltc_hash_descriptor sha1_desc = -{ - "sha1", - 2, - 20, - 64, - - /* OID */ - { 1, 3, 14, 3, 2, 26, }, - 6, - - &sha1_init, - &sha1_process, - &sha1_done, - &sha1_test, - NULL -}; - -#define F0(x,y,z) (z ^ (x & (y ^ z))) -#define F1(x,y,z) (x ^ y ^ z) -#define F2(x,y,z) ((x & y) | (z & (x | y))) -#define F3(x,y,z) (x ^ y ^ z) - -#ifdef LTC_CLEAN_STACK -static int ss_sha1_compress(hash_state *md, const unsigned char *buf) -#else -static int s_sha1_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong32 a,b,c,d,e,W[80],i; -#ifdef LTC_SMALL_CODE - ulong32 t; -#endif - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32H(W[i], buf + (4*i)); - } - - /* copy state */ - a = md->sha1.state[0]; - b = md->sha1.state[1]; - c = md->sha1.state[2]; - d = md->sha1.state[3]; - e = md->sha1.state[4]; - - /* expand it */ - for (i = 16; i < 80; i++) { - W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); - } - - /* compress */ - /* round one */ - #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); - #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); - #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); - #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); - -#ifdef LTC_SMALL_CODE - - for (i = 0; i < 20; ) { - FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 40; ) { - FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 60; ) { - FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 80; ) { - FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; - } - -#else - - for (i = 0; i < 20; ) { - FF0(a,b,c,d,e,i++); - FF0(e,a,b,c,d,i++); - FF0(d,e,a,b,c,i++); - FF0(c,d,e,a,b,i++); - FF0(b,c,d,e,a,i++); - } - - /* round two */ - for (; i < 40; ) { - FF1(a,b,c,d,e,i++); - FF1(e,a,b,c,d,i++); - FF1(d,e,a,b,c,i++); - FF1(c,d,e,a,b,i++); - FF1(b,c,d,e,a,i++); - } - - /* round three */ - for (; i < 60; ) { - FF2(a,b,c,d,e,i++); - FF2(e,a,b,c,d,i++); - FF2(d,e,a,b,c,i++); - FF2(c,d,e,a,b,i++); - FF2(b,c,d,e,a,i++); - } - - /* round four */ - for (; i < 80; ) { - FF3(a,b,c,d,e,i++); - FF3(e,a,b,c,d,i++); - FF3(d,e,a,b,c,i++); - FF3(c,d,e,a,b,i++); - FF3(b,c,d,e,a,i++); - } -#endif - - #undef FF0 - #undef FF1 - #undef FF2 - #undef FF3 - - /* store */ - md->sha1.state[0] = md->sha1.state[0] + a; - md->sha1.state[1] = md->sha1.state[1] + b; - md->sha1.state[2] = md->sha1.state[2] + c; - md->sha1.state[3] = md->sha1.state[3] + d; - md->sha1.state[4] = md->sha1.state[4] + e; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_sha1_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_sha1_compress(md, buf); - burn_stack(sizeof(ulong32) * 87); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha1_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->sha1.state[0] = 0x67452301UL; - md->sha1.state[1] = 0xefcdab89UL; - md->sha1.state[2] = 0x98badcfeUL; - md->sha1.state[3] = 0x10325476UL; - md->sha1.state[4] = 0xc3d2e1f0UL; - md->sha1.curlen = 0; - md->sha1.length = 0; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return CRYPT_OK if successful -*/ -int sha1_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha1.curlen >= sizeof(md->sha1.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->sha1.length += md->sha1.curlen * 8; - - /* append the '1' bit */ - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->sha1.curlen > 56) { - while (md->sha1.curlen < 64) { - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; - } - s_sha1_compress(md, md->sha1.buf); - md->sha1.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->sha1.curlen < 56) { - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->sha1.length, md->sha1.buf+56); - s_sha1_compress(md, md->sha1.buf); - - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32H(md->sha1.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha1_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[20]; - } tests[] = { - { "abc", - { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, - 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, - 0x9c, 0xd0, 0xd8, 0x9d } - }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, - 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, - 0xE5, 0x46, 0x70, 0xF1 } - } - }; - - int i; - unsigned char tmp[20]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha1_init(&md); - sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha1_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#undef F0 -#undef F1 -#undef F2 -#undef F3 -#undef FF0 -#undef FF1 -#undef FF2 -#undef FF3 - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha224.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha224.c deleted file mode 100644 index 1e2f295..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha224.c +++ /dev/null @@ -1,119 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @param sha224.c - LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis) -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_SHA224) && defined(LTC_SHA256) - -const struct ltc_hash_descriptor sha224_desc = -{ - "sha224", - 10, - 28, - 64, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 4, }, - 9, - - &sha224_init, - &sha256_process, - &sha224_done, - &sha224_test, - NULL -}; - -/* init the sha256 er... sha224 state ;-) */ -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha224_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->sha256.curlen = 0; - md->sha256.length = 0; - md->sha256.state[0] = 0xc1059ed8UL; - md->sha256.state[1] = 0x367cd507UL; - md->sha256.state[2] = 0x3070dd17UL; - md->sha256.state[3] = 0xf70e5939UL; - md->sha256.state[4] = 0xffc00b31UL; - md->sha256.state[5] = 0x68581511UL; - md->sha256.state[6] = 0x64f98fa7UL; - md->sha256.state[7] = 0xbefa4fa4UL; - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (28 bytes) - @return CRYPT_OK if successful -*/ -int sha224_done(hash_state * md, unsigned char *out) -{ - unsigned char buf[32]; - int err; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - err = sha256_done(md, buf); - XMEMCPY(out, buf, 28); -#ifdef LTC_CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return err; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha224_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[28]; - } tests[] = { - { "abc", - { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, - 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, - 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, - 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 } - }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, - 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, - 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, - 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 } - }, - }; - - int i; - unsigned char tmp[28]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha224_init(&md); - sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha224_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */ - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha256.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha256.c deleted file mode 100644 index 3a012d8..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha256.c +++ /dev/null @@ -1,331 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file sha256.c - LTC_SHA256 by Tom St Denis -*/ - -#ifdef LTC_SHA256 - -const struct ltc_hash_descriptor sha256_desc = -{ - "sha256", - 0, - 32, - 64, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, - 9, - - &sha256_init, - &sha256_process, - &sha256_done, - &sha256_test, - NULL -}; - -#ifdef LTC_SMALL_CODE -/* the K array */ -static const ulong32 K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; -#endif - -/* Various logical functions */ -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -/* compress 512-bits */ -#ifdef LTC_CLEAN_STACK -static int ss_sha256_compress(hash_state * md, const unsigned char *buf) -#else -static int s_sha256_compress(hash_state * md, const unsigned char *buf) -#endif -{ - ulong32 S[8], W[64], t0, t1; -#ifdef LTC_SMALL_CODE - ulong32 t; -#endif - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->sha256.state[i]; - } - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32H(W[i], buf + (4*i)); - } - - /* fill W[16..63] */ - for (i = 16; i < 64; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - - /* Compress */ -#ifdef LTC_SMALL_CODE -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 64; ++i) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; - } -#else -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); -#endif -#undef RND - - /* feedback */ - for (i = 0; i < 8; i++) { - md->sha256.state[i] = md->sha256.state[i] + S[i]; - } - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_sha256_compress(hash_state * md, const unsigned char *buf) -{ - int err; - err = ss_sha256_compress(md, buf); - burn_stack(sizeof(ulong32) * 74); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha256_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->sha256.curlen = 0; - md->sha256.length = 0; - md->sha256.state[0] = 0x6A09E667UL; - md->sha256.state[1] = 0xBB67AE85UL; - md->sha256.state[2] = 0x3C6EF372UL; - md->sha256.state[3] = 0xA54FF53AUL; - md->sha256.state[4] = 0x510E527FUL; - md->sha256.state[5] = 0x9B05688CUL; - md->sha256.state[6] = 0x1F83D9ABUL; - md->sha256.state[7] = 0x5BE0CD19UL; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (32 bytes) - @return CRYPT_OK if successful -*/ -int sha256_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha256.curlen >= sizeof(md->sha256.buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->sha256.length += md->sha256.curlen * 8; - - /* append the '1' bit */ - md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->sha256.curlen > 56) { - while (md->sha256.curlen < 64) { - md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; - } - s_sha256_compress(md, md->sha256.buf); - md->sha256.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->sha256.curlen < 56) { - md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->sha256.length, md->sha256.buf+56); - s_sha256_compress(md, md->sha256.buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE32H(md->sha256.state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha256_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[32]; - } tests[] = { - { "abc", - { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } - }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, - 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, - 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, - 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } - }, - }; - - int i; - unsigned char tmp[32]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha256_init(&md); - sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha256_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#undef Ch -#undef Maj -#undef S -#undef R -#undef Sigma0 -#undef Sigma1 -#undef Gamma0 -#undef Gamma1 - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha384.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha384.c deleted file mode 100644 index cb3391a..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha384.c +++ /dev/null @@ -1,124 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @param sha384.c - LTC_SHA384 hash included in sha512.c, Tom St Denis -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_SHA384) && defined(LTC_SHA512) - -const struct ltc_hash_descriptor sha384_desc = -{ - "sha384", - 4, - 48, - 128, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 2, }, - 9, - - &sha384_init, - &sha512_process, - &sha384_done, - &sha384_test, - NULL -}; - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha384_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->sha512.curlen = 0; - md->sha512.length = 0; - md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8); - md->sha512.state[1] = CONST64(0x629a292a367cd507); - md->sha512.state[2] = CONST64(0x9159015a3070dd17); - md->sha512.state[3] = CONST64(0x152fecd8f70e5939); - md->sha512.state[4] = CONST64(0x67332667ffc00b31); - md->sha512.state[5] = CONST64(0x8eb44a8768581511); - md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7); - md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4); - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (48 bytes) - @return CRYPT_OK if successful -*/ -int sha384_done(hash_state * md, unsigned char *out) -{ - unsigned char buf[64]; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha512.curlen >= sizeof(md->sha512.buf)) { - return CRYPT_INVALID_ARG; - } - - sha512_done(md, buf); - XMEMCPY(out, buf, 48); -#ifdef LTC_CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha384_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[48]; - } tests[] = { - { "abc", - { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, - 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, - 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, - 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, - 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, - 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } - }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, - 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, - 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, - 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, - 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, - 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } - }, - }; - - int i; - unsigned char tmp[48]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha384_init(&md); - sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha384_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA384", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512.c deleted file mode 100644 index 01f5632..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512.c +++ /dev/null @@ -1,309 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @param sha512.c - LTC_SHA512 by Tom St Denis -*/ - -#ifdef LTC_SHA512 - -const struct ltc_hash_descriptor sha512_desc = -{ - "sha512", - 5, - 64, - 128, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, - 9, - - &sha512_init, - &sha512_process, - &sha512_done, - &sha512_test, - NULL -}; - -/* the K array */ -static const ulong64 K[80] = { -CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), -CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), -CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), -CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), -CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), -CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), -CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), -CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), -CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), -CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), -CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), -CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), -CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), -CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), -CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), -CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), -CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), -CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), -CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), -CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), -CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), -CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), -CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), -CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), -CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), -CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), -CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), -CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), -CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), -CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), -CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), -CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), -CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), -CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), -CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), -CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), -CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), -CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), -CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), -CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) -}; - -/* Various logical functions */ -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR64c(x, n) -#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n)) -#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) -#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) -#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) -#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) - -/* compress 1024-bits */ -#ifdef LTC_CLEAN_STACK -static int ss_sha512_compress(hash_state * md, const unsigned char *buf) -#else -static int s_sha512_compress(hash_state * md, const unsigned char *buf) -#endif -{ - ulong64 S[8], W[80], t0, t1; - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->sha512.state[i]; - } - - /* copy the state into 1024-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD64H(W[i], buf + (8*i)); - } - - /* fill W[16..79] */ - for (i = 16; i < 80; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - - /* Compress */ -#ifdef LTC_SMALL_CODE - for (i = 0; i < 80; i++) { - t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; - t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); - S[7] = S[6]; - S[6] = S[5]; - S[5] = S[4]; - S[4] = S[3] + t0; - S[3] = S[2]; - S[2] = S[1]; - S[1] = S[0]; - S[0] = t0 + t1; - } -#else -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 80; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); - } -#endif - - - /* feedback */ - for (i = 0; i < 8; i++) { - md->sha512.state[i] = md->sha512.state[i] + S[i]; - } - - return CRYPT_OK; -} - -/* compress 1024-bits */ -#ifdef LTC_CLEAN_STACK -static int s_sha512_compress(hash_state * md, const unsigned char *buf) -{ - int err; - err = ss_sha512_compress(md, buf); - burn_stack(sizeof(ulong64) * 90 + sizeof(int)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha512_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - md->sha512.curlen = 0; - md->sha512.length = 0; - md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); - md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); - md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); - md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); - md->sha512.state[4] = CONST64(0x510e527fade682d1); - md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); - md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); - md->sha512.state[7] = CONST64(0x5be0cd19137e2179); - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(sha512_process, s_sha512_compress, sha512, 128) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (64 bytes) - @return CRYPT_OK if successful -*/ -int sha512_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha512.curlen >= sizeof(md->sha512.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->sha512.length += md->sha512.curlen * CONST64(8); - - /* append the '1' bit */ - md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 112 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->sha512.curlen > 112) { - while (md->sha512.curlen < 128) { - md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; - } - s_sha512_compress(md, md->sha512.buf); - md->sha512.curlen = 0; - } - - /* pad upto 120 bytes of zeroes - * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash - * > 2^64 bits of data... :-) - */ - while (md->sha512.curlen < 120) { - md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->sha512.length, md->sha512.buf+120); - s_sha512_compress(md, md->sha512.buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE64H(md->sha512.state[i], out+(8*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha512_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[64]; - } tests[] = { - { "abc", - { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, - 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, - 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, - 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, - 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, - 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, - 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, - 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } - }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, - 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, - 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, - 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, - 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, - 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, - 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, - 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } - }, - }; - - int i; - unsigned char tmp[64]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha512_init(&md); - sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha512_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#undef Ch -#undef Maj -#undef S -#undef R -#undef Sigma0 -#undef Sigma1 -#undef Gamma0 -#undef Gamma1 - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_224.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_224.c deleted file mode 100644 index 861852e..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_224.c +++ /dev/null @@ -1,120 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @param sha512_224.c - SHA512/224 hash included in sha512.c -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_SHA512_224) && defined(LTC_SHA512) - -const struct ltc_hash_descriptor sha512_224_desc = -{ - "sha512-224", - 15, - 28, - 128, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 5, }, - 9, - - &sha512_224_init, - &sha512_process, - &sha512_224_done, - &sha512_224_test, - NULL -}; - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha512_224_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->sha512.curlen = 0; - md->sha512.length = 0; - md->sha512.state[0] = CONST64(0x8C3D37C819544DA2); - md->sha512.state[1] = CONST64(0x73E1996689DCD4D6); - md->sha512.state[2] = CONST64(0x1DFAB7AE32FF9C82); - md->sha512.state[3] = CONST64(0x679DD514582F9FCF); - md->sha512.state[4] = CONST64(0x0F6D2B697BD44DA8); - md->sha512.state[5] = CONST64(0x77E36F7304C48942); - md->sha512.state[6] = CONST64(0x3F9D85A86A1D36C8); - md->sha512.state[7] = CONST64(0x1112E6AD91D692A1); - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (48 bytes) - @return CRYPT_OK if successful -*/ -int sha512_224_done(hash_state * md, unsigned char *out) -{ - unsigned char buf[64]; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha512.curlen >= sizeof(md->sha512.buf)) { - return CRYPT_INVALID_ARG; - } - - sha512_done(md, buf); - XMEMCPY(out, buf, 28); -#ifdef LTC_CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha512_224_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[28]; - } tests[] = { - { "abc", - { 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, - 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, - 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, - 0x3E, 0x89, 0x24, 0xAA } - }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - { 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, - 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, - 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, - 0x68, 0x67, 0x4A, 0xF9 } - }, - }; - - int i; - unsigned char tmp[28]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha512_224_init(&md); - sha512_224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha512_224_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-224", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_256.c b/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_256.c deleted file mode 100644 index 1f04154..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha2/sha512_256.c +++ /dev/null @@ -1,120 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -/** - @param sha512_256.c - SHA512/256 hash included in sha512.c -*/ - -#include "tomcrypt_private.h" - -#if defined(LTC_SHA512_256) && defined(LTC_SHA512) - -const struct ltc_hash_descriptor sha512_256_desc = -{ - "sha512-256", - 16, - 32, - 128, - - /* OID */ - { 2, 16, 840, 1, 101, 3, 4, 2, 6, }, - 9, - - &sha512_256_init, - &sha512_process, - &sha512_256_done, - &sha512_256_test, - NULL -}; - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int sha512_256_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - - md->sha512.curlen = 0; - md->sha512.length = 0; - md->sha512.state[0] = CONST64(0x22312194FC2BF72C); - md->sha512.state[1] = CONST64(0x9F555FA3C84C64C2); - md->sha512.state[2] = CONST64(0x2393B86B6F53B151); - md->sha512.state[3] = CONST64(0x963877195940EABD); - md->sha512.state[4] = CONST64(0x96283EE2A88EFFE3); - md->sha512.state[5] = CONST64(0xBE5E1E2553863992); - md->sha512.state[6] = CONST64(0x2B0199FC2C85B8AA); - md->sha512.state[7] = CONST64(0x0EB72DDC81C52CA2); - return CRYPT_OK; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (48 bytes) - @return CRYPT_OK if successful -*/ -int sha512_256_done(hash_state * md, unsigned char *out) -{ - unsigned char buf[64]; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->sha512.curlen >= sizeof(md->sha512.buf)) { - return CRYPT_INVALID_ARG; - } - - sha512_done(md, buf); - XMEMCPY(out, buf, 32); -#ifdef LTC_CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int sha512_256_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[32]; - } tests[] = { - { "abc", - { 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, - 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, - 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, - 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 } - }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - { 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, - 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, - 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, - 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A } - }, - }; - - int i; - unsigned char tmp[32]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - sha512_256_init(&md); - sha512_256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - sha512_256_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-265", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha3.c b/Sources/DataLiteC/libtomcrypt/hashes/sha3.c deleted file mode 100644 index 154eefe..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha3.c +++ /dev/null @@ -1,384 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* based on https://github.com/brainhub/SHA3IUF (public domain) */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_SHA3 - -const struct ltc_hash_descriptor sha3_224_desc = -{ - "sha3-224", /* name of hash */ - 17, /* internal ID */ - 28, /* Size of digest in octets */ - 144, /* Input block size in octets */ - { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ - 9, /* Length OID */ - &sha3_224_init, - &sha3_process, - &sha3_done, - &sha3_224_test, - NULL -}; - -const struct ltc_hash_descriptor sha3_256_desc = -{ - "sha3-256", /* name of hash */ - 18, /* internal ID */ - 32, /* Size of digest in octets */ - 136, /* Input block size in octets */ - { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ - 9, /* Length OID */ - &sha3_256_init, - &sha3_process, - &sha3_done, - &sha3_256_test, - NULL -}; - -const struct ltc_hash_descriptor sha3_384_desc = -{ - "sha3-384", /* name of hash */ - 19, /* internal ID */ - 48, /* Size of digest in octets */ - 104, /* Input block size in octets */ - { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ - 9, /* Length OID */ - &sha3_384_init, - &sha3_process, - &sha3_done, - &sha3_384_test, - NULL -}; - -const struct ltc_hash_descriptor sha3_512_desc = -{ - "sha3-512", /* name of hash */ - 20, /* internal ID */ - 64, /* Size of digest in octets */ - 72, /* Input block size in octets */ - { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ - 9, /* Length OID */ - &sha3_512_init, - &sha3_process, - &sha3_done, - &sha3_512_test, - NULL -}; -#endif - -#ifdef LTC_KECCAK -const struct ltc_hash_descriptor keccak_224_desc = -{ - "keccak224", /* name of hash */ - 29, /* internal ID */ - 28, /* Size of digest in octets */ - 144, /* Input block size in octets */ - { 0 }, 0, /* no ASN.1 OID */ - &sha3_224_init, - &sha3_process, - &keccak_done, - &keccak_224_test, - NULL -}; - -const struct ltc_hash_descriptor keccak_256_desc = -{ - "keccak256", /* name of hash */ - 30, /* internal ID */ - 32, /* Size of digest in octets */ - 136, /* Input block size in octets */ - { 0 }, 0, /* no ASN.1 OID */ - &sha3_256_init, - &sha3_process, - &keccak_done, - &keccak_256_test, - NULL -}; - -const struct ltc_hash_descriptor keccak_384_desc = -{ - "keccak384", /* name of hash */ - 31, /* internal ID */ - 48, /* Size of digest in octets */ - 104, /* Input block size in octets */ - { 0 }, 0, /* no ASN.1 OID */ - &sha3_384_init, - &sha3_process, - &keccak_done, - &keccak_384_test, - NULL -}; - -const struct ltc_hash_descriptor keccak_512_desc = -{ - "keccak512", /* name of hash */ - 32, /* internal ID */ - 64, /* Size of digest in octets */ - 72, /* Input block size in octets */ - { 0 }, 0, /* no ASN.1 OID */ - &sha3_512_init, - &sha3_process, - &keccak_done, - &keccak_512_test, - NULL -}; -#endif - -#if defined(LTC_SHA3) || defined(LTC_KECCAK) - -#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */ -#define SHA3_KECCAK_ROUNDS 24 - -static const ulong64 s_keccakf_rndc[24] = { - CONST64(0x0000000000000001), CONST64(0x0000000000008082), - CONST64(0x800000000000808a), CONST64(0x8000000080008000), - CONST64(0x000000000000808b), CONST64(0x0000000080000001), - CONST64(0x8000000080008081), CONST64(0x8000000000008009), - CONST64(0x000000000000008a), CONST64(0x0000000000000088), - CONST64(0x0000000080008009), CONST64(0x000000008000000a), - CONST64(0x000000008000808b), CONST64(0x800000000000008b), - CONST64(0x8000000000008089), CONST64(0x8000000000008003), - CONST64(0x8000000000008002), CONST64(0x8000000000000080), - CONST64(0x000000000000800a), CONST64(0x800000008000000a), - CONST64(0x8000000080008081), CONST64(0x8000000000008080), - CONST64(0x0000000080000001), CONST64(0x8000000080008008) -}; - -static const unsigned s_keccakf_rotc[24] = { - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 -}; - -static const unsigned s_keccakf_piln[24] = { - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 -}; - -static void s_keccakf(ulong64 s[25]) -{ - int i, j, round; - ulong64 t, bc[5]; - - for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) { - /* Theta */ - for(i = 0; i < 5; i++) { - bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; - } - for(i = 0; i < 5; i++) { - t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1); - for(j = 0; j < 25; j += 5) { - s[j + i] ^= t; - } - } - /* Rho Pi */ - t = s[1]; - for(i = 0; i < 24; i++) { - j = s_keccakf_piln[i]; - bc[0] = s[j]; - s[j] = ROL64(t, s_keccakf_rotc[i]); - t = bc[0]; - } - /* Chi */ - for(j = 0; j < 25; j += 5) { - for(i = 0; i < 5; i++) { - bc[i] = s[j + i]; - } - for(i = 0; i < 5; i++) { - s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; - } - } - /* Iota */ - s[0] ^= s_keccakf_rndc[round]; - } -} - -static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad) -{ - unsigned i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(hash != NULL); - - md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8))); - md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); - s_keccakf(md->sha3.s); - - /* store sha3.s[] as little-endian bytes into sha3.sb */ - for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { - STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); - } - - XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4); - return CRYPT_OK; -} - -/* Public Inteface */ - -int sha3_224_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - XMEMSET(&md->sha3, 0, sizeof(md->sha3)); - md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); - return CRYPT_OK; -} - -int sha3_256_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - XMEMSET(&md->sha3, 0, sizeof(md->sha3)); - md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); - return CRYPT_OK; -} - -int sha3_384_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - XMEMSET(&md->sha3, 0, sizeof(md->sha3)); - md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); - return CRYPT_OK; -} - -int sha3_512_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - XMEMSET(&md->sha3, 0, sizeof(md->sha3)); - md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); - return CRYPT_OK; -} - -#ifdef LTC_SHA3 -int sha3_shake_init(hash_state *md, int num) -{ - LTC_ARGCHK(md != NULL); - if (num != 128 && num != 256) return CRYPT_INVALID_ARG; - XMEMSET(&md->sha3, 0, sizeof(md->sha3)); - md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); - return CRYPT_OK; -} -#endif - -int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) -{ - /* 0...7 -- how much is needed to have a word */ - unsigned old_tail = (8 - md->sha3.byte_index) & 7; - - unsigned long words; - unsigned tail; - unsigned long i; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(in != NULL); - - if(inlen < old_tail) { /* have no complete word or haven't started the word yet */ - while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); - return CRYPT_OK; - } - - if(old_tail) { /* will have one word to process */ - inlen -= old_tail; - while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); - /* now ready to add saved to the sponge */ - md->sha3.s[md->sha3.word_index] ^= md->sha3.saved; - md->sha3.byte_index = 0; - md->sha3.saved = 0; - if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { - s_keccakf(md->sha3.s); - md->sha3.word_index = 0; - } - } - - /* now work in full words directly from input */ - words = inlen / sizeof(ulong64); - tail = inlen - words * sizeof(ulong64); - - for(i = 0; i < words; i++, in += sizeof(ulong64)) { - ulong64 t; - LOAD64L(t, in); - md->sha3.s[md->sha3.word_index] ^= t; - if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { - s_keccakf(md->sha3.s); - md->sha3.word_index = 0; - } - } - - /* finally, save the partial word */ - while (tail--) { - md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); - } - return CRYPT_OK; -} - -#ifdef LTC_SHA3 -int sha3_done(hash_state *md, unsigned char *out) -{ - return ss_done(md, out, CONST64(0x06)); -} -#endif - -#ifdef LTC_KECCAK -int keccak_done(hash_state *md, unsigned char *out) -{ - return ss_done(md, out, CONST64(0x01)); -} -#endif - -#ifdef LTC_SHA3 -int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) -{ - /* IMPORTANT NOTE: sha3_shake_done can be called many times */ - unsigned long idx; - unsigned i; - - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (!md->sha3.xof_flag) { - /* shake_xof operation must be done only once */ - md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8))); - md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); - s_keccakf(md->sha3.s); - /* store sha3.s[] as little-endian bytes into sha3.sb */ - for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { - STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); - } - md->sha3.byte_index = 0; - md->sha3.xof_flag = 1; - } - - for (idx = 0; idx < outlen; idx++) { - if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) { - s_keccakf(md->sha3.s); - /* store sha3.s[] as little-endian bytes into sha3.sb */ - for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { - STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); - } - md->sha3.byte_index = 0; - } - out[idx] = md->sha3.sb[md->sha3.byte_index++]; - } - return CRYPT_OK; -} - -int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen) -{ - hash_state md; - int err; - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err; - if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err; - if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err; - return CRYPT_OK; -} -#endif - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/hashes/sha3_test.c b/Sources/DataLiteC/libtomcrypt/hashes/sha3_test.c deleted file mode 100644 index 95fcfcb..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/sha3_test.c +++ /dev/null @@ -1,719 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* based on https://github.com/brainhub/SHA3IUF (public domain) */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SHA3 - -int sha3_224_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char buf[200], hash[224 / 8]; - int i; - hash_state c; - const unsigned char c1 = 0xa3; - - const unsigned char sha3_224_empty[224 / 8] = { - 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, - 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, - 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, - 0x5b, 0x5a, 0x6b, 0xc7 - }; - - const unsigned char sha3_224_0xa3_200_times[224 / 8] = { - 0x93, 0x76, 0x81, 0x6a, 0xba, 0x50, 0x3f, 0x72, - 0xf9, 0x6c, 0xe7, 0xeb, 0x65, 0xac, 0x09, 0x5d, - 0xee, 0xe3, 0xbe, 0x4b, 0xf9, 0xbb, 0xc2, 0xa1, - 0xcb, 0x7e, 0x11, 0xe0 - }; - - XMEMSET(buf, c1, sizeof(buf)); - - /* SHA3-224 on an empty buffer */ - sha3_224_init(&c); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_224_empty, sizeof(sha3_224_empty), "SHA3-224", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-224 in two steps. [FIPS 202] */ - sha3_224_init(&c); - sha3_process(&c, buf, sizeof(buf) / 2); - sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-224 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_224_init(&c); - while (i--) { - sha3_process(&c, &c1, 1); - } - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int sha3_256_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char buf[200], hash[256 / 8]; - int i; - hash_state c; - const unsigned char c1 = 0xa3; - - const unsigned char sha3_256_empty[256 / 8] = { - 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, - 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, - 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, - 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a - }; - const unsigned char sha3_256_0xa3_200_times[256 / 8] = { - 0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07, - 0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf, - 0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73, - 0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87 - }; - - XMEMSET(buf, c1, sizeof(buf)); - - /* SHA3-256 on an empty buffer */ - sha3_256_init(&c); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_256_empty, sizeof(sha3_256_empty), "SHA3-256", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-256 as a single buffer. [FIPS 202] */ - sha3_256_init(&c); - sha3_process(&c, buf, sizeof(buf)); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-256 in two steps. [FIPS 202] */ - sha3_256_init(&c); - sha3_process(&c, buf, sizeof(buf) / 2); - sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_256_init(&c); - while (i--) { - sha3_process(&c, &c1, 1); - } - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 3)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output - * matched with sha3sum. */ - sha3_256_init(&c); - sha3_process(&c, (unsigned char*) - "\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a" - "\x93\xd1\x56\x43\xd7\x18\x1d\x2a" - "\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f" - "\x20\xed\x21\xf1\x47\xbe\xf7\x32" - "\xbf\x3a\x60\xef\x40\x67\xc3\x73" - "\x4b\x85\xbc\x8c\xd4\x71\x78\x0f" - "\x10\xdc\x9e\x82\x91\xb5\x83\x39" - "\xa6\x77\xb9\x60\x21\x8f\x71\xe7" - "\x93\xf2\x79\x7a\xea\x34\x94\x06" - "\x51\x28\x29\x06\x5d\x37\xbb\x55" - "\xea\x79\x6f\xa4\xf5\x6f\xd8\x89" - "\x6b\x49\xb2\xcd\x19\xb4\x32\x15" - "\xad\x96\x7c\x71\x2b\x24\xe5\x03" - "\x2d\x06\x52\x32\xe0\x2c\x12\x74" - "\x09\xd2\xed\x41\x46\xb9\xd7\x5d" - "\x76\x3d\x52\xdb\x98\xd9\x49\xd3" - "\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8); - sha3_done(&c, hash); - if(compare_testvector(hash, sizeof(hash), - "\xa1\x9e\xee\x92\xbb\x20\x97\xb6" - "\x4e\x82\x3d\x59\x77\x98\xaa\x18" - "\xbe\x9b\x7c\x73\x6b\x80\x59\xab" - "\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8, "SHA3-256", 4)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int sha3_384_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char buf[200], hash[384 / 8]; - int i; - hash_state c; - const unsigned char c1 = 0xa3; - - const unsigned char sha3_384_0xa3_200_times[384 / 8] = { - 0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9, - 0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b, - 0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e, - 0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd, - 0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98, - 0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f - }; - - XMEMSET(buf, c1, sizeof(buf)); - - /* SHA3-384 as a single buffer. [FIPS 202] */ - sha3_384_init(&c); - sha3_process(&c, buf, sizeof(buf)); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-384 in two steps. [FIPS 202] */ - sha3_384_init(&c); - sha3_process(&c, buf, sizeof(buf) / 2); - sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_384_init(&c); - while (i--) { - sha3_process(&c, &c1, 1); - } - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int sha3_512_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char buf[200], hash[512 / 8]; - int i; - hash_state c; - const unsigned char c1 = 0xa3; - - const unsigned char sha3_512_0xa3_200_times[512 / 8] = { - 0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1, - 0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b, - 0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0, - 0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8, - 0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3, - 0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b, - 0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41, - 0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00 - }; - - XMEMSET(buf, c1, sizeof(buf)); - - /* SHA3-512 as a single buffer. [FIPS 202] */ - sha3_512_init(&c); - sha3_process(&c, buf, sizeof(buf)); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-512 in two steps. [FIPS 202] */ - sha3_512_init(&c); - sha3_process(&c, buf, sizeof(buf) / 2); - sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_512_init(&c); - while (i--) { - sha3_process(&c, &c1, 1); - } - sha3_done(&c, hash); - if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int sha3_shake_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char buf[200], hash[512]; - int i; - hash_state c; - const unsigned char c1 = 0xa3; - unsigned long len; - - const unsigned char shake256_empty[32] = { - 0xab, 0x0b, 0xae, 0x31, 0x63, 0x39, 0x89, 0x43, - 0x04, 0xe3, 0x58, 0x77, 0xb0, 0xc2, 0x8a, 0x9b, - 0x1f, 0xd1, 0x66, 0xc7, 0x96, 0xb9, 0xcc, 0x25, - 0x8a, 0x06, 0x4a, 0x8f, 0x57, 0xe2, 0x7f, 0x2a - }; - const unsigned char shake256_0xa3_200_times[32] = { - 0x6a, 0x1a, 0x9d, 0x78, 0x46, 0x43, 0x6e, 0x4d, - 0xca, 0x57, 0x28, 0xb6, 0xf7, 0x60, 0xee, 0xf0, - 0xca, 0x92, 0xbf, 0x0b, 0xe5, 0x61, 0x5e, 0x96, - 0x95, 0x9d, 0x76, 0x71, 0x97, 0xa0, 0xbe, 0xeb - }; - const unsigned char shake128_empty[32] = { - 0x43, 0xe4, 0x1b, 0x45, 0xa6, 0x53, 0xf2, 0xa5, - 0xc4, 0x49, 0x2c, 0x1a, 0xdd, 0x54, 0x45, 0x12, - 0xdd, 0xa2, 0x52, 0x98, 0x33, 0x46, 0x2b, 0x71, - 0xa4, 0x1a, 0x45, 0xbe, 0x97, 0x29, 0x0b, 0x6f - }; - const unsigned char shake128_0xa3_200_times[32] = { - 0x44, 0xc9, 0xfb, 0x35, 0x9f, 0xd5, 0x6a, 0xc0, - 0xa9, 0xa7, 0x5a, 0x74, 0x3c, 0xff, 0x68, 0x62, - 0xf1, 0x7d, 0x72, 0x59, 0xab, 0x07, 0x52, 0x16, - 0xc0, 0x69, 0x95, 0x11, 0x64, 0x3b, 0x64, 0x39 - }; - - XMEMSET(buf, c1, sizeof(buf)); - - /* SHAKE256 on an empty buffer */ - sha3_shake_init(&c, 256); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake256_empty), shake256_empty, sizeof(shake256_empty), "SHAKE256", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE256 via sha3_shake_memory [FIPS 202] */ - len = 512; - sha3_shake_memory(256, buf, sizeof(buf), hash, &len); - if (compare_testvector(hash + 480, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE256 as a single buffer. [FIPS 202] */ - sha3_shake_init(&c, 256); - sha3_shake_process(&c, buf, sizeof(buf)); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE256 in two steps. [FIPS 202] */ - sha3_shake_init(&c, 256); - sha3_shake_process(&c, buf, sizeof(buf) / 2); - sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 3)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE256 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_shake_init(&c, 256); - while (i--) sha3_shake_process(&c, &c1, 1); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 4)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE128 on an empty buffer */ - sha3_shake_init(&c, 128); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake128_empty), shake128_empty, sizeof(shake128_empty), "SHAKE128", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE128 via sha3_shake_memory [FIPS 202] */ - len = 512; - sha3_shake_memory(128, buf, sizeof(buf), hash, &len); - if (compare_testvector(hash + 480, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 1)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE128 as a single buffer. [FIPS 202] */ - sha3_shake_init(&c, 128); - sha3_shake_process(&c, buf, sizeof(buf)); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 2)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE128 in two steps. [FIPS 202] */ - sha3_shake_init(&c, 128); - sha3_shake_process(&c, buf, sizeof(buf) / 2); - sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 3)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* SHAKE128 byte-by-byte: 200 steps. [FIPS 202] */ - i = 200; - sha3_shake_init(&c, 128); - while (i--) sha3_shake_process(&c, &c1, 1); - for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ - if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 4)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif - -#ifdef LTC_KECCAK - -int keccak_224_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - hash_state c; - unsigned char hash[MAXBLOCKSIZE]; - - keccak_224_init(&c); - keccak_process(&c, (unsigned char*) "\xcc", 1); - keccak_done(&c, hash); - if(compare_testvector(hash, 28, - "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2" - "\x46\x29\x0f\x2d\x60\x86\xe3\x2e" - "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c" - "\x89\x9f\x28\x02", 28, - "KECCAK-224", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_224_init(&c); - keccak_process(&c, (unsigned char*)"\x41\xfb", 2); - keccak_done(&c, hash); - if(compare_testvector(hash, 28, - "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa" - "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10" - "\x6a\x73\x4b\x24\x98\x6d\x5d\x97" - "\x8f\xef\xd6\x2c", 28, - "KECCAK-224", 1) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_224_init(&c); - keccak_process(&c, (unsigned char*) - "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" - "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); - keccak_done(&c, hash); - if(compare_testvector(hash, 28, - "\x56\x79\xcd\x50\x9c\x51\x20\xaf" - "\x54\x79\x5c\xf4\x77\x14\x96\x41" - "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03" - "\x40\x70\x4e\x57", 28, - "KECCAK-224", 2) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_224_init(&c); - keccak_process(&c, (unsigned char*) - "\x43\x3c\x53\x03\x13\x16\x24\xc0" - "\x02\x1d\x86\x8a\x30\x82\x54\x75" - "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" - "\x03\x98\xf4\xca\x44\x23\xb9\x82" - "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" - "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" - "\x92\xcc\x1b\x06\xce\xdf\x32\x24" - "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" - "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" - "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" - "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" - "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" - "\x6d\xcb\xb4\xce", 100); - keccak_done(&c, hash); - if(compare_testvector(hash, 28, - "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2" - "\xda\x72\x95\x77\x42\xa8\xd4\xe4" - "\x8e\x21\x3b\x5f\x89\x34\x60\x4b" - "\xfd\x4d\x2c\x3a", 28, - "KECCAK-224", 3) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int keccak_256_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - hash_state c; - unsigned char hash[MAXBLOCKSIZE]; - - keccak_256_init(&c); - keccak_process(&c, (unsigned char*) "\xcc", 1); - keccak_done(&c, hash); - if(compare_testvector(hash, 32, - "\xee\xad\x6d\xbf\xc7\x34\x0a\x56" - "\xca\xed\xc0\x44\x69\x6a\x16\x88" - "\x70\x54\x9a\x6a\x7f\x6f\x56\x96" - "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32, - "KECCAK-256", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_256_init(&c); - keccak_process(&c, (unsigned char*)"\x41\xfb", 2); - keccak_done(&c, hash); - if(compare_testvector(hash, 32, - "\xa8\xea\xce\xda\x4d\x47\xb3\x28" - "\x1a\x79\x5a\xd9\xe1\xea\x21\x22" - "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1" - "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32, - "KECCAK-256", 1) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_256_init(&c); - keccak_process(&c, (unsigned char*) - "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" - "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); - keccak_done(&c, hash); - if(compare_testvector(hash, 32, - "\x0e\x32\xde\xfa\x20\x71\xf0\xb5" - "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0" - "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0" - "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32, - "KECCAK-256", 2) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_256_init(&c); - keccak_process(&c, (unsigned char*) - "\x43\x3c\x53\x03\x13\x16\x24\xc0" - "\x02\x1d\x86\x8a\x30\x82\x54\x75" - "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" - "\x03\x98\xf4\xca\x44\x23\xb9\x82" - "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" - "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" - "\x92\xcc\x1b\x06\xce\xdf\x32\x24" - "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" - "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" - "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" - "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" - "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" - "\x6d\xcb\xb4\xce", 100); - keccak_done(&c, hash); - if(compare_testvector(hash, 32, - "\xce\x87\xa5\x17\x3b\xff\xd9\x23" - "\x99\x22\x16\x58\xf8\x01\xd4\x5c" - "\x29\x4d\x90\x06\xee\x9f\x3f\x9d" - "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32, - "KECCAK-256", 3) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int keccak_384_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - hash_state c; - unsigned char hash[MAXBLOCKSIZE]; - - keccak_384_init(&c); - keccak_process(&c, (unsigned char*) "\xcc", 1); - keccak_done(&c, hash); - if(compare_testvector(hash, 48, - "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01" - "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a" - "\x1a\x69\xca\xf4\xa7\x96\xae\x40" - "\x56\x80\x16\x1e\x29\x57\x26\x41" - "\xf5\xfa\x1e\x86\x41\xd7\x95\x83" - "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48, - "KECCAK-384", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_384_init(&c); - keccak_process(&c, (unsigned char*)"\x41\xfb", 2); - keccak_done(&c, hash); - if(compare_testvector(hash, 48, - "\x49\x5c\xce\x27\x14\xcd\x72\xc8" - "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5" - "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb" - "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d" - "\xb8\x41\x0e\x75\xee\xfe\xa6\x55" - "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48, - "KECCAK-384", 1) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_384_init(&c); - keccak_process(&c, (unsigned char*) - "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" - "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); - keccak_done(&c, hash); - if(compare_testvector(hash, 48, - "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b" - "\xad\x87\x68\x83\xd2\xd6\xdd\x65" - "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c" - "\xc4\xc1\x86\x40\x5a\x12\xed\x64" - "\xba\x96\x67\x2e\xed\xda\x8c\x5a" - "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48, - "KECCAK-384", 2) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_384_init(&c); - keccak_process(&c, (unsigned char*) - "\x43\x3c\x53\x03\x13\x16\x24\xc0" - "\x02\x1d\x86\x8a\x30\x82\x54\x75" - "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" - "\x03\x98\xf4\xca\x44\x23\xb9\x82" - "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" - "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" - "\x92\xcc\x1b\x06\xce\xdf\x32\x24" - "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" - "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" - "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" - "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" - "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" - "\x6d\xcb\xb4\xce", 100); - keccak_done(&c, hash); - if(compare_testvector(hash, 48, - "\x13\x51\x14\x50\x8d\xd6\x3e\x27" - "\x9e\x70\x9c\x26\xf7\x81\x7c\x04" - "\x82\x76\x6c\xde\x49\x13\x2e\x3e" - "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35" - "\x96\xd1\x84\x10\x0b\x38\x48\x68" - "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48, - "KECCAK-384", 3) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -int keccak_512_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - hash_state c; - unsigned char hash[MAXBLOCKSIZE]; - - keccak_512_init(&c); - keccak_process(&c, (unsigned char*) "\xcc", 1); - keccak_done(&c, hash); - if(compare_testvector(hash, 64, - "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7" - "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde" - "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b" - "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16" - "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c" - "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13" - "\xbc\x3b\x62\x25\xec\xe7\xa8\x10" - "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64, - "KECCAK-512", 0) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_512_init(&c); - keccak_process(&c, (unsigned char*)"\x41\xfb", 2); - keccak_done(&c, hash); - if(compare_testvector(hash, 64, - "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc" - "\xe9\xf9\x7f\x11\x90\xe9\x01\x32" - "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd" - "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3" - "\xf0\xea\xe7\xdc\xb6\x86\x22\xff" - "\x23\x2f\xa3\xce\xce\x0d\x46\x16" - "\xcd\xeb\x39\x31\xf9\x38\x03\x66" - "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64, - "KECCAK-512", 1) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_512_init(&c); - keccak_process(&c, (unsigned char*) - "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" - "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); - keccak_done(&c, hash); - if(compare_testvector(hash, 64, - "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9" - "\xb7\x69\x01\x59\x95\x64\x43\x11" - "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09" - "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c" - "\xfb\x59\x64\x18\xe8\xe4\x23\x42" - "\xd1\x17\xe0\x74\x71\xa8\x91\x43" - "\x14\xba\x7b\x0e\x26\x4d\xad\xf0" - "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64, - "KECCAK-512", 2) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - keccak_512_init(&c); - keccak_process(&c, (unsigned char*) - "\x43\x3c\x53\x03\x13\x16\x24\xc0" - "\x02\x1d\x86\x8a\x30\x82\x54\x75" - "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" - "\x03\x98\xf4\xca\x44\x23\xb9\x82" - "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" - "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" - "\x92\xcc\x1b\x06\xce\xdf\x32\x24" - "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" - "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" - "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" - "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" - "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" - "\x6d\xcb\xb4\xce", 100); - keccak_done(&c, hash); - if(compare_testvector(hash, 64, - "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f" - "\x46\x84\xad\xb4\xb8\x24\xc4\x96" - "\xc6\x48\x2e\x51\x14\x95\x65\xd3" - "\xd1\x72\x26\x82\x88\x84\x30\x6b" - "\x51\xd6\x14\x8a\x72\x62\x2c\x2b" - "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b" - "\xdc\x03\xea\xed\xe4\x53\x67\x6a" - "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64, - "KECCAK-512", 3) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/hashes/tiger.c b/Sources/DataLiteC/libtomcrypt/hashes/tiger.c deleted file mode 100644 index a1b66f7..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/tiger.c +++ /dev/null @@ -1,920 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file tiger.c - Tiger hash function, Tom St Denis -*/ - -#ifdef LTC_TIGER - -const struct ltc_hash_descriptor tiger_desc = -{ - "tiger", - 1, - 24, - 64, - - /* OID */ - { 1, 3, 6, 1, 4, 1, 11591, 12, 2, }, - 9, - - &tiger_init, - &tiger_process, - &tiger_done, - &tiger_test, - NULL -}; - -const struct ltc_hash_descriptor tiger2_desc = -{ - "tiger2", - 33, - 24, - 64, - - /* OID ... does not exist */ - { 0 }, - 0, - - &tiger2_init, - &tiger_process, - &tiger_done, - &tiger2_test, - NULL -}; - -#define t1 (table) -#define t2 (table+256) -#define t3 (table+256*2) -#define t4 (table+256*3) - -static const ulong64 table[4*256] = { - CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */, - CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */, - CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */, - CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */, - CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */, - CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */, - CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */, - CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */, - CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */, - CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */, - CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */, - CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */, - CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */, - CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */, - CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */, - CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */, - CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */, - CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */, - CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */, - CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */, - CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */, - CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */, - CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */, - CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */, - CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */, - CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */, - CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */, - CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */, - CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */, - CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */, - CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */, - CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */, - CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */, - CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */, - CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */, - CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */, - CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */, - CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */, - CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */, - CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */, - CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */, - CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */, - CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */, - CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */, - CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */, - CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */, - CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */, - CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */, - CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */, - CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */, - CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */, - CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */, - CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */, - CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */, - CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */, - CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */, - CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */, - CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */, - CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */, - CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */, - CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */, - CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */, - CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */, - CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */, - CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */, - CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */, - CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */, - CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */, - CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */, - CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */, - CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */, - CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */, - CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */, - CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */, - CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */, - CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */, - CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */, - CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */, - CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */, - CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */, - CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */, - CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */, - CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */, - CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */, - CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */, - CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */, - CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */, - CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */, - CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */, - CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */, - CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */, - CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */, - CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */, - CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */, - CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */, - CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */, - CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */, - CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */, - CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */, - CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */, - CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */, - CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */, - CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */, - CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */, - CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */, - CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */, - CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */, - CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */, - CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */, - CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */, - CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */, - CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */, - CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */, - CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */, - CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */, - CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */, - CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */, - CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */, - CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */, - CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */, - CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */, - CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */, - CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */, - CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */, - CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */, - CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */, - CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */, - CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */, - CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */, - CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */, - CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */, - CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */, - CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */, - CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */, - CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */, - CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */, - CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */, - CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */, - CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */, - CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */, - CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */, - CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */, - CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */, - CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */, - CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */, - CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */, - CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */, - CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */, - CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */, - CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */, - CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */, - CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */, - CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */, - CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */, - CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */, - CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */, - CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */, - CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */, - CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */, - CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */, - CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */, - CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */, - CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */, - CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */, - CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */, - CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */, - CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */, - CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */, - CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */, - CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */, - CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */, - CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */, - CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */, - CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */, - CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */, - CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */, - CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */, - CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */, - CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */, - CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */, - CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */, - CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */, - CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */, - CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */, - CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */, - CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */, - CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */, - CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */, - CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */, - CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */, - CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */, - CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */, - CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */, - CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */, - CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */, - CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */, - CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */, - CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */, - CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */, - CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */, - CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */, - CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */, - CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */, - CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */, - CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */, - CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */, - CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */, - CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */, - CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */, - CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */, - CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */, - CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */, - CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */, - CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */, - CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */, - CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */, - CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */, - CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */, - CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */, - CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */, - CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */, - CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */, - CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */, - CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */, - CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */, - CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */, - CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */, - CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */, - CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */, - CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */, - CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */, - CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */, - CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */, - CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */, - CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */, - CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */, - CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */, - CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */, - CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */, - CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */, - CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */, - CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */, - CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */, - CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */, - CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */, - CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */, - CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */, - CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */, - CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */, - CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */, - CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */, - CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */, - CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */, - CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */, - CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */, - CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */, - CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */, - CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */, - CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */, - CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */, - CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */, - CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */, - CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */, - CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */, - CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */, - CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */, - CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */, - CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */, - CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */, - CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */, - CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */, - CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */, - CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */, - CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */, - CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */, - CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */, - CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */, - CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */, - CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */, - CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */, - CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */, - CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */, - CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */, - CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */, - CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */, - CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */, - CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */, - CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */, - CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */, - CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */, - CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */, - CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */, - CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */, - CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */, - CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */, - CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */, - CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */, - CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */, - CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */, - CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */, - CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */, - CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */, - CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */, - CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */, - CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */, - CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */, - CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */, - CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */, - CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */, - CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */, - CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */, - CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */, - CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */, - CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */, - CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */, - CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */, - CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */, - CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */, - CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */, - CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */, - CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */, - CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */, - CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */, - CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */, - CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */, - CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */, - CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */, - CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */, - CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */, - CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */, - CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */, - CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */, - CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */, - CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */, - CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */, - CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */, - CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */, - CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */, - CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */, - CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */, - CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */, - CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */, - CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */, - CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */, - CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */, - CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */, - CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */, - CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */, - CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */, - CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */, - CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */, - CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */, - CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */, - CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */, - CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */, - CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */, - CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */, - CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */, - CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */, - CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */, - CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */, - CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */, - CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */, - CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */, - CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */, - CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */, - CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */, - CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */, - CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */, - CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */, - CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */, - CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */, - CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */, - CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */, - CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */, - CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */, - CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */, - CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */, - CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */, - CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */, - CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */, - CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */, - CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */, - CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */, - CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */, - CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */, - CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */, - CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */, - CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */, - CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */, - CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */, - CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */, - CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */, - CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */, - CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */, - CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */, - CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */, - CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */, - CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */, - CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */, - CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */, - CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */, - CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */, - CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */, - CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */, - CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */, - CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */, - CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */, - CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */, - CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */, - CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */, - CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */, - CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */, - CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */, - CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */, - CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */, - CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */, - CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */, - CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */, - CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */, - CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */, - CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */, - CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */, - CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */, - CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */, - CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */, - CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */, - CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */, - CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */, - CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */, - CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */, - CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */, - CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */, - CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */, - CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */, - CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */, - CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */, - CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */, - CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */, - CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */, - CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */, - CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */, - CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */, - CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */, - CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */, - CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */, - CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */, - CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */, - CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */, - CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */, - CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */, - CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */, - CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */, - CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */, - CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */, - CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */, - CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */, - CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */, - CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */, - CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */, - CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */, - CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */, - CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */, - CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */, - CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */, - CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */, - CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */, - CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */, - CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */, - CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */, - CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */, - CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */, - CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */, - CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */, - CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */, - CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */, - CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */, - CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */, - CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */, - CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */, - CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */, - CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */, - CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */, - CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */, - CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */, - CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */, - CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */, - CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */, - CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */, - CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */, - CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */, - CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */, - CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */, - CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */, - CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */, - CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */, - CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */, - CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */, - CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */, - CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */, - CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */, - CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */, - CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */, - CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */, - CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */, - CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */, - CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */, - CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */, - CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */, - CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */, - CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */, - CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */}; - -/* one round of the hash function */ -static LTC_INLINE void s_tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul) -{ - ulong64 tmp; - tmp = (*c ^= x); - *a -= t1[LTC_BYTE(tmp, 0)] ^ t2[LTC_BYTE(tmp, 2)] ^ t3[LTC_BYTE(tmp, 4)] ^ t4[LTC_BYTE(tmp, 6)]; - tmp = (*b += t4[LTC_BYTE(tmp, 1)] ^ t3[LTC_BYTE(tmp, 3)] ^ t2[LTC_BYTE(tmp,5)] ^ t1[LTC_BYTE(tmp,7)]); - switch (mul) { - case 5: *b = (tmp << 2) + tmp; break; - case 7: *b = (tmp << 3) - tmp; break; - case 9: *b = (tmp << 3) + tmp; break; - } -} - -/* one complete pass */ -static void s_pass(ulong64 *a, ulong64 *b, ulong64 *c, const ulong64 *x, int mul) -{ - s_tiger_round(a,b,c,x[0],mul); - s_tiger_round(b,c,a,x[1],mul); - s_tiger_round(c,a,b,x[2],mul); - s_tiger_round(a,b,c,x[3],mul); - s_tiger_round(b,c,a,x[4],mul); - s_tiger_round(c,a,b,x[5],mul); - s_tiger_round(a,b,c,x[6],mul); - s_tiger_round(b,c,a,x[7],mul); -} - -/* The key mixing schedule */ -static void s_key_schedule(ulong64 *x) -{ - x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); - x[1] ^= x[0]; - x[2] += x[1]; - x[3] -= x[2] ^ ((~x[1])<<19); - x[4] ^= x[3]; - x[5] += x[4]; - x[6] -= x[5] ^ ((~x[4])>>23); - x[7] ^= x[6]; - x[0] += x[7]; - x[1] -= x[0] ^ ((~x[7])<<19); - x[2] ^= x[1]; - x[3] += x[2]; - x[4] -= x[3] ^ ((~x[2])>>23); - x[5] ^= x[4]; - x[6] += x[5]; - x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF); -} - -#ifdef LTC_CLEAN_STACK -static int ss_tiger_compress(hash_state *md, const unsigned char *buf) -#else -static int s_tiger_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong64 a, b, c, x[8], t; - unsigned long i; - - /* load words */ - for (i = 0; i < 8; i++) { - LOAD64L(x[i],&buf[8*i]); - } - a = md->tiger.state[0]; - b = md->tiger.state[1]; - c = md->tiger.state[2]; - - s_pass(&a,&b,&c,x,5); - s_key_schedule(x); - s_pass(&c,&a,&b,x,7); - s_key_schedule(x); - s_pass(&b,&c,&a,x,9); - for (i = 3; i < md->tiger.passes; ++i) { - s_key_schedule(x); - s_pass(&a,&b,&c,x,9); - t = a; a = c; c = b; b = t; - } - - /* store state */ - md->tiger.state[0] = a ^ md->tiger.state[0]; - md->tiger.state[1] = b - md->tiger.state[1]; - md->tiger.state[2] = c + md->tiger.state[2]; - - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -static int s_tiger_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_tiger_compress(md, buf); - burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long)); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int tiger_init(hash_state *md) -{ - LTC_ARGCHK(md != NULL); - md->tiger.state[0] = CONST64(0x0123456789ABCDEF); - md->tiger.state[1] = CONST64(0xFEDCBA9876543210); - md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187); - md->tiger.curlen = 0; - md->tiger.length = 0; - md->tiger.passes = 3; - md->tiger.pad = 0x01u; - return CRYPT_OK; -} - -/** - Initialize the hash state (extended version) - @param md The hash state you wish to initialize - @param passes The number of passes that should be executed - when the compress function is called. - @return CRYPT_OK if successful -*/ -int tiger_init_ex(hash_state *md, unsigned long passes) -{ - int err; - if ((err = tiger_init(md) != CRYPT_OK)) { - return err; - } - md->tiger.passes = passes; - return CRYPT_OK; -} - -/** - Initialize the hash state (extended version) - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int tiger2_init(hash_state *md) -{ - int err; - if ((err = tiger_init(md) != CRYPT_OK)) { - return err; - } - md->tiger.pad = 0x80u; - return CRYPT_OK; -} - -/** - Initialize the hash state (extended version) - @param md The hash state you wish to initialize - @param passes The number of passes that should be executed - when the compress function is called. - @return CRYPT_OK if successful -*/ -int tiger2_init_ex(hash_state *md, unsigned long passes) -{ - int err; - if ((err = tiger2_init(md) != CRYPT_OK)) { - return err; - } - md->tiger.passes = passes; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(tiger_process, s_tiger_compress, tiger, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (24 bytes) - @return CRYPT_OK if successful -*/ -int tiger_done(hash_state * md, unsigned char *out) -{ - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->tiger.curlen >= sizeof(md->tiger.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->tiger.length += md->tiger.curlen * 8; - - /* append the padding bit */ - md->tiger.buf[md->tiger.curlen++] = md->tiger.pad; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. */ - if (md->tiger.curlen > 56) { - while (md->tiger.curlen < 64) { - md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; - } - s_tiger_compress(md, md->tiger.buf); - md->tiger.curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->tiger.curlen < 56) { - md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md->tiger.length, md->tiger.buf+56); - s_tiger_compress(md, md->tiger.buf); - - /* copy output */ - STORE64L(md->tiger.state[0], &out[0]); - STORE64L(md->tiger.state[1], &out[8]); - STORE64L(md->tiger.state[2], &out[16]); -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -static int s_tiger_test(unsigned int idx) -{ - #ifndef LTC_TEST - LTC_UNUSED_PARAM(idx); - return CRYPT_NOP; - #else - static const struct { - const char *msg; - unsigned char hash[2][24]; - } tests[] = { - { "", - { - { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, - 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, - 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }, - { 0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73, - 0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92, - 0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41 }, - }, - }, - { "abc", - { - { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, - 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, - 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }, - { 0xf6, 0x8d, 0x7b, 0xc5, 0xaf, 0x4b, 0x43, 0xa0, - 0x6e, 0x04, 0x8d, 0x78, 0x29, 0x56, 0x0d, 0x4a, - 0x94, 0x15, 0x65, 0x8b, 0xb0, 0xb1, 0xf3, 0xbf }, - }, - }, - { "Tiger", - { - { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, - 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, - 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }, - { 0xfe, 0x40, 0x79, 0x8b, 0x8e, 0xb9, 0x37, 0xfd, - 0x97, 0x76, 0x08, 0x93, 0x05, 0x48, 0xd6, 0xa8, - 0x94, 0xc2, 0x0b, 0x04, 0xcb, 0xef, 0x7a, 0x42 }, - }, - }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - { - { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, - 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, - 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }, - { 0x15, 0x9b, 0x38, 0x0a, 0xb7, 0x92, 0x94, 0xe0, - 0xda, 0x19, 0xf1, 0x62, 0x82, 0xce, 0x6d, 0xce, - 0x0f, 0x84, 0xd3, 0x4f, 0x72, 0x9d, 0xbe, 0xa3 }, - }, - }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - { - { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, - 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, - 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }, - { 0x01, 0xef, 0x91, 0x0b, 0x9b, 0xb2, 0xcb, 0x4c, - 0x6c, 0x47, 0x49, 0x5c, 0x86, 0xb3, 0x64, 0x1a, - 0xff, 0x14, 0xfb, 0xf7, 0x79, 0x40, 0x9c, 0x0e }, - }, - }, - }; - int (*init[2])(hash_state *hash) = { tiger_init, tiger2_init }; - - int i; - unsigned char tmp[24]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - init[idx](&md); - tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); - tiger_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash[idx], sizeof(tests[i].hash[idx]), !idx ? "TIGER": "TIGER2", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int tiger_test(void) -{ - return s_tiger_test(0); -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int tiger2_test(void) -{ - return s_tiger_test(1); -} - -#undef t1 -#undef t2 -#undef t3 -#undef t4 - -#endif - -/* -Hash of "": - 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A -Hash of "abc": - F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 -Hash of "Tiger": - 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF -Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": - 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 -Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789": - 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 -Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham": - 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 -Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.": - EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 -Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.": - 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC -Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": - 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 -*/ - - - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirl.c b/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirl.c deleted file mode 100644 index 802cdc3..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirl.c +++ /dev/null @@ -1,300 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file whirl.c - LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis -*/ - -#include "tomcrypt_private.h" - -#ifdef LTC_WHIRLPOOL - -const struct ltc_hash_descriptor whirlpool_desc = -{ - "whirlpool", - 11, - 64, - 64, - - /* OID */ - { 1, 0, 10118, 3, 0, 55 }, - 6, - - &whirlpool_init, - &whirlpool_process, - &whirlpool_done, - &whirlpool_test, - NULL -}; - -/* the sboxes */ -#ifndef LTC_WHIRLTAB_C -#define LTC_WHIRLTAB_C -#include "whirltab.c" -#endif - -/* get a_{i,j} */ -#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) - -/* shortcut macro to perform three functions at once */ -#define theta_pi_gamma(a, i) \ - (SB0(GB(a, i-0, 7)) ^ \ - SB1(GB(a, i-1, 6)) ^ \ - SB2(GB(a, i-2, 5)) ^ \ - SB3(GB(a, i-3, 4)) ^ \ - SB4(GB(a, i-4, 3)) ^ \ - SB5(GB(a, i-5, 2)) ^ \ - SB6(GB(a, i-6, 1)) ^ \ - SB7(GB(a, i-7, 0))) - -#ifdef LTC_CLEAN_STACK -static int ss_whirlpool_compress(hash_state *md, const unsigned char *buf) -#else -static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) -#endif -{ - ulong64 K[2][8], T[3][8]; - int x, y; - - /* load the block/state */ - for (x = 0; x < 8; x++) { - K[0][x] = md->whirlpool.state[x]; - - LOAD64H(T[0][x], buf + (8 * x)); - T[2][x] = T[0][x]; - T[0][x] ^= K[0][x]; - } - - /* do rounds 1..10 */ - for (x = 0; x < 10; x += 2) { - /* odd round */ - /* apply main transform to K[0] into K[1] */ - for (y = 0; y < 8; y++) { - K[1][y] = theta_pi_gamma(K[0], y); - } - /* xor the constant */ - K[1][0] ^= cont[x]; - - /* apply main transform to T[0] into T[1] */ - for (y = 0; y < 8; y++) { - T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; - } - - /* even round */ - /* apply main transform to K[1] into K[0] */ - for (y = 0; y < 8; y++) { - K[0][y] = theta_pi_gamma(K[1], y); - } - /* xor the constant */ - K[0][0] ^= cont[x+1]; - - /* apply main transform to T[1] into T[0] */ - for (y = 0; y < 8; y++) { - T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; - } - } - - /* store state */ - for (x = 0; x < 8; x++) { - md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; - } - - return CRYPT_OK; -} - - -#ifdef LTC_CLEAN_STACK -static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) -{ - int err; - err = ss_whirlpool_compress(md, buf); - burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); - return err; -} -#endif - - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int whirlpool_init(hash_state * md) -{ - LTC_ARGCHK(md != NULL); - zeromem(&md->whirlpool, sizeof(md->whirlpool)); - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(whirlpool_process, s_whirlpool_compress, whirlpool, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (64 bytes) - @return CRYPT_OK if successful -*/ -int whirlpool_done(hash_state * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->whirlpool.length += md->whirlpool.curlen * 8; - - /* append the '1' bit */ - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 32 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->whirlpool.curlen > 32) { - while (md->whirlpool.curlen < 64) { - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; - } - s_whirlpool_compress(md, md->whirlpool.buf); - md->whirlpool.curlen = 0; - } - - /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ - while (md->whirlpool.curlen < 56) { - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->whirlpool.length, md->whirlpool.buf+56); - s_whirlpool_compress(md, md->whirlpool.buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE64H(md->whirlpool.state[i], out+(8*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(*md)); -#endif - return CRYPT_OK; -} - -/** - Self-test the hash - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled -*/ -int whirlpool_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int len; - unsigned char msg[128], hash[64]; - } tests[] = { - - /* NULL Message */ -{ - 0, - { 0x00 }, - { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, - 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, - 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, - 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } -}, - - - /* 448-bits of 0 bits */ -{ - - 56, - { 0x00 }, - { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, - 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, - 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, - 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } -}, - - /* 520-bits of 0 bits */ -{ - 65, - { 0x00 }, - { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, - 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, - 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, - 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } -}, - - /* 512-bits, leading set */ -{ - 64, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, - 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, - 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, - 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } -}, - - /* 512-bits, leading set of second byte */ -{ - 64, - { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, - 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, - 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, - 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } -}, - - /* 512-bits, leading set of last byte */ -{ - 64, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, - { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, - 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, - 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, - 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } -}, - -}; - - int i; - unsigned char tmp[64]; - hash_state md; - - for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { - whirlpool_init(&md); - whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); - whirlpool_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - -#undef GB -#undef theta_pi_gamma - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirltab.c b/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirltab.c deleted file mode 100644 index 42ecae4..0000000 --- a/Sources/DataLiteC/libtomcrypt/hashes/whirl/whirltab.c +++ /dev/null @@ -1,586 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file whirltab.c - LTC_WHIRLPOOL tables, Tom St Denis -*/ - -#ifdef LTC_WHIRLTAB_C - -static const ulong64 sbox0[] = { -CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb), -CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d), -CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e), -CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8), -CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a), -CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80), -CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c), -CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5), -CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e), -CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944), -CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a), -CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9), -CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507), -CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78), -CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7), -CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56), -CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71), -CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a), -CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f), -CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6), -CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de), -CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f), -CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc), -CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59), -CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4), -CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032), -CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d), -CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7), -CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f), -CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482), -CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df), -CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8), -CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e), -CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3), -CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea), -CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4), -CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9), -CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e), -CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f), -CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae), -CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7), -CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152), -CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab), -CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816), -CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598), -CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e), -CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee), -CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824), -CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65), -CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819), -CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299), -CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0), -CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c), -CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05), -CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b), -CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88), -CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1), -CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b), -CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c), -CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba), -CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241), -CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6), -CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed), -CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2) -}; - -#ifdef LTC_SMALL_CODE - -#define SB0(x) sbox0[x] -#define SB1(x) ROR64c(sbox0[x], 8) -#define SB2(x) ROR64c(sbox0[x], 16) -#define SB3(x) ROR64c(sbox0[x], 24) -#define SB4(x) ROR64c(sbox0[x], 32) -#define SB5(x) ROR64c(sbox0[x], 40) -#define SB6(x) ROR64c(sbox0[x], 48) -#define SB7(x) ROR64c(sbox0[x], 56) - -#else - -#define SB0(x) sbox0[x] -#define SB1(x) sbox1[x] -#define SB2(x) sbox2[x] -#define SB3(x) sbox3[x] -#define SB4(x) sbox4[x] -#define SB5(x) sbox5[x] -#define SB6(x) sbox6[x] -#define SB7(x) sbox7[x] - - -static const ulong64 sbox1[] = { -CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), -CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), -CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7), -CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4), -CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01), -CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a), -CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99), -CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae), -CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7), -CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9), -CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214), -CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17), -CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5), -CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce), -CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b), -CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad), -CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc), -CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21), -CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e), -CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66), -CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2), -CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf), -CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d), -CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d), -CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d), -CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590), -CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe), -CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41), -CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44), -CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24), -CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5), -CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a), -CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756), -CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736), -CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0), -CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3), -CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9), -CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d), -CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a), -CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809), -CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e), -CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431), -CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2), -CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198), -CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605), -CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2), -CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c), -CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408), -CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a), -CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448), -CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522), -CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb), -CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3), -CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb), -CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06), -CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f), -CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6), -CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8), -CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c), -CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df), -CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12), -CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7), -CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55), -CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411) -}; - -static const ulong64 sbox2[] = { -CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f), -CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e), -CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06), -CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07), -CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c), -CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1), -CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed), -CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216), -CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56), -CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95), -CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022), -CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab), -CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303), -CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6), -CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d), -CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f), -CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3), -CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc), -CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b), -CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff), -CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8), -CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a), -CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492), -CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a), -CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba), -CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75), -CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e), -CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c), -CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa), -CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a), -CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b), -CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9), -CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587), -CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877), -CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d), -CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74), -CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365), -CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7), -CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264), -CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498), -CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863), -CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4), -CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220), -CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61), -CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486), -CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8), -CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066), -CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014), -CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839), -CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4), -CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855), -CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60), -CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c), -CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8), -CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f), -CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137), -CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202), -CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1), -CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43), -CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42), -CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d), -CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e), -CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e), -CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4) -}; - -static const ulong64 sbox3[] = { -CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813), -CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42), -CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb), -CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa), -CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04), -CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5), -CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e), -CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782), -CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b), -CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e), -CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50), -CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c), -CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3), -CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f), -CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c), -CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e), -CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617), -CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84), -CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738), -CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385), -CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af), -CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986), -CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834), -CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9), -CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074), -CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a), -CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2), -CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19), -CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d), -CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290), -CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33), -CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5), -CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45), -CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8), -CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba), -CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b), -CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03), -CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e), -CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52), -CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24), -CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8), -CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4), -CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2), -CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a), -CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14), -CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f), -CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0), -CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420), -CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68), -CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d), -CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188), -CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b), -CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb), -CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6), -CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318), -CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921), -CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2), -CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47), -CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a), -CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b), -CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948), -CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b), -CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449), -CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644) -}; - -static const ulong64 sbox4[] = { -CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8), -CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f), -CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5), -CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552), -CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e), -CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435), -CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2), -CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157), -CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5), -CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda), -CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a), -CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85), -CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4), -CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167), -CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b), -CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8), -CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566), -CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e), -CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07), -CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33), -CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971), -CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9), -CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88), -CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0), -CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80), -CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48), -CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f), -CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae), -CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822), -CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812), -CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec), -CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d), -CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b), -CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b), -CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50), -CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef), -CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea), -CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0), -CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d), -CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a), -CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f), -CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296), -CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959), -CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c), -CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c), -CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961), -CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e), -CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004), -CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d), -CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024), -CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411), -CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb), -CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7), -CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3), -CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03), -CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9), -CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153), -CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c), -CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546), -CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1), -CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409), -CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed), -CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4), -CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286) -}; - -static const ulong64 sbox5[] = { -CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887), -CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21), -CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3), -CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255), -CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02), -CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4), -CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f), -CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741), -CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3), -CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f), -CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28), -CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e), -CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7), -CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781), -CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16), -CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847), -CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685), -CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42), -CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c), -CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc), -CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9), -CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943), -CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a), -CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa), -CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a), -CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d), -CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61), -CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82), -CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288), -CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248), -CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97), -CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4), -CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac), -CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c), -CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d), -CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b), -CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f), -CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027), -CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29), -CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12), -CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c), -CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662), -CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979), -CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d), -CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a), -CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199), -CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78), -CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410), -CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34), -CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490), -CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144), -CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b), -CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb), -CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b), -CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c), -CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e), -CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351), -CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad), -CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605), -CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3), -CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924), -CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93), -CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa), -CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622) -}; - -static const ulong64 sbox6[] = { -CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8), -CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f), -CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5), -CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252), -CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e), -CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535), -CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2), -CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757), -CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5), -CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada), -CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a), -CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585), -CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4), -CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767), -CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b), -CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8), -CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666), -CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e), -CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707), -CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333), -CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171), -CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9), -CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888), -CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0), -CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080), -CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848), -CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f), -CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae), -CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222), -CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212), -CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec), -CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d), -CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b), -CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b), -CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050), -CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef), -CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea), -CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0), -CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d), -CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a), -CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f), -CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696), -CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959), -CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c), -CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c), -CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161), -CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e), -CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404), -CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d), -CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424), -CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111), -CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb), -CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7), -CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3), -CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303), -CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9), -CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353), -CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c), -CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646), -CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1), -CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909), -CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded), -CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4), -CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686) -}; - -static const ulong64 sbox7[] = { -CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8), -CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f), -CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5), -CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852), -CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e), -CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035), -CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2), -CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557), -CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5), -CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da), -CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a), -CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985), -CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4), -CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867), -CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b), -CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8), -CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166), -CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e), -CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07), -CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633), -CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71), -CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9), -CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88), -CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0), -CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480), -CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248), -CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f), -CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae), -CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22), -CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212), -CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec), -CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d), -CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b), -CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b), -CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50), -CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef), -CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea), -CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0), -CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d), -CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a), -CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f), -CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296), -CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59), -CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c), -CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c), -CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61), -CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e), -CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404), -CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d), -CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924), -CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911), -CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb), -CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7), -CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3), -CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03), -CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9), -CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153), -CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c), -CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46), -CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1), -CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109), -CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed), -CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4), -CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286) -}; - -#endif - -static const ulong64 cont[] = { -CONST64(0x1823c6e887b8014f), -CONST64(0x36a6d2f5796f9152), -CONST64(0x60bc9b8ea30c7b35), -CONST64(0x1de0d7c22e4bfe57), -CONST64(0x157737e59ff04ada), -CONST64(0x58c9290ab1a06b85), -CONST64(0xbd5d10f4cb3e0567), -CONST64(0xe427418ba77d95d8), -CONST64(0xfbee7c66dd17479e), -CONST64(0xca2dbf07ad5a8333), -CONST64(0x6302aa71c81949d9), -}; - -#endif /* LTC_WHIRLTAB_C */ diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt.h deleted file mode 100644 index 8fddb43..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt.h +++ /dev/null @@ -1,101 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#ifndef TOMCRYPT_H_ -#define TOMCRYPT_H_ -#include -#include -#include -#include -#include -#include -#include -#include - -/* use configuration data */ -#include "tomcrypt_custom.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* version */ -#define CRYPT 0x0118 -#define SCRYPT "1.18.2-develop" - -/* max size of either a cipher/hash block or symmetric key [largest of the two] */ -#define MAXBLOCKSIZE 144 - -#ifndef TAB_SIZE -/* descriptor table size */ -#define TAB_SIZE 48 -#endif - -/* error codes [will be expanded in future releases] */ -enum { - CRYPT_OK=0, /* Result OK */ - CRYPT_ERROR, /* Generic Error */ - CRYPT_NOP, /* Not a failure but no operation was performed */ - - CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ - CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ - CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ - - CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ - CRYPT_INVALID_PACKET, /* Invalid input packet given */ - - CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ - CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ - - CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ - CRYPT_INVALID_HASH, /* Invalid hash specified */ - CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ - - CRYPT_MEM, /* Out of memory */ - - CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ - CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ - - CRYPT_INVALID_ARG, /* Generic invalid argument */ - CRYPT_FILE_NOTFOUND, /* File Not Found */ - - CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ - - CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ - - CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ - - CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ - - CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ - - CRYPT_INVALID_PRIME_SIZE, /* Invalid size of prime requested */ - CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ - - CRYPT_HASH_OVERFLOW, /* Hash applied to too many bits */ - CRYPT_PW_CTX_MISSING, /* Password context to decrypt key file is missing */ - CRYPT_UNKNOWN_PEM, /* The PEM header was not recognized */ - - /* Here only follows the number of error codes. - * This will never be returned and shall always be at the end of the enum. */ - CRYPT_ERR_NUM -}; - -#include "tomcrypt_cfg.h" -#include "tomcrypt_macros.h" -#include "tomcrypt_cipher.h" -#include "tomcrypt_hash.h" -#include "tomcrypt_mac.h" -#include "tomcrypt_prng.h" -#include "tomcrypt_pk.h" -#include "tomcrypt_math.h" -#include "tomcrypt_misc.h" -#include "tomcrypt_argchk.h" -#include "tomcrypt_pkcs.h" - -#ifdef __cplusplus - } -#endif - -#endif /* TOMCRYPT_H_ */ - diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_argchk.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_argchk.h deleted file mode 100644 index f3884e9..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_argchk.h +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* Defines the LTC_ARGCHK macro used within the library */ -/* ARGTYPE is defined in tomcrypt_cfg.h */ - -/* ARGTYPE is per default defined to 0 */ -#if ARGTYPE == 0 - -#include - -LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d); -#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) -#define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) - -#elif ARGTYPE == 1 - -/* fatal type of error */ -#define LTC_ARGCHK(x) assert((x)) -#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) - -#elif ARGTYPE == 2 - -#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } -#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) - -#elif ARGTYPE == 3 - -#define LTC_ARGCHK(x) LTC_UNUSED_PARAM(x) -#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) - -#elif ARGTYPE == 4 - -#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; -#define LTC_ARGCHKVD(x) if (!(x)) return; - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cfg.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cfg.h deleted file mode 100644 index af828e2..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cfg.h +++ /dev/null @@ -1,354 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* This is the build config file. - * - * With this you can setup what to include/exclude automatically during any build. Just comment - * out the line that #define's the word for the thing you want to remove. phew! - */ - -#ifndef TOMCRYPT_CFG_H -#define TOMCRYPT_CFG_H - -#if defined(_WIN32) || defined(_MSC_VER) - #define LTC_CALL __cdecl -#elif !defined(LTC_CALL) - #define LTC_CALL -#endif - -#ifndef LTC_EXPORT - #define LTC_EXPORT -#endif - -/* certain platforms use macros for these, making the prototypes broken */ -#ifndef LTC_NO_PROTOTYPES - -/* you can change how memory allocation works ... */ -LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); -LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); -LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); -LTC_EXPORT void LTC_CALL XFREE(void *p); - -LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); - - -/* change the clock function too */ -LTC_EXPORT clock_t LTC_CALL XCLOCK(void); - -/* various other functions */ -LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); -LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); -LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); - -LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); - -#endif - -/* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */ -#if defined(__GNUC__) || defined(__xlc__) - #define LTC_INLINE __inline__ -#elif defined(_MSC_VER) || defined(__HP_cc) - #define LTC_INLINE __inline -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define LTC_INLINE inline -#else - #define LTC_INLINE -#endif - -#if defined(__clang__) || defined(__GNUC_MINOR__) -#define LTC_NORETURN __attribute__ ((noreturn)) -#elif defined(_MSC_VER) -#define LTC_NORETURN __declspec(noreturn) -#else -#define LTC_NORETURN -#endif - -/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ -#ifndef ARGTYPE - #define ARGTYPE 0 -#endif - -#undef LTC_ENCRYPT -#define LTC_ENCRYPT 0 -#undef LTC_DECRYPT -#define LTC_DECRYPT 1 - -/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code - * - * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. - * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** - * use the portable [slower] macros. - */ -/* detect x86/i386/ARM 32bit */ -#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_ARM) - #define ENDIAN_LITTLE - #define ENDIAN_32BITWORD - #define LTC_FAST -#endif - -/* detect amd64/x64/arm64 */ -#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64) - #define ENDIAN_LITTLE - #define ENDIAN_64BITWORD - #define LTC_FAST -#endif - -/* detect PPC32 */ -#if defined(LTC_PPC32) - #define ENDIAN_BIG - #define ENDIAN_32BITWORD - #define LTC_FAST -#endif - -/* detects MIPS R5900 processors (PS2) */ -#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) - #define ENDIAN_64BITWORD - #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) - #define ENDIAN_BIG - #else - #define ENDIAN_LITTLE - #endif -#endif - -/* detect AIX */ -#if defined(_AIX) && defined(_BIG_ENDIAN) - #define ENDIAN_BIG - #if defined(__LP64__) || defined(_ARCH_PPC64) - #define ENDIAN_64BITWORD - #else - #define ENDIAN_32BITWORD - #endif -#endif - -/* detect HP-UX */ -#if defined(__hpux) || defined(__hpux__) - #define ENDIAN_BIG - #if defined(__ia64) || defined(__ia64__) || defined(__LP64__) - #define ENDIAN_64BITWORD - #else - #define ENDIAN_32BITWORD - #endif -#endif - -/* detect Apple OS X */ -#if defined(__APPLE__) && defined(__MACH__) - #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__) - #define ENDIAN_LITTLE - #else - #define ENDIAN_BIG - #endif - #if defined(__LP64__) || defined(__x86_64__) - #define ENDIAN_64BITWORD - #else - #define ENDIAN_32BITWORD - #endif -#endif - -/* detect SPARC and SPARC64 */ -#if defined(__sparc__) || defined(__sparc) - #define ENDIAN_BIG - #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) - #define ENDIAN_64BITWORD - #else - #define ENDIAN_32BITWORD - #endif -#endif - -/* detect IBM S390(x) */ -#if defined(__s390x__) || defined(__s390__) - #define ENDIAN_BIG - #if defined(__s390x__) - #define ENDIAN_64BITWORD - #else - #define ENDIAN_32BITWORD - #endif -#endif - -/* detect PPC64 */ -#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) - #define ENDIAN_64BITWORD - #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - #define ENDIAN_BIG - #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define ENDIAN_LITTLE - #endif - #define LTC_FAST -#endif - -/* Detect ILP32, commonly known as x32 on Linux and also possible on AIX */ -#if defined(_ILP32) || defined(__ILP32__) - #define ENDIAN_64BITWORD_ILP32 -#endif - -/* endianness fallback */ -#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) - #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ - defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ - defined(__BIG_ENDIAN__) || \ - defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ - defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ - defined(__m68k__) - #define ENDIAN_BIG - #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ - defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ - defined(__LITTLE_ENDIAN__) || \ - defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ - defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ - defined(_M_ARM) || defined(_M_ARM64) - #define ENDIAN_LITTLE - #else - #error Cannot detect endianness - #endif -#endif - -/* ulong64: 64-bit data type */ -#ifdef _MSC_VER - #define CONST64(n) n ## ui64 - typedef unsigned __int64 ulong64; - typedef __int64 long64; -#else - #define CONST64(n) n ## uLL - typedef unsigned long long ulong64; - typedef long long long64; -#endif - -/* ulong32: "32-bit at least" data type */ -#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ - defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ - defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ - defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ - defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ - defined(__LP64__) || defined(_LP64) || defined(__64BIT__) || defined(_M_ARM64) - typedef unsigned ulong32; - #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) - #define ENDIAN_64BITWORD - #endif -#else - typedef unsigned long ulong32; - #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) - #define ENDIAN_32BITWORD - #endif -#endif - -#if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER) -typedef unsigned long long ltc_mp_digit; -#else -typedef unsigned long ltc_mp_digit; -#endif - -/* No asm is a quick way to disable anything "not portable" */ -#ifdef LTC_NO_ASM - #define ENDIAN_NEUTRAL - #undef ENDIAN_32BITWORD - #undef ENDIAN_64BITWORD - #undef LTC_FAST - #define LTC_NO_BSWAP - #define LTC_NO_ROLC - #define LTC_NO_ROTATE -#endif - -/* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */ -#if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__) - #undef LTC_FAST -#endif - -#ifdef LTC_FAST - #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x)) - #ifdef ENDIAN_64BITWORD - typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE; - #else - typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE; - #endif -#endif - -#if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) - #error You must specify a word size as well as endianess in tomcrypt_cfg.h -#endif - -#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) - #define ENDIAN_NEUTRAL -#endif - -#if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD)) - #error Cannot be 32 and 64 bit words... -#endif - -/* gcc 4.3 and up has a bswap builtin; detect it by gcc version. - * clang also supports the bswap builtin, and although clang pretends - * to be gcc (macro-wise, anyway), clang pretends to be a version - * prior to gcc 4.3, so we can't detect bswap that way. Instead, - * clang has a __has_builtin mechanism that can be used to check - * for builtins: - * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */ -#ifndef __has_builtin - #define __has_builtin(x) 0 -#endif -#if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \ - ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ - (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))) - #define LTC_HAVE_BSWAP_BUILTIN -#endif - -#if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32)) - #define LTC_HAVE_ROTATE_BUILTIN -#endif - -#if __has_builtin(__builtin_clzl) - #define LTC_HAVE_CLZL_BUILTIN -#endif - -#if __has_builtin(__builtin_ctzl) - #define LTC_HAVE_CTZL_BUILTIN -#endif - -#if defined(__GNUC__) - #define LTC_ALIGN(n) __attribute__((aligned(n))) -#else - #define LTC_ALIGN(n) -#endif - -/* Choose Windows Vista as minimum Version if we're compiling with at least VS2019 - * This is done in order to test the bcrypt RNG and can still be overridden by the user. */ -#if defined(_MSC_VER) && _MSC_VER >= 1920 -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0600 -# endif -# ifndef WINVER -# define WINVER 0x0600 -# endif -#endif - -/* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code - * before including `tomcrypt.h` to disable this functionality. - */ -#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK) -# define LTC_NULL_TERMINATED __attribute__((sentinel)) -#else -# define LTC_NULL_TERMINATED -#endif - -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) -# define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s))) -# define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s) -# define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s) -#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) -# define LTC_DEPRECATED(s) __attribute__((deprecated)) -# define LTC_DEPRECATED_PRAGMA(s) -#elif defined(_MSC_VER) && _MSC_VER >= 1500 - /* supported since Visual Studio 2008 */ -# define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s)) -# define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s)) -#else -# define LTC_DEPRECATED(s) -# define LTC_DEPRECATED_PRAGMA(s) -#endif - -#if defined(__GNUC__) || defined(__clang__) -# define LTC_ATTRIBUTE(x) __attribute__(x) -#else -# define LTC_ATTRIBUTE(x) -#endif - -#endif /* TOMCRYPT_CFG_H */ diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cipher.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cipher.h deleted file mode 100644 index 60e6c9a..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_cipher.h +++ /dev/null @@ -1,1187 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* ---- SYMMETRIC KEY STUFF ----- - * - * We put each of the ciphers scheduled keys in their own structs then we put all of - * the key formats in one union. This makes the function prototypes easier to use. - */ -#ifdef LTC_BLOWFISH -struct blowfish_key { - ulong32 S[4][256]; - ulong32 K[18]; -}; -#endif - -#ifdef LTC_RC5 -struct rc5_key { - int rounds; - ulong32 K[50]; -}; -#endif - -#ifdef LTC_RC6 -struct rc6_key { - ulong32 K[44]; -}; -#endif - -#ifdef LTC_SAFERP -struct saferp_key { - unsigned char K[33][16]; - long rounds; -}; -#endif - -#ifdef LTC_RIJNDAEL -struct rijndael_key { - unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; - ulong32 *eK; - ulong32 *dK; - int Nr; -}; -#endif - -#ifdef LTC_KSEED -struct kseed_key { - ulong32 K[32], dK[32]; -}; -#endif - -#ifdef LTC_KASUMI -struct kasumi_key { - ulong32 KLi1[8], KLi2[8], - KOi1[8], KOi2[8], KOi3[8], - KIi1[8], KIi2[8], KIi3[8]; -}; -#endif - -#ifdef LTC_XTEA -struct xtea_key { - unsigned long A[32], B[32]; -}; -#endif - -#ifdef LTC_TWOFISH -#ifndef LTC_TWOFISH_SMALL - struct twofish_key { - ulong32 S[4][256], K[40]; - }; -#else - struct twofish_key { - ulong32 K[40]; - unsigned char S[32], start; - }; -#endif -#endif - -#ifdef LTC_SAFER -#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6 -#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10 -#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8 -#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10 -#define LTC_SAFER_MAX_NOF_ROUNDS 13 -#define LTC_SAFER_BLOCK_LEN 8 -#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS)) -typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN]; -typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN]; -struct safer_key { safer_key_t key; }; -#endif - -#ifdef LTC_RC2 -struct rc2_key { unsigned xkey[64]; }; -#endif - -#ifdef LTC_DES -struct des_key { - ulong32 ek[32], dk[32]; -}; - -struct desx_key { - ulong32 ek[32], dk[32]; - ulong32 k[2][2]; -}; - -struct des3_key { - ulong32 ek[3][32], dk[3][32]; -}; -#endif - -#ifdef LTC_SM4 -struct sm4_key { - ulong32 ek[32], dk[32]; -}; -#endif - -#ifdef LTC_CAST5 -struct cast5_key { - ulong32 K[32], keylen; -}; -#endif - -#ifdef LTC_NOEKEON -struct noekeon_key { - ulong32 K[4], dK[4]; -}; -#endif - -#ifdef LTC_SKIPJACK -struct skipjack_key { - unsigned char key[10]; -}; -#endif - -#ifdef LTC_KHAZAD -struct khazad_key { - ulong64 roundKeyEnc[8 + 1]; - ulong64 roundKeyDec[8 + 1]; -}; -#endif - -#ifdef LTC_ANUBIS -struct anubis_key { - ulong32 roundKeyEnc[18 + 1][4]; - ulong32 roundKeyDec[18 + 1][4]; - int keyBits; - int R; -}; -#endif - -#ifdef LTC_MULTI2 -struct multi2_key { - ulong32 uk[8]; - int N; -}; -#endif - -#ifdef LTC_CAMELLIA -struct camellia_key { - ulong64 kw[4], k[24], kl[6]; - int R; -}; -#endif - -#ifdef LTC_IDEA -/* rounds */ -#define LTC_IDEA_ROUNDS 8 -/* key schedule length in # of unsigned shorts */ -#define LTC_IDEA_KEYLEN 6*LTC_IDEA_ROUNDS+4 -struct idea_key { - unsigned short int ek[LTC_IDEA_KEYLEN]; /* enc key */ - unsigned short int dk[LTC_IDEA_KEYLEN]; /* dec key */ -}; -#endif - -#ifdef LTC_SERPENT -struct serpent_key { - ulong32 k[33*4]; -}; -#endif - -#ifdef LTC_TEA -struct tea_key { - ulong32 k[4]; -}; -#endif - -typedef union Symmetric_key { -#ifdef LTC_DES - struct des_key des; - struct desx_key desx; - struct des3_key des3; -#endif -#ifdef LTC_SM4 - struct sm4_key sm4; -#endif -#ifdef LTC_RC2 - struct rc2_key rc2; -#endif -#ifdef LTC_SAFER - struct safer_key safer; -#endif -#ifdef LTC_TWOFISH - struct twofish_key twofish; -#endif -#ifdef LTC_BLOWFISH - struct blowfish_key blowfish; -#endif -#ifdef LTC_RC5 - struct rc5_key rc5; -#endif -#ifdef LTC_RC6 - struct rc6_key rc6; -#endif -#ifdef LTC_SAFERP - struct saferp_key saferp; -#endif -#ifdef LTC_RIJNDAEL - struct rijndael_key rijndael; -#endif -#ifdef LTC_XTEA - struct xtea_key xtea; -#endif -#ifdef LTC_CAST5 - struct cast5_key cast5; -#endif -#ifdef LTC_NOEKEON - struct noekeon_key noekeon; -#endif -#ifdef LTC_SKIPJACK - struct skipjack_key skipjack; -#endif -#ifdef LTC_KHAZAD - struct khazad_key khazad; -#endif -#ifdef LTC_ANUBIS - struct anubis_key anubis; -#endif -#ifdef LTC_KSEED - struct kseed_key kseed; -#endif -#ifdef LTC_KASUMI - struct kasumi_key kasumi; -#endif -#ifdef LTC_MULTI2 - struct multi2_key multi2; -#endif -#ifdef LTC_CAMELLIA - struct camellia_key camellia; -#endif -#ifdef LTC_IDEA - struct idea_key idea; -#endif -#ifdef LTC_SERPENT - struct serpent_key serpent; -#endif -#ifdef LTC_TEA - struct tea_key tea; -#endif - void *data; -} symmetric_key; - -#ifdef LTC_ECB_MODE -/** A block cipher ECB structure */ -typedef struct { - /** The scheduled key */ - symmetric_key key; - /** The index of the cipher chosen */ - int cipher, - /** The block size of the given cipher */ - blocklen; -} symmetric_ECB; -#endif - -#ifdef LTC_CFB_MODE -/** A block cipher CFB structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE], - /** The pad used to encrypt/decrypt */ - pad[MAXBLOCKSIZE]; - /** The width of the mode: 1, 8, 64, or 128 */ - int width, - /** The padding offset */ - padlen; -} symmetric_CFB; -#endif - -#ifdef LTC_OFB_MODE -/** A block cipher OFB structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE]; - /** The padding offset */ - int padlen; - -} symmetric_OFB; -#endif - -#ifdef LTC_CBC_MODE -/** A block cipher CBC structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE]; -} symmetric_CBC; -#endif - - -#ifdef LTC_CTR_MODE -/** A block cipher CTR structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The counter */ - unsigned char ctr[MAXBLOCKSIZE]; - /** The pad used to encrypt/decrypt */ - unsigned char pad[MAXBLOCKSIZE]; - - /** The padding offset */ - int padlen, - /** The mode (endianess) of the CTR, 0==little, 1==big */ - mode, - /** counter width */ - ctrlen; -} symmetric_CTR; -#endif - - -#ifdef LTC_LRW_MODE -/** A LRW structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The current IV */ - unsigned char IV[16], - /** the tweak key */ - tweak[16], - /** The current pad, it's the product of the first 15 bytes against the tweak key */ - pad[16]; -#ifdef LTC_LRW_TABLES - /** The pre-computed multiplication table */ - unsigned char PC[16][256][16]; -#endif - - /** The index of the cipher chosen (must be a 128-bit block cipher) */ - int cipher; -} symmetric_LRW; -#endif - -#ifdef LTC_F8_MODE -/** A block cipher F8 structure */ -typedef struct { - /** The ECB context of the cipher */ - symmetric_ECB ecb; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE], - MIV[MAXBLOCKSIZE]; - /** The padding offset */ - int padlen; - /** Current block count */ - ulong32 blockcnt; -} symmetric_F8; -#endif - - -/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ -extern struct ltc_cipher_descriptor { - /** name of cipher */ - const char *name; - /** internal ID */ - unsigned char ID; - /** min keysize (octets) */ - int min_key_length, - /** max keysize (octets) */ - max_key_length, - /** block size (octets) */ - block_length, - /** default number of rounds */ - default_rounds; - /** Setup the cipher - @param key The input symmetric key - @param keylen The length of the input key (octets) - @param num_rounds The requested number of rounds (0==default) - @param skey [out] The destination of the scheduled key - @return CRYPT_OK if successful - */ - int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); - /** Encrypt a block - @param pt The plaintext - @param ct [out] The ciphertext - @param skey The scheduled key - @return CRYPT_OK if successful - */ - int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); - /** Decrypt a block - @param ct The ciphertext - @param pt [out] The plaintext - @param skey The scheduled key - @return CRYPT_OK if successful - */ - int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); - /** Test the block cipher - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled - */ - int (*test)(void); - - /** Terminate the context - @param skey The scheduled key - */ - void (*done)(symmetric_key *skey); - - /** Determine a key size - @param keysize [in/out] The size of the key desired and the suggested size - @return CRYPT_OK if successful - */ - int (*keysize)(int *keysize); - -/** Accelerators **/ - /** Accelerated ECB encryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, const symmetric_key *skey); - - /** Accelerated ECB decryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, const symmetric_key *skey); - - /** Accelerated CBC encryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param IV The initial value (input/output) - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const symmetric_key *skey); - - /** Accelerated CBC decryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param IV The initial value (input/output) - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const symmetric_key *skey); - - /** Accelerated CTR encryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param IV The initial value (input/output) - @param mode little or big endian counter (mode=0 or mode=1) - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, const symmetric_key *skey); - - /** Accelerated LRW - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param IV The initial value (input/output) - @param tweak The LRW tweak - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, const symmetric_key *skey); - - /** Accelerated LRW - @param ct Ciphertext - @param pt Plaintext - @param blocks The number of complete blocks to process - @param IV The initial value (input/output) - @param tweak The LRW tweak - @param skey The scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, const symmetric_key *skey); - - /** Accelerated CCM packet (one-shot) - @param key The secret key to use - @param keylen The length of the secret key (octets) - @param uskey A previously scheduled key [optional can be NULL] - @param nonce The session nonce [use once] - @param noncelen The length of the nonce - @param header The header for the session - @param headerlen The length of the header (octets) - @param pt [out] The plaintext - @param ptlen The length of the plaintext (octets) - @param ct [out] The ciphertext - @param tag [out] The destination tag - @param taglen [in/out] The max size and resulting size of the authentication tag - @param direction Encrypt or Decrypt direction (0 or 1) - @return CRYPT_OK if successful - */ - int (*accel_ccm_memory)( - const unsigned char *key, unsigned long keylen, - const symmetric_key *uskey, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction); - - /** Accelerated GCM packet (one shot) - @param key The secret key - @param keylen The length of the secret key - @param IV The initialization vector - @param IVlen The length of the initialization vector - @param adata The additional authentication data (header) - @param adatalen The length of the adata - @param pt The plaintext - @param ptlen The length of the plaintext (ciphertext length is the same) - @param ct The ciphertext - @param tag [out] The MAC tag - @param taglen [in/out] The MAC tag length - @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) - @return CRYPT_OK on success - */ - int (*accel_gcm_memory)( - const unsigned char *key, unsigned long keylen, - const unsigned char *IV, unsigned long IVlen, - const unsigned char *adata, unsigned long adatalen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction); - - /** Accelerated one shot LTC_OMAC - @param key The secret key - @param keylen The key length (octets) - @param in The message - @param inlen Length of message (octets) - @param out [out] Destination for tag - @param outlen [in/out] Initial and final size of out - @return CRYPT_OK on success - */ - int (*omac_memory)( - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - - /** Accelerated one shot XCBC - @param key The secret key - @param keylen The key length (octets) - @param in The message - @param inlen Length of message (octets) - @param out [out] Destination for tag - @param outlen [in/out] Initial and final size of out - @return CRYPT_OK on success - */ - int (*xcbc_memory)( - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - - /** Accelerated one shot F9 - @param key The secret key - @param keylen The key length (octets) - @param in The message - @param inlen Length of message (octets) - @param out [out] Destination for tag - @param outlen [in/out] Initial and final size of out - @return CRYPT_OK on success - @remark Requires manual padding - */ - int (*f9_memory)( - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - - /** Accelerated XTS encryption - @param pt Plaintext - @param ct Ciphertext - @param blocks The number of complete blocks to process - @param tweak The 128-bit encryption tweak (input/output). - The tweak should not be encrypted on input, but - next tweak will be copied encrypted on output. - @param skey1 The first scheduled key context - @param skey2 The second scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct, - unsigned long blocks, unsigned char *tweak, - const symmetric_key *skey1, const symmetric_key *skey2); - - /** Accelerated XTS decryption - @param ct Ciphertext - @param pt Plaintext - @param blocks The number of complete blocks to process - @param tweak The 128-bit encryption tweak (input/output). - The tweak should not be encrypted on input, but - next tweak will be copied encrypted on output. - @param skey1 The first scheduled key context - @param skey2 The second scheduled key context - @return CRYPT_OK if successful - */ - int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt, - unsigned long blocks, unsigned char *tweak, - const symmetric_key *skey1, const symmetric_key *skey2); -} cipher_descriptor[]; - -#ifdef LTC_BLOWFISH -int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int blowfish_test(void); -void blowfish_done(symmetric_key *skey); -int blowfish_keysize(int *keysize); -extern const struct ltc_cipher_descriptor blowfish_desc; -#endif - -#ifdef LTC_RC5 -int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int rc5_test(void); -void rc5_done(symmetric_key *skey); -int rc5_keysize(int *keysize); -extern const struct ltc_cipher_descriptor rc5_desc; -#endif - -#ifdef LTC_RC6 -int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int rc6_test(void); -void rc6_done(symmetric_key *skey); -int rc6_keysize(int *keysize); -extern const struct ltc_cipher_descriptor rc6_desc; -#endif - -#ifdef LTC_RC2 -int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey); -int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int rc2_test(void); -void rc2_done(symmetric_key *skey); -int rc2_keysize(int *keysize); -extern const struct ltc_cipher_descriptor rc2_desc; -#endif - -#ifdef LTC_SAFERP -int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int saferp_test(void); -void saferp_done(symmetric_key *skey); -int saferp_keysize(int *keysize); -extern const struct ltc_cipher_descriptor saferp_desc; -#endif - -#ifdef LTC_SAFER -int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int safer_k64_test(void); -int safer_sk64_test(void); -int safer_sk128_test(void); -void safer_done(symmetric_key *skey); -int safer_64_keysize(int *keysize); -int safer_128_keysize(int *keysize); -extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; -#endif - -#ifdef LTC_RIJNDAEL -/* declare aes properly now */ -int aes_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int aes_test(void); -void aes_done(symmetric_key *skey); -int aes_keysize(int *keysize); -int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int aes_enc_test(void); -void aes_enc_done(symmetric_key *skey); -int aes_enc_keysize(int *keysize); -extern const struct ltc_cipher_descriptor aes_desc; -extern const struct ltc_cipher_descriptor aes_enc_desc; - -int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int rijndael_test(void); -void rijndael_done(symmetric_key *skey); -int rijndael_keysize(int *keysize); -int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -void rijndael_enc_done(symmetric_key *skey); -int rijndael_enc_keysize(int *keysize); -extern const struct ltc_cipher_descriptor rijndael_desc; -extern const struct ltc_cipher_descriptor rijndael_enc_desc; -#endif - -#if defined(LTC_AES_NI) -int aesni_is_supported(void); -int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int aesni_test(void); -void aesni_done(symmetric_key *skey); -int aesni_keysize(int *keysize); -extern const struct ltc_cipher_descriptor aesni_desc; -#endif - -#ifdef LTC_XTEA -int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int xtea_test(void); -void xtea_done(symmetric_key *skey); -int xtea_keysize(int *keysize); -extern const struct ltc_cipher_descriptor xtea_desc; -#endif - -#ifdef LTC_TWOFISH -int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int twofish_test(void); -void twofish_done(symmetric_key *skey); -int twofish_keysize(int *keysize); -extern const struct ltc_cipher_descriptor twofish_desc; -#endif - -#ifdef LTC_DES -int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int des_test(void); -void des_done(symmetric_key *skey); -int des_keysize(int *keysize); -int desx_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int desx_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int desx_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int desx_test(void); -void desx_done(symmetric_key *skey); -int desx_keysize(int *keysize); -int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int des3_test(void); -void des3_done(symmetric_key *skey); -int des3_keysize(int *keysize); -extern const struct ltc_cipher_descriptor des_desc, desx_desc, des3_desc; -#endif - -#ifdef LTC_SM4 -int sm4_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int sm4_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int sm4_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int sm4_test(void); -void sm4_done(symmetric_key *skey); -int sm4_keysize(int *keysize); -extern const struct ltc_cipher_descriptor sm4_desc; -#endif - -#ifdef LTC_CAST5 -int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int cast5_test(void); -void cast5_done(symmetric_key *skey); -int cast5_keysize(int *keysize); -extern const struct ltc_cipher_descriptor cast5_desc; -#endif - -#ifdef LTC_NOEKEON -int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int noekeon_test(void); -void noekeon_done(symmetric_key *skey); -int noekeon_keysize(int *keysize); -extern const struct ltc_cipher_descriptor noekeon_desc; -#endif - -#ifdef LTC_SKIPJACK -int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int skipjack_test(void); -void skipjack_done(symmetric_key *skey); -int skipjack_keysize(int *keysize); -extern const struct ltc_cipher_descriptor skipjack_desc; -#endif - -#ifdef LTC_KHAZAD -int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int khazad_test(void); -void khazad_done(symmetric_key *skey); -int khazad_keysize(int *keysize); -extern const struct ltc_cipher_descriptor khazad_desc; -#endif - -#ifdef LTC_ANUBIS -int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int anubis_test(void); -void anubis_done(symmetric_key *skey); -int anubis_keysize(int *keysize); -extern const struct ltc_cipher_descriptor anubis_desc; -#endif - -#ifdef LTC_KSEED -int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int kseed_test(void); -void kseed_done(symmetric_key *skey); -int kseed_keysize(int *keysize); -extern const struct ltc_cipher_descriptor kseed_desc; -#endif - -#ifdef LTC_KASUMI -int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int kasumi_test(void); -void kasumi_done(symmetric_key *skey); -int kasumi_keysize(int *keysize); -extern const struct ltc_cipher_descriptor kasumi_desc; -#endif - - -#ifdef LTC_MULTI2 -int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int multi2_test(void); -void multi2_done(symmetric_key *skey); -int multi2_keysize(int *keysize); -extern const struct ltc_cipher_descriptor multi2_desc; -#endif - -#ifdef LTC_CAMELLIA -int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int camellia_test(void); -void camellia_done(symmetric_key *skey); -int camellia_keysize(int *keysize); -extern const struct ltc_cipher_descriptor camellia_desc; -#endif - -#ifdef LTC_IDEA -int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int idea_test(void); -void idea_done(symmetric_key *skey); -int idea_keysize(int *keysize); -extern const struct ltc_cipher_descriptor idea_desc; -#endif - -#ifdef LTC_SERPENT -int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int serpent_test(void); -void serpent_done(symmetric_key *skey); -int serpent_keysize(int *keysize); -extern const struct ltc_cipher_descriptor serpent_desc; -#endif - -#ifdef LTC_TEA -int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); -int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); -int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); -int tea_test(void); -void tea_done(symmetric_key *skey); -int tea_keysize(int *keysize); -extern const struct ltc_cipher_descriptor tea_desc; -#endif - -#ifdef LTC_ECB_MODE -int ecb_start(int cipher, const unsigned char *key, - int keylen, int num_rounds, symmetric_ECB *ecb); -int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, const symmetric_ECB *ecb); -int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, const symmetric_ECB *ecb); -int ecb_done(symmetric_ECB *ecb); -#endif - -#ifdef LTC_CFB_MODE -int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CFB *cfb); -int cfb_start_ex(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, int width, symmetric_CFB *cfb); -int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); -int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); -int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb); -int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); -int cfb_done(symmetric_CFB *cfb); -#endif - -#ifdef LTC_OFB_MODE -int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_OFB *ofb); -int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); -int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); -int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb); -int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); -int ofb_done(symmetric_OFB *ofb); -#endif - -#ifdef LTC_CBC_MODE -int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CBC *cbc); -int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); -int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); -int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc); -int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); -int cbc_done(symmetric_CBC *cbc); -#endif - -#ifdef LTC_CTR_MODE - -#define CTR_COUNTER_LITTLE_ENDIAN 0x0000 -#define CTR_COUNTER_BIG_ENDIAN 0x1000 -#define LTC_CTR_RFC3686 0x2000 - -int ctr_start( int cipher, - const unsigned char *IV, - const unsigned char *key, int keylen, - int num_rounds, int ctr_mode, - symmetric_CTR *ctr); -int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); -int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); -int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr); -int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); -int ctr_done(symmetric_CTR *ctr); -int ctr_test(void); -#endif - -#ifdef LTC_LRW_MODE - -#define LRW_ENCRYPT LTC_ENCRYPT -#define LRW_DECRYPT LTC_DECRYPT - -int lrw_start( int cipher, - const unsigned char *IV, - const unsigned char *key, int keylen, - const unsigned char *tweak, - int num_rounds, - symmetric_LRW *lrw); -int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); -int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); -int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw); -int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); -int lrw_done(symmetric_LRW *lrw); -int lrw_test(void); - -/* don't call */ -int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); -#endif - -#ifdef LTC_F8_MODE -int f8_start( int cipher, const unsigned char *IV, - const unsigned char *key, int keylen, - const unsigned char *salt_key, int skeylen, - int num_rounds, symmetric_F8 *f8); -int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); -int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); -int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8); -int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); -int f8_done(symmetric_F8 *f8); -int f8_test_mode(void); -#endif - -#ifdef LTC_XTS_MODE -typedef struct { - symmetric_ECB key1, key2; - int cipher; -} symmetric_xts; - -int xts_start( int cipher, - const unsigned char *key1, - const unsigned char *key2, - unsigned long keylen, - int num_rounds, - symmetric_xts *xts); - -int xts_encrypt( - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tweak, - const symmetric_xts *xts); -int xts_decrypt( - const unsigned char *ct, unsigned long ptlen, - unsigned char *pt, - unsigned char *tweak, - const symmetric_xts *xts); - -void xts_done(symmetric_xts *xts); -int xts_test(void); -void xts_mult_x(unsigned char *I); -#endif - -int find_cipher(const char *name); -int find_cipher_any(const char *name, int blocklen, int keylen); -int find_cipher_id(unsigned char ID); -int register_cipher(const struct ltc_cipher_descriptor *cipher); -int unregister_cipher(const struct ltc_cipher_descriptor *cipher); -int register_all_ciphers(void); -int cipher_is_valid(int idx); - -LTC_MUTEX_PROTO(ltc_cipher_mutex) - -/* ---- stream ciphers ---- */ - -#ifdef LTC_CHACHA - -typedef struct { - ulong32 input[16]; - unsigned char kstream[64]; - unsigned long ksleft; - unsigned long ivlen; - int rounds; -} chacha_state; - -int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds); -int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter); -int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); -int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen); -int chacha_done(chacha_state *st); -int chacha_test(void); -int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *iv, unsigned long ivlen, ulong64 counter, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout); - -#endif /* LTC_CHACHA */ - -#ifdef LTC_SALSA20 - -typedef struct { - ulong32 input[16]; - unsigned char kstream[64]; - unsigned long ksleft; - unsigned long ivlen; - int rounds; -} salsa20_state; - -int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds); -int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); -int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen); -int salsa20_done(salsa20_state *st); -int salsa20_test(void); -int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *iv, unsigned long ivlen, ulong64 counter, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout); - -#endif /* LTC_SALSA20 */ - -#ifdef LTC_XSALSA20 - -int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - int rounds); -int xsalsa20_test(void); -int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout); - -#endif /* LTC_XSALSA20 */ - -#ifdef LTC_SOSEMANUK - -typedef struct { - ulong32 kc[100]; /* key_context */ - ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09; - ulong32 r1, r2; - /* - * Buffering: the stream cipher produces output data by - * blocks of 640 bits. buf[] contains such a block, and - * "ptr" is the index of the next output byte. - */ - unsigned char buf[80]; - unsigned ptr; -} sosemanuk_state; - -int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen); -int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen); -int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen); -int sosemanuk_done(sosemanuk_state *st); -int sosemanuk_test(void); -int sosemanuk_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout); - -#endif /* LTC_SOSEMANUK */ - -#ifdef LTC_RABBIT - -typedef struct { - ulong32 x[8]; - ulong32 c[8]; - ulong32 carry; -} rabbit_ctx; - -typedef struct { - rabbit_ctx master_ctx; - rabbit_ctx work_ctx; - unsigned char block[16]; /* last keystream block containing unused bytes */ - ulong32 unused; /* count fm right */ -} rabbit_state; - -int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen); -int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen); -int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int rabbit_keystream(rabbit_state* st, unsigned char *out, unsigned long outlen); -int rabbit_done(rabbit_state *st); -int rabbit_test(void); -int rabbit_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout); - -#endif /* LTC_RABBIT */ - -#ifdef LTC_RC4_STREAM - -typedef struct { - unsigned int x, y; - unsigned char buf[256]; -} rc4_state; - -int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); -int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); -int rc4_stream_done(rc4_state *st); -int rc4_stream_test(void); -int rc4_stream_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout); - -#endif /* LTC_RC4_STREAM */ - -#ifdef LTC_SOBER128_STREAM - -typedef struct { - ulong32 R[17], /* Working storage for the shift register */ - initR[17], /* saved register contents */ - konst, /* key dependent constant */ - sbuf; /* partial word encryption buffer */ - int nbuf; /* number of part-word stream bits buffered */ -} sober128_state; - -int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); -int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); -int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); -int sober128_stream_done(sober128_state *st); -int sober128_stream_test(void); -int sober128_stream_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout); - -#endif /* LTC_SOBER128_STREAM */ diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_custom.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_custom.h deleted file mode 100644 index 31440b4..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_custom.h +++ /dev/null @@ -1,790 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#ifndef TOMCRYPT_CUSTOM_H_ -#define TOMCRYPT_CUSTOM_H_ - -/* macros for various libc functions you can change for embedded targets */ -#ifndef XMALLOC -#define XMALLOC malloc -#endif -#ifndef XREALLOC -#define XREALLOC realloc -#endif -#ifndef XCALLOC -#define XCALLOC calloc -#endif -#ifndef XFREE -#define XFREE free -#endif - -#ifndef XMEMSET -#define XMEMSET memset -#endif -#ifndef XMEMCPY -#define XMEMCPY memcpy -#endif -#ifndef XMEMMOVE -#define XMEMMOVE memmove -#endif -#ifndef XMEMCMP -#define XMEMCMP memcmp -#endif -/* A memory compare function that has to run in constant time, - * c.f. mem_neq() API summary. - */ -#ifndef XMEM_NEQ -#define XMEM_NEQ mem_neq -#endif -#ifndef XSTRCMP -#define XSTRCMP strcmp -#endif -#ifndef XSTRLEN -#define XSTRLEN strlen -#endif -#ifndef XSTRNCPY -#define XSTRNCPY strncpy -#endif - -#ifndef XCLOCK -#define XCLOCK clock -#endif - -#ifndef XQSORT -#define XQSORT qsort -#endif - -#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \ - defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \ - defined(strlen) || defined(strncpy) || defined(clock) || defined(qsort) ) \ - && !defined(LTC_NO_PROTOTYPES) -#define LTC_NO_PROTOTYPES -#endif - -/* shortcut to disable automatic inclusion */ -#if defined LTC_NOTHING && !defined LTC_EASY - #define LTC_NO_CIPHERS - #define LTC_NO_MODES - #define LTC_NO_HASHES - #define LTC_NO_MACS - #define LTC_NO_PRNGS - #define LTC_NO_PK - #define LTC_NO_PKCS - #define LTC_NO_MISC -#endif /* LTC_NOTHING */ - -/* Easy button? */ -#ifdef LTC_EASY - #define LTC_NO_CIPHERS - #define LTC_RIJNDAEL - #define LTC_BLOWFISH - #define LTC_DES - #define LTC_SM4 - #define LTC_CAST5 - - #define LTC_NO_MODES - #define LTC_ECB_MODE - #define LTC_CBC_MODE - #define LTC_CTR_MODE - - #define LTC_NO_HASHES - #define LTC_SHA1 - #define LTC_SHA3 - #define LTC_SHA512 - #define LTC_SHA384 - #define LTC_SHA256 - #define LTC_SHA224 - #define LTC_HASH_HELPERS - - #define LTC_NO_MACS - #define LTC_HMAC - #define LTC_OMAC - #define LTC_CCM_MODE - - #define LTC_NO_PRNGS - #define LTC_SPRNG - #define LTC_YARROW - #define LTC_DEVRANDOM - #define LTC_TRY_URANDOM_FIRST - #define LTC_RNG_GET_BYTES - #define LTC_RNG_MAKE_PRNG - - #define LTC_NO_PK - #define LTC_MRSA - #define LTC_MECC - - #define LTC_NO_MISC - #define LTC_BASE64 - #define LTC_BASE16 - #define LTC_PEM -#endif /* LTC_EASY */ - -/* The minimal set of functionality to run the tests */ -#ifdef LTC_MINIMAL - #define LTC_RIJNDAEL - #define LTC_SHA256 - #define LTC_YARROW - #define LTC_CTR_MODE - - #define LTC_RNG_MAKE_PRNG - #define LTC_RNG_GET_BYTES - #define LTC_DEVRANDOM - #define LTC_TRY_URANDOM_FIRST - - #undef LTC_NO_FILE -#endif /* LTC_MINIMAL */ - -/* Enable self-test test vector checking */ -#ifndef LTC_NO_TEST - #define LTC_TEST -#endif -/* Enable extended self-tests */ -/* #define LTC_TEST_EXT */ - -/* Use small code where possible */ -/* #define LTC_SMALL_CODE */ - -/* clean the stack of functions which put private information on stack */ -/* #define LTC_CLEAN_STACK */ - -/* disable all file related functions */ -/* #define LTC_NO_FILE */ - -/* disable all forms of ASM */ -/* #define LTC_NO_ASM */ - -/* disable FAST mode */ -/* #define LTC_NO_FAST */ - -/* disable BSWAP on x86 */ -/* #define LTC_NO_BSWAP */ - -/* ---> math provider? <--- */ -#ifndef LTC_NO_MATH - -/* LibTomMath */ -/* #define LTM_DESC */ - -/* TomsFastMath */ -/* #define TFM_DESC */ - -/* GNU Multiple Precision Arithmetic Library */ -/* #define GMP_DESC */ - -#endif /* LTC_NO_MATH */ - -/* ---> Symmetric Block Ciphers <--- */ -#ifndef LTC_NO_CIPHERS - -#define LTC_BLOWFISH -#define LTC_RC2 -#define LTC_RC5 -#define LTC_RC6 -#define LTC_SAFERP -#define LTC_RIJNDAEL -#define LTC_XTEA -/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format - * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ -#define LTC_TWOFISH -#ifndef LTC_NO_TABLES - #define LTC_TWOFISH_TABLES - /* #define LTC_TWOFISH_ALL_TABLES */ -#else - #define LTC_TWOFISH_SMALL -#endif -/* #define LTC_TWOFISH_SMALL */ -/* LTC_DES includes EDE triple-DES */ -#define LTC_DES -#define LTC_SM4 -#define LTC_CAST5 -#define LTC_NOEKEON -#define LTC_SKIPJACK -#define LTC_SAFER -#define LTC_KHAZAD -#define LTC_ANUBIS -#define LTC_ANUBIS_TWEAK -#define LTC_KSEED -#define LTC_KASUMI -#define LTC_MULTI2 -#define LTC_CAMELLIA -#define LTC_IDEA -#define LTC_SERPENT -#define LTC_TEA - -/* stream ciphers */ -#define LTC_CHACHA -#define LTC_SALSA20 -#define LTC_XSALSA20 -#define LTC_SOSEMANUK -#define LTC_RABBIT -#define LTC_RC4_STREAM -#define LTC_SOBER128_STREAM - -#endif /* LTC_NO_CIPHERS */ - - -/* ---> Block Cipher Modes of Operation <--- */ -#ifndef LTC_NO_MODES - -#define LTC_CFB_MODE -#define LTC_OFB_MODE -#define LTC_ECB_MODE -#define LTC_CBC_MODE -#define LTC_CTR_MODE - -/* F8 chaining mode */ -#define LTC_F8_MODE - -/* LRW mode */ -#define LTC_LRW_MODE -#ifndef LTC_NO_TABLES - /* like GCM mode this will enable 16 8x128 tables [64KB] that make - * seeking very fast. - */ - #define LTC_LRW_TABLES -#endif - -/* XTS mode */ -#define LTC_XTS_MODE - -#endif /* LTC_NO_MODES */ - -/* ---> One-Way Hash Functions <--- */ -#ifndef LTC_NO_HASHES - -#define LTC_CHC_HASH -#define LTC_WHIRLPOOL -#define LTC_SHA3 -#define LTC_KECCAK -#define LTC_SHA512 -#define LTC_SHA512_256 -#define LTC_SHA512_224 -#define LTC_SHA384 -#define LTC_SHA256 -#define LTC_SHA224 -#define LTC_TIGER -#define LTC_SHA1 -#define LTC_MD5 -#define LTC_MD4 -#define LTC_MD2 -#define LTC_RIPEMD128 -#define LTC_RIPEMD160 -#define LTC_RIPEMD256 -#define LTC_RIPEMD320 -#define LTC_BLAKE2S -#define LTC_BLAKE2B - -#define LTC_HASH_HELPERS - -#endif /* LTC_NO_HASHES */ - - -/* ---> MAC functions <--- */ -#ifndef LTC_NO_MACS - -#define LTC_HMAC -#define LTC_OMAC -#define LTC_PMAC -#define LTC_XCBC -#define LTC_F9_MODE -#define LTC_PELICAN -#define LTC_POLY1305 -#define LTC_BLAKE2SMAC -#define LTC_BLAKE2BMAC - -/* ---> Encrypt + Authenticate Modes <--- */ - -#define LTC_EAX_MODE - -#define LTC_OCB_MODE -#define LTC_OCB3_MODE -#define LTC_CCM_MODE -#define LTC_GCM_MODE -#define LTC_CHACHA20POLY1305_MODE -#define LTC_SIV_MODE - -/* Use 64KiB tables */ -#ifndef LTC_NO_TABLES - #define LTC_GCM_TABLES -#endif - -/* USE SSE2? requires GCC works on x86_32 and x86_64*/ -#ifdef LTC_GCM_TABLES -/* #define LTC_GCM_TABLES_SSE2 */ -#endif - -#endif /* LTC_NO_MACS */ - - -/* --> Pseudo Random Number Generators <--- */ -#ifndef LTC_NO_PRNGS - -/* Yarrow */ -#define LTC_YARROW - -/* a PRNG that simply reads from an available system source */ -#define LTC_SPRNG - -/* The RC4 stream cipher based PRNG */ -#define LTC_RC4 - -/* The ChaCha20 stream cipher based PRNG */ -#define LTC_CHACHA20_PRNG - -/* Fortuna PRNG */ -#define LTC_FORTUNA - -/* Greg's SOBER128 stream cipher based PRNG */ -#define LTC_SOBER128 - -#if !defined(_WIN32) && !defined(_WIN32_WCE) -/* the *nix style /dev/random device */ -#define LTC_DEVRANDOM -/* try /dev/urandom before trying /dev/random - * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */ -#define LTC_TRY_URANDOM_FIRST -#endif /* not Windows */ - -/* rng_get_bytes() */ -#define LTC_RNG_GET_BYTES -/* rng_make_prng() */ -#define LTC_RNG_MAKE_PRNG - -/* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */ -/* #define LTC_PRNG_ENABLE_LTC_RNG */ - -#endif /* LTC_NO_PRNGS */ - -#ifdef LTC_YARROW - -/* which descriptor of AES to use? */ -/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ -#ifdef ENCRYPT_ONLY - #define LTC_YARROW_AES 0 -#else - #define LTC_YARROW_AES 2 -#endif - -#endif /* LTC_YARROW */ - -#ifdef LTC_FORTUNA - -#if !defined(LTC_FORTUNA_RESEED_RATELIMIT_STATIC) && \ - ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_WIN32)) - -/* time-based rate limit of the reseeding */ -#define LTC_FORTUNA_RESEED_RATELIMIT_TIMED - -/* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */ -#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) - #if __GLIBC_PREREQ(2, 17) - #define LTC_CLOCK_GETTIME - #endif -#elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L - #define LTC_CLOCK_GETTIME -#endif - -#else - -#ifndef LTC_FORTUNA_WD -/* reseed every N calls to the read function */ -#define LTC_FORTUNA_WD 10 -#endif - -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED -/* make sure only one of - * LTC_FORTUNA_RESEED_RATELIMIT_STATIC - * and - * LTC_FORTUNA_RESEED_RATELIMIT_TIMED - * is defined. - */ -#undef LTC_FORTUNA_RESEED_RATELIMIT_TIMED -#warning "undef'ed LTC_FORTUNA_RESEED_RATELIMIT_TIMED, looks like your architecture doesn't support it" -#endif - -#endif - -#ifndef LTC_FORTUNA_POOLS -/* number of pools (4..32) can save a bit of ram by lowering the count */ -#define LTC_FORTUNA_POOLS 32 -#endif - -/* at compile time you can decide whether fortuna uses the regular AES APIs - * or whether it will use the 'encrypt_only' variants. - * This is useful for custom builds of libtomcrypt for size-constrained targets. */ -/* #define LTC_FORTUNA_USE_ENCRYPT_ONLY */ - -#endif /* LTC_FORTUNA */ - - -/* ---> Public Key Crypto <--- */ -#ifndef LTC_NO_PK - -/* Include RSA support */ -#define LTC_MRSA - -/* Include Diffie-Hellman support */ -/* is_prime fails for GMP */ -#define LTC_MDH -/* Supported Key Sizes */ -#define LTC_DH768 -#define LTC_DH1024 -#define LTC_DH1536 -#define LTC_DH2048 - -#if defined(LTM_DESC) || defined(GMP_DESC) -/* tfm has a problem in fp_isprime for larger key sizes */ -#define LTC_DH3072 -#define LTC_DH4096 -#define LTC_DH6144 -#define LTC_DH8192 -#endif - -/* Digital Signature Algorithm */ -#define LTC_MDSA - -/* Ed25519 & X25519 */ -#define LTC_CURVE25519 - -/* ECC */ -#define LTC_MECC - -/* use Shamir's trick for point mul (speeds up signature verification) */ -#define LTC_ECC_SHAMIR - -#if defined(TFM_DESC) && defined(LTC_MECC) - #define LTC_MECC_ACCEL -#endif - -/* do we want fixed point ECC */ -/* #define LTC_MECC_FP */ - -#endif /* LTC_NO_PK */ - -#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING) -/* Enable RSA blinding when doing private key operations by default */ -#define LTC_RSA_BLINDING -#endif /* LTC_NO_RSA_BLINDING */ - -#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING) -/* Enable RSA CRT hardening when doing private key operations by default */ -#define LTC_RSA_CRT_HARDENING -#endif /* LTC_NO_RSA_CRT_HARDENING */ - -#if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT) -/* Enable ECC timing resistant version by default */ -#define LTC_ECC_TIMING_RESISTANT -#endif - -/* PKCS #1 (RSA) and #5 (Password Handling) stuff */ -#ifndef LTC_NO_PKCS - -#define LTC_PKCS_1 -#define LTC_PKCS_5 -#define LTC_PKCS_8 -#define LTC_PKCS_12 - -/* Include ASN.1 DER (required by DSA/RSA) */ -#define LTC_DER - -#endif /* LTC_NO_PKCS */ - -/* misc stuff */ -#ifndef LTC_NO_MISC - -/* Various tidbits of modern neatoness */ -#define LTC_BASE64 -/* ... and it's URL safe version */ -#define LTC_BASE64_URL -/* Base32 encoding/decoding */ -#define LTC_BASE32 -/* Base16/hex encoding/decoding */ -#define LTC_BASE16 - -#define LTC_BCRYPT - -#ifndef LTC_BCRYPT_DEFAULT_ROUNDS -#define LTC_BCRYPT_DEFAULT_ROUNDS 10 -#endif - -/* Keep LTC_NO_HKDF for compatibility reasons - * superseeded by LTC_NO_MISC*/ -#ifndef LTC_NO_HKDF -/* HKDF Key Derivation/Expansion stuff */ -#define LTC_HKDF -#endif /* LTC_NO_HKDF */ - -#define LTC_ADLER32 - -#define LTC_CRC32 - -#define LTC_SSH - -#define LTC_PADDING - -#define LTC_PBES - -#define LTC_PEM - -#endif /* LTC_NO_MISC */ - -/* cleanup */ - -#ifdef LTC_MECC -/* Supported ECC Key Sizes */ -#ifndef LTC_NO_CURVES - #define LTC_ECC_BRAINPOOLP160R1 - #define LTC_ECC_BRAINPOOLP160T1 - #define LTC_ECC_BRAINPOOLP192R1 - #define LTC_ECC_BRAINPOOLP192T1 - #define LTC_ECC_BRAINPOOLP224R1 - #define LTC_ECC_BRAINPOOLP224T1 - #define LTC_ECC_BRAINPOOLP256R1 - #define LTC_ECC_BRAINPOOLP256T1 - #define LTC_ECC_BRAINPOOLP320R1 - #define LTC_ECC_BRAINPOOLP320T1 - #define LTC_ECC_BRAINPOOLP384R1 - #define LTC_ECC_BRAINPOOLP384T1 - #define LTC_ECC_BRAINPOOLP512R1 - #define LTC_ECC_BRAINPOOLP512T1 - #define LTC_ECC_PRIME192V2 - #define LTC_ECC_PRIME192V3 - #define LTC_ECC_PRIME239V1 - #define LTC_ECC_PRIME239V2 - #define LTC_ECC_PRIME239V3 - #define LTC_ECC_SECP112R1 - #define LTC_ECC_SECP112R2 - #define LTC_ECC_SECP128R1 - #define LTC_ECC_SECP128R2 - #define LTC_ECC_SECP160K1 - #define LTC_ECC_SECP160R1 - #define LTC_ECC_SECP160R2 - #define LTC_ECC_SECP192K1 - #define LTC_ECC_SECP192R1 - #define LTC_ECC_SECP224K1 - #define LTC_ECC_SECP224R1 - #define LTC_ECC_SECP256K1 - #define LTC_ECC_SECP256R1 - #define LTC_ECC_SECP384R1 - #define LTC_ECC_SECP521R1 -#endif -#endif /* LTC_MECC */ - -#ifndef LTC_NO_FILE - /* buffer size for reading from a file via fread(..) */ - #ifndef LTC_FILE_READ_BUFSIZE - #define LTC_FILE_READ_BUFSIZE 8192 - #endif -#endif - -#if defined(LTC_PEM) - /* Size of the line-buffer */ - #ifndef LTC_PEM_DECODE_BUFSZ - #define LTC_PEM_DECODE_BUFSZ 80 - #elif LTC_PEM_DECODE_BUFSZ < 72 - #error "LTC_PEM_DECODE_BUFSZ shall not be < 72 bytes" - #endif - /* Size of the decoded data buffer */ - #ifndef LTC_PEM_READ_BUFSIZE - #ifdef LTC_FILE_READ_BUFSIZE - #define LTC_PEM_READ_BUFSIZE LTC_FILE_READ_BUFSIZE - #else - #define LTC_PEM_READ_BUFSIZE 4096 - #endif - #endif - #if defined(LTC_SSH) - #define LTC_PEM_SSH - #endif -#endif - -#if defined(LTC_DER) - #ifndef LTC_DER_MAX_RECURSION - /* Maximum recursion limit when processing nested ASN.1 types. */ - #define LTC_DER_MAX_RECURSION 30 - #endif -#endif - -#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH) - /* Include the MPI functionality? (required by the PK algorithms) */ - #define LTC_MPI - - #ifndef LTC_PK_MAX_RETRIES - /* iterations limit for retry-loops */ - #define LTC_PK_MAX_RETRIES 20 - #endif -#endif - -#ifdef LTC_MRSA - #define LTC_PKCS_1 -#endif - -#if defined(LTC_MRSA) || defined(LTC_MECC) - #define LTC_PKCS_8 -#endif - -#if defined(LTC_PKCS_8) && defined(LTC_DER) - #define LTC_PADDING - #define LTC_PBES -#else - #undef LTC_PKCS_8 -#endif - -#if defined(LTC_CLEAN_STACK) -/* if you're sure that you want to use it, remove the line below */ - #error LTC_CLEAN_STACK is considered as broken -#endif - -#if defined(LTC_PBES) && !defined(LTC_PKCS_5) - #error LTC_PBES requires LTC_PKCS_5 -#endif - -#if defined(LTC_PBES) && !defined(LTC_PKCS_12) - #error LTC_PBES requires LTC_PKCS_12 -#endif - -#if defined(LTC_PKCS_5) && !defined(LTC_HMAC) - #error LTC_PKCS_5 requires LTC_HMAC -#endif - -#if defined(LTC_PKCS_5) && !defined(LTC_HASH_HELPERS) - #error LTC_PKCS_5 requires LTC_HASH_HELPERS -#endif - -#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL) - #error Pelican-MAC requires LTC_RIJNDAEL -#endif - -#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) - #error LTC_EAX_MODE requires CTR and LTC_OMAC mode -#endif - -#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) - #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! -#endif - -#if defined(LTC_DER) && !defined(LTC_MPI) - #error ASN.1 DER requires MPI functionality -#endif - -#if (defined(LTC_MDSA) || defined(LTC_MRSA)) && !defined(LTC_DER) - #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled -#endif - -#if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH) - #error LTC_BCRYPT requires LTC_BLOWFISH -#endif - -#if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305)) - #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305 -#endif - -#if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA) - #error LTC_CHACHA20_PRNG requires LTC_CHACHA -#endif - -#if defined(LTC_XSALSA20) && !defined(LTC_SALSA20) - #error LTC_XSALSA20 requires LTC_SALSA20 -#endif - -#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM) - #error LTC_RC4 requires LTC_RC4_STREAM -#endif - -#if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM) - #error LTC_SOBER128 requires LTC_SOBER128_STREAM -#endif - -#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S) - #error LTC_BLAKE2SMAC requires LTC_BLAKE2S -#endif - -#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B) - #error LTC_BLAKE2BMAC requires LTC_BLAKE2B -#endif - -#if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES) - #error LTC_SPRNG requires LTC_RNG_GET_BYTES -#endif - -#if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC)) - #error LTC_NO_MATH defined, but also a math descriptor -#endif - -#if !defined(LTC_ECB_MODE) -#if defined(LTC_CFB_MODE) || defined(LTC_OFB_MODE) || defined(LTC_CBC_MODE) || defined(LTC_CTR_MODE) || \ - defined(LTC_F8_MODE) || defined(LTC_LRW_MODE) || defined(LTC_XTS_MODE) ) - #error LTC_ECB_MODE not defined, but all other modes depend on it -#endif -#if defined(LTC_OMAC) || defined(LTC_PMAC) || defined(LTC_XCBC) || defined(LTC_F9_MODE) || defined(LTC_EAX_MODE) || \ - defined(LTC_OCB_MODE) || defined(LTC_OCB3_MODE) || defined(LTC_CCM_MODE) || defined(LTC_GCM_MODE) ) - #error LTC_ECB_MODE not defined, but most MAC and AEAD modes depend on it -#endif -#endif - - -/* THREAD management */ -#ifdef LTC_PTHREAD - -#include - -#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; -#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; -#define LTC_MUTEX_TYPE(x) pthread_mutex_t x; -#define LTC_MUTEX_INIT(x) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0); -#define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0); -#define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0); -#define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0); - -#else - -/* default no functions */ -#define LTC_MUTEX_GLOBAL(x) -#define LTC_MUTEX_PROTO(x) -#define LTC_MUTEX_TYPE(x) -#define LTC_MUTEX_INIT(x) -#define LTC_MUTEX_LOCK(x) -#define LTC_MUTEX_UNLOCK(x) -#define LTC_MUTEX_DESTROY(x) - -#endif /* LTC_PTHREAD */ - -/* Debuggers */ - -/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ -/* #define LTC_VALGRIND */ - -/* ECC backwards compatibility */ -#if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112) -#define LTC_ECC_SECP112R1 -#undef LTC_ECC112 -#endif -#if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128) -#define LTC_ECC_SECP128R1 -#undef LTC_ECC128 -#endif -#if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160) -#define LTC_ECC_SECP160R1 -#undef LTC_ECC160 -#endif -#if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192) -#define LTC_ECC_SECP192R1 -#undef LTC_ECC192 -#endif -#if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224) -#define LTC_ECC_SECP224R1 -#undef LTC_ECC224 -#endif -#if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256) -#define LTC_ECC_SECP256R1 -#undef LTC_ECC256 -#endif -#if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384) -#define LTC_ECC_SECP384R1 -#undef LTC_ECC384 -#endif -#if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521) -#define LTC_ECC_SECP521R1 -#undef LTC_ECC521 -#endif - -#endif /* TOMCRYPT_CUSTOM_H_ */ diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_hash.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_hash.h deleted file mode 100644 index 384ee2a..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_hash.h +++ /dev/null @@ -1,509 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* ---- HASH FUNCTIONS ---- */ -#if defined(LTC_SHA3) || defined(LTC_KECCAK) -struct sha3_state { - ulong64 saved; /* the portion of the input message that we didn't consume yet */ - ulong64 s[25]; - unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */ - unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */ - unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */ - unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */ - unsigned short xof_flag; -}; -#endif - -#ifdef LTC_SHA512 -struct sha512_state { - ulong64 length, state[8]; - unsigned long curlen; - unsigned char buf[128]; -}; -#endif - -#ifdef LTC_SHA256 -struct sha256_state { - ulong64 length; - ulong32 state[8], curlen; - unsigned char buf[64]; -}; -#endif - -#ifdef LTC_SHA1 -struct sha1_state { - ulong64 length; - ulong32 state[5], curlen; - unsigned char buf[64]; -}; -#endif - -#ifdef LTC_MD5 -struct md5_state { - ulong64 length; - ulong32 state[4], curlen; - unsigned char buf[64]; -}; -#endif - -#ifdef LTC_MD4 -struct md4_state { - ulong64 length; - ulong32 state[4], curlen; - unsigned char buf[64]; -}; -#endif - -#ifdef LTC_TIGER -struct tiger_state { - ulong64 state[3], length; - unsigned long curlen, passes; - unsigned char buf[64], pad; -}; -#endif - -#ifdef LTC_MD2 -struct md2_state { - unsigned char chksum[16], X[48], buf[16]; - unsigned long curlen; -}; -#endif - -#ifdef LTC_RIPEMD128 -struct rmd128_state { - ulong64 length; - unsigned char buf[64]; - ulong32 curlen, state[4]; -}; -#endif - -#ifdef LTC_RIPEMD160 -struct rmd160_state { - ulong64 length; - unsigned char buf[64]; - ulong32 curlen, state[5]; -}; -#endif - -#ifdef LTC_RIPEMD256 -struct rmd256_state { - ulong64 length; - unsigned char buf[64]; - ulong32 curlen, state[8]; -}; -#endif - -#ifdef LTC_RIPEMD320 -struct rmd320_state { - ulong64 length; - unsigned char buf[64]; - ulong32 curlen, state[10]; -}; -#endif - -#ifdef LTC_WHIRLPOOL -struct whirlpool_state { - ulong64 length, state[8]; - unsigned char buf[64]; - ulong32 curlen; -}; -#endif - -#ifdef LTC_CHC_HASH -struct chc_state { - ulong64 length; - unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; - ulong32 curlen; -}; -#endif - -#ifdef LTC_BLAKE2S -struct blake2s_state { - ulong32 h[8]; - ulong32 t[2]; - ulong32 f[2]; - unsigned char buf[64]; - unsigned long curlen; - unsigned long outlen; - unsigned char last_node; -}; -#endif - -#ifdef LTC_BLAKE2B -struct blake2b_state { - ulong64 h[8]; - ulong64 t[2]; - ulong64 f[2]; - unsigned char buf[128]; - unsigned long curlen; - unsigned long outlen; - unsigned char last_node; -}; -#endif - -typedef union Hash_state { - char dummy[1]; -#ifdef LTC_CHC_HASH - struct chc_state chc; -#endif -#ifdef LTC_WHIRLPOOL - struct whirlpool_state whirlpool; -#endif -#if defined(LTC_SHA3) || defined(LTC_KECCAK) - struct sha3_state sha3; -#endif -#ifdef LTC_SHA512 - struct sha512_state sha512; -#endif -#ifdef LTC_SHA256 - struct sha256_state sha256; -#endif -#ifdef LTC_SHA1 - struct sha1_state sha1; -#endif -#ifdef LTC_MD5 - struct md5_state md5; -#endif -#ifdef LTC_MD4 - struct md4_state md4; -#endif -#ifdef LTC_MD2 - struct md2_state md2; -#endif -#ifdef LTC_TIGER - struct tiger_state tiger; -#endif -#ifdef LTC_RIPEMD128 - struct rmd128_state rmd128; -#endif -#ifdef LTC_RIPEMD160 - struct rmd160_state rmd160; -#endif -#ifdef LTC_RIPEMD256 - struct rmd256_state rmd256; -#endif -#ifdef LTC_RIPEMD320 - struct rmd320_state rmd320; -#endif -#ifdef LTC_BLAKE2S - struct blake2s_state blake2s; -#endif -#ifdef LTC_BLAKE2B - struct blake2b_state blake2b; -#endif - - void *data; -} hash_state; - -/** hash descriptor */ -extern struct ltc_hash_descriptor { - /** name of hash */ - const char *name; - /** internal ID */ - unsigned char ID; - /** Size of digest in octets */ - unsigned long hashsize; - /** Input block size in octets */ - unsigned long blocksize; - /** ASN.1 OID */ - unsigned long OID[16]; - /** Length of DER encoding */ - unsigned long OIDlen; - - /** Init a hash state - @param hash The hash to initialize - @return CRYPT_OK if successful - */ - int (*init)(hash_state *hash); - /** Process a block of data - @param hash The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful - */ - int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); - /** Produce the digest and store it - @param hash The hash state - @param out [out] The destination of the digest - @return CRYPT_OK if successful - */ - int (*done)(hash_state *hash, unsigned char *out); - /** Self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled - */ - int (*test)(void); - - /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ - int (*hmac_block)(const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -} hash_descriptor[]; - -#ifdef LTC_CHC_HASH -int chc_register(int cipher); -int chc_init(hash_state * md); -int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int chc_done(hash_state * md, unsigned char *out); -int chc_test(void); -extern const struct ltc_hash_descriptor chc_desc; -#endif - -#ifdef LTC_WHIRLPOOL -int whirlpool_init(hash_state * md); -int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int whirlpool_done(hash_state * md, unsigned char *out); -int whirlpool_test(void); -extern const struct ltc_hash_descriptor whirlpool_desc; -#endif - -#if defined(LTC_SHA3) || defined(LTC_KECCAK) -/* sha3_NNN_init are shared by SHA3 and KECCAK */ -int sha3_512_init(hash_state * md); -int sha3_384_init(hash_state * md); -int sha3_256_init(hash_state * md); -int sha3_224_init(hash_state * md); -/* sha3_process is the same for all variants of SHA3 + KECCAK */ -int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen); -#endif - -#ifdef LTC_SHA3 -int sha3_512_test(void); -extern const struct ltc_hash_descriptor sha3_512_desc; -int sha3_384_test(void); -extern const struct ltc_hash_descriptor sha3_384_desc; -int sha3_256_test(void); -extern const struct ltc_hash_descriptor sha3_256_desc; -int sha3_224_test(void); -extern const struct ltc_hash_descriptor sha3_224_desc; -int sha3_done(hash_state *md, unsigned char *out); -/* SHAKE128 + SHAKE256 */ -int sha3_shake_init(hash_state *md, int num); -#define sha3_shake_process(a,b,c) sha3_process(a,b,c) -int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen); -int sha3_shake_test(void); -int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen); -#endif - -#ifdef LTC_KECCAK -#define keccak_512_init(a) sha3_512_init(a) -#define keccak_384_init(a) sha3_384_init(a) -#define keccak_256_init(a) sha3_256_init(a) -#define keccak_224_init(a) sha3_224_init(a) -#define keccak_process(a,b,c) sha3_process(a,b,c) -extern const struct ltc_hash_descriptor keccak_512_desc; -int keccak_512_test(void); -extern const struct ltc_hash_descriptor keccak_384_desc; -int keccak_384_test(void); -extern const struct ltc_hash_descriptor keccak_256_desc; -int keccak_256_test(void); -extern const struct ltc_hash_descriptor keccak_224_desc; -int keccak_224_test(void); -int keccak_done(hash_state *md, unsigned char *out); -#endif - -#ifdef LTC_SHA512 -int sha512_init(hash_state * md); -int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int sha512_done(hash_state * md, unsigned char *out); -int sha512_test(void); -extern const struct ltc_hash_descriptor sha512_desc; -#endif - -#ifdef LTC_SHA384 -#ifndef LTC_SHA512 - #error LTC_SHA512 is required for LTC_SHA384 -#endif -int sha384_init(hash_state * md); -#define sha384_process sha512_process -int sha384_done(hash_state * md, unsigned char *out); -int sha384_test(void); -extern const struct ltc_hash_descriptor sha384_desc; -#endif - -#ifdef LTC_SHA512_256 -#ifndef LTC_SHA512 - #error LTC_SHA512 is required for LTC_SHA512_256 -#endif -int sha512_256_init(hash_state * md); -#define sha512_256_process sha512_process -int sha512_256_done(hash_state * md, unsigned char *out); -int sha512_256_test(void); -extern const struct ltc_hash_descriptor sha512_256_desc; -#endif - -#ifdef LTC_SHA512_224 -#ifndef LTC_SHA512 - #error LTC_SHA512 is required for LTC_SHA512_224 -#endif -int sha512_224_init(hash_state * md); -#define sha512_224_process sha512_process -int sha512_224_done(hash_state * md, unsigned char *out); -int sha512_224_test(void); -extern const struct ltc_hash_descriptor sha512_224_desc; -#endif - -#ifdef LTC_SHA256 -int sha256_init(hash_state * md); -int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int sha256_done(hash_state * md, unsigned char *out); -int sha256_test(void); -extern const struct ltc_hash_descriptor sha256_desc; - -#ifdef LTC_SHA224 -#ifndef LTC_SHA256 - #error LTC_SHA256 is required for LTC_SHA224 -#endif -int sha224_init(hash_state * md); -#define sha224_process sha256_process -int sha224_done(hash_state * md, unsigned char *out); -int sha224_test(void); -extern const struct ltc_hash_descriptor sha224_desc; -#endif -#endif - -#ifdef LTC_SHA1 -int sha1_init(hash_state * md); -int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int sha1_done(hash_state * md, unsigned char *out); -int sha1_test(void); -extern const struct ltc_hash_descriptor sha1_desc; -#endif - -#ifdef LTC_BLAKE2S -extern const struct ltc_hash_descriptor blake2s_256_desc; -int blake2s_256_init(hash_state * md); -int blake2s_256_test(void); - -extern const struct ltc_hash_descriptor blake2s_224_desc; -int blake2s_224_init(hash_state * md); -int blake2s_224_test(void); - -extern const struct ltc_hash_descriptor blake2s_160_desc; -int blake2s_160_init(hash_state * md); -int blake2s_160_test(void); - -extern const struct ltc_hash_descriptor blake2s_128_desc; -int blake2s_128_init(hash_state * md); -int blake2s_128_test(void); - -int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); -int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int blake2s_done(hash_state * md, unsigned char *out); -#endif - -#ifdef LTC_BLAKE2B -extern const struct ltc_hash_descriptor blake2b_512_desc; -int blake2b_512_init(hash_state * md); -int blake2b_512_test(void); - -extern const struct ltc_hash_descriptor blake2b_384_desc; -int blake2b_384_init(hash_state * md); -int blake2b_384_test(void); - -extern const struct ltc_hash_descriptor blake2b_256_desc; -int blake2b_256_init(hash_state * md); -int blake2b_256_test(void); - -extern const struct ltc_hash_descriptor blake2b_160_desc; -int blake2b_160_init(hash_state * md); -int blake2b_160_test(void); - -int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); -int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int blake2b_done(hash_state * md, unsigned char *out); -#endif - -#ifdef LTC_MD5 -int md5_init(hash_state * md); -int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int md5_done(hash_state * md, unsigned char *out); -int md5_test(void); -extern const struct ltc_hash_descriptor md5_desc; -#endif - -#ifdef LTC_MD4 -int md4_init(hash_state * md); -int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int md4_done(hash_state * md, unsigned char *out); -int md4_test(void); -extern const struct ltc_hash_descriptor md4_desc; -#endif - -#ifdef LTC_MD2 -int md2_init(hash_state * md); -int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int md2_done(hash_state * md, unsigned char *out); -int md2_test(void); -extern const struct ltc_hash_descriptor md2_desc; -#endif - -#ifdef LTC_TIGER -int tiger_init(hash_state * md); -int tiger_init_ex(hash_state *md, unsigned long passes); -int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int tiger_done(hash_state * md, unsigned char *out); -int tiger_test(void); -int tiger2_init(hash_state *md); -int tiger2_init_ex(hash_state *md, unsigned long passes); -#define tiger2_process(m, i, l) tiger_process(m, i, l) -#define tiger2_done(m, o) tiger_done(m, o) -int tiger2_test(void); -extern const struct ltc_hash_descriptor tiger_desc, tiger2_desc; -#endif - -#ifdef LTC_RIPEMD128 -int rmd128_init(hash_state * md); -int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int rmd128_done(hash_state * md, unsigned char *out); -int rmd128_test(void); -extern const struct ltc_hash_descriptor rmd128_desc; -#endif - -#ifdef LTC_RIPEMD160 -int rmd160_init(hash_state * md); -int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int rmd160_done(hash_state * md, unsigned char *out); -int rmd160_test(void); -extern const struct ltc_hash_descriptor rmd160_desc; -#endif - -#ifdef LTC_RIPEMD256 -int rmd256_init(hash_state * md); -int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int rmd256_done(hash_state * md, unsigned char *out); -int rmd256_test(void); -extern const struct ltc_hash_descriptor rmd256_desc; -#endif - -#ifdef LTC_RIPEMD320 -int rmd320_init(hash_state * md); -int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); -int rmd320_done(hash_state * md, unsigned char *out); -int rmd320_test(void); -extern const struct ltc_hash_descriptor rmd320_desc; -#endif - - -int find_hash(const char *name); -int find_hash_id(unsigned char ID); -int find_hash_oid(const unsigned long *ID, unsigned long IDlen); -int find_hash_any(const char *name, int digestlen); -int register_hash(const struct ltc_hash_descriptor *hash); -int unregister_hash(const struct ltc_hash_descriptor *hash); -int register_all_hashes(void); -int hash_is_valid(int idx); - -LTC_MUTEX_PROTO(ltc_hash_mutex) - -int hash_memory(int hash, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; - -#ifndef LTC_NO_FILE -int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); -int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); -#endif diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_mac.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_mac.h deleted file mode 100644 index 2e067bc..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_mac.h +++ /dev/null @@ -1,579 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#ifdef LTC_HMAC -typedef struct Hmac_state { - hash_state md; - int hash; - unsigned char key[MAXBLOCKSIZE]; -} hmac_state; - -int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); -int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); -int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); -int hmac_test(void); -int hmac_memory(int hash, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int hmac_memory_multi(int hash, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int hmac_file(int hash, const char *fname, const unsigned char *key, - unsigned long keylen, - unsigned char *out, unsigned long *outlen); -#endif - -#ifdef LTC_OMAC - -typedef struct { - int buflen, - blklen; - unsigned char block[MAXBLOCKSIZE], - prev[MAXBLOCKSIZE], - Lu[2][MAXBLOCKSIZE]; - symmetric_ECB key; -} omac_state; - -int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); -int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); -int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); -int omac_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int omac_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int omac_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen); -int omac_test(void); -#endif /* LTC_OMAC */ - -#ifdef LTC_PMAC - -typedef struct { - unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ - Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ - Lr[MAXBLOCKSIZE], /* L * x^-1 */ - block[MAXBLOCKSIZE], /* currently accumulated block */ - checksum[MAXBLOCKSIZE]; /* current checksum */ - - symmetric_ECB key; /* scheduled key for cipher */ - unsigned long block_index; /* index # for current block */ - int block_len, /* length of block */ - buflen; /* number of bytes in the buffer */ -} pmac_state; - -int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); -int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); -int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); - -int pmac_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -int pmac_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; - -int pmac_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen); - -int pmac_test(void); - -/* internal functions */ -int pmac_ntz(unsigned long x); -void pmac_shift_xor(pmac_state *pmac); - -#endif /* PMAC */ - -#ifdef LTC_POLY1305 -typedef struct { - ulong32 r[5]; - ulong32 h[5]; - ulong32 pad[4]; - unsigned long leftover; - unsigned char buffer[16]; - int final; -} poly1305_state; - -int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen); -int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen); -int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen); -int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, - unsigned char *mac, unsigned long *maclen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); -int poly1305_test(void); -#endif /* LTC_POLY1305 */ - -#ifdef LTC_BLAKE2SMAC -typedef hash_state blake2smac_state; -int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); -int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen); -int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen); -int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, - unsigned char *mac, unsigned long *maclen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); -int blake2smac_test(void); -#endif /* LTC_BLAKE2SMAC */ - -#ifdef LTC_BLAKE2BMAC -typedef hash_state blake2bmac_state; -int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); -int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen); -int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen); -int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, - unsigned char *mac, unsigned long *maclen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); -int blake2bmac_test(void); -#endif /* LTC_BLAKE2BMAC */ - - -#ifdef LTC_PELICAN - -typedef struct pelican_state -{ - symmetric_key K; - unsigned char state[16]; - int buflen; -} pelican_state; - -int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); -int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); -int pelican_done(pelican_state *pelmac, unsigned char *out); -int pelican_test(void); - -int pelican_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out); - -#endif - -#ifdef LTC_XCBC - -/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */ -#define LTC_XCBC_PURE 0x8000UL - -typedef struct { - unsigned char K[3][MAXBLOCKSIZE], - IV[MAXBLOCKSIZE]; - - symmetric_ECB key; - - int buflen, - blocksize; -} xcbc_state; - -int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); -int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); -int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); -int xcbc_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int xcbc_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int xcbc_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen); -int xcbc_test(void); - -#endif - -#ifdef LTC_F9_MODE - -typedef struct { - unsigned char akey[MAXBLOCKSIZE], - ACC[MAXBLOCKSIZE], - IV[MAXBLOCKSIZE]; - - symmetric_ECB key; - - int cipher, - buflen, - keylen, - blocksize; -} f9_state; - -int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); -int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); -int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); -int f9_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int f9_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - LTC_NULL_TERMINATED; -int f9_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *fname, - unsigned char *out, unsigned long *outlen); -int f9_test(void); - -#endif - -/* - * ENC+AUTH modes - */ - -#ifdef LTC_EAX_MODE - -#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) - #error LTC_EAX_MODE requires LTC_OMAC and CTR -#endif - -typedef struct { - unsigned char N[MAXBLOCKSIZE]; - symmetric_CTR ctr; - omac_state headeromac, ctomac; -} eax_state; - -int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen); - -int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); -int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); -int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); -int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); - -int eax_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen); - -int eax_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat); - - int eax_test(void); -#endif /* EAX MODE */ - -#ifdef LTC_OCB_MODE -typedef struct { - unsigned char L[MAXBLOCKSIZE], /* L value */ - Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ - Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ - Lr[MAXBLOCKSIZE], /* L * x^-1 */ - R[MAXBLOCKSIZE], /* R value */ - checksum[MAXBLOCKSIZE]; /* current checksum */ - - symmetric_ECB key; /* scheduled key for cipher */ - unsigned long block_index; /* index # for current block */ - int block_len; /* length of block */ -} ocb_state; - -int ocb_init(ocb_state *ocb, int cipher, - const unsigned char *key, unsigned long keylen, const unsigned char *nonce); - -int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); -int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); - -int ocb_done_encrypt(ocb_state *ocb, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen); - -int ocb_done_decrypt(ocb_state *ocb, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, int *stat); - -int ocb_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen); - -int ocb_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat); - -int ocb_test(void); - -/* internal functions */ -void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); -int ocb_ntz(unsigned long x); -int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); - -#endif /* LTC_OCB_MODE */ - -#ifdef LTC_OCB3_MODE -typedef struct { - unsigned char Offset_0[MAXBLOCKSIZE], /* Offset_0 value */ - Offset_current[MAXBLOCKSIZE], /* Offset_{current_block_index} value */ - L_dollar[MAXBLOCKSIZE], /* L_$ value */ - L_star[MAXBLOCKSIZE], /* L_* value */ - L_[32][MAXBLOCKSIZE], /* L_{i} values */ - tag_part[MAXBLOCKSIZE], /* intermediate result of tag calculation */ - checksum[MAXBLOCKSIZE]; /* current checksum */ - - /* AAD related members */ - unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */ - aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */ - adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */ - - symmetric_ECB key; /* scheduled key for cipher */ - int adata_buffer_bytes; /* bytes in AAD buffer */ - unsigned long ablock_index; /* index # for current adata (AAD) block */ - unsigned long block_index; /* index # for current data block */ - int tag_len, /* length of tag */ - block_len; /* length of block */ -} ocb3_state; - -int ocb3_init(ocb3_state *ocb, int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - unsigned long taglen); - -int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); -int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); -int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); -int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); -int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen); -int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen); - -int ocb3_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *adata, unsigned long adatalen, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen); - -int ocb3_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *adata, unsigned long adatalen, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *stat); - -int ocb3_test(void); - -#endif /* LTC_OCB3_MODE */ - -#ifdef LTC_CCM_MODE - -#define CCM_ENCRYPT LTC_ENCRYPT -#define CCM_DECRYPT LTC_DECRYPT - -typedef struct { - symmetric_ECB K; - unsigned char PAD[16], /* flags | Nonce N | l(m) */ - ctr[16], - CTRPAD[16]; - - - int taglen, /* length of the tag (encoded in M value) */ - x; /* index in PAD */ - - unsigned long L, /* L value */ - ptlen, /* length that will be enc / dec */ - current_ptlen, /* current processed length */ - aadlen, /* length of the aad */ - current_aadlen, /* length of the currently provided add */ - noncelen; /* length of the nonce */ - - unsigned char CTRlen; -} ccm_state; - -int ccm_init(ccm_state *ccm, int cipher, - const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen); - -int ccm_reset(ccm_state *ccm); - -int ccm_add_nonce(ccm_state *ccm, - const unsigned char *nonce, unsigned long noncelen); - -int ccm_add_aad(ccm_state *ccm, - const unsigned char *adata, unsigned long adatalen); - -int ccm_process(ccm_state *ccm, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - int direction); - -int ccm_done(ccm_state *ccm, - unsigned char *tag, unsigned long *taglen); - -int ccm_memory(int cipher, - const unsigned char *key, unsigned long keylen, - symmetric_ECB *uskey, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction); - -int ccm_test(void); - -#endif /* LTC_CCM_MODE */ - -#if defined(LTC_LRW_MODE) || defined(LTC_GCM_MODE) -void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); -#endif - - -/* table shared between GCM and LRW */ -#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) -extern const unsigned char gcm_shift_table[]; -#endif - -#ifdef LTC_GCM_MODE - -#define GCM_ENCRYPT LTC_ENCRYPT -#define GCM_DECRYPT LTC_DECRYPT - -#define LTC_GCM_MODE_IV 0 -#define LTC_GCM_MODE_AAD 1 -#define LTC_GCM_MODE_TEXT 2 - -typedef struct { - symmetric_ECB K; - unsigned char H[16], /* multiplier */ - X[16], /* accumulator */ - Y[16], /* counter */ - Y_0[16], /* initial counter */ - buf[16]; /* buffer for stuff */ - -#ifdef LTC_GCM_TABLES - unsigned char PC[16][256][16]; /* 16 tables of 8x128 */ -#endif - int ivmode, /* Which mode is the IV in? */ - mode, /* mode the GCM code is in */ - buflen; /* length of data in buf */ - - ulong64 totlen, /* 64-bit counter used for IV and AAD */ - pttotlen; /* 64-bit counter for the PT */ -} gcm_state; - -void gcm_mult_h(const gcm_state *gcm, unsigned char *I); - -int gcm_init(gcm_state *gcm, int cipher, - const unsigned char *key, int keylen); - -int gcm_reset(gcm_state *gcm); - -int gcm_add_iv(gcm_state *gcm, - const unsigned char *IV, unsigned long IVlen); - -int gcm_add_aad(gcm_state *gcm, - const unsigned char *adata, unsigned long adatalen); - -int gcm_process(gcm_state *gcm, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - int direction); - -int gcm_done(gcm_state *gcm, - unsigned char *tag, unsigned long *taglen); - -int gcm_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *IV, unsigned long IVlen, - const unsigned char *adata, unsigned long adatalen, - unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen, - int direction); -int gcm_test(void); - -#endif /* LTC_GCM_MODE */ - -#ifdef LTC_CHACHA20POLY1305_MODE - -typedef struct { - poly1305_state poly; - chacha_state chacha; - ulong64 aadlen; - ulong64 ctlen; - int aadflg, openssh_compat; -} chacha20poly1305_state; - -#define CHACHA20POLY1305_ENCRYPT LTC_ENCRYPT -#define CHACHA20POLY1305_DECRYPT LTC_DECRYPT -#define CHACHA20POLY1305_OPENSSH_COMPAT 2 - -int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen); -int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen); -int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number); -int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen); -int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); -int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen); -int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *aad, unsigned long aadlen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, - unsigned char *tag, unsigned long *taglen, - int direction); -int chacha20poly1305_test(void); - -#endif /* LTC_CHACHA20POLY1305_MODE */ -#ifdef LTC_SIV_MODE - -int siv_encrypt_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *ad[], unsigned long adlen[], - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned long *ctlen); -int siv_decrypt_memory( int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *ad[], unsigned long adlen[], - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, unsigned long *ptlen); -int siv_memory( int cipher, int direction, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - ...) LTC_NULL_TERMINATED; -int siv_test(void); - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_macros.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_macros.h deleted file mode 100644 index ebb3c84..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_macros.h +++ /dev/null @@ -1,459 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - - -#define LTC_TMPVAR__(n, l) n ## l -#define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l) -#define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__) - -/* ---- HELPER MACROS ---- */ -#ifdef ENDIAN_NEUTRAL - -#define STORE32L(x, y) \ - do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) - -#define LOAD32L(x, y) \ - do { x = ((ulong32)((y)[3] & 255)<<24) | \ - ((ulong32)((y)[2] & 255)<<16) | \ - ((ulong32)((y)[1] & 255)<<8) | \ - ((ulong32)((y)[0] & 255)); } while(0) - -#define STORE64L(x, y) \ - do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ - (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ - (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) - -#define LOAD64L(x, y) \ - do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ - (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ - (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ - (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) - -#define STORE32H(x, y) \ - do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ - (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) - -#define LOAD32H(x, y) \ - do { x = ((ulong32)((y)[0] & 255)<<24) | \ - ((ulong32)((y)[1] & 255)<<16) | \ - ((ulong32)((y)[2] & 255)<<8) | \ - ((ulong32)((y)[3] & 255)); } while(0) - -#define STORE64H(x, y) \ -do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) - -#define LOAD64H(x, y) \ -do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ - (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ - (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ - (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) - - -#elif defined(ENDIAN_LITTLE) - -#ifdef LTC_HAVE_BSWAP_BUILTIN - -#define STORE32H(x, y) \ -do { ulong32 ttt = __builtin_bswap32 ((x)); \ - XMEMCPY ((y), &ttt, 4); } while(0) - -#define LOAD32H(x, y) \ -do { XMEMCPY (&(x), (y), 4); \ - (x) = __builtin_bswap32 ((x)); } while(0) - -#elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) - -#define STORE32H(x, y) \ -__asm__ volatile ( \ - "bswapl %0 \n\t" \ - "movl %0,(%1)\n\t" \ - "bswapl %0 \n\t" \ - ::"r"(x), "r"(y): "memory"); - -#define LOAD32H(x, y) \ -__asm__ volatile ( \ - "movl (%1),%0\n\t" \ - "bswapl %0\n\t" \ - :"=r"(x): "r"(y): "memory"); - -#else - -#define STORE32H(x, y) \ - do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ - (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) - -#define LOAD32H(x, y) \ - do { x = ((ulong32)((y)[0] & 255)<<24) | \ - ((ulong32)((y)[1] & 255)<<16) | \ - ((ulong32)((y)[2] & 255)<<8) | \ - ((ulong32)((y)[3] & 255)); } while(0) - -#endif - -#ifdef LTC_HAVE_BSWAP_BUILTIN - -#define STORE64H(x, y) \ -do { ulong64 ttt = __builtin_bswap64 ((x)); \ - XMEMCPY ((y), &ttt, 8); } while(0) - -#define LOAD64H(x, y) \ -do { XMEMCPY (&(x), (y), 8); \ - (x) = __builtin_bswap64 ((x)); } while(0) - -/* x86_64 processor */ -#elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) - -#define STORE64H(x, y) \ -__asm__ volatile ( \ - "bswapq %0 \n\t" \ - "movq %0,(%1)\n\t" \ - "bswapq %0 \n\t" \ - ::"r"(x), "r"(y): "memory"); - -#define LOAD64H(x, y) \ -__asm__ volatile ( \ - "movq (%1),%0\n\t" \ - "bswapq %0\n\t" \ - :"=r"(x): "r"(y): "memory"); - -#else - -#define STORE64H(x, y) \ -do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) - -#define LOAD64H(x, y) \ -do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ - (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ - (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ - (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) - -#endif - -#ifdef ENDIAN_32BITWORD - -#define STORE32L(x, y) \ - do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) - -#define LOAD32L(x, y) \ - do { XMEMCPY(&(x), y, 4); } while(0) - -#define STORE64L(x, y) \ - do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ - (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ - (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) - -#define LOAD64L(x, y) \ - do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ - (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ - (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ - (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) - -#else /* 64-bit words then */ - -#define STORE32L(x, y) \ - do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) - -#define LOAD32L(x, y) \ - do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) - -#define STORE64L(x, y) \ - do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) - -#define LOAD64L(x, y) \ - do { XMEMCPY(&(x), y, 8); } while(0) - -#endif /* ENDIAN_64BITWORD */ - -#elif defined(ENDIAN_BIG) - -#define STORE32L(x, y) \ - do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) - -#define LOAD32L(x, y) \ - do { x = ((ulong32)((y)[3] & 255)<<24) | \ - ((ulong32)((y)[2] & 255)<<16) | \ - ((ulong32)((y)[1] & 255)<<8) | \ - ((ulong32)((y)[0] & 255)); } while(0) - -#define STORE64L(x, y) \ -do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ - (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ - (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) - -#define LOAD64L(x, y) \ -do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ - (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ - (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ - (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) - -#ifdef ENDIAN_32BITWORD - -#define STORE32H(x, y) \ - do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) - -#define LOAD32H(x, y) \ - do { XMEMCPY(&(x), y, 4); } while(0) - -#define STORE64H(x, y) \ - do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) - -#define LOAD64H(x, y) \ - do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ - (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ - (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ - (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0) - -#else /* 64-bit words then */ - -#define STORE32H(x, y) \ - do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) - -#define LOAD32H(x, y) \ - do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) - -#define STORE64H(x, y) \ - do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) - -#define LOAD64H(x, y) \ - do { XMEMCPY(&(x), y, 8); } while(0) - -#endif /* ENDIAN_64BITWORD */ -#endif /* ENDIAN_BIG */ - -#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ - ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) - - -/* 32-bit Rotates */ -#if defined(_MSC_VER) -#define LTC_ROx_BUILTIN - -/* instrinsic rotate */ -#include -#pragma intrinsic(_rotr,_rotl) -#define ROR(x,n) _rotr(x,n) -#define ROL(x,n) _rotl(x,n) -#define RORc(x,n) ROR(x,n) -#define ROLc(x,n) ROL(x,n) - -#elif defined(LTC_HAVE_ROTATE_BUILTIN) -#define LTC_ROx_BUILTIN - -#define ROR(x,n) __builtin_rotateright32(x,n) -#define ROL(x,n) __builtin_rotateleft32(x,n) -#define ROLc(x,n) ROL(x,n) -#define RORc(x,n) ROR(x,n) - -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) -#define LTC_ROx_ASM - -static inline ulong32 ROL(ulong32 word, int i) -{ - __asm__ ("roll %%cl,%0" - :"=r" (word) - :"0" (word),"c" (i)); - return word; -} - -static inline ulong32 ROR(ulong32 word, int i) -{ - __asm__ ("rorl %%cl,%0" - :"=r" (word) - :"0" (word),"c" (i)); - return word; -} - -#ifndef LTC_NO_ROLC - -#define ROLc(word,i) ({ \ - ulong32 LTC_TMPVAR(ROLc) = (word); \ - __asm__ ("roll %2, %0" : \ - "=r" (LTC_TMPVAR(ROLc)) : \ - "0" (LTC_TMPVAR(ROLc)), \ - "I" (i)); \ - LTC_TMPVAR(ROLc); \ - }) -#define RORc(word,i) ({ \ - ulong32 LTC_TMPVAR(RORc) = (word); \ - __asm__ ("rorl %2, %0" : \ - "=r" (LTC_TMPVAR(RORc)) : \ - "0" (LTC_TMPVAR(RORc)), \ - "I" (i)); \ - LTC_TMPVAR(RORc); \ - }) - -#else - -#define ROLc ROL -#define RORc ROR - -#endif - -#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) -#define LTC_ROx_ASM - -static inline ulong32 ROL(ulong32 word, int i) -{ - __asm__ ("rotlw %0,%0,%2" - :"=r" (word) - :"0" (word),"r" (i)); - return word; -} - -static inline ulong32 ROR(ulong32 word, int i) -{ - __asm__ ("rotlw %0,%0,%2" - :"=r" (word) - :"0" (word),"r" (32-i)); - return word; -} - -#ifndef LTC_NO_ROLC - -static inline ulong32 ROLc(ulong32 word, const int i) -{ - __asm__ ("rotlwi %0,%0,%2" - :"=r" (word) - :"0" (word),"I" (i)); - return word; -} - -static inline ulong32 RORc(ulong32 word, const int i) -{ - __asm__ ("rotrwi %0,%0,%2" - :"=r" (word) - :"0" (word),"I" (i)); - return word; -} - -#else - -#define ROLc ROL -#define RORc ROR - -#endif - - -#else - -/* rotates the hard way */ -#define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) -#define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) -#define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) -#define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) - -#endif - - -/* 64-bit Rotates */ -#if defined(_MSC_VER) - -/* instrinsic rotate */ -#include -#pragma intrinsic(_rotr64,_rotr64) -#define ROR64(x,n) _rotr64(x,n) -#define ROL64(x,n) _rotl64(x,n) -#define ROR64c(x,n) ROR64(x,n) -#define ROL64c(x,n) ROL64(x,n) - -#elif defined(LTC_HAVE_ROTATE_BUILTIN) - -#define ROR64(x,n) __builtin_rotateright64(x,n) -#define ROL64(x,n) __builtin_rotateleft64(x,n) -#define ROR64c(x,n) ROR64(x,n) -#define ROL64c(x,n) ROL64(x,n) - -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) - -static inline ulong64 ROL64(ulong64 word, int i) -{ - __asm__("rolq %%cl,%0" - :"=r" (word) - :"0" (word),"c" (i)); - return word; -} - -static inline ulong64 ROR64(ulong64 word, int i) -{ - __asm__("rorq %%cl,%0" - :"=r" (word) - :"0" (word),"c" (i)); - return word; -} - -#ifndef LTC_NO_ROLC - -#define ROL64c(word,i) ({ \ - ulong64 LTC_TMPVAR(ROL64c) = word; \ - __asm__ ("rolq %2, %0" : \ - "=r" (LTC_TMPVAR(ROL64c)) : \ - "0" (LTC_TMPVAR(ROL64c)), \ - "J" (i)); \ - LTC_TMPVAR(ROL64c); \ - }) -#define ROR64c(word,i) ({ \ - ulong64 LTC_TMPVAR(ROR64c) = word; \ - __asm__ ("rorq %2, %0" : \ - "=r" (LTC_TMPVAR(ROR64c)) : \ - "0" (LTC_TMPVAR(ROR64c)), \ - "J" (i)); \ - LTC_TMPVAR(ROR64c); \ - }) - -#else /* LTC_NO_ROLC */ - -#define ROL64c ROL64 -#define ROR64c ROR64 - -#endif - -#else /* Not x86_64 */ - -#define ROL64(x, y) \ - ( (((x)<<((ulong64)(y)&63)) | \ - (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) - -#define ROR64(x, y) \ - ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ - ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) - -#define ROL64c(x, y) \ - ( (((x)<<((ulong64)(y)&63)) | \ - (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) - -#define ROR64c(x, y) \ - ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ - ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) - -#endif - -#ifndef MAX - #define MAX(x, y) ( ((x)>(y))?(x):(y) ) -#endif - -#ifndef MIN - #define MIN(x, y) ( ((x)<(y))?(x):(y) ) -#endif - -#ifndef LTC_UNUSED_PARAM - #define LTC_UNUSED_PARAM(x) (void)(x) -#endif - -/* there is no snprintf before Visual C++ 2015 */ -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define snprintf _snprintf -#endif diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_math.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_math.h deleted file mode 100644 index 3ce45ac..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_math.h +++ /dev/null @@ -1,519 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** math functions **/ - -#define LTC_MP_LT -1 -#define LTC_MP_EQ 0 -#define LTC_MP_GT 1 - -#define LTC_MP_NO 0 -#define LTC_MP_YES 1 - -#ifndef LTC_MECC - typedef void ecc_point; -#endif - -#ifndef LTC_MRSA - typedef void rsa_key; -#endif - -#ifndef LTC_MILLER_RABIN_REPS - /* Number of rounds of the Miller-Rabin test - * "Reasonable values of reps are between 15 and 50." c.f. gmp doc of mpz_probab_prime_p() - * As of https://security.stackexchange.com/a/4546 we should use 40 rounds */ - #define LTC_MILLER_RABIN_REPS 40 -#endif - -int radix_to_bin(const void *in, int radix, void *out, unsigned long *len); - -/** math descriptor */ -typedef struct { - /** Name of the math provider */ - const char *name; - - /** Bits per digit, amount of bits must fit in an unsigned long */ - int bits_per_digit; - -/* ---- init/deinit functions ---- */ - - /** initialize a bignum - @param a The number to initialize - @return CRYPT_OK on success - */ - int (*init)(void **a); - - /** init copy - @param dst The number to initialize and write to - @param src The number to copy from - @return CRYPT_OK on success - */ - int (*init_copy)(void **dst, const void *src); - - /** deinit - @param a The number to free - @return CRYPT_OK on success - */ - void (*deinit)(void *a); - -/* ---- data movement ---- */ - - /** negate - @param src The number to negate - @param dst The destination - @return CRYPT_OK on success - */ - int (*neg)(const void *src, void *dst); - - /** copy - @param src The number to copy from - @param dst The number to write to - @return CRYPT_OK on success - */ - int (*copy)(const void *src, void *dst); - -/* ---- trivial low level functions ---- */ - - /** set small constant - @param a Number to write to - @param n Source upto bits_per_digit (actually meant for very small constants) - @return CRYPT_OK on success - */ - int (*set_int)(void *a, ltc_mp_digit n); - - /** get small constant - @param a Small number to read, - only fetches up to bits_per_digit from the number - @return The lower bits_per_digit of the integer (unsigned) - */ - unsigned long (*get_int)(const void *a); - - /** get digit n - @param a The number to read from - @param n The number of the digit to fetch - @return The bits_per_digit sized n'th digit of a - */ - ltc_mp_digit (*get_digit)(const void *a, int n); - - /** Get the number of digits that represent the number - @param a The number to count - @return The number of digits used to represent the number - */ - int (*get_digit_count)(const void *a); - - /** compare two integers - @param a The left side integer - @param b The right side integer - @return LTC_MP_LT if a < b, - LTC_MP_GT if a > b and - LTC_MP_EQ otherwise. (signed comparison) - */ - int (*compare)(const void *a, const void *b); - - /** compare against int - @param a The left side integer - @param b The right side integer (upto bits_per_digit) - @return LTC_MP_LT if a < b, - LTC_MP_GT if a > b and - LTC_MP_EQ otherwise. (signed comparison) - */ - int (*compare_d)(const void *a, ltc_mp_digit n); - - /** Count the number of bits used to represent the integer - @param a The integer to count - @return The number of bits required to represent the integer - */ - int (*count_bits)(const void * a); - - /** Count the number of LSB bits which are zero - @param a The integer to count - @return The number of contiguous zero LSB bits - */ - int (*count_lsb_bits)(const void *a); - - /** Compute a power of two - @param a The integer to store the power in - @param n The power of two you want to store (a = 2^n) - @return CRYPT_OK on success - */ - int (*twoexpt)(void *a , int n); - -/* ---- radix conversions ---- */ - - /** read ascii string - @param a The integer to store into - @param str The string to read - @param radix The radix the integer has been represented in (2-64) - @return CRYPT_OK on success - */ - int (*read_radix)(void *a, const char *str, int radix); - - /** write number to string - @param a The integer to store - @param str The destination for the string - @param radix The radix the integer is to be represented in (2-64) - @return CRYPT_OK on success - */ - int (*write_radix)(const void *a, char *str, int radix); - - /** get size as unsigned char string - @param a The integer to get the size (when stored in array of octets) - @return The length of the integer in octets - */ - unsigned long (*unsigned_size)(const void *a); - - /** store an integer as an array of octets - @param src The integer to store - @param dst The buffer to store the integer in - @return CRYPT_OK on success - */ - int (*unsigned_write)(const void *src, unsigned char *dst); - - /** read an array of octets and store as integer - @param dst The integer to load - @param src The array of octets - @param len The number of octets - @return CRYPT_OK on success - */ - int (*unsigned_read)( void *dst, - const unsigned char *src, - unsigned long len); - -/* ---- basic math ---- */ - - /** add two integers - @param a The first source integer - @param b The second source integer - @param c The destination of "a + b" - @return CRYPT_OK on success - */ - int (*add)(const void *a, const void *b, void *c); - - /** add two integers - @param a The first source integer - @param b The second source integer - (single digit of upto bits_per_digit in length) - @param c The destination of "a + b" - @return CRYPT_OK on success - */ - int (*addi)(const void *a, ltc_mp_digit b, void *c); - - /** subtract two integers - @param a The first source integer - @param b The second source integer - @param c The destination of "a - b" - @return CRYPT_OK on success - */ - int (*sub)(const void *a, const void *b, void *c); - - /** subtract two integers - @param a The first source integer - @param b The second source integer - (single digit of upto bits_per_digit in length) - @param c The destination of "a - b" - @return CRYPT_OK on success - */ - int (*subi)(const void *a, ltc_mp_digit b, void *c); - - /** multiply two integers - @param a The first source integer - @param b The second source integer - (single digit of upto bits_per_digit in length) - @param c The destination of "a * b" - @return CRYPT_OK on success - */ - int (*mul)(const void *a, const void *b, void *c); - - /** multiply two integers - @param a The first source integer - @param b The second source integer - (single digit of upto bits_per_digit in length) - @param c The destination of "a * b" - @return CRYPT_OK on success - */ - int (*muli)(const void *a, ltc_mp_digit b, void *c); - - /** Square an integer - @param a The integer to square - @param b The destination - @return CRYPT_OK on success - */ - int (*sqr)(const void *a, void *b); - - /** Square root (mod prime) - @param a The integer to compute square root mod prime from - @param b The prime - @param c The destination - @return CRYPT_OK on success - */ - int (*sqrtmod_prime)(const void *a, const void *b, void *c); - - /** Divide an integer - @param a The dividend - @param b The divisor - @param c The quotient (can be NULL to signify don't care) - @param d The remainder (can be NULL to signify don't care) - @return CRYPT_OK on success - */ - int (*mpdiv)(const void *a, const void *b, void *c, void *d); - - /** divide by two - @param a The integer to divide (shift right) - @param b The destination - @return CRYPT_OK on success - */ - int (*div_2)(const void *a, void *b); - - /** Get remainder (small value) - @param a The integer to reduce - @param b The modulus (upto bits_per_digit in length) - @param c The destination for the residue - @return CRYPT_OK on success - */ - int (*modi)(const void *a, ltc_mp_digit b, ltc_mp_digit *c); - - /** gcd - @param a The first integer - @param b The second integer - @param c The destination for (a, b) - @return CRYPT_OK on success - */ - int (*gcd)(const void *a, const void *b, void *c); - - /** lcm - @param a The first integer - @param b The second integer - @param c The destination for [a, b] - @return CRYPT_OK on success - */ - int (*lcm)(const void *a, const void *b, void *c); - - /** Modular multiplication - @param a The first source - @param b The second source - @param c The modulus - @param d The destination (a*b mod c) - @return CRYPT_OK on success - */ - int (*mulmod)(const void *a, const void *b, const void *c, void *d); - - /** Modular squaring - @param a The first source - @param b The modulus - @param c The destination (a*a mod b) - @return CRYPT_OK on success - */ - int (*sqrmod)(const void *a, const void *b, void *c); - - /** Modular inversion - @param a The value to invert - @param b The modulus - @param c The destination (1/a mod b) - @return CRYPT_OK on success - */ - int (*invmod)(const void *a, const void *b, void *c); - -/* ---- reduction ---- */ - - /** setup Montgomery - @param a The modulus - @param b The destination for the reduction digit - @return CRYPT_OK on success - */ - int (*montgomery_setup)(const void *a, void **b); - - /** get normalization value - @param a The destination for the normalization value - @param b The modulus - @return CRYPT_OK on success - */ - int (*montgomery_normalization)(void *a, const void *b); - - /** reduce a number - @param a The number [and dest] to reduce - @param b The modulus - @param c The value "b" from montgomery_setup() - @return CRYPT_OK on success - */ - int (*montgomery_reduce)(void *a, const void *b, void *c); - - /** clean up (frees memory) - @param a The value "b" from montgomery_setup() - @return CRYPT_OK on success - */ - void (*montgomery_deinit)(void *a); - -/* ---- exponentiation ---- */ - - /** Modular exponentiation - @param a The base integer - @param b The power (can be negative) integer - @param c The modulus integer - @param d The destination - @return CRYPT_OK on success - */ - int (*exptmod)(const void *a, const void *b, const void *c, void *d); - - /** Primality testing - @param a The integer to test - @param b The number of Miller-Rabin tests that shall be executed - @param c The destination of the result (FP_YES if prime) - @return CRYPT_OK on success - */ - int (*isprime)(const void *a, int b, int *c); - -/* ---- (optional) ecc point math ---- */ - - /** ECC GF(p) point multiplication (from the NIST curves) - @param k The integer to multiply the point by - @param G The point to multiply - @param R The destination for kG - @param a ECC curve parameter a - @param modulus The modulus for the field - @param map Boolean indicated whether to map back to affine or not - (can be ignored if you work in affine only) - @return CRYPT_OK on success - */ - int (*ecc_ptmul)( const void *k, - const ecc_point *G, - ecc_point *R, - const void *a, - const void *modulus, - int map); - - /** ECC GF(p) point addition - @param P The first point - @param Q The second point - @param R The destination of P + Q - @param ma The curve parameter "a" in montgomery form - @param modulus The modulus - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success - */ - int (*ecc_ptadd)(const ecc_point *P, - const ecc_point *Q, - ecc_point *R, - const void *ma, - const void *modulus, - void *mp); - - /** ECC GF(p) point double - @param P The first point - @param R The destination of 2P - @param ma The curve parameter "a" in montgomery form - @param modulus The modulus - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success - */ - int (*ecc_ptdbl)(const ecc_point *P, - ecc_point *R, - const void *ma, - const void *modulus, - void *mp); - - /** ECC mapping from projective to affine, - currently uses (x,y,z) => (x/z^2, y/z^3, 1) - @param P The point to map - @param modulus The modulus - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success - @remark The mapping can be different but keep in mind a - ecc_point only has three integers (x,y,z) so if - you use a different mapping you have to make it fit. - */ - int (*ecc_map)(ecc_point *P, const void *modulus, void *mp); - - /** Computes kA*A + kB*B = C using Shamir's Trick - @param A First point to multiply - @param kA What to multiple A by - @param B Second point to multiply - @param kB What to multiple B by - @param C [out] Destination point (can overlap with A or B) - @param ma The curve parameter "a" in montgomery form - @param modulus Modulus for curve - @return CRYPT_OK on success - */ - int (*ecc_mul2add)(const ecc_point *A, void *kA, - const ecc_point *B, void *kB, - ecc_point *C, - const void *ma, - const void *modulus); - -/* ---- (optional) rsa optimized math (for internal CRT) ---- */ - - /** RSA Key Generation - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param size The size of the key in octets - @param e The "e" value (public key). - e==65537 is a good choice - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful, upon error all allocated ram is freed - */ - int (*rsa_keygen)(prng_state *prng, - int wprng, - int size, - long e, - rsa_key *key); - - /** RSA exponentiation - @param in The octet array representing the base - @param inlen The length of the input - @param out The destination (to be stored in an octet array format) - @param outlen The length of the output buffer and the resulting size - (zero padded to the size of the modulus) - @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA - @param key The RSA key to use - @return CRYPT_OK on success - */ - int (*rsa_me)(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int which, - const rsa_key *key); - -/* ---- basic math continued ---- */ - - /** Modular addition - @param a The first source - @param b The second source - @param c The modulus - @param d The destination (a + b mod c) - @return CRYPT_OK on success - */ - int (*addmod)(const void *a, const void *b, const void *c, void *d); - - /** Modular substraction - @param a The first source - @param b The second source - @param c The modulus - @param d The destination (a - b mod c) - @return CRYPT_OK on success - */ - int (*submod)(const void *a, const void *b, const void *c, void *d); - -/* ---- misc stuff ---- */ - - /** Make a pseudo-random mpi - @param a The mpi to make random - @param size The desired length - @return CRYPT_OK on success - */ - int (*rand)(void *a, int size); -} ltc_math_descriptor; - -extern ltc_math_descriptor ltc_mp; - -int ltc_mp_init_multi(void **a, ...) LTC_NULL_TERMINATED; -void ltc_mp_deinit_multi(void *a, ...) LTC_NULL_TERMINATED; -void ltc_mp_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED; - -#ifdef LTM_DESC -extern const ltc_math_descriptor ltm_desc; -#endif - -#ifdef TFM_DESC -extern const ltc_math_descriptor tfm_desc; -#endif - -#ifdef GMP_DESC -extern const ltc_math_descriptor gmp_desc; -#endif diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_misc.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_misc.h deleted file mode 100644 index 1d25e16..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_misc.h +++ /dev/null @@ -1,213 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* ---- LTC_BASE64 Routines ---- */ -#ifdef LTC_BASE64 -int base64_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen); - -int base64_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int base64_strict_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int base64_sane_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -#endif - -#ifdef LTC_BASE64_URL -int base64url_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen); -int base64url_strict_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen); - -int base64url_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int base64url_strict_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int base64url_sane_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -#endif - -/* ---- BASE32 Routines ---- */ -#ifdef LTC_BASE32 -typedef enum { - BASE32_RFC4648 = 0, - BASE32_BASE32HEX = 1, - BASE32_ZBASE32 = 2, - BASE32_CROCKFORD = 3 -} base32_alphabet; -int base32_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - base32_alphabet id); -int base32_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - base32_alphabet id); -#endif - -/* ---- BASE16 Routines ---- */ -#ifdef LTC_BASE16 -int base16_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - unsigned int options); -int base16_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -#endif - -#ifdef LTC_BCRYPT -int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, - const unsigned char *salt, unsigned long salt_len, - unsigned int rounds, int hash_idx, - unsigned char *out, unsigned long *outlen); -#endif - -/* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ -#ifdef LTC_HKDF - -int hkdf_test(void); - -int hkdf_extract(int hash_idx, - const unsigned char *salt, unsigned long saltlen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -int hkdf_expand(int hash_idx, - const unsigned char *info, unsigned long infolen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen); - -int hkdf(int hash_idx, - const unsigned char *salt, unsigned long saltlen, - const unsigned char *info, unsigned long infolen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen); - -#endif /* LTC_HKDF */ - -/* ---- MEM routines ---- */ -int mem_neq(const void *a, const void *b, size_t len); -void zeromem(volatile void *out, size_t outlen); -void burn_stack(unsigned long len); - -const char *error_to_string(int err); - -extern const char *crypt_build_settings; - -/* ---- HMM ---- */ -int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED; - -/* ---- Dynamic language support ---- */ -int crypt_get_constant(const char* namein, int *valueout); -int crypt_list_all_constants(char *names_list, unsigned int *names_list_size); - -int crypt_get_size(const char* namein, unsigned int *sizeout); -int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size); - -#ifdef LTM_DESC -LTC_DEPRECATED(crypt_mp_init) void init_LTM(void); -#endif -#ifdef TFM_DESC -LTC_DEPRECATED(crypt_mp_init) void init_TFM(void); -#endif -#ifdef GMP_DESC -LTC_DEPRECATED(crypt_mp_init) void init_GMP(void); -#endif -int crypt_mp_init(const char* mpi); - -#ifdef LTC_ADLER32 -typedef struct adler32_state_s -{ - unsigned short s[2]; -} adler32_state; - -void adler32_init(adler32_state *ctx); -void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); -void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size); -int adler32_test(void); -#endif - -#ifdef LTC_CRC32 -typedef struct crc32_state_s -{ - ulong32 crc; -} crc32_state; - -void crc32_init(crc32_state *ctx); -void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length); -void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size); -int crc32_test(void); -#endif - - -#ifdef LTC_PADDING - -enum padding_type { - LTC_PAD_PKCS7 = 0x0000U, -#ifdef LTC_RNG_GET_BYTES - LTC_PAD_ISO_10126 = 0x1000U, -#endif - LTC_PAD_ANSI_X923 = 0x2000U, - LTC_PAD_SSH = 0x3000U, - /* The following padding modes don't contain the padding - * length as last byte of the padding. - */ - LTC_PAD_ONE_AND_ZERO = 0x8000U, - LTC_PAD_ZERO = 0x9000U, - LTC_PAD_ZERO_ALWAYS = 0xA000U, -}; - -int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode); -int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode); -#endif /* LTC_PADDING */ - -#ifdef LTC_PEM -/* Buffer-based API */ -int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx); -int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx); - -#ifdef LTC_SSH -/** - Callback function for each key in an `authorized_keys` file. - - This function takes ownership of the `k` parameter passed. - `k` must be free'd by calling `pka_key_destroy(&k)`. - - @param k Pointer to the PKA key. - @param comment Pointer to a string with the comment. - @param ctx The `ctx` pointer as passed to the read function. -*/ -typedef int (*ssh_authorized_key_cb)(ltc_pka_key *k, const char *comment, void *ctx); - -int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx); -int ssh_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx); -#endif /* LTC_SSH */ - -/* FILE*-based API */ -#ifndef LTC_NO_FILE -int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx); -int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx); -#ifdef LTC_SSH -int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx); -int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx); -#endif /* LTC_SSH */ -#endif /* LTC_NO_FILE */ - -#endif /* LTC_PEM */ - -#ifdef LTC_SSH -typedef enum ssh_data_type_ { - LTC_SSHDATA_EOL, - LTC_SSHDATA_BYTE, - LTC_SSHDATA_BOOLEAN, - LTC_SSHDATA_UINT32, - LTC_SSHDATA_UINT64, - LTC_SSHDATA_STRING, - LTC_SSHDATA_MPINT, - LTC_SSHDATA_NAMELIST, -} ssh_data_type; - -/* VA list handy helpers with tuples of */ -int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; -int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED; -#endif /* LTC_SSH */ - -int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pk.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pk.h deleted file mode 100644 index c4a2017..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pk.h +++ /dev/null @@ -1,936 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -typedef struct password_ctx { - /** - Callback function that is called when a password is required. - - Please be aware that the library takes ownership of the pointer that is - returned to the library via `str`. - The data will be zeroed and `free()`'d as soon as it isn't required anymore. - c.f. the documentation of the `free()` function pointer for details. - - @param str Pointer to pointer where the password will be stored. - @param len Pointer to the length of the password. - @param userdata `userdata` that was passed in the `password_ctx` struct. - @return CRYPT_OK on success - */ - int (*callback)(void **str, unsigned long *len, void *userdata); - /** - Optional free function to free the allocated buffer. - - At the point where the value returned by `callback()` is not required - anymore the library will free it by either calling this `free()` function - or `XFREE()` in case this `free()` function is set to `NULL`. - - @param str Pointer to the buffer to be free'd. - */ - void (*free)(void *str); - /** Opaque `userdata` pointer passed when the callback is called */ - void *userdata; -} password_ctx; - -/* ---- NUMBER THEORY ---- */ - -enum ltc_pka_id { - LTC_PKA_UNDEF = 0, - LTC_PKA_RSA, - LTC_PKA_DSA, - LTC_PKA_EC, - LTC_PKA_X25519, - LTC_PKA_ED25519, - LTC_PKA_DH, - LTC_PKA_NUM -}; - -enum public_key_type { - /* Refers to the public key */ - PK_PUBLIC = 0x0000, - /* Refers to the private key */ - PK_PRIVATE = 0x0001, - - /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */ - PK_STD = 0x1000, - /* Indicates compressed public ECC key */ - PK_COMPRESSED = 0x2000, - /* Indicates ECC key with the curve specified by OID */ - PK_CURVEOID = 0x4000 -}; - -int rand_prime(void *N, long len, prng_state *prng, int wprng); - -/* ---- RSA ---- */ -#ifdef LTC_MRSA - -/** RSA PKCS style key */ -typedef struct Rsa_key { - /** Type of key, PK_PRIVATE or PK_PUBLIC */ - int type; - /** The public exponent */ - void *e; - /** The private exponent */ - void *d; - /** The modulus */ - void *N; - /** The p factor of N */ - void *p; - /** The q factor of N */ - void *q; - /** The 1/q mod p CRT param */ - void *qP; - /** The d mod (p - 1) CRT param */ - void *dP; - /** The d mod (q - 1) CRT param */ - void *dQ; -} rsa_key; - -int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); -int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, - const unsigned char *e, unsigned long elen, rsa_key *key); -int rsa_get_size(const rsa_key *key); - -int rsa_exptmod(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int which, - const rsa_key *key); - -void rsa_free(rsa_key *key); - -/* These use PKCS #1 v2.0 padding */ -#define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \ - rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key) - -#define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \ - rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key) - -#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ - rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) - -#define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ - rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) - -#define rsa_sign_saltlen_get_max(hash_idx, key) \ - rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) - -/* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ -int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - prng_state *prng, int prng_idx, - int mgf_hash, int lparam_hash, - int padding, - const rsa_key *key); - -int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - int mgf_hash, int lparam_hash, - int padding, - int *stat, const rsa_key *key); - -int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - int padding, - prng_state *prng, int prng_idx, - int hash_idx, unsigned long saltlen, - const rsa_key *key); - -int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int padding, - int hash_idx, unsigned long saltlen, - int *stat, const rsa_key *key); - -int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); - -/* PKCS #1 import/export */ -int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key); -int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); - -int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key); -int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, rsa_key *key); - -int rsa_set_key(const unsigned char *N, unsigned long Nlen, - const unsigned char *e, unsigned long elen, - const unsigned char *d, unsigned long dlen, - rsa_key *key); -int rsa_set_factors(const unsigned char *p, unsigned long plen, - const unsigned char *q, unsigned long qlen, - rsa_key *key); -int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, - const unsigned char *dQ, unsigned long dQlen, - const unsigned char *qP, unsigned long qPlen, - rsa_key *key); -#endif - -/* ---- DH Routines ---- */ -#ifdef LTC_MDH - -typedef struct { - int type; - void *x; - void *y; - void *base; - void *prime; -} dh_key; - -int dh_get_groupsize(const dh_key *key); - -int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key); -int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); -int dh_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, dh_key *key); - -int dh_set_pg(const unsigned char *p, unsigned long plen, - const unsigned char *g, unsigned long glen, - dh_key *key); -int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key); -int dh_set_pg_groupsize(int groupsize, dh_key *key); - -int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key); -int dh_generate_key(prng_state *prng, int wprng, dh_key *key); - -int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, - unsigned char *out, unsigned long *outlen); - -void dh_free(dh_key *key); - -int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key); -#endif /* LTC_MDH */ - - -/* ---- ECC Routines ---- */ -#ifdef LTC_MECC - -/* size of our temp buffers for exported keys */ -#define ECC_BUF_SIZE 256 - -/* max private key size */ -#define ECC_MAXSIZE 66 - -/** Structure defines a GF(p) curve */ -typedef struct { - /** The prime that defines the field the curve is in (encoded in hex) */ - const char *prime; - - /** The fields A param (hex) */ - const char *A; - - /** The fields B param (hex) */ - const char *B; - - /** The order of the curve (hex) */ - const char *order; - - /** The x co-ordinate of the base point on the curve (hex) */ - const char *Gx; - - /** The y co-ordinate of the base point on the curve (hex) */ - const char *Gy; - - /** The co-factor */ - unsigned long cofactor; - - /** The OID */ - const char *OID; -} ltc_ecc_curve; - -/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ -typedef struct { - /** The x co-ordinate */ - void *x; - - /** The y co-ordinate */ - void *y; - - /** The z co-ordinate */ - void *z; -} ecc_point; - -/** ECC key's domain parameters */ -typedef struct { - /** The size of the curve in octets */ - int size; - /** The prime that defines the field the curve is in */ - void *prime; - /** The fields A param */ - void *A; - /** The fields B param */ - void *B; - /** The order of the curve */ - void *order; - /** The base point G on the curve */ - ecc_point base; - /** The co-factor */ - unsigned long cofactor; - /** The OID */ - unsigned long oid[16]; - unsigned long oidlen; -} ltc_ecc_dp; - -/** An ECC key */ -typedef struct { - /** Type of key, PK_PRIVATE or PK_PUBLIC */ - int type; - - /** Structure with domain parameters */ - ltc_ecc_dp dp; - - /** Structure with the public key */ - ecc_point pubkey; - - /** The private key */ - void *k; - - /** The hash algorithm to use when creating a signature. - * Setting this will enable RFC6979 compatible signature generation. - * The macro ECC_SET_RFC6979_HASH_ALG() is provided as a helper - * to set this.*/ - const char *rfc6979_hash_alg; -} ecc_key; - -#define ECC_SET_RFC6979_HASH_ALG(key, alg) do { \ - (key)->rfc6979_hash_alg = (alg); \ -} while(0) - -/** Formats of ECC signatures */ -typedef enum ecc_signature_type_ { - /* ASN.1 encoded, ANSI X9.62 */ - LTC_ECCSIG_ANSIX962 = 0x0, - /* raw R, S values */ - LTC_ECCSIG_RFC7518 = 0x1, - /* raw R, S, V (+27) values */ - LTC_ECCSIG_ETH27 = 0x2, - /* SSH + ECDSA signature format defined by RFC5656 */ - LTC_ECCSIG_RFC5656 = 0x3, -} ecc_signature_type; - -/** the ECC params provided */ -extern const ltc_ecc_curve ltc_ecc_curves[]; - -void ecc_sizes(int *low, int *high); -int ecc_get_size(const ecc_key *key); - -int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu); -int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key); -int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); -int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); -int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); -int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key); - -int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); -int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu); -void ecc_free(ecc_key *key); - -#if defined(LTC_DER) -int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); -int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); -int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); - -int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); -int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key); -int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, ecc_key *key); -int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key); -#endif - -int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen); -int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); -int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); - -int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, - unsigned char *out, unsigned long *outlen); - -#if defined(LTC_DER) -int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, - const ecc_key *key); - -int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const ecc_key *key); - -int ecc_sign_hash(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_verify_hash(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); -#endif - -int ecc_sign_hash_rfc7518(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_sign_hash_rfc7518_ex(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - int *recid, - const ecc_key *key); - -int ecc_verify_hash_rfc7518(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); - -#if defined(LTC_SSH) -int ecc_sign_hash_rfc5656(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_verify_hash_rfc5656(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); -#endif - -int ecc_sign_hash_eth27(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_verify_hash_eth27(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); - -int ecc_recover_key(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int recid, - ecc_signature_type sigformat, - ecc_key *key); - -#endif - -#ifdef LTC_CURVE25519 - -typedef struct { - /** The key type, PK_PRIVATE or PK_PUBLIC */ - enum public_key_type type; - - /** The PK-algorithm, LTC_PKA_ED25519 or LTC_PKA_X25519 */ - enum ltc_pka_id pka; - - /** The private key */ - unsigned char priv[32]; - - /** The public key */ - unsigned char pub[32]; -} curve25519_key; - - -/** Ed25519 Signature API */ -int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); - -int ed25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key); - -int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); -int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); -int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); -int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - curve25519_key *key); - -int ed25519_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const curve25519_key *private_key); -int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const unsigned char *ctx, unsigned long ctxlen, - const curve25519_key *private_key); -int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const unsigned char *ctx, unsigned long ctxlen, - const curve25519_key *private_key); -int ed25519_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - int *stat, - const curve25519_key *public_key); -int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - const unsigned char *ctx, unsigned long ctxlen, - int *stat, - const curve25519_key *public_key); -int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - const unsigned char *ctx, unsigned long ctxlen, - int *stat, - const curve25519_key *public_key); - -/** X25519 Key-Exchange API */ -int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); - -int x25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key); - -int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); -int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); -int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); -int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - curve25519_key *key); - -int x25519_shared_secret(const curve25519_key *private_key, - const curve25519_key *public_key, - unsigned char *out, unsigned long *outlen); - -#endif /* LTC_CURVE25519 */ - -#ifdef LTC_MDSA - -/* Max diff between group and modulus size in bytes (max case: L=8192bits, N=256bits) */ -#define LTC_MDSA_DELTA 992 - -/* Max DSA group size in bytes */ -#define LTC_MDSA_MAX_GROUP 64 - -/* Max DSA modulus size in bytes (the actual DSA size, max 8192 bits) */ -#define LTC_MDSA_MAX_MODULUS 1024 - -/** DSA key structure */ -typedef struct { - /** The key type, PK_PRIVATE or PK_PUBLIC */ - int type; - - /** The order of the sub-group used in octets */ - int qord; - - /** The generator */ - void *g; - - /** The prime used to generate the sub-group */ - void *q; - - /** The large prime that generats the field the contains the sub-group */ - void *p; - - /** The private key */ - void *x; - - /** The public key */ - void *y; -} dsa_key; - -int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); - -int dsa_set_pqg(const unsigned char *p, unsigned long plen, - const unsigned char *q, unsigned long qlen, - const unsigned char *g, unsigned long glen, - dsa_key *key); -int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key); -int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); - -int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key); -int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key); - -void dsa_free(dsa_key *key); - -int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, - void *r, void *s, - prng_state *prng, int wprng, const dsa_key *key); - -int dsa_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const dsa_key *key); - -int dsa_verify_hash_raw( void *r, void *s, - const unsigned char *hash, unsigned long hashlen, - int *stat, const dsa_key *key); - -int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const dsa_key *key); - -int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, - const dsa_key *key); - -int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const dsa_key *key); - -int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); -int dsa_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - dsa_key *key); -int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key); -int dsa_verify_key(const dsa_key *key, int *stat); -int dsa_shared_secret(void *private_key, void *base, - const dsa_key *public_key, - unsigned char *out, unsigned long *outlen); -#endif /* LTC_MDSA */ - -/* - * LibTomCrypt tagged-union for holding a Public Key - */ - -typedef struct { - union { -#ifdef LTC_CURVE25519 - curve25519_key x25519; - curve25519_key ed25519; -#endif -#ifdef LTC_MDH - dh_key dh; -#endif -#ifdef LTC_MDSA - dsa_key dsa; -#endif -#ifdef LTC_MECC - ecc_key ecc; -#endif -#ifdef LTC_MRSA - rsa_key rsa; -#endif - char dummy; - } u; - enum ltc_pka_id id; -} ltc_pka_key; - -void pka_key_free(ltc_pka_key *key); -void pka_key_destroy(ltc_pka_key **key); - -#ifdef LTC_DER -/* DER handling */ - -typedef enum ltc_asn1_type_ { - /* 0 */ - LTC_ASN1_EOL, - LTC_ASN1_BOOLEAN, - LTC_ASN1_INTEGER, - LTC_ASN1_SHORT_INTEGER, - LTC_ASN1_BIT_STRING, - /* 5 */ - LTC_ASN1_OCTET_STRING, - LTC_ASN1_NULL, - LTC_ASN1_OBJECT_IDENTIFIER, - LTC_ASN1_IA5_STRING, - LTC_ASN1_PRINTABLE_STRING, - /* 10 */ - LTC_ASN1_UTF8_STRING, - LTC_ASN1_UTCTIME, - LTC_ASN1_CHOICE, - LTC_ASN1_SEQUENCE, - LTC_ASN1_SET, - /* 15 */ - LTC_ASN1_SETOF, - LTC_ASN1_RAW_BIT_STRING, - LTC_ASN1_TELETEX_STRING, - LTC_ASN1_GENERALIZEDTIME, - LTC_ASN1_CUSTOM_TYPE, -} ltc_asn1_type; - -typedef enum { - LTC_ASN1_CL_UNIVERSAL = 0x0, - LTC_ASN1_CL_APPLICATION = 0x1, - LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2, - LTC_ASN1_CL_PRIVATE = 0x3, -} ltc_asn1_class; - -typedef enum { - LTC_ASN1_PC_PRIMITIVE = 0x0, - LTC_ASN1_PC_CONSTRUCTED = 0x1, -} ltc_asn1_pc; - -/** A LTC ASN.1 list type */ -typedef struct ltc_asn1_list_ { - /** The LTC ASN.1 enumerated type identifier */ - ltc_asn1_type type; - /** The data to encode or place for decoding */ - void *data; - /** The size of the input or resulting output */ - unsigned long size; - /** The used flag - * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made - * 2. This is used by the ASN.1 decoder to indicate if an element is used - * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */ - int used; - /** Flag used to indicate optional items in ASN.1 sequences */ - int optional; - /** ASN.1 identifier */ - ltc_asn1_class klass; - ltc_asn1_pc pc; - ulong64 tag; - /** prev/next entry in the list */ - struct ltc_asn1_list_ *prev, *next, *child, *parent; -} ltc_asn1_list; - -#define LTC_SET_ASN1(list, index, Type, Data, Size) \ - do { \ - int LTC_TMPVAR(SA) = (index); \ - ltc_asn1_list *LTC_TMPVAR(SA_list) = (list); \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].type = (Type); \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].data = (void*)(Data); \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].size = (Size); \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].used = 0; \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].optional = 0; \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].klass = 0; \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].pc = 0; \ - LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].tag = 0; \ - } while (0) - -#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ - do { \ - int LTC_TMPVAR(SAI) = (index); \ - ltc_asn1_list *LTC_TMPVAR(SAI_list) = (list); \ - LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].type = LTC_ASN1_CUSTOM_TYPE; \ - LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].klass = (Class); \ - LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].pc = (Pc); \ - LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag); \ - } while (0) - -#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ - do { \ - int LTC_TMPVAR(SACC) = (index); \ - LTC_SET_ASN1(list, LTC_TMPVAR(SACC), LTC_ASN1_CUSTOM_TYPE, Data, 1); \ - LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACC), Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ - } while (0) - -#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ - do { \ - int LTC_TMPVAR(SACP) = (index); \ - LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size); \ - LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ - list[LTC_TMPVAR(SACP)].used = (int)(Type); \ - } while (0) - -extern const char* der_asn1_class_to_string_map[]; -extern const unsigned long der_asn1_class_to_string_map_sz; - -extern const char* der_asn1_pc_to_string_map[]; -extern const unsigned long der_asn1_pc_to_string_map_sz; - -extern const char* der_asn1_tag_to_string_map[]; -extern const unsigned long der_asn1_tag_to_string_map_sz; - -/* SEQUENCE */ -int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int type_of); - -#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) - -/** The supported bitmap for all the - * decoders with a `flags` argument. - */ -enum ltc_der_seq { - LTC_DER_SEQ_ZERO = 0x0u, - - /** Bit0 - [0]=Unordered (SET or SETOF) - * [1]=Ordered (SEQUENCE) */ - LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO, - LTC_DER_SEQ_ORDERED = 0x1u, - - /** Bit1 - [0]=Relaxed - * [1]=Strict */ - LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO, - LTC_DER_SEQ_STRICT = 0x2u, - - /** Alternative naming */ - LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED, - LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED, -}; - -int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *list, unsigned long outlen, unsigned int flags); - -#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED) -#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT) - -int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, - unsigned long *outlen); - - -/* Custom-types */ -int der_encode_custom_type(const ltc_asn1_list *root, - unsigned char *out, unsigned long *outlen); - -int der_decode_custom_type(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *root); - -int der_length_custom_type(const ltc_asn1_list *root, - unsigned long *outlen, - unsigned long *payloadlen); - -/* SET */ -#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET) -#define der_length_set der_length_sequence -int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -/* VA list handy helpers with triplets of */ -int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; -int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; - -/* FLEXI DECODER handle unknown list decoder */ -int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); -#define der_free_sequence_flexi der_sequence_free -void der_sequence_free(ltc_asn1_list *in); -void der_sequence_shrink(ltc_asn1_list *in); - -/* BOOLEAN */ -int der_length_boolean(unsigned long *outlen); -int der_encode_boolean(int in, - unsigned char *out, unsigned long *outlen); -int der_decode_boolean(const unsigned char *in, unsigned long inlen, - int *out); -/* INTEGER */ -int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); -int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); -int der_length_integer(void *num, unsigned long *outlen); - -/* INTEGER -- handy for 0..2^32-1 values */ -int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); -int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); -int der_length_short_integer(unsigned long num, unsigned long *outlen); - -/* BIT STRING */ -int der_encode_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_decode_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_length_bit_string(unsigned long nbits, unsigned long *outlen); - -/* OCTET STRING */ -int der_encode_octet_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_decode_octet_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_length_octet_string(unsigned long noctets, unsigned long *outlen); - -/* OBJECT IDENTIFIER */ -int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, - unsigned char *out, unsigned long *outlen); -int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, - unsigned long *words, unsigned long *outlen); -int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen); - -/* IA5 STRING */ -int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); - -/* TELETEX STRING */ -int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); - -/* PRINTABLE STRING */ -int der_encode_printable_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_decode_printable_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); -int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); - -/* UTF-8 */ -#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(__WCHAR_MAX__) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) - #if defined(__WCHAR_MAX__) - #define LTC_WCHAR_MAX __WCHAR_MAX__ - #else - #include - #define LTC_WCHAR_MAX WCHAR_MAX - #endif -/* please note that it might happen that LTC_WCHAR_MAX is undefined */ -#else - typedef ulong32 wchar_t; - #define LTC_WCHAR_MAX 0xFFFFFFFF -#endif - -int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, - wchar_t *out, unsigned long *outlen); -int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); - - -/* CHOICE */ -int der_decode_choice(const unsigned char *in, unsigned long *inlen, - ltc_asn1_list *list, unsigned long outlen); - -/* UTCTime */ -typedef struct { - unsigned YY, /* year */ - MM, /* month */ - DD, /* day */ - hh, /* hour */ - mm, /* minute */ - ss, /* second */ - off_dir, /* timezone offset direction 0 == +, 1 == - */ - off_hh, /* timezone offset hours */ - off_mm; /* timezone offset minutes */ -} ltc_utctime; - -int der_encode_utctime(const ltc_utctime *utctime, - unsigned char *out, unsigned long *outlen); - -int der_decode_utctime(const unsigned char *in, unsigned long *inlen, - ltc_utctime *out); - -int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen); - -/* GeneralizedTime */ -typedef struct { - unsigned YYYY, /* year */ - MM, /* month */ - DD, /* day */ - hh, /* hour */ - mm, /* minute */ - ss, /* second */ - fs, /* fractional seconds */ - off_dir, /* timezone offset direction 0 == +, 1 == - */ - off_hh, /* timezone offset hours */ - off_mm; /* timezone offset minutes */ -} ltc_generalizedtime; - -int der_encode_generalizedtime(const ltc_generalizedtime *gtime, - unsigned char *out, unsigned long *outlen); - -int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, - ltc_generalizedtime *out); - -int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen); - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pkcs.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pkcs.h deleted file mode 100644 index cca013c..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_pkcs.h +++ /dev/null @@ -1,101 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* PKCS Header Info */ - -/* ===> PKCS #1 -- RSA Cryptography <=== */ -#ifdef LTC_PKCS_1 - -enum ltc_pkcs_1_v1_5_blocks -{ - LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ - LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ -}; - -enum ltc_pkcs_1_paddings -{ - LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ - LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ - LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */ - LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ -}; - -int pkcs_1_mgf1( int hash_idx, - const unsigned char *seed, unsigned long seedlen, - unsigned char *mask, unsigned long masklen); - -int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); -int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); - -/* *** v1.5 padding */ -int pkcs_1_v1_5_encode(const unsigned char *msg, - unsigned long msglen, - int block_type, - unsigned long modulus_bitlen, - prng_state *prng, - int prng_idx, - unsigned char *out, - unsigned long *outlen); - -int pkcs_1_v1_5_decode(const unsigned char *msg, - unsigned long msglen, - int block_type, - unsigned long modulus_bitlen, - unsigned char *out, - unsigned long *outlen, - int *is_valid); - -/* *** v2.1 padding */ -int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, prng_state *prng, - int prng_idx, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen); - -int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen, - int *res); - -int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, prng_state *prng, - int prng_idx, int hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen); - -int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, - unsigned long modulus_bitlen, int *res); - -#endif /* LTC_PKCS_1 */ - -/* ===> PKCS #5 -- Password Based Cryptography <=== */ -#ifdef LTC_PKCS_5 - -/* Algorithm #1 (PBKDF1) */ -int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, - const unsigned char *salt, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen); - -/* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys. - Compatible with EVP_BytesToKey() */ -int pkcs_5_alg1_openssl(const unsigned char *password, - unsigned long password_len, - const unsigned char *salt, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen); - -/* Algorithm #2 (PBKDF2) */ -int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen); - -int pkcs_5_test (void); -#endif /* LTC_PKCS_5 */ - diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_private.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_private.h deleted file mode 100644 index 7069b16..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_private.h +++ /dev/null @@ -1,744 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt.h" -#include - -#ifndef TOMCRYPT_PRIVATE_H_ -#define TOMCRYPT_PRIVATE_H_ - -/* - * Internal Macros - */ -/* Static assertion */ -#define LTC_STATIC_ASSERT(msg, cond) typedef char ltc_static_assert_##msg[(cond) ? 1 : -1]; - -#define LTC_PAD_MASK (0xF000U) - -/* only real 64bit, not ILP32 */ -#if defined(ENDIAN_64BITWORD) && !defined(ENDIAN_64BITWORD_ILP32) - #define CONSTPTR(n) CONST64(n) -#else - #define CONSTPTR(n) n ## uL -#endif - -LTC_STATIC_ASSERT(correct_CONSTPTR_size, sizeof(CONSTPTR(1)) == sizeof(void*)) - -/* Poor-man's `uintptr_t` since we can't use stdint.h - * c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */ -typedef size_t ltc_uintptr; - -LTC_STATIC_ASSERT(correct_ltc_uintptr_size, sizeof(ltc_uintptr) == sizeof(void*)) - -/* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address. - * Make sure that the buffer that is passed is huge enough. - */ -#define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&((unsigned char*)(buf))[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1))))) - -#define LTC_OID_MAX_STRLEN 256 - -/* `NULL` as defined by the standard is not guaranteed to be of a pointer - * type. In order to make sure that in vararg API's a pointer type is used, - * define our own version and use that one internally. - */ -#ifndef LTC_NULL - #define LTC_NULL ((void *)0) -#endif - -#define LTC_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) - -/* - * Internal Enums - */ - -enum ltc_oid_id { - LTC_OID_UNDEF, - LTC_OID_RSA, - LTC_OID_DSA, - LTC_OID_EC, - LTC_OID_EC_PRIMEF, - LTC_OID_X25519, - LTC_OID_ED25519, - LTC_OID_DH, - LTC_OID_NUM -}; - -/* - * Internal Types - */ - -typedef struct { - int size; - const char *name, *base, *prime; -} ltc_dh_set_type; - - -struct password { - /* usually a `char*` but could also contain binary data - * so use a `void*` + length to be on the safe side. - */ - void *pw; - unsigned long l; -}; - -typedef int (*fn_kdf_t)(const struct password *pwd, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen); - -#if defined(LTC_PBES) -typedef struct { - /* KDF */ - fn_kdf_t kdf; - /* Hash or HMAC */ - const char* h; - /* cipher */ - const char* c; - unsigned long keylen; - /* not used for pbkdf2 */ - unsigned long blocklen; -} pbes_properties; - -typedef struct -{ - pbes_properties type; - struct password pw; - ltc_asn1_list *enc_data; - ltc_asn1_list *salt; - ltc_asn1_list *iv; - unsigned long iterations; - /* only used for RC2 */ - unsigned long key_bits; -} pbes_arg; - -typedef struct { - const pbes_properties *data; - const char *oid; -} oid_to_pbes; -#endif - -/* - * Internal functions - */ - - -/* tomcrypt_cipher.h */ - -int ecb_encrypt_block(const unsigned char *pt, unsigned char *ct, const symmetric_ECB *ecb); -int ecb_decrypt_block(const unsigned char *ct, unsigned char *pt, const symmetric_ECB *ecb); - - -void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); -int blowfish_expand(const unsigned char *key, int keylen, - const unsigned char *data, int datalen, - symmetric_key *skey); -int blowfish_setup_with_data(const unsigned char *key, int keylen, - const unsigned char *data, int datalen, - symmetric_key *skey); - -/* tomcrypt_hash.h */ - -/* a simple macro for making hash "process" functions */ -#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ -int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ -{ \ - unsigned long n; \ - int err; \ - LTC_ARGCHK(md != NULL); \ - LTC_ARGCHK(in != NULL); \ - if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ - return CRYPT_INVALID_ARG; \ - } \ - if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \ - || ((inlen * 8) < inlen)) { \ - return CRYPT_HASH_OVERFLOW; \ - } \ - while (inlen > 0) { \ - if (md-> state_var .curlen == 0 && inlen >= block_size) { \ - if ((err = compress_name (md, in)) != CRYPT_OK) { \ - return err; \ - } \ - md-> state_var .length += block_size * 8; \ - in += block_size; \ - inlen -= block_size; \ - } else { \ - n = MIN(inlen, (block_size - md-> state_var .curlen)); \ - XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ - md-> state_var .curlen += n; \ - in += n; \ - inlen -= n; \ - if (md-> state_var .curlen == block_size) { \ - if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ - return err; \ - } \ - md-> state_var .length += 8*block_size; \ - md-> state_var .curlen = 0; \ - } \ - } \ - } \ - return CRYPT_OK; \ -} - - -/* tomcrypt_mac.h */ - -int ocb3_int_ntz(unsigned long x); -void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len); - -#ifdef LTC_OMAC -int omac_vprocess(omac_state *omac, const unsigned char *in, unsigned long inlen, va_list args); -#endif -/* tomcrypt_math.h */ - -#if !defined(DESC_DEF_ONLY) - -#define LTC_MP_DIGIT_BIT ltc_mp.bits_per_digit - -/* some handy macros */ -#define ltc_mp_init(a) ltc_mp.init(a) -#define ltc_mp_clear(a) ltc_mp.deinit(a) -#define ltc_mp_init_copy(a, b) ltc_mp.init_copy(a, b) - -#define ltc_mp_neg(a, b) ltc_mp.neg(a, b) -#define ltc_mp_copy(a, b) ltc_mp.copy(a, b) - -#define ltc_mp_set(a, b) ltc_mp.set_int(a, b) -#define ltc_mp_set_int(a, b) ltc_mp.set_int(a, b) -#define ltc_mp_get_int(a) ltc_mp.get_int(a) -#define ltc_mp_get_digit(a, n) ltc_mp.get_digit(a, n) -#define ltc_mp_get_digit_count(a) ltc_mp.get_digit_count(a) -#define ltc_mp_cmp(a, b) ltc_mp.compare(a, b) -#define ltc_mp_cmp_d(a, b) ltc_mp.compare_d(a, b) -#define ltc_mp_count_bits(a) ltc_mp.count_bits(a) -#define ltc_mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) -#define ltc_mp_2expt(a, b) ltc_mp.twoexpt(a, b) - -#define ltc_mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) -#define ltc_mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) -#define ltc_mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) -#define ltc_mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) -#define ltc_mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) - -#define ltc_mp_add(a, b, c) ltc_mp.add(a, b, c) -#define ltc_mp_add_d(a, b, c) ltc_mp.addi(a, b, c) -#define ltc_mp_sub(a, b, c) ltc_mp.sub(a, b, c) -#define ltc_mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) -#define ltc_mp_mul(a, b, c) ltc_mp.mul(a, b, c) -#define ltc_mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) -#define ltc_mp_sqr(a, b) ltc_mp.sqr(a, b) -#define ltc_mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c) -#define ltc_mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) -#define ltc_mp_div_2(a, b) ltc_mp.div_2(a, b) -#define ltc_mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) -#define ltc_mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) -#define ltc_mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) -#define ltc_mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) - -#define ltc_mp_addmod(a, b, c, d) ltc_mp.addmod(a, b, c, d) -#define ltc_mp_submod(a, b, c, d) ltc_mp.submod(a, b, c, d) -#define ltc_mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) -#define ltc_mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) -#define ltc_mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) - -#define ltc_mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) -#define ltc_mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) -#define ltc_mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) -#define ltc_mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) - -#define ltc_mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) -#define ltc_mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, b, c) - -#define ltc_mp_iszero(a) (ltc_mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) -#define ltc_mp_isodd(a) (ltc_mp_get_digit_count(a) > 0 ? (ltc_mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) -#define ltc_mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0) - -#define ltc_mp_tohex(a, b) ltc_mp_toradix(a, b, 16) - -#define ltc_mp_rand(a, b) ltc_mp.rand(a, b) - -#endif - - -/* tomcrypt_misc.h */ - -typedef enum { - /** Use `\r\n` as line separator */ - BASE64_PEM_CRLF = 1, - /** Create output with 72 chars line length */ - BASE64_PEM_SSH = 2, -} base64_pem_flags; - -int base64_encode_pem(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - unsigned int flags); - -/* PEM related */ - -#ifdef LTC_PEM -enum cipher_mode { - cm_modes = 0x00ff, - cm_flags = 0xff00, - /* Flags */ - cm_openssh = 0x0100, - cm_1bit = 0x0200, - cm_8bit = 0x0400, - /* Modes */ - cm_none = 0x0000, - cm_cbc = 0x0001, - cm_cfb = 0x0002, - cm_ctr = 0x0003, - cm_ofb = 0x0004, - cm_stream = 0x0005, - cm_gcm = 0x0006, - cm_cfb1 = cm_cfb | cm_1bit, - cm_cfb8 = cm_cfb | cm_8bit, - cm_stream_openssh = cm_stream | cm_openssh, -}; - -struct blockcipher_info { - const char *name; - const char *algo; - unsigned long keylen; - enum cipher_mode mode; - /* should use `MAXBLOCKSIZE` here, but all supported - * blockciphers require max 16 bytes IV */ - char iv[16 * 2 + 1]; -}; - -struct str { - char *p; - unsigned long len; -}; - -#define SET_STR(n, s) n.p = s, n.len = XSTRLEN(s) -#define SET_CSTR(n, s) n.p = (char*)s, n.len = (sizeof s) - 1 -#define COPY_STR(n, s, l) do { XMEMCPY(n.p, s, l); n.len = l; } while(0) -#define RESET_STR(n) do { n.p = NULL; n.len = 0; } while(0) - -enum more_headers { - no, - yes, - maybe -}; - -enum pem_flags { - pf_encrypted = 0x01u, - pf_pkcs8 = 0x02u, - pf_public = 0x04u, - pf_x509 = 0x08u, - pf_encrypted_pkcs8 = pf_encrypted | pf_pkcs8, -}; - -struct pem_header_id { - struct str start, end; - enum more_headers has_more_headers; - enum pem_flags flags; - enum ltc_pka_id pka; - int (*decrypt)(void *, unsigned long *, void *); -}; - -struct pem_headers { - const struct pem_header_id *id; - int encrypted; - struct blockcipher_info info; - struct password *pw; -}; - -struct bufp { - /* `end` points to one byte after the last - * element of the allocated buffer - */ - char *start, *work, *end; -}; - -#define SET_BUFP(n, d, l) n.start = (char*)d, n.work = (char*)d, n.end = (char*)d + l + 1 - -struct get_char { - int (*get)(struct get_char*); - union { -#ifndef LTC_NO_FILE - FILE *f; -#endif /* LTC_NO_FILE */ - struct bufp buf; - } data; - struct str unget_buf; - char unget_buf_[LTC_PEM_DECODE_BUFSZ]; - int prev_get; -}; -#endif - -/* others */ - -void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz); -void password_free(struct password *pw, const struct password_ctx *ctx); - -#if defined(LTC_PBES) -int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size); - -int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res); -int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res); -#endif - -#ifdef LTC_PEM -int pem_decrypt(unsigned char *data, unsigned long *datalen, - unsigned char *key, unsigned long keylen, - unsigned char *iv, unsigned long ivlen, - unsigned char *tag, unsigned long taglen, - const struct blockcipher_info *info, - enum padding_type padding); -#ifndef LTC_NO_FILE -int pem_get_char_from_file(struct get_char *g); -#endif /* LTC_NO_FILE */ -int pem_get_char_from_buf(struct get_char *g); -int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, struct get_char *g); -#endif - -/* tomcrypt_pk.h */ - -int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng); -int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng); - -int pk_get_oid(enum ltc_oid_id id, const char **st); -int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka); -int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid); -#ifdef LTC_DER -int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id); -#endif -int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen); -int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen); - -int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size); - -/* ---- DH Routines ---- */ -#ifdef LTC_MRSA -int rsa_init(rsa_key *key); -void rsa_shrink_key(rsa_key *key); -int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, - rsa_key *key); /* used by op-tee */ -int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); -int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key); -#endif /* LTC_MRSA */ - -/* ---- DH Routines ---- */ -#ifdef LTC_MDH -extern const ltc_dh_set_type ltc_dh_sets[]; - -int dh_init(dh_key *key); -int dh_check_pubkey(const dh_key *key); -int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key); -#endif /* LTC_MDH */ - -/* ---- ECC Routines ---- */ -#ifdef LTC_MECC -int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); -int ecc_copy_curve(const ecc_key *srckey, ecc_key *key); -int ecc_set_curve_by_size(int size, ecc_key *key); -int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key); -#ifdef LTC_DER -int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key); -#endif -int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); -int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key); - -int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, - void *r, void *s, prng_state *prng, int wprng, - int *recid, const ecc_key *key); - -int ecc_verify_hash_internal(void *r, void *s, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key); - -int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, ecc_key *key); - -#ifdef LTC_SSH -int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); -#endif - -/* low level functions */ -ecc_point *ltc_ecc_new_point(void); -void ltc_ecc_del_point(ecc_point *p); -int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p); -int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst); -int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y); -int ltc_ecc_is_point_at_infinity(const ecc_point *P, const void *modulus, int *retval); -int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); -int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); -int ltc_ecc_verify_key(const ecc_key *key); - -/* point ops (mp == montgomery digit) */ -#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) -/* R = 2P */ -int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, - const void *ma, const void *modulus, void *mp); - -/* R = P + Q */ -int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, - const void *ma, const void *modulus, void *mp); -#endif - -#if defined(LTC_MECC_FP) -/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ -int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); - -/* functions for saving/loading/freeing/adding to fixed point cache */ -int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); -int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); -void ltc_ecc_fp_free(void); -int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); - -/* lock/unlock all points currently in fixed point cache */ -void ltc_ecc_fp_tablelock(int lock); -#endif - -/* R = kG */ -int ltc_ecc_mulmod(const void *k, const ecc_point *G, ecc_point *R, - const void *a, const void *modulus, int map); - -#ifdef LTC_ECC_SHAMIR -/* kA*A + kB*B = C */ -int ltc_ecc_mul2add(const ecc_point *A, void *kA, - const ecc_point *B, void *kB, - ecc_point *C, - const void *ma, - const void *modulus); - -#ifdef LTC_MECC_FP -/* Shamir's trick with optimized point multiplication using fixed point cache */ -int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, - const ecc_point *B, void *kB, - ecc_point *C, - const void *ma, - const void *modulus); -#endif - -#endif - - -/* map P to affine from projective */ -int ltc_ecc_map(ecc_point *P, const void *modulus, void *mp); -#endif /* LTC_MECC */ - -#ifdef LTC_MDSA -int dsa_int_init(dsa_key *key); -int dsa_int_validate(const dsa_key *key, int *stat); -int dsa_int_validate_xy(const dsa_key *key, int *stat); -int dsa_int_validate_pqg(const dsa_key *key, int *stat); -int dsa_int_validate_primes(const dsa_key *key, int *stat); -int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key); -int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key); -#endif /* LTC_MDSA */ - - -#ifdef LTC_CURVE25519 - -int tweetnacl_crypto_sign( - unsigned char *sm,unsigned long long *smlen, - const unsigned char *m,unsigned long long mlen, - const unsigned char *sk,const unsigned char *pk, - const unsigned char *ctx,unsigned long long cs); -int tweetnacl_crypto_sign_open( - int *stat, - unsigned char *m,unsigned long long *mlen, - const unsigned char *sm,unsigned long long smlen, - const unsigned char *ctx, unsigned long long cs, - const unsigned char *pk); -int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk); -int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk); -int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); -int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n); -int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen); - -int ed25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - curve25519_key *key); -int x25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - curve25519_key *key); - -int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - enum ltc_oid_id id, - curve25519_key *key); -int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - enum ltc_oid_id id, - curve25519_key *key); -int ec25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key); -int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, - unsigned char flag, - const unsigned char *ctx, unsigned long ctxlen); -#endif /* LTC_CURVE25519 */ - -#ifdef LTC_DER - -#define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t))) - -/* DER handling */ -int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *root, - ltc_asn1_list *list, unsigned long outlen, unsigned int flags); - -int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen); -int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id); -int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen); - -int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen); -int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen); -int der_length_asn1_length(unsigned long len, unsigned long *outlen); - -int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, - unsigned long *outlen, unsigned long *payloadlen); - -int der_length_object_identifier_full(const unsigned long *words, unsigned long nwords, - unsigned long *outlen, unsigned long *datalen); - -int der_ia5_char_encode(int c); -int der_ia5_value_decode(int v); - -int der_printable_char_encode(int c); -int der_printable_value_decode(int v); - -unsigned long der_utf8_charsize(const wchar_t c); - -typedef struct { - ltc_asn1_type t; - ltc_asn1_list **pp; -} der_flexi_check; - -#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \ - do { \ - int LTC_SDFC_temp##__LINE__ = (index); \ - list[LTC_SDFC_temp##__LINE__].t = Type; \ - list[LTC_SDFC_temp##__LINE__].pp = P; \ - } while (0) - - -extern const ltc_asn1_type der_asn1_tag_to_type_map[]; -extern const unsigned long der_asn1_tag_to_type_map_sz; - -extern const int der_asn1_type_to_identifier_map[]; -extern const unsigned long der_asn1_type_to_identifier_map_sz; - -int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check); - -int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) - LTC_NULL_TERMINATED; - -int der_teletex_char_encode(int c); -int der_teletex_value_decode(int v); - -int der_utf8_valid_char(const wchar_t c); - -typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx); - -int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, - enum ltc_oid_id algorithm, ltc_asn1_type param_type, - ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx); -int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki); - -/* SUBJECT PUBLIC KEY INFO */ -int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, - enum ltc_oid_id algorithm, const void* public_key, unsigned long public_key_len, - ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); - -int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, - enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len, - ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); - -int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); - -#endif /* LTC_DER */ - -/* tomcrypt_pkcs.h */ - -#ifdef LTC_PKCS_8 - -/* Public-Key Cryptography Standards (PKCS) #8: - * Private-Key Information Syntax Specification Version 1.2 - * https://tools.ietf.org/html/rfc5208 - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * where: - * - Version ::= INTEGER - * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * - PrivateKey ::= OCTET STRING - * - Attributes ::= SET OF Attribute - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData } - * where: - * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - EncryptedData ::= OCTET STRING - */ - -int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - ltc_asn1_list **decoded_list); - -int pkcs8_get_children(const ltc_asn1_list *decoded_list, enum ltc_oid_id *pka, - ltc_asn1_list **alg_id, ltc_asn1_list **priv_key); - -#endif /* LTC_PKCS_8 */ - - -#ifdef LTC_PKCS_12 - -int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen); - -int pkcs12_kdf( int hash_id, - const unsigned char *pw, unsigned long pwlen, - const unsigned char *salt, unsigned long saltlen, - unsigned int iterations, unsigned char purpose, - unsigned char *out, unsigned long outlen); - -#endif /* LTC_PKCS_12 */ - -/* tomcrypt_prng.h */ - -#define LTC_PRNG_EXPORT(which) \ -int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \ -{ \ - unsigned long len = which ## _desc.export_size; \ - \ - LTC_ARGCHK(prng != NULL); \ - LTC_ARGCHK(out != NULL); \ - LTC_ARGCHK(outlen != NULL); \ - \ - if (*outlen < len) { \ - *outlen = len; \ - return CRYPT_BUFFER_OVERFLOW; \ - } \ - \ - if (which ## _read(out, len, prng) != len) { \ - return CRYPT_ERROR_READPRNG; \ - } \ - \ - *outlen = len; \ - return CRYPT_OK; \ -} - -/* extract a byte portably */ -#ifdef _MSC_VER - #define LTC_BYTE(x, n) ((unsigned char)((x) >> (8 * (n)))) -#else - #define LTC_BYTE(x, n) (((x) >> (8 * (n))) & 255) -#endif - -/* - * On Windows, choose whether to use CryptGenRandom() [older Windows versions] - * or BCryptGenRandom() [newer Windows versions]. - * If CryptGenRandom() is desired, define LTC_NO_WIN32_BCRYPT when building. - */ -#if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 - #if !defined(LTC_NO_WIN32_BCRYPT) - #define LTC_WIN32_BCRYPT - #endif -#endif - -#endif /* TOMCRYPT_PRIVATE_H_ */ diff --git a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_prng.h b/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_prng.h deleted file mode 100644 index b8fa585..0000000 --- a/Sources/DataLiteC/libtomcrypt/headers/tomcrypt_prng.h +++ /dev/null @@ -1,223 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* ---- PRNG Stuff ---- */ -#ifdef LTC_YARROW -struct yarrow_prng { - int cipher, hash; - unsigned char pool[MAXBLOCKSIZE]; - symmetric_CTR ctr; -}; -#endif - -#ifdef LTC_RC4 -struct rc4_prng { - rc4_state s; -}; -#endif - -#ifdef LTC_CHACHA20_PRNG -struct chacha20_prng { - chacha_state s; /* chacha state */ - unsigned char ent[40]; /* entropy buffer */ - unsigned long idx; /* entropy counter */ -}; -#endif - -#ifdef LTC_FORTUNA -struct fortuna_prng { - hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */ - - symmetric_key skey; - - unsigned char K[32], /* the current key */ - IV[16]; /* IV for CTR mode */ - - unsigned long pool_idx, /* current pool we will add to */ - pool0_len; /* length of 0'th pool */ - ulong64 wd; - ulong64 reset_cnt; /* number of times we have reseeded */ -}; -#endif - -#ifdef LTC_SOBER128 -struct sober128_prng { - sober128_state s; /* sober128 state */ - unsigned char ent[40]; /* entropy buffer */ - unsigned long idx; /* entropy counter */ -}; -#endif - -typedef struct { - union { - char dummy[1]; -#ifdef LTC_YARROW - struct yarrow_prng yarrow; -#endif -#ifdef LTC_RC4 - struct rc4_prng rc4; -#endif -#ifdef LTC_CHACHA20_PRNG - struct chacha20_prng chacha; -#endif -#ifdef LTC_FORTUNA - struct fortuna_prng fortuna; -#endif -#ifdef LTC_SOBER128 - struct sober128_prng sober128; -#endif - } u; - short ready; /* ready flag 0-1 */ - LTC_MUTEX_TYPE(lock) /* lock */ -} prng_state; - -/** PRNG descriptor */ -extern struct ltc_prng_descriptor { - /** Name of the PRNG */ - const char *name; - /** size in bytes of exported state */ - int export_size; - /** Start a PRNG state - @param prng [out] The state to initialize - @return CRYPT_OK if successful - */ - int (*start)(prng_state *prng); - /** Add entropy to the PRNG - @param in The entropy - @param inlen Length of the entropy (octets)\ - @param prng The PRNG state - @return CRYPT_OK if successful - */ - int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); - /** Ready a PRNG state to read from - @param prng The PRNG state to ready - @return CRYPT_OK if successful - */ - int (*ready)(prng_state *prng); - /** Read from the PRNG - @param out [out] Where to store the data - @param outlen Length of data desired (octets) - @param prng The PRNG state to read from - @return Number of octets read - */ - unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); - /** Terminate a PRNG state - @param prng The PRNG state to terminate - @return CRYPT_OK if successful - */ - int (*done)(prng_state *prng); - /** Export a PRNG state - @param out [out] The destination for the state - @param outlen [in/out] The max size and resulting size of the PRNG state - @param prng The PRNG to export - @return CRYPT_OK if successful - */ - int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); - /** Import a PRNG state - @param in The data to import - @param inlen The length of the data to import (octets) - @param prng The PRNG to initialize/import - @return CRYPT_OK if successful - */ - int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); - /** Self-test the PRNG - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled - */ - int (*test)(void); -} prng_descriptor[]; - -#ifdef LTC_YARROW -int yarrow_start(prng_state *prng); -int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int yarrow_ready(prng_state *prng); -unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int yarrow_done(prng_state *prng); -int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int yarrow_test(void); -extern const struct ltc_prng_descriptor yarrow_desc; -#endif - -#ifdef LTC_FORTUNA -int fortuna_start(prng_state *prng); -int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng); -int fortuna_ready(prng_state *prng); -unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int fortuna_done(prng_state *prng); -int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng); -int fortuna_test(void); -extern const struct ltc_prng_descriptor fortuna_desc; -#endif - -#ifdef LTC_RC4 -int rc4_start(prng_state *prng); -int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int rc4_ready(prng_state *prng); -unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int rc4_done(prng_state *prng); -int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int rc4_test(void); -extern const struct ltc_prng_descriptor rc4_desc; -#endif - -#ifdef LTC_CHACHA20_PRNG -int chacha20_prng_start(prng_state *prng); -int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int chacha20_prng_ready(prng_state *prng); -unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int chacha20_prng_done(prng_state *prng); -int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int chacha20_prng_test(void); -extern const struct ltc_prng_descriptor chacha20_prng_desc; -#endif - -#ifdef LTC_SPRNG -int sprng_start(prng_state *prng); -int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int sprng_ready(prng_state *prng); -unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int sprng_done(prng_state *prng); -int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int sprng_test(void); -extern const struct ltc_prng_descriptor sprng_desc; -#endif - -#ifdef LTC_SOBER128 -int sober128_start(prng_state *prng); -int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); -int sober128_ready(prng_state *prng); -unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); -int sober128_done(prng_state *prng); -int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); -int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); -int sober128_test(void); -extern const struct ltc_prng_descriptor sober128_desc; -#endif - -int find_prng(const char *name); -int register_prng(const struct ltc_prng_descriptor *prng); -int unregister_prng(const struct ltc_prng_descriptor *prng); -int register_all_prngs(void); -int prng_is_valid(int idx); -LTC_MUTEX_PROTO(ltc_prng_mutex) - -/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this - * might not work on all platforms as planned - */ -unsigned long rng_get_bytes(unsigned char *out, - unsigned long outlen, - void (*callback)(void)); - -int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); - -#ifdef LTC_PRNG_ENABLE_LTC_RNG -extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, - void (*callback)(void)); -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac.c deleted file mode 100644 index ac26e10..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2BMAC - -/** - Initialize an BLAKE2B MAC context. - @param st The BLAKE2B MAC state - @param outlen The size of the MAC output (octets) - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - return blake2b_init(st, outlen, key, keylen); -} - -/** - Process data through BLAKE2B MAC - @param st The BLAKE2B MAC state - @param in The data to send through HMAC - @param inlen The length of the data to HMAC (octets) - @return CRYPT_OK if successful -*/ -int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen) -{ - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - return blake2b_process(st, in, inlen); -} - -/** - Terminate a BLAKE2B MAC session - @param st The BLAKE2B MAC state - @param mac [out] The destination of the BLAKE2B MAC authentication tag - @param maclen [in/out] The max size and resulting size of the BLAKE2B MAC authentication tag - @return CRYPT_OK if successful -*/ -int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - LTC_ARGCHK(*maclen >= st->blake2b.outlen); - - *maclen = st->blake2b.outlen; - return blake2b_done(st, mac); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_file.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_file.c deleted file mode 100644 index 831e845..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_file.c +++ /dev/null @@ -1,78 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2BMAC - -/** - BLAKE2B MAC a file - @param fname The name of the file you wish to BLAKE2B MAC - @param key The secret key - @param keylen The length of the secret key - @param mac [out] The BLAKE2B MAC authentication tag - @param maclen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(fname); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(mac); - LTC_UNUSED_PARAM(maclen); - return CRYPT_NOP; -#else - blake2bmac_state st; - FILE *in; - unsigned char *buf; - size_t x; - int err; - - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = blake2bmac_done(&st, mac, maclen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2bmac_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory.c deleted file mode 100644 index 3f5e309..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2BMAC - -/** - BLAKE2B MAC a block of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data to BLAKE2B MAC - @param inlen The length of the data to BLAKE2B MAC (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @return CRYPT_OK if successful -*/ -int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) -{ - blake2bmac_state st; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - err = blake2bmac_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2bmac_state)); -#endif - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c deleted file mode 100644 index 3ce33a6..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_memory_multi.c +++ /dev/null @@ -1,51 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2BMAC - -/** - BLAKE2B MAC multiple blocks of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @param in The data to BLAKE2B MAC - @param inlen The length of the data to BLAKE2B MAC (octets) - @param ... tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) -{ - blake2bmac_state st; - int err; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - va_start(args, inlen); - curptr = in; - curlen = inlen; - if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - for (;;) { - if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) break; - curlen = va_arg(args, unsigned long); - } - err = blake2bmac_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2bmac_state)); -#endif - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_test.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_test.c deleted file mode 100644 index b2651cc..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2bmac_test.c +++ /dev/null @@ -1,304 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2BMAC - -int blake2bmac_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const unsigned char tests[256][64] = { - /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ - { 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68 }, - { 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd }, - { 0xda, 0x2c, 0xfb, 0xe2, 0xd8, 0x40, 0x9a, 0x0f, 0x38, 0x02, 0x61, 0x13, 0x88, 0x4f, 0x84, 0xb5, 0x01, 0x56, 0x37, 0x1a, 0xe3, 0x04, 0xc4, 0x43, 0x01, 0x73, 0xd0, 0x8a, 0x99, 0xd9, 0xfb, 0x1b, 0x98, 0x31, 0x64, 0xa3, 0x77, 0x07, 0x06, 0xd5, 0x37, 0xf4, 0x9e, 0x0c, 0x91, 0x6d, 0x9f, 0x32, 0xb9, 0x5c, 0xc3, 0x7a, 0x95, 0xb9, 0x9d, 0x85, 0x74, 0x36, 0xf0, 0x23, 0x2c, 0x88, 0xa9, 0x65 }, - { 0x33, 0xd0, 0x82, 0x5d, 0xdd, 0xf7, 0xad, 0xa9, 0x9b, 0x0e, 0x7e, 0x30, 0x71, 0x04, 0xad, 0x07, 0xca, 0x9c, 0xfd, 0x96, 0x92, 0x21, 0x4f, 0x15, 0x61, 0x35, 0x63, 0x15, 0xe7, 0x84, 0xf3, 0xe5, 0xa1, 0x7e, 0x36, 0x4a, 0xe9, 0xdb, 0xb1, 0x4c, 0xb2, 0x03, 0x6d, 0xf9, 0x32, 0xb7, 0x7f, 0x4b, 0x29, 0x27, 0x61, 0x36, 0x5f, 0xb3, 0x28, 0xde, 0x7a, 0xfd, 0xc6, 0xd8, 0x99, 0x8f, 0x5f, 0xc1 }, - { 0xbe, 0xaa, 0x5a, 0x3d, 0x08, 0xf3, 0x80, 0x71, 0x43, 0xcf, 0x62, 0x1d, 0x95, 0xcd, 0x69, 0x05, 0x14, 0xd0, 0xb4, 0x9e, 0xff, 0xf9, 0xc9, 0x1d, 0x24, 0xb5, 0x92, 0x41, 0xec, 0x0e, 0xef, 0xa5, 0xf6, 0x01, 0x96, 0xd4, 0x07, 0x04, 0x8b, 0xba, 0x8d, 0x21, 0x46, 0x82, 0x8e, 0xbc, 0xb0, 0x48, 0x8d, 0x88, 0x42, 0xfd, 0x56, 0xbb, 0x4f, 0x6d, 0xf8, 0xe1, 0x9c, 0x4b, 0x4d, 0xaa, 0xb8, 0xac }, - { 0x09, 0x80, 0x84, 0xb5, 0x1f, 0xd1, 0x3d, 0xea, 0xe5, 0xf4, 0x32, 0x0d, 0xe9, 0x4a, 0x68, 0x8e, 0xe0, 0x7b, 0xae, 0xa2, 0x80, 0x04, 0x86, 0x68, 0x9a, 0x86, 0x36, 0x11, 0x7b, 0x46, 0xc1, 0xf4, 0xc1, 0xf6, 0xaf, 0x7f, 0x74, 0xae, 0x7c, 0x85, 0x76, 0x00, 0x45, 0x6a, 0x58, 0xa3, 0xaf, 0x25, 0x1d, 0xc4, 0x72, 0x3a, 0x64, 0xcc, 0x7c, 0x0a, 0x5a, 0xb6, 0xd9, 0xca, 0xc9, 0x1c, 0x20, 0xbb }, - { 0x60, 0x44, 0x54, 0x0d, 0x56, 0x08, 0x53, 0xeb, 0x1c, 0x57, 0xdf, 0x00, 0x77, 0xdd, 0x38, 0x10, 0x94, 0x78, 0x1c, 0xdb, 0x90, 0x73, 0xe5, 0xb1, 0xb3, 0xd3, 0xf6, 0xc7, 0x82, 0x9e, 0x12, 0x06, 0x6b, 0xba, 0xca, 0x96, 0xd9, 0x89, 0xa6, 0x90, 0xde, 0x72, 0xca, 0x31, 0x33, 0xa8, 0x36, 0x52, 0xba, 0x28, 0x4a, 0x6d, 0x62, 0x94, 0x2b, 0x27, 0x1f, 0xfa, 0x26, 0x20, 0xc9, 0xe7, 0x5b, 0x1f }, - { 0x7a, 0x8c, 0xfe, 0x9b, 0x90, 0xf7, 0x5f, 0x7e, 0xcb, 0x3a, 0xcc, 0x05, 0x3a, 0xae, 0xd6, 0x19, 0x31, 0x12, 0xb6, 0xf6, 0xa4, 0xae, 0xeb, 0x3f, 0x65, 0xd3, 0xde, 0x54, 0x19, 0x42, 0xde, 0xb9, 0xe2, 0x22, 0x81, 0x52, 0xa3, 0xc4, 0xbb, 0xbe, 0x72, 0xfc, 0x3b, 0x12, 0x62, 0x95, 0x28, 0xcf, 0xbb, 0x09, 0xfe, 0x63, 0x0f, 0x04, 0x74, 0x33, 0x9f, 0x54, 0xab, 0xf4, 0x53, 0xe2, 0xed, 0x52 }, - { 0x38, 0x0b, 0xea, 0xf6, 0xea, 0x7c, 0xc9, 0x36, 0x5e, 0x27, 0x0e, 0xf0, 0xe6, 0xf3, 0xa6, 0x4f, 0xb9, 0x02, 0xac, 0xae, 0x51, 0xdd, 0x55, 0x12, 0xf8, 0x42, 0x59, 0xad, 0x2c, 0x91, 0xf4, 0xbc, 0x41, 0x08, 0xdb, 0x73, 0x19, 0x2a, 0x5b, 0xbf, 0xb0, 0xcb, 0xcf, 0x71, 0xe4, 0x6c, 0x3e, 0x21, 0xae, 0xe1, 0xc5, 0xe8, 0x60, 0xdc, 0x96, 0xe8, 0xeb, 0x0b, 0x7b, 0x84, 0x26, 0xe6, 0xab, 0xe9 }, - { 0x60, 0xfe, 0x3c, 0x45, 0x35, 0xe1, 0xb5, 0x9d, 0x9a, 0x61, 0xea, 0x85, 0x00, 0xbf, 0xac, 0x41, 0xa6, 0x9d, 0xff, 0xb1, 0xce, 0xad, 0xd9, 0xac, 0xa3, 0x23, 0xe9, 0xa6, 0x25, 0xb6, 0x4d, 0xa5, 0x76, 0x3b, 0xad, 0x72, 0x26, 0xda, 0x02, 0xb9, 0xc8, 0xc4, 0xf1, 0xa5, 0xde, 0x14, 0x0a, 0xc5, 0xa6, 0xc1, 0x12, 0x4e, 0x4f, 0x71, 0x8c, 0xe0, 0xb2, 0x8e, 0xa4, 0x73, 0x93, 0xaa, 0x66, 0x37 }, - { 0x4f, 0xe1, 0x81, 0xf5, 0x4a, 0xd6, 0x3a, 0x29, 0x83, 0xfe, 0xaa, 0xf7, 0x7d, 0x1e, 0x72, 0x35, 0xc2, 0xbe, 0xb1, 0x7f, 0xa3, 0x28, 0xb6, 0xd9, 0x50, 0x5b, 0xda, 0x32, 0x7d, 0xf1, 0x9f, 0xc3, 0x7f, 0x02, 0xc4, 0xb6, 0xf0, 0x36, 0x8c, 0xe2, 0x31, 0x47, 0x31, 0x3a, 0x8e, 0x57, 0x38, 0xb5, 0xfa, 0x2a, 0x95, 0xb2, 0x9d, 0xe1, 0xc7, 0xf8, 0x26, 0x4e, 0xb7, 0x7b, 0x69, 0xf5, 0x85, 0xcd }, - { 0xf2, 0x28, 0x77, 0x3c, 0xe3, 0xf3, 0xa4, 0x2b, 0x5f, 0x14, 0x4d, 0x63, 0x23, 0x7a, 0x72, 0xd9, 0x96, 0x93, 0xad, 0xb8, 0x83, 0x7d, 0x0e, 0x11, 0x2a, 0x8a, 0x0f, 0x8f, 0xff, 0xf2, 0xc3, 0x62, 0x85, 0x7a, 0xc4, 0x9c, 0x11, 0xec, 0x74, 0x0d, 0x15, 0x00, 0x74, 0x9d, 0xac, 0x9b, 0x1f, 0x45, 0x48, 0x10, 0x8b, 0xf3, 0x15, 0x57, 0x94, 0xdc, 0xc9, 0xe4, 0x08, 0x28, 0x49, 0xe2, 0xb8, 0x5b }, - { 0x96, 0x24, 0x52, 0xa8, 0x45, 0x5c, 0xc5, 0x6c, 0x85, 0x11, 0x31, 0x7e, 0x3b, 0x1f, 0x3b, 0x2c, 0x37, 0xdf, 0x75, 0xf5, 0x88, 0xe9, 0x43, 0x25, 0xfd, 0xd7, 0x70, 0x70, 0x35, 0x9c, 0xf6, 0x3a, 0x9a, 0xe6, 0xe9, 0x30, 0x93, 0x6f, 0xdf, 0x8e, 0x1e, 0x08, 0xff, 0xca, 0x44, 0x0c, 0xfb, 0x72, 0xc2, 0x8f, 0x06, 0xd8, 0x9a, 0x21, 0x51, 0xd1, 0xc4, 0x6c, 0xd5, 0xb2, 0x68, 0xef, 0x85, 0x63 }, - { 0x43, 0xd4, 0x4b, 0xfa, 0x18, 0x76, 0x8c, 0x59, 0x89, 0x6b, 0xf7, 0xed, 0x17, 0x65, 0xcb, 0x2d, 0x14, 0xaf, 0x8c, 0x26, 0x02, 0x66, 0x03, 0x90, 0x99, 0xb2, 0x5a, 0x60, 0x3e, 0x4d, 0xdc, 0x50, 0x39, 0xd6, 0xef, 0x3a, 0x91, 0x84, 0x7d, 0x10, 0x88, 0xd4, 0x01, 0xc0, 0xc7, 0xe8, 0x47, 0x78, 0x1a, 0x8a, 0x59, 0x0d, 0x33, 0xa3, 0xc6, 0xcb, 0x4d, 0xf0, 0xfa, 0xb1, 0xc2, 0xf2, 0x23, 0x55 }, - { 0xdc, 0xff, 0xa9, 0xd5, 0x8c, 0x2a, 0x4c, 0xa2, 0xcd, 0xbb, 0x0c, 0x7a, 0xa4, 0xc4, 0xc1, 0xd4, 0x51, 0x65, 0x19, 0x00, 0x89, 0xf4, 0xe9, 0x83, 0xbb, 0x1c, 0x2c, 0xab, 0x4a, 0xae, 0xff, 0x1f, 0xa2, 0xb5, 0xee, 0x51, 0x6f, 0xec, 0xd7, 0x80, 0x54, 0x02, 0x40, 0xbf, 0x37, 0xe5, 0x6c, 0x8b, 0xcc, 0xa7, 0xfa, 0xb9, 0x80, 0xe1, 0xe6, 0x1c, 0x94, 0x00, 0xd8, 0xa9, 0xa5, 0xb1, 0x4a, 0xc6 }, - { 0x6f, 0xbf, 0x31, 0xb4, 0x5a, 0xb0, 0xc0, 0xb8, 0xda, 0xd1, 0xc0, 0xf5, 0xf4, 0x06, 0x13, 0x79, 0x91, 0x2d, 0xde, 0x5a, 0xa9, 0x22, 0x09, 0x9a, 0x03, 0x0b, 0x72, 0x5c, 0x73, 0x34, 0x6c, 0x52, 0x42, 0x91, 0xad, 0xef, 0x89, 0xd2, 0xf6, 0xfd, 0x8d, 0xfc, 0xda, 0x6d, 0x07, 0xda, 0xd8, 0x11, 0xa9, 0x31, 0x45, 0x36, 0xc2, 0x91, 0x5e, 0xd4, 0x5d, 0xa3, 0x49, 0x47, 0xe8, 0x3d, 0xe3, 0x4e }, - { 0xa0, 0xc6, 0x5b, 0xdd, 0xde, 0x8a, 0xde, 0xf5, 0x72, 0x82, 0xb0, 0x4b, 0x11, 0xe7, 0xbc, 0x8a, 0xab, 0x10, 0x5b, 0x99, 0x23, 0x1b, 0x75, 0x0c, 0x02, 0x1f, 0x4a, 0x73, 0x5c, 0xb1, 0xbc, 0xfa, 0xb8, 0x75, 0x53, 0xbb, 0xa3, 0xab, 0xb0, 0xc3, 0xe6, 0x4a, 0x0b, 0x69, 0x55, 0x28, 0x51, 0x85, 0xa0, 0xbd, 0x35, 0xfb, 0x8c, 0xfd, 0xe5, 0x57, 0x32, 0x9b, 0xeb, 0xb1, 0xf6, 0x29, 0xee, 0x93 }, - { 0xf9, 0x9d, 0x81, 0x55, 0x50, 0x55, 0x8e, 0x81, 0xec, 0xa2, 0xf9, 0x67, 0x18, 0xae, 0xd1, 0x0d, 0x86, 0xf3, 0xf1, 0xcf, 0xb6, 0x75, 0xcc, 0xe0, 0x6b, 0x0e, 0xff, 0x02, 0xf6, 0x17, 0xc5, 0xa4, 0x2c, 0x5a, 0xa7, 0x60, 0x27, 0x0f, 0x26, 0x79, 0xda, 0x26, 0x77, 0xc5, 0xae, 0xb9, 0x4f, 0x11, 0x42, 0x27, 0x7f, 0x21, 0xc7, 0xf7, 0x9f, 0x3c, 0x4f, 0x0c, 0xce, 0x4e, 0xd8, 0xee, 0x62, 0xb1 }, - { 0x95, 0x39, 0x1d, 0xa8, 0xfc, 0x7b, 0x91, 0x7a, 0x20, 0x44, 0xb3, 0xd6, 0xf5, 0x37, 0x4e, 0x1c, 0xa0, 0x72, 0xb4, 0x14, 0x54, 0xd5, 0x72, 0xc7, 0x35, 0x6c, 0x05, 0xfd, 0x4b, 0xc1, 0xe0, 0xf4, 0x0b, 0x8b, 0xb8, 0xb4, 0xa9, 0xf6, 0xbc, 0xe9, 0xbe, 0x2c, 0x46, 0x23, 0xc3, 0x99, 0xb0, 0xdc, 0xa0, 0xda, 0xb0, 0x5c, 0xb7, 0x28, 0x1b, 0x71, 0xa2, 0x1b, 0x0e, 0xbc, 0xd9, 0xe5, 0x56, 0x70 }, - { 0x04, 0xb9, 0xcd, 0x3d, 0x20, 0xd2, 0x21, 0xc0, 0x9a, 0xc8, 0x69, 0x13, 0xd3, 0xdc, 0x63, 0x04, 0x19, 0x89, 0xa9, 0xa1, 0xe6, 0x94, 0xf1, 0xe6, 0x39, 0xa3, 0xba, 0x7e, 0x45, 0x18, 0x40, 0xf7, 0x50, 0xc2, 0xfc, 0x19, 0x1d, 0x56, 0xad, 0x61, 0xf2, 0xe7, 0x93, 0x6b, 0xc0, 0xac, 0x8e, 0x09, 0x4b, 0x60, 0xca, 0xee, 0xd8, 0x78, 0xc1, 0x87, 0x99, 0x04, 0x54, 0x02, 0xd6, 0x1c, 0xea, 0xf9 }, - { 0xec, 0x0e, 0x0e, 0xf7, 0x07, 0xe4, 0xed, 0x6c, 0x0c, 0x66, 0xf9, 0xe0, 0x89, 0xe4, 0x95, 0x4b, 0x05, 0x80, 0x30, 0xd2, 0xdd, 0x86, 0x39, 0x8f, 0xe8, 0x40, 0x59, 0x63, 0x1f, 0x9e, 0xe5, 0x91, 0xd9, 0xd7, 0x73, 0x75, 0x35, 0x51, 0x49, 0x17, 0x8c, 0x0c, 0xf8, 0xf8, 0xe7, 0xc4, 0x9e, 0xd2, 0xa5, 0xe4, 0xf9, 0x54, 0x88, 0xa2, 0x24, 0x70, 0x67, 0xc2, 0x08, 0x51, 0x0f, 0xad, 0xc4, 0x4c }, - { 0x9a, 0x37, 0xcc, 0xe2, 0x73, 0xb7, 0x9c, 0x09, 0x91, 0x36, 0x77, 0x51, 0x0e, 0xaf, 0x76, 0x88, 0xe8, 0x9b, 0x33, 0x14, 0xd3, 0x53, 0x2f, 0xd2, 0x76, 0x4c, 0x39, 0xde, 0x02, 0x2a, 0x29, 0x45, 0xb5, 0x71, 0x0d, 0x13, 0x51, 0x7a, 0xf8, 0xdd, 0xc0, 0x31, 0x66, 0x24, 0xe7, 0x3b, 0xec, 0x1c, 0xe6, 0x7d, 0xf1, 0x52, 0x28, 0x30, 0x20, 0x36, 0xf3, 0x30, 0xab, 0x0c, 0xb4, 0xd2, 0x18, 0xdd }, - { 0x4c, 0xf9, 0xbb, 0x8f, 0xb3, 0xd4, 0xde, 0x8b, 0x38, 0xb2, 0xf2, 0x62, 0xd3, 0xc4, 0x0f, 0x46, 0xdf, 0xe7, 0x47, 0xe8, 0xfc, 0x0a, 0x41, 0x4c, 0x19, 0x3d, 0x9f, 0xcf, 0x75, 0x31, 0x06, 0xce, 0x47, 0xa1, 0x8f, 0x17, 0x2f, 0x12, 0xe8, 0xa2, 0xf1, 0xc2, 0x67, 0x26, 0x54, 0x53, 0x58, 0xe5, 0xee, 0x28, 0xc9, 0xe2, 0x21, 0x3a, 0x87, 0x87, 0xaa, 0xfb, 0xc5, 0x16, 0xd2, 0x34, 0x31, 0x52 }, - { 0x64, 0xe0, 0xc6, 0x3a, 0xf9, 0xc8, 0x08, 0xfd, 0x89, 0x31, 0x37, 0x12, 0x98, 0x67, 0xfd, 0x91, 0x93, 0x9d, 0x53, 0xf2, 0xaf, 0x04, 0xbe, 0x4f, 0xa2, 0x68, 0x00, 0x61, 0x00, 0x06, 0x9b, 0x2d, 0x69, 0xda, 0xa5, 0xc5, 0xd8, 0xed, 0x7f, 0xdd, 0xcb, 0x2a, 0x70, 0xee, 0xec, 0xdf, 0x2b, 0x10, 0x5d, 0xd4, 0x6a, 0x1e, 0x3b, 0x73, 0x11, 0x72, 0x8f, 0x63, 0x9a, 0xb4, 0x89, 0x32, 0x6b, 0xc9 }, - { 0x5e, 0x9c, 0x93, 0x15, 0x8d, 0x65, 0x9b, 0x2d, 0xef, 0x06, 0xb0, 0xc3, 0xc7, 0x56, 0x50, 0x45, 0x54, 0x26, 0x62, 0xd6, 0xee, 0xe8, 0xa9, 0x6a, 0x89, 0xb7, 0x8a, 0xde, 0x09, 0xfe, 0x8b, 0x3d, 0xcc, 0x09, 0x6d, 0x4f, 0xe4, 0x88, 0x15, 0xd8, 0x8d, 0x8f, 0x82, 0x62, 0x01, 0x56, 0x60, 0x2a, 0xf5, 0x41, 0x95, 0x5e, 0x1f, 0x6c, 0xa3, 0x0d, 0xce, 0x14, 0xe2, 0x54, 0xc3, 0x26, 0xb8, 0x8f }, - { 0x77, 0x75, 0xdf, 0xf8, 0x89, 0x45, 0x8d, 0xd1, 0x1a, 0xef, 0x41, 0x72, 0x76, 0x85, 0x3e, 0x21, 0x33, 0x5e, 0xb8, 0x8e, 0x4d, 0xec, 0x9c, 0xfb, 0x4e, 0x9e, 0xdb, 0x49, 0x82, 0x00, 0x88, 0x55, 0x1a, 0x2c, 0xa6, 0x03, 0x39, 0xf1, 0x20, 0x66, 0x10, 0x11, 0x69, 0xf0, 0xdf, 0xe8, 0x4b, 0x09, 0x8f, 0xdd, 0xb1, 0x48, 0xd9, 0xda, 0x6b, 0x3d, 0x61, 0x3d, 0xf2, 0x63, 0x88, 0x9a, 0xd6, 0x4b }, - { 0xf0, 0xd2, 0x80, 0x5a, 0xfb, 0xb9, 0x1f, 0x74, 0x39, 0x51, 0x35, 0x1a, 0x6d, 0x02, 0x4f, 0x93, 0x53, 0xa2, 0x3c, 0x7c, 0xe1, 0xfc, 0x2b, 0x05, 0x1b, 0x3a, 0x8b, 0x96, 0x8c, 0x23, 0x3f, 0x46, 0xf5, 0x0f, 0x80, 0x6e, 0xcb, 0x15, 0x68, 0xff, 0xaa, 0x0b, 0x60, 0x66, 0x1e, 0x33, 0x4b, 0x21, 0xdd, 0xe0, 0x4f, 0x8f, 0xa1, 0x55, 0xac, 0x74, 0x0e, 0xeb, 0x42, 0xe2, 0x0b, 0x60, 0xd7, 0x64 }, - { 0x86, 0xa2, 0xaf, 0x31, 0x6e, 0x7d, 0x77, 0x54, 0x20, 0x1b, 0x94, 0x2e, 0x27, 0x53, 0x64, 0xac, 0x12, 0xea, 0x89, 0x62, 0xab, 0x5b, 0xd8, 0xd7, 0xfb, 0x27, 0x6d, 0xc5, 0xfb, 0xff, 0xc8, 0xf9, 0xa2, 0x8c, 0xae, 0x4e, 0x48, 0x67, 0xdf, 0x67, 0x80, 0xd9, 0xb7, 0x25, 0x24, 0x16, 0x09, 0x27, 0xc8, 0x55, 0xda, 0x5b, 0x60, 0x78, 0xe0, 0xb5, 0x54, 0xaa, 0x91, 0xe3, 0x1c, 0xb9, 0xca, 0x1d }, - { 0x10, 0xbd, 0xf0, 0xca, 0xa0, 0x80, 0x27, 0x05, 0xe7, 0x06, 0x36, 0x9b, 0xaf, 0x8a, 0x3f, 0x79, 0xd7, 0x2c, 0x0a, 0x03, 0xa8, 0x06, 0x75, 0xa7, 0xbb, 0xb0, 0x0b, 0xe3, 0xa4, 0x5e, 0x51, 0x64, 0x24, 0xd1, 0xee, 0x88, 0xef, 0xb5, 0x6f, 0x6d, 0x57, 0x77, 0x54, 0x5a, 0xe6, 0xe2, 0x77, 0x65, 0xc3, 0xa8, 0xf5, 0xe4, 0x93, 0xfc, 0x30, 0x89, 0x15, 0x63, 0x89, 0x33, 0xa1, 0xdf, 0xee, 0x55 }, - { 0xb0, 0x17, 0x81, 0x09, 0x2b, 0x17, 0x48, 0x45, 0x9e, 0x2e, 0x4e, 0xc1, 0x78, 0x69, 0x66, 0x27, 0xbf, 0x4e, 0xba, 0xfe, 0xbb, 0xa7, 0x74, 0xec, 0xf0, 0x18, 0xb7, 0x9a, 0x68, 0xae, 0xb8, 0x49, 0x17, 0xbf, 0x0b, 0x84, 0xbb, 0x79, 0xd1, 0x7b, 0x74, 0x31, 0x51, 0x14, 0x4c, 0xd6, 0x6b, 0x7b, 0x33, 0xa4, 0xb9, 0xe5, 0x2c, 0x76, 0xc4, 0xe1, 0x12, 0x05, 0x0f, 0xf5, 0x38, 0x5b, 0x7f, 0x0b }, - { 0xc6, 0xdb, 0xc6, 0x1d, 0xec, 0x6e, 0xae, 0xac, 0x81, 0xe3, 0xd5, 0xf7, 0x55, 0x20, 0x3c, 0x8e, 0x22, 0x05, 0x51, 0x53, 0x4a, 0x0b, 0x2f, 0xd1, 0x05, 0xa9, 0x18, 0x89, 0x94, 0x5a, 0x63, 0x85, 0x50, 0x20, 0x4f, 0x44, 0x09, 0x3d, 0xd9, 0x98, 0xc0, 0x76, 0x20, 0x5d, 0xff, 0xad, 0x70, 0x3a, 0x0e, 0x5c, 0xd3, 0xc7, 0xf4, 0x38, 0xa7, 0xe6, 0x34, 0xcd, 0x59, 0xfe, 0xde, 0xdb, 0x53, 0x9e }, - { 0xeb, 0xa5, 0x1a, 0xcf, 0xfb, 0x4c, 0xea, 0x31, 0xdb, 0x4b, 0x8d, 0x87, 0xe9, 0xbf, 0x7d, 0xd4, 0x8f, 0xe9, 0x7b, 0x02, 0x53, 0xae, 0x67, 0xaa, 0x58, 0x0f, 0x9a, 0xc4, 0xa9, 0xd9, 0x41, 0xf2, 0xbe, 0xa5, 0x18, 0xee, 0x28, 0x68, 0x18, 0xcc, 0x9f, 0x63, 0x3f, 0x2a, 0x3b, 0x9f, 0xb6, 0x8e, 0x59, 0x4b, 0x48, 0xcd, 0xd6, 0xd5, 0x15, 0xbf, 0x1d, 0x52, 0xba, 0x6c, 0x85, 0xa2, 0x03, 0xa7 }, - { 0x86, 0x22, 0x1f, 0x3a, 0xda, 0x52, 0x03, 0x7b, 0x72, 0x22, 0x4f, 0x10, 0x5d, 0x79, 0x99, 0x23, 0x1c, 0x5e, 0x55, 0x34, 0xd0, 0x3d, 0xa9, 0xd9, 0xc0, 0xa1, 0x2a, 0xcb, 0x68, 0x46, 0x0c, 0xd3, 0x75, 0xda, 0xf8, 0xe2, 0x43, 0x86, 0x28, 0x6f, 0x96, 0x68, 0xf7, 0x23, 0x26, 0xdb, 0xf9, 0x9b, 0xa0, 0x94, 0x39, 0x24, 0x37, 0xd3, 0x98, 0xe9, 0x5b, 0xb8, 0x16, 0x1d, 0x71, 0x7f, 0x89, 0x91 }, - { 0x55, 0x95, 0xe0, 0x5c, 0x13, 0xa7, 0xec, 0x4d, 0xc8, 0xf4, 0x1f, 0xb7, 0x0c, 0xb5, 0x0a, 0x71, 0xbc, 0xe1, 0x7c, 0x02, 0x4f, 0xf6, 0xde, 0x7a, 0xf6, 0x18, 0xd0, 0xcc, 0x4e, 0x9c, 0x32, 0xd9, 0x57, 0x0d, 0x6d, 0x3e, 0xa4, 0x5b, 0x86, 0x52, 0x54, 0x91, 0x03, 0x0c, 0x0d, 0x8f, 0x2b, 0x18, 0x36, 0xd5, 0x77, 0x8c, 0x1c, 0xe7, 0x35, 0xc1, 0x77, 0x07, 0xdf, 0x36, 0x4d, 0x05, 0x43, 0x47 }, - { 0xce, 0x0f, 0x4f, 0x6a, 0xca, 0x89, 0x59, 0x0a, 0x37, 0xfe, 0x03, 0x4d, 0xd7, 0x4d, 0xd5, 0xfa, 0x65, 0xeb, 0x1c, 0xbd, 0x0a, 0x41, 0x50, 0x8a, 0xad, 0xdc, 0x09, 0x35, 0x1a, 0x3c, 0xea, 0x6d, 0x18, 0xcb, 0x21, 0x89, 0xc5, 0x4b, 0x70, 0x0c, 0x00, 0x9f, 0x4c, 0xbf, 0x05, 0x21, 0xc7, 0xea, 0x01, 0xbe, 0x61, 0xc5, 0xae, 0x09, 0xcb, 0x54, 0xf2, 0x7b, 0xc1, 0xb4, 0x4d, 0x65, 0x8c, 0x82 }, - { 0x7e, 0xe8, 0x0b, 0x06, 0xa2, 0x15, 0xa3, 0xbc, 0xa9, 0x70, 0xc7, 0x7c, 0xda, 0x87, 0x61, 0x82, 0x2b, 0xc1, 0x03, 0xd4, 0x4f, 0xa4, 0xb3, 0x3f, 0x4d, 0x07, 0xdc, 0xb9, 0x97, 0xe3, 0x6d, 0x55, 0x29, 0x8b, 0xce, 0xae, 0x12, 0x24, 0x1b, 0x3f, 0xa0, 0x7f, 0xa6, 0x3b, 0xe5, 0x57, 0x60, 0x68, 0xda, 0x38, 0x7b, 0x8d, 0x58, 0x59, 0xae, 0xab, 0x70, 0x13, 0x69, 0x84, 0x8b, 0x17, 0x6d, 0x42 }, - { 0x94, 0x0a, 0x84, 0xb6, 0xa8, 0x4d, 0x10, 0x9a, 0xab, 0x20, 0x8c, 0x02, 0x4c, 0x6c, 0xe9, 0x64, 0x76, 0x76, 0xba, 0x0a, 0xaa, 0x11, 0xf8, 0x6d, 0xbb, 0x70, 0x18, 0xf9, 0xfd, 0x22, 0x20, 0xa6, 0xd9, 0x01, 0xa9, 0x02, 0x7f, 0x9a, 0xbc, 0xf9, 0x35, 0x37, 0x27, 0x27, 0xcb, 0xf0, 0x9e, 0xbd, 0x61, 0xa2, 0xa2, 0xee, 0xb8, 0x76, 0x53, 0xe8, 0xec, 0xad, 0x1b, 0xab, 0x85, 0xdc, 0x83, 0x27 }, - { 0x20, 0x20, 0xb7, 0x82, 0x64, 0xa8, 0x2d, 0x9f, 0x41, 0x51, 0x14, 0x1a, 0xdb, 0xa8, 0xd4, 0x4b, 0xf2, 0x0c, 0x5e, 0xc0, 0x62, 0xee, 0xe9, 0xb5, 0x95, 0xa1, 0x1f, 0x9e, 0x84, 0x90, 0x1b, 0xf1, 0x48, 0xf2, 0x98, 0xe0, 0xc9, 0xf8, 0x77, 0x7d, 0xcd, 0xbc, 0x7c, 0xc4, 0x67, 0x0a, 0xac, 0x35, 0x6c, 0xc2, 0xad, 0x8c, 0xcb, 0x16, 0x29, 0xf1, 0x6f, 0x6a, 0x76, 0xbc, 0xef, 0xbe, 0xe7, 0x60 }, - { 0xd1, 0xb8, 0x97, 0xb0, 0xe0, 0x75, 0xba, 0x68, 0xab, 0x57, 0x2a, 0xdf, 0x9d, 0x9c, 0x43, 0x66, 0x63, 0xe4, 0x3e, 0xb3, 0xd8, 0xe6, 0x2d, 0x92, 0xfc, 0x49, 0xc9, 0xbe, 0x21, 0x4e, 0x6f, 0x27, 0x87, 0x3f, 0xe2, 0x15, 0xa6, 0x51, 0x70, 0xe6, 0xbe, 0xa9, 0x02, 0x40, 0x8a, 0x25, 0xb4, 0x95, 0x06, 0xf4, 0x7b, 0xab, 0xd0, 0x7c, 0xec, 0xf7, 0x11, 0x3e, 0xc1, 0x0c, 0x5d, 0xd3, 0x12, 0x52 }, - { 0xb1, 0x4d, 0x0c, 0x62, 0xab, 0xfa, 0x46, 0x9a, 0x35, 0x71, 0x77, 0xe5, 0x94, 0xc1, 0x0c, 0x19, 0x42, 0x43, 0xed, 0x20, 0x25, 0xab, 0x8a, 0xa5, 0xad, 0x2f, 0xa4, 0x1a, 0xd3, 0x18, 0xe0, 0xff, 0x48, 0xcd, 0x5e, 0x60, 0xbe, 0xc0, 0x7b, 0x13, 0x63, 0x4a, 0x71, 0x1d, 0x23, 0x26, 0xe4, 0x88, 0xa9, 0x85, 0xf3, 0x1e, 0x31, 0x15, 0x33, 0x99, 0xe7, 0x30, 0x88, 0xef, 0xc8, 0x6a, 0x5c, 0x55 }, - { 0x41, 0x69, 0xc5, 0xcc, 0x80, 0x8d, 0x26, 0x97, 0xdc, 0x2a, 0x82, 0x43, 0x0d, 0xc2, 0x3e, 0x3c, 0xd3, 0x56, 0xdc, 0x70, 0xa9, 0x45, 0x66, 0x81, 0x05, 0x02, 0xb8, 0xd6, 0x55, 0xb3, 0x9a, 0xbf, 0x9e, 0x7f, 0x90, 0x2f, 0xe7, 0x17, 0xe0, 0x38, 0x92, 0x19, 0x85, 0x9e, 0x19, 0x45, 0xdf, 0x1a, 0xf6, 0xad, 0xa4, 0x2e, 0x4c, 0xcd, 0xa5, 0x5a, 0x19, 0x7b, 0x71, 0x00, 0xa3, 0x0c, 0x30, 0xa1 }, - { 0x25, 0x8a, 0x4e, 0xdb, 0x11, 0x3d, 0x66, 0xc8, 0x39, 0xc8, 0xb1, 0xc9, 0x1f, 0x15, 0xf3, 0x5a, 0xde, 0x60, 0x9f, 0x11, 0xcd, 0x7f, 0x86, 0x81, 0xa4, 0x04, 0x5b, 0x9f, 0xef, 0x7b, 0x0b, 0x24, 0xc8, 0x2c, 0xda, 0x06, 0xa5, 0xf2, 0x06, 0x7b, 0x36, 0x88, 0x25, 0xe3, 0x91, 0x4e, 0x53, 0xd6, 0x94, 0x8e, 0xde, 0x92, 0xef, 0xd6, 0xe8, 0x38, 0x7f, 0xa2, 0xe5, 0x37, 0x23, 0x9b, 0x5b, 0xee }, - { 0x79, 0xd2, 0xd8, 0x69, 0x6d, 0x30, 0xf3, 0x0f, 0xb3, 0x46, 0x57, 0x76, 0x11, 0x71, 0xa1, 0x1e, 0x6c, 0x3f, 0x1e, 0x64, 0xcb, 0xe7, 0xbe, 0xbe, 0xe1, 0x59, 0xcb, 0x95, 0xbf, 0xaf, 0x81, 0x2b, 0x4f, 0x41, 0x1e, 0x2f, 0x26, 0xd9, 0xc4, 0x21, 0xdc, 0x2c, 0x28, 0x4a, 0x33, 0x42, 0xd8, 0x23, 0xec, 0x29, 0x38, 0x49, 0xe4, 0x2d, 0x1e, 0x46, 0xb0, 0xa4, 0xac, 0x1e, 0x3c, 0x86, 0xab, 0xaa }, - { 0x8b, 0x94, 0x36, 0x01, 0x0d, 0xc5, 0xde, 0xe9, 0x92, 0xae, 0x38, 0xae, 0xa9, 0x7f, 0x2c, 0xd6, 0x3b, 0x94, 0x6d, 0x94, 0xfe, 0xdd, 0x2e, 0xc9, 0x67, 0x1d, 0xcd, 0xe3, 0xbd, 0x4c, 0xe9, 0x56, 0x4d, 0x55, 0x5c, 0x66, 0xc1, 0x5b, 0xb2, 0xb9, 0x00, 0xdf, 0x72, 0xed, 0xb6, 0xb8, 0x91, 0xeb, 0xca, 0xdf, 0xef, 0xf6, 0x3c, 0x9e, 0xa4, 0x03, 0x6a, 0x99, 0x8b, 0xe7, 0x97, 0x39, 0x81, 0xe7 }, - { 0xc8, 0xf6, 0x8e, 0x69, 0x6e, 0xd2, 0x82, 0x42, 0xbf, 0x99, 0x7f, 0x5b, 0x3b, 0x34, 0x95, 0x95, 0x08, 0xe4, 0x2d, 0x61, 0x38, 0x10, 0xf1, 0xe2, 0xa4, 0x35, 0xc9, 0x6e, 0xd2, 0xff, 0x56, 0x0c, 0x70, 0x22, 0xf3, 0x61, 0xa9, 0x23, 0x4b, 0x98, 0x37, 0xfe, 0xee, 0x90, 0xbf, 0x47, 0x92, 0x2e, 0xe0, 0xfd, 0x5f, 0x8d, 0xdf, 0x82, 0x37, 0x18, 0xd8, 0x6d, 0x1e, 0x16, 0xc6, 0x09, 0x00, 0x71 }, - { 0xb0, 0x2d, 0x3e, 0xee, 0x48, 0x60, 0xd5, 0x86, 0x8b, 0x2c, 0x39, 0xce, 0x39, 0xbf, 0xe8, 0x10, 0x11, 0x29, 0x05, 0x64, 0xdd, 0x67, 0x8c, 0x85, 0xe8, 0x78, 0x3f, 0x29, 0x30, 0x2d, 0xfc, 0x13, 0x99, 0xba, 0x95, 0xb6, 0xb5, 0x3c, 0xd9, 0xeb, 0xbf, 0x40, 0x0c, 0xca, 0x1d, 0xb0, 0xab, 0x67, 0xe1, 0x9a, 0x32, 0x5f, 0x2d, 0x11, 0x58, 0x12, 0xd2, 0x5d, 0x00, 0x97, 0x8a, 0xd1, 0xbc, 0xa4 }, - { 0x76, 0x93, 0xea, 0x73, 0xaf, 0x3a, 0xc4, 0xda, 0xd2, 0x1c, 0xa0, 0xd8, 0xda, 0x85, 0xb3, 0x11, 0x8a, 0x7d, 0x1c, 0x60, 0x24, 0xcf, 0xaf, 0x55, 0x76, 0x99, 0x86, 0x82, 0x17, 0xbc, 0x0c, 0x2f, 0x44, 0xa1, 0x99, 0xbc, 0x6c, 0x0e, 0xdd, 0x51, 0x97, 0x98, 0xba, 0x05, 0xbd, 0x5b, 0x1b, 0x44, 0x84, 0x34, 0x6a, 0x47, 0xc2, 0xca, 0xdf, 0x6b, 0xf3, 0x0b, 0x78, 0x5c, 0xc8, 0x8b, 0x2b, 0xaf }, - { 0xa0, 0xe5, 0xc1, 0xc0, 0x03, 0x1c, 0x02, 0xe4, 0x8b, 0x7f, 0x09, 0xa5, 0xe8, 0x96, 0xee, 0x9a, 0xef, 0x2f, 0x17, 0xfc, 0x9e, 0x18, 0xe9, 0x97, 0xd7, 0xf6, 0xca, 0xc7, 0xae, 0x31, 0x64, 0x22, 0xc2, 0xb1, 0xe7, 0x79, 0x84, 0xe5, 0xf3, 0xa7, 0x3c, 0xb4, 0x5d, 0xee, 0xd5, 0xd3, 0xf8, 0x46, 0x00, 0x10, 0x5e, 0x6e, 0xe3, 0x8f, 0x2d, 0x09, 0x0c, 0x7d, 0x04, 0x42, 0xea, 0x34, 0xc4, 0x6d }, - { 0x41, 0xda, 0xa6, 0xad, 0xcf, 0xdb, 0x69, 0xf1, 0x44, 0x0c, 0x37, 0xb5, 0x96, 0x44, 0x01, 0x65, 0xc1, 0x5a, 0xda, 0x59, 0x68, 0x13, 0xe2, 0xe2, 0x2f, 0x06, 0x0f, 0xcd, 0x55, 0x1f, 0x24, 0xde, 0xe8, 0xe0, 0x4b, 0xa6, 0x89, 0x03, 0x87, 0x88, 0x6c, 0xee, 0xc4, 0xa7, 0xa0, 0xd7, 0xfc, 0x6b, 0x44, 0x50, 0x63, 0x92, 0xec, 0x38, 0x22, 0xc0, 0xd8, 0xc1, 0xac, 0xfc, 0x7d, 0x5a, 0xeb, 0xe8 }, - { 0x14, 0xd4, 0xd4, 0x0d, 0x59, 0x84, 0xd8, 0x4c, 0x5c, 0xf7, 0x52, 0x3b, 0x77, 0x98, 0xb2, 0x54, 0xe2, 0x75, 0xa3, 0xa8, 0xcc, 0x0a, 0x1b, 0xd0, 0x6e, 0xbc, 0x0b, 0xee, 0x72, 0x68, 0x56, 0xac, 0xc3, 0xcb, 0xf5, 0x16, 0xff, 0x66, 0x7c, 0xda, 0x20, 0x58, 0xad, 0x5c, 0x34, 0x12, 0x25, 0x44, 0x60, 0xa8, 0x2c, 0x92, 0x18, 0x70, 0x41, 0x36, 0x3c, 0xc7, 0x7a, 0x4d, 0xc2, 0x15, 0xe4, 0x87 }, - { 0xd0, 0xe7, 0xa1, 0xe2, 0xb9, 0xa4, 0x47, 0xfe, 0xe8, 0x3e, 0x22, 0x77, 0xe9, 0xff, 0x80, 0x10, 0xc2, 0xf3, 0x75, 0xae, 0x12, 0xfa, 0x7a, 0xaa, 0x8c, 0xa5, 0xa6, 0x31, 0x78, 0x68, 0xa2, 0x6a, 0x36, 0x7a, 0x0b, 0x69, 0xfb, 0xc1, 0xcf, 0x32, 0xa5, 0x5d, 0x34, 0xeb, 0x37, 0x06, 0x63, 0x01, 0x6f, 0x3d, 0x21, 0x10, 0x23, 0x0e, 0xba, 0x75, 0x40, 0x28, 0xa5, 0x6f, 0x54, 0xac, 0xf5, 0x7c }, - { 0xe7, 0x71, 0xaa, 0x8d, 0xb5, 0xa3, 0xe0, 0x43, 0xe8, 0x17, 0x8f, 0x39, 0xa0, 0x85, 0x7b, 0xa0, 0x4a, 0x3f, 0x18, 0xe4, 0xaa, 0x05, 0x74, 0x3c, 0xf8, 0xd2, 0x22, 0xb0, 0xb0, 0x95, 0x82, 0x53, 0x50, 0xba, 0x42, 0x2f, 0x63, 0x38, 0x2a, 0x23, 0xd9, 0x2e, 0x41, 0x49, 0x07, 0x4e, 0x81, 0x6a, 0x36, 0xc1, 0xcd, 0x28, 0x28, 0x4d, 0x14, 0x62, 0x67, 0x94, 0x0b, 0x31, 0xf8, 0x81, 0x8e, 0xa2 }, - { 0xfe, 0xb4, 0xfd, 0x6f, 0x9e, 0x87, 0xa5, 0x6b, 0xef, 0x39, 0x8b, 0x32, 0x84, 0xd2, 0xbd, 0xa5, 0xb5, 0xb0, 0xe1, 0x66, 0x58, 0x3a, 0x66, 0xb6, 0x1e, 0x53, 0x84, 0x57, 0xff, 0x05, 0x84, 0x87, 0x2c, 0x21, 0xa3, 0x29, 0x62, 0xb9, 0x92, 0x8f, 0xfa, 0xb5, 0x8d, 0xe4, 0xaf, 0x2e, 0xdd, 0x4e, 0x15, 0xd8, 0xb3, 0x55, 0x70, 0x52, 0x32, 0x07, 0xff, 0x4e, 0x2a, 0x5a, 0xa7, 0x75, 0x4c, 0xaa }, - { 0x46, 0x2f, 0x17, 0xbf, 0x00, 0x5f, 0xb1, 0xc1, 0xb9, 0xe6, 0x71, 0x77, 0x9f, 0x66, 0x52, 0x09, 0xec, 0x28, 0x73, 0xe3, 0xe4, 0x11, 0xf9, 0x8d, 0xab, 0xf2, 0x40, 0xa1, 0xd5, 0xec, 0x3f, 0x95, 0xce, 0x67, 0x96, 0xb6, 0xfc, 0x23, 0xfe, 0x17, 0x19, 0x03, 0xb5, 0x02, 0x02, 0x34, 0x67, 0xde, 0xc7, 0x27, 0x3f, 0xf7, 0x48, 0x79, 0xb9, 0x29, 0x67, 0xa2, 0xa4, 0x3a, 0x5a, 0x18, 0x3d, 0x33 }, - { 0xd3, 0x33, 0x81, 0x93, 0xb6, 0x45, 0x53, 0xdb, 0xd3, 0x8d, 0x14, 0x4b, 0xea, 0x71, 0xc5, 0x91, 0x5b, 0xb1, 0x10, 0xe2, 0xd8, 0x81, 0x80, 0xdb, 0xc5, 0xdb, 0x36, 0x4f, 0xd6, 0x17, 0x1d, 0xf3, 0x17, 0xfc, 0x72, 0x68, 0x83, 0x1b, 0x5a, 0xef, 0x75, 0xe4, 0x34, 0x2b, 0x2f, 0xad, 0x87, 0x97, 0xba, 0x39, 0xed, 0xdc, 0xef, 0x80, 0xe6, 0xec, 0x08, 0x15, 0x93, 0x50, 0xb1, 0xad, 0x69, 0x6d }, - { 0xe1, 0x59, 0x0d, 0x58, 0x5a, 0x3d, 0x39, 0xf7, 0xcb, 0x59, 0x9a, 0xbd, 0x47, 0x90, 0x70, 0x96, 0x64, 0x09, 0xa6, 0x84, 0x6d, 0x43, 0x77, 0xac, 0xf4, 0x47, 0x1d, 0x06, 0x5d, 0x5d, 0xb9, 0x41, 0x29, 0xcc, 0x9b, 0xe9, 0x25, 0x73, 0xb0, 0x5e, 0xd2, 0x26, 0xbe, 0x1e, 0x9b, 0x7c, 0xb0, 0xca, 0xbe, 0x87, 0x91, 0x85, 0x89, 0xf8, 0x0d, 0xad, 0xd4, 0xef, 0x5e, 0xf2, 0x5a, 0x93, 0xd2, 0x8e }, - { 0xf8, 0xf3, 0x72, 0x6a, 0xc5, 0xa2, 0x6c, 0xc8, 0x01, 0x32, 0x49, 0x3a, 0x6f, 0xed, 0xcb, 0x0e, 0x60, 0x76, 0x0c, 0x09, 0xcf, 0xc8, 0x4c, 0xad, 0x17, 0x81, 0x75, 0x98, 0x68, 0x19, 0x66, 0x5e, 0x76, 0x84, 0x2d, 0x7b, 0x9f, 0xed, 0xf7, 0x6d, 0xdd, 0xeb, 0xf5, 0xd3, 0xf5, 0x6f, 0xaa, 0xad, 0x44, 0x77, 0x58, 0x7a, 0xf2, 0x16, 0x06, 0xd3, 0x96, 0xae, 0x57, 0x0d, 0x8e, 0x71, 0x9a, 0xf2 }, - { 0x30, 0x18, 0x60, 0x55, 0xc0, 0x79, 0x49, 0x94, 0x81, 0x83, 0xc8, 0x50, 0xe9, 0xa7, 0x56, 0xcc, 0x09, 0x93, 0x7e, 0x24, 0x7d, 0x9d, 0x92, 0x8e, 0x86, 0x9e, 0x20, 0xba, 0xfc, 0x3c, 0xd9, 0x72, 0x17, 0x19, 0xd3, 0x4e, 0x04, 0xa0, 0x89, 0x9b, 0x92, 0xc7, 0x36, 0x08, 0x45, 0x50, 0x18, 0x68, 0x86, 0xef, 0xba, 0x2e, 0x79, 0x0d, 0x8b, 0xe6, 0xeb, 0xf0, 0x40, 0xb2, 0x09, 0xc4, 0x39, 0xa4 }, - { 0xf3, 0xc4, 0x27, 0x6c, 0xb8, 0x63, 0x63, 0x77, 0x12, 0xc2, 0x41, 0xc4, 0x44, 0xc5, 0xcc, 0x1e, 0x35, 0x54, 0xe0, 0xfd, 0xdb, 0x17, 0x4d, 0x03, 0x58, 0x19, 0xdd, 0x83, 0xeb, 0x70, 0x0b, 0x4c, 0xe8, 0x8d, 0xf3, 0xab, 0x38, 0x41, 0xba, 0x02, 0x08, 0x5e, 0x1a, 0x99, 0xb4, 0xe1, 0x73, 0x10, 0xc5, 0x34, 0x10, 0x75, 0xc0, 0x45, 0x8b, 0xa3, 0x76, 0xc9, 0x5a, 0x68, 0x18, 0xfb, 0xb3, 0xe2 }, - { 0x0a, 0xa0, 0x07, 0xc4, 0xdd, 0x9d, 0x58, 0x32, 0x39, 0x30, 0x40, 0xa1, 0x58, 0x3c, 0x93, 0x0b, 0xca, 0x7d, 0xc5, 0xe7, 0x7e, 0xa5, 0x3a, 0xdd, 0x7e, 0x2b, 0x3f, 0x7c, 0x8e, 0x23, 0x13, 0x68, 0x04, 0x35, 0x20, 0xd4, 0xa3, 0xef, 0x53, 0xc9, 0x69, 0xb6, 0xbb, 0xfd, 0x02, 0x59, 0x46, 0xf6, 0x32, 0xbd, 0x7f, 0x76, 0x5d, 0x53, 0xc2, 0x10, 0x03, 0xb8, 0xf9, 0x83, 0xf7, 0x5e, 0x2a, 0x6a }, - { 0x08, 0xe9, 0x46, 0x47, 0x20, 0x53, 0x3b, 0x23, 0xa0, 0x4e, 0xc2, 0x4f, 0x7a, 0xe8, 0xc1, 0x03, 0x14, 0x5f, 0x76, 0x53, 0x87, 0xd7, 0x38, 0x77, 0x7d, 0x3d, 0x34, 0x34, 0x77, 0xfd, 0x1c, 0x58, 0xdb, 0x05, 0x21, 0x42, 0xca, 0xb7, 0x54, 0xea, 0x67, 0x43, 0x78, 0xe1, 0x87, 0x66, 0xc5, 0x35, 0x42, 0xf7, 0x19, 0x70, 0x17, 0x1c, 0xc4, 0xf8, 0x16, 0x94, 0x24, 0x6b, 0x71, 0x7d, 0x75, 0x64 }, - { 0xd3, 0x7f, 0xf7, 0xad, 0x29, 0x79, 0x93, 0xe7, 0xec, 0x21, 0xe0, 0xf1, 0xb4, 0xb5, 0xae, 0x71, 0x9c, 0xdc, 0x83, 0xc5, 0xdb, 0x68, 0x75, 0x27, 0xf2, 0x75, 0x16, 0xcb, 0xff, 0xa8, 0x22, 0x88, 0x8a, 0x68, 0x10, 0xee, 0x5c, 0x1c, 0xa7, 0xbf, 0xe3, 0x32, 0x11, 0x19, 0xbe, 0x1a, 0xb7, 0xbf, 0xa0, 0xa5, 0x02, 0x67, 0x1c, 0x83, 0x29, 0x49, 0x4d, 0xf7, 0xad, 0x6f, 0x52, 0x2d, 0x44, 0x0f }, - { 0xdd, 0x90, 0x42, 0xf6, 0xe4, 0x64, 0xdc, 0xf8, 0x6b, 0x12, 0x62, 0xf6, 0xac, 0xcf, 0xaf, 0xbd, 0x8c, 0xfd, 0x90, 0x2e, 0xd3, 0xed, 0x89, 0xab, 0xf7, 0x8f, 0xfa, 0x48, 0x2d, 0xbd, 0xee, 0xb6, 0x96, 0x98, 0x42, 0x39, 0x4c, 0x9a, 0x11, 0x68, 0xae, 0x3d, 0x48, 0x1a, 0x01, 0x78, 0x42, 0xf6, 0x60, 0x00, 0x2d, 0x42, 0x44, 0x7c, 0x6b, 0x22, 0xf7, 0xb7, 0x2f, 0x21, 0xaa, 0xe0, 0x21, 0xc9 }, - { 0xbd, 0x96, 0x5b, 0xf3, 0x1e, 0x87, 0xd7, 0x03, 0x27, 0x53, 0x6f, 0x2a, 0x34, 0x1c, 0xeb, 0xc4, 0x76, 0x8e, 0xca, 0x27, 0x5f, 0xa0, 0x5e, 0xf9, 0x8f, 0x7f, 0x1b, 0x71, 0xa0, 0x35, 0x12, 0x98, 0xde, 0x00, 0x6f, 0xba, 0x73, 0xfe, 0x67, 0x33, 0xed, 0x01, 0xd7, 0x58, 0x01, 0xb4, 0xa9, 0x28, 0xe5, 0x42, 0x31, 0xb3, 0x8e, 0x38, 0xc5, 0x62, 0xb2, 0xe3, 0x3e, 0xa1, 0x28, 0x49, 0x92, 0xfa }, - { 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22 }, - { 0x93, 0x9f, 0xa1, 0x89, 0x69, 0x9c, 0x5d, 0x2c, 0x81, 0xdd, 0xd1, 0xff, 0xc1, 0xfa, 0x20, 0x7c, 0x97, 0x0b, 0x6a, 0x36, 0x85, 0xbb, 0x29, 0xce, 0x1d, 0x3e, 0x99, 0xd4, 0x2f, 0x2f, 0x74, 0x42, 0xda, 0x53, 0xe9, 0x5a, 0x72, 0x90, 0x73, 0x14, 0xf4, 0x58, 0x83, 0x99, 0xa3, 0xff, 0x5b, 0x0a, 0x92, 0xbe, 0xb3, 0xf6, 0xbe, 0x26, 0x94, 0xf9, 0xf8, 0x6e, 0xcf, 0x29, 0x52, 0xd5, 0xb4, 0x1c }, - { 0xc5, 0x16, 0x54, 0x17, 0x01, 0x86, 0x3f, 0x91, 0x00, 0x5f, 0x31, 0x41, 0x08, 0xce, 0xec, 0xe3, 0xc6, 0x43, 0xe0, 0x4f, 0xc8, 0xc4, 0x2f, 0xd2, 0xff, 0x55, 0x62, 0x20, 0xe6, 0x16, 0xaa, 0xa6, 0xa4, 0x8a, 0xeb, 0x97, 0xa8, 0x4b, 0xad, 0x74, 0x78, 0x2e, 0x8d, 0xff, 0x96, 0xa1, 0xa2, 0xfa, 0x94, 0x93, 0x39, 0xd7, 0x22, 0xed, 0xca, 0xa3, 0x2b, 0x57, 0x06, 0x70, 0x41, 0xdf, 0x88, 0xcc }, - { 0x98, 0x7f, 0xd6, 0xe0, 0xd6, 0x85, 0x7c, 0x55, 0x3e, 0xae, 0xbb, 0x3d, 0x34, 0x97, 0x0a, 0x2c, 0x2f, 0x6e, 0x89, 0xa3, 0x54, 0x8f, 0x49, 0x25, 0x21, 0x72, 0x2b, 0x80, 0xa1, 0xc2, 0x1a, 0x15, 0x38, 0x92, 0x34, 0x6d, 0x2c, 0xba, 0x64, 0x44, 0x21, 0x2d, 0x56, 0xda, 0x9a, 0x26, 0xe3, 0x24, 0xdc, 0xcb, 0xc0, 0xdc, 0xde, 0x85, 0xd4, 0xd2, 0xee, 0x43, 0x99, 0xee, 0xc5, 0xa6, 0x4e, 0x8f }, - { 0xae, 0x56, 0xde, 0xb1, 0xc2, 0x32, 0x8d, 0x9c, 0x40, 0x17, 0x70, 0x6b, 0xce, 0x6e, 0x99, 0xd4, 0x13, 0x49, 0x05, 0x3b, 0xa9, 0xd3, 0x36, 0xd6, 0x77, 0xc4, 0xc2, 0x7d, 0x9f, 0xd5, 0x0a, 0xe6, 0xae, 0xe1, 0x7e, 0x85, 0x31, 0x54, 0xe1, 0xf4, 0xfe, 0x76, 0x72, 0x34, 0x6d, 0xa2, 0xea, 0xa3, 0x1e, 0xea, 0x53, 0xfc, 0xf2, 0x4a, 0x22, 0x80, 0x4f, 0x11, 0xd0, 0x3d, 0xa6, 0xab, 0xfc, 0x2b }, - { 0x49, 0xd6, 0xa6, 0x08, 0xc9, 0xbd, 0xe4, 0x49, 0x18, 0x70, 0x49, 0x85, 0x72, 0xac, 0x31, 0xaa, 0xc3, 0xfa, 0x40, 0x93, 0x8b, 0x38, 0xa7, 0x81, 0x8f, 0x72, 0x38, 0x3e, 0xb0, 0x40, 0xad, 0x39, 0x53, 0x2b, 0xc0, 0x65, 0x71, 0xe1, 0x3d, 0x76, 0x7e, 0x69, 0x45, 0xab, 0x77, 0xc0, 0xbd, 0xc3, 0xb0, 0x28, 0x42, 0x53, 0x34, 0x3f, 0x9f, 0x6c, 0x12, 0x44, 0xeb, 0xf2, 0xff, 0x0d, 0xf8, 0x66 }, - { 0xda, 0x58, 0x2a, 0xd8, 0xc5, 0x37, 0x0b, 0x44, 0x69, 0xaf, 0x86, 0x2a, 0xa6, 0x46, 0x7a, 0x22, 0x93, 0xb2, 0xb2, 0x8b, 0xd8, 0x0a, 0xe0, 0xe9, 0x1f, 0x42, 0x5a, 0xd3, 0xd4, 0x72, 0x49, 0xfd, 0xf9, 0x88, 0x25, 0xcc, 0x86, 0xf1, 0x40, 0x28, 0xc3, 0x30, 0x8c, 0x98, 0x04, 0xc7, 0x8b, 0xfe, 0xee, 0xee, 0x46, 0x14, 0x44, 0xce, 0x24, 0x36, 0x87, 0xe1, 0xa5, 0x05, 0x22, 0x45, 0x6a, 0x1d }, - { 0xd5, 0x26, 0x6a, 0xa3, 0x33, 0x11, 0x94, 0xae, 0xf8, 0x52, 0xee, 0xd8, 0x6d, 0x7b, 0x5b, 0x26, 0x33, 0xa0, 0xaf, 0x1c, 0x73, 0x59, 0x06, 0xf2, 0xe1, 0x32, 0x79, 0xf1, 0x49, 0x31, 0xa9, 0xfc, 0x3b, 0x0e, 0xac, 0x5c, 0xe9, 0x24, 0x52, 0x73, 0xbd, 0x1a, 0xa9, 0x29, 0x05, 0xab, 0xe1, 0x62, 0x78, 0xef, 0x7e, 0xfd, 0x47, 0x69, 0x47, 0x89, 0xa7, 0x28, 0x3b, 0x77, 0xda, 0x3c, 0x70, 0xf8 }, - { 0x29, 0x62, 0x73, 0x4c, 0x28, 0x25, 0x21, 0x86, 0xa9, 0xa1, 0x11, 0x1c, 0x73, 0x2a, 0xd4, 0xde, 0x45, 0x06, 0xd4, 0xb4, 0x48, 0x09, 0x16, 0x30, 0x3e, 0xb7, 0x99, 0x1d, 0x65, 0x9c, 0xcd, 0xa0, 0x7a, 0x99, 0x11, 0x91, 0x4b, 0xc7, 0x5c, 0x41, 0x8a, 0xb7, 0xa4, 0x54, 0x17, 0x57, 0xad, 0x05, 0x47, 0x96, 0xe2, 0x67, 0x97, 0xfe, 0xaf, 0x36, 0xe9, 0xf6, 0xad, 0x43, 0xf1, 0x4b, 0x35, 0xa4 }, - { 0xe8, 0xb7, 0x9e, 0xc5, 0xd0, 0x6e, 0x11, 0x1b, 0xdf, 0xaf, 0xd7, 0x1e, 0x9f, 0x57, 0x60, 0xf0, 0x0a, 0xc8, 0xac, 0x5d, 0x8b, 0xf7, 0x68, 0xf9, 0xff, 0x6f, 0x08, 0xb8, 0xf0, 0x26, 0x09, 0x6b, 0x1c, 0xc3, 0xa4, 0xc9, 0x73, 0x33, 0x30, 0x19, 0xf1, 0xe3, 0x55, 0x3e, 0x77, 0xda, 0x3f, 0x98, 0xcb, 0x9f, 0x54, 0x2e, 0x0a, 0x90, 0xe5, 0xf8, 0xa9, 0x40, 0xcc, 0x58, 0xe5, 0x98, 0x44, 0xb3 }, - { 0xdf, 0xb3, 0x20, 0xc4, 0x4f, 0x9d, 0x41, 0xd1, 0xef, 0xdc, 0xc0, 0x15, 0xf0, 0x8d, 0xd5, 0x53, 0x9e, 0x52, 0x6e, 0x39, 0xc8, 0x7d, 0x50, 0x9a, 0xe6, 0x81, 0x2a, 0x96, 0x9e, 0x54, 0x31, 0xbf, 0x4f, 0xa7, 0xd9, 0x1f, 0xfd, 0x03, 0xb9, 0x81, 0xe0, 0xd5, 0x44, 0xcf, 0x72, 0xd7, 0xb1, 0xc0, 0x37, 0x4f, 0x88, 0x01, 0x48, 0x2e, 0x6d, 0xea, 0x2e, 0xf9, 0x03, 0x87, 0x7e, 0xba, 0x67, 0x5e }, - { 0xd8, 0x86, 0x75, 0x11, 0x8f, 0xdb, 0x55, 0xa5, 0xfb, 0x36, 0x5a, 0xc2, 0xaf, 0x1d, 0x21, 0x7b, 0xf5, 0x26, 0xce, 0x1e, 0xe9, 0xc9, 0x4b, 0x2f, 0x00, 0x90, 0xb2, 0xc5, 0x8a, 0x06, 0xca, 0x58, 0x18, 0x7d, 0x7f, 0xe5, 0x7c, 0x7b, 0xed, 0x9d, 0x26, 0xfc, 0xa0, 0x67, 0xb4, 0x11, 0x0e, 0xef, 0xcd, 0x9a, 0x0a, 0x34, 0x5d, 0xe8, 0x72, 0xab, 0xe2, 0x0d, 0xe3, 0x68, 0x00, 0x1b, 0x07, 0x45 }, - { 0xb8, 0x93, 0xf2, 0xfc, 0x41, 0xf7, 0xb0, 0xdd, 0x6e, 0x2f, 0x6a, 0xa2, 0xe0, 0x37, 0x0c, 0x0c, 0xff, 0x7d, 0xf0, 0x9e, 0x3a, 0xcf, 0xcc, 0x0e, 0x92, 0x0b, 0x6e, 0x6f, 0xad, 0x0e, 0xf7, 0x47, 0xc4, 0x06, 0x68, 0x41, 0x7d, 0x34, 0x2b, 0x80, 0xd2, 0x35, 0x1e, 0x8c, 0x17, 0x5f, 0x20, 0x89, 0x7a, 0x06, 0x2e, 0x97, 0x65, 0xe6, 0xc6, 0x7b, 0x53, 0x9b, 0x6b, 0xa8, 0xb9, 0x17, 0x05, 0x45 }, - { 0x6c, 0x67, 0xec, 0x56, 0x97, 0xac, 0xcd, 0x23, 0x5c, 0x59, 0xb4, 0x86, 0xd7, 0xb7, 0x0b, 0xae, 0xed, 0xcb, 0xd4, 0xaa, 0x64, 0xeb, 0xd4, 0xee, 0xf3, 0xc7, 0xea, 0xc1, 0x89, 0x56, 0x1a, 0x72, 0x62, 0x50, 0xae, 0xc4, 0xd4, 0x8c, 0xad, 0xca, 0xfb, 0xbe, 0x2c, 0xe3, 0xc1, 0x6c, 0xe2, 0xd6, 0x91, 0xa8, 0xcc, 0xe0, 0x6e, 0x88, 0x79, 0x55, 0x6d, 0x44, 0x83, 0xed, 0x71, 0x65, 0xc0, 0x63 }, - { 0xf1, 0xaa, 0x2b, 0x04, 0x4f, 0x8f, 0x0c, 0x63, 0x8a, 0x3f, 0x36, 0x2e, 0x67, 0x7b, 0x5d, 0x89, 0x1d, 0x6f, 0xd2, 0xab, 0x07, 0x65, 0xf6, 0xee, 0x1e, 0x49, 0x87, 0xde, 0x05, 0x7e, 0xad, 0x35, 0x78, 0x83, 0xd9, 0xb4, 0x05, 0xb9, 0xd6, 0x09, 0xee, 0xa1, 0xb8, 0x69, 0xd9, 0x7f, 0xb1, 0x6d, 0x9b, 0x51, 0x01, 0x7c, 0x55, 0x3f, 0x3b, 0x93, 0xc0, 0xa1, 0xe0, 0xf1, 0x29, 0x6f, 0xed, 0xcd }, - { 0xcb, 0xaa, 0x25, 0x95, 0x72, 0xd4, 0xae, 0xbf, 0xc1, 0x91, 0x7a, 0xcd, 0xdc, 0x58, 0x2b, 0x9f, 0x8d, 0xfa, 0xa9, 0x28, 0xa1, 0x98, 0xca, 0x7a, 0xcd, 0x0f, 0x2a, 0xa7, 0x6a, 0x13, 0x4a, 0x90, 0x25, 0x2e, 0x62, 0x98, 0xa6, 0x5b, 0x08, 0x18, 0x6a, 0x35, 0x0d, 0x5b, 0x76, 0x26, 0x69, 0x9f, 0x8c, 0xb7, 0x21, 0xa3, 0xea, 0x59, 0x21, 0xb7, 0x53, 0xae, 0x3a, 0x2d, 0xce, 0x24, 0xba, 0x3a }, - { 0xfa, 0x15, 0x49, 0xc9, 0x79, 0x6c, 0xd4, 0xd3, 0x03, 0xdc, 0xf4, 0x52, 0xc1, 0xfb, 0xd5, 0x74, 0x4f, 0xd9, 0xb9, 0xb4, 0x70, 0x03, 0xd9, 0x20, 0xb9, 0x2d, 0xe3, 0x48, 0x39, 0xd0, 0x7e, 0xf2, 0xa2, 0x9d, 0xed, 0x68, 0xf6, 0xfc, 0x9e, 0x6c, 0x45, 0xe0, 0x71, 0xa2, 0xe4, 0x8b, 0xd5, 0x0c, 0x50, 0x84, 0xe9, 0x6b, 0x65, 0x7d, 0xd0, 0x40, 0x40, 0x45, 0xa1, 0xdd, 0xef, 0xe2, 0x82, 0xed }, - { 0x5c, 0xf2, 0xac, 0x89, 0x7a, 0xb4, 0x44, 0xdc, 0xb5, 0xc8, 0xd8, 0x7c, 0x49, 0x5d, 0xbd, 0xb3, 0x4e, 0x18, 0x38, 0xb6, 0xb6, 0x29, 0x42, 0x7c, 0xaa, 0x51, 0x70, 0x2a, 0xd0, 0xf9, 0x68, 0x85, 0x25, 0xf1, 0x3b, 0xec, 0x50, 0x3a, 0x3c, 0x3a, 0x2c, 0x80, 0xa6, 0x5e, 0x0b, 0x57, 0x15, 0xe8, 0xaf, 0xab, 0x00, 0xff, 0xa5, 0x6e, 0xc4, 0x55, 0xa4, 0x9a, 0x1a, 0xd3, 0x0a, 0xa2, 0x4f, 0xcd }, - { 0x9a, 0xaf, 0x80, 0x20, 0x7b, 0xac, 0xe1, 0x7b, 0xb7, 0xab, 0x14, 0x57, 0x57, 0xd5, 0x69, 0x6b, 0xde, 0x32, 0x40, 0x6e, 0xf2, 0x2b, 0x44, 0x29, 0x2e, 0xf6, 0x5d, 0x45, 0x19, 0xc3, 0xbb, 0x2a, 0xd4, 0x1a, 0x59, 0xb6, 0x2c, 0xc3, 0xe9, 0x4b, 0x6f, 0xa9, 0x6d, 0x32, 0xa7, 0xfa, 0xad, 0xae, 0x28, 0xaf, 0x7d, 0x35, 0x09, 0x72, 0x19, 0xaa, 0x3f, 0xd8, 0xcd, 0xa3, 0x1e, 0x40, 0xc2, 0x75 }, - { 0xaf, 0x88, 0xb1, 0x63, 0x40, 0x2c, 0x86, 0x74, 0x5c, 0xb6, 0x50, 0xc2, 0x98, 0x8f, 0xb9, 0x52, 0x11, 0xb9, 0x4b, 0x03, 0xef, 0x29, 0x0e, 0xed, 0x96, 0x62, 0x03, 0x42, 0x41, 0xfd, 0x51, 0xcf, 0x39, 0x8f, 0x80, 0x73, 0xe3, 0x69, 0x35, 0x4c, 0x43, 0xea, 0xe1, 0x05, 0x2f, 0x9b, 0x63, 0xb0, 0x81, 0x91, 0xca, 0xa1, 0x38, 0xaa, 0x54, 0xfe, 0xa8, 0x89, 0xcc, 0x70, 0x24, 0x23, 0x68, 0x97 }, - { 0x48, 0xfa, 0x7d, 0x64, 0xe1, 0xce, 0xee, 0x27, 0xb9, 0x86, 0x4d, 0xb5, 0xad, 0xa4, 0xb5, 0x3d, 0x00, 0xc9, 0xbc, 0x76, 0x26, 0x55, 0x58, 0x13, 0xd3, 0xcd, 0x67, 0x30, 0xab, 0x3c, 0xc0, 0x6f, 0xf3, 0x42, 0xd7, 0x27, 0x90, 0x5e, 0x33, 0x17, 0x1b, 0xde, 0x6e, 0x84, 0x76, 0xe7, 0x7f, 0xb1, 0x72, 0x08, 0x61, 0xe9, 0x4b, 0x73, 0xa2, 0xc5, 0x38, 0xd2, 0x54, 0x74, 0x62, 0x85, 0xf4, 0x30 }, - { 0x0e, 0x6f, 0xd9, 0x7a, 0x85, 0xe9, 0x04, 0xf8, 0x7b, 0xfe, 0x85, 0xbb, 0xeb, 0x34, 0xf6, 0x9e, 0x1f, 0x18, 0x10, 0x5c, 0xf4, 0xed, 0x4f, 0x87, 0xae, 0xc3, 0x6c, 0x6e, 0x8b, 0x5f, 0x68, 0xbd, 0x2a, 0x6f, 0x3d, 0xc8, 0xa9, 0xec, 0xb2, 0xb6, 0x1d, 0xb4, 0xee, 0xdb, 0x6b, 0x2e, 0xa1, 0x0b, 0xf9, 0xcb, 0x02, 0x51, 0xfb, 0x0f, 0x8b, 0x34, 0x4a, 0xbf, 0x7f, 0x36, 0x6b, 0x6d, 0xe5, 0xab }, - { 0x06, 0x62, 0x2d, 0xa5, 0x78, 0x71, 0x76, 0x28, 0x7f, 0xdc, 0x8f, 0xed, 0x44, 0x0b, 0xad, 0x18, 0x7d, 0x83, 0x00, 0x99, 0xc9, 0x4e, 0x6d, 0x04, 0xc8, 0xe9, 0xc9, 0x54, 0xcd, 0xa7, 0x0c, 0x8b, 0xb9, 0xe1, 0xfc, 0x4a, 0x6d, 0x0b, 0xaa, 0x83, 0x1b, 0x9b, 0x78, 0xef, 0x66, 0x48, 0x68, 0x1a, 0x48, 0x67, 0xa1, 0x1d, 0xa9, 0x3e, 0xe3, 0x6e, 0x5e, 0x6a, 0x37, 0xd8, 0x7f, 0xc6, 0x3f, 0x6f }, - { 0x1d, 0xa6, 0x77, 0x2b, 0x58, 0xfa, 0xbf, 0x9c, 0x61, 0xf6, 0x8d, 0x41, 0x2c, 0x82, 0xf1, 0x82, 0xc0, 0x23, 0x6d, 0x7d, 0x57, 0x5e, 0xf0, 0xb5, 0x8d, 0xd2, 0x24, 0x58, 0xd6, 0x43, 0xcd, 0x1d, 0xfc, 0x93, 0xb0, 0x38, 0x71, 0xc3, 0x16, 0xd8, 0x43, 0x0d, 0x31, 0x29, 0x95, 0xd4, 0x19, 0x7f, 0x08, 0x74, 0xc9, 0x91, 0x72, 0xba, 0x00, 0x4a, 0x01, 0xee, 0x29, 0x5a, 0xba, 0xc2, 0x4e, 0x46 }, - { 0x3c, 0xd2, 0xd9, 0x32, 0x0b, 0x7b, 0x1d, 0x5f, 0xb9, 0xaa, 0xb9, 0x51, 0xa7, 0x60, 0x23, 0xfa, 0x66, 0x7b, 0xe1, 0x4a, 0x91, 0x24, 0xe3, 0x94, 0x51, 0x39, 0x18, 0xa3, 0xf4, 0x40, 0x96, 0xae, 0x49, 0x04, 0xba, 0x0f, 0xfc, 0x15, 0x0b, 0x63, 0xbc, 0x7a, 0xb1, 0xee, 0xb9, 0xa6, 0xe2, 0x57, 0xe5, 0xc8, 0xf0, 0x00, 0xa7, 0x03, 0x94, 0xa5, 0xaf, 0xd8, 0x42, 0x71, 0x5d, 0xe1, 0x5f, 0x29 }, - { 0x04, 0xcd, 0xc1, 0x4f, 0x74, 0x34, 0xe0, 0xb4, 0xbe, 0x70, 0xcb, 0x41, 0xdb, 0x4c, 0x77, 0x9a, 0x88, 0xea, 0xef, 0x6a, 0xcc, 0xeb, 0xcb, 0x41, 0xf2, 0xd4, 0x2f, 0xff, 0xe7, 0xf3, 0x2a, 0x8e, 0x28, 0x1b, 0x5c, 0x10, 0x3a, 0x27, 0x02, 0x1d, 0x0d, 0x08, 0x36, 0x22, 0x50, 0x75, 0x3c, 0xdf, 0x70, 0x29, 0x21, 0x95, 0xa5, 0x3a, 0x48, 0x72, 0x8c, 0xeb, 0x58, 0x44, 0xc2, 0xd9, 0x8b, 0xab }, - { 0x90, 0x71, 0xb7, 0xa8, 0xa0, 0x75, 0xd0, 0x09, 0x5b, 0x8f, 0xb3, 0xae, 0x51, 0x13, 0x78, 0x57, 0x35, 0xab, 0x98, 0xe2, 0xb5, 0x2f, 0xaf, 0x91, 0xd5, 0xb8, 0x9e, 0x44, 0xaa, 0xc5, 0xb5, 0xd4, 0xeb, 0xbf, 0x91, 0x22, 0x3b, 0x0f, 0xf4, 0xc7, 0x19, 0x05, 0xda, 0x55, 0x34, 0x2e, 0x64, 0x65, 0x5d, 0x6e, 0xf8, 0xc8, 0x9a, 0x47, 0x68, 0xc3, 0xf9, 0x3a, 0x6d, 0xc0, 0x36, 0x6b, 0x5b, 0xc8 }, - { 0xeb, 0xb3, 0x02, 0x40, 0xdd, 0x96, 0xc7, 0xbc, 0x8d, 0x0a, 0xbe, 0x49, 0xaa, 0x4e, 0xdc, 0xbb, 0x4a, 0xfd, 0xc5, 0x1f, 0xf9, 0xaa, 0xf7, 0x20, 0xd3, 0xf9, 0xe7, 0xfb, 0xb0, 0xf9, 0xc6, 0xd6, 0x57, 0x13, 0x50, 0x50, 0x17, 0x69, 0xfc, 0x4e, 0xbd, 0x0b, 0x21, 0x41, 0x24, 0x7f, 0xf4, 0x00, 0xd4, 0xfd, 0x4b, 0xe4, 0x14, 0xed, 0xf3, 0x77, 0x57, 0xbb, 0x90, 0xa3, 0x2a, 0xc5, 0xc6, 0x5a }, - { 0x85, 0x32, 0xc5, 0x8b, 0xf3, 0xc8, 0x01, 0x5d, 0x9d, 0x1c, 0xbe, 0x00, 0xee, 0xf1, 0xf5, 0x08, 0x2f, 0x8f, 0x36, 0x32, 0xfb, 0xe9, 0xf1, 0xed, 0x4f, 0x9d, 0xfb, 0x1f, 0xa7, 0x9e, 0x82, 0x83, 0x06, 0x6d, 0x77, 0xc4, 0x4c, 0x4a, 0xf9, 0x43, 0xd7, 0x6b, 0x30, 0x03, 0x64, 0xae, 0xcb, 0xd0, 0x64, 0x8c, 0x8a, 0x89, 0x39, 0xbd, 0x20, 0x41, 0x23, 0xf4, 0xb5, 0x62, 0x60, 0x42, 0x2d, 0xec }, - { 0xfe, 0x98, 0x46, 0xd6, 0x4f, 0x7c, 0x77, 0x08, 0x69, 0x6f, 0x84, 0x0e, 0x2d, 0x76, 0xcb, 0x44, 0x08, 0xb6, 0x59, 0x5c, 0x2f, 0x81, 0xec, 0x6a, 0x28, 0xa7, 0xf2, 0xf2, 0x0c, 0xb8, 0x8c, 0xfe, 0x6a, 0xc0, 0xb9, 0xe9, 0xb8, 0x24, 0x4f, 0x08, 0xbd, 0x70, 0x95, 0xc3, 0x50, 0xc1, 0xd0, 0x84, 0x2f, 0x64, 0xfb, 0x01, 0xbb, 0x7f, 0x53, 0x2d, 0xfc, 0xd4, 0x73, 0x71, 0xb0, 0xae, 0xeb, 0x79 }, - { 0x28, 0xf1, 0x7e, 0xa6, 0xfb, 0x6c, 0x42, 0x09, 0x2d, 0xc2, 0x64, 0x25, 0x7e, 0x29, 0x74, 0x63, 0x21, 0xfb, 0x5b, 0xda, 0xea, 0x98, 0x73, 0xc2, 0xa7, 0xfa, 0x9d, 0x8f, 0x53, 0x81, 0x8e, 0x89, 0x9e, 0x16, 0x1b, 0xc7, 0x7d, 0xfe, 0x80, 0x90, 0xaf, 0xd8, 0x2b, 0xf2, 0x26, 0x6c, 0x5c, 0x1b, 0xc9, 0x30, 0xa8, 0xd1, 0x54, 0x76, 0x24, 0x43, 0x9e, 0x66, 0x2e, 0xf6, 0x95, 0xf2, 0x6f, 0x24 }, - { 0xec, 0x6b, 0x7d, 0x7f, 0x03, 0x0d, 0x48, 0x50, 0xac, 0xae, 0x3c, 0xb6, 0x15, 0xc2, 0x1d, 0xd2, 0x52, 0x06, 0xd6, 0x3e, 0x84, 0xd1, 0xdb, 0x8d, 0x95, 0x73, 0x70, 0x73, 0x7b, 0xa0, 0xe9, 0x84, 0x67, 0xea, 0x0c, 0xe2, 0x74, 0xc6, 0x61, 0x99, 0x90, 0x1e, 0xae, 0xc1, 0x8a, 0x08, 0x52, 0x57, 0x15, 0xf5, 0x3b, 0xfd, 0xb0, 0xaa, 0xcb, 0x61, 0x3d, 0x34, 0x2e, 0xbd, 0xce, 0xed, 0xdc, 0x3b }, - { 0xb4, 0x03, 0xd3, 0x69, 0x1c, 0x03, 0xb0, 0xd3, 0x41, 0x8d, 0xf3, 0x27, 0xd5, 0x86, 0x0d, 0x34, 0xbb, 0xfc, 0xc4, 0x51, 0x9b, 0xfb, 0xce, 0x36, 0xbf, 0x33, 0xb2, 0x08, 0x38, 0x5f, 0xad, 0xb9, 0x18, 0x6b, 0xc7, 0x8a, 0x76, 0xc4, 0x89, 0xd8, 0x9f, 0xd5, 0x7e, 0x7d, 0xc7, 0x54, 0x12, 0xd2, 0x3b, 0xcd, 0x1d, 0xae, 0x84, 0x70, 0xce, 0x92, 0x74, 0x75, 0x4b, 0xb8, 0x58, 0x5b, 0x13, 0xc5 }, - { 0x31, 0xfc, 0x79, 0x73, 0x8b, 0x87, 0x72, 0xb3, 0xf5, 0x5c, 0xd8, 0x17, 0x88, 0x13, 0xb3, 0xb5, 0x2d, 0x0d, 0xb5, 0xa4, 0x19, 0xd3, 0x0b, 0xa9, 0x49, 0x5c, 0x4b, 0x9d, 0xa0, 0x21, 0x9f, 0xac, 0x6d, 0xf8, 0xe7, 0xc2, 0x3a, 0x81, 0x15, 0x51, 0xa6, 0x2b, 0x82, 0x7f, 0x25, 0x6e, 0xcd, 0xb8, 0x12, 0x4a, 0xc8, 0xa6, 0x79, 0x2c, 0xcf, 0xec, 0xc3, 0xb3, 0x01, 0x27, 0x22, 0xe9, 0x44, 0x63 }, - { 0xbb, 0x20, 0x39, 0xec, 0x28, 0x70, 0x91, 0xbc, 0xc9, 0x64, 0x2f, 0xc9, 0x00, 0x49, 0xe7, 0x37, 0x32, 0xe0, 0x2e, 0x57, 0x7e, 0x28, 0x62, 0xb3, 0x22, 0x16, 0xae, 0x9b, 0xed, 0xcd, 0x73, 0x0c, 0x4c, 0x28, 0x4e, 0xf3, 0x96, 0x8c, 0x36, 0x8b, 0x7d, 0x37, 0x58, 0x4f, 0x97, 0xbd, 0x4b, 0x4d, 0xc6, 0xef, 0x61, 0x27, 0xac, 0xfe, 0x2e, 0x6a, 0xe2, 0x50, 0x91, 0x24, 0xe6, 0x6c, 0x8a, 0xf4 }, - { 0xf5, 0x3d, 0x68, 0xd1, 0x3f, 0x45, 0xed, 0xfc, 0xb9, 0xbd, 0x41, 0x5e, 0x28, 0x31, 0xe9, 0x38, 0x35, 0x0d, 0x53, 0x80, 0xd3, 0x43, 0x22, 0x78, 0xfc, 0x1c, 0x0c, 0x38, 0x1f, 0xcb, 0x7c, 0x65, 0xc8, 0x2d, 0xaf, 0xe0, 0x51, 0xd8, 0xc8, 0xb0, 0xd4, 0x4e, 0x09, 0x74, 0xa0, 0xe5, 0x9e, 0xc7, 0xbf, 0x7e, 0xd0, 0x45, 0x9f, 0x86, 0xe9, 0x6f, 0x32, 0x9f, 0xc7, 0x97, 0x52, 0x51, 0x0f, 0xd3 }, - { 0x8d, 0x56, 0x8c, 0x79, 0x84, 0xf0, 0xec, 0xdf, 0x76, 0x40, 0xfb, 0xc4, 0x83, 0xb5, 0xd8, 0xc9, 0xf8, 0x66, 0x34, 0xf6, 0xf4, 0x32, 0x91, 0x84, 0x1b, 0x30, 0x9a, 0x35, 0x0a, 0xb9, 0xc1, 0x13, 0x7d, 0x24, 0x06, 0x6b, 0x09, 0xda, 0x99, 0x44, 0xba, 0xc5, 0x4d, 0x5b, 0xb6, 0x58, 0x0d, 0x83, 0x60, 0x47, 0xaa, 0xc7, 0x4a, 0xb7, 0x24, 0xb8, 0x87, 0xeb, 0xf9, 0x3d, 0x4b, 0x32, 0xec, 0xa9 }, - { 0xc0, 0xb6, 0x5c, 0xe5, 0xa9, 0x6f, 0xf7, 0x74, 0xc4, 0x56, 0xca, 0xc3, 0xb5, 0xf2, 0xc4, 0xcd, 0x35, 0x9b, 0x4f, 0xf5, 0x3e, 0xf9, 0x3a, 0x3d, 0xa0, 0x77, 0x8b, 0xe4, 0x90, 0x0d, 0x1e, 0x8d, 0xa1, 0x60, 0x1e, 0x76, 0x9e, 0x8f, 0x1b, 0x02, 0xd2, 0xa2, 0xf8, 0xc5, 0xb9, 0xfa, 0x10, 0xb4, 0x4f, 0x1c, 0x18, 0x69, 0x85, 0x46, 0x8f, 0xee, 0xb0, 0x08, 0x73, 0x02, 0x83, 0xa6, 0x65, 0x7d }, - { 0x49, 0x00, 0xbb, 0xa6, 0xf5, 0xfb, 0x10, 0x3e, 0xce, 0x8e, 0xc9, 0x6a, 0xda, 0x13, 0xa5, 0xc3, 0xc8, 0x54, 0x88, 0xe0, 0x55, 0x51, 0xda, 0x6b, 0x6b, 0x33, 0xd9, 0x88, 0xe6, 0x11, 0xec, 0x0f, 0xe2, 0xe3, 0xc2, 0xaa, 0x48, 0xea, 0x6a, 0xe8, 0x98, 0x6a, 0x3a, 0x23, 0x1b, 0x22, 0x3c, 0x5d, 0x27, 0xce, 0xc2, 0xea, 0xdd, 0xe9, 0x1c, 0xe0, 0x79, 0x81, 0xee, 0x65, 0x28, 0x62, 0xd1, 0xe4 }, - { 0xc7, 0xf5, 0xc3, 0x7c, 0x72, 0x85, 0xf9, 0x27, 0xf7, 0x64, 0x43, 0x41, 0x4d, 0x43, 0x57, 0xff, 0x78, 0x96, 0x47, 0xd7, 0xa0, 0x05, 0xa5, 0xa7, 0x87, 0xe0, 0x3c, 0x34, 0x6b, 0x57, 0xf4, 0x9f, 0x21, 0xb6, 0x4f, 0xa9, 0xcf, 0x4b, 0x7e, 0x45, 0x57, 0x3e, 0x23, 0x04, 0x90, 0x17, 0x56, 0x71, 0x21, 0xa9, 0xc3, 0xd4, 0xb2, 0xb7, 0x3e, 0xc5, 0xe9, 0x41, 0x35, 0x77, 0x52, 0x5d, 0xb4, 0x5a }, - { 0xec, 0x70, 0x96, 0x33, 0x07, 0x36, 0xfd, 0xb2, 0xd6, 0x4b, 0x56, 0x53, 0xe7, 0x47, 0x5d, 0xa7, 0x46, 0xc2, 0x3a, 0x46, 0x13, 0xa8, 0x26, 0x87, 0xa2, 0x80, 0x62, 0xd3, 0x23, 0x63, 0x64, 0x28, 0x4a, 0xc0, 0x17, 0x20, 0xff, 0xb4, 0x06, 0xcf, 0xe2, 0x65, 0xc0, 0xdf, 0x62, 0x6a, 0x18, 0x8c, 0x9e, 0x59, 0x63, 0xac, 0xe5, 0xd3, 0xd5, 0xbb, 0x36, 0x3e, 0x32, 0xc3, 0x8c, 0x21, 0x90, 0xa6 }, - { 0x82, 0xe7, 0x44, 0xc7, 0x5f, 0x46, 0x49, 0xec, 0x52, 0xb8, 0x07, 0x71, 0xa7, 0x7d, 0x47, 0x5a, 0x3b, 0xc0, 0x91, 0x98, 0x95, 0x56, 0x96, 0x0e, 0x27, 0x6a, 0x5f, 0x9e, 0xad, 0x92, 0xa0, 0x3f, 0x71, 0x87, 0x42, 0xcd, 0xcf, 0xea, 0xee, 0x5c, 0xb8, 0x5c, 0x44, 0xaf, 0x19, 0x8a, 0xdc, 0x43, 0xa4, 0xa4, 0x28, 0xf5, 0xf0, 0xc2, 0xdd, 0xb0, 0xbe, 0x36, 0x05, 0x9f, 0x06, 0xd7, 0xdf, 0x73 }, - { 0x28, 0x34, 0xb7, 0xa7, 0x17, 0x0f, 0x1f, 0x5b, 0x68, 0x55, 0x9a, 0xb7, 0x8c, 0x10, 0x50, 0xec, 0x21, 0xc9, 0x19, 0x74, 0x0b, 0x78, 0x4a, 0x90, 0x72, 0xf6, 0xe5, 0xd6, 0x9f, 0x82, 0x8d, 0x70, 0xc9, 0x19, 0xc5, 0x03, 0x9f, 0xb1, 0x48, 0xe3, 0x9e, 0x2c, 0x8a, 0x52, 0x11, 0x83, 0x78, 0xb0, 0x64, 0xca, 0x8d, 0x50, 0x01, 0xcd, 0x10, 0xa5, 0x47, 0x83, 0x87, 0xb9, 0x66, 0x71, 0x5e, 0xd6 }, - { 0x16, 0xb4, 0xad, 0xa8, 0x83, 0xf7, 0x2f, 0x85, 0x3b, 0xb7, 0xef, 0x25, 0x3e, 0xfc, 0xab, 0x0c, 0x3e, 0x21, 0x61, 0x68, 0x7a, 0xd6, 0x15, 0x43, 0xa0, 0xd2, 0x82, 0x4f, 0x91, 0xc1, 0xf8, 0x13, 0x47, 0xd8, 0x6b, 0xe7, 0x09, 0xb1, 0x69, 0x96, 0xe1, 0x7f, 0x2d, 0xd4, 0x86, 0x92, 0x7b, 0x02, 0x88, 0xad, 0x38, 0xd1, 0x30, 0x63, 0xc4, 0xa9, 0x67, 0x2c, 0x39, 0x39, 0x7d, 0x37, 0x89, 0xb6 }, - { 0x78, 0xd0, 0x48, 0xf3, 0xa6, 0x9d, 0x8b, 0x54, 0xae, 0x0e, 0xd6, 0x3a, 0x57, 0x3a, 0xe3, 0x50, 0xd8, 0x9f, 0x7c, 0x6c, 0xf1, 0xf3, 0x68, 0x89, 0x30, 0xde, 0x89, 0x9a, 0xfa, 0x03, 0x76, 0x97, 0x62, 0x9b, 0x31, 0x4e, 0x5c, 0xd3, 0x03, 0xaa, 0x62, 0xfe, 0xea, 0x72, 0xa2, 0x5b, 0xf4, 0x2b, 0x30, 0x4b, 0x6c, 0x6b, 0xcb, 0x27, 0xfa, 0xe2, 0x1c, 0x16, 0xd9, 0x25, 0xe1, 0xfb, 0xda, 0xc3 }, - { 0x0f, 0x74, 0x6a, 0x48, 0x74, 0x92, 0x87, 0xad, 0xa7, 0x7a, 0x82, 0x96, 0x1f, 0x05, 0xa4, 0xda, 0x4a, 0xbd, 0xb7, 0xd7, 0x7b, 0x12, 0x20, 0xf8, 0x36, 0xd0, 0x9e, 0xc8, 0x14, 0x35, 0x9c, 0x0e, 0xc0, 0x23, 0x9b, 0x8c, 0x7b, 0x9f, 0xf9, 0xe0, 0x2f, 0x56, 0x9d, 0x1b, 0x30, 0x1e, 0xf6, 0x7c, 0x46, 0x12, 0xd1, 0xde, 0x4f, 0x73, 0x0f, 0x81, 0xc1, 0x2c, 0x40, 0xcc, 0x06, 0x3c, 0x5c, 0xaa }, - { 0xf0, 0xfc, 0x85, 0x9d, 0x3b, 0xd1, 0x95, 0xfb, 0xdc, 0x2d, 0x59, 0x1e, 0x4c, 0xda, 0xc1, 0x51, 0x79, 0xec, 0x0f, 0x1d, 0xc8, 0x21, 0xc1, 0x1d, 0xf1, 0xf0, 0xc1, 0xd2, 0x6e, 0x62, 0x60, 0xaa, 0xa6, 0x5b, 0x79, 0xfa, 0xfa, 0xca, 0xfd, 0x7d, 0x3a, 0xd6, 0x1e, 0x60, 0x0f, 0x25, 0x09, 0x05, 0xf5, 0x87, 0x8c, 0x87, 0x45, 0x28, 0x97, 0x64, 0x7a, 0x35, 0xb9, 0x95, 0xbc, 0xad, 0xc3, 0xa3 }, - { 0x26, 0x20, 0xf6, 0x87, 0xe8, 0x62, 0x5f, 0x6a, 0x41, 0x24, 0x60, 0xb4, 0x2e, 0x2c, 0xef, 0x67, 0x63, 0x42, 0x08, 0xce, 0x10, 0xa0, 0xcb, 0xd4, 0xdf, 0xf7, 0x04, 0x4a, 0x41, 0xb7, 0x88, 0x00, 0x77, 0xe9, 0xf8, 0xdc, 0x3b, 0x8d, 0x12, 0x16, 0xd3, 0x37, 0x6a, 0x21, 0xe0, 0x15, 0xb5, 0x8f, 0xb2, 0x79, 0xb5, 0x21, 0xd8, 0x3f, 0x93, 0x88, 0xc7, 0x38, 0x2c, 0x85, 0x05, 0x59, 0x0b, 0x9b }, - { 0x22, 0x7e, 0x3a, 0xed, 0x8d, 0x2c, 0xb1, 0x0b, 0x91, 0x8f, 0xcb, 0x04, 0xf9, 0xde, 0x3e, 0x6d, 0x0a, 0x57, 0xe0, 0x84, 0x76, 0xd9, 0x37, 0x59, 0xcd, 0x7b, 0x2e, 0xd5, 0x4a, 0x1c, 0xbf, 0x02, 0x39, 0xc5, 0x28, 0xfb, 0x04, 0xbb, 0xf2, 0x88, 0x25, 0x3e, 0x60, 0x1d, 0x3b, 0xc3, 0x8b, 0x21, 0x79, 0x4a, 0xfe, 0xf9, 0x0b, 0x17, 0x09, 0x4a, 0x18, 0x2c, 0xac, 0x55, 0x77, 0x45, 0xe7, 0x5f }, - { 0x1a, 0x92, 0x99, 0x01, 0xb0, 0x9c, 0x25, 0xf2, 0x7d, 0x6b, 0x35, 0xbe, 0x7b, 0x2f, 0x1c, 0x47, 0x45, 0x13, 0x1f, 0xde, 0xbc, 0xa7, 0xf3, 0xe2, 0x45, 0x19, 0x26, 0x72, 0x04, 0x34, 0xe0, 0xdb, 0x6e, 0x74, 0xfd, 0x69, 0x3a, 0xd2, 0x9b, 0x77, 0x7d, 0xc3, 0x35, 0x5c, 0x59, 0x2a, 0x36, 0x1c, 0x48, 0x73, 0xb0, 0x11, 0x33, 0xa5, 0x7c, 0x2e, 0x3b, 0x70, 0x75, 0xcb, 0xdb, 0x86, 0xf4, 0xfc }, - { 0x5f, 0xd7, 0x96, 0x8b, 0xc2, 0xfe, 0x34, 0xf2, 0x20, 0xb5, 0xe3, 0xdc, 0x5a, 0xf9, 0x57, 0x17, 0x42, 0xd7, 0x3b, 0x7d, 0x60, 0x81, 0x9f, 0x28, 0x88, 0xb6, 0x29, 0x07, 0x2b, 0x96, 0xa9, 0xd8, 0xab, 0x2d, 0x91, 0xb8, 0x2d, 0x0a, 0x9a, 0xab, 0xa6, 0x1b, 0xbd, 0x39, 0x95, 0x81, 0x32, 0xfc, 0xc4, 0x25, 0x70, 0x23, 0xd1, 0xec, 0xa5, 0x91, 0xb3, 0x05, 0x4e, 0x2d, 0xc8, 0x1c, 0x82, 0x00 }, - { 0xdf, 0xcc, 0xe8, 0xcf, 0x32, 0x87, 0x0c, 0xc6, 0xa5, 0x03, 0xea, 0xda, 0xfc, 0x87, 0xfd, 0x6f, 0x78, 0x91, 0x8b, 0x9b, 0x4d, 0x07, 0x37, 0xdb, 0x68, 0x10, 0xbe, 0x99, 0x6b, 0x54, 0x97, 0xe7, 0xe5, 0xcc, 0x80, 0xe3, 0x12, 0xf6, 0x1e, 0x71, 0xff, 0x3e, 0x96, 0x24, 0x43, 0x60, 0x73, 0x15, 0x64, 0x03, 0xf7, 0x35, 0xf5, 0x6b, 0x0b, 0x01, 0x84, 0x5c, 0x18, 0xf6, 0xca, 0xf7, 0x72, 0xe6 }, - { 0x02, 0xf7, 0xef, 0x3a, 0x9c, 0xe0, 0xff, 0xf9, 0x60, 0xf6, 0x70, 0x32, 0xb2, 0x96, 0xef, 0xca, 0x30, 0x61, 0xf4, 0x93, 0x4d, 0x69, 0x07, 0x49, 0xf2, 0xd0, 0x1c, 0x35, 0xc8, 0x1c, 0x14, 0xf3, 0x9a, 0x67, 0xfa, 0x35, 0x0b, 0xc8, 0xa0, 0x35, 0x9b, 0xf1, 0x72, 0x4b, 0xff, 0xc3, 0xbc, 0xa6, 0xd7, 0xc7, 0xbb, 0xa4, 0x79, 0x1f, 0xd5, 0x22, 0xa3, 0xad, 0x35, 0x3c, 0x02, 0xec, 0x5a, 0xa8 }, - { 0x64, 0xbe, 0x5c, 0x6a, 0xba, 0x65, 0xd5, 0x94, 0x84, 0x4a, 0xe7, 0x8b, 0xb0, 0x22, 0xe5, 0xbe, 0xbe, 0x12, 0x7f, 0xd6, 0xb6, 0xff, 0xa5, 0xa1, 0x37, 0x03, 0x85, 0x5a, 0xb6, 0x3b, 0x62, 0x4d, 0xcd, 0x1a, 0x36, 0x3f, 0x99, 0x20, 0x3f, 0x63, 0x2e, 0xc3, 0x86, 0xf3, 0xea, 0x76, 0x7f, 0xc9, 0x92, 0xe8, 0xed, 0x96, 0x86, 0x58, 0x6a, 0xa2, 0x75, 0x55, 0xa8, 0x59, 0x9d, 0x5b, 0x80, 0x8f }, - { 0xf7, 0x85, 0x85, 0x50, 0x5c, 0x4e, 0xaa, 0x54, 0xa8, 0xb5, 0xbe, 0x70, 0xa6, 0x1e, 0x73, 0x5e, 0x0f, 0xf9, 0x7a, 0xf9, 0x44, 0xdd, 0xb3, 0x00, 0x1e, 0x35, 0xd8, 0x6c, 0x4e, 0x21, 0x99, 0xd9, 0x76, 0x10, 0x4b, 0x6a, 0xe3, 0x17, 0x50, 0xa3, 0x6a, 0x72, 0x6e, 0xd2, 0x85, 0x06, 0x4f, 0x59, 0x81, 0xb5, 0x03, 0x88, 0x9f, 0xef, 0x82, 0x2f, 0xcd, 0xc2, 0x89, 0x8d, 0xdd, 0xb7, 0x88, 0x9a }, - { 0xe4, 0xb5, 0x56, 0x60, 0x33, 0x86, 0x95, 0x72, 0xed, 0xfd, 0x87, 0x47, 0x9a, 0x5b, 0xb7, 0x3c, 0x80, 0xe8, 0x75, 0x9b, 0x91, 0x23, 0x28, 0x79, 0xd9, 0x6b, 0x1d, 0xda, 0x36, 0xc0, 0x12, 0x07, 0x6e, 0xe5, 0xa2, 0xed, 0x7a, 0xe2, 0xde, 0x63, 0xef, 0x84, 0x06, 0xa0, 0x6a, 0xea, 0x82, 0xc1, 0x88, 0x03, 0x1b, 0x56, 0x0b, 0xea, 0xfb, 0x58, 0x3f, 0xb3, 0xde, 0x9e, 0x57, 0x95, 0x2a, 0x7e }, - { 0xe1, 0xb3, 0xe7, 0xed, 0x86, 0x7f, 0x6c, 0x94, 0x84, 0xa2, 0xa9, 0x7f, 0x77, 0x15, 0xf2, 0x5e, 0x25, 0x29, 0x4e, 0x99, 0x2e, 0x41, 0xf6, 0xa7, 0xc1, 0x61, 0xff, 0xc2, 0xad, 0xc6, 0xda, 0xae, 0xb7, 0x11, 0x31, 0x02, 0xd5, 0xe6, 0x09, 0x02, 0x87, 0xfe, 0x6a, 0xd9, 0x4c, 0xe5, 0xd6, 0xb7, 0x39, 0xc6, 0xca, 0x24, 0x0b, 0x05, 0xc7, 0x6f, 0xb7, 0x3f, 0x25, 0xdd, 0x02, 0x4b, 0xf9, 0x35 }, - { 0x85, 0xfd, 0x08, 0x5f, 0xdc, 0x12, 0xa0, 0x80, 0x98, 0x3d, 0xf0, 0x7b, 0xd7, 0x01, 0x2b, 0x0d, 0x40, 0x2a, 0x0f, 0x40, 0x43, 0xfc, 0xb2, 0x77, 0x5a, 0xdf, 0x0b, 0xad, 0x17, 0x4f, 0x9b, 0x08, 0xd1, 0x67, 0x6e, 0x47, 0x69, 0x85, 0x78, 0x5c, 0x0a, 0x5d, 0xcc, 0x41, 0xdb, 0xff, 0x6d, 0x95, 0xef, 0x4d, 0x66, 0xa3, 0xfb, 0xdc, 0x4a, 0x74, 0xb8, 0x2b, 0xa5, 0x2d, 0xa0, 0x51, 0x2b, 0x74 }, - { 0xae, 0xd8, 0xfa, 0x76, 0x4b, 0x0f, 0xbf, 0xf8, 0x21, 0xe0, 0x52, 0x33, 0xd2, 0xf7, 0xb0, 0x90, 0x0e, 0xc4, 0x4d, 0x82, 0x6f, 0x95, 0xe9, 0x3c, 0x34, 0x3c, 0x1b, 0xc3, 0xba, 0x5a, 0x24, 0x37, 0x4b, 0x1d, 0x61, 0x6e, 0x7e, 0x7a, 0xba, 0x45, 0x3a, 0x0a, 0xda, 0x5e, 0x4f, 0xab, 0x53, 0x82, 0x40, 0x9e, 0x0d, 0x42, 0xce, 0x9c, 0x2b, 0xc7, 0xfb, 0x39, 0xa9, 0x9c, 0x34, 0x0c, 0x20, 0xf0 }, - { 0x7b, 0xa3, 0xb2, 0xe2, 0x97, 0x23, 0x35, 0x22, 0xee, 0xb3, 0x43, 0xbd, 0x3e, 0xbc, 0xfd, 0x83, 0x5a, 0x04, 0x00, 0x77, 0x35, 0xe8, 0x7f, 0x0c, 0xa3, 0x00, 0xcb, 0xee, 0x6d, 0x41, 0x65, 0x65, 0x16, 0x21, 0x71, 0x58, 0x1e, 0x40, 0x20, 0xff, 0x4c, 0xf1, 0x76, 0x45, 0x0f, 0x12, 0x91, 0xea, 0x22, 0x85, 0xcb, 0x9e, 0xbf, 0xfe, 0x4c, 0x56, 0x66, 0x06, 0x27, 0x68, 0x51, 0x45, 0x05, 0x1c }, - { 0xde, 0x74, 0x8b, 0xcf, 0x89, 0xec, 0x88, 0x08, 0x47, 0x21, 0xe1, 0x6b, 0x85, 0xf3, 0x0a, 0xdb, 0x1a, 0x61, 0x34, 0xd6, 0x64, 0xb5, 0x84, 0x35, 0x69, 0xba, 0xbc, 0x5b, 0xbd, 0x1a, 0x15, 0xca, 0x9b, 0x61, 0x80, 0x3c, 0x90, 0x1a, 0x4f, 0xef, 0x32, 0x96, 0x5a, 0x17, 0x49, 0xc9, 0xf3, 0xa4, 0xe2, 0x43, 0xe1, 0x73, 0x93, 0x9d, 0xc5, 0xa8, 0xdc, 0x49, 0x5c, 0x67, 0x1a, 0xb5, 0x21, 0x45 }, - { 0xaa, 0xf4, 0xd2, 0xbd, 0xf2, 0x00, 0xa9, 0x19, 0x70, 0x6d, 0x98, 0x42, 0xdc, 0xe1, 0x6c, 0x98, 0x14, 0x0d, 0x34, 0xbc, 0x43, 0x3d, 0xf3, 0x20, 0xab, 0xa9, 0xbd, 0x42, 0x9e, 0x54, 0x9a, 0xa7, 0xa3, 0x39, 0x76, 0x52, 0xa4, 0xd7, 0x68, 0x27, 0x77, 0x86, 0xcf, 0x99, 0x3c, 0xde, 0x23, 0x38, 0x67, 0x3e, 0xd2, 0xe6, 0xb6, 0x6c, 0x96, 0x1f, 0xef, 0xb8, 0x2c, 0xd2, 0x0c, 0x93, 0x33, 0x8f }, - { 0xc4, 0x08, 0x21, 0x89, 0x68, 0xb7, 0x88, 0xbf, 0x86, 0x4f, 0x09, 0x97, 0xe6, 0xbc, 0x4c, 0x3d, 0xba, 0x68, 0xb2, 0x76, 0xe2, 0x12, 0x5a, 0x48, 0x43, 0x29, 0x60, 0x52, 0xff, 0x93, 0xbf, 0x57, 0x67, 0xb8, 0xcd, 0xce, 0x71, 0x31, 0xf0, 0x87, 0x64, 0x30, 0xc1, 0x16, 0x5f, 0xec, 0x6c, 0x4f, 0x47, 0xad, 0xaa, 0x4f, 0xd8, 0xbc, 0xfa, 0xce, 0xf4, 0x63, 0xb5, 0xd3, 0xd0, 0xfa, 0x61, 0xa0 }, - { 0x76, 0xd2, 0xd8, 0x19, 0xc9, 0x2b, 0xce, 0x55, 0xfa, 0x8e, 0x09, 0x2a, 0xb1, 0xbf, 0x9b, 0x9e, 0xab, 0x23, 0x7a, 0x25, 0x26, 0x79, 0x86, 0xca, 0xcf, 0x2b, 0x8e, 0xe1, 0x4d, 0x21, 0x4d, 0x73, 0x0d, 0xc9, 0xa5, 0xaa, 0x2d, 0x7b, 0x59, 0x6e, 0x86, 0xa1, 0xfd, 0x8f, 0xa0, 0x80, 0x4c, 0x77, 0x40, 0x2d, 0x2f, 0xcd, 0x45, 0x08, 0x36, 0x88, 0xb2, 0x18, 0xb1, 0xcd, 0xfa, 0x0d, 0xcb, 0xcb }, - { 0x72, 0x06, 0x5e, 0xe4, 0xdd, 0x91, 0xc2, 0xd8, 0x50, 0x9f, 0xa1, 0xfc, 0x28, 0xa3, 0x7c, 0x7f, 0xc9, 0xfa, 0x7d, 0x5b, 0x3f, 0x8a, 0xd3, 0xd0, 0xd7, 0xa2, 0x56, 0x26, 0xb5, 0x7b, 0x1b, 0x44, 0x78, 0x8d, 0x4c, 0xaf, 0x80, 0x62, 0x90, 0x42, 0x5f, 0x98, 0x90, 0xa3, 0xa2, 0xa3, 0x5a, 0x90, 0x5a, 0xb4, 0xb3, 0x7a, 0xcf, 0xd0, 0xda, 0x6e, 0x45, 0x17, 0xb2, 0x52, 0x5c, 0x96, 0x51, 0xe4 }, - { 0x64, 0x47, 0x5d, 0xfe, 0x76, 0x00, 0xd7, 0x17, 0x1b, 0xea, 0x0b, 0x39, 0x4e, 0x27, 0xc9, 0xb0, 0x0d, 0x8e, 0x74, 0xdd, 0x1e, 0x41, 0x6a, 0x79, 0x47, 0x36, 0x82, 0xad, 0x3d, 0xfd, 0xbb, 0x70, 0x66, 0x31, 0x55, 0x80, 0x55, 0xcf, 0xc8, 0xa4, 0x0e, 0x07, 0xbd, 0x01, 0x5a, 0x45, 0x40, 0xdc, 0xde, 0xa1, 0x58, 0x83, 0xcb, 0xbf, 0x31, 0x41, 0x2d, 0xf1, 0xde, 0x1c, 0xd4, 0x15, 0x2b, 0x91 }, - { 0x12, 0xcd, 0x16, 0x74, 0xa4, 0x48, 0x8a, 0x5d, 0x7c, 0x2b, 0x31, 0x60, 0xd2, 0xe2, 0xc4, 0xb5, 0x83, 0x71, 0xbe, 0xda, 0xd7, 0x93, 0x41, 0x8d, 0x6f, 0x19, 0xc6, 0xee, 0x38, 0x5d, 0x70, 0xb3, 0xe0, 0x67, 0x39, 0x36, 0x9d, 0x4d, 0xf9, 0x10, 0xed, 0xb0, 0xb0, 0xa5, 0x4c, 0xbf, 0xf4, 0x3d, 0x54, 0x54, 0x4c, 0xd3, 0x7a, 0xb3, 0xa0, 0x6c, 0xfa, 0x0a, 0x3d, 0xda, 0xc8, 0xb6, 0x6c, 0x89 }, - { 0x60, 0x75, 0x69, 0x66, 0x47, 0x9d, 0xed, 0xc6, 0xdd, 0x4b, 0xcf, 0xf8, 0xea, 0x7d, 0x1d, 0x4c, 0xe4, 0xd4, 0xaf, 0x2e, 0x7b, 0x09, 0x7e, 0x32, 0xe3, 0x76, 0x35, 0x18, 0x44, 0x11, 0x47, 0xcc, 0x12, 0xb3, 0xc0, 0xee, 0x6d, 0x2e, 0xca, 0xbf, 0x11, 0x98, 0xce, 0xc9, 0x2e, 0x86, 0xa3, 0x61, 0x6f, 0xba, 0x4f, 0x4e, 0x87, 0x2f, 0x58, 0x25, 0x33, 0x0a, 0xdb, 0xb4, 0xc1, 0xde, 0xe4, 0x44 }, - { 0xa7, 0x80, 0x3b, 0xcb, 0x71, 0xbc, 0x1d, 0x0f, 0x43, 0x83, 0xdd, 0xe1, 0xe0, 0x61, 0x2e, 0x04, 0xf8, 0x72, 0xb7, 0x15, 0xad, 0x30, 0x81, 0x5c, 0x22, 0x49, 0xcf, 0x34, 0xab, 0xb8, 0xb0, 0x24, 0x91, 0x5c, 0xb2, 0xfc, 0x9f, 0x4e, 0x7c, 0xc4, 0xc8, 0xcf, 0xd4, 0x5b, 0xe2, 0xd5, 0xa9, 0x1e, 0xab, 0x09, 0x41, 0xc7, 0xd2, 0x70, 0xe2, 0xda, 0x4c, 0xa4, 0xa9, 0xf7, 0xac, 0x68, 0x66, 0x3a }, - { 0xb8, 0x4e, 0xf6, 0xa7, 0x22, 0x9a, 0x34, 0xa7, 0x50, 0xd9, 0xa9, 0x8e, 0xe2, 0x52, 0x98, 0x71, 0x81, 0x6b, 0x87, 0xfb, 0xe3, 0xbc, 0x45, 0xb4, 0x5f, 0xa5, 0xae, 0x82, 0xd5, 0x14, 0x15, 0x40, 0x21, 0x11, 0x65, 0xc3, 0xc5, 0xd7, 0xa7, 0x47, 0x6b, 0xa5, 0xa4, 0xaa, 0x06, 0xd6, 0x64, 0x76, 0xf0, 0xd9, 0xdc, 0x49, 0xa3, 0xf1, 0xee, 0x72, 0xc3, 0xac, 0xab, 0xd4, 0x98, 0x96, 0x74, 0x14 }, - { 0xfa, 0xe4, 0xb6, 0xd8, 0xef, 0xc3, 0xf8, 0xc8, 0xe6, 0x4d, 0x00, 0x1d, 0xab, 0xec, 0x3a, 0x21, 0xf5, 0x44, 0xe8, 0x27, 0x14, 0x74, 0x52, 0x51, 0xb2, 0xb4, 0xb3, 0x93, 0xf2, 0xf4, 0x3e, 0x0d, 0xa3, 0xd4, 0x03, 0xc6, 0x4d, 0xb9, 0x5a, 0x2c, 0xb6, 0xe2, 0x3e, 0xbb, 0x7b, 0x9e, 0x94, 0xcd, 0xd5, 0xdd, 0xac, 0x54, 0xf0, 0x7c, 0x4a, 0x61, 0xbd, 0x3c, 0xb1, 0x0a, 0xa6, 0xf9, 0x3b, 0x49 }, - { 0x34, 0xf7, 0x28, 0x66, 0x05, 0xa1, 0x22, 0x36, 0x95, 0x40, 0x14, 0x1d, 0xed, 0x79, 0xb8, 0x95, 0x72, 0x55, 0xda, 0x2d, 0x41, 0x55, 0xab, 0xbf, 0x5a, 0x8d, 0xbb, 0x89, 0xc8, 0xeb, 0x7e, 0xde, 0x8e, 0xee, 0xf1, 0xda, 0xa4, 0x6d, 0xc2, 0x9d, 0x75, 0x1d, 0x04, 0x5d, 0xc3, 0xb1, 0xd6, 0x58, 0xbb, 0x64, 0xb8, 0x0f, 0xf8, 0x58, 0x9e, 0xdd, 0xb3, 0x82, 0x4b, 0x13, 0xda, 0x23, 0x5a, 0x6b }, - { 0x3b, 0x3b, 0x48, 0x43, 0x4b, 0xe2, 0x7b, 0x9e, 0xab, 0xab, 0xba, 0x43, 0xbf, 0x6b, 0x35, 0xf1, 0x4b, 0x30, 0xf6, 0xa8, 0x8d, 0xc2, 0xe7, 0x50, 0xc3, 0x58, 0x47, 0x0d, 0x6b, 0x3a, 0xa3, 0xc1, 0x8e, 0x47, 0xdb, 0x40, 0x17, 0xfa, 0x55, 0x10, 0x6d, 0x82, 0x52, 0xf0, 0x16, 0x37, 0x1a, 0x00, 0xf5, 0xf8, 0xb0, 0x70, 0xb7, 0x4b, 0xa5, 0xf2, 0x3c, 0xff, 0xc5, 0x51, 0x1c, 0x9f, 0x09, 0xf0 }, - { 0xba, 0x28, 0x9e, 0xbd, 0x65, 0x62, 0xc4, 0x8c, 0x3e, 0x10, 0xa8, 0xad, 0x6c, 0xe0, 0x2e, 0x73, 0x43, 0x3d, 0x1e, 0x93, 0xd7, 0xc9, 0x27, 0x9d, 0x4d, 0x60, 0xa7, 0xe8, 0x79, 0xee, 0x11, 0xf4, 0x41, 0xa0, 0x00, 0xf4, 0x8e, 0xd9, 0xf7, 0xc4, 0xed, 0x87, 0xa4, 0x51, 0x36, 0xd7, 0xdc, 0xcd, 0xca, 0x48, 0x21, 0x09, 0xc7, 0x8a, 0x51, 0x06, 0x2b, 0x3b, 0xa4, 0x04, 0x4a, 0xda, 0x24, 0x69 }, - { 0x02, 0x29, 0x39, 0xe2, 0x38, 0x6c, 0x5a, 0x37, 0x04, 0x98, 0x56, 0xc8, 0x50, 0xa2, 0xbb, 0x10, 0xa1, 0x3d, 0xfe, 0xa4, 0x21, 0x2b, 0x4c, 0x73, 0x2a, 0x88, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0xf5, 0x48, 0x75, 0xc5, 0x44, 0x88, 0x16, 0xb2, 0x78, 0x5a, 0x00, 0x7d, 0xa8, 0xa8, 0xd2, 0xbc, 0x7d, 0x71, 0xa5, 0x4e, 0x4e, 0x65, 0x71, 0xf1, 0x0b, 0x60, 0x0c, 0xbd, 0xb2, 0x5d, 0x13, 0xed, 0xe3 }, - { 0xe6, 0xfe, 0xc1, 0x9d, 0x89, 0xce, 0x87, 0x17, 0xb1, 0xa0, 0x87, 0x02, 0x46, 0x70, 0xfe, 0x02, 0x6f, 0x6c, 0x7c, 0xbd, 0xa1, 0x1c, 0xae, 0xf9, 0x59, 0xbb, 0x2d, 0x35, 0x1b, 0xf8, 0x56, 0xf8, 0x05, 0x5d, 0x1c, 0x0e, 0xbd, 0xaa, 0xa9, 0xd1, 0xb1, 0x78, 0x86, 0xfc, 0x2c, 0x56, 0x2b, 0x5e, 0x99, 0x64, 0x2f, 0xc0, 0x64, 0x71, 0x0c, 0x0d, 0x34, 0x88, 0xa0, 0x2b, 0x5e, 0xd7, 0xf6, 0xfd }, - { 0x94, 0xc9, 0x6f, 0x02, 0xa8, 0xf5, 0x76, 0xac, 0xa3, 0x2b, 0xa6, 0x1c, 0x2b, 0x20, 0x6f, 0x90, 0x72, 0x85, 0xd9, 0x29, 0x9b, 0x83, 0xac, 0x17, 0x5c, 0x20, 0x9a, 0x8d, 0x43, 0xd5, 0x3b, 0xfe, 0x68, 0x3d, 0xd1, 0xd8, 0x3e, 0x75, 0x49, 0xcb, 0x90, 0x6c, 0x28, 0xf5, 0x9a, 0xb7, 0xc4, 0x6f, 0x87, 0x51, 0x36, 0x6a, 0x28, 0xc3, 0x9d, 0xd5, 0xfe, 0x26, 0x93, 0xc9, 0x01, 0x96, 0x66, 0xc8 }, - { 0x31, 0xa0, 0xcd, 0x21, 0x5e, 0xbd, 0x2c, 0xb6, 0x1d, 0xe5, 0xb9, 0xed, 0xc9, 0x1e, 0x61, 0x95, 0xe3, 0x1c, 0x59, 0xa5, 0x64, 0x8d, 0x5c, 0x9f, 0x73, 0x7e, 0x12, 0x5b, 0x26, 0x05, 0x70, 0x8f, 0x2e, 0x32, 0x5a, 0xb3, 0x38, 0x1c, 0x8d, 0xce, 0x1a, 0x3e, 0x95, 0x88, 0x86, 0xf1, 0xec, 0xdc, 0x60, 0x31, 0x8f, 0x88, 0x2c, 0xfe, 0x20, 0xa2, 0x41, 0x91, 0x35, 0x2e, 0x61, 0x7b, 0x0f, 0x21 }, - { 0x91, 0xab, 0x50, 0x4a, 0x52, 0x2d, 0xce, 0x78, 0x77, 0x9f, 0x4c, 0x6c, 0x6b, 0xa2, 0xe6, 0xb6, 0xdb, 0x55, 0x65, 0xc7, 0x6d, 0x3e, 0x7e, 0x7c, 0x92, 0x0c, 0xaf, 0x7f, 0x75, 0x7e, 0xf9, 0xdb, 0x7c, 0x8f, 0xcf, 0x10, 0xe5, 0x7f, 0x03, 0x37, 0x9e, 0xa9, 0xbf, 0x75, 0xeb, 0x59, 0x89, 0x5d, 0x96, 0xe1, 0x49, 0x80, 0x0b, 0x6a, 0xae, 0x01, 0xdb, 0x77, 0x8b, 0xb9, 0x0a, 0xfb, 0xc9, 0x89 }, - { 0xd8, 0x5c, 0xab, 0xc6, 0xbd, 0x5b, 0x1a, 0x01, 0xa5, 0xaf, 0xd8, 0xc6, 0x73, 0x47, 0x40, 0xda, 0x9f, 0xd1, 0xc1, 0xac, 0xc6, 0xdb, 0x29, 0xbf, 0xc8, 0xa2, 0xe5, 0xb6, 0x68, 0xb0, 0x28, 0xb6, 0xb3, 0x15, 0x4b, 0xfb, 0x87, 0x03, 0xfa, 0x31, 0x80, 0x25, 0x1d, 0x58, 0x9a, 0xd3, 0x80, 0x40, 0xce, 0xb7, 0x07, 0xc4, 0xba, 0xd1, 0xb5, 0x34, 0x3c, 0xb4, 0x26, 0xb6, 0x1e, 0xaa, 0x49, 0xc1 }, - { 0xd6, 0x2e, 0xfb, 0xec, 0x2c, 0xa9, 0xc1, 0xf8, 0xbd, 0x66, 0xce, 0x8b, 0x3f, 0x6a, 0x89, 0x8c, 0xb3, 0xf7, 0x56, 0x6b, 0xa6, 0x56, 0x8c, 0x61, 0x8a, 0xd1, 0xfe, 0xb2, 0xb6, 0x5b, 0x76, 0xc3, 0xce, 0x1d, 0xd2, 0x0f, 0x73, 0x95, 0x37, 0x2f, 0xaf, 0x28, 0x42, 0x7f, 0x61, 0xc9, 0x27, 0x80, 0x49, 0xcf, 0x01, 0x40, 0xdf, 0x43, 0x4f, 0x56, 0x33, 0x04, 0x8c, 0x86, 0xb8, 0x1e, 0x03, 0x99 }, - { 0x7c, 0x8f, 0xdc, 0x61, 0x75, 0x43, 0x9e, 0x2c, 0x3d, 0xb1, 0x5b, 0xaf, 0xa7, 0xfb, 0x06, 0x14, 0x3a, 0x6a, 0x23, 0xbc, 0x90, 0xf4, 0x49, 0xe7, 0x9d, 0xee, 0xf7, 0x3c, 0x3d, 0x49, 0x2a, 0x67, 0x17, 0x15, 0xc1, 0x93, 0xb6, 0xfe, 0xa9, 0xf0, 0x36, 0x05, 0x0b, 0x94, 0x60, 0x69, 0x85, 0x6b, 0x89, 0x7e, 0x08, 0xc0, 0x07, 0x68, 0xf5, 0xee, 0x5d, 0xdc, 0xf7, 0x0b, 0x7c, 0xd6, 0xd0, 0xe0 }, - { 0x58, 0x60, 0x2e, 0xe7, 0x46, 0x8e, 0x6b, 0xc9, 0xdf, 0x21, 0xbd, 0x51, 0xb2, 0x3c, 0x00, 0x5f, 0x72, 0xd6, 0xcb, 0x01, 0x3f, 0x0a, 0x1b, 0x48, 0xcb, 0xec, 0x5e, 0xca, 0x29, 0x92, 0x99, 0xf9, 0x7f, 0x09, 0xf5, 0x4a, 0x9a, 0x01, 0x48, 0x3e, 0xae, 0xb3, 0x15, 0xa6, 0x47, 0x8b, 0xad, 0x37, 0xba, 0x47, 0xca, 0x13, 0x47, 0xc7, 0xc8, 0xfc, 0x9e, 0x66, 0x95, 0x59, 0x2c, 0x91, 0xd7, 0x23 }, - { 0x27, 0xf5, 0xb7, 0x9e, 0xd2, 0x56, 0xb0, 0x50, 0x99, 0x3d, 0x79, 0x34, 0x96, 0xed, 0xf4, 0x80, 0x7c, 0x1d, 0x85, 0xa7, 0xb0, 0xa6, 0x7c, 0x9c, 0x4f, 0xa9, 0x98, 0x60, 0x75, 0x0b, 0x0a, 0xe6, 0x69, 0x89, 0x67, 0x0a, 0x8f, 0xfd, 0x78, 0x56, 0xd7, 0xce, 0x41, 0x15, 0x99, 0xe5, 0x8c, 0x4d, 0x77, 0xb2, 0x32, 0xa6, 0x2b, 0xef, 0x64, 0xd1, 0x52, 0x75, 0xbe, 0x46, 0xa6, 0x82, 0x35, 0xff }, - { 0x39, 0x57, 0xa9, 0x76, 0xb9, 0xf1, 0x88, 0x7b, 0xf0, 0x04, 0xa8, 0xdc, 0xa9, 0x42, 0xc9, 0x2d, 0x2b, 0x37, 0xea, 0x52, 0x60, 0x0f, 0x25, 0xe0, 0xc9, 0xbc, 0x57, 0x07, 0xd0, 0x27, 0x9c, 0x00, 0xc6, 0xe8, 0x5a, 0x83, 0x9b, 0x0d, 0x2d, 0x8e, 0xb5, 0x9c, 0x51, 0xd9, 0x47, 0x88, 0xeb, 0xe6, 0x24, 0x74, 0xa7, 0x91, 0xca, 0xdf, 0x52, 0xcc, 0xcf, 0x20, 0xf5, 0x07, 0x0b, 0x65, 0x73, 0xfc }, - { 0xea, 0xa2, 0x37, 0x6d, 0x55, 0x38, 0x0b, 0xf7, 0x72, 0xec, 0xca, 0x9c, 0xb0, 0xaa, 0x46, 0x68, 0xc9, 0x5c, 0x70, 0x71, 0x62, 0xfa, 0x86, 0xd5, 0x18, 0xc8, 0xce, 0x0c, 0xa9, 0xbf, 0x73, 0x62, 0xb9, 0xf2, 0xa0, 0xad, 0xc3, 0xff, 0x59, 0x92, 0x2d, 0xf9, 0x21, 0xb9, 0x45, 0x67, 0xe8, 0x1e, 0x45, 0x2f, 0x6c, 0x1a, 0x07, 0xfc, 0x81, 0x7c, 0xeb, 0xe9, 0x96, 0x04, 0xb3, 0x50, 0x5d, 0x38 }, - { 0xc1, 0xe2, 0xc7, 0x8b, 0x6b, 0x27, 0x34, 0xe2, 0x48, 0x0e, 0xc5, 0x50, 0x43, 0x4c, 0xb5, 0xd6, 0x13, 0x11, 0x1a, 0xdc, 0xc2, 0x1d, 0x47, 0x55, 0x45, 0xc3, 0xb1, 0xb7, 0xe6, 0xff, 0x12, 0x44, 0x44, 0x76, 0xe5, 0xc0, 0x55, 0x13, 0x2e, 0x22, 0x29, 0xdc, 0x0f, 0x80, 0x70, 0x44, 0xbb, 0x91, 0x9b, 0x1a, 0x56, 0x62, 0xdd, 0x38, 0xa9, 0xee, 0x65, 0xe2, 0x43, 0xa3, 0x91, 0x1a, 0xed, 0x1a }, - { 0x8a, 0xb4, 0x87, 0x13, 0x38, 0x9d, 0xd0, 0xfc, 0xf9, 0xf9, 0x65, 0xd3, 0xce, 0x66, 0xb1, 0xe5, 0x59, 0xa1, 0xf8, 0xc5, 0x87, 0x41, 0xd6, 0x76, 0x83, 0xcd, 0x97, 0x13, 0x54, 0xf4, 0x52, 0xe6, 0x2d, 0x02, 0x07, 0xa6, 0x5e, 0x43, 0x6c, 0x5d, 0x5d, 0x8f, 0x8e, 0xe7, 0x1c, 0x6a, 0xbf, 0xe5, 0x0e, 0x66, 0x90, 0x04, 0xc3, 0x02, 0xb3, 0x1a, 0x7e, 0xa8, 0x31, 0x1d, 0x4a, 0x91, 0x60, 0x51 }, - { 0x24, 0xce, 0x0a, 0xdd, 0xaa, 0x4c, 0x65, 0x03, 0x8b, 0xd1, 0xb1, 0xc0, 0xf1, 0x45, 0x2a, 0x0b, 0x12, 0x87, 0x77, 0xaa, 0xbc, 0x94, 0xa2, 0x9d, 0xf2, 0xfd, 0x6c, 0x7e, 0x2f, 0x85, 0xf8, 0xab, 0x9a, 0xc7, 0xef, 0xf5, 0x16, 0xb0, 0xe0, 0xa8, 0x25, 0xc8, 0x4a, 0x24, 0xcf, 0xe4, 0x92, 0xea, 0xad, 0x0a, 0x63, 0x08, 0xe4, 0x6d, 0xd4, 0x2f, 0xe8, 0x33, 0x3a, 0xb9, 0x71, 0xbb, 0x30, 0xca }, - { 0x51, 0x54, 0xf9, 0x29, 0xee, 0x03, 0x04, 0x5b, 0x6b, 0x0c, 0x00, 0x04, 0xfa, 0x77, 0x8e, 0xde, 0xe1, 0xd1, 0x39, 0x89, 0x32, 0x67, 0xcc, 0x84, 0x82, 0x5a, 0xd7, 0xb3, 0x6c, 0x63, 0xde, 0x32, 0x79, 0x8e, 0x4a, 0x16, 0x6d, 0x24, 0x68, 0x65, 0x61, 0x35, 0x4f, 0x63, 0xb0, 0x07, 0x09, 0xa1, 0x36, 0x4b, 0x3c, 0x24, 0x1d, 0xe3, 0xfe, 0xbf, 0x07, 0x54, 0x04, 0x58, 0x97, 0x46, 0x7c, 0xd4 }, - { 0xe7, 0x4e, 0x90, 0x79, 0x20, 0xfd, 0x87, 0xbd, 0x5a, 0xd6, 0x36, 0xdd, 0x11, 0x08, 0x5e, 0x50, 0xee, 0x70, 0x45, 0x9c, 0x44, 0x3e, 0x1c, 0xe5, 0x80, 0x9a, 0xf2, 0xbc, 0x2e, 0xba, 0x39, 0xf9, 0xe6, 0xd7, 0x12, 0x8e, 0x0e, 0x37, 0x12, 0xc3, 0x16, 0xda, 0x06, 0xf4, 0x70, 0x5d, 0x78, 0xa4, 0x83, 0x8e, 0x28, 0x12, 0x1d, 0x43, 0x44, 0xa2, 0xc7, 0x9c, 0x5e, 0x0d, 0xb3, 0x07, 0xa6, 0x77 }, - { 0xbf, 0x91, 0xa2, 0x23, 0x34, 0xba, 0xc2, 0x0f, 0x3f, 0xd8, 0x06, 0x63, 0xb3, 0xcd, 0x06, 0xc4, 0xe8, 0x80, 0x2f, 0x30, 0xe6, 0xb5, 0x9f, 0x90, 0xd3, 0x03, 0x5c, 0xc9, 0x79, 0x8a, 0x21, 0x7e, 0xd5, 0xa3, 0x1a, 0xbb, 0xda, 0x7f, 0xa6, 0x84, 0x28, 0x27, 0xbd, 0xf2, 0xa7, 0xa1, 0xc2, 0x1f, 0x6f, 0xcf, 0xcc, 0xbb, 0x54, 0xc6, 0xc5, 0x29, 0x26, 0xf3, 0x2d, 0xa8, 0x16, 0x26, 0x9b, 0xe1 }, - { 0xd9, 0xd5, 0xc7, 0x4b, 0xe5, 0x12, 0x1b, 0x0b, 0xd7, 0x42, 0xf2, 0x6b, 0xff, 0xb8, 0xc8, 0x9f, 0x89, 0x17, 0x1f, 0x3f, 0x93, 0x49, 0x13, 0x49, 0x2b, 0x09, 0x03, 0xc2, 0x71, 0xbb, 0xe2, 0xb3, 0x39, 0x5e, 0xf2, 0x59, 0x66, 0x9b, 0xef, 0x43, 0xb5, 0x7f, 0x7f, 0xcc, 0x30, 0x27, 0xdb, 0x01, 0x82, 0x3f, 0x6b, 0xae, 0xe6, 0x6e, 0x4f, 0x9f, 0xea, 0xd4, 0xd6, 0x72, 0x6c, 0x74, 0x1f, 0xce }, - { 0x50, 0xc8, 0xb8, 0xcf, 0x34, 0xcd, 0x87, 0x9f, 0x80, 0xe2, 0xfa, 0xab, 0x32, 0x30, 0xb0, 0xc0, 0xe1, 0xcc, 0x3e, 0x9d, 0xca, 0xde, 0xb1, 0xb9, 0xd9, 0x7a, 0xb9, 0x23, 0x41, 0x5d, 0xd9, 0xa1, 0xfe, 0x38, 0xad, 0xdd, 0x5c, 0x11, 0x75, 0x6c, 0x67, 0x99, 0x0b, 0x25, 0x6e, 0x95, 0xad, 0x6d, 0x8f, 0x9f, 0xed, 0xce, 0x10, 0xbf, 0x1c, 0x90, 0x67, 0x9c, 0xde, 0x0e, 0xcf, 0x1b, 0xe3, 0x47 }, - { 0x0a, 0x38, 0x6e, 0x7c, 0xd5, 0xdd, 0x9b, 0x77, 0xa0, 0x35, 0xe0, 0x9f, 0xe6, 0xfe, 0xe2, 0xc8, 0xce, 0x61, 0xb5, 0x38, 0x3c, 0x87, 0xea, 0x43, 0x20, 0x50, 0x59, 0xc5, 0xe4, 0xcd, 0x4f, 0x44, 0x08, 0x31, 0x9b, 0xb0, 0xa8, 0x23, 0x60, 0xf6, 0xa5, 0x8e, 0x6c, 0x9c, 0xe3, 0xf4, 0x87, 0xc4, 0x46, 0x06, 0x3b, 0xf8, 0x13, 0xbc, 0x6b, 0xa5, 0x35, 0xe1, 0x7f, 0xc1, 0x82, 0x6c, 0xfc, 0x91 }, - { 0x1f, 0x14, 0x59, 0xcb, 0x6b, 0x61, 0xcb, 0xac, 0x5f, 0x0e, 0xfe, 0x8f, 0xc4, 0x87, 0x53, 0x8f, 0x42, 0x54, 0x89, 0x87, 0xfc, 0xd5, 0x62, 0x21, 0xcf, 0xa7, 0xbe, 0xb2, 0x25, 0x04, 0x76, 0x9e, 0x79, 0x2c, 0x45, 0xad, 0xfb, 0x1d, 0x6b, 0x3d, 0x60, 0xd7, 0xb7, 0x49, 0xc8, 0xa7, 0x5b, 0x0b, 0xdf, 0x14, 0xe8, 0xea, 0x72, 0x1b, 0x95, 0xdc, 0xa5, 0x38, 0xca, 0x6e, 0x25, 0x71, 0x12, 0x09 }, - { 0xe5, 0x8b, 0x38, 0x36, 0xb7, 0xd8, 0xfe, 0xdb, 0xb5, 0x0c, 0xa5, 0x72, 0x5c, 0x65, 0x71, 0xe7, 0x4c, 0x07, 0x85, 0xe9, 0x78, 0x21, 0xda, 0xb8, 0xb6, 0x29, 0x8c, 0x10, 0xe4, 0xc0, 0x79, 0xd4, 0xa6, 0xcd, 0xf2, 0x2f, 0x0f, 0xed, 0xb5, 0x50, 0x32, 0x92, 0x5c, 0x16, 0x74, 0x81, 0x15, 0xf0, 0x1a, 0x10, 0x5e, 0x77, 0xe0, 0x0c, 0xee, 0x3d, 0x07, 0x92, 0x4d, 0xc0, 0xd8, 0xf9, 0x06, 0x59 }, - { 0xb9, 0x29, 0xcc, 0x65, 0x05, 0xf0, 0x20, 0x15, 0x86, 0x72, 0xde, 0xda, 0x56, 0xd0, 0xdb, 0x08, 0x1a, 0x2e, 0xe3, 0x4c, 0x00, 0xc1, 0x10, 0x00, 0x29, 0xbd, 0xf8, 0xea, 0x98, 0x03, 0x4f, 0xa4, 0xbf, 0x3e, 0x86, 0x55, 0xec, 0x69, 0x7f, 0xe3, 0x6f, 0x40, 0x55, 0x3c, 0x5b, 0xb4, 0x68, 0x01, 0x64, 0x4a, 0x62, 0x7d, 0x33, 0x42, 0xf4, 0xfc, 0x92, 0xb6, 0x1f, 0x03, 0x29, 0x0f, 0xb3, 0x81 }, - { 0x72, 0xd3, 0x53, 0x99, 0x4b, 0x49, 0xd3, 0xe0, 0x31, 0x53, 0x92, 0x9a, 0x1e, 0x4d, 0x4f, 0x18, 0x8e, 0xe5, 0x8a, 0xb9, 0xe7, 0x2e, 0xe8, 0xe5, 0x12, 0xf2, 0x9b, 0xc7, 0x73, 0x91, 0x38, 0x19, 0xce, 0x05, 0x7d, 0xdd, 0x70, 0x02, 0xc0, 0x43, 0x3e, 0xe0, 0xa1, 0x61, 0x14, 0xe3, 0xd1, 0x56, 0xdd, 0x2c, 0x4a, 0x7e, 0x80, 0xee, 0x53, 0x37, 0x8b, 0x86, 0x70, 0xf2, 0x3e, 0x33, 0xef, 0x56 }, - { 0xc7, 0x0e, 0xf9, 0xbf, 0xd7, 0x75, 0xd4, 0x08, 0x17, 0x67, 0x37, 0xa0, 0x73, 0x6d, 0x68, 0x51, 0x7c, 0xe1, 0xaa, 0xad, 0x7e, 0x81, 0xa9, 0x3c, 0x8c, 0x1e, 0xd9, 0x67, 0xea, 0x21, 0x4f, 0x56, 0xc8, 0xa3, 0x77, 0xb1, 0x76, 0x3e, 0x67, 0x66, 0x15, 0xb6, 0x0f, 0x39, 0x88, 0x24, 0x1e, 0xae, 0x6e, 0xab, 0x96, 0x85, 0xa5, 0x12, 0x49, 0x29, 0xd2, 0x81, 0x88, 0xf2, 0x9e, 0xab, 0x06, 0xf7 }, - { 0xc2, 0x30, 0xf0, 0x80, 0x26, 0x79, 0xcb, 0x33, 0x82, 0x2e, 0xf8, 0xb3, 0xb2, 0x1b, 0xf7, 0xa9, 0xa2, 0x89, 0x42, 0x09, 0x29, 0x01, 0xd7, 0xda, 0xc3, 0x76, 0x03, 0x00, 0x83, 0x10, 0x26, 0xcf, 0x35, 0x4c, 0x92, 0x32, 0xdf, 0x3e, 0x08, 0x4d, 0x99, 0x03, 0x13, 0x0c, 0x60, 0x1f, 0x63, 0xc1, 0xf4, 0xa4, 0xa4, 0xb8, 0x10, 0x6e, 0x46, 0x8c, 0xd4, 0x43, 0xbb, 0xe5, 0xa7, 0x34, 0xf4, 0x5f }, - { 0x6f, 0x43, 0x09, 0x4c, 0xaf, 0xb5, 0xeb, 0xf1, 0xf7, 0xa4, 0x93, 0x7e, 0xc5, 0x0f, 0x56, 0xa4, 0xc9, 0xda, 0x30, 0x3c, 0xbb, 0x55, 0xac, 0x1f, 0x27, 0xf1, 0xf1, 0x97, 0x6c, 0xd9, 0x6b, 0xed, 0xa9, 0x46, 0x4f, 0x0e, 0x7b, 0x9c, 0x54, 0x62, 0x0b, 0x8a, 0x9f, 0xba, 0x98, 0x31, 0x64, 0xb8, 0xbe, 0x35, 0x78, 0x42, 0x5a, 0x02, 0x4f, 0x5f, 0xe1, 0x99, 0xc3, 0x63, 0x56, 0xb8, 0x89, 0x72 }, - { 0x37, 0x45, 0x27, 0x3f, 0x4c, 0x38, 0x22, 0x5d, 0xb2, 0x33, 0x73, 0x81, 0x87, 0x1a, 0x0c, 0x6a, 0xaf, 0xd3, 0xaf, 0x9b, 0x01, 0x8c, 0x88, 0xaa, 0x02, 0x02, 0x58, 0x50, 0xa5, 0xdc, 0x3a, 0x42, 0xa1, 0xa3, 0xe0, 0x3e, 0x56, 0xcb, 0xf1, 0xb0, 0x87, 0x6d, 0x63, 0xa4, 0x41, 0xf1, 0xd2, 0x85, 0x6a, 0x39, 0xb8, 0x80, 0x1e, 0xb5, 0xaf, 0x32, 0x52, 0x01, 0xc4, 0x15, 0xd6, 0x5e, 0x97, 0xfe }, - { 0xc5, 0x0c, 0x44, 0xcc, 0xa3, 0xec, 0x3e, 0xda, 0xae, 0x77, 0x9a, 0x7e, 0x17, 0x94, 0x50, 0xeb, 0xdd, 0xa2, 0xf9, 0x70, 0x67, 0xc6, 0x90, 0xaa, 0x6c, 0x5a, 0x4a, 0xc7, 0xc3, 0x01, 0x39, 0xbb, 0x27, 0xc0, 0xdf, 0x4d, 0xb3, 0x22, 0x0e, 0x63, 0xcb, 0x11, 0x0d, 0x64, 0xf3, 0x7f, 0xfe, 0x07, 0x8d, 0xb7, 0x26, 0x53, 0xe2, 0xda, 0xac, 0xf9, 0x3a, 0xe3, 0xf0, 0xa2, 0xd1, 0xa7, 0xeb, 0x2e }, - { 0x8a, 0xef, 0x26, 0x3e, 0x38, 0x5c, 0xbc, 0x61, 0xe1, 0x9b, 0x28, 0x91, 0x42, 0x43, 0x26, 0x2a, 0xf5, 0xaf, 0xe8, 0x72, 0x6a, 0xf3, 0xce, 0x39, 0xa7, 0x9c, 0x27, 0x02, 0x8c, 0xf3, 0xec, 0xd3, 0xf8, 0xd2, 0xdf, 0xd9, 0xcf, 0xc9, 0xad, 0x91, 0xb5, 0x8f, 0x6f, 0x20, 0x77, 0x8f, 0xd5, 0xf0, 0x28, 0x94, 0xa3, 0xd9, 0x1c, 0x7d, 0x57, 0xd1, 0xe4, 0xb8, 0x66, 0xa7, 0xf3, 0x64, 0xb6, 0xbe }, - { 0x28, 0x69, 0x61, 0x41, 0xde, 0x6e, 0x2d, 0x9b, 0xcb, 0x32, 0x35, 0x57, 0x8a, 0x66, 0x16, 0x6c, 0x14, 0x48, 0xd3, 0xe9, 0x05, 0xa1, 0xb4, 0x82, 0xd4, 0x23, 0xbe, 0x4b, 0xc5, 0x36, 0x9b, 0xc8, 0xc7, 0x4d, 0xae, 0x0a, 0xcc, 0x9c, 0xc1, 0x23, 0xe1, 0xd8, 0xdd, 0xce, 0x9f, 0x97, 0x91, 0x7e, 0x8c, 0x01, 0x9c, 0x55, 0x2d, 0xa3, 0x2d, 0x39, 0xd2, 0x21, 0x9b, 0x9a, 0xbf, 0x0f, 0xa8, 0xc8 }, - { 0x2f, 0xb9, 0xeb, 0x20, 0x85, 0x83, 0x01, 0x81, 0x90, 0x3a, 0x9d, 0xaf, 0xe3, 0xdb, 0x42, 0x8e, 0xe1, 0x5b, 0xe7, 0x66, 0x22, 0x24, 0xef, 0xd6, 0x43, 0x37, 0x1f, 0xb2, 0x56, 0x46, 0xae, 0xe7, 0x16, 0xe5, 0x31, 0xec, 0xa6, 0x9b, 0x2b, 0xdc, 0x82, 0x33, 0xf1, 0xa8, 0x08, 0x1f, 0xa4, 0x3d, 0xa1, 0x50, 0x03, 0x02, 0x97, 0x5a, 0x77, 0xf4, 0x2f, 0xa5, 0x92, 0x13, 0x67, 0x10, 0xe9, 0xdc }, - { 0x66, 0xf9, 0xa7, 0x14, 0x3f, 0x7a, 0x33, 0x14, 0xa6, 0x69, 0xbf, 0x2e, 0x24, 0xbb, 0xb3, 0x50, 0x14, 0x26, 0x1d, 0x63, 0x9f, 0x49, 0x5b, 0x6c, 0x9c, 0x1f, 0x10, 0x4f, 0xe8, 0xe3, 0x20, 0xac, 0xa6, 0x0d, 0x45, 0x50, 0xd6, 0x9d, 0x52, 0xed, 0xbd, 0x5a, 0x3c, 0xde, 0xb4, 0x01, 0x4a, 0xe6, 0x5b, 0x1d, 0x87, 0xaa, 0x77, 0x0b, 0x69, 0xae, 0x5c, 0x15, 0xf4, 0x33, 0x0b, 0x0b, 0x0a, 0xd8 }, - { 0xf4, 0xc4, 0xdd, 0x1d, 0x59, 0x4c, 0x35, 0x65, 0xe3, 0xe2, 0x5c, 0xa4, 0x3d, 0xad, 0x82, 0xf6, 0x2a, 0xbe, 0xa4, 0x83, 0x5e, 0xd4, 0xcd, 0x81, 0x1b, 0xcd, 0x97, 0x5e, 0x46, 0x27, 0x98, 0x28, 0xd4, 0x4d, 0x4c, 0x62, 0xc3, 0x67, 0x9f, 0x1b, 0x7f, 0x7b, 0x9d, 0xd4, 0x57, 0x1d, 0x7b, 0x49, 0x55, 0x73, 0x47, 0xb8, 0xc5, 0x46, 0x0c, 0xbd, 0xc1, 0xbe, 0xf6, 0x90, 0xfb, 0x2a, 0x08, 0xc0 }, - { 0x8f, 0x1d, 0xc9, 0x64, 0x9c, 0x3a, 0x84, 0x55, 0x1f, 0x8f, 0x6e, 0x91, 0xca, 0xc6, 0x82, 0x42, 0xa4, 0x3b, 0x1f, 0x8f, 0x32, 0x8e, 0xe9, 0x22, 0x80, 0x25, 0x73, 0x87, 0xfa, 0x75, 0x59, 0xaa, 0x6d, 0xb1, 0x2e, 0x4a, 0xea, 0xdc, 0x2d, 0x26, 0x09, 0x91, 0x78, 0x74, 0x9c, 0x68, 0x64, 0xb3, 0x57, 0xf3, 0xf8, 0x3b, 0x2f, 0xb3, 0xef, 0xa8, 0xd2, 0xa8, 0xdb, 0x05, 0x6b, 0xed, 0x6b, 0xcc }, - { 0x31, 0x39, 0xc1, 0xa7, 0xf9, 0x7a, 0xfd, 0x16, 0x75, 0xd4, 0x60, 0xeb, 0xbc, 0x07, 0xf2, 0x72, 0x8a, 0xa1, 0x50, 0xdf, 0x84, 0x96, 0x24, 0x51, 0x1e, 0xe0, 0x4b, 0x74, 0x3b, 0xa0, 0xa8, 0x33, 0x09, 0x2f, 0x18, 0xc1, 0x2d, 0xc9, 0x1b, 0x4d, 0xd2, 0x43, 0xf3, 0x33, 0x40, 0x2f, 0x59, 0xfe, 0x28, 0xab, 0xdb, 0xbb, 0xae, 0x30, 0x1e, 0x7b, 0x65, 0x9c, 0x7a, 0x26, 0xd5, 0xc0, 0xf9, 0x79 }, - { 0x06, 0xf9, 0x4a, 0x29, 0x96, 0x15, 0x8a, 0x81, 0x9f, 0xe3, 0x4c, 0x40, 0xde, 0x3c, 0xf0, 0x37, 0x9f, 0xd9, 0xfb, 0x85, 0xb3, 0xe3, 0x63, 0xba, 0x39, 0x26, 0xa0, 0xe7, 0xd9, 0x60, 0xe3, 0xf4, 0xc2, 0xe0, 0xc7, 0x0c, 0x7c, 0xe0, 0xcc, 0xb2, 0xa6, 0x4f, 0xc2, 0x98, 0x69, 0xf6, 0xe7, 0xab, 0x12, 0xbd, 0x4d, 0x3f, 0x14, 0xfc, 0xe9, 0x43, 0x27, 0x90, 0x27, 0xe7, 0x85, 0xfb, 0x5c, 0x29 }, - { 0xc2, 0x9c, 0x39, 0x9e, 0xf3, 0xee, 0xe8, 0x96, 0x1e, 0x87, 0x56, 0x5c, 0x1c, 0xe2, 0x63, 0x92, 0x5f, 0xc3, 0xd0, 0xce, 0x26, 0x7d, 0x13, 0xe4, 0x8d, 0xd9, 0xe7, 0x32, 0xee, 0x67, 0xb0, 0xf6, 0x9f, 0xad, 0x56, 0x40, 0x1b, 0x0f, 0x10, 0xfc, 0xaa, 0xc1, 0x19, 0x20, 0x10, 0x46, 0xcc, 0xa2, 0x8c, 0x5b, 0x14, 0xab, 0xde, 0xa3, 0x21, 0x2a, 0xe6, 0x55, 0x62, 0xf7, 0xf1, 0x38, 0xdb, 0x3d }, - { 0x4c, 0xec, 0x4c, 0x9d, 0xf5, 0x2e, 0xef, 0x05, 0xc3, 0xf6, 0xfa, 0xaa, 0x97, 0x91, 0xbc, 0x74, 0x45, 0x93, 0x71, 0x83, 0x22, 0x4e, 0xcc, 0x37, 0xa1, 0xe5, 0x8d, 0x01, 0x32, 0xd3, 0x56, 0x17, 0x53, 0x1d, 0x7e, 0x79, 0x5f, 0x52, 0xaf, 0x7b, 0x1e, 0xb9, 0xd1, 0x47, 0xde, 0x12, 0x92, 0xd3, 0x45, 0xfe, 0x34, 0x18, 0x23, 0xf8, 0xe6, 0xbc, 0x1e, 0x5b, 0xad, 0xca, 0x5c, 0x65, 0x61, 0x08 }, - { 0x89, 0x8b, 0xfb, 0xae, 0x93, 0xb3, 0xe1, 0x8d, 0x00, 0x69, 0x7e, 0xab, 0x7d, 0x97, 0x04, 0xfa, 0x36, 0xec, 0x33, 0x9d, 0x07, 0x61, 0x31, 0xce, 0xfd, 0xf3, 0x0e, 0xdb, 0xe8, 0xd9, 0xcc, 0x81, 0xc3, 0xa8, 0x0b, 0x12, 0x96, 0x59, 0xb1, 0x63, 0xa3, 0x23, 0xba, 0xb9, 0x79, 0x3d, 0x4f, 0xee, 0xd9, 0x2d, 0x54, 0xda, 0xe9, 0x66, 0xc7, 0x75, 0x29, 0x76, 0x4a, 0x09, 0xbe, 0x88, 0xdb, 0x45 }, - { 0xee, 0x9b, 0xd0, 0x46, 0x9d, 0x3a, 0xaf, 0x4f, 0x14, 0x03, 0x5b, 0xe4, 0x8a, 0x2c, 0x3b, 0x84, 0xd9, 0xb4, 0xb1, 0xff, 0xf1, 0xd9, 0x45, 0xe1, 0xf1, 0xc1, 0xd3, 0x89, 0x80, 0xa9, 0x51, 0xbe, 0x19, 0x7b, 0x25, 0xfe, 0x22, 0xc7, 0x31, 0xf2, 0x0a, 0xea, 0xcc, 0x93, 0x0b, 0xa9, 0xc4, 0xa1, 0xf4, 0x76, 0x22, 0x27, 0x61, 0x7a, 0xd3, 0x50, 0xfd, 0xab, 0xb4, 0xe8, 0x02, 0x73, 0xa0, 0xf4 }, - { 0x3d, 0x4d, 0x31, 0x13, 0x30, 0x05, 0x81, 0xcd, 0x96, 0xac, 0xbf, 0x09, 0x1c, 0x3d, 0x0f, 0x3c, 0x31, 0x01, 0x38, 0xcd, 0x69, 0x79, 0xe6, 0x02, 0x6c, 0xde, 0x62, 0x3e, 0x2d, 0xd1, 0xb2, 0x4d, 0x4a, 0x86, 0x38, 0xbe, 0xd1, 0x07, 0x33, 0x44, 0x78, 0x3a, 0xd0, 0x64, 0x9c, 0xc6, 0x30, 0x5c, 0xce, 0xc0, 0x4b, 0xeb, 0x49, 0xf3, 0x1c, 0x63, 0x30, 0x88, 0xa9, 0x9b, 0x65, 0x13, 0x02, 0x67 }, - { 0x95, 0xc0, 0x59, 0x1a, 0xd9, 0x1f, 0x92, 0x1a, 0xc7, 0xbe, 0x6d, 0x9c, 0xe3, 0x7e, 0x06, 0x63, 0xed, 0x80, 0x11, 0xc1, 0xcf, 0xd6, 0xd0, 0x16, 0x2a, 0x55, 0x72, 0xe9, 0x43, 0x68, 0xba, 0xc0, 0x20, 0x24, 0x48, 0x5e, 0x6a, 0x39, 0x85, 0x4a, 0xa4, 0x6f, 0xe3, 0x8e, 0x97, 0xd6, 0xc6, 0xb1, 0x94, 0x7c, 0xd2, 0x72, 0xd8, 0x6b, 0x06, 0xbb, 0x5b, 0x2f, 0x78, 0xb9, 0xb6, 0x8d, 0x55, 0x9d }, - { 0x22, 0x7b, 0x79, 0xde, 0xd3, 0x68, 0x15, 0x3b, 0xf4, 0x6c, 0x0a, 0x3c, 0xa9, 0x78, 0xbf, 0xdb, 0xef, 0x31, 0xf3, 0x02, 0x4a, 0x56, 0x65, 0x84, 0x24, 0x68, 0x49, 0x0b, 0x0f, 0xf7, 0x48, 0xae, 0x04, 0xe7, 0x83, 0x2e, 0xd4, 0xc9, 0xf4, 0x9d, 0xe9, 0xb1, 0x70, 0x67, 0x09, 0xd6, 0x23, 0xe5, 0xc8, 0xc1, 0x5e, 0x3c, 0xae, 0xca, 0xe8, 0xd5, 0xe4, 0x33, 0x43, 0x0f, 0xf7, 0x2f, 0x20, 0xeb }, - { 0x5d, 0x34, 0xf3, 0x95, 0x2f, 0x01, 0x05, 0xee, 0xf8, 0x8a, 0xe8, 0xb6, 0x4c, 0x6c, 0xe9, 0x5e, 0xbf, 0xad, 0xe0, 0xe0, 0x2c, 0x69, 0xb0, 0x87, 0x62, 0xa8, 0x71, 0x2d, 0x2e, 0x49, 0x11, 0xad, 0x3f, 0x94, 0x1f, 0xc4, 0x03, 0x4d, 0xc9, 0xb2, 0xe4, 0x79, 0xfd, 0xbc, 0xd2, 0x79, 0xb9, 0x02, 0xfa, 0xf5, 0xd8, 0x38, 0xbb, 0x2e, 0x0c, 0x64, 0x95, 0xd3, 0x72, 0xb5, 0xb7, 0x02, 0x98, 0x13 }, - { 0x7f, 0x93, 0x9b, 0xf8, 0x35, 0x3a, 0xbc, 0xe4, 0x9e, 0x77, 0xf1, 0x4f, 0x37, 0x50, 0xaf, 0x20, 0xb7, 0xb0, 0x39, 0x02, 0xe1, 0xa1, 0xe7, 0xfb, 0x6a, 0xaf, 0x76, 0xd0, 0x25, 0x9c, 0xd4, 0x01, 0xa8, 0x31, 0x90, 0xf1, 0x56, 0x40, 0xe7, 0x4f, 0x3e, 0x6c, 0x5a, 0x90, 0xe8, 0x39, 0xc7, 0x82, 0x1f, 0x64, 0x74, 0x75, 0x7f, 0x75, 0xc7, 0xbf, 0x90, 0x02, 0x08, 0x4d, 0xdc, 0x7a, 0x62, 0xdc }, - { 0x06, 0x2b, 0x61, 0xa2, 0xf9, 0xa3, 0x3a, 0x71, 0xd7, 0xd0, 0xa0, 0x61, 0x19, 0x64, 0x4c, 0x70, 0xb0, 0x71, 0x6a, 0x50, 0x4d, 0xe7, 0xe5, 0xe1, 0xbe, 0x49, 0xbd, 0x7b, 0x86, 0xe7, 0xed, 0x68, 0x17, 0x71, 0x4f, 0x9f, 0x0f, 0xc3, 0x13, 0xd0, 0x61, 0x29, 0x59, 0x7e, 0x9a, 0x22, 0x35, 0xec, 0x85, 0x21, 0xde, 0x36, 0xf7, 0x29, 0x0a, 0x90, 0xcc, 0xfc, 0x1f, 0xfa, 0x6d, 0x0a, 0xee, 0x29 }, - { 0xf2, 0x9e, 0x01, 0xee, 0xae, 0x64, 0x31, 0x1e, 0xb7, 0xf1, 0xc6, 0x42, 0x2f, 0x94, 0x6b, 0xf7, 0xbe, 0xa3, 0x63, 0x79, 0x52, 0x3e, 0x7b, 0x2b, 0xba, 0xba, 0x7d, 0x1d, 0x34, 0xa2, 0x2d, 0x5e, 0xa5, 0xf1, 0xc5, 0xa0, 0x9d, 0x5c, 0xe1, 0xfe, 0x68, 0x2c, 0xce, 0xd9, 0xa4, 0x79, 0x8d, 0x1a, 0x05, 0xb4, 0x6c, 0xd7, 0x2d, 0xff, 0x5c, 0x1b, 0x35, 0x54, 0x40, 0xb2, 0xa2, 0xd4, 0x76, 0xbc }, - { 0xec, 0x38, 0xcd, 0x3b, 0xba, 0xb3, 0xef, 0x35, 0xd7, 0xcb, 0x6d, 0x5c, 0x91, 0x42, 0x98, 0x35, 0x1d, 0x8a, 0x9d, 0xc9, 0x7f, 0xce, 0xe0, 0x51, 0xa8, 0xa0, 0x2f, 0x58, 0xe3, 0xed, 0x61, 0x84, 0xd0, 0xb7, 0x81, 0x0a, 0x56, 0x15, 0x41, 0x1a, 0xb1, 0xb9, 0x52, 0x09, 0xc3, 0xc8, 0x10, 0x11, 0x4f, 0xde, 0xb2, 0x24, 0x52, 0x08, 0x4e, 0x77, 0xf3, 0xf8, 0x47, 0xc6, 0xdb, 0xaa, 0xfe, 0x16 }, - { 0xc2, 0xae, 0xf5, 0xe0, 0xca, 0x43, 0xe8, 0x26, 0x41, 0x56, 0x5b, 0x8c, 0xb9, 0x43, 0xaa, 0x8b, 0xa5, 0x35, 0x50, 0xca, 0xef, 0x79, 0x3b, 0x65, 0x32, 0xfa, 0xfa, 0xd9, 0x4b, 0x81, 0x60, 0x82, 0xf0, 0x11, 0x3a, 0x3e, 0xa2, 0xf6, 0x36, 0x08, 0xab, 0x40, 0x43, 0x7e, 0xcc, 0x0f, 0x02, 0x29, 0xcb, 0x8f, 0xa2, 0x24, 0xdc, 0xf1, 0xc4, 0x78, 0xa6, 0x7d, 0x9b, 0x64, 0x16, 0x2b, 0x92, 0xd1 }, - { 0x15, 0xf5, 0x34, 0xef, 0xff, 0x71, 0x05, 0xcd, 0x1c, 0x25, 0x4d, 0x07, 0x4e, 0x27, 0xd5, 0x89, 0x8b, 0x89, 0x31, 0x3b, 0x7d, 0x36, 0x6d, 0xc2, 0xd7, 0xd8, 0x71, 0x13, 0xfa, 0x7d, 0x53, 0xaa, 0xe1, 0x3f, 0x6d, 0xba, 0x48, 0x7a, 0xd8, 0x10, 0x3d, 0x5e, 0x85, 0x4c, 0x91, 0xfd, 0xb6, 0xe1, 0xe7, 0x4b, 0x2e, 0xf6, 0xd1, 0x43, 0x17, 0x69, 0xc3, 0x07, 0x67, 0xdd, 0xe0, 0x67, 0xa3, 0x5c }, - { 0x89, 0xac, 0xbc, 0xa0, 0xb1, 0x69, 0x89, 0x7a, 0x0a, 0x27, 0x14, 0xc2, 0xdf, 0x8c, 0x95, 0xb5, 0xb7, 0x9c, 0xb6, 0x93, 0x90, 0x14, 0x2b, 0x7d, 0x60, 0x18, 0xbb, 0x3e, 0x30, 0x76, 0xb0, 0x99, 0xb7, 0x9a, 0x96, 0x41, 0x52, 0xa9, 0xd9, 0x12, 0xb1, 0xb8, 0x64, 0x12, 0xb7, 0xe3, 0x72, 0xe9, 0xce, 0xca, 0xd7, 0xf2, 0x5d, 0x4c, 0xba, 0xb8, 0xa3, 0x17, 0xbe, 0x36, 0x49, 0x2a, 0x67, 0xd7 }, - { 0xe3, 0xc0, 0x73, 0x91, 0x90, 0xed, 0x84, 0x9c, 0x9c, 0x96, 0x2f, 0xd9, 0xdb, 0xb5, 0x5e, 0x20, 0x7e, 0x62, 0x4f, 0xca, 0xc1, 0xeb, 0x41, 0x76, 0x91, 0x51, 0x54, 0x99, 0xee, 0xa8, 0xd8, 0x26, 0x7b, 0x7e, 0x8f, 0x12, 0x87, 0xa6, 0x36, 0x33, 0xaf, 0x50, 0x11, 0xfd, 0xe8, 0xc4, 0xdd, 0xf5, 0x5b, 0xfd, 0xf7, 0x22, 0xed, 0xf8, 0x88, 0x31, 0x41, 0x4f, 0x2c, 0xfa, 0xed, 0x59, 0xcb, 0x9a }, - { 0x8d, 0x6c, 0xf8, 0x7c, 0x08, 0x38, 0x0d, 0x2d, 0x15, 0x06, 0xee, 0xe4, 0x6f, 0xd4, 0x22, 0x2d, 0x21, 0xd8, 0xc0, 0x4e, 0x58, 0x5f, 0xbf, 0xd0, 0x82, 0x69, 0xc9, 0x8f, 0x70, 0x28, 0x33, 0xa1, 0x56, 0x32, 0x6a, 0x07, 0x24, 0x65, 0x64, 0x00, 0xee, 0x09, 0x35, 0x1d, 0x57, 0xb4, 0x40, 0x17, 0x5e, 0x2a, 0x5d, 0xe9, 0x3c, 0xc5, 0xf8, 0x0d, 0xb6, 0xda, 0xf8, 0x35, 0x76, 0xcf, 0x75, 0xfa }, - { 0xda, 0x24, 0xbe, 0xde, 0x38, 0x36, 0x66, 0xd5, 0x63, 0xee, 0xed, 0x37, 0xf6, 0x31, 0x9b, 0xaf, 0x20, 0xd5, 0xc7, 0x5d, 0x16, 0x35, 0xa6, 0xba, 0x5e, 0xf4, 0xcf, 0xa1, 0xac, 0x95, 0x48, 0x7e, 0x96, 0xf8, 0xc0, 0x8a, 0xf6, 0x00, 0xaa, 0xb8, 0x7c, 0x98, 0x6e, 0xba, 0xd4, 0x9f, 0xc7, 0x0a, 0x58, 0xb4, 0x89, 0x0b, 0x9c, 0x87, 0x6e, 0x09, 0x10, 0x16, 0xda, 0xf4, 0x9e, 0x1d, 0x32, 0x2e }, - { 0xf9, 0xd1, 0xd1, 0xb1, 0xe8, 0x7e, 0xa7, 0xae, 0x75, 0x3a, 0x02, 0x97, 0x50, 0xcc, 0x1c, 0xf3, 0xd0, 0x15, 0x7d, 0x41, 0x80, 0x5e, 0x24, 0x5c, 0x56, 0x17, 0xbb, 0x93, 0x4e, 0x73, 0x2f, 0x0a, 0xe3, 0x18, 0x0b, 0x78, 0xe0, 0x5b, 0xfe, 0x76, 0xc7, 0xc3, 0x05, 0x1e, 0x3e, 0x3a, 0xc7, 0x8b, 0x9b, 0x50, 0xc0, 0x51, 0x42, 0x65, 0x7e, 0x1e, 0x03, 0x21, 0x5d, 0x6e, 0xc7, 0xbf, 0xd0, 0xfc }, - { 0x11, 0xb7, 0xbc, 0x16, 0x68, 0x03, 0x20, 0x48, 0xaa, 0x43, 0x34, 0x3d, 0xe4, 0x76, 0x39, 0x5e, 0x81, 0x4b, 0xbb, 0xc2, 0x23, 0x67, 0x8d, 0xb9, 0x51, 0xa1, 0xb0, 0x3a, 0x02, 0x1e, 0xfa, 0xc9, 0x48, 0xcf, 0xbe, 0x21, 0x5f, 0x97, 0xfe, 0x9a, 0x72, 0xa2, 0xf6, 0xbc, 0x03, 0x9e, 0x39, 0x56, 0xbf, 0xa4, 0x17, 0xc1, 0xa9, 0xf1, 0x0d, 0x6d, 0x7b, 0xa5, 0xd3, 0xd3, 0x2f, 0xf3, 0x23, 0xe5 }, - { 0xb8, 0xd9, 0x00, 0x0e, 0x4f, 0xc2, 0xb0, 0x66, 0xed, 0xb9, 0x1a, 0xfe, 0xe8, 0xe7, 0xeb, 0x0f, 0x24, 0xe3, 0xa2, 0x01, 0xdb, 0x8b, 0x67, 0x93, 0xc0, 0x60, 0x85, 0x81, 0xe6, 0x28, 0xed, 0x0b, 0xcc, 0x4e, 0x5a, 0xa6, 0x78, 0x79, 0x92, 0xa4, 0xbc, 0xc4, 0x4e, 0x28, 0x80, 0x93, 0xe6, 0x3e, 0xe8, 0x3a, 0xbd, 0x0b, 0xc3, 0xec, 0x6d, 0x09, 0x34, 0xa6, 0x74, 0xa4, 0xda, 0x13, 0x83, 0x8a }, - { 0xce, 0x32, 0x5e, 0x29, 0x4f, 0x9b, 0x67, 0x19, 0xd6, 0xb6, 0x12, 0x78, 0x27, 0x6a, 0xe0, 0x6a, 0x25, 0x64, 0xc0, 0x3b, 0xb0, 0xb7, 0x83, 0xfa, 0xfe, 0x78, 0x5b, 0xdf, 0x89, 0xc7, 0xd5, 0xac, 0xd8, 0x3e, 0x78, 0x75, 0x6d, 0x30, 0x1b, 0x44, 0x56, 0x99, 0x02, 0x4e, 0xae, 0xb7, 0x7b, 0x54, 0xd4, 0x77, 0x33, 0x6e, 0xc2, 0xa4, 0xf3, 0x32, 0xf2, 0xb3, 0xf8, 0x87, 0x65, 0xdd, 0xb0, 0xc3 }, - { 0x29, 0xac, 0xc3, 0x0e, 0x96, 0x03, 0xae, 0x2f, 0xcc, 0xf9, 0x0b, 0xf9, 0x7e, 0x6c, 0xc4, 0x63, 0xeb, 0xe2, 0x8c, 0x1b, 0x2f, 0x9b, 0x4b, 0x76, 0x5e, 0x70, 0x53, 0x7c, 0x25, 0xc7, 0x02, 0xa2, 0x9d, 0xcb, 0xfb, 0xf1, 0x4c, 0x99, 0xc5, 0x43, 0x45, 0xba, 0x2b, 0x51, 0xf1, 0x7b, 0x77, 0xb5, 0xf1, 0x5d, 0xb9, 0x2b, 0xba, 0xd8, 0xfa, 0x95, 0xc4, 0x71, 0xf5, 0xd0, 0x70, 0xa1, 0x37, 0xcc }, - { 0x33, 0x79, 0xcb, 0xaa, 0xe5, 0x62, 0xa8, 0x7b, 0x4c, 0x04, 0x25, 0x55, 0x0f, 0xfd, 0xd6, 0xbf, 0xe1, 0x20, 0x3f, 0x0d, 0x66, 0x6c, 0xc7, 0xea, 0x09, 0x5b, 0xe4, 0x07, 0xa5, 0xdf, 0xe6, 0x1e, 0xe9, 0x14, 0x41, 0xcd, 0x51, 0x54, 0xb3, 0xe5, 0x3b, 0x4f, 0x5f, 0xb3, 0x1a, 0xd4, 0xc7, 0xa9, 0xad, 0x5c, 0x7a, 0xf4, 0xae, 0x67, 0x9a, 0xa5, 0x1a, 0x54, 0x00, 0x3a, 0x54, 0xca, 0x6b, 0x2d }, - { 0x30, 0x95, 0xa3, 0x49, 0xd2, 0x45, 0x70, 0x8c, 0x7c, 0xf5, 0x50, 0x11, 0x87, 0x03, 0xd7, 0x30, 0x2c, 0x27, 0xb6, 0x0a, 0xf5, 0xd4, 0xe6, 0x7f, 0xc9, 0x78, 0xf8, 0xa4, 0xe6, 0x09, 0x53, 0xc7, 0xa0, 0x4f, 0x92, 0xfc, 0xf4, 0x1a, 0xee, 0x64, 0x32, 0x1c, 0xcb, 0x70, 0x7a, 0x89, 0x58, 0x51, 0x55, 0x2b, 0x1e, 0x37, 0xb0, 0x0b, 0xc5, 0xe6, 0xb7, 0x2f, 0xa5, 0xbc, 0xef, 0x9e, 0x3f, 0xff }, - { 0x07, 0x26, 0x2d, 0x73, 0x8b, 0x09, 0x32, 0x1f, 0x4d, 0xbc, 0xce, 0xc4, 0xbb, 0x26, 0xf4, 0x8c, 0xb0, 0xf0, 0xed, 0x24, 0x6c, 0xe0, 0xb3, 0x1b, 0x9a, 0x6e, 0x7b, 0xc6, 0x83, 0x04, 0x9f, 0x1f, 0x3e, 0x55, 0x45, 0xf2, 0x8c, 0xe9, 0x32, 0xdd, 0x98, 0x5c, 0x5a, 0xb0, 0xf4, 0x3b, 0xd6, 0xde, 0x07, 0x70, 0x56, 0x0a, 0xf3, 0x29, 0x06, 0x5e, 0xd2, 0xe4, 0x9d, 0x34, 0x62, 0x4c, 0x2c, 0xbb }, - { 0xb6, 0x40, 0x5e, 0xca, 0x8e, 0xe3, 0x31, 0x6c, 0x87, 0x06, 0x1c, 0xc6, 0xec, 0x18, 0xdb, 0xa5, 0x3e, 0x6c, 0x25, 0x0c, 0x63, 0xba, 0x1f, 0x3b, 0xae, 0x9e, 0x55, 0xdd, 0x34, 0x98, 0x03, 0x6a, 0xf0, 0x8c, 0xd2, 0x72, 0xaa, 0x24, 0xd7, 0x13, 0xc6, 0x02, 0x0d, 0x77, 0xab, 0x2f, 0x39, 0x19, 0xaf, 0x1a, 0x32, 0xf3, 0x07, 0x42, 0x06, 0x18, 0xab, 0x97, 0xe7, 0x39, 0x53, 0x99, 0x4f, 0xb4 }, - { 0x7e, 0xe6, 0x82, 0xf6, 0x31, 0x48, 0xee, 0x45, 0xf6, 0xe5, 0x31, 0x5d, 0xa8, 0x1e, 0x5c, 0x6e, 0x55, 0x7c, 0x2c, 0x34, 0x64, 0x1f, 0xc5, 0x09, 0xc7, 0xa5, 0x70, 0x10, 0x88, 0xc3, 0x8a, 0x74, 0x75, 0x61, 0x68, 0xe2, 0xcd, 0x8d, 0x35, 0x1e, 0x88, 0xfd, 0x1a, 0x45, 0x1f, 0x36, 0x0a, 0x01, 0xf5, 0xb2, 0x58, 0x0f, 0x9b, 0x5a, 0x2e, 0x8c, 0xfc, 0x13, 0x8f, 0x3d, 0xd5, 0x9a, 0x3f, 0xfc }, - { 0x1d, 0x26, 0x3c, 0x17, 0x9d, 0x6b, 0x26, 0x8f, 0x6f, 0xa0, 0x16, 0xf3, 0xa4, 0xf2, 0x9e, 0x94, 0x38, 0x91, 0x12, 0x5e, 0xd8, 0x59, 0x3c, 0x81, 0x25, 0x60, 0x59, 0xf5, 0xa7, 0xb4, 0x4a, 0xf2, 0xdc, 0xb2, 0x03, 0x0d, 0x17, 0x5c, 0x00, 0xe6, 0x2e, 0xca, 0xf7, 0xee, 0x96, 0x68, 0x2a, 0xa0, 0x7a, 0xb2, 0x0a, 0x61, 0x10, 0x24, 0xa2, 0x85, 0x32, 0xb1, 0xc2, 0x5b, 0x86, 0x65, 0x79, 0x02 }, - { 0x10, 0x6d, 0x13, 0x2c, 0xbd, 0xb4, 0xcd, 0x25, 0x97, 0x81, 0x28, 0x46, 0xe2, 0xbc, 0x1b, 0xf7, 0x32, 0xfe, 0xc5, 0xf0, 0xa5, 0xf6, 0x5d, 0xbb, 0x39, 0xec, 0x4e, 0x6d, 0xc6, 0x4a, 0xb2, 0xce, 0x6d, 0x24, 0x63, 0x0d, 0x0f, 0x15, 0xa8, 0x05, 0xc3, 0x54, 0x00, 0x25, 0xd8, 0x4a, 0xfa, 0x98, 0xe3, 0x67, 0x03, 0xc3, 0xdb, 0xee, 0x71, 0x3e, 0x72, 0xdd, 0xe8, 0x46, 0x5b, 0xc1, 0xbe, 0x7e }, - { 0x0e, 0x79, 0x96, 0x82, 0x26, 0x65, 0x06, 0x67, 0xa8, 0xd8, 0x62, 0xea, 0x8d, 0xa4, 0x89, 0x1a, 0xf5, 0x6a, 0x4e, 0x3a, 0x8b, 0x6d, 0x17, 0x50, 0xe3, 0x94, 0xf0, 0xde, 0xa7, 0x6d, 0x64, 0x0d, 0x85, 0x07, 0x7b, 0xce, 0xc2, 0xcc, 0x86, 0x88, 0x6e, 0x50, 0x67, 0x51, 0xb4, 0xf6, 0xa5, 0x83, 0x8f, 0x7f, 0x0b, 0x5f, 0xef, 0x76, 0x5d, 0x9d, 0xc9, 0x0d, 0xcd, 0xcb, 0xaf, 0x07, 0x9f, 0x08 }, - { 0x52, 0x11, 0x56, 0xa8, 0x2a, 0xb0, 0xc4, 0xe5, 0x66, 0xe5, 0x84, 0x4d, 0x5e, 0x31, 0xad, 0x9a, 0xaf, 0x14, 0x4b, 0xbd, 0x5a, 0x46, 0x4f, 0xdc, 0xa3, 0x4d, 0xbd, 0x57, 0x17, 0xe8, 0xff, 0x71, 0x1d, 0x3f, 0xfe, 0xbb, 0xfa, 0x08, 0x5d, 0x67, 0xfe, 0x99, 0x6a, 0x34, 0xf6, 0xd3, 0xe4, 0xe6, 0x0b, 0x13, 0x96, 0xbf, 0x4b, 0x16, 0x10, 0xc2, 0x63, 0xbd, 0xbb, 0x83, 0x4d, 0x56, 0x08, 0x16 }, - { 0x1a, 0xba, 0x88, 0xbe, 0xfc, 0x55, 0xbc, 0x25, 0xef, 0xbc, 0xe0, 0x2d, 0xb8, 0xb9, 0x93, 0x3e, 0x46, 0xf5, 0x76, 0x61, 0xba, 0xea, 0xbe, 0xb2, 0x1c, 0xc2, 0x57, 0x4d, 0x2a, 0x51, 0x8a, 0x3c, 0xba, 0x5d, 0xc5, 0xa3, 0x8e, 0x49, 0x71, 0x34, 0x40, 0xb2, 0x5f, 0x9c, 0x74, 0x4e, 0x75, 0xf6, 0xb8, 0x5c, 0x9d, 0x8f, 0x46, 0x81, 0xf6, 0x76, 0x16, 0x0f, 0x61, 0x05, 0x35, 0x7b, 0x84, 0x06 }, - { 0x5a, 0x99, 0x49, 0xfc, 0xb2, 0xc4, 0x73, 0xcd, 0xa9, 0x68, 0xac, 0x1b, 0x5d, 0x08, 0x56, 0x6d, 0xc2, 0xd8, 0x16, 0xd9, 0x60, 0xf5, 0x7e, 0x63, 0xb8, 0x98, 0xfa, 0x70, 0x1c, 0xf8, 0xeb, 0xd3, 0xf5, 0x9b, 0x12, 0x4d, 0x95, 0xbf, 0xbb, 0xed, 0xc5, 0xf1, 0xcf, 0x0e, 0x17, 0xd5, 0xea, 0xed, 0x0c, 0x02, 0xc5, 0x0b, 0x69, 0xd8, 0xa4, 0x02, 0xca, 0xbc, 0xca, 0x44, 0x33, 0xb5, 0x1f, 0xd4 }, - { 0xb0, 0xce, 0xad, 0x09, 0x80, 0x7c, 0x67, 0x2a, 0xf2, 0xeb, 0x2b, 0x0f, 0x06, 0xdd, 0xe4, 0x6c, 0xf5, 0x37, 0x0e, 0x15, 0xa4, 0x09, 0x6b, 0x1a, 0x7d, 0x7c, 0xbb, 0x36, 0xec, 0x31, 0xc2, 0x05, 0xfb, 0xef, 0xca, 0x00, 0xb7, 0xa4, 0x16, 0x2f, 0xa8, 0x9f, 0xb4, 0xfb, 0x3e, 0xb7, 0x8d, 0x79, 0x77, 0x0c, 0x23, 0xf4, 0x4e, 0x72, 0x06, 0x66, 0x4c, 0xe3, 0xcd, 0x93, 0x1c, 0x29, 0x1e, 0x5d }, - { 0xbb, 0x66, 0x64, 0x93, 0x1e, 0xc9, 0x70, 0x44, 0xe4, 0x5b, 0x2a, 0xe4, 0x20, 0xae, 0x1c, 0x55, 0x1a, 0x88, 0x74, 0xbc, 0x93, 0x7d, 0x08, 0xe9, 0x69, 0x39, 0x9c, 0x39, 0x64, 0xeb, 0xdb, 0xa8, 0x34, 0x6c, 0xdd, 0x5d, 0x09, 0xca, 0xaf, 0xe4, 0xc2, 0x8b, 0xa7, 0xec, 0x78, 0x81, 0x91, 0xce, 0xca, 0x65, 0xdd, 0xd6, 0xf9, 0x5f, 0x18, 0x58, 0x3e, 0x04, 0x0d, 0x0f, 0x30, 0xd0, 0x36, 0x4d }, - { 0x65, 0xbc, 0x77, 0x0a, 0x5f, 0xaa, 0x37, 0x92, 0x36, 0x98, 0x03, 0x68, 0x3e, 0x84, 0x4b, 0x0b, 0xe7, 0xee, 0x96, 0xf2, 0x9f, 0x6d, 0x6a, 0x35, 0x56, 0x80, 0x06, 0xbd, 0x55, 0x90, 0xf9, 0xa4, 0xef, 0x63, 0x9b, 0x7a, 0x80, 0x61, 0xc7, 0xb0, 0x42, 0x4b, 0x66, 0xb6, 0x0a, 0xc3, 0x4a, 0xf3, 0x11, 0x99, 0x05, 0xf3, 0x3a, 0x9d, 0x8c, 0x3a, 0xe1, 0x83, 0x82, 0xca, 0x9b, 0x68, 0x99, 0x00 }, - { 0xea, 0x9b, 0x4d, 0xca, 0x33, 0x33, 0x36, 0xaa, 0xf8, 0x39, 0xa4, 0x5c, 0x6e, 0xaa, 0x48, 0xb8, 0xcb, 0x4c, 0x7d, 0xda, 0xbf, 0xfe, 0xa4, 0xf6, 0x43, 0xd6, 0x35, 0x7e, 0xa6, 0x62, 0x8a, 0x48, 0x0a, 0x5b, 0x45, 0xf2, 0xb0, 0x52, 0xc1, 0xb0, 0x7d, 0x1f, 0xed, 0xca, 0x91, 0x8b, 0x6f, 0x11, 0x39, 0xd8, 0x0f, 0x74, 0xc2, 0x45, 0x10, 0xdc, 0xba, 0xa4, 0xbe, 0x70, 0xea, 0xcc, 0x1b, 0x06 }, - { 0xe6, 0x34, 0x2f, 0xb4, 0xa7, 0x80, 0xad, 0x97, 0x5d, 0x0e, 0x24, 0xbc, 0xe1, 0x49, 0x98, 0x9b, 0x91, 0xd3, 0x60, 0x55, 0x7e, 0x87, 0x99, 0x4f, 0x6b, 0x45, 0x7b, 0x89, 0x55, 0x75, 0xcc, 0x02, 0xd0, 0xc1, 0x5b, 0xad, 0x3c, 0xe7, 0x57, 0x7f, 0x4c, 0x63, 0x92, 0x7f, 0xf1, 0x3f, 0x3e, 0x38, 0x1f, 0xf7, 0xe7, 0x2b, 0xdb, 0xe7, 0x45, 0x32, 0x48, 0x44, 0xa9, 0xd2, 0x7e, 0x3f, 0x1c, 0x01 }, - { 0x3e, 0x20, 0x9c, 0x9b, 0x33, 0xe8, 0xe4, 0x61, 0x17, 0x8a, 0xb4, 0x6b, 0x1c, 0x64, 0xb4, 0x9a, 0x07, 0xfb, 0x74, 0x5f, 0x1c, 0x8b, 0xc9, 0x5f, 0xbf, 0xb9, 0x4c, 0x6b, 0x87, 0xc6, 0x95, 0x16, 0x65, 0x1b, 0x26, 0x4e, 0xf9, 0x80, 0x93, 0x7f, 0xad, 0x41, 0x23, 0x8b, 0x91, 0xdd, 0xc0, 0x11, 0xa5, 0xdd, 0x77, 0x7c, 0x7e, 0xfd, 0x44, 0x94, 0xb4, 0xb6, 0xec, 0xd3, 0xa9, 0xc2, 0x2a, 0xc0 }, - { 0xfd, 0x6a, 0x3d, 0x5b, 0x18, 0x75, 0xd8, 0x04, 0x86, 0xd6, 0xe6, 0x96, 0x94, 0xa5, 0x6d, 0xbb, 0x04, 0xa9, 0x9a, 0x4d, 0x05, 0x1f, 0x15, 0xdb, 0x26, 0x89, 0x77, 0x6b, 0xa1, 0xc4, 0x88, 0x2e, 0x6d, 0x46, 0x2a, 0x60, 0x3b, 0x70, 0x15, 0xdc, 0x9f, 0x4b, 0x74, 0x50, 0xf0, 0x53, 0x94, 0x30, 0x3b, 0x86, 0x52, 0xcf, 0xb4, 0x04, 0xa2, 0x66, 0x96, 0x2c, 0x41, 0xba, 0xe6, 0xe1, 0x8a, 0x94 }, - { 0x95, 0x1e, 0x27, 0x51, 0x7e, 0x6b, 0xad, 0x9e, 0x41, 0x95, 0xfc, 0x86, 0x71, 0xde, 0xe3, 0xe7, 0xe9, 0xbe, 0x69, 0xce, 0xe1, 0x42, 0x2c, 0xb9, 0xfe, 0xcf, 0xce, 0x0d, 0xba, 0x87, 0x5f, 0x7b, 0x31, 0x0b, 0x93, 0xee, 0x3a, 0x3d, 0x55, 0x8f, 0x94, 0x1f, 0x63, 0x5f, 0x66, 0x8f, 0xf8, 0x32, 0xd2, 0xc1, 0xd0, 0x33, 0xc5, 0xe2, 0xf0, 0x99, 0x7e, 0x4c, 0x66, 0xf1, 0x47, 0x34, 0x4e, 0x02 }, - { 0x8e, 0xba, 0x2f, 0x87, 0x4f, 0x1a, 0xe8, 0x40, 0x41, 0x90, 0x3c, 0x7c, 0x42, 0x53, 0xc8, 0x22, 0x92, 0x53, 0x0f, 0xc8, 0x50, 0x95, 0x50, 0xbf, 0xdc, 0x34, 0xc9, 0x5c, 0x7e, 0x28, 0x89, 0xd5, 0x65, 0x0b, 0x0a, 0xd8, 0xcb, 0x98, 0x8e, 0x5c, 0x48, 0x94, 0xcb, 0x87, 0xfb, 0xfb, 0xb1, 0x96, 0x12, 0xea, 0x93, 0xcc, 0xc4, 0xc5, 0xca, 0xd1, 0x71, 0x58, 0xb9, 0x76, 0x34, 0x64, 0xb4, 0x92 }, - { 0x16, 0xf7, 0x12, 0xea, 0xa1, 0xb7, 0xc6, 0x35, 0x47, 0x19, 0xa8, 0xe7, 0xdb, 0xdf, 0xaf, 0x55, 0xe4, 0x06, 0x3a, 0x4d, 0x27, 0x7d, 0x94, 0x75, 0x50, 0x01, 0x9b, 0x38, 0xdf, 0xb5, 0x64, 0x83, 0x09, 0x11, 0x05, 0x7d, 0x50, 0x50, 0x61, 0x36, 0xe2, 0x39, 0x4c, 0x3b, 0x28, 0x94, 0x5c, 0xc9, 0x64, 0x96, 0x7d, 0x54, 0xe3, 0x00, 0x0c, 0x21, 0x81, 0x62, 0x6c, 0xfb, 0x9b, 0x73, 0xef, 0xd2 }, - { 0xc3, 0x96, 0x39, 0xe7, 0xd5, 0xc7, 0xfb, 0x8c, 0xdd, 0x0f, 0xd3, 0xe6, 0xa5, 0x20, 0x96, 0x03, 0x94, 0x37, 0x12, 0x2f, 0x21, 0xc7, 0x8f, 0x16, 0x79, 0xce, 0xa9, 0xd7, 0x8a, 0x73, 0x4c, 0x56, 0xec, 0xbe, 0xb2, 0x86, 0x54, 0xb4, 0xf1, 0x8e, 0x34, 0x2c, 0x33, 0x1f, 0x6f, 0x72, 0x29, 0xec, 0x4b, 0x4b, 0xc2, 0x81, 0xb2, 0xd8, 0x0a, 0x6e, 0xb5, 0x00, 0x43, 0xf3, 0x17, 0x96, 0xc8, 0x8c }, - { 0x72, 0xd0, 0x81, 0xaf, 0x99, 0xf8, 0xa1, 0x73, 0xdc, 0xc9, 0xa0, 0xac, 0x4e, 0xb3, 0x55, 0x74, 0x05, 0x63, 0x9a, 0x29, 0x08, 0x4b, 0x54, 0xa4, 0x01, 0x72, 0x91, 0x2a, 0x2f, 0x8a, 0x39, 0x51, 0x29, 0xd5, 0x53, 0x6f, 0x09, 0x18, 0xe9, 0x02, 0xf9, 0xe8, 0xfa, 0x60, 0x00, 0x99, 0x5f, 0x41, 0x68, 0xdd, 0xc5, 0xf8, 0x93, 0x01, 0x1b, 0xe6, 0xa0, 0xdb, 0xc9, 0xb8, 0xa1, 0xa3, 0xf5, 0xbb }, - { 0xc1, 0x1a, 0xa8, 0x1e, 0x5e, 0xfd, 0x24, 0xd5, 0xfc, 0x27, 0xee, 0x58, 0x6c, 0xfd, 0x88, 0x47, 0xfb, 0xb0, 0xe2, 0x76, 0x01, 0xcc, 0xec, 0xe5, 0xec, 0xca, 0x01, 0x98, 0xe3, 0xc7, 0x76, 0x53, 0x93, 0xbb, 0x74, 0x45, 0x7c, 0x7e, 0x7a, 0x27, 0xeb, 0x91, 0x70, 0x35, 0x0e, 0x1f, 0xb5, 0x38, 0x57, 0x17, 0x75, 0x06, 0xbe, 0x3e, 0x76, 0x2c, 0xc0, 0xf1, 0x4d, 0x8c, 0x3a, 0xfe, 0x90, 0x77 }, - { 0xc2, 0x8f, 0x21, 0x50, 0xb4, 0x52, 0xe6, 0xc0, 0xc4, 0x24, 0xbc, 0xde, 0x6f, 0x8d, 0x72, 0x00, 0x7f, 0x93, 0x10, 0xfe, 0xd7, 0xf2, 0xf8, 0x7d, 0xe0, 0xdb, 0xb6, 0x4f, 0x44, 0x79, 0xd6, 0xc1, 0x44, 0x1b, 0xa6, 0x6f, 0x44, 0xb2, 0xac, 0xce, 0xe6, 0x16, 0x09, 0x17, 0x7e, 0xd3, 0x40, 0x12, 0x8b, 0x40, 0x7e, 0xce, 0xc7, 0xc6, 0x4b, 0xbe, 0x50, 0xd6, 0x3d, 0x22, 0xd8, 0x62, 0x77, 0x27 }, - { 0xf6, 0x3d, 0x88, 0x12, 0x28, 0x77, 0xec, 0x30, 0xb8, 0xc8, 0xb0, 0x0d, 0x22, 0xe8, 0x90, 0x00, 0xa9, 0x66, 0x42, 0x61, 0x12, 0xbd, 0x44, 0x16, 0x6e, 0x2f, 0x52, 0x5b, 0x76, 0x9c, 0xcb, 0xe9, 0xb2, 0x86, 0xd4, 0x37, 0xa0, 0x12, 0x91, 0x30, 0xdd, 0xe1, 0xa8, 0x6c, 0x43, 0xe0, 0x4b, 0xed, 0xb5, 0x94, 0xe6, 0x71, 0xd9, 0x82, 0x83, 0xaf, 0xe6, 0x4c, 0xe3, 0x31, 0xde, 0x98, 0x28, 0xfd }, - { 0x34, 0x8b, 0x05, 0x32, 0x88, 0x0b, 0x88, 0xa6, 0x61, 0x4a, 0x8d, 0x74, 0x08, 0xc3, 0xf9, 0x13, 0x35, 0x7f, 0xbb, 0x60, 0xe9, 0x95, 0xc6, 0x02, 0x05, 0xbe, 0x91, 0x39, 0xe7, 0x49, 0x98, 0xae, 0xde, 0x7f, 0x45, 0x81, 0xe4, 0x2f, 0x6b, 0x52, 0x69, 0x8f, 0x7f, 0xa1, 0x21, 0x97, 0x08, 0xc1, 0x44, 0x98, 0x06, 0x7f, 0xd1, 0xe0, 0x95, 0x02, 0xde, 0x83, 0xa7, 0x7d, 0xd2, 0x81, 0x15, 0x0c }, - { 0x51, 0x33, 0xdc, 0x8b, 0xef, 0x72, 0x53, 0x59, 0xdf, 0xf5, 0x97, 0x92, 0xd8, 0x5e, 0xaf, 0x75, 0xb7, 0xe1, 0xdc, 0xd1, 0x97, 0x8b, 0x01, 0xc3, 0x5b, 0x1b, 0x85, 0xfc, 0xeb, 0xc6, 0x33, 0x88, 0xad, 0x99, 0xa1, 0x7b, 0x63, 0x46, 0xa2, 0x17, 0xdc, 0x1a, 0x96, 0x22, 0xeb, 0xd1, 0x22, 0xec, 0xf6, 0x91, 0x3c, 0x4d, 0x31, 0xa6, 0xb5, 0x2a, 0x69, 0x5b, 0x86, 0xaf, 0x00, 0xd7, 0x41, 0xa0 }, - { 0x27, 0x53, 0xc4, 0xc0, 0xe9, 0x8e, 0xca, 0xd8, 0x06, 0xe8, 0x87, 0x80, 0xec, 0x27, 0xfc, 0xcd, 0x0f, 0x5c, 0x1a, 0xb5, 0x47, 0xf9, 0xe4, 0xbf, 0x16, 0x59, 0xd1, 0x92, 0xc2, 0x3a, 0xa2, 0xcc, 0x97, 0x1b, 0x58, 0xb6, 0x80, 0x25, 0x80, 0xba, 0xef, 0x8a, 0xdc, 0x3b, 0x77, 0x6e, 0xf7, 0x08, 0x6b, 0x25, 0x45, 0xc2, 0x98, 0x7f, 0x34, 0x8e, 0xe3, 0x71, 0x9c, 0xde, 0xf2, 0x58, 0xc4, 0x03 }, - { 0xb1, 0x66, 0x35, 0x73, 0xce, 0x4b, 0x9d, 0x8c, 0xae, 0xfc, 0x86, 0x50, 0x12, 0xf3, 0xe3, 0x97, 0x14, 0xb9, 0x89, 0x8a, 0x5d, 0xa6, 0xce, 0x17, 0xc2, 0x5a, 0x6a, 0x47, 0x93, 0x1a, 0x9d, 0xdb, 0x9b, 0xbe, 0x98, 0xad, 0xaa, 0x55, 0x3b, 0xee, 0xd4, 0x36, 0xe8, 0x95, 0x78, 0x45, 0x54, 0x16, 0xc2, 0xa5, 0x2a, 0x52, 0x5c, 0xf2, 0x86, 0x2b, 0x8d, 0x1d, 0x49, 0xa2, 0x53, 0x1b, 0x73, 0x91 }, - { 0x64, 0xf5, 0x8b, 0xd6, 0xbf, 0xc8, 0x56, 0xf5, 0xe8, 0x73, 0xb2, 0xa2, 0x95, 0x6e, 0xa0, 0xed, 0xa0, 0xd6, 0xdb, 0x0d, 0xa3, 0x9c, 0x8c, 0x7f, 0xc6, 0x7c, 0x9f, 0x9f, 0xee, 0xfc, 0xff, 0x30, 0x72, 0xcd, 0xf9, 0xe6, 0xea, 0x37, 0xf6, 0x9a, 0x44, 0xf0, 0xc6, 0x1a, 0xa0, 0xda, 0x36, 0x93, 0xc2, 0xdb, 0x5b, 0x54, 0x96, 0x0c, 0x02, 0x81, 0xa0, 0x88, 0x15, 0x1d, 0xb4, 0x2b, 0x11, 0xe8 }, - { 0x07, 0x64, 0xc7, 0xbe, 0x28, 0x12, 0x5d, 0x90, 0x65, 0xc4, 0xb9, 0x8a, 0x69, 0xd6, 0x0a, 0xed, 0xe7, 0x03, 0x54, 0x7c, 0x66, 0xa1, 0x2e, 0x17, 0xe1, 0xc6, 0x18, 0x99, 0x41, 0x32, 0xf5, 0xef, 0x82, 0x48, 0x2c, 0x1e, 0x3f, 0xe3, 0x14, 0x6c, 0xc6, 0x53, 0x76, 0xcc, 0x10, 0x9f, 0x01, 0x38, 0xed, 0x9a, 0x80, 0xe4, 0x9f, 0x1f, 0x3c, 0x7d, 0x61, 0x0d, 0x2f, 0x24, 0x32, 0xf2, 0x06, 0x05 }, - { 0xf7, 0x48, 0x78, 0x43, 0x98, 0xa2, 0xff, 0x03, 0xeb, 0xeb, 0x07, 0xe1, 0x55, 0xe6, 0x61, 0x16, 0xa8, 0x39, 0x74, 0x1a, 0x33, 0x6e, 0x32, 0xda, 0x71, 0xec, 0x69, 0x60, 0x01, 0xf0, 0xad, 0x1b, 0x25, 0xcd, 0x48, 0xc6, 0x9c, 0xfc, 0xa7, 0x26, 0x5e, 0xca, 0x1d, 0xd7, 0x19, 0x04, 0xa0, 0xce, 0x74, 0x8a, 0xc4, 0x12, 0x4f, 0x35, 0x71, 0x07, 0x6d, 0xfa, 0x71, 0x16, 0xa9, 0xcf, 0x00, 0xe9 }, - { 0x3f, 0x0d, 0xbc, 0x01, 0x86, 0xbc, 0xeb, 0x6b, 0x78, 0x5b, 0xa7, 0x8d, 0x2a, 0x2a, 0x01, 0x3c, 0x91, 0x0b, 0xe1, 0x57, 0xbd, 0xaf, 0xfa, 0xe8, 0x1b, 0xb6, 0x66, 0x3b, 0x1a, 0x73, 0x72, 0x2f, 0x7f, 0x12, 0x28, 0x79, 0x5f, 0x3e, 0xca, 0xda, 0x87, 0xcf, 0x6e, 0xf0, 0x07, 0x84, 0x74, 0xaf, 0x73, 0xf3, 0x1e, 0xca, 0x0c, 0xc2, 0x00, 0xed, 0x97, 0x5b, 0x68, 0x93, 0xf7, 0x61, 0xcb, 0x6d }, - { 0xd4, 0x76, 0x2c, 0xd4, 0x59, 0x98, 0x76, 0xca, 0x75, 0xb2, 0xb8, 0xfe, 0x24, 0x99, 0x44, 0xdb, 0xd2, 0x7a, 0xce, 0x74, 0x1f, 0xda, 0xb9, 0x36, 0x16, 0xcb, 0xc6, 0xe4, 0x25, 0x46, 0x0f, 0xeb, 0x51, 0xd4, 0xe7, 0xad, 0xcc, 0x38, 0x18, 0x0e, 0x7f, 0xc4, 0x7c, 0x89, 0x02, 0x4a, 0x7f, 0x56, 0x19, 0x1a, 0xdb, 0x87, 0x8d, 0xfd, 0xe4, 0xea, 0xd6, 0x22, 0x23, 0xf5, 0xa2, 0x61, 0x0e, 0xfe }, - { 0xcd, 0x36, 0xb3, 0xd5, 0xb4, 0xc9, 0x1b, 0x90, 0xfc, 0xbb, 0xa7, 0x95, 0x13, 0xcf, 0xee, 0x19, 0x07, 0xd8, 0x64, 0x5a, 0x16, 0x2a, 0xfd, 0x0c, 0xd4, 0xcf, 0x41, 0x92, 0xd4, 0xa5, 0xf4, 0xc8, 0x92, 0x18, 0x3a, 0x8e, 0xac, 0xdb, 0x2b, 0x6b, 0x6a, 0x9d, 0x9a, 0xa8, 0xc1, 0x1a, 0xc1, 0xb2, 0x61, 0xb3, 0x80, 0xdb, 0xee, 0x24, 0xca, 0x46, 0x8f, 0x1b, 0xfd, 0x04, 0x3c, 0x58, 0xee, 0xfe }, - { 0x98, 0x59, 0x34, 0x52, 0x28, 0x16, 0x61, 0xa5, 0x3c, 0x48, 0xa9, 0xd8, 0xcd, 0x79, 0x08, 0x26, 0xc1, 0xa1, 0xce, 0x56, 0x77, 0x38, 0x05, 0x3d, 0x0b, 0xee, 0x4a, 0x91, 0xa3, 0xd5, 0xbd, 0x92, 0xee, 0xfd, 0xba, 0xbe, 0xbe, 0x32, 0x04, 0xf2, 0x03, 0x1c, 0xa5, 0xf7, 0x81, 0xbd, 0xa9, 0x9e, 0xf5, 0xd8, 0xae, 0x56, 0xe5, 0xb0, 0x4a, 0x9e, 0x1e, 0xcd, 0x21, 0xb0, 0xeb, 0x05, 0xd3, 0xe1 }, - { 0x77, 0x1f, 0x57, 0xdd, 0x27, 0x75, 0xcc, 0xda, 0xb5, 0x59, 0x21, 0xd3, 0xe8, 0xe3, 0x0c, 0xcf, 0x48, 0x4d, 0x61, 0xfe, 0x1c, 0x1b, 0x9c, 0x2a, 0xe8, 0x19, 0xd0, 0xfb, 0x2a, 0x12, 0xfa, 0xb9, 0xbe, 0x70, 0xc4, 0xa7, 0xa1, 0x38, 0xda, 0x84, 0xe8, 0x28, 0x04, 0x35, 0xda, 0xad, 0xe5, 0xbb, 0xe6, 0x6a, 0xf0, 0x83, 0x6a, 0x15, 0x4f, 0x81, 0x7f, 0xb1, 0x7f, 0x33, 0x97, 0xe7, 0x25, 0xa3 }, - { 0xc6, 0x08, 0x97, 0xc6, 0xf8, 0x28, 0xe2, 0x1f, 0x16, 0xfb, 0xb5, 0xf1, 0x5b, 0x32, 0x3f, 0x87, 0xb6, 0xc8, 0x95, 0x5e, 0xab, 0xf1, 0xd3, 0x80, 0x61, 0xf7, 0x07, 0xf6, 0x08, 0xab, 0xdd, 0x99, 0x3f, 0xac, 0x30, 0x70, 0x63, 0x3e, 0x28, 0x6c, 0xf8, 0x33, 0x9c, 0xe2, 0x95, 0xdd, 0x35, 0x2d, 0xf4, 0xb4, 0xb4, 0x0b, 0x2f, 0x29, 0xda, 0x1d, 0xd5, 0x0b, 0x3a, 0x05, 0xd0, 0x79, 0xe6, 0xbb }, - { 0x82, 0x10, 0xcd, 0x2c, 0x2d, 0x3b, 0x13, 0x5c, 0x2c, 0xf0, 0x7f, 0xa0, 0xd1, 0x43, 0x3c, 0xd7, 0x71, 0xf3, 0x25, 0xd0, 0x75, 0xc6, 0x46, 0x9d, 0x9c, 0x7f, 0x1b, 0xa0, 0x94, 0x3c, 0xd4, 0xab, 0x09, 0x80, 0x8c, 0xab, 0xf4, 0xac, 0xb9, 0xce, 0x5b, 0xb8, 0x8b, 0x49, 0x89, 0x29, 0xb4, 0xb8, 0x47, 0xf6, 0x81, 0xad, 0x2c, 0x49, 0x0d, 0x04, 0x2d, 0xb2, 0xae, 0xc9, 0x42, 0x14, 0xb0, 0x6b }, - { 0x1d, 0x4e, 0xdf, 0xff, 0xd8, 0xfd, 0x80, 0xf7, 0xe4, 0x10, 0x78, 0x40, 0xfa, 0x3a, 0xa3, 0x1e, 0x32, 0x59, 0x84, 0x91, 0xe4, 0xaf, 0x70, 0x13, 0xc1, 0x97, 0xa6, 0x5b, 0x7f, 0x36, 0xdd, 0x3a, 0xc4, 0xb4, 0x78, 0x45, 0x61, 0x11, 0xcd, 0x43, 0x09, 0xd9, 0x24, 0x35, 0x10, 0x78, 0x2f, 0xa3, 0x1b, 0x7c, 0x4c, 0x95, 0xfa, 0x95, 0x15, 0x20, 0xd0, 0x20, 0xeb, 0x7e, 0x5c, 0x36, 0xe4, 0xef }, - { 0xaf, 0x8e, 0x6e, 0x91, 0xfa, 0xb4, 0x6c, 0xe4, 0x87, 0x3e, 0x1a, 0x50, 0xa8, 0xef, 0x44, 0x8c, 0xc2, 0x91, 0x21, 0xf7, 0xf7, 0x4d, 0xee, 0xf3, 0x4a, 0x71, 0xef, 0x89, 0xcc, 0x00, 0xd9, 0x27, 0x4b, 0xc6, 0xc2, 0x45, 0x4b, 0xbb, 0x32, 0x30, 0xd8, 0xb2, 0xec, 0x94, 0xc6, 0x2b, 0x1d, 0xec, 0x85, 0xf3, 0x59, 0x3b, 0xfa, 0x30, 0xea, 0x6f, 0x7a, 0x44, 0xd7, 0xc0, 0x94, 0x65, 0xa2, 0x53 }, - { 0x29, 0xfd, 0x38, 0x4e, 0xd4, 0x90, 0x6f, 0x2d, 0x13, 0xaa, 0x9f, 0xe7, 0xaf, 0x90, 0x59, 0x90, 0x93, 0x8b, 0xed, 0x80, 0x7f, 0x18, 0x32, 0x45, 0x4a, 0x37, 0x2a, 0xb4, 0x12, 0xee, 0xa1, 0xf5, 0x62, 0x5a, 0x1f, 0xcc, 0x9a, 0xc8, 0x34, 0x3b, 0x7c, 0x67, 0xc5, 0xab, 0xa6, 0xe0, 0xb1, 0xcc, 0x46, 0x44, 0x65, 0x49, 0x13, 0x69, 0x2c, 0x6b, 0x39, 0xeb, 0x91, 0x87, 0xce, 0xac, 0xd3, 0xec }, - { 0xa2, 0x68, 0xc7, 0x88, 0x5d, 0x98, 0x74, 0xa5, 0x1c, 0x44, 0xdf, 0xfe, 0xd8, 0xea, 0x53, 0xe9, 0x4f, 0x78, 0x45, 0x6e, 0x0b, 0x2e, 0xd9, 0x9f, 0xf5, 0xa3, 0x92, 0x47, 0x60, 0x81, 0x38, 0x26, 0xd9, 0x60, 0xa1, 0x5e, 0xdb, 0xed, 0xbb, 0x5d, 0xe5, 0x22, 0x6b, 0xa4, 0xb0, 0x74, 0xe7, 0x1b, 0x05, 0xc5, 0x5b, 0x97, 0x56, 0xbb, 0x79, 0xe5, 0x5c, 0x02, 0x75, 0x4c, 0x2c, 0x7b, 0x6c, 0x8a }, - { 0x0c, 0xf8, 0x54, 0x54, 0x88, 0xd5, 0x6a, 0x86, 0x81, 0x7c, 0xd7, 0xec, 0xb1, 0x0f, 0x71, 0x16, 0xb7, 0xea, 0x53, 0x0a, 0x45, 0xb6, 0xea, 0x49, 0x7b, 0x6c, 0x72, 0xc9, 0x97, 0xe0, 0x9e, 0x3d, 0x0d, 0xa8, 0x69, 0x8f, 0x46, 0xbb, 0x00, 0x6f, 0xc9, 0x77, 0xc2, 0xcd, 0x3d, 0x11, 0x77, 0x46, 0x3a, 0xc9, 0x05, 0x7f, 0xdd, 0x16, 0x62, 0xc8, 0x5d, 0x0c, 0x12, 0x64, 0x43, 0xc1, 0x04, 0x73 }, - { 0xb3, 0x96, 0x14, 0x26, 0x8f, 0xdd, 0x87, 0x81, 0x51, 0x5e, 0x2c, 0xfe, 0xbf, 0x89, 0xb4, 0xd5, 0x40, 0x2b, 0xab, 0x10, 0xc2, 0x26, 0xe6, 0x34, 0x4e, 0x6b, 0x9a, 0xe0, 0x00, 0xfb, 0x0d, 0x6c, 0x79, 0xcb, 0x2f, 0x3e, 0xc8, 0x0e, 0x80, 0xea, 0xeb, 0x19, 0x80, 0xd2, 0xf8, 0x69, 0x89, 0x16, 0xbd, 0x2e, 0x9f, 0x74, 0x72, 0x36, 0x65, 0x51, 0x16, 0x64, 0x9c, 0xd3, 0xca, 0x23, 0xa8, 0x37 }, - { 0x74, 0xbe, 0xf0, 0x92, 0xfc, 0x6f, 0x1e, 0x5d, 0xba, 0x36, 0x63, 0xa3, 0xfb, 0x00, 0x3b, 0x2a, 0x5b, 0xa2, 0x57, 0x49, 0x65, 0x36, 0xd9, 0x9f, 0x62, 0xb9, 0xd7, 0x3f, 0x8f, 0x9e, 0xb3, 0xce, 0x9f, 0xf3, 0xee, 0xc7, 0x09, 0xeb, 0x88, 0x36, 0x55, 0xec, 0x9e, 0xb8, 0x96, 0xb9, 0x12, 0x8f, 0x2a, 0xfc, 0x89, 0xcf, 0x7d, 0x1a, 0xb5, 0x8a, 0x72, 0xf4, 0xa3, 0xbf, 0x03, 0x4d, 0x2b, 0x4a }, - { 0x3a, 0x98, 0x8d, 0x38, 0xd7, 0x56, 0x11, 0xf3, 0xef, 0x38, 0xb8, 0x77, 0x49, 0x80, 0xb3, 0x3e, 0x57, 0x3b, 0x6c, 0x57, 0xbe, 0xe0, 0x46, 0x9b, 0xa5, 0xee, 0xd9, 0xb4, 0x4f, 0x29, 0x94, 0x5e, 0x73, 0x47, 0x96, 0x7f, 0xba, 0x2c, 0x16, 0x2e, 0x1c, 0x3b, 0xe7, 0xf3, 0x10, 0xf2, 0xf7, 0x5e, 0xe2, 0x38, 0x1e, 0x7b, 0xfd, 0x6b, 0x3f, 0x0b, 0xae, 0xa8, 0xd9, 0x5d, 0xfb, 0x1d, 0xaf, 0xb1 }, - { 0x58, 0xae, 0xdf, 0xce, 0x6f, 0x67, 0xdd, 0xc8, 0x5a, 0x28, 0xc9, 0x92, 0xf1, 0xc0, 0xbd, 0x09, 0x69, 0xf0, 0x41, 0xe6, 0x6f, 0x1e, 0xe8, 0x80, 0x20, 0xa1, 0x25, 0xcb, 0xfc, 0xfe, 0xbc, 0xd6, 0x17, 0x09, 0xc9, 0xc4, 0xeb, 0xa1, 0x92, 0xc1, 0x5e, 0x69, 0xf0, 0x20, 0xd4, 0x62, 0x48, 0x60, 0x19, 0xfa, 0x8d, 0xea, 0x0c, 0xd7, 0xa4, 0x29, 0x21, 0xa1, 0x9d, 0x2f, 0xe5, 0x46, 0xd4, 0x3d }, - { 0x93, 0x47, 0xbd, 0x29, 0x14, 0x73, 0xe6, 0xb4, 0xe3, 0x68, 0x43, 0x7b, 0x8e, 0x56, 0x1e, 0x06, 0x5f, 0x64, 0x9a, 0x6d, 0x8a, 0xda, 0x47, 0x9a, 0xd0, 0x9b, 0x19, 0x99, 0xa8, 0xf2, 0x6b, 0x91, 0xcf, 0x61, 0x20, 0xfd, 0x3b, 0xfe, 0x01, 0x4e, 0x83, 0xf2, 0x3a, 0xcf, 0xa4, 0xc0, 0xad, 0x7b, 0x37, 0x12, 0xb2, 0xc3, 0xc0, 0x73, 0x32, 0x70, 0x66, 0x31, 0x12, 0xcc, 0xd9, 0x28, 0x5c, 0xd9 }, - { 0xb3, 0x21, 0x63, 0xe7, 0xc5, 0xdb, 0xb5, 0xf5, 0x1f, 0xdc, 0x11, 0xd2, 0xea, 0xc8, 0x75, 0xef, 0xbb, 0xcb, 0x7e, 0x76, 0x99, 0x09, 0x0a, 0x7e, 0x7f, 0xf8, 0xa8, 0xd5, 0x07, 0x95, 0xaf, 0x5d, 0x74, 0xd9, 0xff, 0x98, 0x54, 0x3e, 0xf8, 0xcd, 0xf8, 0x9a, 0xc1, 0x3d, 0x04, 0x85, 0x27, 0x87, 0x56, 0xe0, 0xef, 0x00, 0xc8, 0x17, 0x74, 0x56, 0x61, 0xe1, 0xd5, 0x9f, 0xe3, 0x8e, 0x75, 0x37 }, - { 0x10, 0x85, 0xd7, 0x83, 0x07, 0xb1, 0xc4, 0xb0, 0x08, 0xc5, 0x7a, 0x2e, 0x7e, 0x5b, 0x23, 0x46, 0x58, 0xa0, 0xa8, 0x2e, 0x4f, 0xf1, 0xe4, 0xaa, 0xac, 0x72, 0xb3, 0x12, 0xfd, 0xa0, 0xfe, 0x27, 0xd2, 0x33, 0xbc, 0x5b, 0x10, 0xe9, 0xcc, 0x17, 0xfd, 0xc7, 0x69, 0x7b, 0x54, 0x0c, 0x7d, 0x95, 0xeb, 0x21, 0x5a, 0x19, 0xa1, 0xa0, 0xe2, 0x0e, 0x1a, 0xbf, 0xa1, 0x26, 0xef, 0xd5, 0x68, 0xc7 }, - { 0x4e, 0x5c, 0x73, 0x4c, 0x7d, 0xde, 0x01, 0x1d, 0x83, 0xea, 0xc2, 0xb7, 0x34, 0x7b, 0x37, 0x35, 0x94, 0xf9, 0x2d, 0x70, 0x91, 0xb9, 0xca, 0x34, 0xcb, 0x9c, 0x6f, 0x39, 0xbd, 0xf5, 0xa8, 0xd2, 0xf1, 0x34, 0x37, 0x9e, 0x16, 0xd8, 0x22, 0xf6, 0x52, 0x21, 0x70, 0xcc, 0xf2, 0xdd, 0xd5, 0x5c, 0x84, 0xb9, 0xe6, 0xc6, 0x4f, 0xc9, 0x27, 0xac, 0x4c, 0xf8, 0xdf, 0xb2, 0xa1, 0x77, 0x01, 0xf2 }, - { 0x69, 0x5d, 0x83, 0xbd, 0x99, 0x0a, 0x11, 0x17, 0xb3, 0xd0, 0xce, 0x06, 0xcc, 0x88, 0x80, 0x27, 0xd1, 0x2a, 0x05, 0x4c, 0x26, 0x77, 0xfd, 0x82, 0xf0, 0xd4, 0xfb, 0xfc, 0x93, 0x57, 0x55, 0x23, 0xe7, 0x99, 0x1a, 0x5e, 0x35, 0xa3, 0x75, 0x2e, 0x9b, 0x70, 0xce, 0x62, 0x99, 0x2e, 0x26, 0x8a, 0x87, 0x77, 0x44, 0xcd, 0xd4, 0x35, 0xf5, 0xf1, 0x30, 0x86, 0x9c, 0x9a, 0x20, 0x74, 0xb3, 0x38 }, - { 0xa6, 0x21, 0x37, 0x43, 0x56, 0x8e, 0x3b, 0x31, 0x58, 0xb9, 0x18, 0x43, 0x01, 0xf3, 0x69, 0x08, 0x47, 0x55, 0x4c, 0x68, 0x45, 0x7c, 0xb4, 0x0f, 0xc9, 0xa4, 0xb8, 0xcf, 0xd8, 0xd4, 0xa1, 0x18, 0xc3, 0x01, 0xa0, 0x77, 0x37, 0xae, 0xda, 0x0f, 0x92, 0x9c, 0x68, 0x91, 0x3c, 0x5f, 0x51, 0xc8, 0x03, 0x94, 0xf5, 0x3b, 0xff, 0x1c, 0x3e, 0x83, 0xb2, 0xe4, 0x0c, 0xa9, 0x7e, 0xba, 0x9e, 0x15 }, - { 0xd4, 0x44, 0xbf, 0xa2, 0x36, 0x2a, 0x96, 0xdf, 0x21, 0x3d, 0x07, 0x0e, 0x33, 0xfa, 0x84, 0x1f, 0x51, 0x33, 0x4e, 0x4e, 0x76, 0x86, 0x6b, 0x81, 0x39, 0xe8, 0xaf, 0x3b, 0xb3, 0x39, 0x8b, 0xe2, 0xdf, 0xad, 0xdc, 0xbc, 0x56, 0xb9, 0x14, 0x6d, 0xe9, 0xf6, 0x81, 0x18, 0xdc, 0x58, 0x29, 0xe7, 0x4b, 0x0c, 0x28, 0xd7, 0x71, 0x19, 0x07, 0xb1, 0x21, 0xf9, 0x16, 0x1c, 0xb9, 0x2b, 0x69, 0xa9 }, - { 0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97, 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5, 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b, 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d, 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d, 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61 }, - }; - unsigned char inp[1000], out[1000]; - unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }; - unsigned long ilen, klen = sizeof(key), mlen = 64; - blake2bmac_state st; - - for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; - - for (ilen = 0; ilen < 256; ilen++) { - const unsigned char *mac = tests[ilen]; - unsigned long olen = mlen; - /* process piece by piece */ - if (ilen > 15) { - blake2bmac_init(&st, olen, key, klen); - blake2bmac_process(&st, (unsigned char*)inp, 5); - blake2bmac_process(&st, (unsigned char*)inp + 5, 4); - blake2bmac_process(&st, (unsigned char*)inp + 9, 3); - blake2bmac_process(&st, (unsigned char*)inp + 12, 2); - blake2bmac_process(&st, (unsigned char*)inp + 14, 1); - blake2bmac_process(&st, (unsigned char*)inp + 15, ilen - 15); - blake2bmac_done(&st, out, &olen); - if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; - } - /* process in one go */ - blake2bmac_init(&st, olen, key, klen); - blake2bmac_process(&st, (unsigned char*)inp, ilen); - blake2bmac_done(&st, out, &olen); - if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac.c deleted file mode 100644 index f42c7ae..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2SMAC - -/** - Initialize an BLAKE2S MAC context. - @param st The BLAKE2S MAC state - @param outlen The size of the MAC output (octets) - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - return blake2s_init(st, outlen, key, keylen); -} - -/** - Process data through BLAKE2S MAC - @param st The BLAKE2S MAC state - @param in The data to send through HMAC - @param inlen The length of the data to HMAC (octets) - @return CRYPT_OK if successful -*/ -int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen) -{ - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - return blake2s_process(st, in, inlen); -} - -/** - Terminate a BLAKE2S MAC session - @param st The BLAKE2S MAC state - @param mac [out] The destination of the BLAKE2S MAC authentication tag - @param maclen [in/out] The max size and resulting size of the BLAKE2S MAC authentication tag - @return CRYPT_OK if successful -*/ -int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - LTC_ARGCHK(*maclen >= st->blake2s.outlen); - - *maclen = st->blake2s.outlen; - return blake2s_done(st, mac); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_file.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_file.c deleted file mode 100644 index bcfbe06..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_file.c +++ /dev/null @@ -1,78 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2SMAC - -/** - BLAKE2S MAC a file - @param fname The name of the file you wish to BLAKE2S MAC - @param key The secret key - @param keylen The length of the secret key - @param mac [out] The BLAKE2S MAC authentication tag - @param maclen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(fname); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(mac); - LTC_UNUSED_PARAM(maclen); - return CRYPT_NOP; -#else - blake2smac_state st; - FILE *in; - unsigned char *buf; - size_t x; - int err; - - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = blake2smac_done(&st, mac, maclen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2smac_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory.c deleted file mode 100644 index 755267b..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2SMAC - -/** - BLAKE2S MAC a block of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data to BLAKE2S MAC - @param inlen The length of the data to BLAKE2S MAC (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @return CRYPT_OK if successful -*/ -int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) -{ - blake2smac_state st; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - err = blake2smac_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2smac_state)); -#endif - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory_multi.c deleted file mode 100644 index a3d62c3..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_memory_multi.c +++ /dev/null @@ -1,51 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2SMAC - -/** - BLAKE2S MAC multiple blocks of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @param in The data to BLAKE2S MAC - @param inlen The length of the data to BLAKE2S MAC (octets) - @param ... tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) -{ - blake2smac_state st; - int err; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - va_start(args, inlen); - curptr = in; - curlen = inlen; - if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - for (;;) { - if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) break; - curlen = va_arg(args, unsigned long); - } - err = blake2smac_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(blake2smac_state)); -#endif - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_test.c b/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_test.c deleted file mode 100644 index acfb030..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/blake2/blake2smac_test.c +++ /dev/null @@ -1,304 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BLAKE2SMAC - -int blake2smac_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const unsigned char tests[256][32] = { - /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */ - { 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49 }, - { 0x40, 0xd1, 0x5f, 0xee, 0x7c, 0x32, 0x88, 0x30, 0x16, 0x6a, 0xc3, 0xf9, 0x18, 0x65, 0x0f, 0x80, 0x7e, 0x7e, 0x01, 0xe1, 0x77, 0x25, 0x8c, 0xdc, 0x0a, 0x39, 0xb1, 0x1f, 0x59, 0x80, 0x66, 0xf1 }, - { 0x6b, 0xb7, 0x13, 0x00, 0x64, 0x4c, 0xd3, 0x99, 0x1b, 0x26, 0xcc, 0xd4, 0xd2, 0x74, 0xac, 0xd1, 0xad, 0xea, 0xb8, 0xb1, 0xd7, 0x91, 0x45, 0x46, 0xc1, 0x19, 0x8b, 0xbe, 0x9f, 0xc9, 0xd8, 0x03 }, - { 0x1d, 0x22, 0x0d, 0xbe, 0x2e, 0xe1, 0x34, 0x66, 0x1f, 0xdf, 0x6d, 0x9e, 0x74, 0xb4, 0x17, 0x04, 0x71, 0x05, 0x56, 0xf2, 0xf6, 0xe5, 0xa0, 0x91, 0xb2, 0x27, 0x69, 0x74, 0x45, 0xdb, 0xea, 0x6b }, - { 0xf6, 0xc3, 0xfb, 0xad, 0xb4, 0xcc, 0x68, 0x7a, 0x00, 0x64, 0xa5, 0xbe, 0x6e, 0x79, 0x1b, 0xec, 0x63, 0xb8, 0x68, 0xad, 0x62, 0xfb, 0xa6, 0x1b, 0x37, 0x57, 0xef, 0x9c, 0xa5, 0x2e, 0x05, 0xb2 }, - { 0x49, 0xc1, 0xf2, 0x11, 0x88, 0xdf, 0xd7, 0x69, 0xae, 0xa0, 0xe9, 0x11, 0xdd, 0x6b, 0x41, 0xf1, 0x4d, 0xab, 0x10, 0x9d, 0x2b, 0x85, 0x97, 0x7a, 0xa3, 0x08, 0x8b, 0x5c, 0x70, 0x7e, 0x85, 0x98 }, - { 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f, 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01, 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43 }, - { 0xe6, 0xc8, 0x12, 0x56, 0x37, 0x43, 0x8d, 0x09, 0x05, 0xb7, 0x49, 0xf4, 0x65, 0x60, 0xac, 0x89, 0xfd, 0x47, 0x1c, 0xf8, 0x69, 0x2e, 0x28, 0xfa, 0xb9, 0x82, 0xf7, 0x3f, 0x01, 0x9b, 0x83, 0xa9 }, - { 0x19, 0xfc, 0x8c, 0xa6, 0x97, 0x9d, 0x60, 0xe6, 0xed, 0xd3, 0xb4, 0x54, 0x1e, 0x2f, 0x96, 0x7c, 0xed, 0x74, 0x0d, 0xf6, 0xec, 0x1e, 0xae, 0xbb, 0xfe, 0x81, 0x38, 0x32, 0xe9, 0x6b, 0x29, 0x74 }, - { 0xa6, 0xad, 0x77, 0x7c, 0xe8, 0x81, 0xb5, 0x2b, 0xb5, 0xa4, 0x42, 0x1a, 0xb6, 0xcd, 0xd2, 0xdf, 0xba, 0x13, 0xe9, 0x63, 0x65, 0x2d, 0x4d, 0x6d, 0x12, 0x2a, 0xee, 0x46, 0x54, 0x8c, 0x14, 0xa7 }, - { 0xf5, 0xc4, 0xb2, 0xba, 0x1a, 0x00, 0x78, 0x1b, 0x13, 0xab, 0xa0, 0x42, 0x52, 0x42, 0xc6, 0x9c, 0xb1, 0x55, 0x2f, 0x3f, 0x71, 0xa9, 0xa3, 0xbb, 0x22, 0xb4, 0xa6, 0xb4, 0x27, 0x7b, 0x46, 0xdd }, - { 0xe3, 0x3c, 0x4c, 0x9b, 0xd0, 0xcc, 0x7e, 0x45, 0xc8, 0x0e, 0x65, 0xc7, 0x7f, 0xa5, 0x99, 0x7f, 0xec, 0x70, 0x02, 0x73, 0x85, 0x41, 0x50, 0x9e, 0x68, 0xa9, 0x42, 0x38, 0x91, 0xe8, 0x22, 0xa3 }, - { 0xfb, 0xa1, 0x61, 0x69, 0xb2, 0xc3, 0xee, 0x10, 0x5b, 0xe6, 0xe1, 0xe6, 0x50, 0xe5, 0xcb, 0xf4, 0x07, 0x46, 0xb6, 0x75, 0x3d, 0x03, 0x6a, 0xb5, 0x51, 0x79, 0x01, 0x4a, 0xd7, 0xef, 0x66, 0x51 }, - { 0xf5, 0xc4, 0xbe, 0xc6, 0xd6, 0x2f, 0xc6, 0x08, 0xbf, 0x41, 0xcc, 0x11, 0x5f, 0x16, 0xd6, 0x1c, 0x7e, 0xfd, 0x3f, 0xf6, 0xc6, 0x56, 0x92, 0xbb, 0xe0, 0xaf, 0xff, 0xb1, 0xfe, 0xde, 0x74, 0x75 }, - { 0xa4, 0x86, 0x2e, 0x76, 0xdb, 0x84, 0x7f, 0x05, 0xba, 0x17, 0xed, 0xe5, 0xda, 0x4e, 0x7f, 0x91, 0xb5, 0x92, 0x5c, 0xf1, 0xad, 0x4b, 0xa1, 0x27, 0x32, 0xc3, 0x99, 0x57, 0x42, 0xa5, 0xcd, 0x6e }, - { 0x65, 0xf4, 0xb8, 0x60, 0xcd, 0x15, 0xb3, 0x8e, 0xf8, 0x14, 0xa1, 0xa8, 0x04, 0x31, 0x4a, 0x55, 0xbe, 0x95, 0x3c, 0xaa, 0x65, 0xfd, 0x75, 0x8a, 0xd9, 0x89, 0xff, 0x34, 0xa4, 0x1c, 0x1e, 0xea }, - { 0x19, 0xba, 0x23, 0x4f, 0x0a, 0x4f, 0x38, 0x63, 0x7d, 0x18, 0x39, 0xf9, 0xd9, 0xf7, 0x6a, 0xd9, 0x1c, 0x85, 0x22, 0x30, 0x71, 0x43, 0xc9, 0x7d, 0x5f, 0x93, 0xf6, 0x92, 0x74, 0xce, 0xc9, 0xa7 }, - { 0x1a, 0x67, 0x18, 0x6c, 0xa4, 0xa5, 0xcb, 0x8e, 0x65, 0xfc, 0xa0, 0xe2, 0xec, 0xbc, 0x5d, 0xdc, 0x14, 0xae, 0x38, 0x1b, 0xb8, 0xbf, 0xfe, 0xb9, 0xe0, 0xa1, 0x03, 0x44, 0x9e, 0x3e, 0xf0, 0x3c }, - { 0xaf, 0xbe, 0xa3, 0x17, 0xb5, 0xa2, 0xe8, 0x9c, 0x0b, 0xd9, 0x0c, 0xcf, 0x5d, 0x7f, 0xd0, 0xed, 0x57, 0xfe, 0x58, 0x5e, 0x4b, 0xe3, 0x27, 0x1b, 0x0a, 0x6b, 0xf0, 0xf5, 0x78, 0x6b, 0x0f, 0x26 }, - { 0xf1, 0xb0, 0x15, 0x58, 0xce, 0x54, 0x12, 0x62, 0xf5, 0xec, 0x34, 0x29, 0x9d, 0x6f, 0xb4, 0x09, 0x00, 0x09, 0xe3, 0x43, 0x4b, 0xe2, 0xf4, 0x91, 0x05, 0xcf, 0x46, 0xaf, 0x4d, 0x2d, 0x41, 0x24 }, - { 0x13, 0xa0, 0xa0, 0xc8, 0x63, 0x35, 0x63, 0x5e, 0xaa, 0x74, 0xca, 0x2d, 0x5d, 0x48, 0x8c, 0x79, 0x7b, 0xbb, 0x4f, 0x47, 0xdc, 0x07, 0x10, 0x50, 0x15, 0xed, 0x6a, 0x1f, 0x33, 0x09, 0xef, 0xce }, - { 0x15, 0x80, 0xaf, 0xee, 0xbe, 0xbb, 0x34, 0x6f, 0x94, 0xd5, 0x9f, 0xe6, 0x2d, 0xa0, 0xb7, 0x92, 0x37, 0xea, 0xd7, 0xb1, 0x49, 0x1f, 0x56, 0x67, 0xa9, 0x0e, 0x45, 0xed, 0xf6, 0xca, 0x8b, 0x03 }, - { 0x20, 0xbe, 0x1a, 0x87, 0x5b, 0x38, 0xc5, 0x73, 0xdd, 0x7f, 0xaa, 0xa0, 0xde, 0x48, 0x9d, 0x65, 0x5c, 0x11, 0xef, 0xb6, 0xa5, 0x52, 0x69, 0x8e, 0x07, 0xa2, 0xd3, 0x31, 0xb5, 0xf6, 0x55, 0xc3 }, - { 0xbe, 0x1f, 0xe3, 0xc4, 0xc0, 0x40, 0x18, 0xc5, 0x4c, 0x4a, 0x0f, 0x6b, 0x9a, 0x2e, 0xd3, 0xc5, 0x3a, 0xbe, 0x3a, 0x9f, 0x76, 0xb4, 0xd2, 0x6d, 0xe5, 0x6f, 0xc9, 0xae, 0x95, 0x05, 0x9a, 0x99 }, - { 0xe3, 0xe3, 0xac, 0xe5, 0x37, 0xeb, 0x3e, 0xdd, 0x84, 0x63, 0xd9, 0xad, 0x35, 0x82, 0xe1, 0x3c, 0xf8, 0x65, 0x33, 0xff, 0xde, 0x43, 0xd6, 0x68, 0xdd, 0x2e, 0x93, 0xbb, 0xdb, 0xd7, 0x19, 0x5a }, - { 0x11, 0x0c, 0x50, 0xc0, 0xbf, 0x2c, 0x6e, 0x7a, 0xeb, 0x7e, 0x43, 0x5d, 0x92, 0xd1, 0x32, 0xab, 0x66, 0x55, 0x16, 0x8e, 0x78, 0xa2, 0xde, 0xcd, 0xec, 0x33, 0x30, 0x77, 0x76, 0x84, 0xd9, 0xc1 }, - { 0xe9, 0xba, 0x8f, 0x50, 0x5c, 0x9c, 0x80, 0xc0, 0x86, 0x66, 0xa7, 0x01, 0xf3, 0x36, 0x7e, 0x6c, 0xc6, 0x65, 0xf3, 0x4b, 0x22, 0xe7, 0x3c, 0x3c, 0x04, 0x17, 0xeb, 0x1c, 0x22, 0x06, 0x08, 0x2f }, - { 0x26, 0xcd, 0x66, 0xfc, 0xa0, 0x23, 0x79, 0xc7, 0x6d, 0xf1, 0x23, 0x17, 0x05, 0x2b, 0xca, 0xfd, 0x6c, 0xd8, 0xc3, 0xa7, 0xb8, 0x90, 0xd8, 0x05, 0xf3, 0x6c, 0x49, 0x98, 0x97, 0x82, 0x43, 0x3a }, - { 0x21, 0x3f, 0x35, 0x96, 0xd6, 0xe3, 0xa5, 0xd0, 0xe9, 0x93, 0x2c, 0xd2, 0x15, 0x91, 0x46, 0x01, 0x5e, 0x2a, 0xbc, 0x94, 0x9f, 0x47, 0x29, 0xee, 0x26, 0x32, 0xfe, 0x1e, 0xdb, 0x78, 0xd3, 0x37 }, - { 0x10, 0x15, 0xd7, 0x01, 0x08, 0xe0, 0x3b, 0xe1, 0xc7, 0x02, 0xfe, 0x97, 0x25, 0x36, 0x07, 0xd1, 0x4a, 0xee, 0x59, 0x1f, 0x24, 0x13, 0xea, 0x67, 0x87, 0x42, 0x7b, 0x64, 0x59, 0xff, 0x21, 0x9a }, - { 0x3c, 0xa9, 0x89, 0xde, 0x10, 0xcf, 0xe6, 0x09, 0x90, 0x94, 0x72, 0xc8, 0xd3, 0x56, 0x10, 0x80, 0x5b, 0x2f, 0x97, 0x77, 0x34, 0xcf, 0x65, 0x2c, 0xc6, 0x4b, 0x3b, 0xfc, 0x88, 0x2d, 0x5d, 0x89 }, - { 0xb6, 0x15, 0x6f, 0x72, 0xd3, 0x80, 0xee, 0x9e, 0xa6, 0xac, 0xd1, 0x90, 0x46, 0x4f, 0x23, 0x07, 0xa5, 0xc1, 0x79, 0xef, 0x01, 0xfd, 0x71, 0xf9, 0x9f, 0x2d, 0x0f, 0x7a, 0x57, 0x36, 0x0a, 0xea }, - { 0xc0, 0x3b, 0xc6, 0x42, 0xb2, 0x09, 0x59, 0xcb, 0xe1, 0x33, 0xa0, 0x30, 0x3e, 0x0c, 0x1a, 0xbf, 0xf3, 0xe3, 0x1e, 0xc8, 0xe1, 0xa3, 0x28, 0xec, 0x85, 0x65, 0xc3, 0x6d, 0xec, 0xff, 0x52, 0x65 }, - { 0x2c, 0x3e, 0x08, 0x17, 0x6f, 0x76, 0x0c, 0x62, 0x64, 0xc3, 0xa2, 0xcd, 0x66, 0xfe, 0xc6, 0xc3, 0xd7, 0x8d, 0xe4, 0x3f, 0xc1, 0x92, 0x45, 0x7b, 0x2a, 0x4a, 0x66, 0x0a, 0x1e, 0x0e, 0xb2, 0x2b }, - { 0xf7, 0x38, 0xc0, 0x2f, 0x3c, 0x1b, 0x19, 0x0c, 0x51, 0x2b, 0x1a, 0x32, 0xde, 0xab, 0xf3, 0x53, 0x72, 0x8e, 0x0e, 0x9a, 0xb0, 0x34, 0x49, 0x0e, 0x3c, 0x34, 0x09, 0x94, 0x6a, 0x97, 0xae, 0xec }, - { 0x8b, 0x18, 0x80, 0xdf, 0x30, 0x1c, 0xc9, 0x63, 0x41, 0x88, 0x11, 0x08, 0x89, 0x64, 0x83, 0x92, 0x87, 0xff, 0x7f, 0xe3, 0x1c, 0x49, 0xea, 0x6e, 0xbd, 0x9e, 0x48, 0xbd, 0xee, 0xe4, 0x97, 0xc5 }, - { 0x1e, 0x75, 0xcb, 0x21, 0xc6, 0x09, 0x89, 0x02, 0x03, 0x75, 0xf1, 0xa7, 0xa2, 0x42, 0x83, 0x9f, 0x0b, 0x0b, 0x68, 0x97, 0x3a, 0x4c, 0x2a, 0x05, 0xcf, 0x75, 0x55, 0xed, 0x5a, 0xae, 0xc4, 0xc1 }, - { 0x62, 0xbf, 0x8a, 0x9c, 0x32, 0xa5, 0xbc, 0xcf, 0x29, 0x0b, 0x6c, 0x47, 0x4d, 0x75, 0xb2, 0xa2, 0xa4, 0x09, 0x3f, 0x1a, 0x9e, 0x27, 0x13, 0x94, 0x33, 0xa8, 0xf2, 0xb3, 0xbc, 0xe7, 0xb8, 0xd7 }, - { 0x16, 0x6c, 0x83, 0x50, 0xd3, 0x17, 0x3b, 0x5e, 0x70, 0x2b, 0x78, 0x3d, 0xfd, 0x33, 0xc6, 0x6e, 0xe0, 0x43, 0x27, 0x42, 0xe9, 0xb9, 0x2b, 0x99, 0x7f, 0xd2, 0x3c, 0x60, 0xdc, 0x67, 0x56, 0xca }, - { 0x04, 0x4a, 0x14, 0xd8, 0x22, 0xa9, 0x0c, 0xac, 0xf2, 0xf5, 0xa1, 0x01, 0x42, 0x8a, 0xdc, 0x8f, 0x41, 0x09, 0x38, 0x6c, 0xcb, 0x15, 0x8b, 0xf9, 0x05, 0xc8, 0x61, 0x8b, 0x8e, 0xe2, 0x4e, 0xc3 }, - { 0x38, 0x7d, 0x39, 0x7e, 0xa4, 0x3a, 0x99, 0x4b, 0xe8, 0x4d, 0x2d, 0x54, 0x4a, 0xfb, 0xe4, 0x81, 0xa2, 0x00, 0x0f, 0x55, 0x25, 0x26, 0x96, 0xbb, 0xa2, 0xc5, 0x0c, 0x8e, 0xbd, 0x10, 0x13, 0x47 }, - { 0x56, 0xf8, 0xcc, 0xf1, 0xf8, 0x64, 0x09, 0xb4, 0x6c, 0xe3, 0x61, 0x66, 0xae, 0x91, 0x65, 0x13, 0x84, 0x41, 0x57, 0x75, 0x89, 0xdb, 0x08, 0xcb, 0xc5, 0xf6, 0x6c, 0xa2, 0x97, 0x43, 0xb9, 0xfd }, - { 0x97, 0x06, 0xc0, 0x92, 0xb0, 0x4d, 0x91, 0xf5, 0x3d, 0xff, 0x91, 0xfa, 0x37, 0xb7, 0x49, 0x3d, 0x28, 0xb5, 0x76, 0xb5, 0xd7, 0x10, 0x46, 0x9d, 0xf7, 0x94, 0x01, 0x66, 0x22, 0x36, 0xfc, 0x03 }, - { 0x87, 0x79, 0x68, 0x68, 0x6c, 0x06, 0x8c, 0xe2, 0xf7, 0xe2, 0xad, 0xcf, 0xf6, 0x8b, 0xf8, 0x74, 0x8e, 0xdf, 0x3c, 0xf8, 0x62, 0xcf, 0xb4, 0xd3, 0x94, 0x7a, 0x31, 0x06, 0x95, 0x80, 0x54, 0xe3 }, - { 0x88, 0x17, 0xe5, 0x71, 0x98, 0x79, 0xac, 0xf7, 0x02, 0x47, 0x87, 0xec, 0xcd, 0xb2, 0x71, 0x03, 0x55, 0x66, 0xcf, 0xa3, 0x33, 0xe0, 0x49, 0x40, 0x7c, 0x01, 0x78, 0xcc, 0xc5, 0x7a, 0x5b, 0x9f }, - { 0x89, 0x38, 0x24, 0x9e, 0x4b, 0x50, 0xca, 0xda, 0xcc, 0xdf, 0x5b, 0x18, 0x62, 0x13, 0x26, 0xcb, 0xb1, 0x52, 0x53, 0xe3, 0x3a, 0x20, 0xf5, 0x63, 0x6e, 0x99, 0x5d, 0x72, 0x47, 0x8d, 0xe4, 0x72 }, - { 0xf1, 0x64, 0xab, 0xba, 0x49, 0x63, 0xa4, 0x4d, 0x10, 0x72, 0x57, 0xe3, 0x23, 0x2d, 0x90, 0xac, 0xa5, 0xe6, 0x6a, 0x14, 0x08, 0x24, 0x8c, 0x51, 0x74, 0x1e, 0x99, 0x1d, 0xb5, 0x22, 0x77, 0x56 }, - { 0xd0, 0x55, 0x63, 0xe2, 0xb1, 0xcb, 0xa0, 0xc4, 0xa2, 0xa1, 0xe8, 0xbd, 0xe3, 0xa1, 0xa0, 0xd9, 0xf5, 0xb4, 0x0c, 0x85, 0xa0, 0x70, 0xd6, 0xf5, 0xfb, 0x21, 0x06, 0x6e, 0xad, 0x5d, 0x06, 0x01 }, - { 0x03, 0xfb, 0xb1, 0x63, 0x84, 0xf0, 0xa3, 0x86, 0x6f, 0x4c, 0x31, 0x17, 0x87, 0x76, 0x66, 0xef, 0xbf, 0x12, 0x45, 0x97, 0x56, 0x4b, 0x29, 0x3d, 0x4a, 0xab, 0x0d, 0x26, 0x9f, 0xab, 0xdd, 0xfa }, - { 0x5f, 0xa8, 0x48, 0x6a, 0xc0, 0xe5, 0x29, 0x64, 0xd1, 0x88, 0x1b, 0xbe, 0x33, 0x8e, 0xb5, 0x4b, 0xe2, 0xf7, 0x19, 0x54, 0x92, 0x24, 0x89, 0x20, 0x57, 0xb4, 0xda, 0x04, 0xba, 0x8b, 0x34, 0x75 }, - { 0xcd, 0xfa, 0xbc, 0xee, 0x46, 0x91, 0x11, 0x11, 0x23, 0x6a, 0x31, 0x70, 0x8b, 0x25, 0x39, 0xd7, 0x1f, 0xc2, 0x11, 0xd9, 0xb0, 0x9c, 0x0d, 0x85, 0x30, 0xa1, 0x1e, 0x1d, 0xbf, 0x6e, 0xed, 0x01 }, - { 0x4f, 0x82, 0xde, 0x03, 0xb9, 0x50, 0x47, 0x93, 0xb8, 0x2a, 0x07, 0xa0, 0xbd, 0xcd, 0xff, 0x31, 0x4d, 0x75, 0x9e, 0x7b, 0x62, 0xd2, 0x6b, 0x78, 0x49, 0x46, 0xb0, 0xd3, 0x6f, 0x91, 0x6f, 0x52 }, - { 0x25, 0x9e, 0xc7, 0xf1, 0x73, 0xbc, 0xc7, 0x6a, 0x09, 0x94, 0xc9, 0x67, 0xb4, 0xf5, 0xf0, 0x24, 0xc5, 0x60, 0x57, 0xfb, 0x79, 0xc9, 0x65, 0xc4, 0xfa, 0xe4, 0x18, 0x75, 0xf0, 0x6a, 0x0e, 0x4c }, - { 0x19, 0x3c, 0xc8, 0xe7, 0xc3, 0xe0, 0x8b, 0xb3, 0x0f, 0x54, 0x37, 0xaa, 0x27, 0xad, 0xe1, 0xf1, 0x42, 0x36, 0x9b, 0x24, 0x6a, 0x67, 0x5b, 0x23, 0x83, 0xe6, 0xda, 0x9b, 0x49, 0xa9, 0x80, 0x9e }, - { 0x5c, 0x10, 0x89, 0x6f, 0x0e, 0x28, 0x56, 0xb2, 0xa2, 0xee, 0xe0, 0xfe, 0x4a, 0x2c, 0x16, 0x33, 0x56, 0x5d, 0x18, 0xf0, 0xe9, 0x3e, 0x1f, 0xab, 0x26, 0xc3, 0x73, 0xe8, 0xf8, 0x29, 0x65, 0x4d }, - { 0xf1, 0x60, 0x12, 0xd9, 0x3f, 0x28, 0x85, 0x1a, 0x1e, 0xb9, 0x89, 0xf5, 0xd0, 0xb4, 0x3f, 0x3f, 0x39, 0xca, 0x73, 0xc9, 0xa6, 0x2d, 0x51, 0x81, 0xbf, 0xf2, 0x37, 0x53, 0x6b, 0xd3, 0x48, 0xc3 }, - { 0x29, 0x66, 0xb3, 0xcf, 0xae, 0x1e, 0x44, 0xea, 0x99, 0x6d, 0xc5, 0xd6, 0x86, 0xcf, 0x25, 0xfa, 0x05, 0x3f, 0xb6, 0xf6, 0x72, 0x01, 0xb9, 0xe4, 0x6e, 0xad, 0xe8, 0x5d, 0x0a, 0xd6, 0xb8, 0x06 }, - { 0xdd, 0xb8, 0x78, 0x24, 0x85, 0xe9, 0x00, 0xbc, 0x60, 0xbc, 0xf4, 0xc3, 0x3a, 0x6f, 0xd5, 0x85, 0x68, 0x0c, 0xc6, 0x83, 0xd5, 0x16, 0xef, 0xa0, 0x3e, 0xb9, 0x98, 0x5f, 0xad, 0x87, 0x15, 0xfb }, - { 0x4c, 0x4d, 0x6e, 0x71, 0xae, 0xa0, 0x57, 0x86, 0x41, 0x31, 0x48, 0xfc, 0x7a, 0x78, 0x6b, 0x0e, 0xca, 0xf5, 0x82, 0xcf, 0xf1, 0x20, 0x9f, 0x5a, 0x80, 0x9f, 0xba, 0x85, 0x04, 0xce, 0x66, 0x2c }, - { 0xfb, 0x4c, 0x5e, 0x86, 0xd7, 0xb2, 0x22, 0x9b, 0x99, 0xb8, 0xba, 0x6d, 0x94, 0xc2, 0x47, 0xef, 0x96, 0x4a, 0xa3, 0xa2, 0xba, 0xe8, 0xed, 0xc7, 0x75, 0x69, 0xf2, 0x8d, 0xbb, 0xff, 0x2d, 0x4e }, - { 0xe9, 0x4f, 0x52, 0x6d, 0xe9, 0x01, 0x96, 0x33, 0xec, 0xd5, 0x4a, 0xc6, 0x12, 0x0f, 0x23, 0x95, 0x8d, 0x77, 0x18, 0xf1, 0xe7, 0x71, 0x7b, 0xf3, 0x29, 0x21, 0x1a, 0x4f, 0xae, 0xed, 0x4e, 0x6d }, - { 0xcb, 0xd6, 0x66, 0x0a, 0x10, 0xdb, 0x3f, 0x23, 0xf7, 0xa0, 0x3d, 0x4b, 0x9d, 0x40, 0x44, 0xc7, 0x93, 0x2b, 0x28, 0x01, 0xac, 0x89, 0xd6, 0x0b, 0xc9, 0xeb, 0x92, 0xd6, 0x5a, 0x46, 0xc2, 0xa0 }, - { 0x88, 0x18, 0xbb, 0xd3, 0xdb, 0x4d, 0xc1, 0x23, 0xb2, 0x5c, 0xbb, 0xa5, 0xf5, 0x4c, 0x2b, 0xc4, 0xb3, 0xfc, 0xf9, 0xbf, 0x7d, 0x7a, 0x77, 0x09, 0xf4, 0xae, 0x58, 0x8b, 0x26, 0x7c, 0x4e, 0xce }, - { 0xc6, 0x53, 0x82, 0x51, 0x3f, 0x07, 0x46, 0x0d, 0xa3, 0x98, 0x33, 0xcb, 0x66, 0x6c, 0x5e, 0xd8, 0x2e, 0x61, 0xb9, 0xe9, 0x98, 0xf4, 0xb0, 0xc4, 0x28, 0x7c, 0xee, 0x56, 0xc3, 0xcc, 0x9b, 0xcd }, - { 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4 }, - { 0x21, 0xfe, 0x0c, 0xeb, 0x00, 0x52, 0xbe, 0x7f, 0xb0, 0xf0, 0x04, 0x18, 0x7c, 0xac, 0xd7, 0xde, 0x67, 0xfa, 0x6e, 0xb0, 0x93, 0x8d, 0x92, 0x76, 0x77, 0xf2, 0x39, 0x8c, 0x13, 0x23, 0x17, 0xa8 }, - { 0x2e, 0xf7, 0x3f, 0x3c, 0x26, 0xf1, 0x2d, 0x93, 0x88, 0x9f, 0x3c, 0x78, 0xb6, 0xa6, 0x6c, 0x1d, 0x52, 0xb6, 0x49, 0xdc, 0x9e, 0x85, 0x6e, 0x2c, 0x17, 0x2e, 0xa7, 0xc5, 0x8a, 0xc2, 0xb5, 0xe3 }, - { 0x38, 0x8a, 0x3c, 0xd5, 0x6d, 0x73, 0x86, 0x7a, 0xbb, 0x5f, 0x84, 0x01, 0x49, 0x2b, 0x6e, 0x26, 0x81, 0xeb, 0x69, 0x85, 0x1e, 0x76, 0x7f, 0xd8, 0x42, 0x10, 0xa5, 0x60, 0x76, 0xfb, 0x3d, 0xd3 }, - { 0xaf, 0x53, 0x3e, 0x02, 0x2f, 0xc9, 0x43, 0x9e, 0x4e, 0x3c, 0xb8, 0x38, 0xec, 0xd1, 0x86, 0x92, 0x23, 0x2a, 0xdf, 0x6f, 0xe9, 0x83, 0x95, 0x26, 0xd3, 0xc3, 0xdd, 0x1b, 0x71, 0x91, 0x0b, 0x1a }, - { 0x75, 0x1c, 0x09, 0xd4, 0x1a, 0x93, 0x43, 0x88, 0x2a, 0x81, 0xcd, 0x13, 0xee, 0x40, 0x81, 0x8d, 0x12, 0xeb, 0x44, 0xc6, 0xc7, 0xf4, 0x0d, 0xf1, 0x6e, 0x4a, 0xea, 0x8f, 0xab, 0x91, 0x97, 0x2a }, - { 0x5b, 0x73, 0xdd, 0xb6, 0x8d, 0x9d, 0x2b, 0x0a, 0xa2, 0x65, 0xa0, 0x79, 0x88, 0xd6, 0xb8, 0x8a, 0xe9, 0xaa, 0xc5, 0x82, 0xaf, 0x83, 0x03, 0x2f, 0x8a, 0x9b, 0x21, 0xa2, 0xe1, 0xb7, 0xbf, 0x18 }, - { 0x3d, 0xa2, 0x91, 0x26, 0xc7, 0xc5, 0xd7, 0xf4, 0x3e, 0x64, 0x24, 0x2a, 0x79, 0xfe, 0xaa, 0x4e, 0xf3, 0x45, 0x9c, 0xde, 0xcc, 0xc8, 0x98, 0xed, 0x59, 0xa9, 0x7f, 0x6e, 0xc9, 0x3b, 0x9d, 0xab }, - { 0x56, 0x6d, 0xc9, 0x20, 0x29, 0x3d, 0xa5, 0xcb, 0x4f, 0xe0, 0xaa, 0x8a, 0xbd, 0xa8, 0xbb, 0xf5, 0x6f, 0x55, 0x23, 0x13, 0xbf, 0xf1, 0x90, 0x46, 0x64, 0x1e, 0x36, 0x15, 0xc1, 0xe3, 0xed, 0x3f }, - { 0x41, 0x15, 0xbe, 0xa0, 0x2f, 0x73, 0xf9, 0x7f, 0x62, 0x9e, 0x5c, 0x55, 0x90, 0x72, 0x0c, 0x01, 0xe7, 0xe4, 0x49, 0xae, 0x2a, 0x66, 0x97, 0xd4, 0xd2, 0x78, 0x33, 0x21, 0x30, 0x36, 0x92, 0xf9 }, - { 0x4c, 0xe0, 0x8f, 0x47, 0x62, 0x46, 0x8a, 0x76, 0x70, 0x01, 0x21, 0x64, 0x87, 0x8d, 0x68, 0x34, 0x0c, 0x52, 0xa3, 0x5e, 0x66, 0xc1, 0x88, 0x4d, 0x5c, 0x86, 0x48, 0x89, 0xab, 0xc9, 0x66, 0x77 }, - { 0x81, 0xea, 0x0b, 0x78, 0x04, 0x12, 0x4e, 0x0c, 0x22, 0xea, 0x5f, 0xc7, 0x11, 0x04, 0xa2, 0xaf, 0xcb, 0x52, 0xa1, 0xfa, 0x81, 0x6f, 0x3e, 0xcb, 0x7d, 0xcb, 0x5d, 0x9d, 0xea, 0x17, 0x86, 0xd0 }, - { 0xfe, 0x36, 0x27, 0x33, 0xb0, 0x5f, 0x6b, 0xed, 0xaf, 0x93, 0x79, 0xd7, 0xf7, 0x93, 0x6e, 0xde, 0x20, 0x9b, 0x1f, 0x83, 0x23, 0xc3, 0x92, 0x25, 0x49, 0xd9, 0xe7, 0x36, 0x81, 0xb5, 0xdb, 0x7b }, - { 0xef, 0xf3, 0x7d, 0x30, 0xdf, 0xd2, 0x03, 0x59, 0xbe, 0x4e, 0x73, 0xfd, 0xf4, 0x0d, 0x27, 0x73, 0x4b, 0x3d, 0xf9, 0x0a, 0x97, 0xa5, 0x5e, 0xd7, 0x45, 0x29, 0x72, 0x94, 0xca, 0x85, 0xd0, 0x9f }, - { 0x17, 0x2f, 0xfc, 0x67, 0x15, 0x3d, 0x12, 0xe0, 0xca, 0x76, 0xa8, 0xb6, 0xcd, 0x5d, 0x47, 0x31, 0x88, 0x5b, 0x39, 0xce, 0x0c, 0xac, 0x93, 0xa8, 0x97, 0x2a, 0x18, 0x00, 0x6c, 0x8b, 0x8b, 0xaf }, - { 0xc4, 0x79, 0x57, 0xf1, 0xcc, 0x88, 0xe8, 0x3e, 0xf9, 0x44, 0x58, 0x39, 0x70, 0x9a, 0x48, 0x0a, 0x03, 0x6b, 0xed, 0x5f, 0x88, 0xac, 0x0f, 0xcc, 0x8e, 0x1e, 0x70, 0x3f, 0xfa, 0xac, 0x13, 0x2c }, - { 0x30, 0xf3, 0x54, 0x83, 0x70, 0xcf, 0xdc, 0xed, 0xa5, 0xc3, 0x7b, 0x56, 0x9b, 0x61, 0x75, 0xe7, 0x99, 0xee, 0xf1, 0xa6, 0x2a, 0xaa, 0x94, 0x32, 0x45, 0xae, 0x76, 0x69, 0xc2, 0x27, 0xa7, 0xb5 }, - { 0xc9, 0x5d, 0xcb, 0x3c, 0xf1, 0xf2, 0x7d, 0x0e, 0xef, 0x2f, 0x25, 0xd2, 0x41, 0x38, 0x70, 0x90, 0x4a, 0x87, 0x7c, 0x4a, 0x56, 0xc2, 0xde, 0x1e, 0x83, 0xe2, 0xbc, 0x2a, 0xe2, 0xe4, 0x68, 0x21 }, - { 0xd5, 0xd0, 0xb5, 0xd7, 0x05, 0x43, 0x4c, 0xd4, 0x6b, 0x18, 0x57, 0x49, 0xf6, 0x6b, 0xfb, 0x58, 0x36, 0xdc, 0xdf, 0x6e, 0xe5, 0x49, 0xa2, 0xb7, 0xa4, 0xae, 0xe7, 0xf5, 0x80, 0x07, 0xca, 0xaf }, - { 0xbb, 0xc1, 0x24, 0xa7, 0x12, 0xf1, 0x5d, 0x07, 0xc3, 0x00, 0xe0, 0x5b, 0x66, 0x83, 0x89, 0xa4, 0x39, 0xc9, 0x17, 0x77, 0xf7, 0x21, 0xf8, 0x32, 0x0c, 0x1c, 0x90, 0x78, 0x06, 0x6d, 0x2c, 0x7e }, - { 0xa4, 0x51, 0xb4, 0x8c, 0x35, 0xa6, 0xc7, 0x85, 0x4c, 0xfa, 0xae, 0x60, 0x26, 0x2e, 0x76, 0x99, 0x08, 0x16, 0x38, 0x2a, 0xc0, 0x66, 0x7e, 0x5a, 0x5c, 0x9e, 0x1b, 0x46, 0xc4, 0x34, 0x2d, 0xdf }, - { 0xb0, 0xd1, 0x50, 0xfb, 0x55, 0xe7, 0x78, 0xd0, 0x11, 0x47, 0xf0, 0xb5, 0xd8, 0x9d, 0x99, 0xec, 0xb2, 0x0f, 0xf0, 0x7e, 0x5e, 0x67, 0x60, 0xd6, 0xb6, 0x45, 0xeb, 0x5b, 0x65, 0x4c, 0x62, 0x2b }, - { 0x34, 0xf7, 0x37, 0xc0, 0xab, 0x21, 0x99, 0x51, 0xee, 0xe8, 0x9a, 0x9f, 0x8d, 0xac, 0x29, 0x9c, 0x9d, 0x4c, 0x38, 0xf3, 0x3f, 0xa4, 0x94, 0xc5, 0xc6, 0xee, 0xfc, 0x92, 0xb6, 0xdb, 0x08, 0xbc }, - { 0x1a, 0x62, 0xcc, 0x3a, 0x00, 0x80, 0x0d, 0xcb, 0xd9, 0x98, 0x91, 0x08, 0x0c, 0x1e, 0x09, 0x84, 0x58, 0x19, 0x3a, 0x8c, 0xc9, 0xf9, 0x70, 0xea, 0x99, 0xfb, 0xef, 0xf0, 0x03, 0x18, 0xc2, 0x89 }, - { 0xcf, 0xce, 0x55, 0xeb, 0xaf, 0xc8, 0x40, 0xd7, 0xae, 0x48, 0x28, 0x1c, 0x7f, 0xd5, 0x7e, 0xc8, 0xb4, 0x82, 0xd4, 0xb7, 0x04, 0x43, 0x74, 0x95, 0x49, 0x5a, 0xc4, 0x14, 0xcf, 0x4a, 0x37, 0x4b }, - { 0x67, 0x46, 0xfa, 0xcf, 0x71, 0x14, 0x6d, 0x99, 0x9d, 0xab, 0xd0, 0x5d, 0x09, 0x3a, 0xe5, 0x86, 0x64, 0x8d, 0x1e, 0xe2, 0x8e, 0x72, 0x61, 0x7b, 0x99, 0xd0, 0xf0, 0x08, 0x6e, 0x1e, 0x45, 0xbf }, - { 0x57, 0x1c, 0xed, 0x28, 0x3b, 0x3f, 0x23, 0xb4, 0xe7, 0x50, 0xbf, 0x12, 0xa2, 0xca, 0xf1, 0x78, 0x18, 0x47, 0xbd, 0x89, 0x0e, 0x43, 0x60, 0x3c, 0xdc, 0x59, 0x76, 0x10, 0x2b, 0x7b, 0xb1, 0x1b }, - { 0xcf, 0xcb, 0x76, 0x5b, 0x04, 0x8e, 0x35, 0x02, 0x2c, 0x5d, 0x08, 0x9d, 0x26, 0xe8, 0x5a, 0x36, 0xb0, 0x05, 0xa2, 0xb8, 0x04, 0x93, 0xd0, 0x3a, 0x14, 0x4e, 0x09, 0xf4, 0x09, 0xb6, 0xaf, 0xd1 }, - { 0x40, 0x50, 0xc7, 0xa2, 0x77, 0x05, 0xbb, 0x27, 0xf4, 0x20, 0x89, 0xb2, 0x99, 0xf3, 0xcb, 0xe5, 0x05, 0x4e, 0xad, 0x68, 0x72, 0x7e, 0x8e, 0xf9, 0x31, 0x8c, 0xe6, 0xf2, 0x5c, 0xd6, 0xf3, 0x1d }, - { 0x18, 0x40, 0x70, 0xbd, 0x5d, 0x26, 0x5f, 0xbd, 0xc1, 0x42, 0xcd, 0x1c, 0x5c, 0xd0, 0xd7, 0xe4, 0x14, 0xe7, 0x03, 0x69, 0xa2, 0x66, 0xd6, 0x27, 0xc8, 0xfb, 0xa8, 0x4f, 0xa5, 0xe8, 0x4c, 0x34 }, - { 0x9e, 0xdd, 0xa9, 0xa4, 0x44, 0x39, 0x02, 0xa9, 0x58, 0x8c, 0x0d, 0x0c, 0xcc, 0x62, 0xb9, 0x30, 0x21, 0x84, 0x79, 0xa6, 0x84, 0x1e, 0x6f, 0xe7, 0xd4, 0x30, 0x03, 0xf0, 0x4b, 0x1f, 0xd6, 0x43 }, - { 0xe4, 0x12, 0xfe, 0xef, 0x79, 0x08, 0x32, 0x4a, 0x6d, 0xa1, 0x84, 0x16, 0x29, 0xf3, 0x5d, 0x3d, 0x35, 0x86, 0x42, 0x01, 0x93, 0x10, 0xec, 0x57, 0xc6, 0x14, 0x83, 0x6b, 0x63, 0xd3, 0x07, 0x63 }, - { 0x1a, 0x2b, 0x8e, 0xdf, 0xf3, 0xf9, 0xac, 0xc1, 0x55, 0x4f, 0xcb, 0xae, 0x3c, 0xf1, 0xd6, 0x29, 0x8c, 0x64, 0x62, 0xe2, 0x2e, 0x5e, 0xb0, 0x25, 0x96, 0x84, 0xf8, 0x35, 0x01, 0x2b, 0xd1, 0x3f }, - { 0x28, 0x8c, 0x4a, 0xd9, 0xb9, 0x40, 0x97, 0x62, 0xea, 0x07, 0xc2, 0x4a, 0x41, 0xf0, 0x4f, 0x69, 0xa7, 0xd7, 0x4b, 0xee, 0x2d, 0x95, 0x43, 0x53, 0x74, 0xbd, 0xe9, 0x46, 0xd7, 0x24, 0x1c, 0x7b }, - { 0x80, 0x56, 0x91, 0xbb, 0x28, 0x67, 0x48, 0xcf, 0xb5, 0x91, 0xd3, 0xae, 0xbe, 0x7e, 0x6f, 0x4e, 0x4d, 0xc6, 0xe2, 0x80, 0x8c, 0x65, 0x14, 0x3c, 0xc0, 0x04, 0xe4, 0xeb, 0x6f, 0xd0, 0x9d, 0x43 }, - { 0xd4, 0xac, 0x8d, 0x3a, 0x0a, 0xfc, 0x6c, 0xfa, 0x7b, 0x46, 0x0a, 0xe3, 0x00, 0x1b, 0xae, 0xb3, 0x6d, 0xad, 0xb3, 0x7d, 0xa0, 0x7d, 0x2e, 0x8a, 0xc9, 0x18, 0x22, 0xdf, 0x34, 0x8a, 0xed, 0x3d }, - { 0xc3, 0x76, 0x61, 0x70, 0x14, 0xd2, 0x01, 0x58, 0xbc, 0xed, 0x3d, 0x3b, 0xa5, 0x52, 0xb6, 0xec, 0xcf, 0x84, 0xe6, 0x2a, 0xa3, 0xeb, 0x65, 0x0e, 0x90, 0x02, 0x9c, 0x84, 0xd1, 0x3e, 0xea, 0x69 }, - { 0xc4, 0x1f, 0x09, 0xf4, 0x3c, 0xec, 0xae, 0x72, 0x93, 0xd6, 0x00, 0x7c, 0xa0, 0xa3, 0x57, 0x08, 0x7d, 0x5a, 0xe5, 0x9b, 0xe5, 0x00, 0xc1, 0xcd, 0x5b, 0x28, 0x9e, 0xe8, 0x10, 0xc7, 0xb0, 0x82 }, - { 0x03, 0xd1, 0xce, 0xd1, 0xfb, 0xa5, 0xc3, 0x91, 0x55, 0xc4, 0x4b, 0x77, 0x65, 0xcb, 0x76, 0x0c, 0x78, 0x70, 0x8d, 0xcf, 0xc8, 0x0b, 0x0b, 0xd8, 0xad, 0xe3, 0xa5, 0x6d, 0xa8, 0x83, 0x0b, 0x29 }, - { 0x09, 0xbd, 0xe6, 0xf1, 0x52, 0x21, 0x8d, 0xc9, 0x2c, 0x41, 0xd7, 0xf4, 0x53, 0x87, 0xe6, 0x3e, 0x58, 0x69, 0xd8, 0x07, 0xec, 0x70, 0xb8, 0x21, 0x40, 0x5d, 0xbd, 0x88, 0x4b, 0x7f, 0xcf, 0x4b }, - { 0x71, 0xc9, 0x03, 0x6e, 0x18, 0x17, 0x9b, 0x90, 0xb3, 0x7d, 0x39, 0xe9, 0xf0, 0x5e, 0xb8, 0x9c, 0xc5, 0xfc, 0x34, 0x1f, 0xd7, 0xc4, 0x77, 0xd0, 0xd7, 0x49, 0x32, 0x85, 0xfa, 0xca, 0x08, 0xa4 }, - { 0x59, 0x16, 0x83, 0x3e, 0xbb, 0x05, 0xcd, 0x91, 0x9c, 0xa7, 0xfe, 0x83, 0xb6, 0x92, 0xd3, 0x20, 0x5b, 0xef, 0x72, 0x39, 0x2b, 0x2c, 0xf6, 0xbb, 0x0a, 0x6d, 0x43, 0xf9, 0x94, 0xf9, 0x5f, 0x11 }, - { 0xf6, 0x3a, 0xab, 0x3e, 0xc6, 0x41, 0xb3, 0xb0, 0x24, 0x96, 0x4c, 0x2b, 0x43, 0x7c, 0x04, 0xf6, 0x04, 0x3c, 0x4c, 0x7e, 0x02, 0x79, 0x23, 0x99, 0x95, 0x40, 0x19, 0x58, 0xf8, 0x6b, 0xbe, 0x54 }, - { 0xf1, 0x72, 0xb1, 0x80, 0xbf, 0xb0, 0x97, 0x40, 0x49, 0x31, 0x20, 0xb6, 0x32, 0x6c, 0xbd, 0xc5, 0x61, 0xe4, 0x77, 0xde, 0xf9, 0xbb, 0xcf, 0xd2, 0x8c, 0xc8, 0xc1, 0xc5, 0xe3, 0x37, 0x9a, 0x31 }, - { 0xcb, 0x9b, 0x89, 0xcc, 0x18, 0x38, 0x1d, 0xd9, 0x14, 0x1a, 0xde, 0x58, 0x86, 0x54, 0xd4, 0xe6, 0xa2, 0x31, 0xd5, 0xbf, 0x49, 0xd4, 0xd5, 0x9a, 0xc2, 0x7d, 0x86, 0x9c, 0xbe, 0x10, 0x0c, 0xf3 }, - { 0x7b, 0xd8, 0x81, 0x50, 0x46, 0xfd, 0xd8, 0x10, 0xa9, 0x23, 0xe1, 0x98, 0x4a, 0xae, 0xbd, 0xcd, 0xf8, 0x4d, 0x87, 0xc8, 0x99, 0x2d, 0x68, 0xb5, 0xee, 0xb4, 0x60, 0xf9, 0x3e, 0xb3, 0xc8, 0xd7 }, - { 0x60, 0x7b, 0xe6, 0x68, 0x62, 0xfd, 0x08, 0xee, 0x5b, 0x19, 0xfa, 0xca, 0xc0, 0x9d, 0xfd, 0xbc, 0xd4, 0x0c, 0x31, 0x21, 0x01, 0xd6, 0x6e, 0x6e, 0xbd, 0x2b, 0x84, 0x1f, 0x1b, 0x9a, 0x93, 0x25 }, - { 0x9f, 0xe0, 0x3b, 0xbe, 0x69, 0xab, 0x18, 0x34, 0xf5, 0x21, 0x9b, 0x0d, 0xa8, 0x8a, 0x08, 0xb3, 0x0a, 0x66, 0xc5, 0x91, 0x3f, 0x01, 0x51, 0x96, 0x3c, 0x36, 0x05, 0x60, 0xdb, 0x03, 0x87, 0xb3 }, - { 0x90, 0xa8, 0x35, 0x85, 0x71, 0x7b, 0x75, 0xf0, 0xe9, 0xb7, 0x25, 0xe0, 0x55, 0xee, 0xee, 0xb9, 0xe7, 0xa0, 0x28, 0xea, 0x7e, 0x6c, 0xbc, 0x07, 0xb2, 0x09, 0x17, 0xec, 0x03, 0x63, 0xe3, 0x8c }, - { 0x33, 0x6e, 0xa0, 0x53, 0x0f, 0x4a, 0x74, 0x69, 0x12, 0x6e, 0x02, 0x18, 0x58, 0x7e, 0xbb, 0xde, 0x33, 0x58, 0xa0, 0xb3, 0x1c, 0x29, 0xd2, 0x00, 0xf7, 0xdc, 0x7e, 0xb1, 0x5c, 0x6a, 0xad, 0xd8 }, - { 0xa7, 0x9e, 0x76, 0xdc, 0x0a, 0xbc, 0xa4, 0x39, 0x6f, 0x07, 0x47, 0xcd, 0x7b, 0x74, 0x8d, 0xf9, 0x13, 0x00, 0x76, 0x26, 0xb1, 0xd6, 0x59, 0xda, 0x0c, 0x1f, 0x78, 0xb9, 0x30, 0x3d, 0x01, 0xa3 }, - { 0x44, 0xe7, 0x8a, 0x77, 0x37, 0x56, 0xe0, 0x95, 0x15, 0x19, 0x50, 0x4d, 0x70, 0x38, 0xd2, 0x8d, 0x02, 0x13, 0xa3, 0x7e, 0x0c, 0xe3, 0x75, 0x37, 0x17, 0x57, 0xbc, 0x99, 0x63, 0x11, 0xe3, 0xb8 }, - { 0x77, 0xac, 0x01, 0x2a, 0x3f, 0x75, 0x4d, 0xcf, 0xea, 0xb5, 0xeb, 0x99, 0x6b, 0xe9, 0xcd, 0x2d, 0x1f, 0x96, 0x11, 0x1b, 0x6e, 0x49, 0xf3, 0x99, 0x4d, 0xf1, 0x81, 0xf2, 0x85, 0x69, 0xd8, 0x25 }, - { 0xce, 0x5a, 0x10, 0xdb, 0x6f, 0xcc, 0xda, 0xf1, 0x40, 0xaa, 0xa4, 0xde, 0xd6, 0x25, 0x0a, 0x9c, 0x06, 0xe9, 0x22, 0x2b, 0xc9, 0xf9, 0xf3, 0x65, 0x8a, 0x4a, 0xff, 0x93, 0x5f, 0x2b, 0x9f, 0x3a }, - { 0xec, 0xc2, 0x03, 0xa7, 0xfe, 0x2b, 0xe4, 0xab, 0xd5, 0x5b, 0xb5, 0x3e, 0x6e, 0x67, 0x35, 0x72, 0xe0, 0x07, 0x8d, 0xa8, 0xcd, 0x37, 0x5e, 0xf4, 0x30, 0xcc, 0x97, 0xf9, 0xf8, 0x00, 0x83, 0xaf }, - { 0x14, 0xa5, 0x18, 0x6d, 0xe9, 0xd7, 0xa1, 0x8b, 0x04, 0x12, 0xb8, 0x56, 0x3e, 0x51, 0xcc, 0x54, 0x33, 0x84, 0x0b, 0x4a, 0x12, 0x9a, 0x8f, 0xf9, 0x63, 0xb3, 0x3a, 0x3c, 0x4a, 0xfe, 0x8e, 0xbb }, - { 0x13, 0xf8, 0xef, 0x95, 0xcb, 0x86, 0xe6, 0xa6, 0x38, 0x93, 0x1c, 0x8e, 0x10, 0x76, 0x73, 0xeb, 0x76, 0xba, 0x10, 0xd7, 0xc2, 0xcd, 0x70, 0xb9, 0xd9, 0x92, 0x0b, 0xbe, 0xed, 0x92, 0x94, 0x09 }, - { 0x0b, 0x33, 0x8f, 0x4e, 0xe1, 0x2f, 0x2d, 0xfc, 0xb7, 0x87, 0x13, 0x37, 0x79, 0x41, 0xe0, 0xb0, 0x63, 0x21, 0x52, 0x58, 0x1d, 0x13, 0x32, 0x51, 0x6e, 0x4a, 0x2c, 0xab, 0x19, 0x42, 0xcc, 0xa4 }, - { 0xea, 0xab, 0x0e, 0xc3, 0x7b, 0x3b, 0x8a, 0xb7, 0x96, 0xe9, 0xf5, 0x72, 0x38, 0xde, 0x14, 0xa2, 0x64, 0xa0, 0x76, 0xf3, 0x88, 0x7d, 0x86, 0xe2, 0x9b, 0xb5, 0x90, 0x6d, 0xb5, 0xa0, 0x0e, 0x02 }, - { 0x23, 0xcb, 0x68, 0xb8, 0xc0, 0xe6, 0xdc, 0x26, 0xdc, 0x27, 0x76, 0x6d, 0xdc, 0x0a, 0x13, 0xa9, 0x94, 0x38, 0xfd, 0x55, 0x61, 0x7a, 0xa4, 0x09, 0x5d, 0x8f, 0x96, 0x97, 0x20, 0xc8, 0x72, 0xdf }, - { 0x09, 0x1d, 0x8e, 0xe3, 0x0d, 0x6f, 0x29, 0x68, 0xd4, 0x6b, 0x68, 0x7d, 0xd6, 0x52, 0x92, 0x66, 0x57, 0x42, 0xde, 0x0b, 0xb8, 0x3d, 0xcc, 0x00, 0x04, 0xc7, 0x2c, 0xe1, 0x00, 0x07, 0xa5, 0x49 }, - { 0x7f, 0x50, 0x7a, 0xbc, 0x6d, 0x19, 0xba, 0x00, 0xc0, 0x65, 0xa8, 0x76, 0xec, 0x56, 0x57, 0x86, 0x88, 0x82, 0xd1, 0x8a, 0x22, 0x1b, 0xc4, 0x6c, 0x7a, 0x69, 0x12, 0x54, 0x1f, 0x5b, 0xc7, 0xba }, - { 0xa0, 0x60, 0x7c, 0x24, 0xe1, 0x4e, 0x8c, 0x22, 0x3d, 0xb0, 0xd7, 0x0b, 0x4d, 0x30, 0xee, 0x88, 0x01, 0x4d, 0x60, 0x3f, 0x43, 0x7e, 0x9e, 0x02, 0xaa, 0x7d, 0xaf, 0xa3, 0xcd, 0xfb, 0xad, 0x94 }, - { 0xdd, 0xbf, 0xea, 0x75, 0xcc, 0x46, 0x78, 0x82, 0xeb, 0x34, 0x83, 0xce, 0x5e, 0x2e, 0x75, 0x6a, 0x4f, 0x47, 0x01, 0xb7, 0x6b, 0x44, 0x55, 0x19, 0xe8, 0x9f, 0x22, 0xd6, 0x0f, 0xa8, 0x6e, 0x06 }, - { 0x0c, 0x31, 0x1f, 0x38, 0xc3, 0x5a, 0x4f, 0xb9, 0x0d, 0x65, 0x1c, 0x28, 0x9d, 0x48, 0x68, 0x56, 0xcd, 0x14, 0x13, 0xdf, 0x9b, 0x06, 0x77, 0xf5, 0x3e, 0xce, 0x2c, 0xd9, 0xe4, 0x77, 0xc6, 0x0a }, - { 0x46, 0xa7, 0x3a, 0x8d, 0xd3, 0xe7, 0x0f, 0x59, 0xd3, 0x94, 0x2c, 0x01, 0xdf, 0x59, 0x9d, 0xef, 0x78, 0x3c, 0x9d, 0xa8, 0x2f, 0xd8, 0x32, 0x22, 0xcd, 0x66, 0x2b, 0x53, 0xdc, 0xe7, 0xdb, 0xdf }, - { 0xad, 0x03, 0x8f, 0xf9, 0xb1, 0x4d, 0xe8, 0x4a, 0x80, 0x1e, 0x4e, 0x62, 0x1c, 0xe5, 0xdf, 0x02, 0x9d, 0xd9, 0x35, 0x20, 0xd0, 0xc2, 0xfa, 0x38, 0xbf, 0xf1, 0x76, 0xa8, 0xb1, 0xd1, 0x69, 0x8c }, - { 0xab, 0x70, 0xc5, 0xdf, 0xbd, 0x1e, 0xa8, 0x17, 0xfe, 0xd0, 0xcd, 0x06, 0x72, 0x93, 0xab, 0xf3, 0x19, 0xe5, 0xd7, 0x90, 0x1c, 0x21, 0x41, 0xd5, 0xd9, 0x9b, 0x23, 0xf0, 0x3a, 0x38, 0xe7, 0x48 }, - { 0x1f, 0xff, 0xda, 0x67, 0x93, 0x2b, 0x73, 0xc8, 0xec, 0xaf, 0x00, 0x9a, 0x34, 0x91, 0xa0, 0x26, 0x95, 0x3b, 0xab, 0xfe, 0x1f, 0x66, 0x3b, 0x06, 0x97, 0xc3, 0xc4, 0xae, 0x8b, 0x2e, 0x7d, 0xcb }, - { 0xb0, 0xd2, 0xcc, 0x19, 0x47, 0x2d, 0xd5, 0x7f, 0x2b, 0x17, 0xef, 0xc0, 0x3c, 0x8d, 0x58, 0xc2, 0x28, 0x3d, 0xbb, 0x19, 0xda, 0x57, 0x2f, 0x77, 0x55, 0x85, 0x5a, 0xa9, 0x79, 0x43, 0x17, 0xa0 }, - { 0xa0, 0xd1, 0x9a, 0x6e, 0xe3, 0x39, 0x79, 0xc3, 0x25, 0x51, 0x0e, 0x27, 0x66, 0x22, 0xdf, 0x41, 0xf7, 0x15, 0x83, 0xd0, 0x75, 0x01, 0xb8, 0x70, 0x71, 0x12, 0x9a, 0x0a, 0xd9, 0x47, 0x32, 0xa5 }, - { 0x72, 0x46, 0x42, 0xa7, 0x03, 0x2d, 0x10, 0x62, 0xb8, 0x9e, 0x52, 0xbe, 0xa3, 0x4b, 0x75, 0xdf, 0x7d, 0x8f, 0xe7, 0x72, 0xd9, 0xfe, 0x3c, 0x93, 0xdd, 0xf3, 0xc4, 0x54, 0x5a, 0xb5, 0xa9, 0x9b }, - { 0xad, 0xe5, 0xea, 0xa7, 0xe6, 0x1f, 0x67, 0x2d, 0x58, 0x7e, 0xa0, 0x3d, 0xae, 0x7d, 0x7b, 0x55, 0x22, 0x9c, 0x01, 0xd0, 0x6b, 0xc0, 0xa5, 0x70, 0x14, 0x36, 0xcb, 0xd1, 0x83, 0x66, 0xa6, 0x26 }, - { 0x01, 0x3b, 0x31, 0xeb, 0xd2, 0x28, 0xfc, 0xdd, 0xa5, 0x1f, 0xab, 0xb0, 0x3b, 0xb0, 0x2d, 0x60, 0xac, 0x20, 0xca, 0x21, 0x5a, 0xaf, 0xa8, 0x3b, 0xdd, 0x85, 0x5e, 0x37, 0x55, 0xa3, 0x5f, 0x0b }, - { 0x33, 0x2e, 0xd4, 0x0b, 0xb1, 0x0d, 0xde, 0x3c, 0x95, 0x4a, 0x75, 0xd7, 0xb8, 0x99, 0x9d, 0x4b, 0x26, 0xa1, 0xc0, 0x63, 0xc1, 0xdc, 0x6e, 0x32, 0xc1, 0xd9, 0x1b, 0xab, 0x7b, 0xbb, 0x7d, 0x16 }, - { 0xc7, 0xa1, 0x97, 0xb3, 0xa0, 0x5b, 0x56, 0x6b, 0xcc, 0x9f, 0xac, 0xd2, 0x0e, 0x44, 0x1d, 0x6f, 0x6c, 0x28, 0x60, 0xac, 0x96, 0x51, 0xcd, 0x51, 0xd6, 0xb9, 0xd2, 0xcd, 0xee, 0xea, 0x03, 0x90 }, - { 0xbd, 0x9c, 0xf6, 0x4e, 0xa8, 0x95, 0x3c, 0x03, 0x71, 0x08, 0xe6, 0xf6, 0x54, 0x91, 0x4f, 0x39, 0x58, 0xb6, 0x8e, 0x29, 0xc1, 0x67, 0x00, 0xdc, 0x18, 0x4d, 0x94, 0xa2, 0x17, 0x08, 0xff, 0x60 }, - { 0x88, 0x35, 0xb0, 0xac, 0x02, 0x11, 0x51, 0xdf, 0x71, 0x64, 0x74, 0xce, 0x27, 0xce, 0x4d, 0x3c, 0x15, 0xf0, 0xb2, 0xda, 0xb4, 0x80, 0x03, 0xcf, 0x3f, 0x3e, 0xfd, 0x09, 0x45, 0x10, 0x6b, 0x9a }, - { 0x3b, 0xfe, 0xfa, 0x33, 0x01, 0xaa, 0x55, 0xc0, 0x80, 0x19, 0x0c, 0xff, 0xda, 0x8e, 0xae, 0x51, 0xd9, 0xaf, 0x48, 0x8b, 0x4c, 0x1f, 0x24, 0xc3, 0xd9, 0xa7, 0x52, 0x42, 0xfd, 0x8e, 0xa0, 0x1d }, - { 0x08, 0x28, 0x4d, 0x14, 0x99, 0x3c, 0xd4, 0x7d, 0x53, 0xeb, 0xae, 0xcf, 0x0d, 0xf0, 0x47, 0x8c, 0xc1, 0x82, 0xc8, 0x9c, 0x00, 0xe1, 0x85, 0x9c, 0x84, 0x85, 0x16, 0x86, 0xdd, 0xf2, 0xc1, 0xb7 }, - { 0x1e, 0xd7, 0xef, 0x9f, 0x04, 0xc2, 0xac, 0x8d, 0xb6, 0xa8, 0x64, 0xdb, 0x13, 0x10, 0x87, 0xf2, 0x70, 0x65, 0x09, 0x8e, 0x69, 0xc3, 0xfe, 0x78, 0x71, 0x8d, 0x9b, 0x94, 0x7f, 0x4a, 0x39, 0xd0 }, - { 0xc1, 0x61, 0xf2, 0xdc, 0xd5, 0x7e, 0x9c, 0x14, 0x39, 0xb3, 0x1a, 0x9d, 0xd4, 0x3d, 0x8f, 0x3d, 0x7d, 0xd8, 0xf0, 0xeb, 0x7c, 0xfa, 0xc6, 0xfb, 0x25, 0xa0, 0xf2, 0x8e, 0x30, 0x6f, 0x06, 0x61 }, - { 0xc0, 0x19, 0x69, 0xad, 0x34, 0xc5, 0x2c, 0xaf, 0x3d, 0xc4, 0xd8, 0x0d, 0x19, 0x73, 0x5c, 0x29, 0x73, 0x1a, 0xc6, 0xe7, 0xa9, 0x20, 0x85, 0xab, 0x92, 0x50, 0xc4, 0x8d, 0xea, 0x48, 0xa3, 0xfc }, - { 0x17, 0x20, 0xb3, 0x65, 0x56, 0x19, 0xd2, 0xa5, 0x2b, 0x35, 0x21, 0xae, 0x0e, 0x49, 0xe3, 0x45, 0xcb, 0x33, 0x89, 0xeb, 0xd6, 0x20, 0x8a, 0xca, 0xf9, 0xf1, 0x3f, 0xda, 0xcc, 0xa8, 0xbe, 0x49 }, - { 0x75, 0x62, 0x88, 0x36, 0x1c, 0x83, 0xe2, 0x4c, 0x61, 0x7c, 0xf9, 0x5c, 0x90, 0x5b, 0x22, 0xd0, 0x17, 0xcd, 0xc8, 0x6f, 0x0b, 0xf1, 0xd6, 0x58, 0xf4, 0x75, 0x6c, 0x73, 0x79, 0x87, 0x3b, 0x7f }, - { 0xe7, 0xd0, 0xed, 0xa3, 0x45, 0x26, 0x93, 0xb7, 0x52, 0xab, 0xcd, 0xa1, 0xb5, 0x5e, 0x27, 0x6f, 0x82, 0x69, 0x8f, 0x5f, 0x16, 0x05, 0x40, 0x3e, 0xff, 0x83, 0x0b, 0xea, 0x00, 0x71, 0xa3, 0x94 }, - { 0x2c, 0x82, 0xec, 0xaa, 0x6b, 0x84, 0x80, 0x3e, 0x04, 0x4a, 0xf6, 0x31, 0x18, 0xaf, 0xe5, 0x44, 0x68, 0x7c, 0xb6, 0xe6, 0xc7, 0xdf, 0x49, 0xed, 0x76, 0x2d, 0xfd, 0x7c, 0x86, 0x93, 0xa1, 0xbc }, - { 0x61, 0x36, 0xcb, 0xf4, 0xb4, 0x41, 0x05, 0x6f, 0xa1, 0xe2, 0x72, 0x24, 0x98, 0x12, 0x5d, 0x6d, 0xed, 0x45, 0xe1, 0x7b, 0x52, 0x14, 0x39, 0x59, 0xc7, 0xf4, 0xd4, 0xe3, 0x95, 0x21, 0x8a, 0xc2 }, - { 0x72, 0x1d, 0x32, 0x45, 0xaa, 0xfe, 0xf2, 0x7f, 0x6a, 0x62, 0x4f, 0x47, 0x95, 0x4b, 0x6c, 0x25, 0x50, 0x79, 0x52, 0x6f, 0xfa, 0x25, 0xe9, 0xff, 0x77, 0xe5, 0xdc, 0xff, 0x47, 0x3b, 0x15, 0x97 }, - { 0x9d, 0xd2, 0xfb, 0xd8, 0xce, 0xf1, 0x6c, 0x35, 0x3c, 0x0a, 0xc2, 0x11, 0x91, 0xd5, 0x09, 0xeb, 0x28, 0xdd, 0x9e, 0x3e, 0x0d, 0x8c, 0xea, 0x5d, 0x26, 0xca, 0x83, 0x93, 0x93, 0x85, 0x1c, 0x3a }, - { 0xb2, 0x39, 0x4c, 0xea, 0xcd, 0xeb, 0xf2, 0x1b, 0xf9, 0xdf, 0x2c, 0xed, 0x98, 0xe5, 0x8f, 0x1c, 0x3a, 0x4b, 0xbb, 0xff, 0x66, 0x0d, 0xd9, 0x00, 0xf6, 0x22, 0x02, 0xd6, 0x78, 0x5c, 0xc4, 0x6e }, - { 0x57, 0x08, 0x9f, 0x22, 0x27, 0x49, 0xad, 0x78, 0x71, 0x76, 0x5f, 0x06, 0x2b, 0x11, 0x4f, 0x43, 0xba, 0x20, 0xec, 0x56, 0x42, 0x2a, 0x8b, 0x1e, 0x3f, 0x87, 0x19, 0x2c, 0x0e, 0xa7, 0x18, 0xc6 }, - { 0xe4, 0x9a, 0x94, 0x59, 0x96, 0x1c, 0xd3, 0x3c, 0xdf, 0x4a, 0xae, 0x1b, 0x10, 0x78, 0xa5, 0xde, 0xa7, 0xc0, 0x40, 0xe0, 0xfe, 0xa3, 0x40, 0xc9, 0x3a, 0x72, 0x48, 0x72, 0xfc, 0x4a, 0xf8, 0x06 }, - { 0xed, 0xe6, 0x7f, 0x72, 0x0e, 0xff, 0xd2, 0xca, 0x9c, 0x88, 0x99, 0x41, 0x52, 0xd0, 0x20, 0x1d, 0xee, 0x6b, 0x0a, 0x2d, 0x2c, 0x07, 0x7a, 0xca, 0x6d, 0xae, 0x29, 0xf7, 0x3f, 0x8b, 0x63, 0x09 }, - { 0xe0, 0xf4, 0x34, 0xbf, 0x22, 0xe3, 0x08, 0x80, 0x39, 0xc2, 0x1f, 0x71, 0x9f, 0xfc, 0x67, 0xf0, 0xf2, 0xcb, 0x5e, 0x98, 0xa7, 0xa0, 0x19, 0x4c, 0x76, 0xe9, 0x6b, 0xf4, 0xe8, 0xe1, 0x7e, 0x61 }, - { 0x27, 0x7c, 0x04, 0xe2, 0x85, 0x34, 0x84, 0xa4, 0xeb, 0xa9, 0x10, 0xad, 0x33, 0x6d, 0x01, 0xb4, 0x77, 0xb6, 0x7c, 0xc2, 0x00, 0xc5, 0x9f, 0x3c, 0x8d, 0x77, 0xee, 0xf8, 0x49, 0x4f, 0x29, 0xcd }, - { 0x15, 0x6d, 0x57, 0x47, 0xd0, 0xc9, 0x9c, 0x7f, 0x27, 0x09, 0x7d, 0x7b, 0x7e, 0x00, 0x2b, 0x2e, 0x18, 0x5c, 0xb7, 0x2d, 0x8d, 0xd7, 0xeb, 0x42, 0x4a, 0x03, 0x21, 0x52, 0x81, 0x61, 0x21, 0x9f }, - { 0x20, 0xdd, 0xd1, 0xed, 0x9b, 0x1c, 0xa8, 0x03, 0x94, 0x6d, 0x64, 0xa8, 0x3a, 0xe4, 0x65, 0x9d, 0xa6, 0x7f, 0xba, 0x7a, 0x1a, 0x3e, 0xdd, 0xb1, 0xe1, 0x03, 0xc0, 0xf5, 0xe0, 0x3e, 0x3a, 0x2c }, - { 0xf0, 0xaf, 0x60, 0x4d, 0x3d, 0xab, 0xbf, 0x9a, 0x0f, 0x2a, 0x7d, 0x3d, 0xda, 0x6b, 0xd3, 0x8b, 0xba, 0x72, 0xc6, 0xd0, 0x9b, 0xe4, 0x94, 0xfc, 0xef, 0x71, 0x3f, 0xf1, 0x01, 0x89, 0xb6, 0xe6 }, - { 0x98, 0x02, 0xbb, 0x87, 0xde, 0xf4, 0xcc, 0x10, 0xc4, 0xa5, 0xfd, 0x49, 0xaa, 0x58, 0xdf, 0xe2, 0xf3, 0xfd, 0xdb, 0x46, 0xb4, 0x70, 0x88, 0x14, 0xea, 0xd8, 0x1d, 0x23, 0xba, 0x95, 0x13, 0x9b }, - { 0x4f, 0x8c, 0xe1, 0xe5, 0x1d, 0x2f, 0xe7, 0xf2, 0x40, 0x43, 0xa9, 0x04, 0xd8, 0x98, 0xeb, 0xfc, 0x91, 0x97, 0x54, 0x18, 0x75, 0x34, 0x13, 0xaa, 0x09, 0x9b, 0x79, 0x5e, 0xcb, 0x35, 0xce, 0xdb }, - { 0xbd, 0xdc, 0x65, 0x14, 0xd7, 0xee, 0x6a, 0xce, 0x0a, 0x4a, 0xc1, 0xd0, 0xe0, 0x68, 0x11, 0x22, 0x88, 0xcb, 0xcf, 0x56, 0x04, 0x54, 0x64, 0x27, 0x05, 0x63, 0x01, 0x77, 0xcb, 0xa6, 0x08, 0xbd }, - { 0xd6, 0x35, 0x99, 0x4f, 0x62, 0x91, 0x51, 0x7b, 0x02, 0x81, 0xff, 0xdd, 0x49, 0x6a, 0xfa, 0x86, 0x27, 0x12, 0xe5, 0xb3, 0xc4, 0xe5, 0x2e, 0x4c, 0xd5, 0xfd, 0xae, 0x8c, 0x0e, 0x72, 0xfb, 0x08 }, - { 0x87, 0x8d, 0x9c, 0xa6, 0x00, 0xcf, 0x87, 0xe7, 0x69, 0xcc, 0x30, 0x5c, 0x1b, 0x35, 0x25, 0x51, 0x86, 0x61, 0x5a, 0x73, 0xa0, 0xda, 0x61, 0x3b, 0x5f, 0x1c, 0x98, 0xdb, 0xf8, 0x12, 0x83, 0xea }, - { 0xa6, 0x4e, 0xbe, 0x5d, 0xc1, 0x85, 0xde, 0x9f, 0xdd, 0xe7, 0x60, 0x7b, 0x69, 0x98, 0x70, 0x2e, 0xb2, 0x34, 0x56, 0x18, 0x49, 0x57, 0x30, 0x7d, 0x2f, 0xa7, 0x2e, 0x87, 0xa4, 0x77, 0x02, 0xd6 }, - { 0xce, 0x50, 0xea, 0xb7, 0xb5, 0xeb, 0x52, 0xbd, 0xc9, 0xad, 0x8e, 0x5a, 0x48, 0x0a, 0xb7, 0x80, 0xca, 0x93, 0x20, 0xe4, 0x43, 0x60, 0xb1, 0xfe, 0x37, 0xe0, 0x3f, 0x2f, 0x7a, 0xd7, 0xde, 0x01 }, - { 0xee, 0xdd, 0xb7, 0xc0, 0xdb, 0x6e, 0x30, 0xab, 0xe6, 0x6d, 0x79, 0xe3, 0x27, 0x51, 0x1e, 0x61, 0xfc, 0xeb, 0xbc, 0x29, 0xf1, 0x59, 0xb4, 0x0a, 0x86, 0xb0, 0x46, 0xec, 0xf0, 0x51, 0x38, 0x23 }, - { 0x78, 0x7f, 0xc9, 0x34, 0x40, 0xc1, 0xec, 0x96, 0xb5, 0xad, 0x01, 0xc1, 0x6c, 0xf7, 0x79, 0x16, 0xa1, 0x40, 0x5f, 0x94, 0x26, 0x35, 0x6e, 0xc9, 0x21, 0xd8, 0xdf, 0xf3, 0xea, 0x63, 0xb7, 0xe0 }, - { 0x7f, 0x0d, 0x5e, 0xab, 0x47, 0xee, 0xfd, 0xa6, 0x96, 0xc0, 0xbf, 0x0f, 0xbf, 0x86, 0xab, 0x21, 0x6f, 0xce, 0x46, 0x1e, 0x93, 0x03, 0xab, 0xa6, 0xac, 0x37, 0x41, 0x20, 0xe8, 0x90, 0xe8, 0xdf }, - { 0xb6, 0x80, 0x04, 0xb4, 0x2f, 0x14, 0xad, 0x02, 0x9f, 0x4c, 0x2e, 0x03, 0xb1, 0xd5, 0xeb, 0x76, 0xd5, 0x71, 0x60, 0xe2, 0x64, 0x76, 0xd2, 0x11, 0x31, 0xbe, 0xf2, 0x0a, 0xda, 0x7d, 0x27, 0xf4 }, - { 0xb0, 0xc4, 0xeb, 0x18, 0xae, 0x25, 0x0b, 0x51, 0xa4, 0x13, 0x82, 0xea, 0xd9, 0x2d, 0x0d, 0xc7, 0x45, 0x5f, 0x93, 0x79, 0xfc, 0x98, 0x84, 0x42, 0x8e, 0x47, 0x70, 0x60, 0x8d, 0xb0, 0xfa, 0xec }, - { 0xf9, 0x2b, 0x7a, 0x87, 0x0c, 0x05, 0x9f, 0x4d, 0x46, 0x46, 0x4c, 0x82, 0x4e, 0xc9, 0x63, 0x55, 0x14, 0x0b, 0xdc, 0xe6, 0x81, 0x32, 0x2c, 0xc3, 0xa9, 0x92, 0xff, 0x10, 0x3e, 0x3f, 0xea, 0x52 }, - { 0x53, 0x64, 0x31, 0x26, 0x14, 0x81, 0x33, 0x98, 0xcc, 0x52, 0x5d, 0x4c, 0x4e, 0x14, 0x6e, 0xde, 0xb3, 0x71, 0x26, 0x5f, 0xba, 0x19, 0x13, 0x3a, 0x2c, 0x3d, 0x21, 0x59, 0x29, 0x8a, 0x17, 0x42 }, - { 0xf6, 0x62, 0x0e, 0x68, 0xd3, 0x7f, 0xb2, 0xaf, 0x50, 0x00, 0xfc, 0x28, 0xe2, 0x3b, 0x83, 0x22, 0x97, 0xec, 0xd8, 0xbc, 0xe9, 0x9e, 0x8b, 0xe4, 0xd0, 0x4e, 0x85, 0x30, 0x9e, 0x3d, 0x33, 0x74 }, - { 0x53, 0x16, 0xa2, 0x79, 0x69, 0xd7, 0xfe, 0x04, 0xff, 0x27, 0xb2, 0x83, 0x96, 0x1b, 0xff, 0xc3, 0xbf, 0x5d, 0xfb, 0x32, 0xfb, 0x6a, 0x89, 0xd1, 0x01, 0xc6, 0xc3, 0xb1, 0x93, 0x7c, 0x28, 0x71 }, - { 0x81, 0xd1, 0x66, 0x4f, 0xdf, 0x3c, 0xb3, 0x3c, 0x24, 0xee, 0xba, 0xc0, 0xbd, 0x64, 0x24, 0x4b, 0x77, 0xc4, 0xab, 0xea, 0x90, 0xbb, 0xe8, 0xb5, 0xee, 0x0b, 0x2a, 0xaf, 0xcf, 0x2d, 0x6a, 0x53 }, - { 0x34, 0x57, 0x82, 0xf2, 0x95, 0xb0, 0x88, 0x03, 0x52, 0xe9, 0x24, 0xa0, 0x46, 0x7b, 0x5f, 0xbc, 0x3e, 0x8f, 0x3b, 0xfb, 0xc3, 0xc7, 0xe4, 0x8b, 0x67, 0x09, 0x1f, 0xb5, 0xe8, 0x0a, 0x94, 0x42 }, - { 0x79, 0x41, 0x11, 0xea, 0x6c, 0xd6, 0x5e, 0x31, 0x1f, 0x74, 0xee, 0x41, 0xd4, 0x76, 0xcb, 0x63, 0x2c, 0xe1, 0xe4, 0xb0, 0x51, 0xdc, 0x1d, 0x9e, 0x9d, 0x06, 0x1a, 0x19, 0xe1, 0xd0, 0xbb, 0x49 }, - { 0x2a, 0x85, 0xda, 0xf6, 0x13, 0x88, 0x16, 0xb9, 0x9b, 0xf8, 0xd0, 0x8b, 0xa2, 0x11, 0x4b, 0x7a, 0xb0, 0x79, 0x75, 0xa7, 0x84, 0x20, 0xc1, 0xa3, 0xb0, 0x6a, 0x77, 0x7c, 0x22, 0xdd, 0x8b, 0xcb }, - { 0x89, 0xb0, 0xd5, 0xf2, 0x89, 0xec, 0x16, 0x40, 0x1a, 0x06, 0x9a, 0x96, 0x0d, 0x0b, 0x09, 0x3e, 0x62, 0x5d, 0xa3, 0xcf, 0x41, 0xee, 0x29, 0xb5, 0x9b, 0x93, 0x0c, 0x58, 0x20, 0x14, 0x54, 0x55 }, - { 0xd0, 0xfd, 0xcb, 0x54, 0x39, 0x43, 0xfc, 0x27, 0xd2, 0x08, 0x64, 0xf5, 0x21, 0x81, 0x47, 0x1b, 0x94, 0x2c, 0xc7, 0x7c, 0xa6, 0x75, 0xbc, 0xb3, 0x0d, 0xf3, 0x1d, 0x35, 0x8e, 0xf7, 0xb1, 0xeb }, - { 0xb1, 0x7e, 0xa8, 0xd7, 0x70, 0x63, 0xc7, 0x09, 0xd4, 0xdc, 0x6b, 0x87, 0x94, 0x13, 0xc3, 0x43, 0xe3, 0x79, 0x0e, 0x9e, 0x62, 0xca, 0x85, 0xb7, 0x90, 0x0b, 0x08, 0x6f, 0x6b, 0x75, 0xc6, 0x72 }, - { 0xe7, 0x1a, 0x3e, 0x2c, 0x27, 0x4d, 0xb8, 0x42, 0xd9, 0x21, 0x14, 0xf2, 0x17, 0xe2, 0xc0, 0xea, 0xc8, 0xb4, 0x50, 0x93, 0xfd, 0xfd, 0x9d, 0xf4, 0xca, 0x71, 0x62, 0x39, 0x48, 0x62, 0xd5, 0x01 }, - { 0xc0, 0x47, 0x67, 0x59, 0xab, 0x7a, 0xa3, 0x33, 0x23, 0x4f, 0x6b, 0x44, 0xf5, 0xfd, 0x85, 0x83, 0x90, 0xec, 0x23, 0x69, 0x4c, 0x62, 0x2c, 0xb9, 0x86, 0xe7, 0x69, 0xc7, 0x8e, 0xdd, 0x73, 0x3e }, - { 0x9a, 0xb8, 0xea, 0xbb, 0x14, 0x16, 0x43, 0x4d, 0x85, 0x39, 0x13, 0x41, 0xd5, 0x69, 0x93, 0xc5, 0x54, 0x58, 0x16, 0x7d, 0x44, 0x18, 0xb1, 0x9a, 0x0f, 0x2a, 0xd8, 0xb7, 0x9a, 0x83, 0xa7, 0x5b }, - { 0x79, 0x92, 0xd0, 0xbb, 0xb1, 0x5e, 0x23, 0x82, 0x6f, 0x44, 0x3e, 0x00, 0x50, 0x5d, 0x68, 0xd3, 0xed, 0x73, 0x72, 0x99, 0x5a, 0x5c, 0x3e, 0x49, 0x86, 0x54, 0x10, 0x2f, 0xbc, 0xd0, 0x96, 0x4e }, - { 0xc0, 0x21, 0xb3, 0x00, 0x85, 0x15, 0x14, 0x35, 0xdf, 0x33, 0xb0, 0x07, 0xcc, 0xec, 0xc6, 0x9d, 0xf1, 0x26, 0x9f, 0x39, 0xba, 0x25, 0x09, 0x2b, 0xed, 0x59, 0xd9, 0x32, 0xac, 0x0f, 0xdc, 0x28 }, - { 0x91, 0xa2, 0x5e, 0xc0, 0xec, 0x0d, 0x9a, 0x56, 0x7f, 0x89, 0xc4, 0xbf, 0xe1, 0xa6, 0x5a, 0x0e, 0x43, 0x2d, 0x07, 0x06, 0x4b, 0x41, 0x90, 0xe2, 0x7d, 0xfb, 0x81, 0x90, 0x1f, 0xd3, 0x13, 0x9b }, - { 0x59, 0x50, 0xd3, 0x9a, 0x23, 0xe1, 0x54, 0x5f, 0x30, 0x12, 0x70, 0xaa, 0x1a, 0x12, 0xf2, 0xe6, 0xc4, 0x53, 0x77, 0x6e, 0x4d, 0x63, 0x55, 0xde, 0x42, 0x5c, 0xc1, 0x53, 0xf9, 0x81, 0x88, 0x67 }, - { 0xd7, 0x9f, 0x14, 0x72, 0x0c, 0x61, 0x0a, 0xf1, 0x79, 0xa3, 0x76, 0x5d, 0x4b, 0x7c, 0x09, 0x68, 0xf9, 0x77, 0x96, 0x2d, 0xbf, 0x65, 0x5b, 0x52, 0x12, 0x72, 0xb6, 0xf1, 0xe1, 0x94, 0x48, 0x8e }, - { 0xe9, 0x53, 0x1b, 0xfc, 0x8b, 0x02, 0x99, 0x5a, 0xea, 0xa7, 0x5b, 0xa2, 0x70, 0x31, 0xfa, 0xdb, 0xcb, 0xf4, 0xa0, 0xda, 0xb8, 0x96, 0x1d, 0x92, 0x96, 0xcd, 0x7e, 0x84, 0xd2, 0x5d, 0x60, 0x06 }, - { 0x34, 0xe9, 0xc2, 0x6a, 0x01, 0xd7, 0xf1, 0x61, 0x81, 0xb4, 0x54, 0xa9, 0xd1, 0x62, 0x3c, 0x23, 0x3c, 0xb9, 0x9d, 0x31, 0xc6, 0x94, 0x65, 0x6e, 0x94, 0x13, 0xac, 0xa3, 0xe9, 0x18, 0x69, 0x2f }, - { 0xd9, 0xd7, 0x42, 0x2f, 0x43, 0x7b, 0xd4, 0x39, 0xdd, 0xd4, 0xd8, 0x83, 0xda, 0xe2, 0xa0, 0x83, 0x50, 0x17, 0x34, 0x14, 0xbe, 0x78, 0x15, 0x51, 0x33, 0xff, 0xf1, 0x96, 0x4c, 0x3d, 0x79, 0x72 }, - { 0x4a, 0xee, 0x0c, 0x7a, 0xaf, 0x07, 0x54, 0x14, 0xff, 0x17, 0x93, 0xea, 0xd7, 0xea, 0xca, 0x60, 0x17, 0x75, 0xc6, 0x15, 0xdb, 0xd6, 0x0b, 0x64, 0x0b, 0x0a, 0x9f, 0x0c, 0xe5, 0x05, 0xd4, 0x35 }, - { 0x6b, 0xfd, 0xd1, 0x54, 0x59, 0xc8, 0x3b, 0x99, 0xf0, 0x96, 0xbf, 0xb4, 0x9e, 0xe8, 0x7b, 0x06, 0x3d, 0x69, 0xc1, 0x97, 0x4c, 0x69, 0x28, 0xac, 0xfc, 0xfb, 0x40, 0x99, 0xf8, 0xc4, 0xef, 0x67 }, - { 0x9f, 0xd1, 0xc4, 0x08, 0xfd, 0x75, 0xc3, 0x36, 0x19, 0x3a, 0x2a, 0x14, 0xd9, 0x4f, 0x6a, 0xf5, 0xad, 0xf0, 0x50, 0xb8, 0x03, 0x87, 0xb4, 0xb0, 0x10, 0xfb, 0x29, 0xf4, 0xcc, 0x72, 0x70, 0x7c }, - { 0x13, 0xc8, 0x84, 0x80, 0xa5, 0xd0, 0x0d, 0x6c, 0x8c, 0x7a, 0xd2, 0x11, 0x0d, 0x76, 0xa8, 0x2d, 0x9b, 0x70, 0xf4, 0xfa, 0x66, 0x96, 0xd4, 0xe5, 0xdd, 0x42, 0xa0, 0x66, 0xdc, 0xaf, 0x99, 0x20 }, - { 0x82, 0x0e, 0x72, 0x5e, 0xe2, 0x5f, 0xe8, 0xfd, 0x3a, 0x8d, 0x5a, 0xbe, 0x4c, 0x46, 0xc3, 0xba, 0x88, 0x9d, 0xe6, 0xfa, 0x91, 0x91, 0xaa, 0x22, 0xba, 0x67, 0xd5, 0x70, 0x54, 0x21, 0x54, 0x2b }, - { 0x32, 0xd9, 0x3a, 0x0e, 0xb0, 0x2f, 0x42, 0xfb, 0xbc, 0xaf, 0x2b, 0xad, 0x00, 0x85, 0xb2, 0x82, 0xe4, 0x60, 0x46, 0xa4, 0xdf, 0x7a, 0xd1, 0x06, 0x57, 0xc9, 0xd6, 0x47, 0x63, 0x75, 0xb9, 0x3e }, - { 0xad, 0xc5, 0x18, 0x79, 0x05, 0xb1, 0x66, 0x9c, 0xd8, 0xec, 0x9c, 0x72, 0x1e, 0x19, 0x53, 0x78, 0x6b, 0x9d, 0x89, 0xa9, 0xba, 0xe3, 0x07, 0x80, 0xf1, 0xe1, 0xea, 0xb2, 0x4a, 0x00, 0x52, 0x3c }, - { 0xe9, 0x07, 0x56, 0xff, 0x7f, 0x9a, 0xd8, 0x10, 0xb2, 0x39, 0xa1, 0x0c, 0xed, 0x2c, 0xf9, 0xb2, 0x28, 0x43, 0x54, 0xc1, 0xf8, 0xc7, 0xe0, 0xac, 0xcc, 0x24, 0x61, 0xdc, 0x79, 0x6d, 0x6e, 0x89 }, - { 0x12, 0x51, 0xf7, 0x6e, 0x56, 0x97, 0x84, 0x81, 0x87, 0x53, 0x59, 0x80, 0x1d, 0xb5, 0x89, 0xa0, 0xb2, 0x2f, 0x86, 0xd8, 0xd6, 0x34, 0xdc, 0x04, 0x50, 0x6f, 0x32, 0x2e, 0xd7, 0x8f, 0x17, 0xe8 }, - { 0x3a, 0xfa, 0x89, 0x9f, 0xd9, 0x80, 0xe7, 0x3e, 0xcb, 0x7f, 0x4d, 0x8b, 0x8f, 0x29, 0x1d, 0xc9, 0xaf, 0x79, 0x6b, 0xc6, 0x5d, 0x27, 0xf9, 0x74, 0xc6, 0xf1, 0x93, 0xc9, 0x19, 0x1a, 0x09, 0xfd }, - { 0xaa, 0x30, 0x5b, 0xe2, 0x6e, 0x5d, 0xed, 0xdc, 0x3c, 0x10, 0x10, 0xcb, 0xc2, 0x13, 0xf9, 0x5f, 0x05, 0x1c, 0x78, 0x5c, 0x5b, 0x43, 0x1e, 0x6a, 0x7c, 0xd0, 0x48, 0xf1, 0x61, 0x78, 0x75, 0x28 }, - { 0x8e, 0xa1, 0x88, 0x4f, 0xf3, 0x2e, 0x9d, 0x10, 0xf0, 0x39, 0xb4, 0x07, 0xd0, 0xd4, 0x4e, 0x7e, 0x67, 0x0a, 0xbd, 0x88, 0x4a, 0xee, 0xe0, 0xfb, 0x75, 0x7a, 0xe9, 0x4e, 0xaa, 0x97, 0x37, 0x3d }, - { 0xd4, 0x82, 0xb2, 0x15, 0x5d, 0x4d, 0xec, 0x6b, 0x47, 0x36, 0xa1, 0xf1, 0x61, 0x7b, 0x53, 0xaa, 0xa3, 0x73, 0x10, 0x27, 0x7d, 0x3f, 0xef, 0x0c, 0x37, 0xad, 0x41, 0x76, 0x8f, 0xc2, 0x35, 0xb4 }, - { 0x4d, 0x41, 0x39, 0x71, 0x38, 0x7e, 0x7a, 0x88, 0x98, 0xa8, 0xdc, 0x2a, 0x27, 0x50, 0x07, 0x78, 0x53, 0x9e, 0xa2, 0x14, 0xa2, 0xdf, 0xe9, 0xb3, 0xd7, 0xe8, 0xeb, 0xdc, 0xe5, 0xcf, 0x3d, 0xb3 }, - { 0x69, 0x6e, 0x5d, 0x46, 0xe6, 0xc5, 0x7e, 0x87, 0x96, 0xe4, 0x73, 0x5d, 0x08, 0x91, 0x6e, 0x0b, 0x79, 0x29, 0xb3, 0xcf, 0x29, 0x8c, 0x29, 0x6d, 0x22, 0xe9, 0xd3, 0x01, 0x96, 0x53, 0x37, 0x1c }, - { 0x1f, 0x56, 0x47, 0xc1, 0xd3, 0xb0, 0x88, 0x22, 0x88, 0x85, 0x86, 0x5c, 0x89, 0x40, 0x90, 0x8b, 0xf4, 0x0d, 0x1a, 0x82, 0x72, 0x82, 0x19, 0x73, 0xb1, 0x60, 0x00, 0x8e, 0x7a, 0x3c, 0xe2, 0xeb }, - { 0xb6, 0xe7, 0x6c, 0x33, 0x0f, 0x02, 0x1a, 0x5b, 0xda, 0x65, 0x87, 0x50, 0x10, 0xb0, 0xed, 0xf0, 0x91, 0x26, 0xc0, 0xf5, 0x10, 0xea, 0x84, 0x90, 0x48, 0x19, 0x20, 0x03, 0xae, 0xf4, 0xc6, 0x1c }, - { 0x3c, 0xd9, 0x52, 0xa0, 0xbe, 0xad, 0xa4, 0x1a, 0xbb, 0x42, 0x4c, 0xe4, 0x7f, 0x94, 0xb4, 0x2b, 0xe6, 0x4e, 0x1f, 0xfb, 0x0f, 0xd0, 0x78, 0x22, 0x76, 0x80, 0x79, 0x46, 0xd0, 0xd0, 0xbc, 0x55 }, - { 0x98, 0xd9, 0x26, 0x77, 0x43, 0x9b, 0x41, 0xb7, 0xbb, 0x51, 0x33, 0x12, 0xaf, 0xb9, 0x2b, 0xcc, 0x8e, 0xe9, 0x68, 0xb2, 0xe3, 0xb2, 0x38, 0xce, 0xcb, 0x9b, 0x0f, 0x34, 0xc9, 0xbb, 0x63, 0xd0 }, - { 0xec, 0xbc, 0xa2, 0xcf, 0x08, 0xae, 0x57, 0xd5, 0x17, 0xad, 0x16, 0x15, 0x8a, 0x32, 0xbf, 0xa7, 0xdc, 0x03, 0x82, 0xea, 0xed, 0xa1, 0x28, 0xe9, 0x18, 0x86, 0x73, 0x4c, 0x24, 0xa0, 0xb2, 0x9d }, - { 0x94, 0x2c, 0xc7, 0xc0, 0xb5, 0x2e, 0x2b, 0x16, 0xa4, 0xb8, 0x9f, 0xa4, 0xfc, 0x7e, 0x0b, 0xf6, 0x09, 0xe2, 0x9a, 0x08, 0xc1, 0xa8, 0x54, 0x34, 0x52, 0xb7, 0x7c, 0x7b, 0xfd, 0x11, 0xbb, 0x28 }, - { 0x8a, 0x06, 0x5d, 0x8b, 0x61, 0xa0, 0xdf, 0xfb, 0x17, 0x0d, 0x56, 0x27, 0x73, 0x5a, 0x76, 0xb0, 0xe9, 0x50, 0x60, 0x37, 0x80, 0x8c, 0xba, 0x16, 0xc3, 0x45, 0x00, 0x7c, 0x9f, 0x79, 0xcf, 0x8f }, - { 0x1b, 0x9f, 0xa1, 0x97, 0x14, 0x65, 0x9c, 0x78, 0xff, 0x41, 0x38, 0x71, 0x84, 0x92, 0x15, 0x36, 0x10, 0x29, 0xac, 0x80, 0x2b, 0x1c, 0xbc, 0xd5, 0x4e, 0x40, 0x8b, 0xd8, 0x72, 0x87, 0xf8, 0x1f }, - { 0x8d, 0xab, 0x07, 0x1b, 0xcd, 0x6c, 0x72, 0x92, 0xa9, 0xef, 0x72, 0x7b, 0x4a, 0xe0, 0xd8, 0x67, 0x13, 0x30, 0x1d, 0xa8, 0x61, 0x8d, 0x9a, 0x48, 0xad, 0xce, 0x55, 0xf3, 0x03, 0xa8, 0x69, 0xa1 }, - { 0x82, 0x53, 0xe3, 0xe7, 0xc7, 0xb6, 0x84, 0xb9, 0xcb, 0x2b, 0xeb, 0x01, 0x4c, 0xe3, 0x30, 0xff, 0x3d, 0x99, 0xd1, 0x7a, 0xbb, 0xdb, 0xab, 0xe4, 0xf4, 0xd6, 0x74, 0xde, 0xd5, 0x3f, 0xfc, 0x6b }, - { 0xf1, 0x95, 0xf3, 0x21, 0xe9, 0xe3, 0xd6, 0xbd, 0x7d, 0x07, 0x45, 0x04, 0xdd, 0x2a, 0xb0, 0xe6, 0x24, 0x1f, 0x92, 0xe7, 0x84, 0xb1, 0xaa, 0x27, 0x1f, 0xf6, 0x48, 0xb1, 0xca, 0xb6, 0xd7, 0xf6 }, - { 0x27, 0xe4, 0xcc, 0x72, 0x09, 0x0f, 0x24, 0x12, 0x66, 0x47, 0x6a, 0x7c, 0x09, 0x49, 0x5f, 0x2d, 0xb1, 0x53, 0xd5, 0xbc, 0xbd, 0x76, 0x19, 0x03, 0xef, 0x79, 0x27, 0x5e, 0xc5, 0x6b, 0x2e, 0xd8 }, - { 0x89, 0x9c, 0x24, 0x05, 0x78, 0x8e, 0x25, 0xb9, 0x9a, 0x18, 0x46, 0x35, 0x5e, 0x64, 0x6d, 0x77, 0xcf, 0x40, 0x00, 0x83, 0x41, 0x5f, 0x7d, 0xc5, 0xaf, 0xe6, 0x9d, 0x6e, 0x17, 0xc0, 0x00, 0x23 }, - { 0xa5, 0x9b, 0x78, 0xc4, 0x90, 0x57, 0x44, 0x07, 0x6b, 0xfe, 0xe8, 0x94, 0xde, 0x70, 0x7d, 0x4f, 0x12, 0x0b, 0x5c, 0x68, 0x93, 0xea, 0x04, 0x00, 0x29, 0x7d, 0x0b, 0xb8, 0x34, 0x72, 0x76, 0x32 }, - { 0x59, 0xdc, 0x78, 0xb1, 0x05, 0x64, 0x97, 0x07, 0xa2, 0xbb, 0x44, 0x19, 0xc4, 0x8f, 0x00, 0x54, 0x00, 0xd3, 0x97, 0x3d, 0xe3, 0x73, 0x66, 0x10, 0x23, 0x04, 0x35, 0xb1, 0x04, 0x24, 0xb2, 0x4f }, - { 0xc0, 0x14, 0x9d, 0x1d, 0x7e, 0x7a, 0x63, 0x53, 0xa6, 0xd9, 0x06, 0xef, 0xe7, 0x28, 0xf2, 0xf3, 0x29, 0xfe, 0x14, 0xa4, 0x14, 0x9a, 0x3e, 0xa7, 0x76, 0x09, 0xbc, 0x42, 0xb9, 0x75, 0xdd, 0xfa }, - { 0xa3, 0x2f, 0x24, 0x14, 0x74, 0xa6, 0xc1, 0x69, 0x32, 0xe9, 0x24, 0x3b, 0xe0, 0xcf, 0x09, 0xbc, 0xdc, 0x7e, 0x0c, 0xa0, 0xe7, 0xa6, 0xa1, 0xb9, 0xb1, 0xa0, 0xf0, 0x1e, 0x41, 0x50, 0x23, 0x77 }, - { 0xb2, 0x39, 0xb2, 0xe4, 0xf8, 0x18, 0x41, 0x36, 0x1c, 0x13, 0x39, 0xf6, 0x8e, 0x2c, 0x35, 0x9f, 0x92, 0x9a, 0xf9, 0xad, 0x9f, 0x34, 0xe0, 0x1a, 0xab, 0x46, 0x31, 0xad, 0x6d, 0x55, 0x00, 0xb0 }, - { 0x85, 0xfb, 0x41, 0x9c, 0x70, 0x02, 0xa3, 0xe0, 0xb4, 0xb6, 0xea, 0x09, 0x3b, 0x4c, 0x1a, 0xc6, 0x93, 0x66, 0x45, 0xb6, 0x5d, 0xac, 0x5a, 0xc1, 0x5a, 0x85, 0x28, 0xb7, 0xb9, 0x4c, 0x17, 0x54 }, - { 0x96, 0x19, 0x72, 0x06, 0x25, 0xf1, 0x90, 0xb9, 0x3a, 0x3f, 0xad, 0x18, 0x6a, 0xb3, 0x14, 0x18, 0x96, 0x33, 0xc0, 0xd3, 0xa0, 0x1e, 0x6f, 0x9b, 0xc8, 0xc4, 0xa8, 0xf8, 0x2f, 0x38, 0x3d, 0xbf }, - { 0x7d, 0x62, 0x0d, 0x90, 0xfe, 0x69, 0xfa, 0x46, 0x9a, 0x65, 0x38, 0x38, 0x89, 0x70, 0xa1, 0xaa, 0x09, 0xbb, 0x48, 0xa2, 0xd5, 0x9b, 0x34, 0x7b, 0x97, 0xe8, 0xce, 0x71, 0xf4, 0x8c, 0x7f, 0x46 }, - { 0x29, 0x43, 0x83, 0x56, 0x85, 0x96, 0xfb, 0x37, 0xc7, 0x5b, 0xba, 0xcd, 0x97, 0x9c, 0x5f, 0xf6, 0xf2, 0x0a, 0x55, 0x6b, 0xf8, 0x87, 0x9c, 0xc7, 0x29, 0x24, 0x85, 0x5d, 0xf9, 0xb8, 0x24, 0x0e }, - { 0x16, 0xb1, 0x8a, 0xb3, 0x14, 0x35, 0x9c, 0x2b, 0x83, 0x3c, 0x1c, 0x69, 0x86, 0xd4, 0x8c, 0x55, 0xa9, 0xfc, 0x97, 0xcd, 0xe9, 0xa3, 0xc1, 0xf1, 0x0a, 0x31, 0x77, 0x14, 0x0f, 0x73, 0xf7, 0x38 }, - { 0x8c, 0xbb, 0xdd, 0x14, 0xbc, 0x33, 0xf0, 0x4c, 0xf4, 0x58, 0x13, 0xe4, 0xa1, 0x53, 0xa2, 0x73, 0xd3, 0x6a, 0xda, 0xd5, 0xce, 0x71, 0xf4, 0x99, 0xee, 0xb8, 0x7f, 0xb8, 0xac, 0x63, 0xb7, 0x29 }, - { 0x69, 0xc9, 0xa4, 0x98, 0xdb, 0x17, 0x4e, 0xca, 0xef, 0xcc, 0x5a, 0x3a, 0xc9, 0xfd, 0xed, 0xf0, 0xf8, 0x13, 0xa5, 0xbe, 0xc7, 0x27, 0xf1, 0xe7, 0x75, 0xba, 0xbd, 0xec, 0x77, 0x18, 0x81, 0x6e }, - { 0xb4, 0x62, 0xc3, 0xbe, 0x40, 0x44, 0x8f, 0x1d, 0x4f, 0x80, 0x62, 0x62, 0x54, 0xe5, 0x35, 0xb0, 0x8b, 0xc9, 0xcd, 0xcf, 0xf5, 0x99, 0xa7, 0x68, 0x57, 0x8d, 0x4b, 0x28, 0x81, 0xa8, 0xe3, 0xf0 }, - { 0x55, 0x3e, 0x9d, 0x9c, 0x5f, 0x36, 0x0a, 0xc0, 0xb7, 0x4a, 0x7d, 0x44, 0xe5, 0xa3, 0x91, 0xda, 0xd4, 0xce, 0xd0, 0x3e, 0x0c, 0x24, 0x18, 0x3b, 0x7e, 0x8e, 0xca, 0xbd, 0xf1, 0x71, 0x5a, 0x64 }, - { 0x7a, 0x7c, 0x55, 0xa5, 0x6f, 0xa9, 0xae, 0x51, 0xe6, 0x55, 0xe0, 0x19, 0x75, 0xd8, 0xa6, 0xff, 0x4a, 0xe9, 0xe4, 0xb4, 0x86, 0xfc, 0xbe, 0x4e, 0xac, 0x04, 0x45, 0x88, 0xf2, 0x45, 0xeb, 0xea }, - { 0x2a, 0xfd, 0xf3, 0xc8, 0x2a, 0xbc, 0x48, 0x67, 0xf5, 0xde, 0x11, 0x12, 0x86, 0xc2, 0xb3, 0xbe, 0x7d, 0x6e, 0x48, 0x65, 0x7b, 0xa9, 0x23, 0xcf, 0xbf, 0x10, 0x1a, 0x6d, 0xfc, 0xf9, 0xdb, 0x9a }, - { 0x41, 0x03, 0x7d, 0x2e, 0xdc, 0xdc, 0xe0, 0xc4, 0x9b, 0x7f, 0xb4, 0xa6, 0xaa, 0x09, 0x99, 0xca, 0x66, 0x97, 0x6c, 0x74, 0x83, 0xaf, 0xe6, 0x31, 0xd4, 0xed, 0xa2, 0x83, 0x14, 0x4f, 0x6d, 0xfc }, - { 0xc4, 0x46, 0x6f, 0x84, 0x97, 0xca, 0x2e, 0xeb, 0x45, 0x83, 0xa0, 0xb0, 0x8e, 0x9d, 0x9a, 0xc7, 0x43, 0x95, 0x70, 0x9f, 0xda, 0x10, 0x9d, 0x24, 0xf2, 0xe4, 0x46, 0x21, 0x96, 0x77, 0x9c, 0x5d }, - { 0x75, 0xf6, 0x09, 0x33, 0x8a, 0xa6, 0x7d, 0x96, 0x9a, 0x2a, 0xe2, 0xa2, 0x36, 0x2b, 0x2d, 0xa9, 0xd7, 0x7c, 0x69, 0x5d, 0xfd, 0x1d, 0xf7, 0x22, 0x4a, 0x69, 0x01, 0xdb, 0x93, 0x2c, 0x33, 0x64 }, - { 0x68, 0x60, 0x6c, 0xeb, 0x98, 0x9d, 0x54, 0x88, 0xfc, 0x7c, 0xf6, 0x49, 0xf3, 0xd7, 0xc2, 0x72, 0xef, 0x05, 0x5d, 0xa1, 0xa9, 0x3f, 0xae, 0xcd, 0x55, 0xfe, 0x06, 0xf6, 0x96, 0x70, 0x98, 0xca }, - { 0x44, 0x34, 0x6b, 0xde, 0xb7, 0xe0, 0x52, 0xf6, 0x25, 0x50, 0x48, 0xf0, 0xd9, 0xb4, 0x2c, 0x42, 0x5b, 0xab, 0x9c, 0x3d, 0xd2, 0x41, 0x68, 0x21, 0x2c, 0x3e, 0xcf, 0x1e, 0xbf, 0x34, 0xe6, 0xae }, - { 0x8e, 0x9c, 0xf6, 0xe1, 0xf3, 0x66, 0x47, 0x1f, 0x2a, 0xc7, 0xd2, 0xee, 0x9b, 0x5e, 0x62, 0x66, 0xfd, 0xa7, 0x1f, 0x8f, 0x2e, 0x41, 0x09, 0xf2, 0x23, 0x7e, 0xd5, 0xf8, 0x81, 0x3f, 0xc7, 0x18 }, - { 0x84, 0xbb, 0xeb, 0x84, 0x06, 0xd2, 0x50, 0x95, 0x1f, 0x8c, 0x1b, 0x3e, 0x86, 0xa7, 0xc0, 0x10, 0x08, 0x29, 0x21, 0x83, 0x3d, 0xfd, 0x95, 0x55, 0xa2, 0xf9, 0x09, 0xb1, 0x08, 0x6e, 0xb4, 0xb8 }, - { 0xee, 0x66, 0x6f, 0x3e, 0xef, 0x0f, 0x7e, 0x2a, 0x9c, 0x22, 0x29, 0x58, 0xc9, 0x7e, 0xaf, 0x35, 0xf5, 0x1c, 0xed, 0x39, 0x3d, 0x71, 0x44, 0x85, 0xab, 0x09, 0xa0, 0x69, 0x34, 0x0f, 0xdf, 0x88 }, - { 0xc1, 0x53, 0xd3, 0x4a, 0x65, 0xc4, 0x7b, 0x4a, 0x62, 0xc5, 0xca, 0xcf, 0x24, 0x01, 0x09, 0x75, 0xd0, 0x35, 0x6b, 0x2f, 0x32, 0xc8, 0xf5, 0xda, 0x53, 0x0d, 0x33, 0x88, 0x16, 0xad, 0x5d, 0xe6 }, - { 0x9f, 0xc5, 0x45, 0x01, 0x09, 0xe1, 0xb7, 0x79, 0xf6, 0xc7, 0xae, 0x79, 0xd5, 0x6c, 0x27, 0x63, 0x5c, 0x8d, 0xd4, 0x26, 0xc5, 0xa9, 0xd5, 0x4e, 0x25, 0x78, 0xdb, 0x98, 0x9b, 0x8c, 0x3b, 0x4e }, - { 0xd1, 0x2b, 0xf3, 0x73, 0x2e, 0xf4, 0xaf, 0x5c, 0x22, 0xfa, 0x90, 0x35, 0x6a, 0xf8, 0xfc, 0x50, 0xfc, 0xb4, 0x0f, 0x8f, 0x2e, 0xa5, 0xc8, 0x59, 0x47, 0x37, 0xa3, 0xb3, 0xd5, 0xab, 0xdb, 0xd7 }, - { 0x11, 0x03, 0x0b, 0x92, 0x89, 0xbb, 0xa5, 0xaf, 0x65, 0x26, 0x06, 0x72, 0xab, 0x6f, 0xee, 0x88, 0xb8, 0x74, 0x20, 0xac, 0xef, 0x4a, 0x17, 0x89, 0xa2, 0x07, 0x3b, 0x7e, 0xc2, 0xf2, 0xa0, 0x9e }, - { 0x69, 0xcb, 0x19, 0x2b, 0x84, 0x44, 0x00, 0x5c, 0x8c, 0x0c, 0xeb, 0x12, 0xc8, 0x46, 0x86, 0x07, 0x68, 0x18, 0x8c, 0xda, 0x0a, 0xec, 0x27, 0xa9, 0xc8, 0xa5, 0x5c, 0xde, 0xe2, 0x12, 0x36, 0x32 }, - { 0xdb, 0x44, 0x4c, 0x15, 0x59, 0x7b, 0x5f, 0x1a, 0x03, 0xd1, 0xf9, 0xed, 0xd1, 0x6e, 0x4a, 0x9f, 0x43, 0xa6, 0x67, 0xcc, 0x27, 0x51, 0x75, 0xdf, 0xa2, 0xb7, 0x04, 0xe3, 0xbb, 0x1a, 0x9b, 0x83 }, - { 0x3f, 0xb7, 0x35, 0x06, 0x1a, 0xbc, 0x51, 0x9d, 0xfe, 0x97, 0x9e, 0x54, 0xc1, 0xee, 0x5b, 0xfa, 0xd0, 0xa9, 0xd8, 0x58, 0xb3, 0x31, 0x5b, 0xad, 0x34, 0xbd, 0xe9, 0x99, 0xef, 0xd7, 0x24, 0xdd }, - }; - unsigned char inp[1000], out[1000]; - unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - unsigned long ilen, klen = sizeof(key), mlen = 32; - blake2smac_state st; - - for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; - - for (ilen = 0; ilen < 256; ilen++) { - const unsigned char *mac = tests[ilen]; - unsigned long olen = mlen; - /* process piece by piece */ - if (ilen > 15) { - blake2smac_init(&st, olen, key, klen); - blake2smac_process(&st, (unsigned char*)inp, 5); - blake2smac_process(&st, (unsigned char*)inp + 5, 4); - blake2smac_process(&st, (unsigned char*)inp + 9, 3); - blake2smac_process(&st, (unsigned char*)inp + 12, 2); - blake2smac_process(&st, (unsigned char*)inp + 14, 1); - blake2smac_process(&st, (unsigned char*)inp + 15, ilen - 15); - blake2smac_done(&st, out, &olen); - if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; - } - /* process in one go */ - blake2smac_init(&st, olen, key, klen); - blake2smac_process(&st, (unsigned char*)inp, ilen); - blake2smac_done(&st, out, &olen); - if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_done.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_done.c deleted file mode 100644 index 596a33b..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_done.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_done.c - f9 Support, terminate the state -*/ - -#ifdef LTC_F9_MODE - -/** Terminate the f9-MAC state - @param f9 f9 state to terminate - @param out [out] Destination for the MAC tag - @param outlen [in/out] Destination size and final tag size - Return CRYPT_OK on success -*/ -int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen) -{ - int err, x; - LTC_ARGCHK(f9 != NULL); - LTC_ARGCHK(out != NULL); - - /* check structure */ - if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { - return err; - } - - if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) || - (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { - return CRYPT_INVALID_ARG; - } - - if (f9->buflen != 0) { - /* encrypt */ - ecb_encrypt_block(f9->IV, f9->IV, &f9->key); - f9->buflen = 0; - for (x = 0; x < f9->blocksize; x++) { - f9->ACC[x] ^= f9->IV[x]; - } - } - - /* schedule modified key */ - if ((err = ecb_start(f9->cipher, f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) { - return err; - } - - /* encrypt the ACC */ - ecb_encrypt_block(f9->ACC, f9->ACC, &f9->key); - ecb_done(&f9->key); - - /* extract tag */ - for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) { - out[x] = f9->ACC[x]; - } - *outlen = x; - -#ifdef LTC_CLEAN_STACK - zeromem(f9, sizeof(*f9)); -#endif - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_file.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_file.c deleted file mode 100644 index c06f548..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_file.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_file.c - f9 support, process a file, Tom St Denis -*/ - -#ifdef LTC_F9_MODE - -/** - f9 a file - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param fname The name of the file you wish to f9 - @param out [out] Where the authentication tag is to be stored - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int f9_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *fname, - unsigned char *out, unsigned long *outlen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(cipher); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(fname); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(outlen); - return CRYPT_NOP; -#else - size_t x; - int err; - f9_state f9; - FILE *in; - unsigned char *buf; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = f9_done(&f9, out, outlen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&f9, sizeof(f9_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_init.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_init.c deleted file mode 100644 index 8a6e630..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_init.c +++ /dev/null @@ -1,63 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file f9_init.c - F9 Support, start an F9 state -*/ - -#ifdef LTC_F9_MODE - -/** Initialize F9-MAC state - @param f9 [out] f9 state to initialize - @param cipher Index of cipher to use - @param key [in] Secret key - @param keylen Length of secret key in octets - Return CRYPT_OK on success -*/ -int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen) -{ - int x, err; - - LTC_ARGCHK(f9 != NULL); - LTC_ARGCHK(key != NULL); - - /* schedule the key */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_FAST - if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - if ((err = ecb_start(cipher, key, keylen, 0, &f9->key)) != CRYPT_OK) { - goto done; - } - - /* make the second key */ - for (x = 0; (unsigned)x < keylen; x++) { - f9->akey[x] = key[x] ^ 0xAA; - } - - /* setup struct */ - zeromem(f9->IV, cipher_descriptor[cipher].block_length); - zeromem(f9->ACC, cipher_descriptor[cipher].block_length); - f9->blocksize = cipher_descriptor[cipher].block_length; - f9->cipher = cipher; - f9->buflen = 0; - f9->keylen = keylen; -done: - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory.c deleted file mode 100644 index 5f05209..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_process.c - f9 Support, Process a block through F9-MAC -*/ - -#ifdef LTC_F9_MODE - -/** f9-MAC a block of memory - @param cipher Index of cipher to use - @param key [in] Secret key - @param keylen Length of key in octets - @param in [in] Message to MAC - @param inlen Length of input in octets - @param out [out] Destination for the MAC tag - @param outlen [in/out] Output size and final tag size - Return CRYPT_OK on success. -*/ -int f9_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - f9_state *f9; - int err; - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* Use accelerator if found */ - if (cipher_descriptor[cipher].f9_memory != NULL) { - return cipher_descriptor[cipher].f9_memory(key, keylen, in, inlen, out, outlen); - } - - f9 = XCALLOC(1, sizeof(*f9)); - if (f9 == NULL) { - return CRYPT_MEM; - } - - if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { - goto done; - } - - if ((err = f9_process(f9, in, inlen)) != CRYPT_OK) { - goto done; - } - - err = f9_done(f9, out, outlen); -done: - XFREE(f9); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory_multi.c deleted file mode 100644 index 0357cd8..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_memory_multi.c +++ /dev/null @@ -1,77 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_memory_multi.c - f9 support, process multiple blocks of memory, Tom St Denis -*/ - -#ifdef LTC_F9_MODE - -/** - f9 multiple blocks of memory - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param out [out] The destination of the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag (octets) - @param in The data to send through f9 - @param inlen The length of the data to send through f9 (octets) - @param ... tuples of (data,len) pairs to f9, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int f9_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) -{ - int err; - f9_state *f9; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for f9 state */ - f9 = XMALLOC(sizeof(f9_state)); - if (f9 == NULL) { - return CRYPT_MEM; - } - - /* f9 process the message */ - if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - va_start(args, inlen); - curptr = in; - curlen = inlen; - for (;;) { - /* process buf */ - if ((err = f9_process(f9, curptr, curlen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - if ((err = f9_done(f9, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(f9, sizeof(f9_state)); -#endif - XFREE(f9); - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_process.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_process.c deleted file mode 100644 index 8860da3..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_process.c +++ /dev/null @@ -1,66 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_process.c - f9 Support, process blocks with f9 -*/ - -#ifdef LTC_F9_MODE - -/** Process data through f9-MAC - @param f9 The f9-MAC state - @param in Input data to process - @param inlen Length of input in octets - Return CRYPT_OK on success -*/ -int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen) -{ - int err, x; - - LTC_ARGCHK(f9 != NULL); - LTC_ARGCHK(in != NULL); - - /* check structure */ - if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { - return err; - } - - if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) || - (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (f9->buflen == 0) { - while (inlen >= (unsigned long)f9->blocksize) { - for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); - } - ecb_encrypt_block(f9->IV, f9->IV, &f9->key); - for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&(f9->ACC[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))); - } - in += f9->blocksize; - inlen -= f9->blocksize; - } - } -#endif - - while (inlen) { - if (f9->buflen == f9->blocksize) { - ecb_encrypt_block(f9->IV, f9->IV, &f9->key); - for (x = 0; x < f9->blocksize; x++) { - f9->ACC[x] ^= f9->IV[x]; - } - f9->buflen = 0; - } - f9->IV[f9->buflen++] ^= *in++; - --inlen; - } - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_test.c b/Sources/DataLiteC/libtomcrypt/mac/f9/f9_test.c deleted file mode 100644 index 2616d42..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/f9/f9_test.c +++ /dev/null @@ -1,66 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f9_test.c - f9 Support, Test F9 mode -*/ - -#ifdef LTC_F9_MODE - -/** Test f9-MAC mode - Return CRYPT_OK on success -*/ -int f9_test(void) -{ -#ifdef LTC_NO_TEST - return CRYPT_NOP; -#else - static const struct { - int msglen; - unsigned char K[16], M[128], T[4]; - } tests[] = { -{ - 20, - { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, - { 0x38, 0xA6, 0xF0, 0x56, 0xB8, 0xAE, 0xFD, 0xA9, 0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x61, 0x37, 0x34, 0x79, 0x40 }, - { 0x46, 0xE0, 0x0D, 0x4B } -}, - -{ - 105, - { 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3, 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35 }, - { 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2, - 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB, 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11, 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39, 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39, - 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5, 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF, 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1, 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72, - 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF, 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF, 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6, 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A, - 0x40|0x80 }, - { 0x95, 0xAE, 0x41, 0xBA }, -} -}; - unsigned char T[16]; - unsigned long taglen; - int err, x, idx; - - /* find kasumi */ - if ((idx = find_cipher("kasumi")) == -1) { - return CRYPT_NOP; - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - taglen = 4; - if ((err = f9_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { - return err; - } - if (compare_testvector(T, taglen, tests[x].T, 4, "F9", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - return CRYPT_OK; -#endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_done.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_done.c deleted file mode 100644 index a3d3c38..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_done.c +++ /dev/null @@ -1,96 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_done.c - HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize - -/** - Terminate an HMAC session - @param hmac The HMAC state - @param out [out] The destination of the HMAC authentication tag - @param outlen [in/out] The max size and resulting size of the HMAC authentication tag - @return CRYPT_OK if successful -*/ -int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) -{ - unsigned char *buf, *isha; - unsigned long hashsize, i; - int hash, err; - - LTC_ARGCHK(hmac != NULL); - LTC_ARGCHK(out != NULL); - - /* test hash */ - hash = hmac->hash; - if((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - /* get the hash message digest size */ - hashsize = hash_descriptor[hash].hashsize; - - /* allocate buffers */ - buf = XMALLOC(LTC_HMAC_BLOCKSIZE); - isha = XMALLOC(hashsize); - if (buf == NULL || isha == NULL) { - if (buf != NULL) { - XFREE(buf); - } - if (isha != NULL) { - XFREE(isha); - } - return CRYPT_MEM; - } - - /* Get the hash of the first HMAC vector plus the data */ - if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* Create the second HMAC vector vector for step (3) */ - for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { - buf[i] = hmac->key[i] ^ 0x5C; - } - - /* Now calculate the "outer" hash for step (5), (6), and (7) */ - if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* copy to output */ - for (i = 0; i < hashsize && i < *outlen; i++) { - out[i] = buf[i]; - } - *outlen = i; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(isha, hashsize); - zeromem(buf, hashsize); - zeromem(hmac, sizeof(*hmac)); -#endif - - XFREE(isha); - XFREE(buf); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_file.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_file.c deleted file mode 100644 index c944a28..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_file.c +++ /dev/null @@ -1,90 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_file.c - HMAC support, process a file, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -/** - HMAC a file - @param hash The index of the hash you wish to use - @param fname The name of the file you wish to HMAC - @param key The secret key - @param keylen The length of the secret key - @param out [out] The HMAC authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int hmac_file(int hash, const char *fname, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(hash); - LTC_UNUSED_PARAM(fname); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(outlen); - return CRYPT_NOP; -#else - hmac_state hmac; - FILE *in; - unsigned char *buf; - size_t x; - int err; - - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); /* we don't trap this error since we're already returning an error! */ - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = hmac_done(&hmac, out, outlen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&hmac, sizeof(hmac_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_init.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_init.c deleted file mode 100644 index 50c5bcc..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_init.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_init.c - HMAC support, initialize state, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize - -/** - Initialize an HMAC context. - @param hmac The HMAC state - @param hash The index of the hash you want to use - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) -{ - unsigned char *buf; - unsigned long hashsize; - unsigned long i, z; - int err; - - LTC_ARGCHK(hmac != NULL); - LTC_ARGCHK(key != NULL); - - /* valid hash? */ - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - hmac->hash = hash; - hashsize = hash_descriptor[hash].hashsize; - - /* valid key length? */ - if (keylen == 0) { - return CRYPT_INVALID_KEYSIZE; - } - - /* allocate ram for buf */ - buf = XMALLOC(LTC_HMAC_BLOCKSIZE); - if (buf == NULL) { - return CRYPT_MEM; - } - - /* check hash block fits */ - if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) { - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* (1) make sure we have a large enough key */ - if(keylen > LTC_HMAC_BLOCKSIZE) { - z = LTC_HMAC_BLOCKSIZE; - if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - keylen = hashsize; - } else { - XMEMCPY(hmac->key, key, (size_t)keylen); - } - - if(keylen < LTC_HMAC_BLOCKSIZE) { - zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); - } - - /* Create the initialization vector for step (3) */ - for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { - buf[i] = hmac->key[i] ^ 0x36; - } - - /* Pre-pend that to the hash data */ - if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { - goto LBL_ERR; - } - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf, LTC_HMAC_BLOCKSIZE); -#endif - - XFREE(buf); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory.c deleted file mode 100644 index 221be58..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory.c +++ /dev/null @@ -1,76 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_memory.c - HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -/** - HMAC a block of memory to produce the authentication tag - @param hash The index of the hash to use - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data to HMAC - @param inlen The length of the data to HMAC (octets) - @param out [out] Destination of the authentication tag - @param outlen [in/out] Max size and resulting size of authentication tag - @return CRYPT_OK if successful -*/ -int hmac_memory(int hash, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - hmac_state *hmac; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* make sure hash descriptor is valid */ - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - /* is there a descriptor? */ - if (hash_descriptor[hash].hmac_block != NULL) { - return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); - } - - /* nope, so call the hmac functions */ - /* allocate ram for hmac state */ - hmac = XMALLOC(sizeof(hmac_state)); - if (hmac == NULL) { - return CRYPT_MEM; - } - - if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(hmac, sizeof(hmac_state)); -#endif - - XFREE(hmac); - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory_multi.c deleted file mode 100644 index b8a253e..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_memory_multi.c +++ /dev/null @@ -1,79 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_memory_multi.c - HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -/** - HMAC multiple blocks of memory to produce the authentication tag - @param hash The index of the hash to use - @param key The secret key - @param keylen The length of the secret key (octets) - @param out [out] Destination of the authentication tag - @param outlen [in/out] Max size and resulting size of authentication tag - @param in The data to HMAC - @param inlen The length of the data to HMAC (octets) - @param ... tuples of (data,len) pairs to HMAC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int hmac_memory_multi(int hash, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) - -{ - hmac_state *hmac; - int err; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for hmac state */ - hmac = XMALLOC(sizeof(hmac_state)); - if (hmac == NULL) { - return CRYPT_MEM; - } - - if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - va_start(args, inlen); - curptr = in; - curlen = inlen; - for (;;) { - /* process buf */ - if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(hmac, sizeof(hmac_state)); -#endif - XFREE(hmac); - va_end(args); - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_process.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_process.c deleted file mode 100644 index 14738b6..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_process.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_process.c - HMAC support, process data, Tom St Denis/Dobes Vandermeer -*/ - -#ifdef LTC_HMAC - -/** - Process data through HMAC - @param hmac The hmac state - @param in The data to send through HMAC - @param inlen The length of the data to HMAC (octets) - @return CRYPT_OK if successful -*/ -int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) -{ - int err; - LTC_ARGCHK(hmac != NULL); - LTC_ARGCHK(in != NULL); - if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { - return err; - } - return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_test.c b/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_test.c deleted file mode 100644 index b097003..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/hmac/hmac_test.c +++ /dev/null @@ -1,618 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hmac_test.c - HMAC support, self-test, Tom St Denis/Dobes Vandermeer/Steffen Jaeckel -*/ - -#ifdef LTC_HMAC - -/* - TEST CASES SOURCE: - -Network Working Group P. Cheng -Request for Comments: 2202 IBM -Category: Informational R. Glenn - NIST - September 1997 - - Test Cases for HMAC-MD5 and HMAC-SHA-1 - -******************************************************************************* - -Network Working Group J. Kapp -Request for Comments: 2286 Reaper Technologies -Category: Informational February 1998 - - Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128 - -******************************************************************************* - -Network Working Group M. Nystrom -Request for Comments: 4231 RSA Security -Category: Standards Track December 2005 - - Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256, - HMAC-SHA-384, and HMAC-SHA-512 -*/ - -/** - HMAC self-test - @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. -*/ -int hmac_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - unsigned char digest[MAXBLOCKSIZE]; - int i; - - static const unsigned char hmac_test_case_keys[][136] = { - { /* 1 */ - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b - }, -#ifdef LTC_TEST_EXT - { /* 2 */ - 0x4a, 0x65, 0x66, 0x65 - }, - { /* 4 */ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19 - }, - { /* 5 */ - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c - }, - { /* 3, 6, 7 */ - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa - } -#endif /* LTC_TEST_EXT */ - }; - - - static const unsigned char hmac_test_case_data[][153] = { - { - "Hi There" - }, -#ifdef LTC_TEST_EXT - { - "what do ya want for nothing?" - }, - { - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd - }, - { - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd - }, - { - "Test With Truncation" - }, - { - "Test Using Larger Than Block-Size Key - Hash Key First" - }, - { - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" - }, - { - "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." - } -#endif /* LTC_TEST_EXT */ - }; - - static const struct hmac_test_case { - const char *num; - const char *algo; - const unsigned char *key; - unsigned long keylen; - const unsigned char *data; - unsigned long datalen; - unsigned char digest[MAXBLOCKSIZE]; - } cases[] = { - /* - RFC 2202 3. Test Cases for HMAC-SHA-1 - */ - { "rfc2202 3.1", "sha1", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, - 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, - 0xf1, 0x46, 0xbe, 0x00} }, - -#ifdef LTC_TEST_EXT - { "rfc2202 3.2", "sha1", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, - 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, - 0x25, 0x9a, 0x7c, 0x79} }, - - { "rfc2202 3.3", "sha1", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, - 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, - 0x63, 0xf1, 0x75, 0xd3} }, - - { "rfc2202 3.4", "sha1", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, - 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, - 0x2d, 0x72, 0x35, 0xda} }, - - { "rfc2202 3.5", "sha1", - hmac_test_case_keys[3], 20, - hmac_test_case_data[4], 20, - {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, - 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, - - { "rfc2202 3.6", "sha1", - hmac_test_case_keys[4], 80, - hmac_test_case_data[5], 54, - {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, - 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, - 0xed, 0x40, 0x21, 0x12} }, - - { "rfc2202 3.7", "sha1", - hmac_test_case_keys[4], 80, - hmac_test_case_data[6], 73, - {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, - 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, -#endif /* LTC_TEST_EXT */ - - /* - RFC 2202 2. Test Cases for HMAC-MD5 - */ - { "rfc2202 2.1", "md5", - hmac_test_case_keys[0], 16, - hmac_test_case_data[0], 8, - {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, - 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, - -#ifdef LTC_TEST_EXT - { "rfc2202 2.2", "md5", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, - 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, - - { "rfc2202 2.3", "md5", - hmac_test_case_keys[4], 16, - hmac_test_case_data[2], 50, - {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, - 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, - - { "rfc2202 2.4", "md5", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, - 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, - - { "rfc2202 2.5", "md5", - hmac_test_case_keys[3], 16, - hmac_test_case_data[4], 20, - {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, - 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, - - { "rfc2202 2.6", "md5", - hmac_test_case_keys[4], 80, - hmac_test_case_data[5], 54, - {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, - 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, - - { "rfc2202 2.7", "md5", - hmac_test_case_keys[4], 80, - hmac_test_case_data[6], 73, - {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, - 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }, -#endif /* LTC_TEST_EXT */ - - /* - RFC 2286 2. Test Cases for HMAC-RIPEMD160 - */ - { "rfc2286 2.1", "rmd160", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0x24, 0xcb, 0x4b, 0xd6, 0x7d, 0x20, 0xfc, 0x1a, - 0x5d, 0x2e, 0xd7, 0x73, 0x2d, 0xcc, 0x39, 0x37, - 0x7f, 0x0a, 0x56, 0x68} }, - -#ifdef LTC_TEST_EXT - { "rfc2286 2.2", "rmd160", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0xdd, 0xa6, 0xc0, 0x21, 0x3a, 0x48, 0x5a, 0x9e, - 0x24, 0xf4, 0x74, 0x20, 0x64, 0xa7, 0xf0, 0x33, - 0xb4, 0x3c, 0x40, 0x69} }, - - { "rfc2286 2.3", "rmd160", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0xb0, 0xb1, 0x05, 0x36, 0x0d, 0xe7, 0x59, 0x96, - 0x0a, 0xb4, 0xf3, 0x52, 0x98, 0xe1, 0x16, 0xe2, - 0x95, 0xd8, 0xe7, 0xc1} }, - - { "rfc2286 2.4", "rmd160", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0xd5, 0xca, 0x86, 0x2f, 0x4d, 0x21, 0xd5, 0xe6, - 0x10, 0xe1, 0x8b, 0x4c, 0xf1, 0xbe, 0xb9, 0x7a, - 0x43, 0x65, 0xec, 0xf4} }, - - { "rfc2286 2.5", "rmd160", - hmac_test_case_keys[3], 20, - hmac_test_case_data[4], 20, - {0x76, 0x19, 0x69, 0x39, 0x78, 0xf9, 0x1d, 0x90, - 0x53, 0x9a, 0xe7, 0x86, 0x50, 0x0f, 0xf3, 0xd8, - 0xe0, 0x51, 0x8e, 0x39} }, - - { "rfc2286 2.6", "rmd160", - hmac_test_case_keys[4], 80, - hmac_test_case_data[5], 54, - {0x64, 0x66, 0xca, 0x07, 0xac, 0x5e, 0xac, 0x29, - 0xe1, 0xbd, 0x52, 0x3e, 0x5a, 0xda, 0x76, 0x05, - 0xb7, 0x91, 0xfd, 0x8b} }, - - { "rfc2286 2.7", "rmd160", - hmac_test_case_keys[4], 80, - hmac_test_case_data[6], 73, - {0x69, 0xea, 0x60, 0x79, 0x8d, 0x71, 0x61, 0x6c, - 0xce, 0x5f, 0xd0, 0x87, 0x1e, 0x23, 0x75, 0x4c, - 0xd7, 0x5d, 0x5a, 0x0a} }, -#endif /* LTC_TEST_EXT */ - - /* - RFC 2286 3. Test Cases for HMAC-RIPEMD128 - */ - { "rfc2286 3.1", "rmd128", - hmac_test_case_keys[0], 16, - hmac_test_case_data[0], 8, - {0xfb, 0xf6, 0x1f, 0x94, 0x92, 0xaa, 0x4b, 0xbf, - 0x81, 0xc1, 0x72, 0xe8, 0x4e, 0x07, 0x34, 0xdb} }, - -#ifdef LTC_TEST_EXT - { "rfc2286 3.2", "rmd128", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0x87, 0x5f, 0x82, 0x88, 0x62, 0xb6, 0xb3, 0x34, - 0xb4, 0x27, 0xc5, 0x5f, 0x9f, 0x7f, 0xf0, 0x9b} }, - - { "rfc2286 3.3", "rmd128", - hmac_test_case_keys[4], 16, - hmac_test_case_data[2], 50, - {0x09, 0xf0, 0xb2, 0x84, 0x6d, 0x2f, 0x54, 0x3d, - 0xa3, 0x63, 0xcb, 0xec, 0x8d, 0x62, 0xa3, 0x8d} }, - - { "rfc2286 3.4", "rmd128", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0xbd, 0xbb, 0xd7, 0xcf, 0x03, 0xe4, 0x4b, 0x5a, - 0xa6, 0x0a, 0xf8, 0x15, 0xbe, 0x4d, 0x22, 0x94} }, - - { "rfc2286 3.5", "rmd128", - hmac_test_case_keys[3], 16, - hmac_test_case_data[4], 20, - {0xe7, 0x98, 0x08, 0xf2, 0x4b, 0x25, 0xfd, 0x03, - 0x1c, 0x15, 0x5f, 0x0d, 0x55, 0x1d, 0x9a, 0x3a} }, - - { "rfc2286 3.6", "rmd128", - hmac_test_case_keys[4], 80, - hmac_test_case_data[5], 54, - {0xdc, 0x73, 0x29, 0x28, 0xde, 0x98, 0x10, 0x4a, - 0x1f, 0x59, 0xd3, 0x73, 0xc1, 0x50, 0xac, 0xbb} }, - - { "rfc2286 3.7", "rmd128", - hmac_test_case_keys[4], 80, - hmac_test_case_data[6], 73, - {0x5c, 0x6b, 0xec, 0x96, 0x79, 0x3e, 0x16, 0xd4, - 0x06, 0x90, 0xc2, 0x37, 0x63, 0x5f, 0x30, 0xc5} }, -#endif /* LTC_TEST_EXT */ - - /* - RFC 4231 4. Test Vectors - Ch. 4.6 with truncated output left out to simplify tests - */ - { "rfc4231 4.2", "sha224", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, - 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, - 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, - 0x53, 0x68, 0x4b, 0x22} }, - -#ifdef LTC_TEST_EXT - { "rfc4231 4.3", "sha224", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, - 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, - 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, - 0x8f, 0xd0, 0x5e, 0x44} }, - - { "rfc4231 4.4", "sha224", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, - 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, - 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, - 0xec, 0x83, 0x33, 0xea} }, - - { "rfc4231 4.5", "sha224", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, - 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, - 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, - 0xe7, 0xaf, 0xec, 0x5a} }, - - { "rfc4231 4.7", "sha224", - hmac_test_case_keys[4], 131, - hmac_test_case_data[5], 54, - {0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, - 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, - 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, - 0x3f, 0xa6, 0x87, 0x0e} }, - - { "rfc4231 4.8", "sha224", - hmac_test_case_keys[4], 131, - hmac_test_case_data[7], 152, - {0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, - 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, - 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, - 0xf6, 0xf5, 0x65, 0xd1} }, -#endif /* LTC_TEST_EXT */ - - { "rfc4231 4.2", "sha256", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, - 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, - 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, - 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7} }, - -#ifdef LTC_TEST_EXT - { "rfc4231 4.3", "sha256", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, - 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, - 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, - 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43} }, - - { "rfc4231 4.4", "sha256", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, - 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, - 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, - 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe} }, - - { "rfc4231 4.5", "sha256", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, - 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, - 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, - 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b} }, - - { "rfc4231 4.7", "sha256", - hmac_test_case_keys[4], 131, - hmac_test_case_data[5], 54, - {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, - 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, - 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, - 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54} }, - - { "rfc4231 4.8", "sha256", - hmac_test_case_keys[4], 131, - hmac_test_case_data[7], 152, - {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, - 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, - 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, - 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }, -#endif /* LTC_TEST_EXT */ - - { "rfc4231 4.2", "sha384", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, - 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, - 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, - 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, - 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, - 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6} }, - -#ifdef LTC_TEST_EXT - { "rfc4231 4.3", "sha384", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, - 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, - 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, - 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, - 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, - 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49} }, - - { "rfc4231 4.4", "sha384", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, - 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, - 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, - 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, - 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, - 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27} }, - - { "rfc4231 4.5", "sha384", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, - 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, - 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, - 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, - 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, - 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb} }, - - { "rfc4231 4.7", "sha384", - hmac_test_case_keys[4], 131, - hmac_test_case_data[5], 54, - {0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, - 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, - 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, - 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, - 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, - 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52} }, - - { "rfc4231 4.8", "sha384", - hmac_test_case_keys[4], 131, - hmac_test_case_data[7], 152, - {0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, - 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, - 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, - 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, - 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, - 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e} }, -#endif /* LTC_TEST_EXT */ - - { "rfc4231 4.2", "sha512", - hmac_test_case_keys[0], 20, - hmac_test_case_data[0], 8, - {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, - 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, - 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, - 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, - 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, - 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, - 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, - 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54} }, - -#ifdef LTC_TEST_EXT - { "rfc4231 4.3", "sha512", - hmac_test_case_keys[1], 4, - hmac_test_case_data[1], 28, - {0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, - 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, - 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, - 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, - 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, - 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, - 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, - 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37} }, - - { "rfc4231 4.4", "sha512", - hmac_test_case_keys[4], 20, - hmac_test_case_data[2], 50, - {0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, - 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, - 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, - 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, - 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, - 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, - 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, - 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb} }, - - { "rfc4231 4.5", "sha512", - hmac_test_case_keys[2], 25, - hmac_test_case_data[3], 50, - {0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, - 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, - 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, - 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, - 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, - 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, - 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, - 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd} }, - - { "rfc4231 4.7", "sha512", - hmac_test_case_keys[4], 131, - hmac_test_case_data[5], 54, - {0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, - 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, - 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, - 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, - 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, - 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, - 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, - 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98} }, - - { "rfc4231 4.8", "sha512", - hmac_test_case_keys[4], 131, - hmac_test_case_data[7], 152, - {0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, - 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, - 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, - 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, - 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, - 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, - 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, - 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} }, -#endif /* LTC_TEST_EXT */ - - }; - - unsigned long outlen; - int err; - int tested=0,failed=0; - for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { - int hash = find_hash(cases[i].algo); - if (hash == -1) continue; - ++tested; - outlen = sizeof(digest); - if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { -#ifdef LTC_TEST_DBG - printf("HMAC-%s test %s, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); -#endif - return err; - } - - if(compare_testvector(digest, outlen, cases[i].digest, (size_t)hash_descriptor[hash].hashsize, cases[i].num, i)) { - failed++; - } - } - - if (failed != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - if (tested == 0) { - return CRYPT_NOP; - } - return CRYPT_OK; - #endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_done.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_done.c deleted file mode 100644 index 7997d7a..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_done.c +++ /dev/null @@ -1,71 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_done.c - OMAC1 support, terminate a stream, Tom St Denis -*/ - -#ifdef LTC_OMAC - -/** - Terminate an OMAC stream - @param omac The OMAC state - @param out [out] Destination for the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen) -{ - int err, mode; - unsigned x; - - LTC_ARGCHK(omac != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || - (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { - return CRYPT_INVALID_ARG; - } - - /* figure out mode */ - if (omac->buflen != omac->blklen) { - /* add the 0x80 byte */ - omac->block[omac->buflen++] = 0x80; - - /* pad with 0x00 */ - while (omac->buflen < omac->blklen) { - omac->block[omac->buflen++] = 0x00; - } - mode = 1; - } else { - mode = 0; - } - - /* now xor prev + Lu[mode] */ - for (x = 0; x < (unsigned)omac->blklen; x++) { - omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x]; - } - - /* encrypt it */ - if ((err = ecb_encrypt_block(omac->block, omac->block, &omac->key)) != CRYPT_OK) { - return err; - } - ecb_done(&omac->key); - - /* output it */ - for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) { - out[x] = omac->block[x]; - } - *outlen = x; - -#ifdef LTC_CLEAN_STACK - zeromem(omac, sizeof(*omac)); -#endif - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_file.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_file.c deleted file mode 100644 index 012958a..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_file.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_file.c - OMAC1 support, process a file, Tom St Denis -*/ - -#ifdef LTC_OMAC - -/** - OMAC a file - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param filename The name of the file you wish to OMAC - @param out [out] Where the authentication tag is to be stored - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int omac_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(cipher); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(filename); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(outlen); - return CRYPT_NOP; -#else - size_t x; - int err; - omac_state omac; - FILE *in; - unsigned char *buf; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(filename != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(filename, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = omac_done(&omac, out, outlen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&omac, sizeof(omac_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_init.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_init.c deleted file mode 100644 index f2e9857..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_init.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file omac_init.c - OMAC1 support, initialize state, by Tom St Denis -*/ - - -#ifdef LTC_OMAC - -/** - Initialize an OMAC state - @param omac The OMAC state to initialize - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) -{ - int err, x, y, mask, msb, len; - - LTC_ARGCHK(omac != NULL); - LTC_ARGCHK(key != NULL); - - /* schedule the key */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_FAST - if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* now setup the system */ - switch (cipher_descriptor[cipher].block_length) { - case 8: mask = 0x1B; - len = 8; - break; - case 16: mask = 0x87; - len = 16; - break; - default: return CRYPT_INVALID_ARG; - } - - if ((err = ecb_start(cipher, key, keylen, 0, &omac->key)) != CRYPT_OK) { - return err; - } - - /* ok now we need Lu and Lu^2 [calc one from the other] */ - - /* first calc L which is Ek(0) */ - zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length); - if ((err = ecb_encrypt_block(omac->Lu[0], omac->Lu[0], &omac->key)) != CRYPT_OK) { - return err; - } - - /* now do the mults, whoopy! */ - for (x = 0; x < 2; x++) { - /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ - msb = omac->Lu[x][0] >> 7; - - /* shift left */ - for (y = 0; y < (len - 1); y++) { - omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; - } - omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; - - /* copy up as require */ - if (x == 0) { - XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); - } - } - - /* setup state */ - omac->buflen = 0; - omac->blklen = len; - zeromem(omac->prev, sizeof(omac->prev)); - zeromem(omac->block, sizeof(omac->block)); - - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory.c deleted file mode 100644 index 56ac137..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_memory.c - OMAC1 support, process a block of memory, Tom St Denis -*/ - -#ifdef LTC_OMAC - -/** - OMAC a block of memory - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data to send through OMAC - @param inlen The length of the data to send through OMAC (octets) - @param out [out] The destination of the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag (octets) - @return CRYPT_OK if successful -*/ -int omac_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - int err; - omac_state *omac; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* Use accelerator if found */ - if (cipher_descriptor[cipher].omac_memory != NULL) { - return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen); - } - - /* allocate ram for omac state */ - omac = XMALLOC(sizeof(omac_state)); - if (omac == NULL) { - return CRYPT_MEM; - } - - /* omac process the message */ - if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(omac, sizeof(omac_state)); -#endif - - XFREE(omac); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory_multi.c deleted file mode 100644 index 94d4cba..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_memory_multi.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_memory_multi.c - OMAC1 support, process multiple blocks of memory, Tom St Denis -*/ - -#ifdef LTC_OMAC - -static LTC_INLINE int s_omac_vprocess(omac_state *omac, const unsigned char *in, unsigned long inlen, va_list args) -{ - const unsigned char * curptr = in; - unsigned long curlen = inlen; - int err; - for (;;) { - /* process buf */ - if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) { - return err; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - return CRYPT_OK; -} - -int omac_vprocess(omac_state *omac, const unsigned char *in, unsigned long inlen, va_list args) -{ - return s_omac_vprocess(omac, in, inlen, args); -} - -/** - OMAC multiple blocks of memory - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param out [out] The destination of the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag (octets) - @param in The data to send through OMAC - @param inlen The length of the data to send through OMAC (octets) - @param ... tuples of (data,len) pairs to OMAC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int omac_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) -{ - int err; - omac_state *omac; - va_list args; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for omac state */ - omac = XMALLOC(sizeof(omac_state)); - if (omac == NULL) { - return CRYPT_MEM; - } - - /* omac process the message */ - if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - va_start(args, inlen); - if ((err = s_omac_vprocess(omac, in, inlen, args)) != CRYPT_OK) { - goto LBL_ERR; - } - err = omac_done(omac, out, outlen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(omac, sizeof(omac_state)); -#endif - XFREE(omac); - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_process.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_process.c deleted file mode 100644 index 35ee9d2..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_process.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_process.c - OMAC1 support, process data, Tom St Denis -*/ - - -#ifdef LTC_OMAC - -/** - Process data through OMAC - @param omac The OMAC state - @param in The input data to send through OMAC - @param inlen The length of the input (octets) - @return CRYPT_OK if successful -*/ -int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) -{ - unsigned long n, x; - int err; - - LTC_ARGCHK(omac != NULL); - LTC_ARGCHK(in != NULL); - - if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || - (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (omac->buflen == 0 && inlen > (unsigned long)omac->blklen) { - for (x = 0; x < (inlen - omac->blklen); x += omac->blklen) { - for (n = 0; n < (unsigned long)omac->blklen; n += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&omac->prev[n])) ^= *(LTC_FAST_TYPE_PTR_CAST(&in[n])); - } - in += omac->blklen; - if ((err = ecb_encrypt_block(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) { - return err; - } - } - inlen -= x; - } -#endif - - while (inlen != 0) { - /* ok if the block is full we xor in prev, encrypt and replace prev */ - if (omac->buflen == omac->blklen) { - for (x = 0; x < (unsigned long)omac->blklen; x++) { - omac->block[x] ^= omac->prev[x]; - } - if ((err = ecb_encrypt_block(omac->block, omac->prev, &omac->key)) != CRYPT_OK) { - return err; - } - omac->buflen = 0; - } - - /* add bytes */ - n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen)); - XMEMCPY(omac->block + omac->buflen, in, n); - omac->buflen += n; - inlen -= n; - in += n; - } - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_test.c b/Sources/DataLiteC/libtomcrypt/mac/omac/omac_test.c deleted file mode 100644 index c797794..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/omac/omac_test.c +++ /dev/null @@ -1,93 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file omac_test.c - OMAC1 support, self-test, by Tom St Denis -*/ - -#ifdef LTC_OMAC - -/** - Test the OMAC setup - @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled -*/ -int omac_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct { - int keylen, msglen; - unsigned char key[16], msg[64], tag[16]; - } tests[] = { - { 16, 0, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x00 }, - { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } - }, - { 16, 16, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, - { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } - }, - { 16, 40, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, - { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, - 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } - }, - { 16, 64, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, - { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } - } - - }; - unsigned char out[16]; - int x, err, idx; - unsigned long len; - - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - len = sizeof(out); - if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(out, len, tests[x].tag, sizeof(tests[x].tag), "OMAC", x) != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican.c b/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican.c deleted file mode 100644 index 62814ec..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican.c +++ /dev/null @@ -1,162 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pelican.c - Pelican MAC, initialize state, by Tom St Denis -*/ - -#ifdef LTC_PELICAN - -#ifndef LTC_AES_TAB_C -#define LTC_AES_TAB_C -#define ENCRYPT_ONLY -#define PELI_TAB -#include "../../ciphers/aes/aes_tab.c" -#endif - -/** - Initialize a Pelican state - @param pelmac The Pelican state to initialize - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen) -{ - int err; - - LTC_ARGCHK(pelmac != NULL); - LTC_ARGCHK(key != NULL); - -#ifdef LTC_FAST - if (16 % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) { - return err; - } - - zeromem(pelmac->state, 16); - aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K); - pelmac->buflen = 0; - - return CRYPT_OK; -} - -static void s_four_rounds(pelican_state *pelmac) -{ - ulong32 s0, s1, s2, s3, t0, t1, t2, t3; - int r; - - LOAD32H(s0, pelmac->state ); - LOAD32H(s1, pelmac->state + 4); - LOAD32H(s2, pelmac->state + 8); - LOAD32H(s3, pelmac->state + 12); - for (r = 0; r < 4; r++) { - t0 = - Te0(LTC_BYTE(s0, 3)) ^ - Te1(LTC_BYTE(s1, 2)) ^ - Te2(LTC_BYTE(s2, 1)) ^ - Te3(LTC_BYTE(s3, 0)); - t1 = - Te0(LTC_BYTE(s1, 3)) ^ - Te1(LTC_BYTE(s2, 2)) ^ - Te2(LTC_BYTE(s3, 1)) ^ - Te3(LTC_BYTE(s0, 0)); - t2 = - Te0(LTC_BYTE(s2, 3)) ^ - Te1(LTC_BYTE(s3, 2)) ^ - Te2(LTC_BYTE(s0, 1)) ^ - Te3(LTC_BYTE(s1, 0)); - t3 = - Te0(LTC_BYTE(s3, 3)) ^ - Te1(LTC_BYTE(s0, 2)) ^ - Te2(LTC_BYTE(s1, 1)) ^ - Te3(LTC_BYTE(s2, 0)); - s0 = t0; s1 = t1; s2 = t2; s3 = t3; - } - STORE32H(s0, pelmac->state ); - STORE32H(s1, pelmac->state + 4); - STORE32H(s2, pelmac->state + 8); - STORE32H(s3, pelmac->state + 12); -} - -/** - Process a block of text through Pelican - @param pelmac The Pelican MAC state - @param in The input - @param inlen The length input (octets) - @return CRYPT_OK on success - */ -int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen) -{ - - LTC_ARGCHK(pelmac != NULL); - LTC_ARGCHK(in != NULL); - - /* check range */ - if (pelmac->buflen < 0 || pelmac->buflen > 15) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (pelmac->buflen == 0) { - while (inlen & ~15) { - int x; - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x)); - } - s_four_rounds(pelmac); - in += 16; - inlen -= 16; - } - } -#endif - - while (inlen--) { - pelmac->state[pelmac->buflen++] ^= *in++; - if (pelmac->buflen == 16) { - s_four_rounds(pelmac); - pelmac->buflen = 0; - } - } - return CRYPT_OK; -} - -/** - Terminate Pelican MAC - @param pelmac The Pelican MAC state - @param out [out] The TAG - @return CRYPT_OK on sucess -*/ -int pelican_done(pelican_state *pelmac, unsigned char *out) -{ - LTC_ARGCHK(pelmac != NULL); - LTC_ARGCHK(out != NULL); - - /* check range */ - if (pelmac->buflen < 0 || pelmac->buflen > 16) { - return CRYPT_INVALID_ARG; - } - - if (pelmac->buflen == 16) { - s_four_rounds(pelmac); - pelmac->buflen = 0; - } - pelmac->state[pelmac->buflen++] ^= 0x80; - aes_ecb_encrypt(pelmac->state, out, &pelmac->K); - aes_done(&pelmac->K); - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_memory.c b/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_memory.c deleted file mode 100644 index f67eaee..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_memory.c +++ /dev/null @@ -1,47 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pelican_memory.c - Pelican MAC, MAC a block of memory, by Tom St Denis -*/ - -#ifdef LTC_PELICAN - -/** - Pelican block of memory - @param key The key for the MAC - @param keylen The length of the key (octets) - @param in The input to MAC - @param inlen The length of the input (octets) - @param out [out] The output TAG - @return CRYPT_OK on success -*/ -int pelican_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out) -{ - pelican_state *pel; - int err; - - pel = XMALLOC(sizeof(*pel)); - if (pel == NULL) { - return CRYPT_MEM; - } - - if ((err = pelican_init(pel, key, keylen)) != CRYPT_OK) { - XFREE(pel); - return err; - } - if ((err = pelican_process(pel, in ,inlen)) != CRYPT_OK) { - XFREE(pel); - return err; - } - err = pelican_done(pel, out); - XFREE(pel); - return err; -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_test.c b/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_test.c deleted file mode 100644 index 31a237c..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pelican/pelican_test.c +++ /dev/null @@ -1,103 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pelican_test.c - Pelican MAC, test, by Tom St Denis -*/ - -#ifdef LTC_PELICAN - -int pelican_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char K[32], MSG[64], T[16]; - int keylen, ptlen; - } tests[] = { -/* K=16, M=0 */ -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0 }, - { 0xeb, 0x58, 0x37, 0x15, 0xf8, 0x34, 0xde, 0xe5, - 0xa4, 0xd1, 0x6e, 0xe4, 0xb9, 0xd7, 0x76, 0x0e, }, - 16, 0 -}, - -/* K=16, M=3 */ -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0x00, 0x01, 0x02 }, - { 0x1c, 0x97, 0x40, 0x60, 0x6c, 0x58, 0x17, 0x2d, - 0x03, 0x94, 0x19, 0x70, 0x81, 0xc4, 0x38, 0x54, }, - 16, 3 -}, - -/* K=16, M=16 */ -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0x03, 0xcc, 0x46, 0xb8, 0xac, 0xa7, 0x9c, 0x36, - 0x1e, 0x8c, 0x6e, 0xa6, 0x7b, 0x89, 0x32, 0x49, }, - 16, 16 -}, - -/* K=16, M=32 */ -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - { 0x89, 0xcc, 0x36, 0x58, 0x1b, 0xdd, 0x4d, 0xb5, - 0x78, 0xbb, 0xac, 0xf0, 0xff, 0x8b, 0x08, 0x15, }, - 16, 32 -}, - -/* K=16, M=35 */ -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x23 }, - { 0x4a, 0x7d, 0x45, 0x4d, 0xcd, 0xb5, 0xda, 0x8d, - 0x48, 0x78, 0x16, 0x48, 0x5d, 0x45, 0x95, 0x99, }, - 16, 35 -}, -}; - int x, err; - unsigned char out[16]; - pelican_state pel; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = pelican_init(&pel, tests[x].K, tests[x].keylen)) != CRYPT_OK) { - return err; - } - if ((err = pelican_process(&pel, tests[x].MSG, tests[x].ptlen)) != CRYPT_OK) { - return err; - } - if ((err = pelican_done(&pel, out)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(out, 16, tests[x].T, 16, "PELICAN", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_done.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_done.c deleted file mode 100644 index bcad06a..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_done.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_done.c - PMAC implementation, terminate a session, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen) -{ - int err, x; - - LTC_ARGCHK(pmac != NULL); - LTC_ARGCHK(out != NULL); - - if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || - (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { - return CRYPT_INVALID_ARG; - } - - - /* handle padding. If multiple xor in L/x */ - - if (pmac->buflen == pmac->block_len) { - /* xor Lr against the checksum */ - for (x = 0; x < pmac->block_len; x++) { - pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x]; - } - } else { - /* otherwise xor message bytes then the 0x80 byte */ - for (x = 0; x < pmac->buflen; x++) { - pmac->checksum[x] ^= pmac->block[x]; - } - pmac->checksum[x] ^= 0x80; - } - - /* encrypt it */ - if ((err = ecb_encrypt_block(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) { - return err; - } - ecb_done(&pmac->key); - - /* store it */ - for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) { - out[x] = pmac->checksum[x]; - } - *outlen = x; - -#ifdef LTC_CLEAN_STACK - zeromem(pmac, sizeof(*pmac)); -#endif - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_file.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_file.c deleted file mode 100644 index fca9b00..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_file.c +++ /dev/null @@ -1,88 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_file.c - PMAC implementation, process a file, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -/** - PMAC a file - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param filename The name of the file to send through PMAC - @param out [out] Destination for the authentication tag - @param outlen [in/out] Max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int pmac_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(cipher); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(filename); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(outlen); - return CRYPT_NOP; -#else - size_t x; - int err; - pmac_state pmac; - FILE *in; - unsigned char *buf; - - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(filename != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(filename, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = pmac_done(&pmac, out, outlen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&pmac, sizeof(pmac_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_init.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_init.c deleted file mode 100644 index fb5daa9..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_init.c +++ /dev/null @@ -1,146 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pmac_init.c - PMAC implementation, initialize state, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -#define polys pmac_polys -static const struct { - int len; - unsigned char poly_div[MAXBLOCKSIZE], - poly_mul[MAXBLOCKSIZE]; -} polys[] = { -{ - 8, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } -}, { - 16, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } -} -}; - -/** - Initialize a PMAC state - @param pmac The PMAC state to initialize - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) -{ - int poly, x, y, m, err; - unsigned char *L; - - LTC_ARGCHK(pmac != NULL); - LTC_ARGCHK(key != NULL); - - /* valid cipher? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* determine which polys to use */ - pmac->block_len = cipher_descriptor[cipher].block_length; - for (poly = 0; poly < (int)LTC_ARRAY_SIZE(polys); poly++) { - if (polys[poly].len == pmac->block_len) { - break; - } - } - if (poly >= (int)LTC_ARRAY_SIZE(polys)) { - return CRYPT_INVALID_ARG; - } - if (polys[poly].len != pmac->block_len) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (pmac->block_len % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - - /* schedule the key */ - if ((err = ecb_start(cipher, key, keylen, 0, &pmac->key)) != CRYPT_OK) { - return err; - } - - /* allocate L */ - L = XMALLOC(pmac->block_len); - if (L == NULL) { - return CRYPT_MEM; - } - - /* find L = E[0] */ - zeromem(L, pmac->block_len); - if ((err = ecb_encrypt_block(L, L, &pmac->key)) != CRYPT_OK) { - goto error; - } - - /* find Ls[i] = L << i for i == 0..31 */ - XMEMCPY(pmac->Ls[0], L, pmac->block_len); - for (x = 1; x < 32; x++) { - m = pmac->Ls[x-1][0] >> 7; - for (y = 0; y < pmac->block_len-1; y++) { - pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; - } - pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; - - if (m == 1) { - for (y = 0; y < pmac->block_len; y++) { - pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; - } - } - } - - /* find Lr = L / x */ - m = L[pmac->block_len-1] & 1; - - /* shift right */ - for (x = pmac->block_len - 1; x > 0; x--) { - pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; - } - pmac->Lr[0] = L[0] >> 1; - - if (m == 1) { - for (x = 0; x < pmac->block_len; x++) { - pmac->Lr[x] ^= polys[poly].poly_div[x]; - } - } - - /* zero buffer, counters, etc... */ - pmac->block_index = 1; - pmac->buflen = 0; - zeromem(pmac->block, sizeof(pmac->block)); - zeromem(pmac->Li, sizeof(pmac->Li)); - zeromem(pmac->checksum, sizeof(pmac->checksum)); - err = CRYPT_OK; -error: -#ifdef LTC_CLEAN_STACK - zeromem(L, pmac->block_len); -#endif - - XFREE(L); - - return err; -} - -#undef polys - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory.c deleted file mode 100644 index 4671547..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory.c +++ /dev/null @@ -1,62 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_memory.c - PMAC implementation, process a block of memory, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -/** - PMAC a block of memory - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data you wish to send through PMAC - @param inlen The length of data you wish to send through PMAC (octets) - @param out [out] Destination for the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful -*/ -int pmac_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - int err; - pmac_state *pmac; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for pmac state */ - pmac = XMALLOC(sizeof(pmac_state)); - if (pmac == NULL) { - return CRYPT_MEM; - } - - if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = pmac_process(pmac, in, inlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(pmac, sizeof(pmac_state)); -#endif - - XFREE(pmac); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory_multi.c deleted file mode 100644 index 16ba8f6..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_memory_multi.c +++ /dev/null @@ -1,76 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_memory_multi.c - PMAC implementation, process multiple blocks of memory, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -/** - PMAC multiple blocks of memory - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param out [out] Destination for the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag - @param in The data you wish to send through PMAC - @param inlen The length of data you wish to send through PMAC (octets) - @param ... tuples of (data,len) pairs to PMAC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int pmac_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) -{ - int err; - pmac_state *pmac; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for pmac state */ - pmac = XMALLOC(sizeof(pmac_state)); - if (pmac == NULL) { - return CRYPT_MEM; - } - - if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - va_start(args, inlen); - curptr = in; - curlen = inlen; - for (;;) { - /* process buf */ - if ((err = pmac_process(pmac, curptr, curlen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(pmac, sizeof(pmac_state)); -#endif - XFREE(pmac); - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_ntz.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_ntz.c deleted file mode 100644 index 86142ba..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_ntz.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_ntz.c - PMAC implementation, internal function, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -/** - Internal PMAC function -*/ -int pmac_ntz(unsigned long x) -{ -#if defined(LTC_HAVE_CTZL_BUILTIN) - if (x == 0) - return sizeof(unsigned long) * CHAR_BIT; - return __builtin_ctzl(x); -#else - int c; - x &= 0xFFFFFFFFUL; - c = 0; - while ((x & 1) == 0) { - ++c; - x >>= 1; - } - return c; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_process.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_process.c deleted file mode 100644 index b154aef..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_process.c +++ /dev/null @@ -1,91 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pmac_process.c - PMAC implementation, process data, by Tom St Denis -*/ - - -#ifdef LTC_PMAC - -/** - Process data in a PMAC stream - @param pmac The PMAC state - @param in The data to send through PMAC - @param inlen The length of the data to send through PMAC - @return CRYPT_OK if successful -*/ -int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen) -{ - int err, n; - unsigned long x; - unsigned char Z[MAXBLOCKSIZE]; - - LTC_ARGCHK(pmac != NULL); - LTC_ARGCHK(in != NULL); - - if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || - (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (pmac->buflen == 0 && inlen > 16) { - unsigned long y; - for (x = 0; x < (inlen - 16); x += 16) { - pmac_shift_xor(pmac); - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&pmac->Li[y])); - } - if ((err = ecb_encrypt_block(Z, Z, &pmac->key)) != CRYPT_OK) { - return err; - } - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&Z[y])); - } - in += 16; - } - inlen -= x; - } -#endif - - while (inlen != 0) { - /* ok if the block is full we xor in prev, encrypt and replace prev */ - if (pmac->buflen == pmac->block_len) { - pmac_shift_xor(pmac); - for (x = 0; x < (unsigned long)pmac->block_len; x++) { - Z[x] = pmac->Li[x] ^ pmac->block[x]; - } - if ((err = ecb_encrypt_block(Z, Z, &pmac->key)) != CRYPT_OK) { - return err; - } - for (x = 0; x < (unsigned long)pmac->block_len; x++) { - pmac->checksum[x] ^= Z[x]; - } - pmac->buflen = 0; - } - - /* add bytes */ - n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen)); - XMEMCPY(pmac->block + pmac->buflen, in, n); - pmac->buflen += n; - inlen -= n; - in += n; - } - -#ifdef LTC_CLEAN_STACK - zeromem(Z, sizeof(Z)); -#endif - - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_shift_xor.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_shift_xor.c deleted file mode 100644 index ad97fa8..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_shift_xor.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_shift_xor.c - PMAC implementation, internal function, by Tom St Denis -*/ - -#ifdef LTC_PMAC - -/** - Internal function. Performs the state update (adding correct multiple) - @param pmac The PMAC state. -*/ -void pmac_shift_xor(pmac_state *pmac) -{ - int x, y; - y = pmac_ntz(pmac->block_index++); -#ifdef LTC_FAST - for (x = 0; x < pmac->block_len; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Li + x)) ^= - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Ls[y] + x)); - } -#else - for (x = 0; x < pmac->block_len; x++) { - pmac->Li[x] ^= pmac->Ls[y][x]; - } -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_test.c b/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_test.c deleted file mode 100644 index ccbd6c6..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/pmac/pmac_test.c +++ /dev/null @@ -1,144 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pmac_test.c - PMAC implementation, self-test, by Tom St Denis -*/ - - -#ifdef LTC_PMAC - -/** - Test the LTC_OMAC implementation - @return CRYPT_OK if successful, CRYPT_NOP if testing has been disabled -*/ -int pmac_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct { - int msglen; - unsigned char key[16], msg[34], tag[16]; - } tests[] = { - - /* PMAC-AES-128-0B */ -{ - 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00 }, - /* tag */ - { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, - 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } -}, - - /* PMAC-AES-128-3B */ -{ - 3, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02 }, - /* tag */ - { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, - 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } -}, - - /* PMAC-AES-128-16B */ -{ - 16, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* tag */ - { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, - 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } -}, - - /* PMAC-AES-128-20B */ -{ - 20, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 }, - /* tag */ - { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, - 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } -}, - - /* PMAC-AES-128-32B */ -{ - 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* tag */ - { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, - 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } -}, - - /* PMAC-AES-128-34B */ -{ - 34, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21 }, - /* tag */ - { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, - 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } -} - -}; - int err, x, idx; - unsigned long len; - unsigned char outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - len = sizeof(outtag); - if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "PMAC", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* PMAC_MODE */ - - - diff --git a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305.c b/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305.c deleted file mode 100644 index 32cdb55..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305.c +++ /dev/null @@ -1,258 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * Public Domain poly1305 from Andrew Moon - * https://github.com/floodyberry/poly1305-donna - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_POLY1305 - -/* internal only */ -static void s_poly1305_block(poly1305_state *st, const unsigned char *in, unsigned long inlen) -{ - const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ - ulong32 r0,r1,r2,r3,r4; - ulong32 s1,s2,s3,s4; - ulong32 h0,h1,h2,h3,h4; - ulong32 tmp; - ulong64 d0,d1,d2,d3,d4; - ulong32 c; - - r0 = st->r[0]; - r1 = st->r[1]; - r2 = st->r[2]; - r3 = st->r[3]; - r4 = st->r[4]; - - s1 = r1 * 5; - s2 = r2 * 5; - s3 = r3 * 5; - s4 = r4 * 5; - - h0 = st->h[0]; - h1 = st->h[1]; - h2 = st->h[2]; - h3 = st->h[3]; - h4 = st->h[4]; - - while (inlen >= 16) { - /* h += in[i] */ - LOAD32L(tmp, in+ 0); h0 += (tmp ) & 0x3ffffff; - LOAD32L(tmp, in+ 3); h1 += (tmp >> 2) & 0x3ffffff; - LOAD32L(tmp, in+ 6); h2 += (tmp >> 4) & 0x3ffffff; - LOAD32L(tmp, in+ 9); h3 += (tmp >> 6) & 0x3ffffff; - LOAD32L(tmp, in+12); h4 += (tmp >> 8) | hibit; - - /* h *= r */ - d0 = ((ulong64)h0 * r0) + ((ulong64)h1 * s4) + ((ulong64)h2 * s3) + ((ulong64)h3 * s2) + ((ulong64)h4 * s1); - d1 = ((ulong64)h0 * r1) + ((ulong64)h1 * r0) + ((ulong64)h2 * s4) + ((ulong64)h3 * s3) + ((ulong64)h4 * s2); - d2 = ((ulong64)h0 * r2) + ((ulong64)h1 * r1) + ((ulong64)h2 * r0) + ((ulong64)h3 * s4) + ((ulong64)h4 * s3); - d3 = ((ulong64)h0 * r3) + ((ulong64)h1 * r2) + ((ulong64)h2 * r1) + ((ulong64)h3 * r0) + ((ulong64)h4 * s4); - d4 = ((ulong64)h0 * r4) + ((ulong64)h1 * r3) + ((ulong64)h2 * r2) + ((ulong64)h3 * r1) + ((ulong64)h4 * r0); - - /* (partial) h %= p */ - c = (ulong32)(d0 >> 26); h0 = (ulong32)d0 & 0x3ffffff; - d1 += c; c = (ulong32)(d1 >> 26); h1 = (ulong32)d1 & 0x3ffffff; - d2 += c; c = (ulong32)(d2 >> 26); h2 = (ulong32)d2 & 0x3ffffff; - d3 += c; c = (ulong32)(d3 >> 26); h3 = (ulong32)d3 & 0x3ffffff; - d4 += c; c = (ulong32)(d4 >> 26); h4 = (ulong32)d4 & 0x3ffffff; - h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; - h1 += c; - - in += 16; - inlen -= 16; - } - - st->h[0] = h0; - st->h[1] = h1; - st->h[2] = h2; - st->h[3] = h3; - st->h[4] = h4; -} - -/** - Initialize an POLY1305 context. - @param st The POLY1305 state - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen == 32); - - /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ - LOAD32L(st->r[0], key + 0); st->r[0] = (st->r[0] ) & 0x3ffffff; - LOAD32L(st->r[1], key + 3); st->r[1] = (st->r[1] >> 2) & 0x3ffff03; - LOAD32L(st->r[2], key + 6); st->r[2] = (st->r[2] >> 4) & 0x3ffc0ff; - LOAD32L(st->r[3], key + 9); st->r[3] = (st->r[3] >> 6) & 0x3f03fff; - LOAD32L(st->r[4], key + 12); st->r[4] = (st->r[4] >> 8) & 0x00fffff; - - /* h = 0 */ - st->h[0] = 0; - st->h[1] = 0; - st->h[2] = 0; - st->h[3] = 0; - st->h[4] = 0; - - /* save pad for later */ - LOAD32L(st->pad[0], key + 16); - LOAD32L(st->pad[1], key + 20); - LOAD32L(st->pad[2], key + 24); - LOAD32L(st->pad[3], key + 28); - - st->leftover = 0; - st->final = 0; - return CRYPT_OK; -} - -/** - Process data through POLY1305 - @param st The POLY1305 state - @param in The data to send through HMAC - @param inlen The length of the data to HMAC (octets) - @return CRYPT_OK if successful -*/ -int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen) -{ - unsigned long i; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - - /* handle leftover */ - if (st->leftover) { - unsigned long want = (16 - st->leftover); - if (want > inlen) want = inlen; - for (i = 0; i < want; i++) st->buffer[st->leftover + i] = in[i]; - inlen -= want; - in += want; - st->leftover += want; - if (st->leftover < 16) return CRYPT_OK; - s_poly1305_block(st, st->buffer, 16); - st->leftover = 0; - } - - /* process full blocks */ - if (inlen >= 16) { - unsigned long want = (inlen & ~(16 - 1)); - s_poly1305_block(st, in, want); - in += want; - inlen -= want; - } - - /* store leftover */ - if (inlen) { - for (i = 0; i < inlen; i++) st->buffer[st->leftover + i] = in[i]; - st->leftover += inlen; - } - return CRYPT_OK; -} - -/** - Terminate a POLY1305 session - @param st The POLY1305 state - @param mac [out] The destination of the POLY1305 authentication tag - @param maclen [in/out] The max size and resulting size of the POLY1305 authentication tag - @return CRYPT_OK if successful -*/ -int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen) -{ - ulong32 h0,h1,h2,h3,h4,c; - ulong32 g0,g1,g2,g3,g4; - ulong64 f; - ulong32 mask; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - LTC_ARGCHK(*maclen >= 16); - - /* process the remaining block */ - if (st->leftover) { - unsigned long i = st->leftover; - st->buffer[i++] = 1; - for (; i < 16; i++) st->buffer[i] = 0; - st->final = 1; - s_poly1305_block(st, st->buffer, 16); - } - - /* fully carry h */ - h0 = st->h[0]; - h1 = st->h[1]; - h2 = st->h[2]; - h3 = st->h[3]; - h4 = st->h[4]; - - c = h1 >> 26; h1 = h1 & 0x3ffffff; - h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; - h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; - h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; - h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; - h1 += c; - - /* compute h + -p */ - g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; - g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; - g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; - g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; - g4 = h4 + c - (1UL << 26); - - /* select h if h < p, or h + -p if h >= p */ - mask = (g4 >> 31) - 1; - g0 &= mask; - g1 &= mask; - g2 &= mask; - g3 &= mask; - g4 &= mask; - mask = ~mask; - h0 = (h0 & mask) | g0; - h1 = (h1 & mask) | g1; - h2 = (h2 & mask) | g2; - h3 = (h3 & mask) | g3; - h4 = (h4 & mask) | g4; - - /* h = h % (2^128) */ - h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; - h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; - h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; - h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; - - /* mac = (h + pad) % (2^128) */ - f = (ulong64)h0 + st->pad[0] ; h0 = (ulong32)f; - f = (ulong64)h1 + st->pad[1] + (f >> 32); h1 = (ulong32)f; - f = (ulong64)h2 + st->pad[2] + (f >> 32); h2 = (ulong32)f; - f = (ulong64)h3 + st->pad[3] + (f >> 32); h3 = (ulong32)f; - - STORE32L(h0, mac + 0); - STORE32L(h1, mac + 4); - STORE32L(h2, mac + 8); - STORE32L(h3, mac + 12); - - /* zero out the state */ - st->h[0] = 0; - st->h[1] = 0; - st->h[2] = 0; - st->h[3] = 0; - st->h[4] = 0; - st->r[0] = 0; - st->r[1] = 0; - st->r[2] = 0; - st->r[3] = 0; - st->r[4] = 0; - st->pad[0] = 0; - st->pad[1] = 0; - st->pad[2] = 0; - st->pad[3] = 0; - - *maclen = 16; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_file.c b/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_file.c deleted file mode 100644 index e09c994..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_file.c +++ /dev/null @@ -1,83 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * Public Domain poly1305 from Andrew Moon - * https://github.com/floodyberry/poly1305-donna - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_POLY1305 - -/** - POLY1305 a file - @param fname The name of the file you wish to POLY1305 - @param key The secret key - @param keylen The length of the secret key - @param mac [out] The POLY1305 authentication tag - @param maclen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(fname); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(mac); - LTC_UNUSED_PARAM(maclen); - return CRYPT_NOP; -#else - poly1305_state st; - FILE *in; - unsigned char *buf; - size_t x; - int err; - - LTC_ARGCHK(fname != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = poly1305_done(&st, mac, maclen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(poly1305_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory.c b/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory.c deleted file mode 100644 index 8a9fea6..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * Public Domain poly1305 from Andrew Moon - * https://github.com/floodyberry/poly1305-donna - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_POLY1305 - -/** - POLY1305 a block of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param in The data to POLY1305 - @param inlen The length of the data to POLY1305 (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @return CRYPT_OK if successful -*/ -int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) -{ - poly1305_state st; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = poly1305_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - err = poly1305_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(poly1305_state)); -#endif - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory_multi.c deleted file mode 100644 index 07dbde4..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_memory_multi.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * Public Domain poly1305 from Andrew Moon - * https://github.com/floodyberry/poly1305-donna - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_POLY1305 - -/** - POLY1305 multiple blocks of memory to produce the authentication tag - @param key The secret key - @param keylen The length of the secret key (octets) - @param mac [out] Destination of the authentication tag - @param maclen [in/out] Max size and resulting size of authentication tag - @param in The data to POLY1305 - @param inlen The length of the data to POLY1305 (octets) - @param ... tuples of (data,len) pairs to POLY1305, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) -{ - poly1305_state st; - int err; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(mac != NULL); - LTC_ARGCHK(maclen != NULL); - - va_start(args, inlen); - curptr = in; - curlen = inlen; - if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } - for (;;) { - if ((err = poly1305_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) break; - curlen = va_arg(args, unsigned long); - } - err = poly1305_done(&st, mac, maclen); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&st, sizeof(poly1305_state)); -#endif - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_test.c b/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_test.c deleted file mode 100644 index f9b3f75..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/poly1305/poly1305_test.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * Public Domain poly1305 from Andrew Moon - * https://github.com/floodyberry/poly1305-donna - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_POLY1305 - -int poly1305_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - /* https://tools.ietf.org/html/rfc7539#section-2.5.2 */ - unsigned char k[] = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }; - unsigned char tag[] = { 0xA8, 0x06, 0x1D, 0xC1, 0x30, 0x51, 0x36, 0xC6, 0xC2, 0x2B, 0x8B, 0xAF, 0x0C, 0x01, 0x27, 0xA9 }; - char m[] = "Cryptographic Forum Research Group"; - unsigned long len = 16, mlen = XSTRLEN(m); - unsigned char out[1000]; - poly1305_state st; - int err; - - /* process piece by piece */ - if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m, 5)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m + 5, 4)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m + 9, 3)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m + 12, 2)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m + 14, 1)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m + 15, mlen - 15)) != CRYPT_OK) return err; - if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; - if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - /* process in one go */ - if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; - if ((err = poly1305_process(&st, (unsigned char*)m, mlen)) != CRYPT_OK) return err; - if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; - if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_done.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_done.c deleted file mode 100644 index 4163e22..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_done.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_done.c - XCBC Support, terminate the state -*/ - -#ifdef LTC_XCBC - -/** Terminate the XCBC-MAC state - @param xcbc XCBC state to terminate - @param out [out] Destination for the MAC tag - @param outlen [in/out] Destination size and final tag size - Return CRYPT_OK on success -*/ -int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen) -{ - int x; - LTC_ARGCHK(xcbc != NULL); - LTC_ARGCHK(out != NULL); - - if ((xcbc->blocksize < 0) || (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { - return CRYPT_INVALID_ARG; - } - - /* which key do we use? */ - if (xcbc->buflen == xcbc->blocksize) { - /* k2 */ - for (x = 0; x < xcbc->blocksize; x++) { - xcbc->IV[x] ^= xcbc->K[1][x]; - } - } else { - xcbc->IV[xcbc->buflen] ^= 0x80; - /* k3 */ - for (x = 0; x < xcbc->blocksize; x++) { - xcbc->IV[x] ^= xcbc->K[2][x]; - } - } - - /* encrypt */ - ecb_encrypt_block(xcbc->IV, xcbc->IV, &xcbc->key); - ecb_done(&xcbc->key); - - /* extract tag */ - for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) { - out[x] = xcbc->IV[x]; - } - *outlen = x; - -#ifdef LTC_CLEAN_STACK - zeromem(xcbc, sizeof(*xcbc)); -#endif - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_file.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_file.c deleted file mode 100644 index d8612df..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_file.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_file.c - XCBC support, process a file, Tom St Denis -*/ - -#ifdef LTC_XCBC - -/** - XCBC a file - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param filename The name of the file you wish to XCBC - @param out [out] Where the authentication tag is to be stored - @param outlen [in/out] The max size and resulting size of the authentication tag - @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled -*/ -int xcbc_file(int cipher, - const unsigned char *key, unsigned long keylen, - const char *filename, - unsigned char *out, unsigned long *outlen) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(cipher); - LTC_UNUSED_PARAM(key); - LTC_UNUSED_PARAM(keylen); - LTC_UNUSED_PARAM(filename); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(outlen); - return CRYPT_NOP; -#else - size_t x; - int err; - xcbc_state xcbc; - FILE *in; - unsigned char *buf; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(filename != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { - return CRYPT_MEM; - } - - if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - - in = fopen(filename, "rb"); - if (in == NULL) { - err = CRYPT_FILE_NOTFOUND; - goto LBL_ERR; - } - - do { - x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); - if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) { - fclose(in); - goto LBL_CLEANBUF; - } - } while (x == LTC_FILE_READ_BUFSIZE); - - if (fclose(in) != 0) { - err = CRYPT_ERROR; - goto LBL_CLEANBUF; - } - - err = xcbc_done(&xcbc, out, outlen); - -LBL_CLEANBUF: - zeromem(buf, LTC_FILE_READ_BUFSIZE); -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(&xcbc, sizeof(xcbc_state)); -#endif - XFREE(buf); - return err; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_init.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_init.c deleted file mode 100644 index 10c55da..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_init.c +++ /dev/null @@ -1,100 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file xcbc_init.c - XCBC Support, start an XCBC state -*/ - -#ifdef LTC_XCBC - -/** Initialize XCBC-MAC state - @param xcbc [out] XCBC state to initialize - @param cipher Index of cipher to use - @param key [in] Secret key - @param keylen Length of secret key in octets - Return CRYPT_OK on success -*/ -int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen) -{ - int x, y, err; - symmetric_ECB *skey; - unsigned long k1; - - LTC_ARGCHK(xcbc != NULL); - LTC_ARGCHK(key != NULL); - - /* schedule the key */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_FAST - if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - skey = NULL; - - /* are we in pure XCBC mode with three keys? */ - if (keylen & LTC_XCBC_PURE) { - keylen &= ~LTC_XCBC_PURE; - - if (keylen < 2UL*cipher_descriptor[cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - k1 = keylen - 2*cipher_descriptor[cipher].block_length; - XMEMCPY(xcbc->K[0], key, k1); - XMEMCPY(xcbc->K[1], key+k1, cipher_descriptor[cipher].block_length); - XMEMCPY(xcbc->K[2], key+k1 + cipher_descriptor[cipher].block_length, cipher_descriptor[cipher].block_length); - } else { - /* use the key expansion */ - k1 = cipher_descriptor[cipher].block_length; - - /* schedule the user key */ - skey = XCALLOC(1, sizeof(*skey)); - if (skey == NULL) { - return CRYPT_MEM; - } - - if ((err = ecb_start(cipher, key, keylen, 0, skey)) != CRYPT_OK) { - goto done; - } - - /* make the three keys */ - for (y = 0; y < 3; y++) { - for (x = 0; x < cipher_descriptor[cipher].block_length; x++) { - xcbc->K[y][x] = y + 1; - } - ecb_encrypt_block(xcbc->K[y], xcbc->K[y], skey); - } - } - - /* setup K1 */ - err = ecb_start(cipher, xcbc->K[0], k1, 0, &xcbc->key); - - /* setup struct */ - zeromem(xcbc->IV, cipher_descriptor[cipher].block_length); - xcbc->blocksize = cipher_descriptor[cipher].block_length; - xcbc->buflen = 0; -done: - ecb_done(skey); - if (skey != NULL) { -#ifdef LTC_CLEAN_STACK - zeromem(skey, sizeof(*skey)); -#endif - XFREE(skey); - } - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory.c deleted file mode 100644 index bd7f388..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_process.c - XCBC Support, XCBC-MAC a block of memory -*/ - -#ifdef LTC_XCBC - -/** XCBC-MAC a block of memory - @param cipher Index of cipher to use - @param key [in] Secret key - @param keylen Length of key in octets - @param in [in] Message to MAC - @param inlen Length of input in octets - @param out [out] Destination for the MAC tag - @param outlen [in/out] Output size and final tag size - Return CRYPT_OK on success. -*/ -int xcbc_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - xcbc_state *xcbc; - int err; - - /* is the cipher valid? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* Use accelerator if found */ - if (cipher_descriptor[cipher].xcbc_memory != NULL) { - return cipher_descriptor[cipher].xcbc_memory(key, keylen, in, inlen, out, outlen); - } - - xcbc = XCALLOC(1, sizeof(*xcbc)); - if (xcbc == NULL) { - return CRYPT_MEM; - } - - if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { - goto done; - } - - if ((err = xcbc_process(xcbc, in, inlen)) != CRYPT_OK) { - goto done; - } - - err = xcbc_done(xcbc, out, outlen); -done: - XFREE(xcbc); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory_multi.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory_multi.c deleted file mode 100644 index f53de36..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_memory_multi.c +++ /dev/null @@ -1,77 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_memory_multi.c - XCBC support, process multiple blocks of memory, Tom St Denis -*/ - -#ifdef LTC_XCBC - -/** - XCBC multiple blocks of memory - @param cipher The index of the desired cipher - @param key The secret key - @param keylen The length of the secret key (octets) - @param out [out] The destination of the authentication tag - @param outlen [in/out] The max size and resulting size of the authentication tag (octets) - @param in The data to send through XCBC - @param inlen The length of the data to send through XCBC (octets) - @param ... tuples of (data,len) pairs to XCBC, terminated with a (NULL,x) (x=don't care) - @return CRYPT_OK if successful -*/ -int xcbc_memory_multi(int cipher, - const unsigned char *key, unsigned long keylen, - unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...) -{ - int err; - xcbc_state *xcbc; - va_list args; - const unsigned char *curptr; - unsigned long curlen; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* allocate ram for xcbc state */ - xcbc = XMALLOC(sizeof(xcbc_state)); - if (xcbc == NULL) { - return CRYPT_MEM; - } - - /* xcbc process the message */ - if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { - goto LBL_ERR; - } - va_start(args, inlen); - curptr = in; - curlen = inlen; - for (;;) { - /* process buf */ - if ((err = xcbc_process(xcbc, curptr, curlen)) != CRYPT_OK) { - goto LBL_ERR; - } - /* step to next */ - curptr = va_arg(args, const unsigned char*); - if (curptr == NULL) { - break; - } - curlen = va_arg(args, unsigned long); - } - if ((err = xcbc_done(xcbc, out, outlen)) != CRYPT_OK) { - goto LBL_ERR; - } -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(xcbc, sizeof(xcbc_state)); -#endif - XFREE(xcbc); - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_process.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_process.c deleted file mode 100644 index a6e5145..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_process.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_process.c - XCBC Support, process blocks with XCBC -*/ - -#ifdef LTC_XCBC - -/** Process data through XCBC-MAC - @param xcbc The XCBC-MAC state - @param in Input data to process - @param inlen Length of input in octets - Return CRYPT_OK on success -*/ -int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen) -{ -#ifdef LTC_FAST - int x; -#endif - - LTC_ARGCHK(xcbc != NULL); - LTC_ARGCHK(in != NULL); - - if ((xcbc->blocksize < 0) || (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (xcbc->buflen == 0) { - while (inlen > (unsigned long)xcbc->blocksize) { - for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); - } - ecb_encrypt_block(xcbc->IV, xcbc->IV, &xcbc->key); - in += xcbc->blocksize; - inlen -= xcbc->blocksize; - } - } -#endif - - while (inlen) { - if (xcbc->buflen == xcbc->blocksize) { - ecb_encrypt_block(xcbc->IV, xcbc->IV, &xcbc->key); - xcbc->buflen = 0; - } - xcbc->IV[xcbc->buflen++] ^= *in++; - --inlen; - } - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_test.c b/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_test.c deleted file mode 100644 index 2c61105..0000000 --- a/Sources/DataLiteC/libtomcrypt/mac/xcbc/xcbc_test.c +++ /dev/null @@ -1,116 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file xcbc_test.c - XCBC Support, Test XCBC-MAC mode -*/ - -#ifdef LTC_XCBC - -/** Test XCBC-MAC mode - Return CRYPT_OK on success -*/ -int xcbc_test(void) -{ -#ifdef LTC_NO_TEST - return CRYPT_NOP; -#else - static const struct { - int msglen; - unsigned char K[16], M[34], T[16]; - } tests[] = { -{ - 0, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0 }, - - { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, - 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 } -}, - -{ - 3, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0x00, 0x01, 0x02 }, - - { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf, - 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f } -}, - -{ - 16, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, - 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 } -}, - -{ - 32, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - - { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3, - 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 } -}, - -{ - 34, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21 }, - - { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3, - 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 }, -}, - - - -}; - unsigned char T[16]; - unsigned long taglen; - int err, x, idx; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - taglen = 16; - if ((err = xcbc_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { - return err; - } - if (compare_testvector(T, taglen, tests[x].T, 16, "XCBC", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - - return CRYPT_OK; -#endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c b/Sources/DataLiteC/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c deleted file mode 100644 index fa95625..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/fp/ltc_ecc_fp_mulmod.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_fp_mulmod.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && defined(LTC_MECC_FP) -#include - -/* number of entries in the cache */ -#ifndef FP_ENTRIES -#define FP_ENTRIES 16 -#endif - -/* number of bits in LUT */ -#ifndef FP_LUT -#define FP_LUT 8U -#endif - -#if (FP_LUT > 12) || (FP_LUT < 2) - #error FP_LUT must be between 2 and 12 inclusively -#endif - -/** Our FP cache */ -static struct { - ecc_point *g, /* cached COPY of base point */ - *LUT[1U< 6 - { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, - { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, - { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, - { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, - { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, - { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, - { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, - { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, -#if FP_LUT > 7 - { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, - { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, - { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, - { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, - { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, - { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, - { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, - { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, - { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, - { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, - { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, - { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, - { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, - { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, - { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, - { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, -#if FP_LUT > 8 - { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, - { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, - { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, - { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, - { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, - { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, - { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, - { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, - { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, - { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, - { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, - { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, - { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, - { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, - { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, - { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, - { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, - { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, - { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, - { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, - { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, - { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, - { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, - { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, - { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, - { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, - { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, - { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, - { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, - { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, - { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, - { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, -#if FP_LUT > 9 - { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, - { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, - { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, - { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, - { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, - { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, - { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, - { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, - { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, - { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, - { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, - { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, - { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, - { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, - { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, - { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, - { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, - { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, - { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, - { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, - { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, - { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, - { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, - { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, - { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, - { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, - { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, - { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, - { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, - { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, - { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, - { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, - { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, - { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, - { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, - { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, - { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, - { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, - { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, - { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, - { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, - { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, - { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, - { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, - { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, - { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, - { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, - { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, - { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, - { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, - { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, - { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, - { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, - { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, - { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, - { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, - { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, - { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, - { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, - { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, - { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, - { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, - { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, - { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, -#if FP_LUT > 10 - { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, - { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, - { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, - { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, - { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, - { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, - { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, - { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, - { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, - { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, - { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, - { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, - { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, - { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, - { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, - { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, - { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, - { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, - { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, - { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, - { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, - { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, - { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, - { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, - { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, - { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, - { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, - { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, - { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, - { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, - { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, - { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, - { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, - { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, - { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, - { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, - { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, - { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, - { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, - { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, - { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, - { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, - { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, - { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, - { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, - { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, - { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, - { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, - { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, - { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, - { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, - { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, - { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, - { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, - { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, - { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, - { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, - { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, - { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, - { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, - { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, - { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, - { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, - { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, - { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, - { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, - { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, - { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, - { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, - { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, - { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, - { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, - { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, - { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, - { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, - { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, - { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, - { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, - { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, - { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, - { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, - { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, - { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, - { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, - { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, - { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, - { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, - { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, - { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, - { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, - { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, - { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, - { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, - { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, - { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, - { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, - { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, - { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, - { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, - { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, - { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, - { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, - { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, - { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, - { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, - { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, - { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, - { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, - { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, - { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, - { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, - { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, - { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, - { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, - { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, - { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, - { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, - { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, - { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, - { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, - { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, - { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, - { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, - { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, - { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, - { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, - { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, - { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, -#if FP_LUT > 11 - { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, - { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, - { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, - { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, - { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, - { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, - { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, - { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, - { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, - { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, - { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, - { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, - { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, - { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, - { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, - { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, - { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, - { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, - { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, - { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, - { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, - { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, - { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, - { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, - { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, - { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, - { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, - { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, - { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, - { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, - { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, - { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, - { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, - { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, - { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, - { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, - { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, - { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, - { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, - { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, - { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, - { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, - { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, - { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, - { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, - { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, - { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, - { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, - { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, - { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, - { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, - { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, - { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, - { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, - { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, - { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, - { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, - { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, - { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, - { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, - { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, - { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, - { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, - { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, - { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, - { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, - { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, - { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, - { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, - { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, - { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, - { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, - { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, - { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, - { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, - { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, - { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, - { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, - { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, - { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, - { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, - { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, - { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, - { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, - { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, - { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, - { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, - { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, - { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, - { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, - { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, - { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, - { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, - { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, - { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, - { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, - { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, - { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, - { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, - { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, - { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, - { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, - { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, - { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, - { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, - { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, - { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, - { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, - { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, - { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, - { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, - { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, - { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, - { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, - { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, - { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, - { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, - { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, - { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, - { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, - { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, - { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, - { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, - { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, - { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, - { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, - { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, - { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, - { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, - { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, - { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, - { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, - { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, - { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, - { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, - { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, - { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, - { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, - { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, - { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, - { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, - { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, - { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, - { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, - { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, - { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, - { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, - { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, - { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, - { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, - { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, - { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, - { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, - { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, - { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, - { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, - { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, - { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, - { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, - { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, - { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, - { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, - { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, - { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, - { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, - { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, - { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, - { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, - { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, - { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, - { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, - { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, - { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, - { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, - { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, - { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, - { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, - { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, - { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, - { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, - { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, - { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, - { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, - { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, - { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, - { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, - { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, - { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, - { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, - { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, - { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, - { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, - { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, - { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, - { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, - { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, - { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, - { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, - { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, - { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, - { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, - { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, - { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, - { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, - { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, - { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, - { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, - { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, - { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, - { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, - { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, - { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, - { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, - { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, - { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, - { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, - { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, - { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, - { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, - { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, - { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, - { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, - { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, - { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, - { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, - { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, - { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, - { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, - { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, - { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, - { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, - { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, - { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, - { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, - { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, - { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, - { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, - { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, - { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, - { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, - { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, - { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, - { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, - { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, - { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, - { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, - { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, - { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, - { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, - { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, - { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, - { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, - { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, - { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, - { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, - { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, -#endif -#endif -#endif -#endif -#endif -#endif -}; - -/* find a hole and free as required, return -1 if no hole found */ -static int s_find_hole(void) -{ - unsigned x; - int y, z; - for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) { - if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) { - z = x; - y = fp_cache[x].lru_count; - } - } - - /* decrease all */ - for (x = 0; x < FP_ENTRIES; x++) { - if (fp_cache[x].lru_count > 3) { - --(fp_cache[x].lru_count); - } - } - - /* free entry z */ - if (z >= 0 && fp_cache[z].g) { - if (fp_cache[z].mu != NULL) { - ltc_mp_clear(fp_cache[z].mu); - fp_cache[z].mu = NULL; - } - ltc_ecc_del_point(fp_cache[z].g); - fp_cache[z].g = NULL; - for (x = 0; x < (1U<x, g->x) == LTC_MP_EQ && - ltc_mp_cmp(fp_cache[x].g->y, g->y) == LTC_MP_EQ && - ltc_mp_cmp(fp_cache[x].g->z, g->z) == LTC_MP_EQ) { - break; - } - } - if (x == FP_ENTRIES) { - x = -1; - } - return x; -} - -/* add a new base to the cache */ -static int s_add_entry(int idx, ecc_point *g) -{ - unsigned x, y; - - /* allocate base and LUT */ - fp_cache[idx].g = ltc_ecc_new_point(); - if (fp_cache[idx].g == NULL) { - return CRYPT_MEM; - } - - /* copy x and y */ - if ((ltc_mp_copy(g->x, fp_cache[idx].g->x) != CRYPT_OK) || - (ltc_mp_copy(g->y, fp_cache[idx].g->y) != CRYPT_OK) || - (ltc_mp_copy(g->z, fp_cache[idx].g->z) != CRYPT_OK)) { - ltc_ecc_del_point(fp_cache[idx].g); - fp_cache[idx].g = NULL; - return CRYPT_MEM; - } - - for (x = 0; x < (1U<x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) || - (ltc_mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) || - (ltc_mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; } - - /* make all single bit entries */ - for (x = 1; x < FP_LUT; x++) { - if ((ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; } - - /* now double it bitlen/FP_LUT times */ - for (y = 0; y < lut_gap; y++) { - if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; } - - /* invert it */ - if ((err = ltc_mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; } - - /* now square it */ - if ((err = ltc_mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } - - /* fix x */ - if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; } - - /* get 1/z^3 */ - if ((err = ltc_mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } - - /* fix y */ - if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; } - - /* free z */ - ltc_mp_clear(fp_cache[idx].LUT[x]->z); - fp_cache[idx].LUT[x]->z = NULL; - } - ltc_mp_clear(tmp); - - return CRYPT_OK; -ERR: - err = CRYPT_MEM; -DONE: - for (y = 0; y < (1U< ltc_mp_unsigned_bin_size(modulus)) { - /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); - return err; - } - - /* k must be less than modulus */ - if (ltc_mp_cmp(k, order) != LTC_MP_LT) { - if ((err = ltc_mp_init(&tk)) != CRYPT_OK) { - ltc_mp_clear(order); - return err; - } - if ((err = ltc_mp_mod(k, order, tk)) != CRYPT_OK) { - ltc_mp_clear(tk); - ltc_mp_clear(order); - return err; - } - } else { - tk = k; - } - ltc_mp_clear(order); - } else { - tk = k; - } - - /* get bitlen and round up to next multiple of FP_LUT */ - bitlen = ltc_mp_unsigned_bin_size(modulus) << 3; - x = bitlen % FP_LUT; - if (x) { - bitlen += FP_LUT - x; - } - lut_gap = bitlen / FP_LUT; - - /* get the k value */ - if (ltc_mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) { - if (tk != k) { - ltc_mp_clear(tk); - } - return CRYPT_BUFFER_OVERFLOW; - } - - /* store k */ - zeromem(kb, sizeof(kb)); - if ((err = ltc_mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) { - if (tk != k) { - ltc_mp_clear(tk); - } - return err; - } - - /* let's reverse kb so it's little endian */ - x = 0; - y = ltc_mp_unsigned_bin_size(tk) - 1; - if (tk != k) { - ltc_mp_clear(tk); - } - while ((unsigned)x < y) { - z = kb[x]; kb[x] = kb[y]; kb[y] = z; - ++x; --y; - } - - /* at this point we can start, yipee */ - first = 1; - for (x = lut_gap-1; x >= 0; x--) { - /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ - bitpos = x; - for (y = z = 0; y < FP_LUT; y++) { - z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y; - bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ - } - - /* double if not first */ - if (!first) { - if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - - /* add if not first, otherwise copy */ - if (!first && z) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } else if (z) { - if ((ltc_mp_copy(fp_cache[idx].LUT[z]->x, R->x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx].LUT[z]->y, R->y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } - first = 0; - } - } - z = 0; - zeromem(kb, sizeof(kb)); - /* map R back from projective space */ - if (map) { - err = ltc_ecc_map(R, modulus, mp); - } else { - err = CRYPT_OK; - } - return err; -} - -#ifdef LTC_ECC_SHAMIR -/* perform a fixed point ECC mulmod */ -static int ss_accel_fp_mul2add(int idx1, int idx2, - void *kA, void *kB, - ecc_point *R, void *a, void *modulus, void *mp) -{ - unsigned char kb[2][128]; - int x; - unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; - void *tka, *tkb, *order; - - /* if it's smaller than modulus we fine */ - if (ltc_mp_unsigned_bin_size(kA) > ltc_mp_unsigned_bin_size(modulus)) { - /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); - return err; - } - - /* kA must be less than modulus */ - if (ltc_mp_cmp(kA, order) != LTC_MP_LT) { - if ((err = ltc_mp_init(&tka)) != CRYPT_OK) { - ltc_mp_clear(order); - return err; - } - if ((err = ltc_mp_mod(kA, order, tka)) != CRYPT_OK) { - ltc_mp_clear(tka); - ltc_mp_clear(order); - return err; - } - } else { - tka = kA; - } - ltc_mp_clear(order); - } else { - tka = kA; - } - - /* if it's smaller than modulus we fine */ - if (ltc_mp_unsigned_bin_size(kB) > ltc_mp_unsigned_bin_size(modulus)) { - /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); - return err; - } - - /* kB must be less than modulus */ - if (ltc_mp_cmp(kB, order) != LTC_MP_LT) { - if ((err = ltc_mp_init(&tkb)) != CRYPT_OK) { - ltc_mp_clear(order); - return err; - } - if ((err = ltc_mp_mod(kB, order, tkb)) != CRYPT_OK) { - ltc_mp_clear(tkb); - ltc_mp_clear(order); - return err; - } - } else { - tkb = kB; - } - ltc_mp_clear(order); - } else { - tkb = kB; - } - - /* get bitlen and round up to next multiple of FP_LUT */ - bitlen = ltc_mp_unsigned_bin_size(modulus) << 3; - x = bitlen % FP_LUT; - if (x) { - bitlen += FP_LUT - x; - } - lut_gap = bitlen / FP_LUT; - - /* get the k value */ - if ((ltc_mp_unsigned_bin_size(tka) > (sizeof(kb[0]) - 2)) || (ltc_mp_unsigned_bin_size(tkb) > (sizeof(kb[0]) - 2)) ) { - if (tka != kA) { - ltc_mp_clear(tka); - } - if (tkb != kB) { - ltc_mp_clear(tkb); - } - return CRYPT_BUFFER_OVERFLOW; - } - - /* store k */ - zeromem(kb, sizeof(kb)); - if ((err = ltc_mp_to_unsigned_bin(tka, kb[0])) != CRYPT_OK) { - if (tka != kA) { - ltc_mp_clear(tka); - } - if (tkb != kB) { - ltc_mp_clear(tkb); - } - return err; - } - - /* let's reverse kb so it's little endian */ - x = 0; - y = ltc_mp_unsigned_bin_size(tka) - 1; - if (tka != kA) { - ltc_mp_clear(tka); - } - while ((unsigned)x < y) { - z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z; - ++x; --y; - } - - /* store b */ - if ((err = ltc_mp_to_unsigned_bin(tkb, kb[1])) != CRYPT_OK) { - if (tkb != kB) { - ltc_mp_clear(tkb); - } - return err; - } - - x = 0; - y = ltc_mp_unsigned_bin_size(tkb) - 1; - if (tkb != kB) { - ltc_mp_clear(tkb); - } - while ((unsigned)x < y) { - z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z; - ++x; --y; - } - - /* at this point we can start, yipee */ - first = 1; - for (x = lut_gap-1; x >= 0; x--) { - /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ - bitpos = x; - for (y = zA = zB = 0; y < FP_LUT; y++) { - zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y; - zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y; - bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ - } - - /* double if not first */ - if (!first) { - if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - - /* add if not first, otherwise copy */ - if (!first) { - if (zA) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - if (zB) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - } else { - if (zA) { - if ((ltc_mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } - first = 0; - } - if (zB && first == 0) { - if (zB) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - } else if (zB && first == 1) { - if ((ltc_mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } - first = 0; - } - } - } - zeromem(kb, sizeof(kb)); - return ltc_ecc_map(R, modulus, mp); -} - -/** ECC Fixed Point mulmod global - Computes kA*A + kB*B = C using Shamir's Trick - @param A First point to multiply - @param kA What to multiple A by - @param B Second point to multiply - @param kB What to multiple B by - @param C [out] Destination point (can overlap with A or B) - @param modulus Modulus for curve - @return CRYPT_OK on success -*/ -int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, - ecc_point *B, void *kB, - ecc_point *C, - void *a, - void *modulus) -{ - int idx1, idx2, err; - void *mp, *mu; - - mp = NULL; - mu = NULL; - LTC_MUTEX_LOCK(<c_ecc_fp_lock); - /* find point */ - idx1 = s_find_base(A); - - /* no entry? */ - if (idx1 == -1) { - /* find hole and add it */ - if ((idx1 = s_find_hole()) >= 0) { - if ((err = s_add_entry(idx1, A)) != CRYPT_OK) { - goto LBL_ERR; - } - } - } - if (idx1 != -1) { - /* increment LRU */ - ++(fp_cache[idx1].lru_count); - } - - /* find point */ - idx2 = s_find_base(B); - - /* no entry? */ - if (idx2 == -1) { - /* find hole and add it */ - if ((idx2 = s_find_hole()) >= 0) { - if ((err = s_add_entry(idx2, B)) != CRYPT_OK) { - goto LBL_ERR; - } - } - } - if (idx2 != -1) { - /* increment LRU */ - ++(fp_cache[idx2].lru_count); - } - - /* if it's 2 build the LUT, if it's higher just use the LUT */ - if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - - /* compute mu */ - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* build the LUT */ - if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR;; - } - } - - /* if it's 2 build the LUT, if it's higher just use the LUT */ - if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) { - if (mp == NULL) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - - /* compute mu */ - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* build the LUT */ - if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR;; - } - } - - - if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && fp_cache[idx2].lru_count >= 2) { - if (mp == NULL) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - } - err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); - } else { - err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); - } -LBL_ERR: - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - if (mp != NULL) { - ltc_mp_montgomery_free(mp); - } - if (mu != NULL) { - ltc_mp_clear(mu); - } - return err; -} -#endif - -/** ECC Fixed Point mulmod global - @param k The multiplicand - @param G Base point to multiply - @param R [out] Destination of product - @param a ECC curve parameter a - @param modulus The modulus for the curve - @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form - @return CRYPT_OK if successful -*/ -int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) -{ - int idx, err; - void *mp, *mu; - - mp = NULL; - mu = NULL; - LTC_MUTEX_LOCK(<c_ecc_fp_lock); - /* find point */ - idx = s_find_base(G); - - /* no entry? */ - if (idx == -1) { - /* find hole and add it */ - idx = s_find_hole(); - - if (idx >= 0) { - if ((err = s_add_entry(idx, G)) != CRYPT_OK) { - goto LBL_ERR; - } - } - } - if (idx != -1) { - /* increment LRU */ - ++(fp_cache[idx].lru_count); - } - - - /* if it's 2 build the LUT, if it's higher just use the LUT */ - if (idx >= 0 && fp_cache[idx].lru_count == 2) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - - /* compute mu */ - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* build the LUT */ - if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR;; - } - } - - if (idx >= 0 && fp_cache[idx].lru_count >= 2) { - if (mp == NULL) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - } - err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map); - } else { - err = ltc_ecc_mulmod(k, G, R, a, modulus, map); - } -LBL_ERR: - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - if (mp != NULL) { - ltc_mp_montgomery_free(mp); - } - if (mu != NULL) { - ltc_mp_clear(mu); - } - return err; -} - -/* helper function for freeing the cache ... must be called with the cache mutex locked */ -static void s_ltc_ecc_fp_free_cache(void) -{ - unsigned x, y; - for (x = 0; x < FP_ENTRIES; x++) { - if (fp_cache[x].g != NULL) { - for (y = 0; y < (1U<= 0) { - /* it is already in the cache ... just check that the LUT is initialized */ - if(fp_cache[idx].lru_count >= 2) { - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - return CRYPT_OK; - } - } - - if(idx == -1 && (idx = s_find_hole()) == -1) { - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - if ((err = s_add_entry(idx, g)) != CRYPT_OK) { - goto LBL_ERR; - } - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* compute mu */ - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* build the LUT */ - if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR; - } - fp_cache[idx].lru_count = 2; - fp_cache[idx].lock = lock; -LBL_ERR: - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - if (mp != NULL) { - ltc_mp_montgomery_free(mp); - } - if (mu != NULL) { - ltc_mp_clear(mu); - } - return err; -} - -/** Prevent/permit the FP cache from being updated - @param flag If flag is 0, remove cache lock (unlock), otherwise lock it -*/ -void ltc_ecc_fp_tablelock(int lock) -{ - int i; - - LTC_MUTEX_LOCK(<c_ecc_fp_lock); - for (i = 0; i < FP_ENTRIES; i++) { - fp_cache[i].lock = lock; - } - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); -} - -/** Export the current cache as a binary packet - @param out [out] pointer to malloc'ed space containing the packet - @param outlen [out] size of exported packet - @return CRYPT_OK if successful -*/ -int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen) -{ - ltc_asn1_list *cache_entry; - unsigned int i, j, k; - unsigned long fp_entries, fp_lut, num_entries; - int err; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - fp_entries = FP_ENTRIES; - fp_lut = FP_LUT; - num_entries = 0; - - LTC_MUTEX_LOCK(<c_ecc_fp_lock); - /* - * build the list; - Cache DEFINITIONS ::= - BEGIN - CacheDump ::= SEQUENCE { - numEntries SHORTINTEGER, - maxEntries SHORTINTEGER, - numLUT SHORTINTEGER, - cache SEQUENCE OF INTEGER - } - END - * - */ - /* - * The cache itself is a point (3 INTEGERS), - * the LUT as pairs of INTEGERS (2 * 1<x, 1); - LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); - LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); - for (k = 0; k < (1U<x, 1); - LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].LUT[k]->y, 1); - } - LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); - } - LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_EOL, 0, 0); - - LTC_SET_ASN1(cache_entry, 0, LTC_ASN1_SHORT_INTEGER, &num_entries, 1); - - if ((err = der_length_sequence(cache_entry, j, outlen)) != CRYPT_OK) { - goto save_err; - } - if ((*out = XMALLOC(*outlen)) == NULL) { - err = CRYPT_MEM; - goto save_err; - } - err = der_encode_sequence(cache_entry, j, *out, outlen); -save_err: - XFREE(cache_entry); - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - return err; -} - -/** Import a binary packet into the current cache - @param in [in] pointer to packet - @param inlen [in] size of packet (bytes) - @return CRYPT_OK if successful -*/ -int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) -{ - int err; - ltc_asn1_list *asn1_list; - unsigned long num_entries, fp_entries, fp_lut; - unsigned long i, j; - unsigned int x; - - LTC_ARGCHK(in != NULL); - if (inlen == 0) { - return CRYPT_INVALID_ARG; - } - - /* zero indecies */ - i = 0; - j = 0; - asn1_list = NULL; - - LTC_MUTEX_LOCK(<c_ecc_fp_lock); - /* - * start with an empty cache - */ - s_ltc_ecc_fp_free_cache(); - - /* - * decode the input packet: It consists of a sequence with a few - * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a - * SEQUENCE which is the cache itself. - * - * use standard decoding for the first part, then flexible for the second - */ - if((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1, &num_entries, - LTC_ASN1_SHORT_INTEGER, 1, &fp_entries, - LTC_ASN1_SHORT_INTEGER, 1, &fp_lut, - LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) { - goto ERR_OUT; - } - if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { - err = CRYPT_INVALID_PACKET; - goto ERR_OUT; - } - if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<x, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); - for (x = 0; x < (1U<x, &p->y, LTC_NULL)) != CRYPT_OK) { - goto ERR_OUT; - } - p->z = NULL; - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1); - } - if((err = ltc_mp_init(&fp_cache[i].mu)) != CRYPT_OK) { - goto ERR_OUT; - } - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); - fp_cache[i].lru_count = 3; - fp_cache[i].lock = 1; - } - - if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) { - goto ERR_OUT; - } - XFREE(asn1_list); - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - return CRYPT_OK; -ERR_OUT: - if(asn1_list) - XFREE(asn1_list); - s_ltc_ecc_fp_free_cache(); - LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); - return err; -} - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/math/gmp_desc.c b/Sources/DataLiteC/libtomcrypt/math/gmp_desc.c deleted file mode 100644 index 943f37e..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/gmp_desc.c +++ /dev/null @@ -1,658 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#define DESC_DEF_ONLY -#include "tomcrypt_private.h" - -#ifdef GMP_DESC - -#include -#include - -static int init(void **a) -{ - LTC_ARGCHK(a != NULL); - - *a = XCALLOC(1, sizeof(__mpz_struct)); - if (*a == NULL) { - return CRYPT_MEM; - } - mpz_init(*a); - return CRYPT_OK; -} - -static void deinit(void *a) -{ - LTC_ARGCHKVD(a != NULL); - mpz_clear(a); - XFREE(a); -} - -static int neg(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_neg(b, a); - return CRYPT_OK; -} - -static int copy(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_set(b, a); - return CRYPT_OK; -} - -static int init_copy(void **a, const void *b) -{ - if (init(a) != CRYPT_OK) { - return CRYPT_MEM; - } - return copy(b, *a); -} - -/* ---- trivial ---- */ -static int set_int(void *a, ltc_mp_digit b) -{ - LTC_ARGCHK(a != NULL); - mpz_set_ui(a, b); - return CRYPT_OK; -} - -static unsigned long get_int(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mpz_get_ui(a); -} - -static ltc_mp_digit get_digit(const void *a, int n) -{ - LTC_ARGCHK(a != NULL); - return mpz_getlimbn(a, n); -} - -static int get_digit_count(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mpz_size(a); -} - -static int compare(const void *a, const void *b) -{ - int ret; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - ret = mpz_cmp(a, b); - if (ret < 0) { - return LTC_MP_LT; - } else if (ret > 0) { - return LTC_MP_GT; - } else { - return LTC_MP_EQ; - } -} - -static int compare_d(const void *a, ltc_mp_digit b) -{ - int ret; - LTC_ARGCHK(a != NULL); - ret = mpz_cmp_ui((__mpz_struct *)a, b); - if (ret < 0) { - return LTC_MP_LT; - } else if (ret > 0) { - return LTC_MP_GT; - } else { - return LTC_MP_EQ; - } -} - -static int count_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mpz_sizeinbase(a, 2); -} - -static int count_lsb_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mpz_scan1(a, 0); -} - - -static int twoexpt(void *a, int n) -{ - LTC_ARGCHK(a != NULL); - mpz_set_ui(a, 0); - mpz_setbit(a, n); - return CRYPT_OK; -} - -/* ---- conversions ---- */ - -static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - -/* read ascii string */ -static int read_radix(void *a, const char *b, int radix) -{ - int ret; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - if (radix == 64) { - /* Sadly, GMP only supports radixes up to 62, but we need 64. - * So, although this is not the most elegant or efficient way, - * let's just convert the base 64 string (6 bits per digit) to - * an octal string (3 bits per digit) that's twice as long. */ - char c, *tmp, *q; - const char *p; - int i; - tmp = XMALLOC (1 + 2 * XSTRLEN (b)); - if (tmp == NULL) { - return CRYPT_MEM; - } - p = b; - q = tmp; - while ((c = *p++) != 0) { - for (i = 0; i < 64; i++) { - if (c == rmap[i]) - break; - } - if (i == 64) { - XFREE (tmp); - /* printf ("c = '%c'\n", c); */ - return CRYPT_ERROR; - } - *q++ = '0' + (i / 8); - *q++ = '0' + (i % 8); - } - *q = 0; - ret = mpz_set_str(a, tmp, 8); - /* printf ("ret = %d for '%s'\n", ret, tmp); */ - XFREE (tmp); - } else { - ret = mpz_set_str(a, b, radix); - } - return (ret == 0 ? CRYPT_OK : CRYPT_ERROR); -} - -/* write one */ -static int write_radix(const void *a, char *b, int radix) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - if (radix >= 11 && radix <= 36) - /* If radix is positive, GMP uses lowercase, and if negative, uppercase. - * We want it to use uppercase, to match the test vectors (presumably - * generated with LibTomMath). */ - radix = -radix; - mpz_get_str(b, radix, a); - return CRYPT_OK; -} - -/* get size as unsigned char string */ -static unsigned long unsigned_size(const void *a) -{ - unsigned long t; - LTC_ARGCHK(a != NULL); - t = mpz_sizeinbase(a, 2); - if (mpz_cmp_ui((__mpz_struct *)a, 0) == 0) return 0; - return (t>>3) + ((t&7)?1:0); -} - -/* store */ -static int unsigned_write(const void *a, unsigned char *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_export(b, NULL, 1, 1, 1, 0, a); - return CRYPT_OK; -} - -/* read */ -static int unsigned_read(void *a, const unsigned char *b, unsigned long len) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_import(a, len, 1, 1, 1, 0, b); - return CRYPT_OK; -} - -/* add */ -static int add(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_add(c, a, b); - return CRYPT_OK; -} - -static int addi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - mpz_add_ui(c, a, b); - return CRYPT_OK; -} - -/* sub */ -static int sub(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_sub(c, a, b); - return CRYPT_OK; -} - -static int subi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - mpz_sub_ui(c, a, b); - return CRYPT_OK; -} - -/* mul */ -static int mul(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_mul(c, a, b); - return CRYPT_OK; -} - -static int muli(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - mpz_mul_ui(c, a, b); - return CRYPT_OK; -} - -/* sqr */ -static int sqr(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_mul(b, a, a); - return CRYPT_OK; -} - -/* sqrtmod_prime */ -static int sqrtmod_prime(const void *n, const void *prime, void *ret) -{ - int res, legendre, i; - mpz_t t1, C, Q, S, Z, M, T, R, two; - - LTC_ARGCHK(n != NULL); - LTC_ARGCHK(prime != NULL); - LTC_ARGCHK(ret != NULL); - - /* first handle the simple cases */ - if (mpz_cmp_ui((__mpz_struct *)n, 0) == 0) { - mpz_set_ui(ret, 0); - return CRYPT_OK; - } - if (mpz_cmp_ui((__mpz_struct *)prime, 2) == 0) return CRYPT_ERROR; /* prime must be odd */ - legendre = mpz_legendre(n, prime); - if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */ - - mpz_init(t1); mpz_init(C); mpz_init(Q); - mpz_init(S); mpz_init(Z); mpz_init(M); - mpz_init(T); mpz_init(R); mpz_init(two); - - /* SPECIAL CASE: if prime mod 4 == 3 - * compute directly: res = n^(prime+1)/4 mod prime - * Handbook of Applied Cryptography algorithm 3.36 - */ - i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */ - if (i == 3) { - mpz_add_ui(t1, prime, 1); - mpz_fdiv_q_2exp(t1, t1, 2); - mpz_powm(ret, n, t1, prime); - res = CRYPT_OK; - goto cleanup; - } - - /* NOW: Tonelli-Shanks algorithm */ - - /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ - mpz_set(Q, prime); - mpz_sub_ui(Q, Q, 1); - /* Q = prime - 1 */ - mpz_set_ui(S, 0); - /* S = 0 */ - while (mpz_even_p(Q)) { - mpz_fdiv_q_2exp(Q, Q, 1); - /* Q = Q / 2 */ - mpz_add_ui(S, S, 1); - /* S = S + 1 */ - } - - /* find a Z such that the Legendre symbol (Z|prime) == -1 */ - mpz_set_ui(Z, 2); - /* Z = 2 */ - while(1) { - legendre = mpz_legendre(Z, prime); - if (legendre == -1) break; - mpz_add_ui(Z, Z, 1); - /* Z = Z + 1 */ - } - - mpz_powm(C, Z, Q, prime); - /* C = Z ^ Q mod prime */ - mpz_add_ui(t1, Q, 1); - mpz_fdiv_q_2exp(t1, t1, 1); - /* t1 = (Q + 1) / 2 */ - mpz_powm(R, n, t1, prime); - /* R = n ^ ((Q + 1) / 2) mod prime */ - mpz_powm(T, n, Q, prime); - /* T = n ^ Q mod prime */ - mpz_set(M, S); - /* M = S */ - mpz_set_ui(two, 2); - - while (1) { - mpz_set(t1, T); - i = 0; - while (1) { - if (mpz_cmp_ui(t1, 1) == 0) break; - mpz_powm(t1, t1, two, prime); - i++; - } - if (i == 0) { - mpz_set(ret, R); - res = CRYPT_OK; - goto cleanup; - } - mpz_sub_ui(t1, M, i); - mpz_sub_ui(t1, t1, 1); - mpz_powm(t1, two, t1, prime); - /* t1 = 2 ^ (M - i - 1) */ - mpz_powm(t1, C, t1, prime); - /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ - mpz_mul(C, t1, t1); - mpz_mod(C, C, prime); - /* C = (t1 * t1) mod prime */ - mpz_mul(R, R, t1); - mpz_mod(R, R, prime); - /* R = (R * t1) mod prime */ - mpz_mul(T, T, C); - mpz_mod(T, T, prime); - /* T = (T * C) mod prime */ - mpz_set_ui(M, i); - /* M = i */ - } - -cleanup: - mpz_clear(t1); mpz_clear(C); mpz_clear(Q); - mpz_clear(S); mpz_clear(Z); mpz_clear(M); - mpz_clear(T); mpz_clear(R); mpz_clear(two); - return res; -} - -/* div */ -static int divide(const void *a, const void *b, void *c, void *d) -{ - mpz_t tmp; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - if (c != NULL) { - mpz_init(tmp); - mpz_divexact(tmp, a, b); - } - if (d != NULL) { - mpz_mod(d, a, b); - } - if (c != NULL) { - mpz_set(c, tmp); - mpz_clear(tmp); - } - return CRYPT_OK; -} - -static int div_2(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_divexact_ui(b, a, 2); - return CRYPT_OK; -} - -/* modi */ -static int modi(const void *a, ltc_mp_digit b, ltc_mp_digit *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - - *c = mpz_fdiv_ui(a, b); - return CRYPT_OK; -} - -/* gcd */ -static int gcd(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_gcd(c, a, b); - return CRYPT_OK; -} - -/* lcm */ -static int lcm(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_lcm(c, a, b); - return CRYPT_OK; -} - -static int addmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - mpz_add(d, a, b); - mpz_mod(d, d, c); - return CRYPT_OK; -} - -static int submod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - mpz_sub(d, a, b); - mpz_mod(d, d, c); - return CRYPT_OK; -} - -static int mulmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - mpz_mul(d, a, b); - mpz_mod(d, d, c); - return CRYPT_OK; -} - -static int sqrmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_mul(c, a, a); - mpz_mod(c, c, b); - return CRYPT_OK; -} - -/* invmod */ -static int invmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_invert(c, a, b); - return CRYPT_OK; -} - -/* setup */ -static int montgomery_setup(const void *a, void **b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - *b = (void *)1; - return CRYPT_OK; -} - -/* get normalization value */ -static int montgomery_normalization(void *a, const void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - mpz_set_ui(a, 1); - return CRYPT_OK; -} - -/* reduce */ -static int montgomery_reduce(void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - mpz_mod(a, a, b); - return CRYPT_OK; -} - -/* clean up */ -static void montgomery_deinit(void *a) -{ - LTC_UNUSED_PARAM(a); -} - -static int exptmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - mpz_powm(d, a, b, c); - return CRYPT_OK; -} - -static int isprime(const void *a, int b, int *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - if (b == 0) { - b = LTC_MILLER_RABIN_REPS; - } /* if */ - *c = mpz_probab_prime_p(a, b) > 0 ? LTC_MP_YES : LTC_MP_NO; - return CRYPT_OK; -} - -static int set_rand(void *a, int size) -{ - LTC_ARGCHK(a != NULL); - mpz_random(a, size); - return CRYPT_OK; -} - -const ltc_math_descriptor gmp_desc = { - "GNU MP", - sizeof(mp_limb_t) * CHAR_BIT - GMP_NAIL_BITS, - - &init, - &init_copy, - &deinit, - - &neg, - ©, - - &set_int, - &get_int, - &get_digit, - &get_digit_count, - &compare, - &compare_d, - &count_bits, - &count_lsb_bits, - &twoexpt, - - &read_radix, - &write_radix, - &unsigned_size, - &unsigned_write, - &unsigned_read, - - &add, - &addi, - &sub, - &subi, - &mul, - &muli, - &sqr, - &sqrtmod_prime, - ÷, - &div_2, - &modi, - &gcd, - &lcm, - - &mulmod, - &sqrmod, - &invmod, - - &montgomery_setup, - &montgomery_normalization, - &montgomery_reduce, - &montgomery_deinit, - - &exptmod, - &isprime, - -#ifdef LTC_MECC -#ifdef LTC_MECC_FP - <c_ecc_fp_mulmod, -#else - <c_ecc_mulmod, -#endif /* LTC_MECC_FP */ - <c_ecc_projective_add_point, - <c_ecc_projective_dbl_point, - <c_ecc_map, -#ifdef LTC_ECC_SHAMIR -#ifdef LTC_MECC_FP - <c_ecc_fp_mul2add, -#else - <c_ecc_mul2add, -#endif /* LTC_MECC_FP */ -#else - NULL, -#endif /* LTC_ECC_SHAMIR */ -#else - NULL, NULL, NULL, NULL, NULL, -#endif /* LTC_MECC */ - -#ifdef LTC_MRSA - &rsa_make_key, - &rsa_exptmod, -#else - NULL, NULL, -#endif - &addmod, - &submod, - - &set_rand, - -}; - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/math/ltm_desc.c b/Sources/DataLiteC/libtomcrypt/math/ltm_desc.c deleted file mode 100644 index 99c9f14..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/ltm_desc.c +++ /dev/null @@ -1,560 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#define DESC_DEF_ONLY -#include "tomcrypt_private.h" - -#ifdef LTM_DESC - -#include -#if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) -#include -#endif - -static const struct { - mp_err mpi_code; - int ltc_code; -} mpi_to_ltc_codes[] = { - { MP_OKAY , CRYPT_OK}, - { MP_MEM , CRYPT_MEM}, - { MP_VAL , CRYPT_INVALID_ARG}, -#if defined(MP_BUF) || defined(MP_USE_ENUMS) - { MP_ITER , CRYPT_INVALID_PACKET}, - { MP_BUF , CRYPT_BUFFER_OVERFLOW}, -#endif -}; - -/** - Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) - @param err The error to convert - @return The equivalent LTC error code or CRYPT_ERROR if none found -*/ -static int mpi_to_ltc_error(mp_err err) -{ - size_t x; - - for (x = 0; x < LTC_ARRAY_SIZE(mpi_to_ltc_codes); x++) { - if (err == mpi_to_ltc_codes[x].mpi_code) { - return mpi_to_ltc_codes[x].ltc_code; - } - } - return CRYPT_ERROR; -} - -static int init_mpi(void **a) -{ - LTC_ARGCHK(a != NULL); - - *a = XCALLOC(1, sizeof(mp_int)); - if (*a == NULL) { - return CRYPT_MEM; - } else { - return CRYPT_OK; - } -} - -static int init(void **a) -{ - int err; - - LTC_ARGCHK(a != NULL); - - if ((err = init_mpi(a)) != CRYPT_OK) { - return err; - } - if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) { - XFREE(*a); - } - return err; -} - -static void deinit(void *a) -{ - LTC_ARGCHKVD(a != NULL); - mp_clear(a); - XFREE(a); -} - -static int neg(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_neg(a, b)); -} - -static int copy(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_copy(a, b)); -} - -static int init_copy(void **a, const void *b) -{ - int err; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - if ((err = init_mpi(a)) != CRYPT_OK) return err; - return mpi_to_ltc_error(mp_init_copy(*a, b)); -} - -/* ---- trivial ---- */ -static int set_int(void *a, ltc_mp_digit b) -{ - LTC_ARGCHK(a != NULL); -#ifdef BN_MP_SET_INT_C - return mpi_to_ltc_error(mp_set_int(a, b)); -#else - mp_set_u32(a, b); - return CRYPT_OK; -#endif -} - -static unsigned long get_int(const void *a) -{ - LTC_ARGCHK(a != NULL); -#ifdef BN_MP_GET_INT_C - return mp_get_int(a); -#else - return mp_get_ul(a); -#endif -} - -static ltc_mp_digit get_digit(const void *a, int n) -{ - const mp_int *A; - LTC_ARGCHK(a != NULL); - A = a; - return (n >= A->used || n < 0) ? 0 : A->dp[n]; -} - -static int get_digit_count(const void *a) -{ - const mp_int *A; - LTC_ARGCHK(a != NULL); - A = a; - return A->used; -} - -static int compare(const void *a, const void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - switch (mp_cmp(a, b)) { - case MP_LT: return LTC_MP_LT; - case MP_EQ: return LTC_MP_EQ; - case MP_GT: return LTC_MP_GT; - default: return 0; - } -} - -static int compare_d(const void *a, ltc_mp_digit b) -{ - LTC_ARGCHK(a != NULL); - switch (mp_cmp_d(a, b)) { - case MP_LT: return LTC_MP_LT; - case MP_EQ: return LTC_MP_EQ; - case MP_GT: return LTC_MP_GT; - default: return 0; - } -} - -static int count_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mp_count_bits(a); -} - -static int count_lsb_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return mp_cnt_lsb(a); -} - - -static int twoexpt(void *a, int n) -{ - LTC_ARGCHK(a != NULL); - return mpi_to_ltc_error(mp_2expt(a, n)); -} - -/* ---- conversions ---- */ - -/* read ascii string */ -static int read_radix(void *a, const char *b, int radix) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_read_radix(a, b, radix)); -} - -/* write one */ -static int write_radix(const void *a, char *b, int radix) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); -#ifdef BN_MP_TORADIX_C - return mpi_to_ltc_error(mp_toradix(a, b, radix)); -#else - return mpi_to_ltc_error(mp_to_radix(a, b, SIZE_MAX, NULL, radix)); -#endif -} - -/* get size as unsigned char string */ -static unsigned long unsigned_size(const void *a) -{ - LTC_ARGCHK(a != NULL); -#ifdef BN_MP_UNSIGNED_BIN_SIZE_C - return mp_unsigned_bin_size(a); -#else - return (unsigned long)mp_ubin_size(a); -#endif -} - -/* store */ -static int unsigned_write(const void *a, unsigned char *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); -#ifdef BN_MP_TO_UNSIGNED_BIN_C - return mpi_to_ltc_error(mp_to_unsigned_bin(a, b)); -#else - return mpi_to_ltc_error(mp_to_ubin(a, b, SIZE_MAX, NULL)); -#endif -} - -/* read */ -static int unsigned_read(void *a, const unsigned char *b, unsigned long len) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); -#ifdef BN_MP_READ_UNSIGNED_BIN_C - return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len)); -#else - return mpi_to_ltc_error(mp_from_ubin(a, b, (size_t)len)); -#endif -} - -/* add */ -static int add(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_add(a, b, c)); -} - -static int addi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_add_d(a, b, c)); -} - -/* sub */ -static int sub(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_sub(a, b, c)); -} - -static int subi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_sub_d(a, b, c)); -} - -/* mul */ -static int mul(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_mul(a, b, c)); -} - -static int muli(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_mul_d(a, b, c)); -} - -/* sqr */ -static int sqr(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_sqr(a, b)); -} - -/* sqrtmod_prime */ -static int sqrtmod_prime(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c)); -} - -/* div */ -static int divide(const void *a, const void *b, void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_div(a, b, c, d)); -} - -static int div_2(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_div_2(a, b)); -} - -/* modi */ -static int modi(const void *a, ltc_mp_digit b, ltc_mp_digit *c) -{ - mp_digit tmp; - int err; - - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - - if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) { - return err; - } - *c = tmp; - return CRYPT_OK; -} - -/* gcd */ -static int gcd(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_gcd(a, b, c)); -} - -/* lcm */ -static int lcm(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_lcm(a, b, c)); -} - -static int addmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return mpi_to_ltc_error(mp_addmod(a,b,c,d)); -} - -static int submod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return mpi_to_ltc_error(mp_submod(a,b,c,d)); -} - -static int mulmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return mpi_to_ltc_error(mp_mulmod(a,b,c,d)); -} - -static int sqrmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_sqrmod(a,b,c)); -} - -/* invmod */ -static int invmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_invmod(a, b, c)); -} - -/* setup */ -static int montgomery_setup(const void *a, void **b) -{ - int err; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - *b = XCALLOC(1, sizeof(mp_digit)); - if (*b == NULL) { - return CRYPT_MEM; - } - if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, *b))) != CRYPT_OK) { - XFREE(*b); - } - return err; -} - -/* get normalization value */ -static int montgomery_normalization(void *a, const void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b)); -} - -/* reduce */ -static int montgomery_reduce(void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c))); -} - -/* clean up */ -static void montgomery_deinit(void *a) -{ - XFREE(a); -} - -static int exptmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return mpi_to_ltc_error(mp_exptmod(a,b,c,d)); -} - -static int isprime(const void *a, int b, int *c) -{ - int err; -#if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) - int res; -#else - bool res; -#endif - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - b = mp_prime_rabin_miller_trials(mp_count_bits(a)); - err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); - *c = res ? LTC_MP_YES : LTC_MP_NO; - return err; -} - -static int set_rand(void *a, int size) -{ - LTC_ARGCHK(a != NULL); - return mpi_to_ltc_error(mp_rand(a, size)); -} - -#ifndef MP_DIGIT_BIT -#define MP_DIGIT_BIT DIGIT_BIT -#endif - -const ltc_math_descriptor ltm_desc = { - - "LibTomMath", - (int)MP_DIGIT_BIT, - - &init, - &init_copy, - &deinit, - - &neg, - ©, - - &set_int, - &get_int, - &get_digit, - &get_digit_count, - &compare, - &compare_d, - &count_bits, - &count_lsb_bits, - &twoexpt, - - &read_radix, - &write_radix, - &unsigned_size, - &unsigned_write, - &unsigned_read, - - &add, - &addi, - &sub, - &subi, - &mul, - &muli, - &sqr, - &sqrtmod_prime, - ÷, - &div_2, - &modi, - &gcd, - &lcm, - - &mulmod, - &sqrmod, - &invmod, - - &montgomery_setup, - &montgomery_normalization, - &montgomery_reduce, - &montgomery_deinit, - - &exptmod, - &isprime, - -#ifdef LTC_MECC -#ifdef LTC_MECC_FP - <c_ecc_fp_mulmod, -#else - <c_ecc_mulmod, -#endif - <c_ecc_projective_add_point, - <c_ecc_projective_dbl_point, - <c_ecc_map, -#ifdef LTC_ECC_SHAMIR -#ifdef LTC_MECC_FP - <c_ecc_fp_mul2add, -#else - <c_ecc_mul2add, -#endif /* LTC_MECC_FP */ -#else - NULL, -#endif /* LTC_ECC_SHAMIR */ -#else - NULL, NULL, NULL, NULL, NULL, -#endif /* LTC_MECC */ - -#ifdef LTC_MRSA - &rsa_make_key, - &rsa_exptmod, -#else - NULL, NULL, -#endif - &addmod, - &submod, - - &set_rand, - -}; - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/math/multi.c b/Sources/DataLiteC/libtomcrypt/math/multi.c deleted file mode 100644 index 1b7058f..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/multi.c +++ /dev/null @@ -1,64 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_MPI -int ltc_mp_init_multi(void **a, ...) -{ - void **cur = a; - int np = 0; - va_list args; - - va_start(args, a); - while (cur != NULL) { - if (ltc_mp_init(cur) != CRYPT_OK) { - /* failed */ - va_list clean_list; - - va_start(clean_list, a); - cur = a; - while (np--) { - ltc_mp_clear(*cur); - cur = va_arg(clean_list, void**); - } - va_end(clean_list); - va_end(args); - return CRYPT_MEM; - } - ++np; - cur = va_arg(args, void**); - } - va_end(args); - return CRYPT_OK; -} - -void ltc_mp_deinit_multi(void *a, ...) -{ - void *cur = a; - va_list args; - - va_start(args, a); - while (cur != NULL) { - ltc_mp_clear(cur); - cur = va_arg(args, void *); - } - va_end(args); -} - -void ltc_mp_cleanup_multi(void **a, ...) -{ - void **cur = a; - va_list args; - - va_start(args, a); - while (cur != NULL) { - if (*cur != NULL) { - ltc_mp_clear(*cur); - *cur = NULL; - } - cur = va_arg(args, void**); - } - va_end(args); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/math/radix_to_bin.c b/Sources/DataLiteC/libtomcrypt/math/radix_to_bin.c deleted file mode 100644 index 9a7d02d..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/radix_to_bin.c +++ /dev/null @@ -1,52 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file radix_to_bin.c - Convert data from a specific radix to binary. - Steffen Jaeckel -*/ - -/** - Convert data from a specific radix to binary - - The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc - have the following restrictions on parameters: - - \p in - NUL-terminated char buffer - - \p radix - 2..64 - - @param in The input - @param radix The radix of the input - @param out The output buffer - @param len [in/out] The length of the output buffer - - @return CRYPT_OK on success. -*/ -int radix_to_bin(const void *in, int radix, void *out, unsigned long *len) -{ - unsigned long l; - void* mpi; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(len != NULL); - - if ((err = ltc_mp_init(&mpi)) != CRYPT_OK) return err; - if ((err = ltc_mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR; - - if ((l = ltc_mp_unsigned_bin_size(mpi)) > *len) { - *len = l; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - *len = l; - - if ((err = ltc_mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR; - -LBL_ERR: - ltc_mp_clear(mpi); - return err; -} diff --git a/Sources/DataLiteC/libtomcrypt/math/rand_bn.c b/Sources/DataLiteC/libtomcrypt/math/rand_bn.c deleted file mode 100644 index 4f9f4f2..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/rand_bn.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#if defined(LTC_MDSA) || defined(LTC_MECC) -/** - Generate a random number N with given bitlength (note: MSB can be 0) -*/ - -int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng) -{ - int res, bytes; - unsigned char *buf, mask; - - LTC_ARGCHK(N != NULL); - LTC_ARGCHK(bits > 1); - - /* check PRNG */ - if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res; - - bytes = (bits+7) >> 3; - mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8); - - /* allocate buffer */ - if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM; - - /* generate random bytes */ - if (prng_descriptor[wprng].read(buf, bytes, prng) != (unsigned long)bytes) { - res = CRYPT_ERROR_READPRNG; - goto cleanup; - } - /* mask bits */ - buf[0] &= mask; - /* load value */ - if ((res = ltc_mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup; - - res = CRYPT_OK; - -cleanup: -#ifdef LTC_CLEAN_STACK - zeromem(buf, bytes); -#endif - XFREE(buf); - return res; -} - -/** - Generate a random number N in a range: 1 <= N < limit -*/ -int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng) -{ - int res, bits; - - LTC_ARGCHK(N != NULL); - LTC_ARGCHK(limit != NULL); - - bits = ltc_mp_count_bits(limit); - do { - res = rand_bn_bits(N, bits, prng, wprng); - if (res != CRYPT_OK) return res; - } while (ltc_mp_cmp_d(N, 0) != LTC_MP_GT || ltc_mp_cmp(N, limit) != LTC_MP_LT); - - return CRYPT_OK; -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/math/rand_prime.c b/Sources/DataLiteC/libtomcrypt/math/rand_prime.c deleted file mode 100644 index 0cd6c0d..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/rand_prime.c +++ /dev/null @@ -1,78 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS)) - -/** - @file rand_prime.c - Generate a random prime, Tom St Denis -*/ - -#define USE_BBS 1 - -int rand_prime(void *N, long len, prng_state *prng, int wprng) -{ - int err, res, type; - unsigned char *buf; - - LTC_ARGCHK(N != NULL); - - /* get type */ - if (len < 0) { - type = USE_BBS; - len = -len; - } else { - type = 0; - } - - /* allow sizes between 2 and 512 bytes for a prime size */ - if (len < 2 || len > 512) { - return CRYPT_INVALID_PRIME_SIZE; - } - - /* valid PRNG? Better be! */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - /* allocate buffer to work with */ - buf = XCALLOC(1, len); - if (buf == NULL) { - return CRYPT_MEM; - } - - do { - /* generate value */ - if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) { - XFREE(buf); - return CRYPT_ERROR_READPRNG; - } - - /* munge bits */ - buf[0] |= 0x80 | 0x40; - buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); - - /* load value */ - if ((err = ltc_mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) { - XFREE(buf); - return err; - } - - /* test */ - if ((err = ltc_mp_prime_is_prime(N, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { - XFREE(buf); - return err; - } - } while (res == LTC_MP_NO); - -#ifdef LTC_CLEAN_STACK - zeromem(buf, len); -#endif - - XFREE(buf); - return CRYPT_OK; -} - -#endif /* LTC_NO_MATH */ - diff --git a/Sources/DataLiteC/libtomcrypt/math/tfm_desc.c b/Sources/DataLiteC/libtomcrypt/math/tfm_desc.c deleted file mode 100644 index 7c3b400..0000000 --- a/Sources/DataLiteC/libtomcrypt/math/tfm_desc.c +++ /dev/null @@ -1,875 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#define DESC_DEF_ONLY -#include "tomcrypt_private.h" - -#ifdef TFM_DESC - -#include - -#if !defined(TFM_VERSION_3) -# if 0 /* Enable if desirable */ -# warning "pre-constification TFM used (TFM_VERSION_3 undefined)" -# endif -# define TFM_UNCONST(type) (type) -#elif TFM_VERSION <= TFM_VERSION_3(0, 13, 89) -# if 0 /* Enable if desirable */ -# warning "pre-constification TFM used (older version detected)" -# endif -# define TFM_UNCONST(type) (type) -#else -# define TFM_UNCONST(type) -#endif - -static const struct { - int tfm_code, ltc_code; -} tfm_to_ltc_codes[] = { - { FP_OKAY , CRYPT_OK}, - { FP_MEM , CRYPT_MEM}, - { FP_VAL , CRYPT_INVALID_ARG}, -}; - -/** - Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no) - @param err The error to convert - @return The equivalent LTC error code or CRYPT_ERROR if none found -*/ -static int tfm_to_ltc_error(int err) -{ - int x; - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tfm_to_ltc_codes); x++) { - if (err == tfm_to_ltc_codes[x].tfm_code) { - return tfm_to_ltc_codes[x].ltc_code; - } - } - return CRYPT_ERROR; -} - -static int init(void **a) -{ - LTC_ARGCHK(a != NULL); - - *a = XCALLOC(1, sizeof(fp_int)); - if (*a == NULL) { - return CRYPT_MEM; - } - fp_init(*a); - return CRYPT_OK; -} - -static void deinit(void *a) -{ - LTC_ARGCHKVD(a != NULL); - XFREE(a); -} - -static int neg(const void *a, void *b) -{ - /* fp_neg() is a macro that accesses the internals of the b */ - fp_int *tmpb = b; - - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_neg(a, tmpb); - return CRYPT_OK; -} - -static int copy(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_copy(a, b); - return CRYPT_OK; -} - -static int init_copy(void **a, const void *b) -{ - if (init(a) != CRYPT_OK) { - return CRYPT_MEM; - } - return copy(b, *a); -} - -/* ---- trivial ---- */ -static int set_int(void *a, ltc_mp_digit b) -{ - LTC_ARGCHK(a != NULL); - fp_set(a, b); - return CRYPT_OK; -} - -static unsigned long get_int(const void *a) -{ - const fp_int *A; - LTC_ARGCHK(a != NULL); - A = a; - return A->used > 0 ? A->dp[0] : 0; -} - -static ltc_mp_digit get_digit(const void *a, int n) -{ - const fp_int *A; - LTC_ARGCHK(a != NULL); - A = a; - return (n >= A->used || n < 0) ? 0 : A->dp[n]; -} - -static int get_digit_count(const void *a) -{ - const fp_int *A; - LTC_ARGCHK(a != NULL); - A = a; - return A->used; -} - -static int compare(const void *a, const void *b) -{ - int ret; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - ret = fp_cmp(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b); - switch (ret) { - case FP_LT: return LTC_MP_LT; - case FP_EQ: return LTC_MP_EQ; - case FP_GT: return LTC_MP_GT; - } - return 0; -} - -static int compare_d(const void *a, ltc_mp_digit b) -{ - int ret; - LTC_ARGCHK(a != NULL); - ret = fp_cmp_d(TFM_UNCONST(void *)a, b); - switch (ret) { - case FP_LT: return LTC_MP_LT; - case FP_EQ: return LTC_MP_EQ; - case FP_GT: return LTC_MP_GT; - } - return 0; -} - -static int count_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return fp_count_bits(TFM_UNCONST(void *)a); -} - -static int count_lsb_bits(const void *a) -{ - LTC_ARGCHK(a != NULL); - return fp_cnt_lsb(TFM_UNCONST(void *)a); -} - -static int twoexpt(void *a, int n) -{ - LTC_ARGCHK(a != NULL); - fp_2expt(a, n); - return CRYPT_OK; -} - -/* ---- conversions ---- */ - -/* read ascii string */ -static int read_radix(void *a, const char *b, int radix) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return tfm_to_ltc_error(fp_read_radix(a, b, radix)); -} - -/* write one */ -static int write_radix(const void *a, char *b, int radix) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return tfm_to_ltc_error(fp_toradix(TFM_UNCONST(void *)a, b, radix)); -} - -/* get size as unsigned char string */ -static unsigned long unsigned_size(const void *a) -{ - LTC_ARGCHK(a != NULL); - return fp_unsigned_bin_size(TFM_UNCONST(void *)a); -} - -/* store */ -static int unsigned_write(const void *a, unsigned char *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_to_unsigned_bin(TFM_UNCONST(void *)a, b); - return CRYPT_OK; -} - -/* read */ -static int unsigned_read(void *a, const unsigned char *b, unsigned long len) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_read_unsigned_bin(a, b, len); - return CRYPT_OK; -} - -/* add */ -static int add(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_add(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c); - return CRYPT_OK; -} - -static int addi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - fp_add_d(TFM_UNCONST(void *)a, b, c); - return CRYPT_OK; -} - -/* sub */ -static int sub(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_sub(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c); - return CRYPT_OK; -} - -static int subi(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - fp_sub_d(TFM_UNCONST(void *)a, b, c); - return CRYPT_OK; -} - -/* mul */ -static int mul(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_mul(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c); - return CRYPT_OK; -} - -static int muli(const void *a, ltc_mp_digit b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - fp_mul_d(TFM_UNCONST(void *)a, b, c); - return CRYPT_OK; -} - -/* sqr */ -static int sqr(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_sqr(TFM_UNCONST(void *)a, b); - return CRYPT_OK; -} - -/* sqrtmod_prime - NOT SUPPORTED */ - -/* div */ -static int divide(const void *a, const void *b, void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - return tfm_to_ltc_error(fp_div(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c, d)); -} - -static int div_2(const void *a, void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_div_2(TFM_UNCONST(void *)a, b); - return CRYPT_OK; -} - -/* modi */ -static int modi(const void *a, ltc_mp_digit b, ltc_mp_digit *c) -{ - fp_digit tmp; - int err; - - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - - if ((err = tfm_to_ltc_error(fp_mod_d(TFM_UNCONST(void *)a, b, &tmp))) != CRYPT_OK) { - return err; - } - *c = tmp; - return CRYPT_OK; -} - -/* gcd */ -static int gcd(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_gcd(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c); - return CRYPT_OK; -} - -/* lcm */ -static int lcm(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_lcm(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c); - return CRYPT_OK; -} - -static int addmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return tfm_to_ltc_error(fp_addmod(TFM_UNCONST(void *)a,TFM_UNCONST(void *)b,TFM_UNCONST(void *)c,d)); -} - -static int submod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return tfm_to_ltc_error(fp_submod(TFM_UNCONST(void *)a,TFM_UNCONST(void *)b,TFM_UNCONST(void *)c,d)); -} - -static int mulmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return tfm_to_ltc_error(fp_mulmod(TFM_UNCONST(void *)a,TFM_UNCONST(void *)b,TFM_UNCONST(void *)c,d)); -} - -static int sqrmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return tfm_to_ltc_error(fp_sqrmod(TFM_UNCONST(void *)a,TFM_UNCONST(void *)b,c)); -} - -/* invmod */ -static int invmod(const void *a, const void *b, void *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - return tfm_to_ltc_error(fp_invmod(TFM_UNCONST(void *)a, TFM_UNCONST(void *)b, c)); -} - -/* setup */ -static int montgomery_setup(const void *a, void **b) -{ - int err; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - *b = XCALLOC(1, sizeof(fp_digit)); - if (*b == NULL) { - return CRYPT_MEM; - } - if ((err = tfm_to_ltc_error(fp_montgomery_setup(TFM_UNCONST(void *)a, *b))) != CRYPT_OK) { - XFREE(*b); - } - return err; -} - -/* get normalization value */ -static int montgomery_normalization(void *a, const void *b) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - fp_montgomery_calc_normalization(a, TFM_UNCONST(void *)b); - return CRYPT_OK; -} - -/* reduce */ -static int montgomery_reduce(void *a, const void *b, void *c) -{ - fp_digit *tmpc = c; - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - fp_montgomery_reduce(a, TFM_UNCONST(void *)b, *tmpc); - return CRYPT_OK; -} - -/* clean up */ -static void montgomery_deinit(void *a) -{ - XFREE(a); -} - -static int exptmod(const void *a, const void *b, const void *c, void *d) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(c != NULL); - LTC_ARGCHK(d != NULL); - return tfm_to_ltc_error(fp_exptmod(TFM_UNCONST(void *)a,TFM_UNCONST(void *)b,TFM_UNCONST(void *)c,d)); -} - -static int isprime(const void *a, int b, int *c) -{ - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(c != NULL); - if (b == 0) { - b = LTC_MILLER_RABIN_REPS; - } /* if */ - *c = (fp_isprime_ex(TFM_UNCONST(void *)a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO; - return CRYPT_OK; -} - -#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL) - -static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, const void *ma, const void *modulus, void *Mp) -{ - fp_int t1, t2; - fp_digit mp; - int err, inf; - - LTC_ARGCHK(P != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - LTC_ARGCHK(Mp != NULL); - - mp = *((fp_digit*)Mp); - - fp_init(&t1); - fp_init(&t2); - - if (P != R) { - fp_copy(P->x, R->x); - fp_copy(P->y, R->y); - fp_copy(P->z, R->z); - } - - if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* if P is point at infinity >> Result = point at infinity */ - ltc_mp.set_int(R->x, 1); - ltc_mp.set_int(R->y, 1); - ltc_mp.set_int(R->z, 0); - return CRYPT_OK; - } - - /* t1 = Z * Z */ - fp_sqr(R->z, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* Z = Y * Z */ - fp_mul(R->z, R->y, R->z); - fp_montgomery_reduce(R->z, TFM_UNCONST(void *)modulus, mp); - /* Z = 2Z */ - fp_add(R->z, R->z, R->z); - if (fp_cmp(R->z, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(R->z, TFM_UNCONST(void *)modulus, R->z); - } - - if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ - /* T2 = X - T1 */ - fp_sub(R->x, &t1, &t2); - if (fp_cmp_d(&t2, 0) == LTC_MP_LT) { - fp_add(&t2, TFM_UNCONST(void *)modulus, &t2); - } - /* T1 = X + T1 */ - fp_add(&t1, R->x, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* T2 = T1 * T2 */ - fp_mul(&t1, &t2, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T1 = 2T2 */ - fp_add(&t2, &t2, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - } - else { - /* T2 = T1 * T1 */ - fp_sqr(&t1, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T1 = T2 * a */ - fp_mul(&t2, TFM_UNCONST(void *)ma, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* T2 = X * X */ - fp_sqr(R->x, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - } - - /* Y = 2Y */ - fp_add(R->y, R->y, R->y); - if (fp_cmp(R->y, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(R->y, TFM_UNCONST(void *)modulus, R->y); - } - /* Y = Y * Y */ - fp_sqr(R->y, R->y); - fp_montgomery_reduce(R->y, TFM_UNCONST(void *)modulus, mp); - /* T2 = Y * Y */ - fp_sqr(R->y, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T2 = T2/2 */ - if (fp_isodd(&t2)) { - fp_add(&t2, TFM_UNCONST(void *)modulus, &t2); - } - fp_div_2(&t2, &t2); - /* Y = Y * X */ - fp_mul(R->y, R->x, R->y); - fp_montgomery_reduce(R->y, TFM_UNCONST(void *)modulus, mp); - - /* X = T1 * T1 */ - fp_sqr(&t1, R->x); - fp_montgomery_reduce(R->x, TFM_UNCONST(void *)modulus, mp); - /* X = X - Y */ - fp_sub(R->x, R->y, R->x); - if (fp_cmp_d(R->x, 0) == FP_LT) { - fp_add(R->x, TFM_UNCONST(void *)modulus, R->x); - } - /* X = X - Y */ - fp_sub(R->x, R->y, R->x); - if (fp_cmp_d(R->x, 0) == FP_LT) { - fp_add(R->x, TFM_UNCONST(void *)modulus, R->x); - } - - /* Y = Y - X */ - fp_sub(R->y, R->x, R->y); - if (fp_cmp_d(R->y, 0) == FP_LT) { - fp_add(R->y, TFM_UNCONST(void *)modulus, R->y); - } - /* Y = Y * T1 */ - fp_mul(R->y, &t1, R->y); - fp_montgomery_reduce(R->y, TFM_UNCONST(void *)modulus, mp); - /* Y = Y - T2 */ - fp_sub(R->y, &t2, R->y); - if (fp_cmp_d(R->y, 0) == FP_LT) { - fp_add(R->y, TFM_UNCONST(void *)modulus, R->y); - } - - return CRYPT_OK; -} - -/** - Add two ECC points - @param P The point to add - @param Q The point to add - @param R [out] The destination of the double - @param modulus The modulus of the field the ECC curve is in - @param Mp The "b" value from montgomery_setup() - @return CRYPT_OK on success -*/ -static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, const void *ma, const void *modulus, void *Mp) -{ - fp_int t1, t2, x, y, z; - fp_digit mp; - int err, inf; - - LTC_ARGCHK(P != NULL); - LTC_ARGCHK(Q != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - LTC_ARGCHK(Mp != NULL); - - mp = *((fp_digit*)Mp); - - fp_init(&t1); - fp_init(&t2); - fp_init(&x); - fp_init(&y); - fp_init(&z); - - if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* P is point at infinity >> Result = Q */ - ltc_mp.copy(Q->x, R->x); - ltc_mp.copy(Q->y, R->y); - ltc_mp.copy(Q->z, R->z); - return CRYPT_OK; - } - - if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* Q is point at infinity >> Result = P */ - ltc_mp.copy(P->x, R->x); - ltc_mp.copy(P->y, R->y); - ltc_mp.copy(P->z, R->z); - return CRYPT_OK; - } - - /* should we dbl instead? */ - fp_sub(TFM_UNCONST(void *)modulus, Q->y, &t1); - if ( (fp_cmp(P->x, Q->x) == FP_EQ) && - (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) && - (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { - return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp); - } - - fp_copy(P->x, &x); - fp_copy(P->y, &y); - fp_copy(P->z, &z); - - /* if Z is one then these are no-operations */ - if (Q->z != NULL) { - /* T1 = Z' * Z' */ - fp_sqr(Q->z, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* X = X * T1 */ - fp_mul(&t1, &x, &x); - fp_montgomery_reduce(&x, TFM_UNCONST(void *)modulus, mp); - /* T1 = Z' * T1 */ - fp_mul(Q->z, &t1, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* Y = Y * T1 */ - fp_mul(&t1, &y, &y); - fp_montgomery_reduce(&y, TFM_UNCONST(void *)modulus, mp); - } - - /* T1 = Z*Z */ - fp_sqr(&z, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* T2 = X' * T1 */ - fp_mul(Q->x, &t1, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T1 = Z * T1 */ - fp_mul(&z, &t1, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* T1 = Y' * T1 */ - fp_mul(Q->y, &t1, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - - /* Y = Y - T1 */ - fp_sub(&y, &t1, &y); - if (fp_cmp_d(&y, 0) == FP_LT) { - fp_add(&y, TFM_UNCONST(void *)modulus, &y); - } - /* T1 = 2T1 */ - fp_add(&t1, &t1, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* T1 = Y + T1 */ - fp_add(&t1, &y, &t1); - if (fp_cmp(&t1, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t1, TFM_UNCONST(void *)modulus, &t1); - } - /* X = X - T2 */ - fp_sub(&x, &t2, &x); - if (fp_cmp_d(&x, 0) == FP_LT) { - fp_add(&x, TFM_UNCONST(void *)modulus, &x); - } - /* T2 = 2T2 */ - fp_add(&t2, &t2, &t2); - if (fp_cmp(&t2, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t2, TFM_UNCONST(void *)modulus, &t2); - } - /* T2 = X + T2 */ - fp_add(&t2, &x, &t2); - if (fp_cmp(&t2, TFM_UNCONST(void *)modulus) != FP_LT) { - fp_sub(&t2, TFM_UNCONST(void *)modulus, &t2); - } - - /* if Z' != 1 */ - if (Q->z != NULL) { - /* Z = Z * Z' */ - fp_mul(&z, Q->z, &z); - fp_montgomery_reduce(&z, TFM_UNCONST(void *)modulus, mp); - } - - /* Z = Z * X */ - fp_mul(&z, &x, &z); - fp_montgomery_reduce(&z, TFM_UNCONST(void *)modulus, mp); - - /* T1 = T1 * X */ - fp_mul(&t1, &x, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - /* X = X * X */ - fp_sqr(&x, &x); - fp_montgomery_reduce(&x, TFM_UNCONST(void *)modulus, mp); - /* T2 = T2 * x */ - fp_mul(&t2, &x, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* T1 = T1 * X */ - fp_mul(&t1, &x, &t1); - fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp); - - /* X = Y*Y */ - fp_sqr(&y, &x); - fp_montgomery_reduce(&x, TFM_UNCONST(void *)modulus, mp); - /* X = X - T2 */ - fp_sub(&x, &t2, &x); - if (fp_cmp_d(&x, 0) == FP_LT) { - fp_add(&x, TFM_UNCONST(void *)modulus, &x); - } - - /* T2 = T2 - X */ - fp_sub(&t2, &x, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, TFM_UNCONST(void *)modulus, &t2); - } - /* T2 = T2 - X */ - fp_sub(&t2, &x, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, TFM_UNCONST(void *)modulus, &t2); - } - /* T2 = T2 * Y */ - fp_mul(&t2, &y, &t2); - fp_montgomery_reduce(&t2, TFM_UNCONST(void *)modulus, mp); - /* Y = T2 - T1 */ - fp_sub(&t2, &t1, &y); - if (fp_cmp_d(&y, 0) == FP_LT) { - fp_add(&y, TFM_UNCONST(void *)modulus, &y); - } - /* Y = Y/2 */ - if (fp_isodd(&y)) { - fp_add(&y, TFM_UNCONST(void *)modulus, &y); - } - fp_div_2(&y, &y); - - fp_copy(&x, R->x); - fp_copy(&y, R->y); - fp_copy(&z, R->z); - - return CRYPT_OK; -} - - -#endif - -static int set_rand(void *a, int size) -{ - LTC_ARGCHK(a != NULL); - fp_rand(a, size); - return CRYPT_OK; -} - -const ltc_math_descriptor tfm_desc = { - - "TomsFastMath", - (int)DIGIT_BIT, - - &init, - &init_copy, - &deinit, - - &neg, - ©, - - &set_int, - &get_int, - &get_digit, - &get_digit_count, - &compare, - &compare_d, - &count_bits, - &count_lsb_bits, - &twoexpt, - - &read_radix, - &write_radix, - &unsigned_size, - &unsigned_write, - &unsigned_read, - - &add, - &addi, - &sub, - &subi, - &mul, - &muli, - &sqr, - NULL, /* TODO: &sqrtmod_prime */ - ÷, - &div_2, - &modi, - &gcd, - &lcm, - - &mulmod, - &sqrmod, - &invmod, - - &montgomery_setup, - &montgomery_normalization, - &montgomery_reduce, - &montgomery_deinit, - - &exptmod, - &isprime, - -#ifdef LTC_MECC -#ifdef LTC_MECC_FP - <c_ecc_fp_mulmod, -#else - <c_ecc_mulmod, -#endif /* LTC_MECC_FP */ -#ifdef LTC_MECC_ACCEL - &tfm_ecc_projective_add_point, - &tfm_ecc_projective_dbl_point, -#else - <c_ecc_projective_add_point, - <c_ecc_projective_dbl_point, -#endif /* LTC_MECC_ACCEL */ - <c_ecc_map, -#ifdef LTC_ECC_SHAMIR -#ifdef LTC_MECC_FP - <c_ecc_fp_mul2add, -#else - <c_ecc_mul2add, -#endif /* LTC_MECC_FP */ -#else - NULL, -#endif /* LTC_ECC_SHAMIR */ -#else - NULL, NULL, NULL, NULL, NULL, -#endif /* LTC_MECC */ - -#ifdef LTC_MRSA - &rsa_make_key, - &rsa_exptmod, -#else - NULL, NULL, -#endif - &addmod, - &submod, - - set_rand, - -}; - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/adler32.c b/Sources/DataLiteC/libtomcrypt/misc/adler32.c deleted file mode 100644 index 8c2953d..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/adler32.c +++ /dev/null @@ -1,123 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file adler32.c - Adler-32 checksum algorithm - Written and placed in the public domain by Wei Dai - Adapted for libtomcrypt by Steffen Jaeckel -*/ -#ifdef LTC_ADLER32 - -static const unsigned long s_adler32_base = 65521; - -void adler32_init(adler32_state *ctx) -{ - LTC_ARGCHKVD(ctx != NULL); - ctx->s[0] = 1; - ctx->s[1] = 0; -} - -void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) -{ - unsigned long s1, s2; - - LTC_ARGCHKVD(ctx != NULL); - LTC_ARGCHKVD(input != NULL); - s1 = ctx->s[0]; - s2 = ctx->s[1]; - - if (length % 8 != 0) { - do { - s1 += *input++; - s2 += s1; - length--; - } while (length % 8 != 0); - - if (s1 >= s_adler32_base) { - s1 -= s_adler32_base; - } - s2 %= s_adler32_base; - } - - while (length > 0) { - s1 += input[0]; - s2 += s1; - s1 += input[1]; - s2 += s1; - s1 += input[2]; - s2 += s1; - s1 += input[3]; - s2 += s1; - s1 += input[4]; - s2 += s1; - s1 += input[5]; - s2 += s1; - s1 += input[6]; - s2 += s1; - s1 += input[7]; - s2 += s1; - - length -= 8; - input += 8; - - if (s1 >= s_adler32_base) { - s1 -= s_adler32_base; - } - s2 %= s_adler32_base; - } - - LTC_ARGCHKVD(s1 < s_adler32_base); - LTC_ARGCHKVD(s2 < s_adler32_base); - - ctx->s[0] = (unsigned short)s1; - ctx->s[1] = (unsigned short)s2; -} - -void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size) -{ - unsigned char* h; - - LTC_ARGCHKVD(ctx != NULL); - LTC_ARGCHKVD(hash != NULL); - - h = hash; - - switch (size) { - default: - h[3] = ctx->s[0] & 0x0ff; - /* FALLTHROUGH */ - case 3: - h[2] = (ctx->s[0] >> 8) & 0x0ff; - /* FALLTHROUGH */ - case 2: - h[1] = ctx->s[1] & 0x0ff; - /* FALLTHROUGH */ - case 1: - h[0] = (ctx->s[1] >> 8) & 0x0ff; - /* FALLTHROUGH */ - case 0: - ; - } -} - -int adler32_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - const void* in = "libtomcrypt"; - const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; - unsigned char out[4]; - adler32_state ctx; - adler32_init(&ctx); - adler32_update(&ctx, in, XSTRLEN(in)); - adler32_finish(&ctx, out, 4); - if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; -#endif -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/base16/base16_decode.c b/Sources/DataLiteC/libtomcrypt/misc/base16/base16_decode.c deleted file mode 100644 index 8ebc9ea..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base16/base16_decode.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file base16_decode.c - Base16/Hex decode a string. - Based on https://stackoverflow.com/a/23898449 - Adapted for libtomcrypt by Steffen Jaeckel -*/ - -#ifdef LTC_BASE16 - -/** - Base16 decode a string - @param in The Base16 string to decode - @param inlen The length of the Base16 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base16_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long pos, out_len; - unsigned char idx0, idx1; - char in0, in1; - - const unsigned char hashmap[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ - 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ - 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ - 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */ - }; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET; - out_len = *outlen * 2; - for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) { - in0 = in[pos + 0]; - in1 = in[pos + 1]; - - if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET; - if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET; - - idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10; - idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10; - - if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET; - if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET; - - out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1]; - } - *outlen = pos / 2; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/base16/base16_encode.c b/Sources/DataLiteC/libtomcrypt/misc/base16/base16_encode.c deleted file mode 100644 index 206827c..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base16/base16_encode.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file base16_encode.c - Base16/Hex encode a string, Steffen Jaeckel -*/ - -#ifdef LTC_BASE16 - -/** - Base16 encode a buffer - @param in The input buffer to encode - @param inlen The length of the input buffer - @param out [out] The destination of the Base16 encoded data - @param outlen [in/out] The max size and resulting size of the encoded data - @param options Output 'a-f' on 0 and 'A-F' otherwise. - @return CRYPT_OK if successful -*/ -int base16_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - unsigned int options) -{ - unsigned long i, x; - const char *alphabet; - const char *alphabets[2] = { - "0123456789abcdef", - "0123456789ABCDEF", - }; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* check the sizes */ - x = inlen * 2 + 1; - - if (x < inlen) return CRYPT_OVERFLOW; - - if (*outlen < x) { - *outlen = x; - return CRYPT_BUFFER_OVERFLOW; - } - x--; - *outlen = x; /* returning the length without terminating NUL */ - - if (options == 0) { - alphabet = alphabets[0]; - } else { - alphabet = alphabets[1]; - } - - for (i = x; i > 0; i -= 2) { - out[i-2] = alphabet[(in[(i-1)/2] >> 4) & 0x0f]; - out[i-1] = alphabet[in[(i-1)/2] & 0x0f]; - } - - out[x] = '\0'; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/base32/base32_decode.c b/Sources/DataLiteC/libtomcrypt/misc/base32/base32_decode.c deleted file mode 100644 index fc98cce..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base32/base32_decode.c +++ /dev/null @@ -1,111 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BASE32 - -/** - Base32 decode a buffer - @param in The Base32 data to decode - @param inlen The length of the Base32 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD - @return CRYPT_OK if successful -*/ -int base32_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - base32_alphabet id) -{ - unsigned long x; - int y = 0; - ulong64 t = 0; - char c; - const unsigned char *map; - const unsigned char tables[4][43] = { - { /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */ - 99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/, - 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, - 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/, - 13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/ - }, - { /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */ - 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, - 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, - 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/, - 23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/ - }, - { /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */ - 99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/, - 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, - 24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/, - 2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/ - }, - { /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */ - 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, - 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, - 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/, - 21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/ - } - }; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(id >= BASE32_RFC4648); - LTC_ARGCHK(id <= BASE32_CROCKFORD); - - /* ignore all trailing = */ - while (inlen > 0 && in[inlen-1] == '=') inlen--; - - /* no input, nothing to do */ - if (inlen == 0) { - *outlen = 0; - return CRYPT_OK; - } - - /* check the size of output buffer */ - x = (inlen * 5) / 8; - if (*outlen < x) { - *outlen = x; - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = x; - - /* check input data length */ - x = inlen % 8; - if (x == 1 || x == 3 || x == 6) { - return CRYPT_INVALID_PACKET; - } - - map = tables[id]; - for (x = 0; x < inlen; x++) { - c = in[x]; - /* convert to upper case */ - if ((c >= 'a') && (c <= 'z')) c -= 32; - if (c < '0' || c > 'Z' || map[c-'0'] > 31) { - return CRYPT_INVALID_PACKET; - } - t = (t<<5) | map[c-'0']; - if (++y == 8) { - *out++ = (unsigned char)((t>>32) & 255); - *out++ = (unsigned char)((t>>24) & 255); - *out++ = (unsigned char)((t>>16) & 255); - *out++ = (unsigned char)((t>> 8) & 255); - *out++ = (unsigned char)( t & 255); - y = 0; - t = 0; - } - } - if (y > 0) { - t = t << (5 * (8 - y)); - if (y >= 2) *out++ = (unsigned char)((t>>32) & 255); - if (y >= 4) *out++ = (unsigned char)((t>>24) & 255); - if (y >= 5) *out++ = (unsigned char)((t>>16) & 255); - if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255); - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/base32/base32_encode.c b/Sources/DataLiteC/libtomcrypt/misc/base32/base32_encode.c deleted file mode 100644 index 29519bf..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base32/base32_encode.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_BASE32 - -/** - Base32 encode a buffer - @param in The input buffer to encode - @param inlen The length of the input buffer - @param out [out] The destination of the Base32 encoded data - @param outlen [in/out] The max size and resulting size of the encoded data - @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD - @return CRYPT_OK if successful -*/ -int base32_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - base32_alphabet id) -{ - unsigned long i, x; - const char *codes; - const char *alphabet[4] = { - "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */ - "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */ - "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */ - "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */ - }; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(id >= BASE32_RFC4648); - LTC_ARGCHK(id <= BASE32_CROCKFORD); - - /* check the size of output buffer +1 byte for terminating NUL */ - x = (8 * inlen + 4) / 5 + 1; - if (*outlen < x) { - *outlen = x; - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = x - 1; /* returning the length without terminating NUL */ - - /* no input, nothing to do */ - if (inlen == 0) { - *out = '\0'; - return CRYPT_OK; - } - - codes = alphabet[id]; - x = 5 * (inlen / 5); - for (i = 0; i < x; i += 5) { - *out++ = codes[(in[0] >> 3) & 0x1F]; - *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F]; - *out++ = codes[(in[1] >> 1) & 0x1F]; - *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F]; - *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F]; - *out++ = codes[(in[3] >> 2) & 0x1F]; - *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F]; - *out++ = codes[in[4] & 0x1F]; - in += 5; - } - if (i < inlen) { - unsigned a = in[0]; - unsigned b = (i+1 < inlen) ? in[1] : 0; - unsigned c = (i+2 < inlen) ? in[2] : 0; - unsigned d = (i+3 < inlen) ? in[3] : 0; - *out++ = codes[(a >> 3) & 0x1F]; - *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F]; - if (i+1 < inlen) { - *out++ = codes[(b >> 1) & 0x1F]; - *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F]; - } - if (i+2 < inlen) { - *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F]; - } - if (i+3 < inlen) { - *out++ = codes[(d >> 2) & 0x1F]; - *out++ = codes[((d & 0x3) << 3) & 0x1F]; - } - } - *out = '\0'; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/base64/base64_decode.c b/Sources/DataLiteC/libtomcrypt/misc/base64/base64_decode.c deleted file mode 100644 index 20a9ef3..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base64/base64_decode.c +++ /dev/null @@ -1,231 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file base64_decode.c - Compliant base64 code donated by Wayne Scott (wscott@bitmover.com) - base64 URL Safe variant (RFC 4648 section 5) by Karel Miko -*/ - - -#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) - -/* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32) - * 254 - padding character '=' (allowed only at the end) - * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode - */ - -#if defined(LTC_BASE64) -static const unsigned char map_base64[256] = { -255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, -255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, -255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, -255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255 }; -#endif /* LTC_BASE64 */ - -#if defined(LTC_BASE64_URL) -static const unsigned char map_base64url[] = { -255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, -255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, -255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63, -255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255 -}; -#endif /* LTC_BASE64_URL */ - -enum { - insane = 0, - strict = 1, - relaxed = 2 -}; - -static int s_base64_decode_internal(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *map, int mode) -{ - unsigned long t, x, y, z; - unsigned char c; - int g; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - g = 0; /* '=' counter */ - for (x = y = z = t = 0; x < inlen; x++) { - if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) { - continue; /* allow the last byte to be NUL (relaxed+insane) */ - } - c = map[(unsigned char)in[x]&0xFF]; - if (c == 254) { - g++; - continue; - } - if (c == 253) { - if (mode == strict) { - return CRYPT_INVALID_PACKET; - } - continue; /* allow to ignore white-spaces (relaxed+insane) */ - } - if (c == 255) { - if (mode == insane) { - continue; /* allow to ignore invalid garbage (insane) */ - } - return CRYPT_INVALID_PACKET; - } - if ((g > 0) && (mode != insane)) { - /* we only allow '=' to be at the end (strict+relaxed) */ - return CRYPT_INVALID_PACKET; - } - - t = (t<<6)|c; - - if (++y == 4) { - if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW; - out[z++] = (unsigned char)((t>>16)&255); - out[z++] = (unsigned char)((t>>8)&255); - out[z++] = (unsigned char)(t&255); - y = t = 0; - } - } - - if (y != 0) { - if (y == 1) return CRYPT_INVALID_PACKET; -#if defined(LTC_BASE64) - if (((y + g) != 4) && (mode == strict) && (map == map_base64)) return CRYPT_INVALID_PACKET; -#endif /* LTC_BASE64 */ - t = t << (6 * (4 - y)); - if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW; - if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255); - if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255); - } - *outlen = z; - return CRYPT_OK; -} - -#if defined(LTC_BASE64) -/** - Dangerously relaxed base64 decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane); -} - -/** - Strict base64 decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64_strict_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict); -} - -/** - Sane base64 decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64_sane_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed); -} -#endif /* LTC_BASE64 */ - -#if defined(LTC_BASE64_URL) -/** - Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64url_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane); -} - -/** - Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64url_strict_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict); -} - -/** - Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory - @param in The base64 data to decode - @param inlen The length of the base64 data - @param out [out] The destination of the binary decoded data - @param outlen [in/out] The max size and resulting size of the decoded data - @return CRYPT_OK if successful -*/ -int base64url_sane_decode(const char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed); -} -#endif /* LTC_BASE64_URL */ - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/misc/base64/base64_encode.c b/Sources/DataLiteC/libtomcrypt/misc/base64/base64_encode.c deleted file mode 100644 index ef8aee9..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/base64/base64_encode.c +++ /dev/null @@ -1,159 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file base64_encode.c - Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com) - base64 URL Safe variant (RFC 4648 section 5) by Karel Miko -*/ - - -#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) - -#if defined(LTC_BASE64) -static const char * const codes_base64 = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -#endif /* LTC_BASE64 */ - -#if defined(LTC_BASE64_URL) -static const char * const codes_base64url = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -#endif /* LTC_BASE64_URL */ - -enum mode { - nopad = 0, - pad = 1, - lf = 2, - cr = 4, - ssh = 8, - crlf = lf | cr, -}; - -static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - const char *codes, unsigned int mode) -{ - unsigned long i, len2, leven, linelen; - char *p; - - LTC_ARGCHK(outlen != NULL); - - linelen = (mode & ssh) ? 72 : 64; - - /* valid output size ? */ - len2 = 4 * ((inlen + 2) / 3); - if ((mode & crlf) == lf) { - len2 += len2 / linelen; - } else if ((mode & crlf) == crlf) { - len2 += (len2 / linelen) * 2; - } - if (*outlen < len2 + 1) { - *outlen = len2 + 1; - return CRYPT_BUFFER_OVERFLOW; - } - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - if ((void*)in == out) { - return CRYPT_INVALID_ARG; - } - - p = out; - leven = 3*(inlen / 3); - for (i = 0; i < leven; i += 3) { - *p++ = codes[(in[0] >> 2) & 0x3F]; - *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F]; - *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; - *p++ = codes[in[2] & 0x3F]; - in += 3; - if ((p - out) % linelen == 0) { - if (mode & cr) *p++ = '\r'; - if (mode & lf) *p++ = '\n'; - } - } - /* Pad it if necessary... */ - if (i < inlen) { - unsigned a = in[0]; - unsigned b = (i+1 < inlen) ? in[1] : 0; - - *p++ = codes[(a >> 2) & 0x3F]; - *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; - if (mode & pad) { - *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; - *p++ = '='; - } - else { - if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F]; - } - } - - /* append a NULL byte */ - *p = '\0'; - - /* return ok */ - *outlen = (unsigned long)(p - out); /* the length without terminating NUL */ - return CRYPT_OK; -} - -#if defined(LTC_BASE64) -/** - base64 Encode a buffer (NUL terminated) - @param in The input buffer to encode - @param inlen The length of the input buffer - @param out [out] The destination of the base64 encoded data - @param outlen [in/out] The max size and resulting size - @return CRYPT_OK if successful -*/ -int base64_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen) -{ - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad); -} - -/** - base64 Encode a buffer for PEM output - (NUL terminated with line-break at 64 chars) - @param in The input buffer to encode - @param inlen The length of the input buffer - @param out [out] The destination of the base64 encoded data - @param outlen [in/out] The max size and resulting size - @param flags \ref base64_pem_flags - @return CRYPT_OK if successful -*/ -int base64_encode_pem(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - unsigned int flags) -{ - int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf; - int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0; - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf); -} -#endif /* LTC_BASE64 */ - - -#if defined(LTC_BASE64_URL) -/** - base64 (URL Safe, RFC 4648 section 5) Encode a buffer (NUL terminated) - @param in The input buffer to encode - @param inlen The length of the input buffer - @param out [out] The destination of the base64 encoded data - @param outlen [in/out] The max size and resulting size - @return CRYPT_OK if successful -*/ -int base64url_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen) -{ - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad); -} - -int base64url_strict_encode(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen) -{ - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad); -} -#endif /* LTC_BASE64_URL */ - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/misc/bcrypt/bcrypt.c b/Sources/DataLiteC/libtomcrypt/misc/bcrypt/bcrypt.c deleted file mode 100644 index 905f6b2..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/bcrypt/bcrypt.c +++ /dev/null @@ -1,196 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file bcrypt.c - bcrypt pbkdf, Steffen Jaeckel -*/ -#ifdef LTC_BCRYPT - -#define BCRYPT_WORDS 8 -#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) - -static int s_bcrypt_hash(const unsigned char *pt, - const unsigned char *pass, unsigned long passlen, - const unsigned char *salt, unsigned long saltlen, - unsigned char *out, unsigned long *outlen) -{ - symmetric_key key; - int err, n; - ulong32 ct[BCRYPT_WORDS]; - - if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) { - return err; - } - for (n = 0; n < 64; ++n) { - if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) { - return err; - } - if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) { - return err; - } - } - - for (n = 0; n < BCRYPT_WORDS; ++n) { - LOAD32H(ct[n], &pt[n*4]); - } - - for (n = 0; n < 64; ++n) { - blowfish_enc(ct, BCRYPT_WORDS/2, &key); - } - - for (n = 0; n < BCRYPT_WORDS; ++n) { - STORE32L(ct[n], &out[4 * n]); - } - *outlen = sizeof(ct); -#ifdef LTC_CLEAN_STACK - zeromem(&key, sizeof(key)); - zeromem(ct, sizeof(ct)); -#endif - - return CRYPT_OK; -} - -static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen, - const unsigned char *salt, unsigned long saltlen, - unsigned char *out, unsigned long *outlen) -{ - const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite"; - return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen); -} - -/** - Compatible to bcrypt_pbkdf() as provided in OpenBSD - @param password The input password (or key) - @param password_len The length of the password (octets) - @param salt The salt (or nonce) - @param salt_len The length of the salt (octets) - @param rounds # of iterations desired [read specs for more] - @param hash_idx The index of the hash desired - @param out [out] The destination for this algorithm - @param outlen [in/out] The desired size of the algorithm output - @return CRYPT_OK if successful -*/ -int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, - const unsigned char *salt, unsigned long salt_len, - unsigned int rounds, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - int err; - ulong32 blkno; - unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds; - unsigned char *buf[3], blkbuf[4]; - unsigned char *hashed_pass; - - LTC_ARGCHK(secret != NULL); - LTC_ARGCHK(salt != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) { - return CRYPT_INVALID_ARG; - } - /* test hash IDX */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - /* set default value for rounds if not given */ - if (rounds == 0) { - used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS; - } else { - used_rounds = rounds; - } - - buf[0] = XMALLOC(MAXBLOCKSIZE * 3); - hashed_pass = XMALLOC(MAXBLOCKSIZE); - if (buf[0] == NULL || hashed_pass == NULL) { - if (hashed_pass != NULL) { - XFREE(hashed_pass); - } - if (buf[0] != NULL) { - XFREE(buf[0]); - } - return CRYPT_MEM; - } - /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ - buf[1] = buf[0] + MAXBLOCKSIZE; - buf[2] = buf[1] + MAXBLOCKSIZE; - - step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE; - steps = (*outlen + step_size - 1) / step_size; - - hashed_pass_len = MAXBLOCKSIZE; - if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) { - goto LBL_ERR; - } - - left = *outlen; - blkno = 0; - while (left != 0) { - /* increment and store current block number */ - ++blkno; - STORE32H(blkno, blkbuf); - - /* process block number blkno */ - zeromem(buf[0], MAXBLOCKSIZE*2); - - x = MAXBLOCKSIZE; - if ((err = hash_memory_multi(hash_idx, buf[0], &x, - salt, salt_len, - blkbuf, 4uL, - LTC_NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - y = MAXBLOCKSIZE; - if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { - goto LBL_ERR; - } - XMEMCPY(buf[2], buf[1], y); - - /* now compute repeated and XOR it in buf[2] */ - for (itts = 1; itts < used_rounds; ++itts) { - x = MAXBLOCKSIZE; - if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y = MAXBLOCKSIZE; - if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { - goto LBL_ERR; - } - for (x = 0; x < y; x++) { - buf[2][x] ^= buf[1][x]; - } - } - - /* now emit upto `steps` bytes of buf[2] to output */ - steps = MIN(steps, left); - for (y = 0; y < steps; ++y) { - dest = y * step_size + (blkno - 1); - if (dest >= *outlen) - break; - out[dest] = buf[2][y]; - } - left -= y; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf[0], MAXBLOCKSIZE*3); - zeromem(hashed_pass, MAXBLOCKSIZE); -#endif - - XFREE(hashed_pass); - XFREE(buf[0]); - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/burn_stack.c b/Sources/DataLiteC/libtomcrypt/misc/burn_stack.c deleted file mode 100644 index 5d276a4..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/burn_stack.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file burn_stack.c - Burn stack, Tom St Denis -*/ - -/** - Burn some stack memory - @param len amount of stack to burn in bytes -*/ -void burn_stack(unsigned long len) -{ - unsigned char buf[32]; - zeromem(buf, sizeof(buf)); - if (len > (unsigned long)sizeof(buf)) { - burn_stack(len - sizeof(buf)); - } -} - - diff --git a/Sources/DataLiteC/libtomcrypt/misc/compare_testvector.c b/Sources/DataLiteC/libtomcrypt/misc/compare_testvector.c deleted file mode 100644 index bb3c8cb..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/compare_testvector.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file compare_testvector.c - Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel -*/ - -#if defined(LTC_TEST) && defined(LTC_TEST_DBG) -static void s_print_hex(const char* what, const void* v, const unsigned long l) -{ - const unsigned char* p = v; - unsigned long x, y = 0, z; - fprintf(stderr, "%s contents: \n", what); - for (x = 0; x < l; ) { - fprintf(stderr, "%02X ", p[x]); - if (!(++x % 16) || x == l) { - if((x % 16) != 0) { - z = 16 - (x % 16); - if(z >= 8) - fprintf(stderr, " "); - for (; z != 0; --z) { - fprintf(stderr, " "); - } - } - fprintf(stderr, " | "); - for(; y < x; y++) { - if((y % 8) == 0) - fprintf(stderr, " "); - if(isgraph(p[y])) - fprintf(stderr, "%c", p[y]); - else - fprintf(stderr, "."); - } - fprintf(stderr, "\n"); - } - else if((x % 8) == 0) { - fprintf(stderr, " "); - } - } -} -#endif - -/** - Compare two test-vectors - - @param is The data as it is - @param is_len The length of is - @param should The data as it should - @param should_len The length of should - @param what The type of the data - @param which The iteration count - @return 0 on equality, -1 or 1 on difference -*/ -int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) -{ - int res = 0; - if(is_len != should_len) { - res = is_len > should_len ? -1 : 1; - } else { - res = XMEMCMP(is, should, is_len); - } -#if defined(LTC_TEST) && defined(LTC_TEST_DBG) - if (res != 0) { - fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what); - s_print_hex("SHOULD", should, should_len); - s_print_hex("IS ", is, is_len); -#if LTC_TEST_DBG > 1 - } else { - fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what); -#endif - } -#else - LTC_UNUSED_PARAM(which); - LTC_UNUSED_PARAM(what); -#endif - - return res; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/copy_or_zeromem.c b/Sources/DataLiteC/libtomcrypt/misc/copy_or_zeromem.c deleted file mode 100644 index a05eac6..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/copy_or_zeromem.c +++ /dev/null @@ -1,51 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file copy_or_zeromem.c - Either copy or zero a block of memory in constant time, Steffen Jaeckel -*/ - -/** - Either copy or zero a block of memory in constant time - @param src The source where to read from - @param dest The destination where to write to - @param len The length of the area to process (octets) - @param coz Copy (on 0) Or Zero (> 0) -*/ -void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz) -{ - unsigned long y; -#ifdef LTC_FAST - unsigned long z; - LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */ -#endif - unsigned char mask = 0xff; /* initialize mask at all ones */ - - LTC_ARGCHKVD(src != NULL); - LTC_ARGCHKVD(dest != NULL); - - if (coz != 0) coz = 1; - y = 0; - mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */ -#ifdef LTC_FAST - fastMask *= 1 - coz; - if (len & ~15) { - for (; y < (len & ~15); y += 16) { - for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask; - } - } - } -#endif - for (; y < len; y++) { - dest[y] = src[y] & mask; - } -#ifdef LTC_CLEAN_STACK -#ifdef LTC_FAST - fastMask = 0; -#endif - mask = 0; -#endif -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crc32.c b/Sources/DataLiteC/libtomcrypt/misc/crc32.c deleted file mode 100644 index d90e830..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crc32.c +++ /dev/null @@ -1,193 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crc32.c - CRC-32 checksum algorithm - Written and placed in the public domain by Wei Dai - Adapted for libtomcrypt by Steffen Jaeckel -*/ -#ifdef LTC_CRC32 - -static const ulong32 CRC32_NEGL = 0xffffffffUL; - -#if defined(ENDIAN_LITTLE) -#define CRC32_INDEX(c) (c & 0xff) -#define CRC32_SHIFTED(c) (c >> 8) -#elif defined(ENDIAN_BIG) -#define CRC32_INDEX(c) (c >> 24) -#define CRC32_SHIFTED(c) (c << 8) -#else -#error The existing CRC32 implementation only works properly when the endianness of the target platform is known. -#endif - -/* Table of CRC-32's of all single byte values (made by makecrc.c) */ -static const ulong32 crc32_m_tab[] = -{ -#if defined(ENDIAN_LITTLE) - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -#else - 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, - 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, - 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, - 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, - 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, - 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, - 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, - 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, - 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, - 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, - 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, - 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, - 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, - 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, - 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, - 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, - 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, - 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, - 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, - 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, - 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, - 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, - 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, - 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, - 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, - 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, - 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, - 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, - 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, - 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, - 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, - 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, - 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, - 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, - 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, - 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, - 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, - 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, - 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, - 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, - 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, - 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, - 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, - 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, - 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, - 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, - 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, - 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, - 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, - 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, - 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, - 0x8def022dL -#endif -}; - -void crc32_init(crc32_state *ctx) -{ - LTC_ARGCHKVD(ctx != NULL); - ctx->crc = CRC32_NEGL; -} - -void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length) -{ - ulong32 crc; - LTC_ARGCHKVD(ctx != NULL); - LTC_ARGCHKVD(input != NULL); - crc = ctx->crc; - - while (length--) { - crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc); - } - - ctx->crc = crc; -} - -void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size) -{ - unsigned long i; - unsigned char* h; - ulong32 crc; - LTC_ARGCHKVD(ctx != NULL); - LTC_ARGCHKVD(hash != NULL); - - h = hash; - crc = ctx->crc; - crc ^= CRC32_NEGL; - - if (size > 4) size = 4; - for (i = 0; i < size; i++) { - h[i] = ((unsigned char*)&(crc))[size-i-1]; - } -} - -int crc32_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - const void* in = "libtomcrypt"; - const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef }; - unsigned char out[4]; - crc32_state ctx; - crc32_init(&ctx); - crc32_update(&ctx, in, XSTRLEN(in)); - crc32_finish(&ctx, out, 4); - if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - return CRYPT_OK; -#endif -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt.c deleted file mode 100644 index 61b5cd0..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt.c +++ /dev/null @@ -1,586 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt.c - Build strings, Tom St Denis -*/ -#define NAME_VALUE(s) #s"="NAME(s) -#define NAME(s) #s - -const char *crypt_build_settings = - "LibTomCrypt " SCRYPT " (www.libtom.net)\n" - "LibTomCrypt is public domain software.\n" -#if defined(INCLUDE_BUILD_DATE) - "Built on " __DATE__ " at " __TIME__ "\n" -#endif - "\n\nEndianness: " -#if defined(ENDIAN_NEUTRAL) - "neutral/" -#endif -#if defined(ENDIAN_LITTLE) - "little" -#elif defined(ENDIAN_BIG) - "big" -#endif - #if defined(ENDIAN_32BITWORD) - " (32-bit words)\n" - #elif defined(ENDIAN_64BITWORD) - " (64-bit words)\n" - #else - " (no wordsize defined)\n" - #endif - "Clean stack: " -#if defined(LTC_CLEAN_STACK) - "enabled\n" -#else - "disabled\n" -#endif - "\nCiphers built-in:\n" -#if defined(LTC_BLOWFISH) - " Blowfish\n" -#endif -#if defined(LTC_RC2) - " RC2\n" -#endif -#if defined(LTC_RC5) - " RC5\n" -#endif -#if defined(LTC_RC6) - " RC6\n" -#endif -#if defined(LTC_SAFERP) - " Safer+\n" -#endif -#if defined(LTC_SAFER) - " Safer\n" -#endif -#if defined(LTC_RIJNDAEL) - " Rijndael\n" -#endif -#if defined(LTC_XTEA) - " XTEA\n" -#endif -#if defined(LTC_TWOFISH) - " Twofish " - #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) - "(small, tables, all_tables)\n" - #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) - "(small, tables)\n" - #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES) - "(small, all_tables)\n" - #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) - "(tables, all_tables)\n" - #elif defined(LTC_TWOFISH_SMALL) - "(small)\n" - #elif defined(LTC_TWOFISH_TABLES) - "(tables)\n" - #elif defined(LTC_TWOFISH_ALL_TABLES) - "(all_tables)\n" - #else - "\n" - #endif -#endif -#if defined(LTC_DES) - " DES\n" - " DES-X\n" - " 3DES\n" -#endif -#if defined(LTC_SM4) - " SM4\n" -#endif -#if defined(LTC_CAST5) - " CAST5\n" -#endif -#if defined(LTC_NOEKEON) - " Noekeon\n" -#endif -#if defined(LTC_SKIPJACK) - " Skipjack\n" -#endif -#if defined(LTC_KHAZAD) - " Khazad\n" -#endif -#if defined(LTC_ANUBIS) - " Anubis " -#endif -#if defined(LTC_ANUBIS_TWEAK) - " (tweaked)" -#endif - "\n" -#if defined(LTC_KSEED) - " KSEED\n" -#endif -#if defined(LTC_KASUMI) - " KASUMI\n" -#endif -#if defined(LTC_MULTI2) - " MULTI2\n" -#endif -#if defined(LTC_CAMELLIA) - " Camellia\n" -#endif -#if defined(LTC_IDEA) - " IDEA\n" -#endif -#if defined(LTC_SERPENT) - " Serpent\n" -#endif -#if defined(LTC_TEA) - " TEA\n" -#endif - "Stream ciphers built-in:\n" -#if defined(LTC_CHACHA) - " ChaCha\n" -#endif -#if defined(LTC_SALSA20) - " Salsa20\n" -#endif -#if defined(LTC_XSALSA20) - " XSalsa20\n" -#endif -#if defined(LTC_SOSEMANUK) - " Sosemanuk\n" -#endif -#if defined(LTC_RABBIT) - " Rabbit\n" -#endif -#if defined(LTC_RC4_STREAM) - " RC4\n" -#endif -#if defined(LTC_SOBER128_STREAM) - " SOBER128\n" -#endif - - "\nHashes built-in:\n" -#if defined(LTC_SHA3) - " SHA3\n" -#endif -#if defined(LTC_KECCAK) - " KECCAK\n" -#endif -#if defined(LTC_SHA512) - " SHA-512\n" -#endif -#if defined(LTC_SHA384) - " SHA-384\n" -#endif -#if defined(LTC_SHA512_256) - " SHA-512/256\n" -#endif -#if defined(LTC_SHA256) - " SHA-256\n" -#endif -#if defined(LTC_SHA512_224) - " SHA-512/224\n" -#endif -#if defined(LTC_SHA224) - " SHA-224\n" -#endif -#if defined(LTC_TIGER) - " TIGER\n" -#endif -#if defined(LTC_SHA1) - " SHA1\n" -#endif -#if defined(LTC_MD5) - " MD5\n" -#endif -#if defined(LTC_MD4) - " MD4\n" -#endif -#if defined(LTC_MD2) - " MD2\n" -#endif -#if defined(LTC_RIPEMD128) - " RIPEMD128\n" -#endif -#if defined(LTC_RIPEMD160) - " RIPEMD160\n" -#endif -#if defined(LTC_RIPEMD256) - " RIPEMD256\n" -#endif -#if defined(LTC_RIPEMD320) - " RIPEMD320\n" -#endif -#if defined(LTC_WHIRLPOOL) - " WHIRLPOOL\n" -#endif -#if defined(LTC_BLAKE2S) - " BLAKE2S\n" -#endif -#if defined(LTC_BLAKE2B) - " BLAKE2B\n" -#endif -#if defined(LTC_CHC_HASH) - " CHC_HASH\n" -#endif - - "\nBlock Chaining Modes:\n" -#if defined(LTC_CFB_MODE) - " CFB\n" -#endif -#if defined(LTC_OFB_MODE) - " OFB\n" -#endif -#if defined(LTC_ECB_MODE) - " ECB\n" -#endif -#if defined(LTC_CBC_MODE) - " CBC\n" -#endif -#if defined(LTC_CTR_MODE) - " CTR\n" -#endif -#if defined(LTC_LRW_MODE) - " LRW" -#if defined(LTC_LRW_TABLES) - " (tables) " -#endif - "\n" -#endif -#if defined(LTC_F8_MODE) - " F8\n" -#endif -#if defined(LTC_XTS_MODE) - " XTS\n" -#endif - - "\nMACs:\n" -#if defined(LTC_HMAC) - " HMAC\n" -#endif -#if defined(LTC_OMAC) - " OMAC\n" -#endif -#if defined(LTC_PMAC) - " PMAC\n" -#endif -#if defined(LTC_PELICAN) - " PELICAN\n" -#endif -#if defined(LTC_XCBC) - " XCBC\n" -#endif -#if defined(LTC_F9_MODE) - " F9\n" -#endif -#if defined(LTC_POLY1305) - " POLY1305\n" -#endif -#if defined(LTC_BLAKE2SMAC) - " BLAKE2S MAC\n" -#endif -#if defined(LTC_BLAKE2BMAC) - " BLAKE2B MAC\n" -#endif - - "\nENC + AUTH modes:\n" -#if defined(LTC_EAX_MODE) - " EAX\n" -#endif -#if defined(LTC_OCB_MODE) - " OCB\n" -#endif -#if defined(LTC_OCB3_MODE) - " OCB3\n" -#endif -#if defined(LTC_CCM_MODE) - " CCM\n" -#endif -#if defined(LTC_GCM_MODE) - " GCM" -#if defined(LTC_GCM_TABLES) - " (tables) " -#endif -#if defined(LTC_GCM_TABLES_SSE2) - " (SSE2) " -#endif - "\n" -#endif -#if defined(LTC_CHACHA20POLY1305_MODE) - " CHACHA20POLY1305\n" -#endif -#if defined(LTC_SIV_MODE) - " SIV\n" -#endif - - "\nPRNG:\n" -#if defined(LTC_YARROW) - " Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n" -#endif -#if defined(LTC_SPRNG) - " SPRNG\n" -#endif -#if defined(LTC_RC4) - " RC4\n" -#endif -#if defined(LTC_CHACHA20_PRNG) - " ChaCha20\n" -#endif -#if defined(LTC_FORTUNA) - " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", " -#if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED) - "LTC_FORTUNA_RESEED_RATELIMIT_TIMED" -#else - "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD) -#endif -#if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY) - ", LTC_FORTUNA_USE_ENCRYPT_ONLY" -#endif - ")\n" -#endif -#if defined(LTC_SOBER128) - " SOBER128\n" -#endif -#if defined(LTC_WIN32_BCRYPT) - " WIN32_BCRYPT\n" -#endif - - "\nPK Crypto:\n" -#if defined(LTC_MRSA) - " RSA" -#if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING) - " (with blinding and CRT hardening)" -#elif defined(LTC_RSA_BLINDING) - " (with blinding)" -#elif defined(LTC_RSA_CRT_HARDENING) - " (with CRT hardening)" -#endif - "\n" -#endif -#if defined(LTC_MDH) - " DH\n" -#endif -#if defined(LTC_MECC) - " ECC" -#if defined(LTC_ECC_TIMING_RESISTANT) - " (with blinding)" -#endif - "\n" -#endif -#if defined(LTC_MDSA) - " DSA\n" -#endif -#if defined(LTC_CURVE25519) -#if defined(LTC_CURVE25519) - " Ed25519\n" -#endif -#if defined(LTC_CURVE25519) - " X25519\n" -#endif -#endif -#if defined(LTC_PK_MAX_RETRIES) - " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n" -#endif - - "\nMPI (Math):\n" -#if defined(LTC_MPI) - " LTC_MPI\n" -#endif -#if defined(LTM_DESC) - " LTM_DESC\n" -#endif -#if defined(TFM_DESC) - " TFM_DESC\n" -#endif -#if defined(GMP_DESC) - " GMP_DESC\n" -#endif -#if defined(LTC_MILLER_RABIN_REPS) - " "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n" -#endif - - "\nCompiler:\n" -#if defined(_WIN64) - " WIN64 platform detected.\n" -#elif defined(_WIN32) - " WIN32 platform detected.\n" -#endif -#if defined(__CYGWIN__) - " CYGWIN Detected.\n" -#endif -#if defined(__DJGPP__) - " DJGPP Detected.\n" -#endif -#if defined(_MSC_VER) - " MSVC compiler detected.\n" -#endif -#if defined(__clang_version__) - " Clang compiler " __clang_version__ ".\n" -#elif defined(INTEL_CC) - " Intel C Compiler " __VERSION__ ".\n" -#elif defined(__GNUC__) /* clang and icc also define __GNUC__ */ - " GCC compiler " __VERSION__ ".\n" -#endif - -#if defined(__x86_64__) - " x86-64 detected.\n" -#endif -#if defined(LTC_PPC32) - " PPC32 detected.\n" -#endif - - "\nVarious others: " -#if defined(ARGTYPE) - " " NAME_VALUE(ARGTYPE) " " -#endif -#if defined(LTC_ADLER32) - " ADLER32 " -#endif -#if defined(LTC_AES_NI) - " AES-NI " -#endif -#if defined(LTC_BASE64) - " BASE64 " -#endif -#if defined(LTC_BASE64_URL) - " BASE64-URL-SAFE " -#endif -#if defined(LTC_BASE32) - " BASE32 " -#endif -#if defined(LTC_BASE16) - " BASE16 " -#endif -#if defined(LTC_BCRYPT) - " BCRYPT " - " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " " -#endif -#if defined(LTC_CRC32) - " CRC32 " -#endif -#if defined(LTC_DER) - " DER " - " " NAME_VALUE(LTC_DER_MAX_RECURSION) " " -#endif -#if defined(LTC_PKCS_1) - " PKCS#1 " -#endif -#if defined(LTC_PKCS_5) - " PKCS#5 " -#endif -#if defined(LTC_PKCS_8) - " PKCS#8 " -#endif -#if defined(LTC_PKCS_12) - " PKCS#12 " -#endif -#if defined(LTC_PADDING) - " PADDING " -#endif -#if defined(LTC_HKDF) - " HKDF " -#endif -#if defined(LTC_PBES) - " PBES1 " - " PBES2 " -#endif -#if defined(LTC_PEM) - " PEM " - " " NAME_VALUE(LTC_PEM_DECODE_BUFSZ) " " - " " NAME_VALUE(LTC_PEM_READ_BUFSIZE) " " -#endif -#if defined(LTC_SSH) - " SSH " -#endif -#if defined(LTC_PEM_SSH) - " OpenSSH-PEM " -#endif -#if defined(LTC_DEVRANDOM) - " LTC_DEVRANDOM " -#endif -#if defined(LTC_TRY_URANDOM_FIRST) - " LTC_TRY_URANDOM_FIRST " -#endif -#if defined(LTC_RNG_GET_BYTES) - " LTC_RNG_GET_BYTES " -#endif -#if defined(LTC_RNG_MAKE_PRNG) - " LTC_RNG_MAKE_PRNG " -#endif -#if defined(LTC_PRNG_ENABLE_LTC_RNG) - " LTC_PRNG_ENABLE_LTC_RNG " -#endif -#if defined(LTC_HASH_HELPERS) - " LTC_HASH_HELPERS " -#endif -#if defined(LTC_VALGRIND) - " LTC_VALGRIND " -#endif -#if defined(LTC_TEST) - " LTC_TEST " -#endif -#if defined(LTC_TEST_DBG) - " " NAME_VALUE(LTC_TEST_DBG) " " -#endif -#if defined(LTC_TEST_EXT) - " LTC_TEST_EXT " -#endif -#if defined(LTC_SMALL_CODE) - " LTC_SMALL_CODE " -#endif -#if defined(LTC_NO_FILE) - " LTC_NO_FILE " -#endif -#if defined(LTC_FILE_READ_BUFSIZE) - " " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " " -#endif -#if defined(LTC_FAST) - " LTC_FAST " -#endif -#if defined(LTC_NO_FAST) - " LTC_NO_FAST " -#endif -#if defined(LTC_NO_BSWAP) - " LTC_NO_BSWAP " -#endif -#if defined(LTC_NO_ASM) - " LTC_NO_ASM " -#endif -#if defined(LTC_ROx_BUILTIN) - " LTC_ROx_BUILTIN " -#elif defined(LTC_ROx_ASM) - " LTC_ROx_ASM " -#if defined(LTC_NO_ROLC) - " LTC_NO_ROLC " -#endif -#endif -#if defined(LTC_HAVE_ROTATE_BUILTIN) - " LTC_HAVE_ROTATE_BUILTIN " -#endif -#if defined(LTC_HAVE_CLZL_BUILTIN) - " LTC_HAVE_CLZL_BUILTIN " -#endif -#if defined(LTC_HAVE_CTZL_BUILTIN) - " LTC_HAVE_CTZL_BUILTIN " -#endif -#if defined(LTC_NO_TEST) - " LTC_NO_TEST " -#endif -#if defined(LTC_NO_TABLES) - " LTC_NO_TABLES " -#endif -#if defined(LTC_PTHREAD) - " LTC_PTHREAD " -#endif -#if defined(LTC_EASY) - " LTC_EASY " -#endif -#if defined(LTC_MECC_ACCEL) - " LTC_MECC_ACCEL " -#endif -#if defined(LTC_MECC_FP) - " LTC_MECC_FP " -#endif -#if defined(LTC_ECC_SHAMIR) - " LTC_ECC_SHAMIR " -#endif -#if defined(LTC_CLOCK_GETTIME) - " LTC_CLOCK_GETTIME " -#endif - "\n" - ; - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_argchk.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_argchk.c deleted file mode 100644 index 85b562a..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_argchk.c +++ /dev/null @@ -1,17 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_argchk.c - Perform argument checking, Tom St Denis -*/ - -#if (ARGTYPE == 0) -void crypt_argchk(const char *v, const char *s, int d) -{ - fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", - v, d, s); - abort(); -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c deleted file mode 100644 index b79ff33..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_descriptor.c +++ /dev/null @@ -1,15 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_cipher_descriptor.c - Stores the cipher descriptor table, Tom St Denis -*/ - -struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = { -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } - }; - -LTC_MUTEX_GLOBAL(ltc_cipher_mutex) - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c deleted file mode 100644 index 8745ace..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_cipher_is_valid.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_cipher_is_valid.c - Determine if cipher is valid, Tom St Denis -*/ - -/* - Test if a cipher index is valid - @param idx The index of the cipher to search for - @return CRYPT_OK if valid -*/ -int cipher_is_valid(int idx) -{ - LTC_MUTEX_LOCK(<c_cipher_mutex); - if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return CRYPT_INVALID_CIPHER; - } - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_constants.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_constants.c deleted file mode 100644 index eac6dae..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_constants.c +++ /dev/null @@ -1,290 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_constants.c - - Make various constants available to dynamic languages - like Python - Larry Bugbee, February 2013 - - LB - Dec 2013 - revised to include compiler define options - LB - Mar 2014 - added endianness and word size -*/ - -typedef struct { - const char *name; - const int value; -} crypt_constant; - -#define C_STRINGIFY(s) { #s, s } - -static const crypt_constant s_crypt_constants[] = { - - C_STRINGIFY(CRYPT_OK), - C_STRINGIFY(CRYPT_ERROR), - C_STRINGIFY(CRYPT_NOP), - C_STRINGIFY(CRYPT_INVALID_KEYSIZE), - C_STRINGIFY(CRYPT_INVALID_ROUNDS), - C_STRINGIFY(CRYPT_FAIL_TESTVECTOR), - C_STRINGIFY(CRYPT_BUFFER_OVERFLOW), - C_STRINGIFY(CRYPT_INVALID_PACKET), - C_STRINGIFY(CRYPT_INVALID_PRNGSIZE), - C_STRINGIFY(CRYPT_ERROR_READPRNG), - C_STRINGIFY(CRYPT_INVALID_CIPHER), - C_STRINGIFY(CRYPT_INVALID_HASH), - C_STRINGIFY(CRYPT_INVALID_PRNG), - C_STRINGIFY(CRYPT_MEM), - C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH), - C_STRINGIFY(CRYPT_PK_NOT_PRIVATE), - C_STRINGIFY(CRYPT_INVALID_ARG), - C_STRINGIFY(CRYPT_FILE_NOTFOUND), - C_STRINGIFY(CRYPT_PK_INVALID_TYPE), - C_STRINGIFY(CRYPT_OVERFLOW), - C_STRINGIFY(CRYPT_PK_ASN1_ERROR), - C_STRINGIFY(CRYPT_INPUT_TOO_LONG), - C_STRINGIFY(CRYPT_PK_INVALID_SIZE), - C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE), - C_STRINGIFY(CRYPT_PK_INVALID_PADDING), - C_STRINGIFY(CRYPT_HASH_OVERFLOW), - - C_STRINGIFY(PK_PUBLIC), - C_STRINGIFY(PK_PRIVATE), - - C_STRINGIFY(LTC_ENCRYPT), - C_STRINGIFY(LTC_DECRYPT), - -#ifdef LTC_PKCS_1 - {"LTC_PKCS_1", 1}, - /* Block types */ - C_STRINGIFY(LTC_PKCS_1_EMSA), - C_STRINGIFY(LTC_PKCS_1_EME), - - /* Padding types */ - C_STRINGIFY(LTC_PKCS_1_V1_5), - C_STRINGIFY(LTC_PKCS_1_OAEP), - C_STRINGIFY(LTC_PKCS_1_PSS), - C_STRINGIFY(LTC_PKCS_1_V1_5_NA1), -#else - {"LTC_PKCS_1", 0}, -#endif - -#ifdef LTC_PADDING - {"LTC_PADDING", 1}, - - C_STRINGIFY(LTC_PAD_PKCS7), -#ifdef LTC_RNG_GET_BYTES - C_STRINGIFY(LTC_PAD_ISO_10126), -#endif - C_STRINGIFY(LTC_PAD_ANSI_X923), - C_STRINGIFY(LTC_PAD_ONE_AND_ZERO), - C_STRINGIFY(LTC_PAD_ZERO), - C_STRINGIFY(LTC_PAD_ZERO_ALWAYS), -#else - {"LTC_PADDING", 0}, -#endif - -#ifdef LTC_MRSA - {"LTC_MRSA", 1}, -#else - {"LTC_MRSA", 0}, -#endif - -#ifdef LTC_MECC - {"LTC_MECC", 1}, - C_STRINGIFY(ECC_BUF_SIZE), - C_STRINGIFY(ECC_MAXSIZE), -#else - {"LTC_MECC", 0}, -#endif - -#ifdef LTC_MDSA - {"LTC_MDSA", 1}, - C_STRINGIFY(LTC_MDSA_DELTA), - C_STRINGIFY(LTC_MDSA_MAX_GROUP), - C_STRINGIFY(LTC_MDSA_MAX_MODULUS), -#else - {"LTC_MDSA", 0}, -#endif - -#ifdef LTC_MILLER_RABIN_REPS - C_STRINGIFY(LTC_MILLER_RABIN_REPS), -#endif - -#ifdef LTC_DER -/* DER handling */ - {"LTC_DER", 1}, - C_STRINGIFY(LTC_ASN1_EOL), - C_STRINGIFY(LTC_ASN1_BOOLEAN), - C_STRINGIFY(LTC_ASN1_INTEGER), - C_STRINGIFY(LTC_ASN1_SHORT_INTEGER), - C_STRINGIFY(LTC_ASN1_BIT_STRING), - C_STRINGIFY(LTC_ASN1_OCTET_STRING), - C_STRINGIFY(LTC_ASN1_NULL), - C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER), - C_STRINGIFY(LTC_ASN1_IA5_STRING), - C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING), - C_STRINGIFY(LTC_ASN1_UTF8_STRING), - C_STRINGIFY(LTC_ASN1_UTCTIME), - C_STRINGIFY(LTC_ASN1_CHOICE), - C_STRINGIFY(LTC_ASN1_SEQUENCE), - C_STRINGIFY(LTC_ASN1_SET), - C_STRINGIFY(LTC_ASN1_SETOF), - C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING), - C_STRINGIFY(LTC_ASN1_TELETEX_STRING), - C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME), - C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE), - C_STRINGIFY(LTC_DER_MAX_RECURSION), -#else - {"LTC_DER", 0}, -#endif - -#ifdef LTC_CTR_MODE - {"LTC_CTR_MODE", 1}, - C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN), - C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN), - C_STRINGIFY(LTC_CTR_RFC3686), -#else - {"LTC_CTR_MODE", 0}, -#endif -#ifdef LTC_GCM_MODE - C_STRINGIFY(LTC_GCM_MODE_IV), - C_STRINGIFY(LTC_GCM_MODE_AAD), - C_STRINGIFY(LTC_GCM_MODE_TEXT), -#endif - - C_STRINGIFY(LTC_MP_LT), - C_STRINGIFY(LTC_MP_EQ), - C_STRINGIFY(LTC_MP_GT), - - C_STRINGIFY(LTC_MP_NO), - C_STRINGIFY(LTC_MP_YES), - - C_STRINGIFY(MAXBLOCKSIZE), - C_STRINGIFY(TAB_SIZE), - C_STRINGIFY(ARGTYPE), - -#ifdef LTM_DESC - {"LTM_DESC", 1}, -#else - {"LTM_DESC", 0}, -#endif -#ifdef TFM_DESC - {"TFM_DESC", 1}, -#else - {"TFM_DESC", 0}, -#endif -#ifdef GMP_DESC - {"GMP_DESC", 1}, -#else - {"GMP_DESC", 0}, -#endif - -#ifdef LTC_FAST - {"LTC_FAST", 1}, -#else - {"LTC_FAST", 0}, -#endif - -#ifdef LTC_NO_FILE - {"LTC_NO_FILE", 1}, -#else - {"LTC_NO_FILE", 0}, -#endif - -#ifdef ENDIAN_LITTLE - {"ENDIAN_LITTLE", 1}, -#else - {"ENDIAN_LITTLE", 0}, -#endif - -#ifdef ENDIAN_BIG - {"ENDIAN_BIG", 1}, -#else - {"ENDIAN_BIG", 0}, -#endif - -#ifdef ENDIAN_32BITWORD - {"ENDIAN_32BITWORD", 1}, -#else - {"ENDIAN_32BITWORD", 0}, -#endif - -#ifdef ENDIAN_64BITWORD - {"ENDIAN_64BITWORD", 1}, -#else - {"ENDIAN_64BITWORD", 0}, -#endif - -#ifdef ENDIAN_NEUTRAL - {"ENDIAN_NEUTRAL", 1}, -#else - {"ENDIAN_NEUTRAL", 0}, -#endif -}; - - -/* crypt_get_constant() - * valueout will be the value of the named constant - * return -1 if named item not found - */ -int crypt_get_constant(const char* namein, int *valueout) { - int i; - int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]); - for (i=0; i *names_list_size) { - return -1; - } - /* build the names list */ - ptr = names_list; - for (i=0; i total_len) return -1; - total_len -= number_len; - ptr += number_len; - } - /* to remove the trailing new-line */ - ptr -= 1; - *ptr = 0; - } - return 0; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher.c deleted file mode 100644 index e45da9c..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher.c +++ /dev/null @@ -1,29 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_cipher.c - Find a cipher in the descriptor tables, Tom St Denis -*/ - -/** - Find a registered cipher by name - @param name The name of the cipher to look for - @return >= 0 if found, -1 if not present -*/ -int find_cipher(const char *name) -{ - int x; - LTC_ARGCHK(name != NULL); - LTC_MUTEX_LOCK(<c_cipher_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) { - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return -1; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_any.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_any.c deleted file mode 100644 index 5089733..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_any.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_cipher_any.c - Find a cipher in the descriptor tables, Tom St Denis -*/ - -/** - Find a cipher flexibly. First by name then if not present by block and key size - @param name The name of the cipher desired - @param blocklen The minimum length of the block cipher desired (octets) - @param keylen The minimum length of the key size desired (octets) - @return >= 0 if found, -1 if not present -*/ -int find_cipher_any(const char *name, int blocklen, int keylen) -{ - int x; - - if(name != NULL) { - x = find_cipher(name); - if (x != -1) return x; - } - - LTC_MUTEX_LOCK(<c_cipher_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name == NULL) { - continue; - } - if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_id.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_id.c deleted file mode 100644 index 4876e4a..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_cipher_id.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_cipher_id.c - Find cipher by ID, Tom St Denis -*/ - -/** - Find a cipher by ID number - @param ID The ID (not same as index) of the cipher to find - @return >= 0 if found, -1 if not present -*/ -int find_cipher_id(unsigned char ID) -{ - int x; - LTC_MUTEX_LOCK(<c_cipher_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].ID == ID) { - x = (cipher_descriptor[x].name == NULL) ? -1 : x; - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash.c deleted file mode 100644 index 4d8ae49..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_hash.c - Find a hash, Tom St Denis -*/ - -/** - Find a registered hash by name - @param name The name of the hash to look for - @return >= 0 if found, -1 if not present -*/ -int find_hash(const char *name) -{ - int x; - LTC_ARGCHK(name != NULL); - LTC_MUTEX_LOCK(<c_hash_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) { - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_any.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_any.c deleted file mode 100644 index 0827ed2..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_any.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file crypt_find_hash_any.c - Find a hash, Tom St Denis -*/ - -/** - Find a hash flexibly. First by name then if not present by digest size - @param name The name of the hash desired - @param digestlen The minimum length of the digest size (octets) - @return >= 0 if found, -1 if not present -*/int find_hash_any(const char *name, int digestlen) -{ - int x, y, z; - LTC_ARGCHK(name != NULL); - - x = find_hash(name); - if (x != -1) return x; - - LTC_MUTEX_LOCK(<c_hash_mutex); - y = MAXBLOCKSIZE+1; - z = -1; - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name == NULL) { - continue; - } - if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { - z = x; - y = hash_descriptor[x].hashsize; - } - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return z; -} - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_id.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_id.c deleted file mode 100644 index 5de4095..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_id.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_hash_id.c - Find hash by ID, Tom St Denis -*/ - -/** - Find a hash by ID number - @param ID The ID (not same as index) of the hash to find - @return >= 0 if found, -1 if not present -*/ -int find_hash_id(unsigned char ID) -{ - int x; - LTC_MUTEX_LOCK(<c_hash_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].ID == ID) { - x = (hash_descriptor[x].name == NULL) ? -1 : x; - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_oid.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_oid.c deleted file mode 100644 index 0e10235..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_hash_oid.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_hash_oid.c - Find a hash, Tom St Denis -*/ - -int find_hash_oid(const unsigned long *ID, unsigned long IDlen) -{ - int x; - LTC_ARGCHK(ID != NULL); - LTC_MUTEX_LOCK(<c_hash_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) { - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_prng.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_prng.c deleted file mode 100644 index 7297982..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_find_prng.c +++ /dev/null @@ -1,29 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_find_prng.c - Find a PRNG, Tom St Denis -*/ - -/** - Find a registered PRNG by name - @param name The name of the PRNG to look for - @return >= 0 if found, -1 if not present -*/ -int find_prng(const char *name) -{ - int x; - LTC_ARGCHK(name != NULL); - LTC_MUTEX_LOCK(<c_prng_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) { - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return x; - } - } - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return -1; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_fsa.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_fsa.c deleted file mode 100644 index 0cee029..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_fsa.c +++ /dev/null @@ -1,45 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_fsa.c - LibTomCrypt FULL SPEED AHEAD!, Tom St Denis -*/ - -/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */ -int crypt_fsa(void *mp, ...) -{ - va_list args; - void *p; - - va_start(args, mp); - if (mp != NULL) { - XMEMCPY(<c_mp, mp, sizeof(ltc_mp)); - } - - while ((p = va_arg(args, void*)) != NULL) { - if (register_cipher(p) == -1) { - va_end(args); - return CRYPT_INVALID_CIPHER; - } - } - - while ((p = va_arg(args, void*)) != NULL) { - if (register_hash(p) == -1) { - va_end(args); - return CRYPT_INVALID_HASH; - } - } - - while ((p = va_arg(args, void*)) != NULL) { - if (register_prng(p) == -1) { - va_end(args); - return CRYPT_INVALID_PRNG; - } - } - - va_end(args); - return CRYPT_OK; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_descriptor.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_descriptor.c deleted file mode 100644 index 08e0238..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_descriptor.c +++ /dev/null @@ -1,15 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_hash_descriptor.c - Stores the hash descriptor table, Tom St Denis -*/ - -struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = { -{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL } -}; - -LTC_MUTEX_GLOBAL(ltc_hash_mutex) - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_is_valid.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_is_valid.c deleted file mode 100644 index c2d9fd9..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_hash_is_valid.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_hash_is_valid.c - Determine if hash is valid, Tom St Denis -*/ - -/* - Test if a hash index is valid - @param idx The index of the hash to search for - @return CRYPT_OK if valid -*/ -int hash_is_valid(int idx) -{ - LTC_MUTEX_LOCK(<c_hash_mutex); - if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return CRYPT_INVALID_HASH; - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_inits.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_inits.c deleted file mode 100644 index f7af2b8..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_inits.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_inits.c - - Provide math library functions for dynamic languages - like Python - Larry Bugbee, February 2013 -*/ - - -#ifdef LTM_DESC -void init_LTM(void) -{ - ltc_mp = ltm_desc; -} -#endif - -#ifdef TFM_DESC -void init_TFM(void) -{ - ltc_mp = tfm_desc; -} -#endif - -#ifdef GMP_DESC -void init_GMP(void) -{ - ltc_mp = gmp_desc; -} -#endif - -int crypt_mp_init(const char* mpi) -{ - if (mpi == NULL) return CRYPT_ERROR; - switch (mpi[0]) { -#ifdef LTM_DESC - case 'l': - case 'L': - ltc_mp = ltm_desc; - return CRYPT_OK; -#endif -#ifdef TFM_DESC - case 't': - case 'T': - ltc_mp = tfm_desc; - return CRYPT_OK; -#endif -#ifdef GMP_DESC - case 'g': - case 'G': - ltc_mp = gmp_desc; - return CRYPT_OK; -#endif -#ifdef EXT_MATH_LIB - case 'e': - case 'E': - { - extern ltc_math_descriptor EXT_MATH_LIB; - ltc_mp = EXT_MATH_LIB; - } - -#if defined(LTC_TEST_DBG) -#define NAME_VALUE(s) #s"="NAME(s) -#define NAME(s) #s - printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB)); -#undef NAME_VALUE -#undef NAME -#endif - - return CRYPT_OK; -#endif - default: -#if defined(LTC_TEST_DBG) - printf("Unknown/Invalid MPI provider: %s\n", mpi); -#endif - return CRYPT_ERROR; - } -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c deleted file mode 100644 index 760ba63..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_ltc_mp_descriptor.c +++ /dev/null @@ -1,6 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */ -ltc_math_descriptor ltc_mp = { 0 }; diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_descriptor.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_descriptor.c deleted file mode 100644 index 94c26b8..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_descriptor.c +++ /dev/null @@ -1,14 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_prng_descriptor.c - Stores the PRNG descriptors, Tom St Denis -*/ -struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = { -{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - -LTC_MUTEX_GLOBAL(ltc_prng_mutex) - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_is_valid.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_is_valid.c deleted file mode 100644 index f1ba67b..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_is_valid.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_prng_is_valid.c - Determine if PRNG is valid, Tom St Denis -*/ - -/* - Test if a PRNG index is valid - @param idx The index of the PRNG to search for - @return CRYPT_OK if valid -*/ -int prng_is_valid(int idx) -{ - LTC_MUTEX_LOCK(<c_prng_mutex); - if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return CRYPT_INVALID_PRNG; - } - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c deleted file mode 100644 index 49a456f..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_prng_rng_descriptor.c +++ /dev/null @@ -1,7 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PRNG_ENABLE_LTC_RNG -unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c deleted file mode 100644 index 5193ff9..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_ciphers.c +++ /dev/null @@ -1,104 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file crypt_register_all_ciphers.c - - Steffen Jaeckel -*/ - -#define REGISTER_CIPHER(h) do {\ - LTC_ARGCHK(register_cipher(h) != -1); \ -} while(0) - -int register_all_ciphers(void) -{ -#ifdef LTC_RIJNDAEL - /* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */ -#ifdef ENCRYPT_ONLY - /* alternative would be - * register_cipher(&rijndael_enc_desc); - */ - REGISTER_CIPHER(&aes_enc_desc); -#else - /* alternative would be - * register_cipher(&rijndael_desc); - */ - REGISTER_CIPHER(&aes_desc); -#endif -#endif -#ifdef LTC_BLOWFISH - REGISTER_CIPHER(&blowfish_desc); -#endif -#ifdef LTC_XTEA - REGISTER_CIPHER(&xtea_desc); -#endif -#ifdef LTC_RC5 - REGISTER_CIPHER(&rc5_desc); -#endif -#ifdef LTC_RC6 - REGISTER_CIPHER(&rc6_desc); -#endif -#ifdef LTC_SAFERP - REGISTER_CIPHER(&saferp_desc); -#endif -#ifdef LTC_TWOFISH - REGISTER_CIPHER(&twofish_desc); -#endif -#ifdef LTC_SAFER - REGISTER_CIPHER(&safer_k64_desc); - REGISTER_CIPHER(&safer_sk64_desc); - REGISTER_CIPHER(&safer_k128_desc); - REGISTER_CIPHER(&safer_sk128_desc); -#endif -#ifdef LTC_RC2 - REGISTER_CIPHER(&rc2_desc); -#endif -#ifdef LTC_DES - REGISTER_CIPHER(&des_desc); - REGISTER_CIPHER(&desx_desc); - REGISTER_CIPHER(&des3_desc); -#endif -#ifdef LTC_SM4 - REGISTER_CIPHER(&sm4_desc); -#endif -#ifdef LTC_CAST5 - REGISTER_CIPHER(&cast5_desc); -#endif -#ifdef LTC_NOEKEON - REGISTER_CIPHER(&noekeon_desc); -#endif -#ifdef LTC_SKIPJACK - REGISTER_CIPHER(&skipjack_desc); -#endif -#ifdef LTC_ANUBIS - REGISTER_CIPHER(&anubis_desc); -#endif -#ifdef LTC_KHAZAD - REGISTER_CIPHER(&khazad_desc); -#endif -#ifdef LTC_KSEED - REGISTER_CIPHER(&kseed_desc); -#endif -#ifdef LTC_KASUMI - REGISTER_CIPHER(&kasumi_desc); -#endif -#ifdef LTC_MULTI2 - REGISTER_CIPHER(&multi2_desc); -#endif -#ifdef LTC_CAMELLIA - REGISTER_CIPHER(&camellia_desc); -#endif -#ifdef LTC_IDEA - REGISTER_CIPHER(&idea_desc); -#endif -#ifdef LTC_SERPENT - REGISTER_CIPHER(&serpent_desc); -#endif -#ifdef LTC_TEA - REGISTER_CIPHER(&tea_desc); -#endif - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_hashes.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_hashes.c deleted file mode 100644 index 362205f..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_hashes.c +++ /dev/null @@ -1,101 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file crypt_register_all_hashes.c - - Steffen Jaeckel -*/ - -#define REGISTER_HASH(h) do {\ - LTC_ARGCHK(register_hash(h) != -1); \ -} while(0) - -int register_all_hashes(void) -{ -#ifdef LTC_TIGER - REGISTER_HASH(&tiger_desc); - REGISTER_HASH(&tiger2_desc); -#endif -#ifdef LTC_MD2 - REGISTER_HASH(&md2_desc); -#endif -#ifdef LTC_MD4 - REGISTER_HASH(&md4_desc); -#endif -#ifdef LTC_MD5 - REGISTER_HASH(&md5_desc); -#endif -#ifdef LTC_SHA1 - REGISTER_HASH(&sha1_desc); -#endif -#ifdef LTC_SHA224 - REGISTER_HASH(&sha224_desc); -#endif -#ifdef LTC_SHA256 - REGISTER_HASH(&sha256_desc); -#endif -#ifdef LTC_SHA384 - REGISTER_HASH(&sha384_desc); -#endif -#ifdef LTC_SHA512 - REGISTER_HASH(&sha512_desc); -#endif -#ifdef LTC_SHA512_224 - REGISTER_HASH(&sha512_224_desc); -#endif -#ifdef LTC_SHA512_256 - REGISTER_HASH(&sha512_256_desc); -#endif -#ifdef LTC_SHA3 - REGISTER_HASH(&sha3_224_desc); - REGISTER_HASH(&sha3_256_desc); - REGISTER_HASH(&sha3_384_desc); - REGISTER_HASH(&sha3_512_desc); -#endif -#ifdef LTC_KECCAK - REGISTER_HASH(&keccak_224_desc); - REGISTER_HASH(&keccak_256_desc); - REGISTER_HASH(&keccak_384_desc); - REGISTER_HASH(&keccak_512_desc); -#endif -#ifdef LTC_RIPEMD128 - REGISTER_HASH(&rmd128_desc); -#endif -#ifdef LTC_RIPEMD160 - REGISTER_HASH(&rmd160_desc); -#endif -#ifdef LTC_RIPEMD256 - REGISTER_HASH(&rmd256_desc); -#endif -#ifdef LTC_RIPEMD320 - REGISTER_HASH(&rmd320_desc); -#endif -#ifdef LTC_WHIRLPOOL - REGISTER_HASH(&whirlpool_desc); -#endif -#ifdef LTC_BLAKE2S - REGISTER_HASH(&blake2s_128_desc); - REGISTER_HASH(&blake2s_160_desc); - REGISTER_HASH(&blake2s_224_desc); - REGISTER_HASH(&blake2s_256_desc); -#endif -#ifdef LTC_BLAKE2S - REGISTER_HASH(&blake2b_160_desc); - REGISTER_HASH(&blake2b_256_desc); - REGISTER_HASH(&blake2b_384_desc); - REGISTER_HASH(&blake2b_512_desc); -#endif -#ifdef LTC_CHC_HASH - { - int aes_index = find_cipher_any("aes", 8, 16); - if (aes_index != -1) { - REGISTER_HASH(&chc_desc); - LTC_ARGCHK(chc_register(aes_index) == CRYPT_OK); - } - } -#endif - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_prngs.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_prngs.c deleted file mode 100644 index 4a2e2ef..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_all_prngs.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file crypt_register_all_prngs.c - - Steffen Jaeckel -*/ - -#define REGISTER_PRNG(h) do {\ - LTC_ARGCHK(register_prng(h) != -1); \ -} while(0) - -int register_all_prngs(void) -{ -#ifdef LTC_YARROW - REGISTER_PRNG(&yarrow_desc); -#endif -#ifdef LTC_FORTUNA - REGISTER_PRNG(&fortuna_desc); -#endif -#ifdef LTC_RC4 - REGISTER_PRNG(&rc4_desc); -#endif -#ifdef LTC_CHACHA20_PRNG - REGISTER_PRNG(&chacha20_prng_desc); -#endif -#ifdef LTC_SOBER128 - REGISTER_PRNG(&sober128_desc); -#endif -#ifdef LTC_SPRNG - REGISTER_PRNG(&sprng_desc); -#endif - - return CRYPT_OK; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_cipher.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_cipher.c deleted file mode 100644 index 33c8696..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_cipher.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_register_cipher.c - Register a cipher, Tom St Denis -*/ - -/** - Register a cipher with the descriptor table - @param cipher The cipher you wish to register - @return value >= 0 if successfully added (or already present), -1 if unsuccessful -*/ -int register_cipher(const struct ltc_cipher_descriptor *cipher) -{ - int x; - - LTC_ARGCHK(cipher != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_cipher_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name == NULL) { - XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)); - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return x; - } - } - - /* no spot */ - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_hash.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_hash.c deleted file mode 100644 index 1668de3..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_hash.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_register_hash.c - Register a HASH, Tom St Denis -*/ - -/** - Register a hash with the descriptor table - @param hash The hash you wish to register - @return value >= 0 if successfully added (or already present), -1 if unsuccessful -*/ -int register_hash(const struct ltc_hash_descriptor *hash) -{ - int x; - - LTC_ARGCHK(hash != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_hash_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name == NULL) { - XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)); - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return x; - } - } - - /* no spot */ - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_prng.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_prng.c deleted file mode 100644 index 08e056b..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_register_prng.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_register_prng.c - Register a PRNG, Tom St Denis -*/ - -/** - Register a PRNG with the descriptor table - @param prng The PRNG you wish to register - @return value >= 0 if successfully added (or already present), -1 if unsuccessful -*/ -int register_prng(const struct ltc_prng_descriptor *prng) -{ - int x; - - LTC_ARGCHK(prng != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_prng_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (prng_descriptor[x].name == NULL) { - XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)); - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return x; - } - } - - /* no spot */ - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return -1; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_sizes.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_sizes.c deleted file mode 100644 index 26f2d13..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_sizes.c +++ /dev/null @@ -1,354 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_sizes.c - - Make various struct sizes available to dynamic languages - like Python - Larry Bugbee, February 2013 - - LB - Dec 2013 - revised to include compiler define options -*/ - - -typedef struct { - const char *name; - const unsigned int size; -} crypt_size; - -#define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) } -#define SZ_STRINGIFY_T(s) { #s, sizeof(s) } - -static const crypt_size s_crypt_sizes[] = { - /* hash state sizes */ - SZ_STRINGIFY_S(ltc_hash_descriptor), - SZ_STRINGIFY_T(hash_state), -#ifdef LTC_CHC_HASH - SZ_STRINGIFY_S(chc_state), -#endif -#ifdef LTC_WHIRLPOOL - SZ_STRINGIFY_S(whirlpool_state), -#endif -#ifdef LTC_SHA3 - SZ_STRINGIFY_S(sha3_state), -#endif -#ifdef LTC_SHA512 - SZ_STRINGIFY_S(sha512_state), -#endif -#ifdef LTC_SHA256 - SZ_STRINGIFY_S(sha256_state), -#endif -#ifdef LTC_SHA1 - SZ_STRINGIFY_S(sha1_state), -#endif -#ifdef LTC_MD5 - SZ_STRINGIFY_S(md5_state), -#endif -#ifdef LTC_MD4 - SZ_STRINGIFY_S(md4_state), -#endif -#ifdef LTC_MD2 - SZ_STRINGIFY_S(md2_state), -#endif -#ifdef LTC_TIGER - SZ_STRINGIFY_S(tiger_state), -#endif -#ifdef LTC_RIPEMD128 - SZ_STRINGIFY_S(rmd128_state), -#endif -#ifdef LTC_RIPEMD160 - SZ_STRINGIFY_S(rmd160_state), -#endif -#ifdef LTC_RIPEMD256 - SZ_STRINGIFY_S(rmd256_state), -#endif -#ifdef LTC_RIPEMD320 - SZ_STRINGIFY_S(rmd320_state), -#endif -#ifdef LTC_BLAKE2S - SZ_STRINGIFY_S(blake2s_state), -#endif -#ifdef LTC_BLAKE2B - SZ_STRINGIFY_S(blake2b_state), -#endif - - /* block cipher key sizes */ - SZ_STRINGIFY_S(ltc_cipher_descriptor), - SZ_STRINGIFY_T(symmetric_key), -#ifdef LTC_ANUBIS - SZ_STRINGIFY_S(anubis_key), -#endif -#ifdef LTC_CAMELLIA - SZ_STRINGIFY_S(camellia_key), -#endif -#ifdef LTC_BLOWFISH - SZ_STRINGIFY_S(blowfish_key), -#endif -#ifdef LTC_CAST5 - SZ_STRINGIFY_S(cast5_key), -#endif -#ifdef LTC_DES - SZ_STRINGIFY_S(des_key), - SZ_STRINGIFY_S(des3_key), -#endif -#ifdef LTC_SM4 - SZ_STRINGIFY_S(sm4_key), -#endif -#ifdef LTC_IDEA - SZ_STRINGIFY_S(idea_key), -#endif -#ifdef LTC_KASUMI - SZ_STRINGIFY_S(kasumi_key), -#endif -#ifdef LTC_KHAZAD - SZ_STRINGIFY_S(khazad_key), -#endif -#ifdef LTC_KSEED - SZ_STRINGIFY_S(kseed_key), -#endif -#ifdef LTC_MULTI2 - SZ_STRINGIFY_S(multi2_key), -#endif -#ifdef LTC_NOEKEON - SZ_STRINGIFY_S(noekeon_key), -#endif -#ifdef LTC_RC2 - SZ_STRINGIFY_S(rc2_key), -#endif -#ifdef LTC_RC5 - SZ_STRINGIFY_S(rc5_key), -#endif -#ifdef LTC_RC6 - SZ_STRINGIFY_S(rc6_key), -#endif -#ifdef LTC_SERPENT - SZ_STRINGIFY_S(serpent_key), -#endif -#ifdef LTC_SKIPJACK - SZ_STRINGIFY_S(skipjack_key), -#endif -#ifdef LTC_XTEA - SZ_STRINGIFY_S(xtea_key), -#endif -#ifdef LTC_RIJNDAEL - SZ_STRINGIFY_S(rijndael_key), -#endif -#ifdef LTC_SAFER - SZ_STRINGIFY_S(safer_key), -#endif -#ifdef LTC_SAFERP - SZ_STRINGIFY_S(saferp_key), -#endif -#ifdef LTC_TWOFISH - SZ_STRINGIFY_S(twofish_key), -#endif - - /* mode sizes */ -#ifdef LTC_ECB_MODE - SZ_STRINGIFY_T(symmetric_ECB), -#endif -#ifdef LTC_CFB_MODE - SZ_STRINGIFY_T(symmetric_CFB), -#endif -#ifdef LTC_OFB_MODE - SZ_STRINGIFY_T(symmetric_OFB), -#endif -#ifdef LTC_CBC_MODE - SZ_STRINGIFY_T(symmetric_CBC), -#endif -#ifdef LTC_CTR_MODE - SZ_STRINGIFY_T(symmetric_CTR), -#endif -#ifdef LTC_LRW_MODE - SZ_STRINGIFY_T(symmetric_LRW), -#endif -#ifdef LTC_F8_MODE - SZ_STRINGIFY_T(symmetric_F8), -#endif -#ifdef LTC_XTS_MODE - SZ_STRINGIFY_T(symmetric_xts), -#endif - - /* stream cipher sizes */ -#ifdef LTC_CHACHA - SZ_STRINGIFY_T(chacha_state), -#endif -#ifdef LTC_SALSA20 - SZ_STRINGIFY_T(salsa20_state), -#endif -#ifdef LTC_SOSEMANUK - SZ_STRINGIFY_T(sosemanuk_state), -#endif -#ifdef LTC_RABBIT - SZ_STRINGIFY_T(rabbit_state), -#endif -#ifdef LTC_RC4_STREAM - SZ_STRINGIFY_T(rc4_state), -#endif -#ifdef LTC_SOBER128_STREAM - SZ_STRINGIFY_T(sober128_state), -#endif - - /* MAC sizes -- no states for ccm, lrw */ -#ifdef LTC_HMAC - SZ_STRINGIFY_T(hmac_state), -#endif -#ifdef LTC_OMAC - SZ_STRINGIFY_T(omac_state), -#endif -#ifdef LTC_PMAC - SZ_STRINGIFY_T(pmac_state), -#endif -#ifdef LTC_POLY1305 - SZ_STRINGIFY_T(poly1305_state), -#endif -#ifdef LTC_EAX_MODE - SZ_STRINGIFY_T(eax_state), -#endif -#ifdef LTC_OCB_MODE - SZ_STRINGIFY_T(ocb_state), -#endif -#ifdef LTC_OCB3_MODE - SZ_STRINGIFY_T(ocb3_state), -#endif -#ifdef LTC_CCM_MODE - SZ_STRINGIFY_T(ccm_state), -#endif -#ifdef LTC_GCM_MODE - SZ_STRINGIFY_T(gcm_state), -#endif -#ifdef LTC_PELICAN - SZ_STRINGIFY_T(pelican_state), -#endif -#ifdef LTC_XCBC - SZ_STRINGIFY_T(xcbc_state), -#endif -#ifdef LTC_F9_MODE - SZ_STRINGIFY_T(f9_state), -#endif -#ifdef LTC_CHACHA20POLY1305_MODE - SZ_STRINGIFY_T(chacha20poly1305_state), -#endif - - /* asymmetric keys */ -#ifdef LTC_MRSA - SZ_STRINGIFY_T(rsa_key), -#endif -#ifdef LTC_MDSA - SZ_STRINGIFY_T(dsa_key), -#endif -#ifdef LTC_MDH - SZ_STRINGIFY_T(dh_key), -#endif -#ifdef LTC_MECC - SZ_STRINGIFY_T(ltc_ecc_curve), - SZ_STRINGIFY_T(ecc_point), - SZ_STRINGIFY_T(ecc_key), -#endif - - /* DER handling */ -#ifdef LTC_DER - SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */ - SZ_STRINGIFY_T(ltc_utctime), - SZ_STRINGIFY_T(ltc_generalizedtime), -#endif - - /* prng state sizes */ - SZ_STRINGIFY_S(ltc_prng_descriptor), - SZ_STRINGIFY_T(prng_state), -#ifdef LTC_FORTUNA - SZ_STRINGIFY_S(fortuna_prng), -#endif -#ifdef LTC_CHACHA20_PRNG - SZ_STRINGIFY_S(chacha20_prng), -#endif -#ifdef LTC_RC4 - SZ_STRINGIFY_S(rc4_prng), -#endif -#ifdef LTC_SOBER128 - SZ_STRINGIFY_S(sober128_prng), -#endif -#ifdef LTC_YARROW - SZ_STRINGIFY_S(yarrow_prng), -#endif - /* sprng has no state as it uses other potentially available sources */ - /* like /dev/random. See Developers Guide for more info. */ - -#ifdef LTC_ADLER32 - SZ_STRINGIFY_T(adler32_state), -#endif -#ifdef LTC_CRC32 - SZ_STRINGIFY_T(crc32_state), -#endif - - SZ_STRINGIFY_T(ltc_mp_digit), - SZ_STRINGIFY_T(ltc_math_descriptor) - -}; - -/* crypt_get_size() - * sizeout will be the size (bytes) of the named struct or union - * return -1 if named item not found - */ -int crypt_get_size(const char* namein, unsigned int *sizeout) { - int i; - int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]); - for (i=0; i *names_list_size) { - return -1; - } - /* build the names list */ - ptr = names_list; - for (i=0; i total_len) return -1; - total_len -= number_len; - ptr += number_len; - } - /* to remove the trailing new-line */ - ptr -= 1; - *ptr = 0; - } - return 0; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_cipher.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_cipher.c deleted file mode 100644 index bebf920..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_cipher.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_unregister_cipher.c - Unregister a cipher, Tom St Denis -*/ - -/** - Unregister a cipher from the descriptor table - @param cipher The cipher descriptor to remove - @return CRYPT_OK on success -*/ -int unregister_cipher(const struct ltc_cipher_descriptor *cipher) -{ - int x; - - LTC_ARGCHK(cipher != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_cipher_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) { - cipher_descriptor[x].name = NULL; - cipher_descriptor[x].ID = 255; - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return CRYPT_OK; - } - } - LTC_MUTEX_UNLOCK(<c_cipher_mutex); - return CRYPT_ERROR; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_hash.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_hash.c deleted file mode 100644 index c2374d0..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_hash.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_unregister_hash.c - Unregister a hash, Tom St Denis -*/ - -/** - Unregister a hash from the descriptor table - @param hash The hash descriptor to remove - @return CRYPT_OK on success -*/ -int unregister_hash(const struct ltc_hash_descriptor *hash) -{ - int x; - - LTC_ARGCHK(hash != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_hash_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { - hash_descriptor[x].name = NULL; - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return CRYPT_OK; - } - } - LTC_MUTEX_UNLOCK(<c_hash_mutex); - return CRYPT_ERROR; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_prng.c b/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_prng.c deleted file mode 100644 index 1aa11e0..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/crypt/crypt_unregister_prng.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file crypt_unregister_prng.c - Unregister a PRNG, Tom St Denis -*/ - -/** - Unregister a PRNG from the descriptor table - @param prng The PRNG descriptor to remove - @return CRYPT_OK on success -*/ -int unregister_prng(const struct ltc_prng_descriptor *prng) -{ - int x; - - LTC_ARGCHK(prng != NULL); - - /* is it already registered? */ - LTC_MUTEX_LOCK(<c_prng_mutex); - for (x = 0; x < TAB_SIZE; x++) { - if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { - prng_descriptor[x].name = NULL; - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return CRYPT_OK; - } - } - LTC_MUTEX_UNLOCK(<c_prng_mutex); - return CRYPT_ERROR; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/error_to_string.c b/Sources/DataLiteC/libtomcrypt/misc/error_to_string.c deleted file mode 100644 index fd306bb..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/error_to_string.c +++ /dev/null @@ -1,71 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file error_to_string.c - Convert error codes to ASCII strings, Tom St Denis -*/ - -static const char * const err_2_str[CRYPT_ERR_NUM] = -{ - "CRYPT_OK", - "CRYPT_ERROR", - "Non-fatal 'no-operation' requested.", - - "Invalid key size.", - "Invalid number of rounds for block cipher.", - "Algorithm failed test vectors.", - - "Buffer overflow.", - "Invalid input packet.", - - "Invalid number of bits for a PRNG.", - "Error reading the PRNG.", - - "Invalid cipher specified.", - "Invalid hash specified.", - "Invalid PRNG specified.", - - "Out of memory.", - - "Invalid PK key or key type specified for function.", - "A private PK key is required.", - - "Invalid argument provided.", - "File Not Found", - - "Invalid PK type.", - - "An overflow of a value was detected/prevented.", - - "An ASN.1 decoding error occurred.", - - "The input was longer than expected.", - - "Invalid size input for PK parameters.", - - "Invalid size for prime.", - "Invalid padding.", - - "Hash applied to too many bits.", - "Password context to decrypt key file is missing.", - "The PEM header was not recognized", -}; - -LTC_STATIC_ASSERT(correct_err_2_str_size, LTC_ARRAY_SIZE(err_2_str) == CRYPT_ERR_NUM) - -/** - Convert an LTC error code to ASCII - @param err The error code - @return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid. -*/ -const char *error_to_string(int err) -{ - if (err < 0 || err >= CRYPT_ERR_NUM) { - return "Invalid error code."; - } - return err_2_str[err]; -} - diff --git a/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf.c b/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf.c deleted file mode 100644 index 86b4ee8..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf.c +++ /dev/null @@ -1,135 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include -#include -#include - -#include "tomcrypt_private.h" - -#ifdef LTC_HKDF - -/* This is mostly just a wrapper around hmac_memory */ -int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - /* libtomcrypt chokes on a zero length HMAC key, so we need to check for - that. HMAC specifies that keys shorter than the hash's blocksize are - 0 padded to the block size. HKDF specifies that a NULL salt is to be - substituted with a salt comprised of hashLen 0 bytes. HMAC's padding - means that in either case the HMAC is actually using a blocksize long - zero filled key. Unless blocksize < hashLen (which wouldn't make any - sense), we can use a single 0 byte as the HMAC key and still generate - valid results for HKDF. */ - if (salt == NULL || saltlen == 0) { - return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); - } - return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); -} - -int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen) -{ - unsigned long hashsize; - int err; - unsigned char N; - unsigned long Noutlen, outoff; - - unsigned char *T, *dat; - unsigned long Tlen, datlen; - - /* make sure hash descriptor is valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - hashsize = hash_descriptor[hash_idx].hashsize; - - /* RFC5869 parameter restrictions */ - if (inlen < hashsize || outlen > hashsize * 255) { - return CRYPT_INVALID_ARG; - } - if (info == NULL && infolen != 0) { - return CRYPT_INVALID_ARG; - } - LTC_ARGCHK(out != NULL); - - Tlen = hashsize + infolen + 1; - T = XMALLOC(Tlen); /* Replace with static buffer? */ - if (T == NULL) { - return CRYPT_MEM; - } - if (info != NULL) { - XMEMCPY(T + hashsize, info, infolen); - } - - /* HMAC data T(1) doesn't include a previous hash value */ - dat = T + hashsize; - datlen = Tlen - hashsize; - - N = 0; - outoff = 0; /* offset in out to write to */ - while (1) { /* an exit condition breaks mid-loop */ - Noutlen = MIN(hashsize, outlen - outoff); - T[Tlen - 1] = ++N; - if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, - out + outoff, &Noutlen)) != CRYPT_OK) { - zeromem(T, Tlen); - XFREE(T); - return err; - } - outoff += Noutlen; - - if (outoff >= outlen) { /* loop exit condition */ - break; - } - - /* All subsequent HMAC data T(N) DOES include the previous hash value */ - XMEMCPY(T, out + hashsize * (N-1), hashsize); - if (N == 1) { - dat = T; - datlen = Tlen; - } - } - zeromem(T, Tlen); - XFREE(T); - return CRYPT_OK; -} - -/* all in one step */ -int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, - const unsigned char *info, unsigned long infolen, - const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen) -{ - unsigned long hashsize; - int err; - unsigned char *extracted; - - /* make sure hash descriptor is valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - hashsize = hash_descriptor[hash_idx].hashsize; - - extracted = XMALLOC(hashsize); /* replace with static buffer? */ - if (extracted == NULL) { - return CRYPT_MEM; - } - if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { - zeromem(extracted, hashsize); - XFREE(extracted); - return err; - } - err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); - zeromem(extracted, hashsize); - XFREE(extracted); - return err; -} -#endif /* LTC_HKDF */ - - -/* vim: set ts=2 sw=2 et ai si: */ diff --git a/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf_test.c b/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf_test.c deleted file mode 100644 index 99a970c..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/hkdf/hkdf_test.c +++ /dev/null @@ -1,284 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hkdf_test.c - LTC_HKDF support, self-test, Steffen Jaeckel -*/ - -#ifdef LTC_HKDF - -/* - TEST CASES SOURCE: - -Internet Engineering Task Force (IETF) H. Krawczyk -Request for Comments: 5869 IBM Research -Category: Informational P. Eronen -ISSN: 2070-1721 Nokia - May 2010 -Appendix A. Test Vectors -*/ - -/** - LTC_HKDF self-test - @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. -*/ -int hkdf_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - unsigned char OKM[82]; - int i; - - static const struct hkdf_test_case { - int num; - const char* Hash; - unsigned char IKM[80]; - unsigned long IKM_l; - unsigned char salt[80]; - unsigned long salt_l; - unsigned char info[80]; - unsigned long info_l; - unsigned char PRK[32]; - unsigned long PRK_l; - unsigned char OKM[82]; - unsigned long OKM_l; - } cases[] = { -#ifdef LTC_SHA256 - /* - Basic test case with SHA-256 - - Hash = SHA-256 - IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) - salt = 0x000102030405060708090a0b0c (13 octets) - info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) - L = 42 - - PRK = 0x077709362c2e32df0ddc3f0dc47bba63 - 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) - OKM = 0x3cb25f25faacd57a90434f64d0362f2a - 2d2d0a90cf1a5a4c5db02d56ecc4c5bf - 34007208d5b887185865 (42 octets) - */ - {1, "sha256", - {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, - {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9}, 10, - {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, - 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, - 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, - 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32, - {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, - 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, - 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, - 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, - 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, - 0x58, 0x65}, 42}, -#ifdef LTC_TEST_EXT - /* Test with SHA-256 and longer inputs/outputs */ - {2, "sha256", - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, - {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, - {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, - {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, - 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, - 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, - 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32, - {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, - 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, - 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, - 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, - 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, - 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, - 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, - 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, - 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, - 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, - 0x1d, 0x87}, 82}, - /* Test with SHA-256 and zero length salt/info */ - {3, "sha256", - {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, - {0}, 0, - {0}, 0, - {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, - 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, - 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, - 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32, - {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, - 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, - 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, - 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, - 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, - 0x96, 0xc8}, 42}, -#endif /* LTC_TEST_EXT */ -#endif /* LTC_SHA256 */ -#ifdef LTC_SHA1 - /* Basic test case with SHA-1 */ - {4, "sha1", - {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b}, 11, - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, - {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9}, 10, - {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, - 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, - 0xaa, 0x2b, 0xa2, 0x43}, 20, - {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, - 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, - 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, - 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, - 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, - 0xf8, 0x96}, 42}, -#ifdef LTC_TEST_EXT - /* Test with SHA-1 and longer inputs/outputs */ - {5, "sha1", - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, - {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, - {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, - {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, - 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, - 0x22, 0x4c, 0xfa, 0xf6}, 20, - {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, - 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, - 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, - 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, - 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, - 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, - 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, - 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, - 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, - 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, - 0xd3, 0xb4}, 82}, - /* Test with SHA-1 and zero-length salt/info */ - {6, "sha1", - {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, - {0}, 0, - {0}, 0, - {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, - 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, - 0xa0, 0xd3, 0x2d, 0x01}, 20, - {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, - 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, - 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, - 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, - 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, - 0x49, 0x18}, 42}, - /* Test with SHA-1, salt not provided (defaults to HashLen zero octets), - zero-length info */ - {7, "sha1", - {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22, - {0}, 0, /* pass a null pointer */ - {0}, 0, - {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, - 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, - 0x73, 0x13, 0x85, 0xdd}, 20, - {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, - 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, - 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, - 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, - 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, - 0xfc, 0x48}, 42}, -#endif /* LTC_TEST_EXT */ -#endif /* LTC_SHA1 */ - }; - - int err; - int tested=0,failed=0; - for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { - int hash = find_hash(cases[i].Hash); - if (hash == -1) continue; - ++tested; - if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, - cases[i].info, cases[i].info_l, - cases[i].IKM, cases[i].IKM_l, - OKM, cases[i].OKM_l)) != CRYPT_OK) { -#if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1) - printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); -#endif - return err; - } - - if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) { - failed++; - } - } - - if (failed != 0) { - return CRYPT_FAIL_TESTVECTOR; - } - if (tested == 0) { - return CRYPT_NOP; - } - return CRYPT_OK; - #endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/misc/mem_neq.c b/Sources/DataLiteC/libtomcrypt/misc/mem_neq.c deleted file mode 100644 index 8078a0a..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/mem_neq.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file mem_neq.c - Compare two blocks of memory for inequality in constant time. - Steffen Jaeckel -*/ - -/** - Compare two blocks of memory for inequality in constant time. - - The usage is similar to that of standard memcmp, but you can only test - if the memory is equal or not - you can not determine by how much the - first different byte differs. - - This function shall be used to compare results of cryptographic - operations where inequality means most likely usage of a wrong key. - The execution time has therefore to be constant as otherwise - timing attacks could be possible. - - @param a The first memory region - @param b The second memory region - @param len The length of the area to compare (octets) - - @return 0 when a and b are equal for len bytes, 1 they are not equal. -*/ -int mem_neq(const void *a, const void *b, size_t len) -{ - unsigned char ret = 0; - const unsigned char* pa; - const unsigned char* pb; - - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - - pa = a; - pb = b; - - while (len-- > 0) { - ret |= *pa ^ *pb; - ++pa; - ++pb; - } - - ret |= ret >> 4; - ret |= ret >> 2; - ret |= ret >> 1; - ret &= 1; - - return ret; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/padding/padding_depad.c b/Sources/DataLiteC/libtomcrypt/misc/padding/padding_depad.c deleted file mode 100644 index e3f7151..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/padding/padding_depad.c +++ /dev/null @@ -1,90 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PADDING - -/** - Remove padding from your data - - This depads your data. - - @param data The data to depad - @param length [in/out] The size of the data before/after (removing padding) - @param mode One of the LTC_PAD_xx flags - @return CRYPT_OK on success -*/ -int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode) -{ - unsigned long padded_length, unpadded_length, n; - unsigned char pad; - enum padding_type type; - - LTC_ARGCHK(data != NULL); - LTC_ARGCHK(length != NULL); - - padded_length = *length; - - type = mode & LTC_PAD_MASK; - - if (type < LTC_PAD_ONE_AND_ZERO) { - pad = data[padded_length - 1]; - - if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG; - - unpadded_length = padded_length - pad; - } else { - /* init pad to calm old compilers */ - pad = 0x0; - unpadded_length = padded_length; - } - - switch (type) { - case LTC_PAD_ANSI_X923: - pad = 0x0; - /* FALLTHROUGH */ - case LTC_PAD_PKCS7: - for (n = unpadded_length; n < padded_length - 1; ++n) { - if (data[n] != pad) return CRYPT_INVALID_PACKET; - } - break; -#ifdef LTC_RNG_GET_BYTES - case LTC_PAD_ISO_10126: - /* nop */ - break; -#endif - case LTC_PAD_SSH: - pad = 0x1; - for (n = unpadded_length; n < padded_length; ++n) { - if (data[n] != pad++) return CRYPT_INVALID_PACKET; - } - break; - case LTC_PAD_ONE_AND_ZERO: - while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) { - if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET; - unpadded_length--; - } - if (unpadded_length == 0) return CRYPT_INVALID_PACKET; - unpadded_length--; - if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET; - break; - case LTC_PAD_ZERO: - case LTC_PAD_ZERO_ALWAYS: - while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) { - unpadded_length--; - } - if (type == LTC_PAD_ZERO_ALWAYS) { - if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET; - if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET; - } - break; - default: - return CRYPT_INVALID_ARG; - } - - *length = unpadded_length; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/padding/padding_pad.c b/Sources/DataLiteC/libtomcrypt/misc/padding/padding_pad.c deleted file mode 100644 index 7d8bbba..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/padding/padding_pad.c +++ /dev/null @@ -1,151 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PADDING - -/** - Determine the to-be-padded length. - - @param length [in/out] The size of the data before/after padding - @param mode Mask of (LTC_PAD_xxx | block_length) - @return CRYPT_OK on success -*/ -static int s_padding_padded_length(unsigned long *length, unsigned long mode) -{ - enum padding_type padding; - unsigned char pad, block_length, r, t; - - LTC_ARGCHK(length != NULL); - - block_length = mode & 0xff; - padding = mode & LTC_PAD_MASK; - r = *length % block_length; - - switch (padding) { - case LTC_PAD_ZERO: - if (r == 0) { - t = 0; - break; - } - /* FALLTHROUGH */ - case LTC_PAD_PKCS7: - case LTC_PAD_ONE_AND_ZERO: - case LTC_PAD_ZERO_ALWAYS: - case LTC_PAD_SSH: - t = 1; - break; -#ifdef LTC_RNG_GET_BYTES - case LTC_PAD_ISO_10126: - do { - if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) { - return CRYPT_ERROR_READPRNG; - } - t %= (256 / block_length); - } while (t == 0); - break; -#endif - case LTC_PAD_ANSI_X923: - if (block_length != 16) { - return CRYPT_INVALID_ARG; - } - t = 1; - break; - default: - return CRYPT_INVALID_ARG; - } - - pad = (t * block_length) - r; - - if ((pad == 0) && (padding != LTC_PAD_ZERO)) { - pad = block_length; - } - - *length += pad; - - return CRYPT_OK; -} - -/** - Add padding to data. - - This pads your data. - - @param data The data to depad - @param length The size of the data before padding - @param padded_length [in/out] The size of the data available/after padding - @param mode One of the LTC_PAD_xx flags - @return CRYPT_OK on success -*/ -int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode) -{ - unsigned long l, n; - enum padding_type type; - int err; - unsigned char diff, pad; - - LTC_ARGCHK(data != NULL); - LTC_ARGCHK(padded_length != NULL); - - l = length; - if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) { - return err; - } - - type = mode & LTC_PAD_MASK; - - if (*padded_length < l) { -#ifdef LTC_RNG_GET_BYTES - if (type != LTC_PAD_ISO_10126) { - *padded_length = l; - } else { - *padded_length = length + 256; - } -#else - *padded_length = l; -#endif - return CRYPT_BUFFER_OVERFLOW; - } - - if (l - length > 255) return CRYPT_INVALID_ARG; - diff = (unsigned char)(l - length); - - switch (type) { - case LTC_PAD_PKCS7: - XMEMSET(&data[length], diff, diff); - break; -#ifdef LTC_RNG_GET_BYTES - case LTC_PAD_ISO_10126: - if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) { - return CRYPT_ERROR_READPRNG; - } - data[l-1] = diff; - break; -#endif - case LTC_PAD_ANSI_X923: - XMEMSET(&data[length], 0, diff-1); - data[l-1] = diff; - break; - case LTC_PAD_SSH: - pad = 0x1; - for (n = length; n < l; ++n) { - data[n] = pad++; - } - break; - case LTC_PAD_ONE_AND_ZERO: - XMEMSET(&data[length + 1], 0, diff); - data[length] = 0x80; - break; - case LTC_PAD_ZERO: - case LTC_PAD_ZERO_ALWAYS: - XMEMSET(&data[length], 0, diff); - break; - default: - return CRYPT_INVALID_ARG; - } - *padded_length = l; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/password_free.c b/Sources/DataLiteC/libtomcrypt/misc/password_free.c deleted file mode 100644 index e88b700..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/password_free.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file password_free.c - Free the password inside a `struct password`, Steffen Jaeckel -*/ - -/** - Free a password - @param pw The password to be free'd - @param ctx The password context -*/ -void password_free(struct password *pw, const struct password_ctx *ctx) -{ - if (!ctx || !pw || !pw->pw) - return; - - zeromem(pw->pw, pw->l); - if (ctx->free) { - ctx->free(pw->pw); - } else { - XFREE(pw->pw); - } - pw->pw = NULL; - pw->l = 0; -} diff --git a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes.c b/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes.c deleted file mode 100644 index 1b8fd21..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes.c +++ /dev/null @@ -1,79 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_PBES - -/** - Decrypt Data encrypted via either PBES1 or PBES2 - - @param arg The according PBES parameters - @param dec_data [out] The decrypted data - @param dec_size [in/out] The length of the encrypted resp. decrypted data - @return CRYPT_OK on success -*/ -int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size) -{ - int err, hid, cid; - unsigned char k[32], *iv; - unsigned long klen, keylen, dlen; - long diff; - symmetric_CBC cbc; - - LTC_ARGCHK(arg != NULL); - LTC_ARGCHK(arg->type.kdf != NULL); - LTC_ARGCHK(dec_data != NULL); - LTC_ARGCHK(dec_size != NULL); - - hid = find_hash(arg->type.h); - if (hid == -1) return CRYPT_INVALID_HASH; - cid = find_cipher(arg->type.c); - if (cid == -1) return CRYPT_INVALID_CIPHER; - - klen = arg->type.keylen; - - /* RC2 special case */ - if (arg->key_bits != 0) { - /* We can't handle odd lengths of Key Bits */ - if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE; - /* Internally we use bytes, not bits */ - klen = arg->key_bits / 8; - } - keylen = klen; - - if (arg->iv != NULL) { - iv = arg->iv->data; - } else { - iv = k + klen; - klen += arg->type.blocklen; - } - - if (klen > sizeof(k)) return CRYPT_INVALID_ARG; - - if ((err = arg->type.kdf(&arg->pw, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR; - if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR; - if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR; - if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR; - dlen = arg->enc_data->size; - if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR; - diff = (long)arg->enc_data->size - (long)dlen; - if ((diff <= 0) || (diff > cipher_descriptor[cid].block_length)) { - err = CRYPT_PK_INVALID_PADDING; - goto LBL_ERROR; - } - *dec_size = dlen; - return CRYPT_OK; - -LBL_ERROR: - zeromem(k, sizeof(k)); - zeromem(dec_data, *dec_size); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes1.c b/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes1.c deleted file mode 100644 index 86daa47..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes1.c +++ /dev/null @@ -1,112 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PBES - -static int s_pkcs_5_alg1_wrap(const struct password *pwd, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - LTC_UNUSED_PARAM(salt_len); - return pkcs_5_alg1(pwd->pw, pwd->l, salt, iteration_count, hash_idx, out, outlen); -} - -static int s_pkcs_12_wrap(const struct password *pwd, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - int err; - /* convert password to unicode/utf16-be */ - unsigned long pwlen = pwd->l * 2; - unsigned char* pw; - if (*outlen < 32) return CRYPT_INVALID_ARG; - pw = XMALLOC(pwlen + 2); - if (pw == NULL) return CRYPT_MEM; - if ((err = pkcs12_utf8_to_utf16(pwd->pw, pwd->l, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR; - pw[pwlen++] = 0; - pw[pwlen++] = 0; - /* derive KEY */ - if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR; - /* derive IV */ - if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR; - - *outlen = 32; -LBL_ERROR: - zeromem(pw, pwlen); - XFREE(pw); - return err; -} - -static const pbes_properties s_pbes1_types[] = { - { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 }, - { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 }, - { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 }, - { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 }, - { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 }, - { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 }, - { s_pkcs_12_wrap, "sha1", "3des", 24, 8 }, -}; - -static const oid_to_pbes s_pbes1_list[] = { - { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */ - { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */ - { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */ - { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */ - { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */ - { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */ - { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */ - { 0 }, -}; - -static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res) -{ - unsigned int i; - for (i = 0; s_pbes1_list[i].data != NULL; ++i) { - if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) { - if (res != NULL) *res = *s_pbes1_list[i].data; - return CRYPT_OK; - } - } - return CRYPT_INVALID_ARG; -} - -/** - Extract PBES1 parameters - - @param s The start of the sequence with potential PBES1 parameters - @param res Pointer to where the extracted parameters should be stored - @return CRYPT_OK on success -*/ -int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res) -{ - int err; - - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(res != NULL); - - if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err; - - if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) || - !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) { - return CRYPT_INVALID_PACKET; - } - /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC: - * 0:d=0 hl=4 l= 329 cons: SEQUENCE - * 4:d=1 hl=2 l= 27 cons: SEQUENCE - * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s) - * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam) - * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt) - * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations) - * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) - */ - res->salt = s->next->child; - res->iterations = ltc_mp_get_int(s->next->child->next->data); - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes2.c b/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes2.c deleted file mode 100644 index 75d17d3..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pbes/pbes2.c +++ /dev/null @@ -1,201 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PBES - -static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13"; -static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12"; - -typedef struct { - const char *oid; - const char *id; -} oid_id_st; - -static const oid_id_st s_hmac_oid_names[] = { - { "1.2.840.113549.2.7", "sha1" }, - { "1.2.840.113549.2.8", "sha224" }, - { "1.2.840.113549.2.9", "sha256" }, - { "1.2.840.113549.2.10", "sha384" }, - { "1.2.840.113549.2.11", "sha512" }, - { "1.2.840.113549.2.12", "sha512-224" }, - { "1.2.840.113549.2.13", "sha512-256" }, -}; - -static int s_pkcs_5_alg2_wrap(const struct password *pwd, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - return pkcs_5_alg2(pwd->pw, pwd->l, salt, salt_len, iteration_count, hash_idx, out, outlen); -} - -static const pbes_properties s_pbes2_default_types[] = { - { s_pkcs_5_alg2_wrap, "sha1", "des", 8, 0 }, - { s_pkcs_5_alg2_wrap, "sha1", "rc2", 4, 0 }, - { s_pkcs_5_alg2_wrap, "sha1", "3des", 24, 0 }, - { s_pkcs_5_alg2_wrap, "sha1", "aes", 16, 0 }, - { s_pkcs_5_alg2_wrap, "sha1", "aes", 24, 0 }, - { s_pkcs_5_alg2_wrap, "sha1", "aes", 32, 0 }, -}; - -static const oid_to_pbes s_pbes2_list[] = { - { &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */ - { &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */ - { &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */ - { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */ - { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */ - { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */ -}; - -static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res) -{ - unsigned int i; - for (i = 0; i < LTC_ARRAY_SIZE(s_pbes2_list); ++i) { - if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) { - *res = *s_pbes2_list[i].data; - break; - } - } - if (res->c == NULL) return CRYPT_INVALID_CIPHER; - if (hmac_oid != NULL) { - for (i = 0; i < LTC_ARRAY_SIZE(s_hmac_oid_names); ++i) { - if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) { - res->h = s_hmac_oid_names[i].id; - return CRYPT_OK; - } - } - return CRYPT_INVALID_HASH; - } - return CRYPT_OK; -} - - -/** - Extract PBES2 parameters - - @param s The start of the sequence with potential PBES2 parameters - @param res Pointer to where the extracted parameters should be stored - @return CRYPT_OK on success -*/ -int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res) -{ - unsigned long klen; - ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac; - int err; - - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(res != NULL); - - if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err; - - if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) || - !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) { - return CRYPT_INVALID_PACKET; - } - /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc: - * 0:d=0 hl=4 l= 380 cons: SEQUENCE - * 4:d=1 hl=2 l= 78 cons: SEQUENCE - * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s) - * 17:d=2 hl=2 l= 65 cons: SEQUENCE - * 19:d=3 hl=2 l= 41 cons: SEQUENCE - * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf) - * 32:d=4 hl=2 l= 28 cons: SEQUENCE - * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt) - * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter) - * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing) - * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac) - * 60:d=6 hl=2 l= 0 prim: NULL - * 62:d=3 hl=2 l= 20 cons: SEQUENCE - * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc) - * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A - * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) - */ - lkdf = s->next->child->child; - lenc = s->next->child->next->child; - - if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err; - - if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) || - !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) { - return CRYPT_INVALID_PACKET; - } - - liter = lkdf->next->child->next; - loptseq = liter->next; - res->salt = lkdf->next->child; - res->iterations = ltc_mp_get_int(liter->data); - - /* There's an optional INTEGER keyLength after the iterations, skip that if it's there. - * c.f. RFC 2898 A.2 PBKDF2 */ - if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) { - loptseq = loptseq->next; - } - - /* this sequence is optional */ - lhmac = NULL; - if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) && - LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) { - lhmac = loptseq->child; - } - if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err; - - if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) { - /* 'NON-RC2'-CBC */ - res->iv = lenc->next; - } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) { - /* RC2-CBC is a bit special ... - * - * RC2-CBC-Parameter ::= SEQUENCE { - * rc2ParameterVersion INTEGER OPTIONAL, - * iv OCTET STRING (SIZE(8)) } - */ - if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) && - LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) { - klen = ltc_mp_get_int(lenc->next->child->data); - res->iv = lenc->next->child->next; - /* - * Effective Key Bits Encoding - * 40 160 - * 64 120 - * 128 58 - * b >= 256 b - */ - switch (klen) { - case 160: - res->key_bits = 40; - break; - case 120: - res->key_bits = 64; - break; - case 58: - res->key_bits = 128; - break; - default: - /* We don't handle undefined Key Bits */ - if (klen < 256) return CRYPT_INVALID_KEYSIZE; - - res->key_bits = klen; - break; - } - } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) { - res->iv = lenc->next->child; - /* - * If the rc2ParameterVersion field is omitted, the "effective key bits" - * defaults to 32. - */ - res->key_bits = 32; - } else { - return CRYPT_INVALID_PACKET; - } - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/pem/pem.c b/Sources/DataLiteC/libtomcrypt/misc/pem/pem.c deleted file mode 100644 index ca6e350..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pem/pem.c +++ /dev/null @@ -1,344 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pem.c - Const declarations for PEM, Steffen Jaeckel -*/ - -#ifdef LTC_PEM - -const struct pem_header_id pem_std_headers[] = { - { - /* PKCS#8 encrypted */ - SET_CSTR(.start, "-----BEGIN ENCRYPTED PRIVATE KEY-----"), - SET_CSTR(.end, "-----END ENCRYPTED PRIVATE KEY-----"), - .has_more_headers = no, - .flags = pf_encrypted_pkcs8, - }, - { - /* PKCS#8 plain */ - SET_CSTR(.start, "-----BEGIN PRIVATE KEY-----"), - SET_CSTR(.end, "-----END PRIVATE KEY-----"), - .has_more_headers = no, - .flags = pf_pkcs8, - }, - { - /* X.509 Certificates */ - SET_CSTR(.start, "-----BEGIN CERTIFICATE-----"), - SET_CSTR(.end, "-----END CERTIFICATE-----"), - .has_more_headers = no, - .flags = pf_x509, - }, - { - /* Regular (plain) public keys */ - SET_CSTR(.start, "-----BEGIN PUBLIC KEY-----"), - SET_CSTR(.end, "-----END PUBLIC KEY-----"), - .has_more_headers = no, - .flags = pf_public, - }, - { - SET_CSTR(.start, "-----BEGIN RSA PUBLIC KEY-----"), - SET_CSTR(.end, "-----END RSA PUBLIC KEY-----"), - .has_more_headers = no, - .pka = LTC_PKA_RSA, - .flags = pf_public, - }, - /* Regular plain or encrypted private keys */ - { - SET_CSTR(.start, "-----BEGIN RSA PRIVATE KEY-----"), - SET_CSTR(.end, "-----END RSA PRIVATE KEY-----"), - .has_more_headers = maybe, - .pka = LTC_PKA_RSA, - }, - { - SET_CSTR(.start, "-----BEGIN EC PRIVATE KEY-----"), - SET_CSTR(.end, "-----END EC PRIVATE KEY-----"), - .has_more_headers = maybe, - .pka = LTC_PKA_EC, - }, - { - SET_CSTR(.start, "-----BEGIN DSA PRIVATE KEY-----"), - SET_CSTR(.end, "-----END DSA PRIVATE KEY-----"), - .has_more_headers = maybe, - .pka = LTC_PKA_DSA, - }, -}; -const unsigned long pem_std_headers_num = LTC_ARRAY_SIZE(pem_std_headers); - -/* Encrypted PEM files */ -const struct str pem_proc_type_encrypted = { SET_CSTR(, "Proc-Type: 4,ENCRYPTED") }; -#if defined(LTC_SSH) -const struct str pem_ssh_comment = { SET_CSTR(, "Comment: ") }; -#endif -const struct str pem_dek_info_start = { SET_CSTR(, "DEK-Info: ") }; -const struct blockcipher_info pem_dek_infos[] = - { - { .name = "AES-128-CBC,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "AES-192-CBC,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc, }, - { .name = "AES-256-CBC,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc, }, - { .name = "AES-128-CFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "AES-192-CFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb, }, - { .name = "AES-256-CFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb, }, - { .name = "AES-128-CFB1,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb1, }, - { .name = "AES-192-CFB1,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb1, }, - { .name = "AES-256-CFB1,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb1, }, - { .name = "AES-128-CFB8,", .algo = "aes", .keylen = 128 / 8, .mode = cm_cfb8, }, - { .name = "AES-192-CFB8,", .algo = "aes", .keylen = 192 / 8, .mode = cm_cfb8, }, - { .name = "AES-256-CFB8,", .algo = "aes", .keylen = 256 / 8, .mode = cm_cfb8, }, - { .name = "AES-128-CTR,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr, }, - { .name = "AES-192-CTR,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr, }, - { .name = "AES-256-CTR,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr, }, - { .name = "AES-128-OFB,", .algo = "aes", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "AES-192-OFB,", .algo = "aes", .keylen = 192 / 8, .mode = cm_ofb, }, - { .name = "AES-256-OFB,", .algo = "aes", .keylen = 256 / 8, .mode = cm_ofb, }, - { .name = "BF-CBC,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "BF-CFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "BF-OFB,", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "CAMELLIA-128-CBC,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "CAMELLIA-192-CBC,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cbc, }, - { .name = "CAMELLIA-256-CBC,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cbc, }, - { .name = "CAMELLIA-128-CFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "CAMELLIA-192-CFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb, }, - { .name = "CAMELLIA-256-CFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb, }, - { .name = "CAMELLIA-128-CFB1,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb1, }, - { .name = "CAMELLIA-192-CFB1,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb1, }, - { .name = "CAMELLIA-256-CFB1,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb1, }, - { .name = "CAMELLIA-128-CFB8,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_cfb8, }, - { .name = "CAMELLIA-192-CFB8,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_cfb8, }, - { .name = "CAMELLIA-256-CFB8,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_cfb8, }, - { .name = "CAMELLIA-128-CTR,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ctr, }, - { .name = "CAMELLIA-192-CTR,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ctr, }, - { .name = "CAMELLIA-256-CTR,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ctr, }, - { .name = "CAMELLIA-128-OFB,", .algo = "camellia", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "CAMELLIA-192-OFB,", .algo = "camellia", .keylen = 192 / 8, .mode = cm_ofb, }, - { .name = "CAMELLIA-256-OFB,", .algo = "camellia", .keylen = 256 / 8, .mode = cm_ofb, }, - { .name = "CAST5-CBC,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "CAST5-CFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "CAST5-OFB,", .algo = "cast5", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "ChaCha20,", .algo = "chacha20", .keylen = 256 / 8, .mode = cm_stream, }, - { .name = "DES-EDE-CBC,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "DES-EDE-CFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "DES-EDE-OFB,", .algo = "3des", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "DES-EDE3-CBC,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc, }, - { .name = "DES-EDE3-CFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb, }, - { .name = "DES-EDE3-CFB1,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb1, }, - { .name = "DES-EDE3-CFB8,", .algo = "3des", .keylen = 192 / 8, .mode = cm_cfb8, }, - { .name = "DES-EDE3-OFB,", .algo = "3des", .keylen = 192 / 8, .mode = cm_ofb, }, - { .name = "DES-CBC,", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc, }, - { .name = "DES-CFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb, }, - { .name = "DES-CFB1,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb1, }, - { .name = "DES-CFB8,", .algo = "des", .keylen = 64 / 8, .mode = cm_cfb8, }, - { .name = "DES-OFB,", .algo = "des", .keylen = 64 / 8, .mode = cm_ofb, }, - { .name = "DESX-CBC,", .algo = "desx", .keylen = 192 / 8, .mode = cm_cbc, }, - { .name = "IDEA-CBC,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "IDEA-CFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "IDEA-OFB,", .algo = "idea", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "RC5-CBC,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "RC5-CFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "RC5-OFB,", .algo = "rc5", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "RC2-40-CBC,", .algo = "rc2", .keylen = 40 / 8, .mode = cm_cbc, }, - { .name = "RC2-64-CBC,", .algo = "rc2", .keylen = 64 / 8, .mode = cm_cbc, }, - { .name = "RC2-CBC,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "RC2-CFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "RC2-OFB,", .algo = "rc2", .keylen = 128 / 8, .mode = cm_ofb, }, - { .name = "SEED-CBC,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cbc, }, - { .name = "SEED-CFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_cfb, }, - { .name = "SEED-OFB,", .algo = "seed", .keylen = 128 / 8, .mode = cm_ofb, }, - }; -const unsigned long pem_dek_infos_num = LTC_ARRAY_SIZE(pem_dek_infos); - -int pem_decrypt(unsigned char *data, unsigned long *datalen, - unsigned char *key, unsigned long keylen, - unsigned char *iv, unsigned long ivlen, - unsigned char *tag, unsigned long taglen, - const struct blockcipher_info *info, - enum padding_type padding) -{ - int err, cipher = -1; - struct { - union { -#ifdef LTC_CBC_MODE - symmetric_CBC cbc; -#endif -#ifdef LTC_CFB_MODE - symmetric_CFB cfb; -#endif -#ifdef LTC_CTR_MODE - symmetric_CTR ctr; -#endif -#ifdef LTC_OFB_MODE - symmetric_OFB ofb; -#endif - } ctx; - } s; - enum cipher_mode mode = info->mode & cm_modes; - - if (mode != cm_stream) { - cipher = find_cipher(info->algo); - if (cipher == -1) { - return CRYPT_INVALID_CIPHER; - } - } - - switch (info->mode) { - case cm_cbc: -#ifdef LTC_CBC_MODE - LTC_ARGCHK(ivlen == (unsigned long)cipher_descriptor[cipher].block_length); - - if ((err = cbc_start(cipher, iv, key, keylen, 0, &s.ctx.cbc)) != CRYPT_OK) { - goto error_out; - } - if ((err = cbc_decrypt(data, data, *datalen, &s.ctx.cbc)) != CRYPT_OK) { - goto error_out; - } - if ((err = cbc_done(&s.ctx.cbc)) != CRYPT_OK) { - goto error_out; - } - - if ((err = padding_depad(data, datalen, padding | s.ctx.cbc.ecb.blocklen)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_cfb: - case cm_cfb1: - case cm_cfb8: -#ifdef LTC_CFB_MODE - if (info->mode == cm_cfb) { - if ((err = cfb_start(cipher, iv, key, keylen, 0, &s.ctx.cfb)) != CRYPT_OK) { - goto error_out; - } - } else { - if ((err = cfb_start_ex(cipher, iv, key, keylen, 0, info->mode == cm_cfb1 ? 1 : 8, &s.ctx.cfb)) != CRYPT_OK) { - goto error_out; - } - } - if ((err = cfb_decrypt(data, data, *datalen, &s.ctx.cfb)) != CRYPT_OK) { - goto error_out; - } - if ((err = cfb_done(&s.ctx.cfb)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_ctr: -#ifdef LTC_CTR_MODE - if ((err = ctr_start(cipher, iv, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &s.ctx.ctr)) != CRYPT_OK) { - goto error_out; - } - if ((err = ctr_decrypt(data, data, *datalen, &s.ctx.ctr)) != CRYPT_OK) { - goto error_out; - } - if ((err = ctr_done(&s.ctx.ctr)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_ofb: -#ifdef LTC_OFB_MODE - if ((err = ofb_start(cipher, iv, key, keylen, 0, &s.ctx.ofb)) != CRYPT_OK) { - goto error_out; - } - if ((err = ofb_decrypt(data, data, *datalen, &s.ctx.ofb)) != CRYPT_OK) { - goto error_out; - } - if ((err = ofb_done(&s.ctx.ofb)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_gcm: -#ifdef LTC_GCM_MODE - if ((err = gcm_memory(cipher, - key, keylen, - iv, ivlen, - NULL, 0, - data, *datalen, data, - tag, &taglen, - GCM_DECRYPT)) != CRYPT_OK) { - goto error_out; - } -#else - LTC_UNUSED_PARAM(tag); - LTC_UNUSED_PARAM(taglen); - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_stream: -#ifdef LTC_CHACHA - LTC_ARGCHK(ivlen == 16); - - if ((err = chacha_memory(key, keylen, 20, - iv, ivlen, 0, - data, *datalen, data)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - case cm_stream_openssh: -#ifdef LTC_CHACHA20POLY1305_MODE - if ((err = chacha20poly1305_memory(key, 32, - iv, ivlen, - NULL, 0, - data, *datalen, data, - tag, &taglen, - CHACHA20POLY1305_DECRYPT | CHACHA20POLY1305_OPENSSH_COMPAT)) != CRYPT_OK) { - goto error_out; - } -#else - return CRYPT_INVALID_CIPHER; -#endif - break; - default: - err = CRYPT_INVALID_ARG; - break; - } - -error_out: - return err; -} - -#ifndef LTC_NO_FILE -int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - int err = pem_decode_pkcs_filehandle(f, k, pw_ctx); - if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM) - return err; -#if defined(LTC_SSH) - rewind(f); - err = pem_decode_openssh_filehandle(f, k, pw_ctx); -#endif - return err; -} -#endif - -int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - int err = pem_decode_pkcs(buf, len, k, pw_ctx); - if (err == CRYPT_OK || err != CRYPT_UNKNOWN_PEM) - return err; -#if defined(LTC_SSH) - err = pem_decode_openssh(buf, len, k, pw_ctx); -#endif - return err; -} - -#endif /* LTC_PEM */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_pkcs.c b/Sources/DataLiteC/libtomcrypt/misc/pem/pem_pkcs.c deleted file mode 100644 index 682d819..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_pkcs.c +++ /dev/null @@ -1,298 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pem_decode.c - Decode a PEM file, Steffen Jaeckel -*/ - -#ifdef LTC_PEM - -extern const struct pem_header_id pem_std_headers[]; -extern const unsigned long pem_std_headers_num; - -static int s_decrypt_pem(unsigned char *asn1_cert, unsigned long *asn1_len, const struct pem_headers *hdr) -{ - unsigned char iv[MAXBLOCKSIZE], key[MAXBLOCKSIZE]; - unsigned long ivlen, klen; - int err; - - if (hdr->info.keylen > sizeof(key)) { - return CRYPT_BUFFER_OVERFLOW; - } - if (!hdr->pw->pw) { - return CRYPT_INVALID_ARG; - } - - ivlen = sizeof(iv); - if ((err = base16_decode(hdr->info.iv, XSTRLEN(hdr->info.iv), iv, &ivlen)) != CRYPT_OK) { - return err; - } - klen = hdr->info.keylen; - if ((err = pkcs_5_alg1_openssl(hdr->pw->pw, hdr->pw->l, iv, 1, find_hash("md5"), key, &klen))) { - return err; - } - - err = pem_decrypt(asn1_cert, asn1_len, key, klen, iv, ivlen, NULL, 0, &hdr->info, LTC_PAD_PKCS7); - - zeromem(key, sizeof(key)); - zeromem(iv, sizeof(iv)); - return err; -} - -static int s_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka) -{ - der_flexi_check flexi_should[4]; - ltc_asn1_list *seqid, *id; - enum ltc_oid_id oid_id; - int err; - unsigned long n = 0; - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) { - return err; - } - n = 0; - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OBJECT_IDENTIFIER, &id); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - err = der_flexi_sequence_cmp(seqid, flexi_should); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - return err; - } - if ((err = pk_get_oid_from_asn1(id, &oid_id)) != CRYPT_OK) { - return err; - } - return pk_get_pka_id(oid_id, pka); -} - -typedef int (*import_fn)(const unsigned char *, unsigned long, void*); - -static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { -#ifdef LTC_MRSA - [LTC_PKA_RSA] = (import_fn)rsa_import_x509, -#endif -#ifdef LTC_MECC - [LTC_PKA_EC] = (import_fn)ecc_import_x509, -#endif -#ifdef LTC_CURVE25519 - [LTC_PKA_X25519] = (import_fn)x25519_import_x509, - [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509, -#endif -}; - -static int s_import_x509(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k) -{ - enum ltc_pka_id pka = LTC_PKA_UNDEF; - ltc_asn1_list *d, *spki; - int err; - if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) { - return err; - } - err = s_get_pka(spki, &pka); - der_free_sequence_flexi(d); - if (err != CRYPT_OK) { - return err; - } - if (pka < 0 - || pka > LTC_ARRAY_SIZE(s_import_x509_fns) - || s_import_x509_fns[pka] == NULL) { - return CRYPT_PK_INVALID_TYPE; - } - if ((err = s_import_x509_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) { - k->id = pka; - } - return err; -} - -static int s_import_pkcs8(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - int err; - enum ltc_oid_id pka; - ltc_asn1_list *alg_id, *priv_key; - ltc_asn1_list *p8_asn1 = NULL; - if ((err = pkcs8_decode_flexi(asn1_cert, asn1_len, pw_ctx, &p8_asn1)) != CRYPT_OK) { - goto cleanup; - } - if ((err = pkcs8_get_children(p8_asn1, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto cleanup; - } - switch (pka) { -#ifdef LTC_MDH - case LTC_OID_DH: - err = dh_import_pkcs8_asn1(alg_id, priv_key, &k->u.dh); - k->id = LTC_PKA_DH; - break; -#endif -#ifdef LTC_MDSA - case LTC_OID_DSA: - err = dsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.dsa); - k->id = LTC_PKA_DSA; - break; -#endif -#ifdef LTC_MRSA - case LTC_OID_RSA: - err = rsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.rsa); - k->id = LTC_PKA_RSA; - break; -#endif -#ifdef LTC_MECC - case LTC_OID_EC: - err = ecc_import_pkcs8_asn1(alg_id, priv_key, &k->u.ecc); - k->id = LTC_PKA_EC; - break; -#endif -#ifdef LTC_CURVE25519 - case LTC_OID_X25519: - err = x25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.x25519); - k->id = LTC_PKA_X25519; - break; - case LTC_OID_ED25519: - err = ed25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.ed25519); - k->id = LTC_PKA_ED25519; - break; -#endif - default: - err = CRYPT_PK_INVALID_TYPE; - } - -cleanup: - if (p8_asn1) { - der_sequence_free(p8_asn1); - } - return err; -} - -static int s_extract_pka(unsigned char *asn1_cert, unsigned long asn1_len, enum ltc_pka_id *pka) -{ - ltc_asn1_list *pub; - int err = CRYPT_ERROR; - if ((err = der_decode_sequence_flexi(asn1_cert, &asn1_len, &pub)) != CRYPT_OK) { - return err; - } - err = s_get_pka(pub, pka); - der_sequence_free(pub); - return err; -} - -static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = { -#ifdef LTC_MRSA - [LTC_PKA_RSA] = (import_fn)rsa_import, -#endif -#ifdef LTC_MDSA - [LTC_PKA_DSA] = (import_fn)dsa_import, -#endif -#ifdef LTC_MECC - [LTC_PKA_EC] = (import_fn)ecc_import_openssl, -#endif -#ifdef LTC_CURVE25519 - [LTC_PKA_X25519] = (import_fn)x25519_import, - [LTC_PKA_ED25519] = (import_fn)ed25519_import, -#endif -}; - -static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - unsigned char *asn1_cert = NULL; - unsigned long w, asn1_len, n; - int err = CRYPT_ERROR; - struct pem_headers hdr = { 0 }; - struct password pw = { 0 }; - enum ltc_pka_id pka; - XMEMSET(k, 0, sizeof(*k)); - w = LTC_PEM_READ_BUFSIZE * 2; -retry: - asn1_cert = XREALLOC(asn1_cert, w); - for (n = 0; n < pem_std_headers_num; ++n) { - hdr.id = &pem_std_headers[n]; - err = pem_read(asn1_cert, &w, &hdr, g); - if (err == CRYPT_BUFFER_OVERFLOW) { - goto retry; - } else if (err == CRYPT_OK) { - break; - } else if (err != CRYPT_UNKNOWN_PEM) { - goto cleanup; - } - hdr.id = NULL; - } - /* id not found */ - if (hdr.id == NULL) - goto cleanup; - asn1_len = w; - if (hdr.id->flags & pf_pkcs8) { - err = s_import_pkcs8(asn1_cert, asn1_len, k, pw_ctx); - goto cleanup; - } else if (hdr.id->flags == pf_x509) { - err = s_import_x509(asn1_cert, asn1_len, k); - goto cleanup; - } else if ((hdr.id->flags & pf_public) && hdr.id->pka == LTC_PKA_UNDEF) { - if ((err = s_extract_pka(asn1_cert, asn1_len, &pka)) != CRYPT_OK) { - goto cleanup; - } - } else if (hdr.encrypted) { - if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) { - err = CRYPT_PW_CTX_MISSING; - goto cleanup; - } - - hdr.pw = &pw; - if (pw_ctx->callback(&hdr.pw->pw, &hdr.pw->l, pw_ctx->userdata)) { - err = CRYPT_ERROR; - goto cleanup; - } - - if ((err = s_decrypt_pem(asn1_cert, &asn1_len, &hdr)) != CRYPT_OK) { - goto cleanup; - } - pka = hdr.id->pka; - } else { - pka = hdr.id->pka; - } - - if (pka < 0 - || pka > LTC_ARRAY_SIZE(s_import_openssl_fns) - || s_import_openssl_fns[pka] == NULL) { - err = CRYPT_PK_INVALID_TYPE; - goto cleanup; - } - if ((err = s_import_openssl_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) { - k->id = pka; - } - -cleanup: - password_free(hdr.pw, pw_ctx); - XFREE(asn1_cert); - return err; -} - -#ifndef LTC_NO_FILE -int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - LTC_ARGCHK(f != NULL); - LTC_ARGCHK(k != NULL); - { - struct get_char g = { .get = pem_get_char_from_file, .data.f = f }; - return s_decode(&g, k, pw_ctx); - } -} -#endif /* LTC_NO_FILE */ - -int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - LTC_ARGCHK(buf != NULL); - LTC_ARGCHK(len != 0); - LTC_ARGCHK(k != NULL); - { - struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) }; - return s_decode(&g, k, pw_ctx); - } -} - -#endif /* LTC_PEM */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_read.c b/Sources/DataLiteC/libtomcrypt/misc/pem/pem_read.c deleted file mode 100644 index abefff9..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_read.c +++ /dev/null @@ -1,267 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pem_read.c - Read and interpret a PEM file, Steffen Jaeckel -*/ - -#ifdef LTC_PEM - -extern const struct str pem_proc_type_encrypted; -#ifdef LTC_SSH -extern const struct str pem_ssh_comment; -#endif -extern const struct str pem_dek_info_start; -extern const struct blockcipher_info pem_dek_infos[]; -extern const unsigned long pem_dek_infos_num; - -#ifndef LTC_NO_FILE -int pem_get_char_from_file(struct get_char *g) -{ - return getc(g->data.f); -} -#endif /* LTC_NO_FILE */ - -int pem_get_char_from_buf(struct get_char *g) -{ - int ret; - if (g->data.buf.work == g->data.buf.end) { - return -1; - } - ret = *g->data.buf.work; - g->data.buf.work++; - return ret; -} - -static void s_unget_line(char *buf, unsigned long buflen, struct get_char *g) -{ - if (buflen > sizeof(g->unget_buf_)) - return; - g->unget_buf.p = g->unget_buf_; - COPY_STR(g->unget_buf, buf, buflen); -} - -static void s_tts(char *buf, unsigned long *buflen) -{ - while(1) { - unsigned long blen = *buflen; - if (blen < 2) - return; - blen--; - switch (buf[blen]) { - case ' ': - case '\t': - buf[blen] = '\0'; - *buflen = blen; - break; - default: - return; - } - } -} - -static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g, int search_for_start) -{ - unsigned long blen = 0, wr = 0; - int c_; - if (g->unget_buf.p) { - if (*buflen < g->unget_buf.len) { - return NULL; - } - XMEMCPY(buf, g->unget_buf.p, g->unget_buf.len); - *buflen = g->unget_buf.len; - RESET_STR(g->unget_buf); - return buf; - } - if (g->prev_get == -1) { - return NULL; - } - while(blen < *buflen || search_for_start) { - wr = blen < *buflen ? blen : *buflen - 1; - c_ = g->prev_get; - g->prev_get = g->get(g); - if (g->prev_get == '\n') { - buf[wr] = '\0'; - if (c_ == '\r') { - buf[--wr] = '\0'; - } - s_tts(buf, &wr); - *buflen = wr; - return buf; - } - if (g->prev_get == -1 || g->prev_get == '\0') { - buf[wr] = '\0'; - s_tts(buf, &wr); - *buflen = wr; - return buf; - } - buf[wr] = g->prev_get; - blen++; - } - return NULL; -} - -LTC_INLINE static char* s_get_first_line(char *buf, unsigned long *buflen, struct get_char *g) -{ - return s_get_line_i(buf, buflen, g, 1); -} - -LTC_INLINE static char* s_get_line(char *buf, unsigned long *buflen, struct get_char *g) -{ - return s_get_line_i(buf, buflen, g, 0); -} - -static LTC_INLINE int s_fits_buf(void *dest, unsigned long to_write, void *end) -{ - unsigned char *d = dest; - unsigned char *e = end; - unsigned char *w = d + to_write; - if (w < d || w > e) - return 0; - return 1; -} - -static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g) -{ - char buf[LTC_PEM_DECODE_BUFSZ], *alg_start; - unsigned long slen, tmplen, n; - int has_more_headers = hdr->id->has_more_headers == no ? 0 : 3; - - /* Make sure the PEM has the appropriate extension headers if required. - * - * ``` - * Proc-Type: 4,ENCRYPTED[\r]\n - * DEK-Info: ,[\r]\n - * [\r]\n - * ``` - */ - while (has_more_headers) { - slen = sizeof(buf); - if (!s_get_line(buf, &slen, g) || (has_more_headers > 1 && slen == 0)) { - return CRYPT_INVALID_PACKET; - } - switch (has_more_headers) { - case 3: - if (XMEMCMP(buf, pem_proc_type_encrypted.p, pem_proc_type_encrypted.len)) { -#ifdef LTC_SSH - if (XMEMCMP(buf, pem_ssh_comment.p, pem_ssh_comment.len)) -#endif - s_unget_line(buf, slen, g); - if (hdr->id->has_more_headers == maybe) - return CRYPT_OK; - else - return CRYPT_INVALID_PACKET; - } - hdr->encrypted = 1; - break; - case 2: - hdr->info.algo = NULL; - if (XMEMCMP(buf, pem_dek_info_start.p, pem_dek_info_start.len)) - return CRYPT_INVALID_PACKET; - alg_start = &buf[pem_dek_info_start.len]; - for (n = 0; n < pem_dek_infos_num; ++n) { - unsigned long namelen = XSTRLEN(pem_dek_infos[n].name); - if (slen >= namelen + pem_dek_info_start.len && !XMEMCMP(alg_start, pem_dek_infos[n].name, namelen)) { - char *iv = alg_start + namelen; - hdr->info = pem_dek_infos[n]; - tmplen = XSTRLEN(iv); - if (tmplen > sizeof(hdr->info.iv)) - return CRYPT_INVALID_KEYSIZE; - XMEMCPY(hdr->info.iv, iv, tmplen); - break; - } - } - if (hdr->info.algo == NULL) { - return CRYPT_INVALID_CIPHER; - } - break; - case 1: - /* Make sure that there's an empty line in between */ - if (buf[0] != '\0') - return CRYPT_INVALID_PACKET; - break; - default: - return CRYPT_INVALID_CIPHER; - } - has_more_headers--; - } - return CRYPT_OK; -} - -int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, struct get_char *g) -{ - char buf[LTC_PEM_DECODE_BUFSZ]; - char *wpem = asn1_cert; - char *end = wpem + *asn1_len; - const char pem_start[] = "----"; - unsigned long slen, linelen; - int err, hdr_ok = 0; - int would_overflow = 0; - unsigned char empty_lines = 0; - - g->prev_get = 0; - do { - linelen = sizeof(buf); - if (s_get_first_line(buf, &linelen, g) == NULL) { - if (g->prev_get == -1) - return CRYPT_NOP; - else - return CRYPT_INVALID_PACKET; - } - if (linelen < sizeof(pem_start) - 1) - continue; - } while(XMEMCMP(buf, pem_start, sizeof(pem_start) - 1) != 0); - if (hdr->id->start.len != linelen || XMEMCMP(buf, hdr->id->start.p, hdr->id->start.len)) { - s_unget_line(buf, linelen, g); - return CRYPT_UNKNOWN_PEM; - } - - hdr->encrypted = hdr->id->flags & pf_encrypted; - if ((err = s_pem_decode_headers(hdr, g)) != CRYPT_OK) - return err; - - /* Read the base64 encoded part of the PEM */ - slen = sizeof(buf); - while (s_get_line(buf, &slen, g)) { - if (slen == hdr->id->end.len && !XMEMCMP(buf, hdr->id->end.p, slen)) { - hdr_ok = 1; - break; - } - if (!slen) { - if (empty_lines) - break; - empty_lines++; - } - if (!would_overflow && s_fits_buf(wpem, slen, end)) { - XMEMCPY(wpem, buf, slen); - } else { - would_overflow = 1; - } - wpem += slen; - slen = sizeof(buf); - } - if (!hdr_ok) - return CRYPT_INVALID_PACKET; - - if (would_overflow || !s_fits_buf(wpem, 1, end)) { - /* NUL termination */ - wpem++; - /* prevent a wrap-around */ - if (wpem < (char*)asn1_cert) - return CRYPT_OVERFLOW; - *asn1_len = wpem - (char*)asn1_cert; - return CRYPT_BUFFER_OVERFLOW; - } - - *asn1_len = wpem - (char*)asn1_cert; - *wpem++ = '\0'; - - if ((err = base64_strict_decode(asn1_cert, *asn1_len, asn1_cert, asn1_len)) != CRYPT_OK) { - return err; - } - return CRYPT_OK; -} - -#endif /* LTC_PEM */ diff --git a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_ssh.c b/Sources/DataLiteC/libtomcrypt/misc/pem/pem_ssh.c deleted file mode 100644 index 18a18d0..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pem/pem_ssh.c +++ /dev/null @@ -1,863 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pem_ssh.c - SSH specific functionality to process PEM files, Steffen Jaeckel - - The basic format of the key is described here: - https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key -*/ - -#if defined(LTC_PEM_SSH) - -/* Table as of - * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-17 - */ -const struct blockcipher_info ssh_ciphers[] = -{ - { .name = "none", .algo = "", .keylen = 0, .mode = cm_none }, - { .name = "aes128-cbc", .algo = "aes", .keylen = 128 / 8, .mode = cm_cbc }, - { .name = "aes128-ctr", .algo = "aes", .keylen = 128 / 8, .mode = cm_ctr }, - { .name = "aes192-cbc", .algo = "aes", .keylen = 192 / 8, .mode = cm_cbc }, - { .name = "aes192-ctr", .algo = "aes", .keylen = 192 / 8, .mode = cm_ctr }, - { .name = "aes256-cbc", .algo = "aes", .keylen = 256 / 8, .mode = cm_cbc }, - { .name = "aes256-ctr", .algo = "aes", .keylen = 256 / 8, .mode = cm_ctr }, - { .name = "aes128-gcm@openssh.com", .algo = "aes", .keylen = 128 / 8, .mode = cm_gcm }, - { .name = "aes256-gcm@openssh.com", .algo = "aes", .keylen = 256 / 8, .mode = cm_gcm }, - { .name = "blowfish128-cbc", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_cbc }, - { .name = "blowfish128-ctr", .algo = "blowfish", .keylen = 128 / 8, .mode = cm_ctr }, - /* The algo name doesn't matter, it's only used in pem-info */ - { .name = "chacha20-poly1305@openssh.com", .algo = "c20p1305", .keylen = 256 / 8, .mode = cm_stream | cm_openssh }, - { .name = "des-cbc", .algo = "des", .keylen = 64 / 8, .mode = cm_cbc }, - { .name = "3des-cbc", .algo = "3des", .keylen = 192 / 8, .mode = cm_cbc }, - { .name = "3des-ctr", .algo = "3des", .keylen = 192 / 8, .mode = cm_ctr }, - { .name = "serpent128-cbc", .algo = "serpent", .keylen = 128 / 8, .mode = cm_cbc }, - { .name = "serpent128-ctr", .algo = "serpent", .keylen = 128 / 8, .mode = cm_ctr }, - { .name = "serpent192-cbc", .algo = "serpent", .keylen = 192 / 8, .mode = cm_cbc }, - { .name = "serpent192-ctr", .algo = "serpent", .keylen = 192 / 8, .mode = cm_ctr }, - { .name = "serpent256-cbc", .algo = "serpent", .keylen = 256 / 8, .mode = cm_cbc }, - { .name = "serpent256-ctr", .algo = "serpent", .keylen = 256 / 8, .mode = cm_ctr }, - { .name = "twofish128-cbc", .algo = "twofish", .keylen = 128 / 8, .mode = cm_cbc }, - { .name = "twofish128-ctr", .algo = "twofish", .keylen = 128 / 8, .mode = cm_ctr }, - { .name = "twofish192-cbc", .algo = "twofish", .keylen = 192 / 8, .mode = cm_cbc }, - { .name = "twofish192-ctr", .algo = "twofish", .keylen = 192 / 8, .mode = cm_ctr }, - { .name = "twofish-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc }, - { .name = "twofish256-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc }, - { .name = "twofish256-ctr", .algo = "twofish", .keylen = 256 / 8, .mode = cm_ctr }, -}; -const unsigned long ssh_ciphers_num = LTC_ARRAY_SIZE(ssh_ciphers); - -struct kdf_options { - const char *name; - const struct blockcipher_info *cipher; - unsigned char salt[64]; - unsigned long saltlen; - ulong32 num_rounds; - struct password pw; -}; - -#ifdef LTC_MECC -static int s_ssh_find_ecc(const char *pka, const ltc_ecc_curve **curve) -{ - int err; - const char* prefix = "ecdsa-sha2-"; - unsigned long prefixlen = XSTRLEN(prefix); - if (strstr(pka, prefix) == NULL) return CRYPT_PK_INVALID_TYPE; - if ((err = ecc_find_curve(pka + prefixlen, curve)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -static int s_ssh_find_init_ecc(const char *pka, ltc_pka_key *key) -{ - int err; - const ltc_ecc_curve *cu; - if ((err = s_ssh_find_ecc(pka, &cu)) != CRYPT_OK) return err; - return ecc_set_curve(cu, &key->u.ecc); -} - -static int s_ssh_decode_ecdsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *pka_key, enum pem_flags type) -{ - int err; - unsigned char groupname[64], buf0[512], buf1[512]; - unsigned long groupnamelen = sizeof(groupname), buf0len = sizeof(buf0), buf1len = sizeof(buf1); - unsigned long remaining, cur_len, keylen; - const unsigned char *p, *key; - - p = in; - cur_len = *inlen; - remaining = *inlen; - - err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_STRING, groupname, &groupnamelen, - LTC_SSHDATA_STRING, buf0, &buf0len, - LTC_SSHDATA_STRING, buf1, &buf1len, - LTC_SSHDATA_EOL, LTC_NULL); - if (err == CRYPT_OK) { - key = buf1; - keylen = buf1len; - } else if (err == CRYPT_BUFFER_OVERFLOW && buf0len != sizeof(buf0) && buf1len == sizeof(buf1)) { - key = buf0; - keylen = buf0len; - } else { - goto cleanup; - } - - remaining -= cur_len; - cur_len = remaining; - - err = ecc_set_key(key, keylen, type == pf_public ? PK_PUBLIC : PK_PRIVATE, &pka_key->u.ecc); - -cleanup: - zeromem(groupname, sizeof(groupname)); - zeromem(buf0, sizeof(buf0)); - zeromem(buf1, sizeof(buf1)); - if (err == CRYPT_OK) { - pka_key->id = LTC_PKA_EC; - *inlen -= remaining; - } - - return err; -} -#endif - -#ifdef LTC_CURVE25519 -static int s_ssh_decode_ed25519(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type) -{ - int err; - unsigned char pubkey[64], privkey[96]; - unsigned long pubkeylen = sizeof(pubkey), privkeylen = sizeof(privkey); - unsigned long remaining, cur_len; - const unsigned char *p; - - p = in; - cur_len = *inlen; - remaining = *inlen; - - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_STRING, pubkey, &pubkeylen, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - - if (type == pf_public) { - if ((err = ed25519_import_raw(pubkey, pubkeylen, PK_PUBLIC, &key->u.ed25519)) != CRYPT_OK) { - goto cleanup; - } - key->id = LTC_PKA_ED25519; - goto cleanup; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_STRING, privkey, &privkeylen, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - if ((err = ed25519_import_raw(privkey, privkeylen, PK_PRIVATE, &key->u.ed25519)) != CRYPT_OK) { - goto cleanup; - } - - key->id = LTC_PKA_ED25519; - -cleanup: - zeromem(pubkey, sizeof(pubkey)); - zeromem(privkey, sizeof(privkey)); - if (err == CRYPT_OK) { - remaining -= cur_len; - *inlen -= remaining; - } - - return err; -} -#endif - -#ifdef LTC_MRSA -static int s_ssh_decode_dsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type) -{ - int err, stat; - unsigned long remaining, cur_len; - const unsigned char *p; - if ((err = dsa_int_init(&key->u.dsa)) != CRYPT_OK) { - return err; - } - - p = in; - cur_len = *inlen; - remaining = *inlen; - - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_MPINT, key->u.dsa.p, - LTC_SSHDATA_MPINT, key->u.dsa.q, - LTC_SSHDATA_MPINT, key->u.dsa.g, - LTC_SSHDATA_MPINT, key->u.dsa.y, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - key->u.dsa.qord = ltc_mp_unsigned_bin_size(key->u.dsa.q); - if ((err = dsa_int_validate_pqg(&key->u.dsa, &stat)) != CRYPT_OK) { - goto cleanup; - } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto cleanup; - } - - if (type == pf_public) { - key->id = LTC_PKA_DSA; - key->u.dsa.type = PK_PUBLIC; - goto cleanup; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_MPINT, key->u.dsa.x, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - - key->id = LTC_PKA_DSA; - key->u.dsa.type = PK_PRIVATE; - -cleanup: - if (err != CRYPT_OK) { - dsa_free(&key->u.dsa); - } else { - remaining -= cur_len; - *inlen -= remaining; - } - - return err; - -} -#endif - -#ifdef LTC_MRSA -static int s_ssh_decode_rsa(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, enum pem_flags type) -{ - int err; - void *tmp1, *tmp2; - unsigned long remaining, cur_len; - const unsigned char *p; - - if ((err = rsa_init(&key->u.rsa)) != CRYPT_OK) { - return err; - } - - p = in; - cur_len = *inlen; - remaining = *inlen; - - /* ssh-rsa public and private keys contain `e` and `N` in a different order - * public contains `e`, then `N` - * private contains `N`, then `e` - * change the order later on if we import a public key */ - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_MPINT, key->u.rsa.N, - LTC_SSHDATA_MPINT, key->u.rsa.e, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - - if (type == pf_public) { - /* c.f. comment above */ - void *exch = key->u.rsa.N; - key->u.rsa.N = key->u.rsa.e; - key->u.rsa.e = exch; - key->id = LTC_PKA_RSA; - key->u.rsa.type = PK_PUBLIC; - *inlen -= remaining; - goto cleanup; - } - - if ((err = ltc_mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_MPINT, key->u.rsa.d, - LTC_SSHDATA_MPINT, key->u.rsa.qP, - LTC_SSHDATA_MPINT, key->u.rsa.p, - LTC_SSHDATA_MPINT, key->u.rsa.q, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup_tmps; - } - - if ((err = ltc_mp_sub_d(key->u.rsa.p, 1, tmp1)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp1 = q-1 */ - if ((err = ltc_mp_sub_d(key->u.rsa.q, 1, tmp2)) != CRYPT_OK) { goto cleanup_tmps; } /* tmp2 = p-1 */ - if ((err = ltc_mp_mod(key->u.rsa.d, tmp1, key->u.rsa.dP)) != CRYPT_OK) { goto cleanup_tmps; } /* dP = d mod p-1 */ - if ((err = ltc_mp_mod(key->u.rsa.d, tmp2, key->u.rsa.dQ)) != CRYPT_OK) { goto cleanup_tmps; } /* dQ = d mod q-1 */ - - key->id = LTC_PKA_RSA; - key->u.rsa.type = PK_PRIVATE; - -cleanup_tmps: - ltc_mp_deinit_multi(tmp2, tmp1, LTC_NULL); -cleanup: - if (err != CRYPT_OK) { - rsa_free(&key->u.rsa); - } else { - remaining -= cur_len; - *inlen -= remaining; - } - - return err; -} -#endif - -struct ssh_pka { - struct str name; - enum ltc_pka_id id; - int (*find)(const char*, const ltc_ecc_curve **); - int (*init)(const char*, ltc_pka_key*); - int (*decode)(const unsigned char*, unsigned long*, ltc_pka_key*, enum pem_flags); -}; - -struct ssh_pka ssh_pkas[] = { -#ifdef LTC_CURVE25519 - { SET_CSTR(.name, "ssh-ed25519"), - LTC_PKA_ED25519, - NULL, - NULL, - s_ssh_decode_ed25519 }, -#endif -#ifdef LTC_MRSA - { SET_CSTR(.name, "ssh-rsa"), - LTC_PKA_RSA, - NULL, - NULL, - s_ssh_decode_rsa }, -#endif -#ifdef LTC_MDSA - { SET_CSTR(.name, "ssh-dss"), - LTC_PKA_DSA, - NULL, - NULL, - s_ssh_decode_dsa }, -#endif -#ifdef LTC_MECC - { { NULL, 0 }, - LTC_PKA_EC, - s_ssh_find_ecc, - s_ssh_find_init_ecc, - s_ssh_decode_ecdsa }, -#endif -}; - -static int s_decode_key(const unsigned char *in, unsigned long *inlen, ltc_pka_key *key, char **comment, enum pem_flags type) -{ - int err; - ulong32 check1, check2; - unsigned char pka[64]; - unsigned long pkalen = sizeof(pka); - unsigned long remaining, cur_len; - const unsigned char *p; - unsigned long n; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(key != NULL); - - p = in; - cur_len = *inlen; - remaining = *inlen; - - if (type != pf_public) { - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_UINT32, &check1, - LTC_SSHDATA_UINT32, &check2, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - return err; - } - if (check1 != check2) { - return CRYPT_INVALID_PACKET; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - } - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_STRING, pka, &pkalen, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - return err; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - - for (n = 0; n < LTC_ARRAY_SIZE(ssh_pkas); ++n) { - if (ssh_pkas[n].name.p != NULL) { - if (pkalen != ssh_pkas[n].name.len - || XMEMCMP(pka, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue; - } else { - if ((ssh_pkas[n].init == NULL) || - (ssh_pkas[n].init((char*)pka, key) != CRYPT_OK)) continue; - } - if ((err = ssh_pkas[n].decode(p, &cur_len, key, type)) != CRYPT_OK) { - return err; - } - break; - } - if (n == LTC_ARRAY_SIZE(ssh_pkas)) { - return CRYPT_PK_INVALID_TYPE; - } - - p += cur_len; - remaining -= cur_len; - cur_len = remaining; - - if (cur_len != 0 && comment) { - unsigned long commentlen = cur_len; - char *c = XMALLOC(commentlen); - if (c == NULL) { - return CRYPT_MEM; - } - if ((err = ssh_decode_sequence_multi(p, &cur_len, - LTC_SSHDATA_STRING, c, &commentlen, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - return err; - } - if (commentlen == 0) { - XFREE(c); - } else { - *comment = c; - } - } - - p += cur_len; - remaining -= cur_len; - - return remaining ? padding_depad(p, &remaining, LTC_PAD_SSH) : CRYPT_OK; -} - -static LTC_INLINE void skip_spaces(char **r, unsigned long *l) -{ - while(*l && (**r == ' ' || **r == '\t')) { - (*r)++; - (*l)--; - } -} - -static LTC_INLINE void skip_chars(char **r, unsigned long *l) -{ - while(*l && (**r != ' ' && **r != '\t')) { - (*l)--; - if (**r == '\n' || **r == '\r') { - *l = 0; - } else { - (*r)++; - } - } -} - -static LTC_INLINE void skip_to_eol(char **r, unsigned long *l) -{ - while(*l && (**r != '\n' && **r != '\r')) { - (*l)--; - (*r)++; - } -} - -static int s_parse_line(char *line, unsigned long *len, ltc_pka_key *key, char **comment) -{ - int err; - unsigned long n, rlen, olen; - enum authorized_keys_elements { - ake_algo_name = 0, - ake_b64_encoded_key = 1, - ake_comment = 2 - }; - struct str elements[3] = { 0 }; - char *r = line; - unsigned char *buf = NULL; - - rlen = *len; - /* Chop up string into the three authorized_keys_elements */ - for (n = 0; n < LTC_ARRAY_SIZE(elements) && rlen; ++n) { - skip_spaces(&r, &rlen); - elements[n].p = r; - if (n != 2) - skip_chars(&r, &rlen); - else - skip_to_eol(&r, &rlen); - elements[n].len = r - elements[n].p; - *r = '\0'; - r++; - } - - for (n = 0; n < LTC_ARRAY_SIZE(ssh_pkas); ++n) { - if (ssh_pkas[n].name.p != NULL) { - if (elements[ake_algo_name].len != ssh_pkas[n].name.len - || XMEMCMP(elements[ake_algo_name].p, ssh_pkas[n].name.p, ssh_pkas[n].name.len) != 0) continue; - } else { - if ((ssh_pkas[n].find == NULL) || - (ssh_pkas[n].find(elements[ake_algo_name].p, NULL) != CRYPT_OK)) continue; - } - olen = elements[ake_b64_encoded_key].len; - buf = XMALLOC(olen); - if (buf == NULL) { - return CRYPT_MEM; - } - if ((err = base64_strict_decode(elements[ake_b64_encoded_key].p, elements[ake_b64_encoded_key].len, buf, &olen)) == CRYPT_OK) { - err = s_decode_key(buf, &olen, key, comment, pf_public); - if (err == CRYPT_OK && key->id != ssh_pkas[n].id) { - err = CRYPT_PK_INVALID_TYPE; - } - } - XFREE(buf); - - if (err == CRYPT_OK) { - /* Only use the comment that was maybe in the text we just processed, in case when - * there was no comment inside the SSH key. - */ - if (*comment == NULL && elements[ake_comment].p) { - *comment = XMALLOC(elements[ake_comment].len + 1); - if (*comment == NULL) { - return CRYPT_MEM; - } - XMEMCPY(*comment, elements[ake_comment].p, elements[ake_comment].len); - (*comment)[elements[ake_comment].len] = '\0'; - } - *len = r - line; - return CRYPT_OK; - } - } - return CRYPT_PK_INVALID_TYPE; -} - -static int s_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx) -{ - char *s; - int err; - unsigned long clen = len; - ltc_pka_key *key = XCALLOC(1, sizeof(*key)); - char *comment = NULL; - void *cpy = XMALLOC(len); - if (key == NULL || cpy == NULL) { - if (cpy) - XFREE(cpy); - if (key) - XFREE(key); - return CRYPT_MEM; - } - XMEMCPY(cpy, buf, len); - s = cpy; - while (clen && (err = s_parse_line(s, &clen, key, &comment)) == CRYPT_OK) { - if (cb(key, comment, ctx)) { - break; - } - s += clen; - len -= clen; - clen = len; - key = XCALLOC(1, sizeof(*key)); - if (key == NULL) { - err = CRYPT_MEM; - break; - } - if (comment) { - XFREE(comment); - comment = NULL; - } - } - if (comment) - XFREE(comment); - if (cpy) - XFREE(cpy); - if (key) - XFREE(key); - return err; -} - -static int s_decrypt_private_keys(unsigned char *in, unsigned long *inlen, - unsigned char *tag, unsigned long taglen, - struct kdf_options *opts) -{ - int err, cipher; - unsigned long symkey_len, iv_len; - unsigned char symkey[MAXBLOCKSIZE], *iv, iv_[8] = { 0 }; - enum cipher_mode mode = opts->cipher->mode & cm_modes; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(opts != NULL); - - if (mode != cm_stream) { - cipher = find_cipher(opts->cipher->algo); - if (cipher == -1) { - return CRYPT_INVALID_CIPHER; - } - - iv = symkey + opts->cipher->keylen; - iv_len = mode == cm_gcm ? 12 : cipher_descriptor[cipher].block_length; - symkey_len = opts->cipher->keylen + iv_len; - } else { - iv = iv_; - iv_len = sizeof(iv_); - symkey_len = 64; - } - - if (sizeof(symkey) < symkey_len) { - return CRYPT_OVERFLOW; - } - - if ((err = bcrypt_pbkdf_openbsd(opts->pw.pw, opts->pw.l, opts->salt, opts->saltlen, - opts->num_rounds, find_hash("sha512"), symkey, &symkey_len)) != CRYPT_OK) { - return err; - } - err = pem_decrypt(in, inlen, - symkey, opts->cipher->keylen, - iv, iv_len, - tag, taglen, - opts->cipher, LTC_PAD_SSH); - zeromem(symkey, sizeof(symkey)); - - return err; -} - -static int s_decode_header(unsigned char *in, unsigned long *inlen, struct kdf_options *opts) -{ - int err; - unsigned char ciphername[64], kdfname[64], kdfoptions[128], pubkey1[2048]; - unsigned long ciphernamelen = sizeof(ciphername), kdfnamelen = sizeof(kdfname); - unsigned long kdfoptionslen = sizeof(kdfoptions), pubkey1len = sizeof(pubkey1); - ulong32 num_keys; - unsigned long i; - - void *magic = strstr((const char*)in, "openssh-key-v1"); - unsigned long slen = XSTRLEN("openssh-key-v1"); - unsigned char *start = &in[slen + 1]; - unsigned long len = *inlen - slen - 1; - - if (magic == NULL || magic != in) { - return CRYPT_INVALID_PACKET; - } - - if ((err = ssh_decode_sequence_multi(start, &len, - LTC_SSHDATA_STRING, ciphername, &ciphernamelen, - LTC_SSHDATA_STRING, kdfname, &kdfnamelen, - LTC_SSHDATA_STRING, kdfoptions, &kdfoptionslen, - LTC_SSHDATA_UINT32, &num_keys, - LTC_SSHDATA_STRING, pubkey1, &pubkey1len, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - return err; - } - if (num_keys != 1) { - return CRYPT_INVALID_PACKET; - } - - *inlen = len + slen + 1; - - for (i = 0; i < ssh_ciphers_num; ++i) { - if (XSTRCMP((char*)ciphername, ssh_ciphers[i].name) == 0) { - opts->cipher = &ssh_ciphers[i]; - break; - } - } - if (opts->cipher == NULL) { - return CRYPT_INVALID_CIPHER; - } - - if (XSTRCMP((char*)kdfname, "none") == 0) { - /* NOP */ - opts->name = "none"; - } else if (XSTRCMP((char*)kdfname, "bcrypt") == 0) { - opts->name = "bcrypt"; - opts->saltlen = sizeof(opts->salt); - len = kdfoptionslen; - if ((err = ssh_decode_sequence_multi(kdfoptions, &len, - LTC_SSHDATA_STRING, opts->salt, &opts->saltlen, - LTC_SSHDATA_UINT32, &opts->num_rounds, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - return err; - } - if (len != kdfoptionslen) { - return CRYPT_INPUT_TOO_LONG; - } - } else { - return CRYPT_INVALID_PACKET; - } - - return err; -} - - -static const struct pem_header_id pem_openssh[] = { - { - SET_CSTR(.start, "-----BEGIN OPENSSH PRIVATE KEY-----"), - SET_CSTR(.end, "-----END OPENSSH PRIVATE KEY-----"), - .has_more_headers = no - }, - { - SET_CSTR(.start, "---- BEGIN SSH2 PUBLIC KEY ----"), - SET_CSTR(.end, "---- END SSH2 PUBLIC KEY ----"), - .has_more_headers = maybe, - .flags = pf_public - }, -}; -static const unsigned long pem_openssh_num = LTC_ARRAY_SIZE(pem_openssh); - -static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - unsigned char *pem = NULL, *p, *privkey = NULL, *tag; - unsigned long n, w, l, privkey_len, taglen; - int err; - struct pem_headers hdr; - struct kdf_options opts = { 0 }; - XMEMSET(k, 0, sizeof(*k)); - w = LTC_PEM_READ_BUFSIZE * 2; -retry: - pem = XREALLOC(pem, w); - for (n = 0; n < pem_openssh_num; ++n) { - hdr.id = &pem_openssh[n]; - err = pem_read(pem, &w, &hdr, g); - if (err == CRYPT_BUFFER_OVERFLOW) { - goto retry; - } else if (err == CRYPT_OK) { - break; - } else if (err != CRYPT_UNKNOWN_PEM) { - goto cleanup; - } - hdr.id = NULL; - } - /* id not found */ - if (hdr.id == NULL) { - goto cleanup; - } - p = pem; - l = w; - if (hdr.id->flags != pf_public) { - if ((err = s_decode_header(pem, &w, &opts)) != CRYPT_OK) { - goto cleanup; - } - p = pem + w; - l -= w; - w = l; - - privkey_len = l; - privkey = XMALLOC(privkey_len); - if (privkey == NULL) { - return CRYPT_MEM; - } - - if ((err = ssh_decode_sequence_multi(p, &w, - LTC_SSHDATA_STRING, privkey, &privkey_len, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { - goto cleanup; - } - - if (XSTRCMP(opts.name, "none") != 0) { - if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) { - err = CRYPT_PW_CTX_MISSING; - goto cleanup; - } - if (pw_ctx->callback(&opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) { - err = CRYPT_ERROR; - goto cleanup; - } - tag = p + w; - taglen = l - w; - w = privkey_len; - if ((err = s_decrypt_private_keys(privkey, &privkey_len, - tag, taglen, - &opts)) != CRYPT_OK) { - goto cleanup; - } - zeromem(opts.pw.pw, opts.pw.l); - } - - p = privkey; - w = privkey_len; - } - if ((err = s_decode_key(p, &w, k, NULL, hdr.id->flags)) != CRYPT_OK) { - goto cleanup; - } - -cleanup: - password_free(&opts.pw, pw_ctx); - if (privkey) { - zeromem(privkey, privkey_len); - XFREE(privkey); - } - XFREE(pem); - return err; -} - -#ifndef LTC_NO_FILE -int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - LTC_ARGCHK(f != NULL); - LTC_ARGCHK(k != NULL); - { - struct get_char g = { .get = pem_get_char_from_file, .data.f = f }; - return s_decode_openssh(&g, k, pw_ctx); - } -} - -int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx) -{ - size_t tot_data; - void *buf; - int err; - - LTC_ARGCHK(f != NULL); - LTC_ARGCHK(cb != NULL); - - if (fseek(f, 0, SEEK_END) == -1) - return CRYPT_ERROR; - tot_data = ftell(f); - if (fseek(f, 0, SEEK_SET) == -1) - return CRYPT_ERROR; - buf = XMALLOC(tot_data); - if (buf == NULL) { - return CRYPT_MEM; - } - if (fread(buf, 1, tot_data, f) != tot_data) { - err = CRYPT_ERROR; - } else { - err = s_read_authorized_keys(buf, tot_data, cb, ctx); - } - XFREE(buf); - - return err; -} -#endif /* LTC_NO_FILE */ - -int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - LTC_ARGCHK(buf != NULL); - LTC_ARGCHK(len != 0); - LTC_ARGCHK(k != NULL); - { - struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) }; - return s_decode_openssh(&g, k, pw_ctx); - } -} - -int ssh_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx) -{ - LTC_ARGCHK(buf != NULL); - LTC_ARGCHK(len != 0); - LTC_ARGCHK(cb != NULL); - - return s_read_authorized_keys(buf, len, cb, ctx); -} -#endif /* defined(LTC_PEM_SSH) */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_kdf.c b/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_kdf.c deleted file mode 100644 index 191e740..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_kdf.c +++ /dev/null @@ -1,88 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_PKCS_12 - -int pkcs12_kdf( int hash_id, - const unsigned char *pw, unsigned long pwlen, - const unsigned char *salt, unsigned long saltlen, - unsigned int iterations, unsigned char purpose, - unsigned char *out, unsigned long outlen) -{ - unsigned long u = hash_descriptor[hash_id].hashsize; - unsigned long v = hash_descriptor[hash_id].blocksize; - unsigned long c = (outlen + u - 1) / u; - unsigned long Slen = ((saltlen + v - 1) / v) * v; - unsigned long Plen = ((pwlen + v - 1) / v) * v; - unsigned long k = (Plen + Slen) / v; - unsigned long Alen, keylen = 0; - unsigned int tmp, i, j, n; - unsigned char ch; - unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE]; - unsigned char *I, *key; - int err = CRYPT_ERROR; - - LTC_ARGCHK(pw != NULL); - LTC_ARGCHK(salt != NULL); - LTC_ARGCHK(out != NULL); - - key = XMALLOC(u * c); - I = XMALLOC(Plen + Slen); - if (key == NULL || I == NULL) goto DONE; - zeromem(key, u * c); - - for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */ - for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen]; - for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */ - - for (i = 0; i < c; i++) { - Alen = sizeof(A); - err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */ - if (err != CRYPT_OK) goto DONE; - for (j = 1; j < iterations; j++) { - err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */ - if (err != CRYPT_OK) goto DONE; - } - /* fill buffer B with A */ - for (j = 0; j < v; j++) B[j] = A[j % Alen]; - /* B += 1 */ - for (j = v; j > 0; j--) { - if (++B[j - 1] != 0) break; - } - /* I_n += B */ - for (n = 0; n < k; n++) { - ch = 0; - for (j = v; j > 0; j--) { - tmp = I[n * v + j - 1] + B[j - 1] + ch; - ch = (unsigned char)((tmp >> 8) & 0xFF); - I[n * v + j - 1] = (unsigned char)(tmp & 0xFF); - } - } - /* store derived key block */ - XMEMCPY(&key[keylen], A, Alen); - keylen += Alen; - } - - XMEMCPY(out, key, outlen); - err = CRYPT_OK; -DONE: - if (I) { - zeromem(I, Plen + Slen); - XFREE(I); - } - if (key) { - zeromem(key, u * c); - XFREE(key); - } - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c b/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c deleted file mode 100644 index bcf2023..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pkcs12/pkcs12_utf8_to_utf16.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_PKCS_12 - -int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) { - unsigned long len = 0; - const unsigned char* in_end = in + inlen; - const ulong32 offset[6] = { - 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL - }; - int err = CRYPT_ERROR; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - while (in < in_end) { - ulong32 ch = 0; - unsigned short extra = 0; /* 0 */ - if (*in >= 192) extra++; /* 1 */ - if (*in >= 224) extra++; /* 2 */ - if (*in >= 240) extra++; /* 3 */ - if (*in >= 248) extra++; /* 4 */ - if (*in >= 252) extra++; /* 5 */ - if (in + extra >= in_end) goto ERROR; - switch (extra) { - case 5: ch += *in++; ch <<= 6; - /* FALLTHROUGH */ - case 4: ch += *in++; ch <<= 6; - /* FALLTHROUGH */ - case 3: ch += *in++; ch <<= 6; - /* FALLTHROUGH */ - case 2: ch += *in++; ch <<= 6; - /* FALLTHROUGH */ - case 1: ch += *in++; ch <<= 6; - /* FALLTHROUGH */ - case 0: ch += *in++; - } - ch -= offset[extra]; - if (ch > 0xFFFF) goto ERROR; - if (*outlen >= len + 2) { - out[len] = (unsigned short)((ch >> 8) & 0xFF); - out[len + 1] = (unsigned char)(ch & 0xFF); - } - len += 2; - } - - err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK; - *outlen = len; -ERROR: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_1.c b/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_1.c deleted file mode 100644 index ea9c19c..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_1.c +++ /dev/null @@ -1,185 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_5_1.c - PKCS #5, Algorithm #1, Tom St Denis -*/ -#ifdef LTC_PKCS_5 -/** - Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode. - - PKCS#5 v1 specifies that the output key length can be no larger than - the hash output length. OpenSSL unilaterally extended that by repeating - the hash process on a block-by-block basis for as long as needed to make - bigger keys. If you want to be compatible with KDF for e.g. "openssl enc", - you'll want that. - - If you want strict PKCS behavior, turn openssl_compat off. Or (more - likely), use one of the convenience functions below. - - @param password The password (or key) - @param password_len The length of the password (octet) - @param salt The salt (or nonce) which is 8 octets long - @param iteration_count The PKCS #5 v1 iteration count - @param hash_idx The index of the hash desired - @param out [out] The destination for this algorithm - @param outlen [in/out] The max size and resulting size of the algorithm output - @param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL - @return CRYPT_OK if successful -*/ -static int s_pkcs_5_alg1_common(const unsigned char *password, - unsigned long password_len, - const unsigned char *salt, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen, - int openssl_compat) -{ - int err; - unsigned long x; - hash_state *md; - unsigned char *buf; - /* Storage vars in case we need to support > hashsize (OpenSSL compat) */ - unsigned long block = 0, iter; - /* How many bytes to put in the outbut buffer (convenience calc) */ - unsigned long outidx = 0, nb = 0; - - LTC_ARGCHK(password != NULL); - LTC_ARGCHK(salt != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if (iteration_count <= 0) { - return CRYPT_INVALID_ARG; - } - - /* test hash IDX */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* allocate memory */ - md = XMALLOC(sizeof(hash_state)); - buf = XMALLOC(MAXBLOCKSIZE); - if (md == NULL || buf == NULL) { - if (md != NULL) { - XFREE(md); - } - if (buf != NULL) { - XFREE(buf); - } - return CRYPT_MEM; - } - - while(block * hash_descriptor[hash_idx].hashsize < *outlen) { - - /* hash initial (maybe previous hash) + password + salt */ - if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { - goto LBL_ERR; - } - /* in OpenSSL mode, we first hash the previous result for blocks 2-n */ - if (openssl_compat && block) { - if ((err = hash_descriptor[hash_idx].process(md, buf, hash_descriptor[hash_idx].hashsize)) != CRYPT_OK) { - goto LBL_ERR; - } - } - if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { - goto LBL_ERR; - } - - iter = iteration_count; - while (--iter) { - /* code goes here. */ - x = MAXBLOCKSIZE; - if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* limit the size of the copy to however many bytes we have left in - the output buffer (and how many bytes we have to copy) */ - outidx = block*hash_descriptor[hash_idx].hashsize; - nb = hash_descriptor[hash_idx].hashsize; - if(outidx+nb > *outlen) { - nb = *outlen - outidx; - } - if(nb > 0) { - XMEMCPY(out+outidx, buf, nb); - } - - block++; - if (!openssl_compat) { - break; - } - } - /* In strict mode, we always return the hashsize, in compat we filled it - as much as was requested, so we leave it alone. */ - if(!openssl_compat) { - *outlen = hash_descriptor[hash_idx].hashsize; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf, MAXBLOCKSIZE); - zeromem(md, sizeof(hash_state)); -#endif - - XFREE(buf); - XFREE(md); - - return err; -} - -/** - Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension) - @param password The password (or key) - @param password_len The length of the password (octet) - @param salt The salt (or nonce) which is 8 octets long - @param iteration_count The PKCS #5 v1 iteration count - @param hash_idx The index of the hash desired - @param out [out] The destination for this algorithm - @param outlen [in/out] The max size and resulting size of the algorithm output - @return CRYPT_OK if successful -*/ -int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, - const unsigned char *salt, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, - hash_idx, out, outlen, 0); -} - -/** - Execute PKCS #5 v1 - OpenSSL-extension-compatible mode - - Use this one if you need to derive keys as "openssl enc" does by default. - OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1. - @param password The password (or key) - @param password_len The length of the password (octet) - @param salt The salt (or nonce) which is 8 octets long - @param iteration_count The PKCS #5 v1 iteration count - @param hash_idx The index of the hash desired - @param out [out] The destination for this algorithm - @param outlen [in/out] The max size and resulting size of the algorithm output - @return CRYPT_OK if successful -*/ -int pkcs_5_alg1_openssl(const unsigned char *password, - unsigned long password_len, - const unsigned char *salt, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, - hash_idx, out, outlen, 1); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_2.c b/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_2.c deleted file mode 100644 index 61ebd00..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_2.c +++ /dev/null @@ -1,121 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_5_2.c - PKCS #5, Algorithm #2, Tom St Denis -*/ -#ifdef LTC_PKCS_5 - -/** - Execute PKCS #5 v2 - @param password The input password (or key) - @param password_len The length of the password (octets) - @param salt The salt (or nonce) - @param salt_len The length of the salt (octets) - @param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more] - @param hash_idx The index of the hash desired - @param out [out] The destination for this algorithm - @param outlen [in/out] The max size and resulting size of the algorithm output - @return CRYPT_OK if successful -*/ -int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, - const unsigned char *salt, unsigned long salt_len, - int iteration_count, int hash_idx, - unsigned char *out, unsigned long *outlen) -{ - int err, itts; - ulong32 blkno; - unsigned long stored, left, x, y; - unsigned char *buf[2]; - hmac_state *hmac; - - LTC_ARGCHK(password != NULL); - LTC_ARGCHK(salt != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if (iteration_count <= 0) { - return CRYPT_INVALID_ARG; - } - - /* test hash IDX */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - buf[0] = XMALLOC(MAXBLOCKSIZE * 2); - hmac = XMALLOC(sizeof(hmac_state)); - if (hmac == NULL || buf[0] == NULL) { - if (hmac != NULL) { - XFREE(hmac); - } - if (buf[0] != NULL) { - XFREE(buf[0]); - } - return CRYPT_MEM; - } - /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ - buf[1] = buf[0] + MAXBLOCKSIZE; - - left = *outlen; - blkno = 1; - stored = 0; - while (left != 0) { - /* process block number blkno */ - zeromem(buf[0], MAXBLOCKSIZE*2); - - /* store current block number and increment for next pass */ - STORE32H(blkno, buf[1]); - ++blkno; - - /* get PRF(P, S||int(blkno)) */ - if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { - goto LBL_ERR; - } - x = MAXBLOCKSIZE; - if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* now compute repeated and XOR it in buf[1] */ - XMEMCPY(buf[1], buf[0], x); - for (itts = 1; itts < iteration_count; ++itts) { - if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { - goto LBL_ERR; - } - for (y = 0; y < x; y++) { - buf[1][y] ^= buf[0][y]; - } - } - - /* now emit upto x bytes of buf[1] to output */ - for (y = 0; y < x && left != 0; ++y) { - out[stored++] = buf[1][y]; - --left; - } - } - *outlen = stored; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf[0], MAXBLOCKSIZE*2); - zeromem(hmac, sizeof(hmac_state)); -#endif - - XFREE(hmac); - XFREE(buf[0]); - - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_test.c b/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_test.c deleted file mode 100644 index f90c0ee..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/pkcs5/pkcs_5_test.c +++ /dev/null @@ -1,224 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file hkdf_test.c - PKCS #5 support, self-test, Steffen Jaeckel -*/ - -#ifdef LTC_PKCS_5 - -/* - TEST CASES SOURCE: - -Internet Engineering Task Force (IETF) S. Josefsson -Request for Comments: 6070 SJD AB -Category: Informational January 2011 -ISSN: 2070-1721 -*/ - -/** - PKCS #5 self-test - @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. -*/ -int pkcs_5_test (void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - - typedef struct { - const char* P; - unsigned long P_len; - const char* S; - unsigned long S_len; - int c; - unsigned long dkLen; - unsigned char DK[40]; - } case_item; - - static const case_item cases_5_2[] = { - { - "password", - 8, - "salt", - 4, - 1, - 20, - { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, - 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, - 0x2f, 0xe0, 0x37, 0xa6 } - }, - { - "password", - 8, - "salt", - 4, - 2, - 20, - { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, - 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, - 0xd8, 0xde, 0x89, 0x57 } - }, -#ifdef LTC_TEST_EXT - { - "password", - 8, - "salt", - 4, - 4096, - 20, - { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, - 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, - 0x65, 0xa4, 0x29, 0xc1 } - }, - { - "password", - 8, - "salt", - 4, - 16777216, - 20, - { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, - 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, - 0x26, 0x34, 0xe9, 0x84 } - }, - { - "passwordPASSWORDpassword", - 25, - "saltSALTsaltSALTsaltSALTsaltSALTsalt", - 36, - 4096, - 25, - { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, - 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, - 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, - 0x38 } - }, - { - "pass\0word", - 9, - "sa\0lt", - 5, - 4096, - 16, - { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, - 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 } - }, -#endif /* LTC_TEST_EXT */ - }; - - static const case_item cases_5_1[] = { - { - "password", - 8, - "saltsalt", /* must be 8 octects */ - 8, /* ignored by alg1 */ - 1, - 20, - { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, - 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } - }, - }; - - static const case_item cases_5_1o[] = { - { - "password", - 8, - "saltsalt", /* must be 8 octects */ - 8, /* ignored by alg1_openssl */ - 1, - 20, - { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, - 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } - - }, - { - "password", - 8, - "saltsalt", /* must be 8 octects */ - 8, /* ignored by alg1_openssl */ - 1, - 30, - { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, - 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44, - 0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b } - - } - }; - - unsigned char DK[40]; - unsigned long dkLen; - int i, err; - int tested=0, failed=0; - int hash = find_hash("sha1"); - if (hash == -1) - { -#ifdef LTC_TEST_DBG - printf("PKCS#5 test failed: 'sha1' hash not found\n"); -#endif - return CRYPT_ERROR; - } - - /* testing alg 2 */ - for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) { - ++tested; - dkLen = cases_5_2[i].dkLen; - if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len, - (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len, - cases_5_2[i].c, hash, - DK, &dkLen)) != CRYPT_OK) { - LTC_UNUSED_PARAM(err); -#ifdef LTC_TEST_DBG - printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err)); -#endif - ++failed; - } - else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) { - ++failed; - } - } - - /* testing alg 1 */ - for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) { - dkLen = cases_5_1[i].dkLen; - if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len, - (unsigned char*)cases_5_1[i].S, - cases_5_1[i].c, hash, - DK, &dkLen)) != CRYPT_OK) { - LTC_UNUSED_PARAM(err); -#ifdef LTC_TEST_DBG - printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err)); -#endif - ++failed; - } - else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) { - ++failed; - } - } - - /* testing alg 1_openssl */ - for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) { - dkLen = cases_5_1o[i].dkLen; - if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len, - (unsigned char*)cases_5_1o[i].S, - cases_5_1o[i].c, hash, - DK, &dkLen)) != CRYPT_OK) { - LTC_UNUSED_PARAM(err); -#ifdef LTC_TEST_DBG - printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err)); -#endif - ++failed; - } - else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) { - ++failed; - } - } - - return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK; - #endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c b/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c deleted file mode 100644 index 3c4bb44..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_decode_sequence_multi.c +++ /dev/null @@ -1,164 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ssh_decode_sequence_multi.c - SSH data type representation as per RFC4251, Russ Williams -*/ - -#ifdef LTC_SSH - -/** - Decode a SSH sequence using a VA list - @param in The input buffer - @param inlen [in/out] The length of the input buffer and on output the amount of decoded data - @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*) - @return CRYPT_OK on success -*/ -int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) -{ - int err; - va_list args; - ssh_data_type type; - void *vdata; - unsigned char *cdata; - char *sdata; - ulong32 *u32data; - ulong64 *u64data; - unsigned long *bufsize; - ulong32 size; - unsigned long remaining; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - - remaining = *inlen; - /* Decode values from buffer */ - va_start(args, inlen); - while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { - /* Size of length field */ - if (type == LTC_SSHDATA_STRING || - type == LTC_SSHDATA_NAMELIST || - type == LTC_SSHDATA_MPINT) - { - /* Check we'll not read too far */ - if (remaining < 4) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - } - - /* Calculate (or read) length of data */ - size = 0xFFFFFFFFU; - switch (type) { - case LTC_SSHDATA_BYTE: - case LTC_SSHDATA_BOOLEAN: - size = 1; - break; - case LTC_SSHDATA_UINT32: - size = 4; - break; - case LTC_SSHDATA_UINT64: - size = 8; - break; - case LTC_SSHDATA_STRING: - case LTC_SSHDATA_NAMELIST: - case LTC_SSHDATA_MPINT: - LOAD32H(size, in); - in += 4; - remaining -= 4; - break; - - case LTC_SSHDATA_EOL: - /* Should never get here */ - err = CRYPT_INVALID_ARG; - goto error; - } - - /* Check we'll not read too far */ - if (remaining < size) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } else { - remaining -= size; - } - - vdata = va_arg(args, void*); - if (vdata == NULL) { - err = CRYPT_INVALID_ARG; - goto error; - } - - /* Read data */ - switch (type) { - case LTC_SSHDATA_BYTE: - cdata = vdata; - *cdata = *in++; - break; - case LTC_SSHDATA_BOOLEAN: - cdata = vdata; - /* - The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be - interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. - */ - *cdata = (*in++)?1:0; - break; - case LTC_SSHDATA_UINT32: - u32data = vdata; - LOAD32H(*u32data, in); - in += 4; - break; - case LTC_SSHDATA_UINT64: - u64data = vdata; - LOAD64H(*u64data, in); - in += 8; - break; - case LTC_SSHDATA_STRING: - case LTC_SSHDATA_NAMELIST: - sdata = vdata; - bufsize = va_arg(args, unsigned long*); - if (bufsize == NULL) { - err = CRYPT_INVALID_ARG; - goto error; - } - if (size + 1 >= *bufsize) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - if (size > 0) { - XMEMCPY(sdata, (const char *)in, size); - } - sdata[size] = '\0'; - *bufsize = size; - in += size; - break; - case LTC_SSHDATA_MPINT: - if (size == 0) { - if ((err = ltc_mp_set(vdata, 0)) != CRYPT_OK) { goto error; } - } else if ((in[0] & 0x80) != 0) { - /* Negative number - not supported */ - err = CRYPT_INVALID_PACKET; - goto error; - } else { - if ((err = ltc_mp_read_unsigned_bin(vdata, in, size)) != CRYPT_OK) { goto error; } - } - in += size; - break; - - case LTC_SSHDATA_EOL: - /* Should never get here */ - err = CRYPT_INVALID_ARG; - goto error; - } - } - err = CRYPT_OK; - - *inlen -= remaining; - -error: - va_end(args); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c b/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c deleted file mode 100644 index 060be10..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/ssh/ssh_encode_sequence_multi.c +++ /dev/null @@ -1,163 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file ssh_encode_sequence_multi.c - SSH data type representation as per RFC4251, Russ Williams -*/ - -#ifdef LTC_SSH - -/** - Encode a SSH sequence using a VA list - @param out [out] Destination for data - @param outlen [in/out] Length of buffer and resulting length of output - @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long) - @return CRYPT_OK on success -*/ -int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) -{ - int err; - va_list args; - ulong32 size; - ssh_data_type type; - void *vdata; - const char *sdata; - int idata; - ulong32 u32data; - ulong64 u64data; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* Check values and calculate output size */ - size = 0; - va_start(args, outlen); - while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { - switch (type) { - case LTC_SSHDATA_BYTE: - case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */ - LTC_UNUSED_PARAM( va_arg(args, int) ); - size++; - break; - case LTC_SSHDATA_UINT32: - LTC_UNUSED_PARAM( va_arg(args, ulong32) ); - size += 4; - break; - case LTC_SSHDATA_UINT64: - LTC_UNUSED_PARAM( va_arg(args, ulong64) ); - size += 8; - break; - case LTC_SSHDATA_STRING: - case LTC_SSHDATA_NAMELIST: - LTC_UNUSED_PARAM( va_arg(args, char*) ); - size += va_arg(args, unsigned long); - size += 4; - break; - case LTC_SSHDATA_MPINT: - vdata = va_arg(args, void*); - /* Calculate size */ - size += 4; - if (ltc_mp_iszero(vdata) != LTC_MP_YES) { - size += ltc_mp_unsigned_bin_size(vdata); - if ((ltc_mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */ - } - break; - - case LTC_SSHDATA_EOL: /* Should never get here */ - err = CRYPT_INVALID_ARG; - goto error; - } - } - va_end(args); - - /* Check we have sufficient space */ - if (*outlen < size) { - *outlen = size; - err = CRYPT_BUFFER_OVERFLOW; - goto errornoargs; - } - *outlen = size; - - /* Encode values into buffer */ - va_start(args, outlen); - while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { - switch (type) { - case LTC_SSHDATA_BYTE: - idata = va_arg(args, int); - - *out++ = (unsigned char)(idata & 255); - break; - case LTC_SSHDATA_BOOLEAN: - idata = va_arg(args, int); - - /* - The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be - interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. - */ - *out++ = (idata)?1:0; - break; - case LTC_SSHDATA_UINT32: - u32data = va_arg(args, ulong32); - STORE32H(u32data, out); - out += 4; - break; - case LTC_SSHDATA_UINT64: - u64data = va_arg(args, ulong64); - STORE64H(u64data, out); - out += 8; - break; - case LTC_SSHDATA_STRING: - case LTC_SSHDATA_NAMELIST: - sdata = va_arg(args, char*); - size = va_arg(args, unsigned long); - STORE32H(size, out); - out += 4; - XMEMCPY(out, sdata, size); - out += size; - break; - case LTC_SSHDATA_MPINT: - vdata = va_arg(args, void*); - if (ltc_mp_iszero(vdata) == LTC_MP_YES) { - STORE32H(0, out); - out += 4; - } else { - size = ltc_mp_unsigned_bin_size(vdata); - if ((ltc_mp_count_bits(vdata) & 7) == 0) { - /* Zero padding if high bit set */ - STORE32H(size+1, out); - out += 4; - *out++ = 0; - } else { - STORE32H(size, out); - out += 4; - } - if (ltc_mp_to_unsigned_bin(vdata, out) != CRYPT_OK) { - err = CRYPT_ERROR; - goto error; - } - out += size; - } - break; - - case LTC_SSHDATA_EOL: /* Should never get here */ - err = CRYPT_INVALID_ARG; - goto error; - } - } - err = CRYPT_OK; - -error: - va_end(args); -errornoargs: - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/misc/zeromem.c b/Sources/DataLiteC/libtomcrypt/misc/zeromem.c deleted file mode 100644 index 7d14994..0000000 --- a/Sources/DataLiteC/libtomcrypt/misc/zeromem.c +++ /dev/null @@ -1,22 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file zeromem.c - Zero a block of memory, Tom St Denis -*/ - -/** - Zero a block of memory - @param out The destination of the area to zero - @param outlen The length of the area to zero (octets) -*/ -void zeromem(volatile void *out, size_t outlen) -{ - volatile char *mem = out; - LTC_ARGCHKVD(out != NULL); - while (outlen-- > 0) { - *mem++ = '\0'; - } -} diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_decrypt.c deleted file mode 100644 index 4c3add7..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_decrypt.c +++ /dev/null @@ -1,84 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_decrypt.c - CBC implementation, encrypt block, Tom St Denis -*/ - - -#ifdef LTC_CBC_MODE - -/** - CBC decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len The number of bytes to process (must be multiple of block length) - @param cbc CBC state - @return CRYPT_OK if successful -*/ -int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) -{ - int x, err; - unsigned char tmp[16]; -#ifdef LTC_FAST - LTC_FAST_TYPE tmpy; -#else - unsigned char tmpy; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(cbc != NULL); - - if ((err = cipher_is_valid(cbc->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen valid? */ - if (cbc->ecb.blocklen < 1 || cbc->ecb.blocklen > (int)sizeof(cbc->IV) || cbc->ecb.blocklen > (int)sizeof(tmp)) { - return CRYPT_INVALID_ARG; - } - - if (len % cbc->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } -#ifdef LTC_FAST - if (cbc->ecb.blocklen % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - if (cipher_descriptor[cbc->ecb.cipher].accel_cbc_decrypt != NULL) { - return cipher_descriptor[cbc->ecb.cipher].accel_cbc_decrypt(ct, pt, len / cbc->ecb.blocklen, cbc->IV, &cbc->ecb.key); - } - while (len) { - /* decrypt */ - if ((err = ecb_decrypt_block(ct, tmp, &cbc->ecb)) != CRYPT_OK) { - return err; - } - - /* xor IV against plaintext */ -#if defined(LTC_FAST) - for (x = 0; x < cbc->ecb.blocklen; x += sizeof(LTC_FAST_TYPE)) { - tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x)); - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy; - } -#else - for (x = 0; x < cbc->ecb.blocklen; x++) { - tmpy = tmp[x] ^ cbc->IV[x]; - cbc->IV[x] = ct[x]; - pt[x] = tmpy; - } -#endif - - ct += cbc->ecb.blocklen; - pt += cbc->ecb.blocklen; - len -= cbc->ecb.blocklen; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_done.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_done.c deleted file mode 100644 index d66e86f..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_done.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_done.c - CBC implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_CBC_MODE - -/** Terminate the chain - @param cbc The CBC chain to terminate - @return CRYPT_OK on success -*/ -int cbc_done(symmetric_CBC *cbc) -{ - LTC_ARGCHK(cbc != NULL); - - return ecb_done(&cbc->ecb); -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_encrypt.c deleted file mode 100644 index 7274d69..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_encrypt.c +++ /dev/null @@ -1,85 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_encrypt.c - CBC implementation, encrypt block, Tom St Denis -*/ - - -#ifdef LTC_CBC_MODE - -/** - CBC encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len The number of bytes to process (must be multiple of block length) - @param cbc CBC state - @return CRYPT_OK if successful -*/ -int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc) -{ - int x, err; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(cbc != NULL); - - if ((err = cipher_is_valid(cbc->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen valid? */ - if (cbc->ecb.blocklen < 1 || cbc->ecb.blocklen > (int)sizeof(cbc->IV)) { - return CRYPT_INVALID_ARG; - } - - if (len % cbc->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } -#ifdef LTC_FAST - if (cbc->ecb.blocklen % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - if (cipher_descriptor[cbc->ecb.cipher].accel_cbc_encrypt != NULL) { - return cipher_descriptor[cbc->ecb.cipher].accel_cbc_encrypt(pt, ct, len / cbc->ecb.blocklen, cbc->IV, &cbc->ecb.key); - } - while (len) { - /* xor IV against plaintext */ -#if defined(LTC_FAST) - for (x = 0; x < cbc->ecb.blocklen; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)); - } -#else - for (x = 0; x < cbc->ecb.blocklen; x++) { - cbc->IV[x] ^= pt[x]; - } -#endif - - /* encrypt */ - if ((err = ecb_encrypt_block(cbc->IV, ct, &cbc->ecb)) != CRYPT_OK) { - return err; - } - - /* store IV [ciphertext] for a future block */ -#if defined(LTC_FAST) - for (x = 0; x < cbc->ecb.blocklen; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); - } -#else - for (x = 0; x < cbc->ecb.blocklen; x++) { - cbc->IV[x] = ct[x]; - } -#endif - - ct += cbc->ecb.blocklen; - pt += cbc->ecb.blocklen; - len -= cbc->ecb.blocklen; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_getiv.c deleted file mode 100644 index 37bf600..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_getiv.c - CBC implementation, get IV, Tom St Denis -*/ - -#ifdef LTC_CBC_MODE - -/** - Get the current initialization vector - @param IV [out] The destination of the initialization vector - @param len [in/out] The max size and resulting size of the initialization vector - @param cbc The CBC state - @return CRYPT_OK if successful -*/ -int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(cbc != NULL); - if ((unsigned long)cbc->ecb.blocklen > *len) { - *len = cbc->ecb.blocklen; - return CRYPT_BUFFER_OVERFLOW; - } - XMEMCPY(IV, cbc->IV, cbc->ecb.blocklen); - *len = cbc->ecb.blocklen; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_setiv.c deleted file mode 100644 index 92620b0..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_setiv.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_setiv.c - CBC implementation, set IV, Tom St Denis -*/ - - -#ifdef LTC_CBC_MODE - -/** - Set an initialization vector - @param IV The initialization vector - @param len The length of the vector (in octets) - @param cbc The CBC state - @return CRYPT_OK if successful -*/ -int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(cbc != NULL); - if (len != (unsigned long)cbc->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } - XMEMCPY(cbc->IV, IV, len); - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_start.c b/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_start.c deleted file mode 100644 index 58322e1..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cbc/cbc_start.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cbc_start.c - CBC implementation, start chain, Tom St Denis -*/ - -#ifdef LTC_CBC_MODE - -/** - Initialize a CBC context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param cbc The CBC state to initialize - @return CRYPT_OK if successful -*/ -int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CBC *cbc) -{ - int x, err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(cbc != NULL); - - /* setup cipher */ - if ((err = ecb_start(cipher, key, keylen, num_rounds, &cbc->ecb)) != CRYPT_OK) { - return err; - } - - /* copy IV */ - for (x = 0; x < cbc->ecb.blocklen; x++) { - cbc->IV[x] = IV[x]; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_decrypt.c deleted file mode 100644 index 69026e3..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_decrypt.c +++ /dev/null @@ -1,120 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_decrypt.c - CFB implementation, decrypt data, Tom St Denis -*/ - -#ifdef LTC_CFB_MODE - -#ifndef LTC_CFB_SHIFT1LEFT -#define LTC_CFB_SHIFT1LEFT -static LTC_INLINE void s_shift1left_64(unsigned char *b, unsigned char v) -{ - ulong64 bval; - LOAD64H(bval, b); - bval <<= 1; - bval |= v & 0x01u; - STORE64H(bval, b); -} - -static LTC_INLINE void s_shift1left_128(unsigned char *b, unsigned char v) -{ - ulong64 bval[2]; - LOAD64H(bval[0], b); - LOAD64H(bval[1], b + 8); - bval[0] <<= 1; - bval[0] |= (bval[1] >> 63) & 0x01u; - bval[1] <<= 1; - bval[1] |= v & 0x01u; - STORE64H(bval[0], b); - STORE64H(bval[1], b + 8); -} -#endif /* LTC_CFB_SHIFT1LEFT */ - -/** - CFB decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len Length of ciphertext (octets) - @param cfb CFB state - @return CRYPT_OK if successful -*/ -int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) -{ - int err; - ulong64 bitlen = len * 8, bits_per_round; - unsigned int cur_bit = 0; - unsigned char pt_ = 0, ct_ = 0; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(cfb != NULL); - - if (bitlen < len) { - return CRYPT_OVERFLOW; - } - - if ((err = cipher_is_valid(cfb->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (cfb->ecb.blocklen < 0 || cfb->ecb.blocklen > (int)sizeof(cfb->IV) || - cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { - return CRYPT_INVALID_ARG; - } - - bits_per_round = cfb->width == 1 ? 1 : 8; - - while (bitlen > 0) { - if (cfb->padlen == cfb->ecb.blocklen) { - if ((err = ecb_encrypt_block(cfb->pad, cfb->IV, &cfb->ecb)) != CRYPT_OK) { - return err; - } - cfb->padlen = 0; - } - switch (cfb->width) { - case 1: - if (cur_bit++ % 8 == 0) { - ct_ = *ct++; - pt_ = 0; - } else { - ct_ <<= 1; - pt_ <<= 1; - } - if (cfb->ecb.blocklen == 16) - s_shift1left_128(cfb->pad, ct_ >> 7); - else - s_shift1left_64(cfb->pad, ct_ >> 7); - pt_ |= ((ct_ ^ cfb->IV[0]) >> 7) & 0x01u; - cfb->padlen = cfb->ecb.blocklen; - if (cur_bit % 8 == 0) { - *pt++ = pt_; - cur_bit = 0; - } - break; - case 8: - XMEMMOVE(cfb->pad, cfb->pad + 1, cfb->ecb.blocklen - 1); - cfb->pad[cfb->ecb.blocklen - 1] = *ct; - *pt++ = *ct++ ^ cfb->IV[0]; - cfb->padlen = cfb->ecb.blocklen; - break; - case 64: - case 128: - cfb->pad[cfb->padlen] = *ct; - *pt++ = *ct++ ^ cfb->IV[cfb->padlen]; - ++(cfb->padlen); - break; - default: - return CRYPT_INVALID_ARG; - } - bitlen -= bits_per_round; - } - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_done.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_done.c deleted file mode 100644 index 881a17c..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_done.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_done.c - CFB implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_CFB_MODE - -/** Terminate the chain - @param cfb The CFB chain to terminate - @return CRYPT_OK on success -*/ -int cfb_done(symmetric_CFB *cfb) -{ - LTC_ARGCHK(cfb != NULL); - - return ecb_done(&cfb->ecb); -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_encrypt.c deleted file mode 100644 index 22e27aa..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_encrypt.c +++ /dev/null @@ -1,119 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_encrypt.c - CFB implementation, encrypt data, Tom St Denis -*/ - -#ifdef LTC_CFB_MODE - -#ifndef LTC_CFB_SHIFT1LEFT -#define LTC_CFB_SHIFT1LEFT -static LTC_INLINE void s_shift1left_64(unsigned char *b, unsigned char v) -{ - ulong64 bval; - LOAD64H(bval, b); - bval <<= 1; - bval |= v & 0x01u; - STORE64H(bval, b); -} - -static LTC_INLINE void s_shift1left_128(unsigned char *b, unsigned char v) -{ - ulong64 bval[2]; - LOAD64H(bval[0], b); - LOAD64H(bval[1], b + 8); - bval[0] <<= 1; - bval[0] |= (bval[1] >> 63) & 0x01u; - bval[1] <<= 1; - bval[1] |= v & 0x01u; - STORE64H(bval[0], b); - STORE64H(bval[1], b + 8); -} -#endif /* LTC_CFB_SHIFT1LEFT */ - -/** - CFB encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len Length of plaintext (octets) - @param cfb CFB state - @return CRYPT_OK if successful -*/ -int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) -{ - int err; - ulong64 bitlen = len * 8, bits_per_round; - unsigned int cur_bit = 0; - unsigned char pt_ = 0, ct_ = 0; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(cfb != NULL); - - if (bitlen < len) { - return CRYPT_OVERFLOW; - } - - if ((err = cipher_is_valid(cfb->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (cfb->ecb.blocklen < 0 || cfb->ecb.blocklen > (int)sizeof(cfb->IV) || - cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { - return CRYPT_INVALID_ARG; - } - - bits_per_round = cfb->width == 1 ? 1 : 8; - - while (bitlen > 0) { - if (cfb->padlen == cfb->ecb.blocklen) { - if ((err = ecb_encrypt_block(cfb->pad, cfb->IV, &cfb->ecb)) != CRYPT_OK) { - return err; - } - cfb->padlen = 0; - } - switch (cfb->width) { - case 1: - if (cur_bit++ % 8 == 0) { - pt_ = *pt++; - ct_ = 0; - } else { - pt_ <<= 1; - ct_ <<= 1; - } - ct_ |= ((pt_ ^ cfb->IV[0]) >> 7) & 0x01u; - if (cfb->ecb.blocklen == 16) - s_shift1left_128(cfb->pad, ct_); - else - s_shift1left_64(cfb->pad, ct_); - cfb->padlen = cfb->ecb.blocklen; - if (cur_bit % 8 == 0) { - *ct++ = ct_; - cur_bit = 0; - } - break; - case 8: - XMEMMOVE(cfb->pad, cfb->pad + 1, cfb->ecb.blocklen - 1); - cfb->pad[cfb->ecb.blocklen - 1] = (*ct = *pt ^ cfb->IV[0]); - ++pt; - ++ct; - cfb->padlen = cfb->ecb.blocklen; - break; - case 64: - case 128: - cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); - ++pt; - ++ct; - ++(cfb->padlen); - break; - } - bitlen -= bits_per_round; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_getiv.c deleted file mode 100644 index 75ce264..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_getiv.c - CFB implementation, get IV, Tom St Denis -*/ - -#ifdef LTC_CFB_MODE - -/** - Get the current initialization vector - @param IV [out] The destination of the initialization vector - @param len [in/out] The max size and resulting size of the initialization vector - @param cfb The CFB state - @return CRYPT_OK if successful -*/ -int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(cfb != NULL); - if ((unsigned long)cfb->ecb.blocklen > *len) { - *len = cfb->ecb.blocklen; - return CRYPT_BUFFER_OVERFLOW; - } - XMEMCPY(IV, cfb->pad, cfb->ecb.blocklen); - *len = cfb->ecb.blocklen; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_setiv.c deleted file mode 100644 index 1758d64..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_setiv.c +++ /dev/null @@ -1,41 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_setiv.c - CFB implementation, set IV, Tom St Denis -*/ - -#ifdef LTC_CFB_MODE - -/** - Set an initialization vector - @param IV The initialization vector - @param len The length of the vector (in octets) - @param cfb The CFB state - @return CRYPT_OK if successful -*/ -int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb) -{ - int err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(cfb != NULL); - - if ((err = cipher_is_valid(cfb->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (len != (unsigned long)cfb->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } - - /* force next block */ - cfb->padlen = 0; - XMEMCPY(cfb->pad, IV, len); - return ecb_encrypt_block(IV, cfb->IV, &cfb->ecb); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_start.c b/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_start.c deleted file mode 100644 index 8b78b34..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/cfb/cfb_start.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file cfb_start.c - CFB implementation, start chain, Tom St Denis -*/ - - -#ifdef LTC_CFB_MODE - - -/** - Extended initialization of a CFB context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param width The width of the mode in bits (0 for default) - @param cfb The CFB state to initialize - @return CRYPT_OK if successful -*/ -int cfb_start_ex(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, int width, symmetric_CFB *cfb) -{ - int x, err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(cfb != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - switch (width) { - case 0: - width = cipher_descriptor[cipher].block_length * 8; - break; - case 1: - case 8: - LTC_ARGCHK(cipher_descriptor[cipher].block_length == 8 - || cipher_descriptor[cipher].block_length == 16); - break; - case 64: - case 128: - LTC_ARGCHK(width == cipher_descriptor[cipher].block_length * 8); - break; - default: - return CRYPT_INVALID_ARG; - } - - cfb->width = width; - /* init the cipher */ - if ((err = ecb_start(cipher, key, keylen, num_rounds, &cfb->ecb)) != CRYPT_OK) { - return err; - } - /* copy data */ - for (x = 0; x < cfb->ecb.blocklen; x++) { - cfb->pad[x] = IV[x]; - } - - /* encrypt the IV */ - cfb->padlen = 0; - return ecb_encrypt_block(cfb->pad, cfb->IV, &cfb->ecb); -} - -/** - Initialize a CFB context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param cfb The CFB state to initialize - @return CRYPT_OK if successful -*/ -int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CFB *cfb) -{ - return cfb_start_ex(cipher, IV, key, keylen, num_rounds, 0, cfb); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_decrypt.c deleted file mode 100644 index a55a08f..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_decrypt.c +++ /dev/null @@ -1,30 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_decrypt.c - CTR implementation, decrypt data, Tom St Denis -*/ - -#ifdef LTC_CTR_MODE - -/** - CTR decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len Length of ciphertext (octets) - @param ctr CTR state - @return CRYPT_OK if successful -*/ -int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ctr != NULL); - - return ctr_encrypt(ct, pt, len, ctr); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_done.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_done.c deleted file mode 100644 index 670c63b..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_done.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_done.c - CTR implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_CTR_MODE - -/** Terminate the chain - @param ctr The CTR chain to terminate - @return CRYPT_OK on success -*/ -int ctr_done(symmetric_CTR *ctr) -{ - LTC_ARGCHK(ctr != NULL); - - return ecb_done(&ctr->ecb); -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_encrypt.c deleted file mode 100644 index 2859574..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_encrypt.c +++ /dev/null @@ -1,129 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_encrypt.c - CTR implementation, encrypt data, Tom St Denis -*/ - - -#ifdef LTC_CTR_MODE - -/** - CTR encrypt software implementation - @param pt Plaintext - @param ct [out] Ciphertext - @param len Length of plaintext (octets) - @param ctr CTR state - @return CRYPT_OK if successful -*/ -static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) -{ - int x, err; - - while (len) { - /* is the pad empty? */ - if (ctr->padlen == ctr->ecb.blocklen) { - /* increment counter */ - if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { - /* little-endian */ - for (x = 0; x < ctr->ctrlen; x++) { - ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; - if (ctr->ctr[x] != (unsigned char)0) { - break; - } - } - } else { - /* big-endian */ - for (x = ctr->ecb.blocklen-1; x >= ctr->ctrlen; x--) { - ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; - if (ctr->ctr[x] != (unsigned char)0) { - break; - } - } - } - - /* encrypt it */ - if ((err = ecb_encrypt_block(ctr->ctr, ctr->pad, &ctr->ecb)) != CRYPT_OK) { - return err; - } - ctr->padlen = 0; - } -#ifdef LTC_FAST - if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->ecb.blocklen)) { - for (x = 0; x < ctr->ecb.blocklen; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^ - *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x)); - } - pt += ctr->ecb.blocklen; - ct += ctr->ecb.blocklen; - len -= ctr->ecb.blocklen; - ctr->padlen = ctr->ecb.blocklen; - continue; - } -#endif - *ct++ = *pt++ ^ ctr->pad[ctr->padlen++]; - --len; - } - return CRYPT_OK; -} - -/** - CTR encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len Length of plaintext (octets) - @param ctr CTR state - @return CRYPT_OK if successful -*/ -int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) -{ - int err, fr; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ctr != NULL); - - if ((err = cipher_is_valid(ctr->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if ((ctr->ecb.blocklen < 1) || (ctr->ecb.blocklen > (int)sizeof(ctr->ctr)) || - (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (ctr->ecb.blocklen % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ - if ((cipher_descriptor[ctr->ecb.cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->ecb.blocklen)) { - if (ctr->padlen < ctr->ecb.blocklen) { - fr = ctr->ecb.blocklen - ctr->padlen; - if ((err = s_ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) { - return err; - } - pt += fr; - ct += fr; - len -= fr; - } - - if (len >= (unsigned long)ctr->ecb.blocklen) { - if ((err = cipher_descriptor[ctr->ecb.cipher].accel_ctr_encrypt(pt, ct, len/ctr->ecb.blocklen, ctr->ctr, ctr->mode, &ctr->ecb.key)) != CRYPT_OK) { - return err; - } - pt += (len / ctr->ecb.blocklen) * ctr->ecb.blocklen; - ct += (len / ctr->ecb.blocklen) * ctr->ecb.blocklen; - len %= ctr->ecb.blocklen; - } - } - - return s_ctr_encrypt(pt, ct, len, ctr); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_getiv.c deleted file mode 100644 index 7704a7f..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_getiv.c - CTR implementation, get IV, Tom St Denis -*/ - -#ifdef LTC_CTR_MODE - -/** - Get the current initialization vector - @param IV [out] The destination of the initialization vector - @param len [in/out] The max size and resulting size of the initialization vector - @param ctr The CTR state - @return CRYPT_OK if successful -*/ -int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(ctr != NULL); - if ((unsigned long)ctr->ecb.blocklen > *len) { - *len = ctr->ecb.blocklen; - return CRYPT_BUFFER_OVERFLOW; - } - XMEMCPY(IV, ctr->ctr, ctr->ecb.blocklen); - *len = ctr->ecb.blocklen; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_setiv.c deleted file mode 100644 index 75ea1ab..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_setiv.c +++ /dev/null @@ -1,44 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_setiv.c - CTR implementation, set IV, Tom St Denis -*/ - -#ifdef LTC_CTR_MODE - -/** - Set an initialization vector - @param IV The initialization vector - @param len The length of the vector (in octets) - @param ctr The CTR state - @return CRYPT_OK if successful -*/ -int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr) -{ - int err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(ctr != NULL); - - /* bad param? */ - if ((err = cipher_is_valid(ctr->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (len != (unsigned long)ctr->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } - - /* set IV */ - XMEMCPY(ctr->ctr, IV, len); - - /* force next block */ - ctr->padlen = 0; - return ecb_encrypt_block(IV, ctr->pad, &ctr->ecb); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_start.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_start.c deleted file mode 100644 index 03b18a4..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_start.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_start.c - CTR implementation, start chain, Tom St Denis -*/ - - -#ifdef LTC_CTR_MODE - -/** - Initialize a CTR context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN) - @param ctr The CTR state to initialize - @return CRYPT_OK if successful -*/ -int ctr_start( int cipher, - const unsigned char *IV, - const unsigned char *key, int keylen, - int num_rounds, int ctr_mode, - symmetric_CTR *ctr) -{ - int x, err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ctr != NULL); - - /* bad param? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* ctrlen == counter width */ - ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length; - if (ctr->ctrlen > cipher_descriptor[cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) { - ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen; - } - - /* setup cipher */ - if ((err = ecb_start(cipher, key, keylen, num_rounds, &ctr->ecb)) != CRYPT_OK) { - return err; - } - - /* copy ctr */ - ctr->padlen = 0; - ctr->mode = ctr_mode & 0x1000; - for (x = 0; x < ctr->ecb.blocklen; x++) { - ctr->ctr[x] = IV[x]; - } - - if (ctr_mode & LTC_CTR_RFC3686) { - /* increment the IV as per RFC 3686 */ - if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { - /* little-endian */ - for (x = 0; x < ctr->ctrlen; x++) { - ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; - if (ctr->ctr[x] != (unsigned char)0) { - break; - } - } - } else { - /* big-endian */ - for (x = ctr->ecb.blocklen-1; x >= ctr->ctrlen; x--) { - ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; - if (ctr->ctr[x] != (unsigned char)0) { - break; - } - } - } - } - - return ecb_encrypt_block(ctr->ctr, ctr->pad, &ctr->ecb); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_test.c b/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_test.c deleted file mode 100644 index 48c9498..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ctr/ctr_test.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ctr_test.c - CTR implementation, Tests again RFC 3686, Tom St Denis -*/ - -#ifdef LTC_CTR_MODE - -int ctr_test(void) -{ -#ifdef LTC_NO_TEST - return CRYPT_NOP; -#else - static const struct { - int keylen, msglen; - unsigned char key[32], IV[16], pt[64], ct[64]; - } tests[] = { -/* 128-bit key, 16-byte pt */ -{ - 16, 16, - {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E }, - {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 }, - {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 }, -}, - -/* 128-bit key, 36-byte pt */ -{ - 16, 36, - {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC }, - {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 }, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, - 0x20,0x21,0x22,0x23}, - {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7, - 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53, - 0x25,0xB2,0x07,0x2F }, -}, -}; - int idx, err, x; - unsigned char buf[64]; - symmetric_CTR ctr; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - if ((err = ctr_start(idx, tests[x].IV, tests[x].key, tests[x].keylen, 0, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) { - return err; - } - if ((err = ctr_encrypt(tests[x].pt, buf, tests[x].msglen, &ctr)) != CRYPT_OK) { - return err; - } - ctr_done(&ctr); - if (compare_testvector(buf, tests[x].msglen, tests[x].ct, tests[x].msglen, "CTR", x)) { - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#endif - - - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_decrypt.c deleted file mode 100644 index b8a48b0..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_decrypt.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ecb_decrypt.c - ECB implementation, decrypt a block, Tom St Denis -*/ - -#ifdef LTC_ECB_MODE -int ecb_decrypt_block(const unsigned char *ct, unsigned char *pt, const symmetric_ECB *ecb) -{ - /* check for accel */ - if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) { - return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, 1, &ecb->key); - } - return cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key); -} - -/** - ECB decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len The number of octets to process (must be multiple of the cipher block size) - @param ecb ECB state - @return CRYPT_OK if successful -*/ -int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, const symmetric_ECB *ecb) -{ - int err; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ecb != NULL); - if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { - return err; - } - if (len % cipher_descriptor[ecb->cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - /* check for accel */ - if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) { - return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); - } - while (len) { - if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) { - return err; - } - pt += cipher_descriptor[ecb->cipher].block_length; - ct += cipher_descriptor[ecb->cipher].block_length; - len -= cipher_descriptor[ecb->cipher].block_length; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_done.c b/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_done.c deleted file mode 100644 index e1c0c59..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_done.c +++ /dev/null @@ -1,30 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ecb_done.c - ECB implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_ECB_MODE - -/** Terminate the chain - @param ecb The ECB chain to terminate - @return CRYPT_OK on success -*/ -int ecb_done(symmetric_ECB *ecb) -{ - int err; - LTC_ARGCHK(ecb != NULL); - - if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { - return err; - } - cipher_descriptor[ecb->cipher].done(&ecb->key); - return CRYPT_OK; -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_encrypt.c deleted file mode 100644 index 07e8672..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_encrypt.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ecb_encrypt.c - ECB implementation, encrypt a block, Tom St Denis -*/ - -#ifdef LTC_ECB_MODE -int ecb_encrypt_block(const unsigned char *pt, unsigned char *ct, const symmetric_ECB *ecb) -{ - /* check for accel */ - if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) { - return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, 1, &ecb->key); - } - return cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key); -} - -/** - ECB encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len The number of octets to process (must be multiple of the cipher block size) - @param ecb ECB state - @return CRYPT_OK if successful -*/ -int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, const symmetric_ECB *ecb) -{ - int err; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ecb != NULL); - if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { - return err; - } - if (len % cipher_descriptor[ecb->cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - /* check for accel */ - if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) { - return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); - } - while (len) { - if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) { - return err; - } - pt += cipher_descriptor[ecb->cipher].block_length; - ct += cipher_descriptor[ecb->cipher].block_length; - len -= cipher_descriptor[ecb->cipher].block_length; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_start.c b/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_start.c deleted file mode 100644 index d5bc28e..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ecb/ecb_start.c +++ /dev/null @@ -1,36 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ecb_start.c - ECB implementation, start chain, Tom St Denis -*/ - - -#ifdef LTC_ECB_MODE - -/** - Initialize a ECB context - @param cipher The index of the cipher desired - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param ecb The ECB state to initialize - @return CRYPT_OK if successful -*/ -int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb) -{ - int err; - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ecb != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - ecb->cipher = cipher; - ecb->blocklen = cipher_descriptor[cipher].block_length; - return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_decrypt.c deleted file mode 100644 index f9e3a54..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_decrypt.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_decrypt.c - F8 implementation, decrypt data, Tom St Denis -*/ - -#ifdef LTC_F8_MODE - -/** - F8 decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len Length of ciphertext (octets) - @param f8 F8 state - @return CRYPT_OK if successful -*/ -int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(f8 != NULL); - return f8_encrypt(ct, pt, len, f8); -} - - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_done.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_done.c deleted file mode 100644 index 78ee9fe..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_done.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_done.c - F8 implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_F8_MODE - -/** Terminate the chain - @param f8 The F8 chain to terminate - @return CRYPT_OK on success -*/ -int f8_done(symmetric_F8 *f8) -{ - LTC_ARGCHK(f8 != NULL); - - return ecb_done(&f8->ecb); -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_encrypt.c deleted file mode 100644 index ec147fd..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_encrypt.c +++ /dev/null @@ -1,91 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_encrypt.c - F8 implementation, encrypt data, Tom St Denis -*/ - -#ifdef LTC_F8_MODE - -/** - F8 encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len Length of plaintext (octets) - @param f8 F8 state - @return CRYPT_OK if successful -*/ -int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8) -{ - int err, x; - unsigned char buf[MAXBLOCKSIZE]; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(f8 != NULL); - if ((err = cipher_is_valid(f8->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (f8->ecb.blocklen < 0 || f8->ecb.blocklen > (int)sizeof(f8->IV) || - f8->padlen < 0 || f8->padlen > (int)sizeof(f8->IV)) { - return CRYPT_INVALID_ARG; - } - - zeromem(buf, sizeof(buf)); - - /* make sure the pad is empty */ - if (f8->padlen == f8->ecb.blocklen) { - /* xor of IV, MIV and blockcnt == what goes into cipher */ - STORE32H(f8->blockcnt, (buf+(f8->ecb.blocklen-4))); - ++(f8->blockcnt); - for (x = 0; x < f8->ecb.blocklen; x++) { - f8->IV[x] ^= f8->MIV[x] ^ buf[x]; - } - if ((err = ecb_encrypt_block(f8->IV, f8->IV, &f8->ecb)) != CRYPT_OK) { - return err; - } - f8->padlen = 0; - } - -#ifdef LTC_FAST - if (f8->padlen == 0) { - while (len >= (unsigned long)f8->ecb.blocklen) { - STORE32H(f8->blockcnt, (buf+(f8->ecb.blocklen-4))); - ++(f8->blockcnt); - for (x = 0; x < f8->ecb.blocklen; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&ct[x])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])); - *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&f8->MIV[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&buf[x])); - } - if ((err = ecb_encrypt_block(f8->IV, f8->IV, &f8->ecb)) != CRYPT_OK) { - return err; - } - len -= x; - pt += x; - ct += x; - } - } -#endif - - while (len > 0) { - if (f8->padlen == f8->ecb.blocklen) { - /* xor of IV, MIV and blockcnt == what goes into cipher */ - STORE32H(f8->blockcnt, (buf+(f8->ecb.blocklen-4))); - ++(f8->blockcnt); - for (x = 0; x < f8->ecb.blocklen; x++) { - f8->IV[x] ^= f8->MIV[x] ^ buf[x]; - } - if ((err = ecb_encrypt_block(f8->IV, f8->IV, &f8->ecb)) != CRYPT_OK) { - return err; - } - f8->padlen = 0; - } - *ct++ = *pt++ ^ f8->IV[f8->padlen++]; - --len; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_getiv.c deleted file mode 100644 index a38ffde..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_getiv.c - F8 implementation, get IV, Tom St Denis -*/ - -#ifdef LTC_F8_MODE - -/** - Get the current initialization vector - @param IV [out] The destination of the initialization vector - @param len [in/out] The max size and resulting size of the initialization vector - @param f8 The F8 state - @return CRYPT_OK if successful -*/ -int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(f8 != NULL); - if ((unsigned long)f8->ecb.blocklen > *len) { - *len = f8->ecb.blocklen; - return CRYPT_BUFFER_OVERFLOW; - } - XMEMCPY(IV, f8->IV, f8->ecb.blocklen); - *len = f8->ecb.blocklen; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_setiv.c deleted file mode 100644 index fd5411e..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_setiv.c +++ /dev/null @@ -1,40 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_setiv.c - F8 implementation, set IV, Tom St Denis -*/ - -#ifdef LTC_F8_MODE - -/** - Set an initialization vector - @param IV The initialization vector - @param len The length of the vector (in octets) - @param f8 The F8 state - @return CRYPT_OK if successful -*/ -int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8) -{ - int err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(f8 != NULL); - - if ((err = cipher_is_valid(f8->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (len != (unsigned long)f8->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } - - /* force next block */ - f8->padlen = 0; - return ecb_encrypt_block(IV, f8->IV, &f8->ecb); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_start.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_start.c deleted file mode 100644 index cb60803..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_start.c +++ /dev/null @@ -1,84 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_start.c - F8 implementation, start chain, Tom St Denis -*/ - - -#ifdef LTC_F8_MODE - -/** - Initialize an F8 context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param salt_key The salting key for the IV - @param skeylen The length of the salting key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param f8 The F8 state to initialize - @return CRYPT_OK if successful -*/ -int f8_start( int cipher, const unsigned char *IV, - const unsigned char *key, int keylen, - const unsigned char *salt_key, int skeylen, - int num_rounds, symmetric_F8 *f8) -{ - int x, err; - unsigned char tkey[MAXBLOCKSIZE]; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(salt_key != NULL); - LTC_ARGCHK(f8 != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_FAST - if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* copy details */ - f8->blockcnt = 0; - f8->padlen = cipher_descriptor[cipher].block_length; - - /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */ - zeromem(tkey, sizeof(tkey)); - for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) { - tkey[x] = key[x]; - } - for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) { - tkey[x] ^= salt_key[x]; - } - for (; x < keylen && x < (int)sizeof(tkey); x++) { - tkey[x] ^= 0x55; - } - - /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */ - if ((err = ecb_start(cipher, tkey, keylen, num_rounds, &f8->ecb)) != CRYPT_OK) { - return err; - } - - /* encrypt IV */ - if ((err = ecb_encrypt_block(IV, f8->MIV, &f8->ecb)) != CRYPT_OK) { - ecb_done(&f8->ecb); - return err; - } - zeromem(tkey, sizeof(tkey)); - zeromem(f8->IV, sizeof(f8->IV)); - - /* terminate this cipher */ - ecb_done(&f8->ecb); - - /* init the cipher */ - return ecb_start(cipher, key, keylen, num_rounds, &f8->ecb); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_test_mode.c b/Sources/DataLiteC/libtomcrypt/modes/f8/f8_test_mode.c deleted file mode 100644 index 7b25175..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/f8/f8_test_mode.c +++ /dev/null @@ -1,64 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file f8_test_mode.c - F8 implementation, test, Tom St Denis -*/ - - -#ifdef LTC_F8_MODE - -int f8_test_mode(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const unsigned char key[16] = { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18, - 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c }; - static const unsigned char salt[4] = { 0x32, 0xf2, 0x87, 0x0d }; - static const unsigned char IV[16] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5, - 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a }; - static const unsigned char pt[39] = { 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, - 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, - 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73, - 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67 }; - static const unsigned char ct[39] = { 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01, - 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd, - 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4, - 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f, - 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02 }; - unsigned char buf[39]; - symmetric_F8 f8; - int err, idx; - - idx = find_cipher("aes"); - if (idx == -1) { - idx = find_cipher("rijndael"); - if (idx == -1) return CRYPT_NOP; - } - - /* initialize the context */ - if ((err = f8_start(idx, IV, key, sizeof(key), salt, sizeof(salt), 0, &f8)) != CRYPT_OK) { - return err; - } - - /* encrypt block */ - if ((err = f8_encrypt(pt, buf, sizeof(pt), &f8)) != CRYPT_OK) { - f8_done(&f8); - return err; - } - f8_done(&f8); - - /* compare */ - if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "f8", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_decrypt.c deleted file mode 100644 index b4f4059..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_decrypt.c +++ /dev/null @@ -1,39 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_decrypt.c - LRW_MODE implementation, Decrypt blocks, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - LRW decrypt blocks - @param ct The ciphertext - @param pt [out] The plaintext - @param len The length in octets, must be a multiple of 16 - @param lrw The LRW state -*/ -int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw) -{ - int err; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(lrw != NULL); - - if ((err = cipher_is_valid(lrw->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (cipher_descriptor[lrw->ecb.cipher].accel_lrw_decrypt != NULL) { - return cipher_descriptor[lrw->ecb.cipher].accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->ecb.key); - } - - return lrw_process(ct, pt, len, LRW_DECRYPT, lrw); -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_done.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_done.c deleted file mode 100644 index 83ad5f3..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_done.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_done.c - LRW_MODE implementation, Free resources, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Terminate a LRW state - @param lrw The state to terminate - @return CRYPT_OK if successful -*/ -int lrw_done(symmetric_LRW *lrw) -{ - LTC_ARGCHK(lrw != NULL); - - return ecb_done(&lrw->ecb); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_encrypt.c deleted file mode 100644 index 7c8e1ba..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_encrypt.c +++ /dev/null @@ -1,39 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_encrypt.c - LRW_MODE implementation, Encrypt blocks, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - LRW encrypt blocks - @param pt The plaintext - @param ct [out] The ciphertext - @param len The length in octets, must be a multiple of 16 - @param lrw The LRW state -*/ -int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw) -{ - int err; - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(lrw != NULL); - - if ((err = cipher_is_valid(lrw->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (cipher_descriptor[lrw->ecb.cipher].accel_lrw_encrypt != NULL) { - return cipher_descriptor[lrw->ecb.cipher].accel_lrw_encrypt(pt, ct, len, lrw->IV, lrw->tweak, &lrw->ecb.key); - } - - return lrw_process(pt, ct, len, LRW_ENCRYPT, lrw); -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_getiv.c deleted file mode 100644 index 9da1aab..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_getiv.c - LRW_MODE implementation, Retrieve the current IV, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Get the IV for LRW - @param IV [out] The IV, must be 16 octets - @param len Length ... must be at least 16 :-) - @param lrw The LRW state to read - @return CRYPT_OK if successful -*/ -int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(lrw != NULL); - if (*len < 16) { - *len = 16; - return CRYPT_BUFFER_OVERFLOW; - } - - XMEMCPY(IV, lrw->IV, 16); - *len = 16; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_process.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_process.c deleted file mode 100644 index a04f90d..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_process.c +++ /dev/null @@ -1,109 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_process.c - LRW_MODE implementation, Encrypt/decrypt blocks, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Process blocks with LRW, since decrypt/encrypt are largely the same they share this code. - @param pt The "input" data - @param ct [out] The "output" data - @param len The length of the input, must be a multiple of 128-bits (16 octets) - @param mode LRW_ENCRYPT or LRW_DECRYPT - @param lrw The LRW state - @return CRYPT_OK if successful -*/ -int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw) -{ - unsigned char prod[16]; - int x, err; -#ifdef LTC_LRW_TABLES - int y; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(lrw != NULL); - - if (len & 15) { - return CRYPT_INVALID_ARG; - } - - while (len) { - /* copy pad */ - XMEMCPY(prod, lrw->pad, 16); - - /* increment IV */ - for (x = 15; x >= 0; x--) { - lrw->IV[x] = (lrw->IV[x] + 1) & 255; - if (lrw->IV[x]) { - break; - } - } - - /* update pad */ -#ifdef LTC_LRW_TABLES - /* for each byte changed we undo it's affect on the pad then add the new product */ - for (; x < 16; x++) { -#ifdef LTC_FAST - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(lrw->pad + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][lrw->IV[x]][y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][(lrw->IV[x]-1)&255][y])); - } -#else - for (y = 0; y < 16; y++) { - lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y]; - } -#endif - } -#else - gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad); -#endif - - /* xor prod */ -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); - } -#else - for (x = 0; x < 16; x++) { - ct[x] = pt[x] ^ prod[x]; - } -#endif - - /* send through cipher */ - if (mode == LRW_ENCRYPT) { - if ((err = ecb_encrypt_block(ct, ct, &lrw->ecb)) != CRYPT_OK) { - return err; - } - } else { - if ((err = ecb_decrypt_block(ct, ct, &lrw->ecb)) != CRYPT_OK) { - return err; - } - } - - /* xor prod */ -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(ct + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); - } -#else - for (x = 0; x < 16; x++) { - ct[x] = ct[x] ^ prod[x]; - } -#endif - - /* move to next */ - pt += 16; - ct += 16; - len -= 16; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_setiv.c deleted file mode 100644 index 72615e7..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_setiv.c +++ /dev/null @@ -1,68 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_setiv.c - LRW_MODE implementation, Set the current IV, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Set the IV for LRW - @param IV The IV, must be 16 octets - @param len Length ... must be 16 :-) - @param lrw The LRW state to update - @return CRYPT_OK if successful -*/ -int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw) -{ - int err; -#ifdef LTC_LRW_TABLES - unsigned char T[16]; - int x, y; -#endif - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(lrw != NULL); - - if (len != 16) { - return CRYPT_INVALID_ARG; - } - - if ((err = cipher_is_valid(lrw->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* copy the IV */ - XMEMCPY(lrw->IV, IV, 16); - - /* check if we have to actually do work */ - if (cipher_descriptor[lrw->ecb.cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->ecb.cipher].accel_lrw_decrypt != NULL) { - /* we have accelerators, let's bail since they don't use lrw->pad anyways */ - return CRYPT_OK; - } - -#ifdef LTC_LRW_TABLES - XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16); - for (x = 1; x < 16; x++) { -#ifdef LTC_FAST - for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][IV[x]][y])); - } -#else - for (y = 0; y < 16; y++) { - T[y] ^= lrw->PC[x][IV[x]][y]; - } -#endif - } - XMEMCPY(lrw->pad, T, 16); -#else - gcm_gf_mult(lrw->tweak, IV, lrw->pad); -#endif - - return CRYPT_OK; -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_start.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_start.c deleted file mode 100644 index fb0b95e..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_start.c +++ /dev/null @@ -1,92 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_start.c - LRW_MODE implementation, start mode, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Initialize the LRW context - @param cipher The cipher desired, must be a 128-bit block cipher - @param IV The index value, must be 128-bits - @param key The cipher key - @param keylen The length of the cipher key in octets - @param tweak The tweak value (second key), must be 128-bits - @param num_rounds The number of rounds for the cipher (0 == default) - @param lrw [out] The LRW state - @return CRYPT_OK on success. -*/ -int lrw_start( int cipher, - const unsigned char *IV, - const unsigned char *key, int keylen, - const unsigned char *tweak, - int num_rounds, - symmetric_LRW *lrw) -{ - int err; -#ifdef LTC_LRW_TABLES - unsigned char B[16]; - int x, y, z, t; -#endif - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(tweak != NULL); - LTC_ARGCHK(lrw != NULL); - -#ifdef LTC_FAST - if (16 % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* is cipher valid? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_CIPHER; - } - - /* schedule key */ - if ((err = ecb_start(cipher, key, keylen, num_rounds, &lrw->ecb)) != CRYPT_OK) { - return err; - } - lrw->ecb.cipher = cipher; - - /* copy the IV and tweak */ - XMEMCPY(lrw->tweak, tweak, 16); - -#ifdef LTC_LRW_TABLES - /* setup tables */ - /* generate the first table as it has no shifting (from which we make the other tables) */ - zeromem(B, 16); - for (y = 0; y < 256; y++) { - B[0] = y; - gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]); - } - - /* now generate the rest of the tables based the previous table */ - for (x = 1; x < 16; x++) { - for (y = 0; y < 256; y++) { - /* now shift it right by 8 bits */ - t = lrw->PC[x-1][y][15]; - for (z = 15; z > 0; z--) { - lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1]; - } - lrw->PC[x][y][0] = gcm_shift_table[t<<1]; - lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; - } - } -#endif - - /* generate first pad */ - return lrw_setiv(IV, 16, lrw); -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_test.c b/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_test.c deleted file mode 100644 index 893f88d..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/lrw/lrw_test.c +++ /dev/null @@ -1,124 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file lrw_test.c - LRW_MODE implementation, test LRW, Tom St Denis -*/ - -#ifdef LTC_LRW_MODE - -/** - Test LRW against specs - @return CRYPT_OK if goodly -*/ -int lrw_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16]; - } tests[] = { - -{ -{ 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 }, -{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, -{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, -{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, -{ 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 } -}, - -{ -{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, -{ 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc }, -{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, -{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, -{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, -}, - -{ -{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, -{ 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 }, -{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, -{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, -{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, -{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, -}, - -{ - -{ 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 }, -{ 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 }, -{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, -{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, -{ 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 }, -{ 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, - -} -}; - - int idx, err, x; - symmetric_LRW lrw; - unsigned char buf[2][16]; - - idx = find_cipher("aes"); - if (idx == -1) { - idx = find_cipher("rijndael"); - if (idx == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)LTC_ARRAY_SIZE(tests); x++) { - /* schedule it */ - if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) { - return err; - } - - /* check pad against expected tweak */ - if (compare_testvector(tests[x].expected_tweak, 16, lrw.pad, 16, "LRW Tweak", x)) { - lrw_done(&lrw); - return CRYPT_FAIL_TESTVECTOR; - } - - /* process block */ - if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) { - lrw_done(&lrw); - return err; - } - - if (compare_testvector(buf[0], 16, tests[x].C, 16, "LRW Encrypt", x)) { - lrw_done(&lrw); - return CRYPT_FAIL_TESTVECTOR; - } - - /* process block */ - if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) { - lrw_done(&lrw); - return err; - } - - if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) { - lrw_done(&lrw); - return err; - } - - if (compare_testvector(buf[1], 16, tests[x].P, 16, "LRW Decrypt", x)) { - lrw_done(&lrw); - return CRYPT_FAIL_TESTVECTOR; - } - if ((err = lrw_done(&lrw)) != CRYPT_OK) { - return err; - } - } - return CRYPT_OK; -#endif -} - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_decrypt.c deleted file mode 100644 index cebcd7b..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_decrypt.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_decrypt.c - OFB implementation, decrypt data, Tom St Denis -*/ - -#ifdef LTC_OFB_MODE - -/** - OFB decrypt - @param ct Ciphertext - @param pt [out] Plaintext - @param len Length of ciphertext (octets) - @param ofb OFB state - @return CRYPT_OK if successful -*/ -int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) -{ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ofb != NULL); - return ofb_encrypt(ct, pt, len, ofb); -} - - -#endif - - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_done.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_done.c deleted file mode 100644 index 15cf1f6..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_done.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_done.c - OFB implementation, finish chain, Tom St Denis -*/ - -#ifdef LTC_OFB_MODE - -/** Terminate the chain - @param ofb The OFB chain to terminate - @return CRYPT_OK on success -*/ -int ofb_done(symmetric_OFB *ofb) -{ - LTC_ARGCHK(ofb != NULL); - - return ecb_done(&ofb->ecb); -} - - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_encrypt.c deleted file mode 100644 index 211efcc..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_encrypt.c +++ /dev/null @@ -1,48 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_encrypt.c - OFB implementation, encrypt data, Tom St Denis -*/ - -#ifdef LTC_OFB_MODE - -/** - OFB encrypt - @param pt Plaintext - @param ct [out] Ciphertext - @param len Length of plaintext (octets) - @param ofb OFB state - @return CRYPT_OK if successful -*/ -int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb) -{ - int err; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ofb != NULL); - if ((err = cipher_is_valid(ofb->ecb.cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (ofb->ecb.blocklen < 0 || ofb->ecb.blocklen > (int)sizeof(ofb->IV) || - ofb->padlen < 0 || ofb->padlen > (int)sizeof(ofb->IV)) { - return CRYPT_INVALID_ARG; - } - - while (len-- > 0) { - if (ofb->padlen == ofb->ecb.blocklen) { - if ((err = ecb_encrypt_block(ofb->IV, ofb->IV, &ofb->ecb)) != CRYPT_OK) { - return err; - } - ofb->padlen = 0; - } - *ct++ = *pt++ ^ ofb->IV[(ofb->padlen)++]; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_getiv.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_getiv.c deleted file mode 100644 index 6a40c1b..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_getiv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_getiv.c - OFB implementation, get IV, Tom St Denis -*/ - -#ifdef LTC_OFB_MODE - -/** - Get the current initialization vector - @param IV [out] The destination of the initialization vector - @param len [in/out] The max size and resulting size of the initialization vector - @param ofb The OFB state - @return CRYPT_OK if successful -*/ -int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb) -{ - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(len != NULL); - LTC_ARGCHK(ofb != NULL); - if ((unsigned long)ofb->ecb.blocklen > *len) { - *len = ofb->ecb.blocklen; - return CRYPT_BUFFER_OVERFLOW; - } - XMEMCPY(IV, ofb->IV, ofb->ecb.blocklen); - *len = ofb->ecb.blocklen; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_setiv.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_setiv.c deleted file mode 100644 index 9a06cc5..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_setiv.c +++ /dev/null @@ -1,40 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_setiv.c - OFB implementation, set IV, Tom St Denis -*/ - -#ifdef LTC_OFB_MODE - -/** - Set an initialization vector - @param IV The initialization vector - @param len The length of the vector (in octets) - @param ofb The OFB state - @return CRYPT_OK if successful -*/ -int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb) -{ - int err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(ofb != NULL); - - if ((err = cipher_is_valid(ofb->ecb.cipher)) != CRYPT_OK) { - return err; - } - - if (len != (unsigned long)ofb->ecb.blocklen) { - return CRYPT_INVALID_ARG; - } - - /* force next block */ - ofb->padlen = 0; - return ecb_encrypt_block(IV, ofb->IV, &ofb->ecb); -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_start.c b/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_start.c deleted file mode 100644 index 2998f3f..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/ofb/ofb_start.c +++ /dev/null @@ -1,50 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ofb_start.c - OFB implementation, start chain, Tom St Denis -*/ - - -#ifdef LTC_OFB_MODE - -/** - Initialize a OFB context - @param cipher The index of the cipher desired - @param IV The initialization vector - @param key The secret key - @param keylen The length of the secret key (octets) - @param num_rounds Number of rounds in the cipher desired (0 for default) - @param ofb The OFB state to initialize - @return CRYPT_OK if successful -*/ -int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_OFB *ofb) -{ - int x, err; - - LTC_ARGCHK(IV != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ofb != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* init the cipher */ - if ((err = ecb_start(cipher, key, keylen, num_rounds, &ofb->ecb)) != CRYPT_OK) { - return err; - } - ofb->padlen = cipher_descriptor[cipher].block_length; - - /* copy details */ - for (x = 0; x < ofb->ecb.blocklen; x++) { - ofb->IV[x] = IV[x]; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_decrypt.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_decrypt.c deleted file mode 100644 index 50019b9..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_decrypt.c +++ /dev/null @@ -1,146 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects - */ - -#ifdef LTC_XTS_MODE - -static int s_tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, const symmetric_xts *xts) -{ - unsigned long x; - int err; - - /* tweak encrypt block i */ -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&P[x])) = *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); - } -#else - for (x = 0; x < 16; x++) { - P[x] = C[x] ^ T[x]; - } -#endif - - err = ecb_decrypt_block(P, P, &xts->key1); - -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); - } -#else - for (x = 0; x < 16; x++) { - P[x] = P[x] ^ T[x]; - } -#endif - - /* LFSR the tweak */ - xts_mult_x(T); - - return err; -} - -/** XTS Decryption - @param ct [in] Ciphertext - @param ptlen Length of plaintext (and ciphertext) - @param pt [out] Plaintext - @param tweak [in] The 128--bit encryption tweak (e.g. sector number) - @param xts The XTS structure - Returns CRYPT_OK upon success - */ -int xts_decrypt(const unsigned char *ct, unsigned long ptlen, unsigned char *pt, unsigned char *tweak, - const symmetric_xts *xts) -{ - unsigned char PP[16] = {0}, CC[16], T[16]; - unsigned long i, m, mo, lim; - int err; - - /* check inputs */ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tweak != NULL); - LTC_ARGCHK(xts != NULL); - - /* check if valid */ - if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { - return err; - } - - /* get number of blocks */ - m = ptlen >> 4; - mo = ptlen & 15; - - /* must have at least one full block */ - if (m == 0) { - return CRYPT_INVALID_ARG; - } - - if (mo == 0) { - lim = m; - } else { - lim = m - 1; - } - - if (cipher_descriptor[xts->cipher].accel_xts_decrypt && lim > 0) { - - /* use accelerated decryption for whole blocks */ - if ((err = cipher_descriptor[xts->cipher].accel_xts_decrypt(ct, pt, lim, tweak, &xts->key1.key, &xts->key2.key)) != - CRYPT_OK) { - return err; - } - ct += lim * 16; - pt += lim * 16; - - /* tweak is encrypted on output */ - XMEMCPY(T, tweak, sizeof(T)); - } else { - /* encrypt the tweak */ - if ((err = ecb_encrypt_block(tweak, T, &xts->key2)) != CRYPT_OK) { - return err; - } - - for (i = 0; i < lim; i++) { - if ((err = s_tweak_uncrypt(ct, pt, T, xts)) != CRYPT_OK) { - return err; - } - ct += 16; - pt += 16; - } - } - - /* if ptlen not divide 16 then */ - if (mo > 0) { - XMEMCPY(CC, T, 16); - xts_mult_x(CC); - - /* PP = tweak decrypt block m-1 */ - if ((err = s_tweak_uncrypt(ct, PP, CC, xts)) != CRYPT_OK) { - return err; - } - - /* Pm = first ptlen % 16 bytes of PP */ - for (i = 0; i < mo; i++) { - CC[i] = ct[16 + i]; - pt[16 + i] = PP[i]; - } - for (; i < 16; i++) { - CC[i] = PP[i]; - } - - /* Pm-1 = Tweak uncrypt CC */ - if ((err = s_tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) { - return err; - } - } - - /* Decrypt the tweak back */ - if ((err = ecb_decrypt_block(T, tweak, &xts->key2)) != CRYPT_OK) { - return err; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_done.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_done.c deleted file mode 100644 index dd7ed25..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_done.c +++ /dev/null @@ -1,21 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects -*/ - -#ifdef LTC_XTS_MODE - -/** Terminate XTS state - @param xts The state to terminate -*/ -void xts_done(symmetric_xts *xts) -{ - LTC_ARGCHKVD(xts != NULL); - ecb_done(&xts->key1); - ecb_done(&xts->key2); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_encrypt.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_encrypt.c deleted file mode 100644 index 65b129c..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_encrypt.c +++ /dev/null @@ -1,147 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects - */ - -#ifdef LTC_XTS_MODE - -static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const symmetric_xts *xts) -{ - unsigned long x; - int err; - - /* tweak encrypt block i */ -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); - } -#else - for (x = 0; x < 16; x++) { - C[x] = P[x] ^ T[x]; - } -#endif - - if ((err = ecb_encrypt_block(C, C, &xts->key1)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_FAST - for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { - *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); - } -#else - for (x = 0; x < 16; x++) { - C[x] = C[x] ^ T[x]; - } -#endif - - /* LFSR the tweak */ - xts_mult_x(T); - - return CRYPT_OK; -} - -/** XTS Encryption - @param pt [in] Plaintext - @param ptlen Length of plaintext (and ciphertext) - @param ct [out] Ciphertext - @param tweak [in] The 128--bit encryption tweak (e.g. sector number) - @param xts The XTS structure - Returns CRYPT_OK upon success - */ -int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak, - const symmetric_xts *xts) -{ - unsigned char PP[16], CC[16] = {0}, T[16]; - unsigned long i, m, mo, lim; - int err; - - /* check inputs */ - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(tweak != NULL); - LTC_ARGCHK(xts != NULL); - - /* check if valid */ - if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { - return err; - } - - /* get number of blocks */ - m = ptlen >> 4; - mo = ptlen & 15; - - /* must have at least one full block */ - if (m == 0) { - return CRYPT_INVALID_ARG; - } - - if (mo == 0) { - lim = m; - } else { - lim = m - 1; - } - - if (cipher_descriptor[xts->cipher].accel_xts_encrypt && lim > 0) { - - /* use accelerated encryption for whole blocks */ - if ((err = cipher_descriptor[xts->cipher].accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1.key, &xts->key2.key)) != - CRYPT_OK) { - return err; - } - ct += lim * 16; - pt += lim * 16; - - /* tweak is encrypted on output */ - XMEMCPY(T, tweak, sizeof(T)); - } else { - - /* encrypt the tweak */ - if ((err = ecb_encrypt_block(tweak, T, &xts->key2)) != CRYPT_OK) { - return err; - } - - for (i = 0; i < lim; i++) { - if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) { - return err; - } - ct += 16; - pt += 16; - } - } - - /* if ptlen not divide 16 then */ - if (mo > 0) { - /* CC = tweak encrypt block m-1 */ - if ((err = s_tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { - return err; - } - - /* Cm = first ptlen % 16 bytes of CC */ - for (i = 0; i < mo; i++) { - PP[i] = pt[16 + i]; - ct[16 + i] = CC[i]; - } - - for (; i < 16; i++) { - PP[i] = CC[i]; - } - - /* Cm-1 = Tweak encrypt PP */ - if ((err = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { - return err; - } - } - - /* Decrypt the tweak back */ - if ((err = ecb_decrypt_block(T, tweak, &xts->key2)) != CRYPT_OK) { - return err; - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_init.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_init.c deleted file mode 100644 index b523467..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_init.c +++ /dev/null @@ -1,57 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects -*/ - -#ifdef LTC_XTS_MODE - -/** Start XTS mode - @param cipher The index of the cipher to use - @param key1 The encrypt key - @param key2 The tweak encrypt key - @param keylen The length of the keys (each) in octets - @param num_rounds The number of rounds for the cipher (0 == default) - @param xts [out] XTS structure - Returns CRYPT_OK upon success. -*/ -int xts_start(int cipher, const unsigned char *key1, const unsigned char *key2, unsigned long keylen, int num_rounds, - symmetric_xts *xts) -{ - int err; - - /* check inputs */ - LTC_ARGCHK(key1 != NULL); - LTC_ARGCHK(key2 != NULL); - LTC_ARGCHK(xts != NULL); - - /* check if valid */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - if (cipher_descriptor[cipher].block_length != 16) { - return CRYPT_INVALID_ARG; - } - - /* schedule the two ciphers */ - if ((err = ecb_start(cipher, key1, keylen, num_rounds, &xts->key1)) != CRYPT_OK) { - return err; - } - if ((err = ecb_start(cipher, key2, keylen, num_rounds, &xts->key2)) != CRYPT_OK) { - return err; - } - xts->cipher = cipher; - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_mult_x.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_mult_x.c deleted file mode 100644 index 20947a5..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_mult_x.c +++ /dev/null @@ -1,29 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects -*/ - -#ifdef LTC_XTS_MODE - -/** multiply by x - @param I The value to multiply by x (LFSR shift) -*/ -void xts_mult_x(unsigned char *I) -{ - int x; - unsigned char t, tt; - - for (x = t = 0; x < 16; x++) { - tt = I[x] >> 7; - I[x] = ((I[x] << 1) | t) & 0xFF; - t = tt; - } - if (tt) { - I[0] ^= 0x87; - } -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_test.c b/Sources/DataLiteC/libtomcrypt/modes/xts/xts_test.c deleted file mode 100644 index 90e5bdf..0000000 --- a/Sources/DataLiteC/libtomcrypt/modes/xts/xts_test.c +++ /dev/null @@ -1,300 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_XTS_MODE - -#ifndef LTC_NO_TEST -static int s_xts_test_accel_xts_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long blocks, - unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) -{ - int ret; - symmetric_xts xts; - int (*orig)(const unsigned char *, unsigned char *, - unsigned long , unsigned char *, - const symmetric_key *, const symmetric_key *); - - /* AES can be under rijndael or aes... try to find it */ - if ((xts.cipher = find_cipher("aes")) == -1) { - if ((xts.cipher = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - orig = cipher_descriptor[xts.cipher].accel_xts_encrypt; - cipher_descriptor[xts.cipher].accel_xts_encrypt = NULL; - - XMEMCPY(&xts.key1.key, skey1, sizeof(xts.key1)); - XMEMCPY(&xts.key2.key, skey2, sizeof(xts.key2)); - xts.key1.cipher = xts.key2.cipher = xts.cipher; - xts.key1.blocklen = xts.key2.blocklen = cipher_descriptor[xts.cipher].block_length; - - ret = xts_encrypt(pt, blocks << 4, ct, tweak, &xts); - cipher_descriptor[xts.cipher].accel_xts_encrypt = orig; - - return ret; -} - -static int s_xts_test_accel_xts_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long blocks, - unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) -{ - int ret; - symmetric_xts xts; - int (*orig)(const unsigned char *, unsigned char *, - unsigned long , unsigned char *, - const symmetric_key *, const symmetric_key *); - - /* AES can be under rijndael or aes... try to find it */ - if ((xts.cipher = find_cipher("aes")) == -1) { - if ((xts.cipher = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - orig = cipher_descriptor[xts.cipher].accel_xts_decrypt; - cipher_descriptor[xts.cipher].accel_xts_decrypt = NULL; - - XMEMCPY(&xts.key1.key, skey1, sizeof(xts.key1)); - XMEMCPY(&xts.key2.key, skey2, sizeof(xts.key2)); - xts.key1.cipher = xts.key2.cipher = xts.cipher; - xts.key1.blocklen = xts.key2.blocklen = cipher_descriptor[xts.cipher].block_length; - - ret = xts_decrypt(ct, blocks << 4, pt, tweak, &xts); - cipher_descriptor[xts.cipher].accel_xts_decrypt = orig; - - return ret; -} -#endif - -/** - Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects - - Returns CRYPT_OK upon success. -*/ -int xts_test(void) -{ -#ifdef LTC_NO_TEST - return CRYPT_NOP; -#else - static const struct - { - int keylen; - unsigned char key1[32]; - unsigned char key2[32]; - ulong64 seqnum; - unsigned long PTLEN; - unsigned char PTX[512], CTX[512]; - } tests[] = { - -/* #1 32 byte key, 32 byte PTX */ -{ - 32, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - 0, - 32, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x91,0x7c,0xf6,0x9e,0xbd,0x68,0xb2,0xec,0x9b,0x9f,0xe9,0xa3,0xea,0xdd,0xa6,0x92,0xcd,0x43,0xd2,0xf5,0x95,0x98,0xed,0x85,0x8c,0x02,0xc2,0x65,0x2f,0xbf,0x92,0x2e }, -}, - -/* #2, 32 byte key, 32 byte PTX */ -{ - 32, - { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 }, - { 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 }, - CONST64(0x3333333333), - 32, - { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, - { 0xc4,0x54,0x18,0x5e,0x6a,0x16,0x93,0x6e,0x39,0x33,0x40,0x38,0xac,0xef,0x83,0x8b,0xfb,0x18,0x6f,0xff,0x74,0x80,0xad,0xc4,0x28,0x93,0x82,0xec,0xd6,0xd3,0x94,0xf0 }, -}, - -/* #5 from xts.7, 32 byte key, 32 byte PTX */ -{ - 32, - { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, - { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, - CONST64(0x123456789a), - 32, - { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, - { 0xb0,0x1f,0x86,0xf8,0xed,0xc1,0x86,0x37,0x06,0xfa,0x8a,0x42,0x53,0xe3,0x4f,0x28,0xaf,0x31,0x9d,0xe3,0x83,0x34,0x87,0x0f,0x4d,0xd1,0xf9,0x4c,0xbe,0x98,0x32,0xf1 }, -}, - -/* #4, 32 byte key, 512 byte PTX */ -{ - 32, - { 0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26 }, - { 0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95 }, - 0, - 512, - { -0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, -0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, -0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, -0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, -0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, -0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, -0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, -0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, -0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, -0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, -0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, -0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, -0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, -0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, -0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, -0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, - }, - { -0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c, -0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12, -0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce, -0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65, -0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,0xa1,0x0c,0x42,0x11,0x10,0xe6,0xd8,0x15,0x88,0xed,0xe8,0x21,0x03,0xa2,0x52,0xd8, -0xa7,0x50,0xe8,0x76,0x8d,0xef,0xff,0xed,0x91,0x22,0x81,0x0a,0xae,0xb9,0x9f,0x91,0x72,0xaf,0x82,0xb6,0x04,0xdc,0x4b,0x8e,0x51,0xbc,0xb0,0x82,0x35,0xa6,0xf4,0x34, -0x13,0x32,0xe4,0xca,0x60,0x48,0x2a,0x4b,0xa1,0xa0,0x3b,0x3e,0x65,0x00,0x8f,0xc5,0xda,0x76,0xb7,0x0b,0xf1,0x69,0x0d,0xb4,0xea,0xe2,0x9c,0x5f,0x1b,0xad,0xd0,0x3c, -0x5c,0xcf,0x2a,0x55,0xd7,0x05,0xdd,0xcd,0x86,0xd4,0x49,0x51,0x1c,0xeb,0x7e,0xc3,0x0b,0xf1,0x2b,0x1f,0xa3,0x5b,0x91,0x3f,0x9f,0x74,0x7a,0x8a,0xfd,0x1b,0x13,0x0e, -0x94,0xbf,0xf9,0x4e,0xff,0xd0,0x1a,0x91,0x73,0x5c,0xa1,0x72,0x6a,0xcd,0x0b,0x19,0x7c,0x4e,0x5b,0x03,0x39,0x36,0x97,0xe1,0x26,0x82,0x6f,0xb6,0xbb,0xde,0x8e,0xcc, -0x1e,0x08,0x29,0x85,0x16,0xe2,0xc9,0xed,0x03,0xff,0x3c,0x1b,0x78,0x60,0xf6,0xde,0x76,0xd4,0xce,0xcd,0x94,0xc8,0x11,0x98,0x55,0xef,0x52,0x97,0xca,0x67,0xe9,0xf3, -0xe7,0xff,0x72,0xb1,0xe9,0x97,0x85,0xca,0x0a,0x7e,0x77,0x20,0xc5,0xb3,0x6d,0xc6,0xd7,0x2c,0xac,0x95,0x74,0xc8,0xcb,0xbc,0x2f,0x80,0x1e,0x23,0xe5,0x6f,0xd3,0x44, -0xb0,0x7f,0x22,0x15,0x4b,0xeb,0xa0,0xf0,0x8c,0xe8,0x89,0x1e,0x64,0x3e,0xd9,0x95,0xc9,0x4d,0x9a,0x69,0xc9,0xf1,0xb5,0xf4,0x99,0x02,0x7a,0x78,0x57,0x2a,0xee,0xbd, -0x74,0xd2,0x0c,0xc3,0x98,0x81,0xc2,0x13,0xee,0x77,0x0b,0x10,0x10,0xe4,0xbe,0xa7,0x18,0x84,0x69,0x77,0xae,0x11,0x9f,0x7a,0x02,0x3a,0xb5,0x8c,0xca,0x0a,0xd7,0x52, -0xaf,0xe6,0x56,0xbb,0x3c,0x17,0x25,0x6a,0x9f,0x6e,0x9b,0xf1,0x9f,0xdd,0x5a,0x38,0xfc,0x82,0xbb,0xe8,0x72,0xc5,0x53,0x9e,0xdb,0x60,0x9e,0xf4,0xf7,0x9c,0x20,0x3e, -0xbb,0x14,0x0f,0x2e,0x58,0x3c,0xb2,0xad,0x15,0xb4,0xaa,0x5b,0x65,0x50,0x16,0xa8,0x44,0x92,0x77,0xdb,0xd4,0x77,0xef,0x2c,0x8d,0x6c,0x01,0x7d,0xb7,0x38,0xb1,0x8d, -0xeb,0x4a,0x42,0x7d,0x19,0x23,0xce,0x3f,0xf2,0x62,0x73,0x57,0x79,0xa4,0x18,0xf2,0x0a,0x28,0x2d,0xf9,0x20,0x14,0x7b,0xea,0xbe,0x42,0x1e,0xe5,0x31,0x9d,0x05,0x68, - } -}, - -/* #7, 32 byte key, 17 byte PTX */ -{ - 32, - { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, - { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, - CONST64(0x123456789a), - 17, - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 }, - { 0x6c,0x16,0x25,0xdb,0x46,0x71,0x52,0x2d,0x3d,0x75,0x99,0x60,0x1d,0xe7,0xca,0x09,0xed }, -}, - -/* #15, 32 byte key, 25 byte PTX */ -{ - 32, - { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, - { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, - CONST64(0x123456789a), - 25, - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 }, - { 0x8f,0x4d,0xcb,0xad,0x55,0x55,0x8d,0x7b,0x4e,0x01,0xd9,0x37,0x9c,0xd4,0xea,0x22,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73 }, -}, - -/* #21, 32 byte key, 31 byte PTX */ -{ - 32, - { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, - { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, - CONST64(0x123456789a), - 31, - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e }, - { 0xd0,0x5b,0xc0,0x90,0xa8,0xe0,0x4f,0x1b,0x3d,0x3e,0xcd,0xd5,0xba,0xec,0x0f,0xd4,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73,0x06,0xe6,0x4b,0xe5,0xdd,0x82 }, -}, - -}; - unsigned char OUT[512], Torg[16], T[16]; - ulong64 seq; - symmetric_xts xts; - int i, j, k, err, idx; - unsigned long len; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - for (k = 0; k < 4; ++k) { - cipher_descriptor[idx].accel_xts_encrypt = NULL; - cipher_descriptor[idx].accel_xts_decrypt = NULL; - if (k & 0x1) { - cipher_descriptor[idx].accel_xts_encrypt = s_xts_test_accel_xts_encrypt; - } - if (k & 0x2) { - cipher_descriptor[idx].accel_xts_decrypt = s_xts_test_accel_xts_decrypt; - } - for (j = 0; j < 2; j++) { - for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - /* skip the cases where - * the length is smaller than 2*blocklen - * or the length is not a multiple of 32 - */ - if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) { - continue; - } - if ((k > 0) && (j == 1)) { - continue; - } - len = tests[i].PTLEN / 2; - - err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen / 2, 0, &xts); - if (err != CRYPT_OK) { - return err; - } - - seq = tests[i].seqnum; - STORE64L(seq, Torg); - XMEMSET(Torg + 8, 0, 8); - - XMEMCPY(T, Torg, sizeof(T)); - if (j == 0) { - err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - } else { - err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - } - - if (compare_testvector(OUT, tests[i].PTLEN, tests[i].CTX, tests[i].PTLEN, "XTS encrypt", i)) { - xts_done(&xts); - return CRYPT_FAIL_TESTVECTOR; - } - - XMEMCPY(T, Torg, sizeof(T)); - if (j == 0) { - err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - } else { - err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } - } - - if (compare_testvector(OUT, tests[i].PTLEN, tests[i].PTX, tests[i].PTLEN, "XTS decrypt", i)) { - xts_done(&xts); - return CRYPT_FAIL_TESTVECTOR; - } - xts_done(&xts); - } - } - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c deleted file mode 100644 index 83c915d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c +++ /dev/null @@ -1,77 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_bit_string.c - ASN.1 DER, encode a BIT STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a BIT STRING - @param in The DER encoded BIT STRING - @param inlen The size of the DER BIT STRING - @param out [out] The array of bits stored (one per char) - @param outlen [in/out] The number of bits stored - @return CRYPT_OK if successful -*/ -int der_decode_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long dlen, blen, x, y; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* packet must be at least 4 bytes */ - if (inlen < 4) { - return CRYPT_INVALID_ARG; - } - - /* check for 0x03 */ - if ((in[0]&0x1F) != 0x03) { - return CRYPT_INVALID_PACKET; - } - - /* offset in the data */ - x = 1; - - /* get the length of the data */ - y = inlen - 1; - if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { - return err; - } - x += y; - /* is the data len too long or too short? */ - if ((dlen == 0) || (dlen > (inlen - x))) { - return CRYPT_INVALID_PACKET; - } - - /* get padding count */ - blen = ((dlen - 1) << 3) - (in[x++] & 7); - - /* too many bits? */ - if (blen > *outlen) { - *outlen = blen; - return CRYPT_BUFFER_OVERFLOW; - } - - /* decode/store the bits */ - for (y = 0; y < blen; y++) { - out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0; - if ((y & 7) == 7) { - ++x; - } - } - - /* we done */ - *outlen = blen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c deleted file mode 100644 index 1bc74f6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_decode_raw_bit_string.c +++ /dev/null @@ -1,84 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_bit_string.c - ASN.1 DER, encode a BIT STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -#define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n)))) -#define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n)))) - -/** - Store a BIT STRING - @param in The DER encoded BIT STRING - @param inlen The size of the DER BIT STRING - @param out [out] The array of bits stored (8 per char) - @param outlen [in/out] The number of bits stored - @return CRYPT_OK if successful -*/ -int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long dlen, blen, x, y; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* packet must be at least 4 bytes */ - if (inlen < 4) { - return CRYPT_INVALID_ARG; - } - - /* check for 0x03 */ - if ((in[0]&0x1F) != 0x03) { - return CRYPT_INVALID_PACKET; - } - - /* offset in the data */ - x = 1; - - /* get the length of the data */ - y = inlen - 1; - if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { - return err; - } - x += y; - /* is the data len too long or too short? */ - if ((dlen == 0) || (dlen > (inlen - x))) { - return CRYPT_INVALID_PACKET; - } - - /* get padding count */ - blen = ((dlen - 1) << 3) - (in[x++] & 7); - - /* too many bits? */ - if (blen > *outlen) { - *outlen = blen; - return CRYPT_BUFFER_OVERFLOW; - } - - /* decode/store the bits */ - for (y = 0; y < blen; y++) { - if (in[x] & (1 << (7 - (y & 7)))) { - SETBIT(out[y/8], 7-(y%8)); - } else { - CLRBIT(out[y/8], 7-(y%8)); - } - if ((y & 7) == 7) { - ++x; - } - } - - /* we done */ - *outlen = blen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c deleted file mode 100644 index 0c2cd16..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_bit_string.c - ASN.1 DER, encode a BIT STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a BIT STRING - @param in The array of bits to store (one per char) - @param inlen The number of bits tostore - @param out [out] The destination for the DER encoded BIT STRING - @param outlen [in/out] The max size and resulting size of the DER BIT STRING - @return CRYPT_OK if successful -*/ -int der_encode_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long len, x, y; - unsigned char buf; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* avoid overflows */ - if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { - return err; - } - - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* store header (include bit padding count in length) */ - x = 0; - y = ((inlen + 7) >> 3) + 1; - - out[x++] = 0x03; - len = *outlen - x; - if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { - return err; - } - x += len; - - /* store number of zero padding bits */ - out[x++] = (unsigned char)((8 - inlen) & 7); - - /* store the bits in big endian format */ - for (y = buf = 0; y < inlen; y++) { - buf |= (in[y] ? 1 : 0) << (7 - (y & 7)); - if ((y & 7) == 7) { - out[x++] = buf; - buf = 0; - } - } - /* store last byte */ - if (inlen & 7) { - out[x++] = buf; - } - *outlen = x; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c deleted file mode 100644 index 9cc23ae..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_encode_raw_bit_string.c +++ /dev/null @@ -1,75 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_bit_string.c - ASN.1 DER, encode a BIT STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k)) - -/** - Store a BIT STRING - @param in The array of bits to store (8 per char) - @param inlen The number of bits to store - @param out [out] The destination for the DER encoded BIT STRING - @param outlen [in/out] The max size and resulting size of the DER BIT STRING - @return CRYPT_OK if successful -*/ -int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long len, x, y; - unsigned char buf; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* avoid overflows */ - if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { - return err; - } - - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* store header (include bit padding count in length) */ - x = 0; - y = ((inlen + 7) >> 3) + 1; - - out[x++] = 0x03; - len = *outlen - x; - if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { - return err; - } - x += len; - - /* store number of zero padding bits */ - out[x++] = (unsigned char)((8 - inlen) & 7); - - /* store the bits in big endian format */ - for (y = buf = 0; y < inlen; y++) { - buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7)); - if ((y & 7) == 7) { - out[x++] = buf; - buf = 0; - } - } - /* store last byte */ - if (inlen & 7) { - out[x++] = buf; - } - - *outlen = x; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c deleted file mode 100644 index 4554a80..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c +++ /dev/null @@ -1,36 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_bit_string.c - ASN.1 DER, get length of BIT STRING, Tom St Denis -*/ - -#ifdef LTC_DER -/** - Gets length of DER encoding of BIT STRING - @param nbits The number of bits in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_bit_string(unsigned long nbits, unsigned long *outlen) -{ - unsigned long nbytes, x; - int err; - - LTC_ARGCHK(outlen != NULL); - - /* get the number of the bytes */ - nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; - - if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + nbytes; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c deleted file mode 100644 index 35ac7ec..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_boolean.c - ASN.1 DER, decode a BOOLEAN, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Read a BOOLEAN - @param in The destination for the DER encoded BOOLEAN - @param inlen The size of the DER BOOLEAN - @param out [out] The boolean to decode - @return CRYPT_OK if successful -*/ -int der_decode_boolean(const unsigned char *in, unsigned long inlen, - int *out) -{ - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - if (inlen < 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { - return CRYPT_INVALID_ARG; - } - - *out = (in[2]==0xFF) ? 1 : 0; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c deleted file mode 100644 index a77aefb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c +++ /dev/null @@ -1,39 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_boolean.c - ASN.1 DER, encode a BOOLEAN, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a BOOLEAN - @param in The boolean to encode - @param out [out] The destination for the DER encoded BOOLEAN - @param outlen [in/out] The max size and resulting size of the DER BOOLEAN - @return CRYPT_OK if successful -*/ -int der_encode_boolean(int in, - unsigned char *out, unsigned long *outlen) -{ - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(out != NULL); - - if (*outlen < 3) { - *outlen = 3; - return CRYPT_BUFFER_OVERFLOW; - } - - *outlen = 3; - out[0] = 0x01; - out[1] = 0x01; - out[2] = in ? 0xFF : 0x00; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c deleted file mode 100644 index f1b9e57..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_boolean.c - ASN.1 DER, get length of a BOOLEAN, Tom St Denis -*/ - -#ifdef LTC_DER -/** - Gets length of DER encoding of a BOOLEAN - @param outlen [out] The length of the DER encoding - @return CRYPT_OK if successful -*/ -int der_length_boolean(unsigned long *outlen) -{ - LTC_ARGCHK(outlen != NULL); - *outlen = 3; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c deleted file mode 100644 index cf4422a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c +++ /dev/null @@ -1,221 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_choice.c - ASN.1 DER, decode a CHOICE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Decode a CHOICE - @param in The DER encoded input - @param inlen [in/out] The size of the input and resulting size of read type - @param list The list of items to decode - @param outlen The number of items in the list - @return CRYPT_OK on success -*/ -int der_decode_choice(const unsigned char *in, unsigned long *inlen, - ltc_asn1_list *list, unsigned long outlen) -{ - unsigned long size, x, z; - void *data; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(list != NULL); - - /* get blk size */ - if (*inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* set all of the "used" flags to zero */ - for (x = 0; x < outlen; x++) { - list[x].used = 0; - } - - /* now scan until we have a winner */ - for (x = 0; x < outlen; x++) { - size = list[x].size; - data = list[x].data; - - switch (list[x].type) { - case LTC_ASN1_BOOLEAN: - if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) { - if (der_length_boolean(&z) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_INTEGER: - if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { - if (der_length_integer(data, &z) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_SHORT_INTEGER: - if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) { - if (der_length_short_integer(*(unsigned long*)data, &z) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_BIT_STRING: - if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_bit_string(size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_RAW_BIT_STRING: - if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_bit_string(size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_OCTET_STRING: - if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_octet_string(size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_NULL: - if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) { - *inlen = 2; - list[x].used = 1; - return CRYPT_OK; - } - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_TELETEX_STRING: - if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_teletex_string(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_IA5_STRING: - if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_PRINTABLE_STRING: - if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_printable_string(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_UTF8_STRING: - if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) { - if (der_length_utf8_string(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - list[x].size = size; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_UTCTIME: - z = *inlen; - if (der_decode_utctime(in, &z, data) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - break; - - case LTC_ASN1_GENERALIZEDTIME: - z = *inlen; - if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - break; - - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) { - if (der_length_sequence(data, size, &z) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_CUSTOM_TYPE: - if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) { - if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) { - list[x].used = 1; - *inlen = z; - return CRYPT_OK; - } - } - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_EOL: - return CRYPT_INVALID_ARG; - } - } - - return CRYPT_INVALID_PACKET; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c deleted file mode 100644 index 4c4d52d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_decode_custom_type.c +++ /dev/null @@ -1,426 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -/** - @file der_decode_custom_type.c - ASN.1 DER, decode a Custom type, Steffen Jaeckel -*/ - -#ifdef LTC_DER - -/** - Decode a Custom type - @param in The DER encoded input - @param inlen The size of the input - @param root The item that defines the custom type to decode - @return CRYPT_OK on success -*/ -int der_decode_custom_type(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *root) -{ - LTC_ARGCHK(root != NULL); - return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED); -} - -/** - Extended-decode a Custom type - - This function is used to decode custom types and sequences/sets - For custom types root is used - For sequences/sets list and outlen are used - - @param in The DER encoded input - @param inlen The size of the input - @param root The item that defines the custom type to decode - @param list The list of items to decode - @param outlen The number of items in the list - @param flags c.f. enum ltc_der_seq - @return CRYPT_OK on success -*/ -int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *root, - ltc_asn1_list *list, unsigned long outlen, - unsigned int flags) -{ - int err, seq_err, i, ordered; - ltc_asn1_type type; - ltc_asn1_list ident; - unsigned long size, x, y, z, blksize; - unsigned char* in_new = NULL; - void *data; - - LTC_ARGCHK(in != NULL); - - /* get blk size */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - x = 0; - - if (root == NULL) { - LTC_ARGCHK(list != NULL); - - /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ - if (in[x] != 0x30 && in[x] != 0x31) { - return CRYPT_INVALID_PACKET; - } - ++x; - } else { - if (root->type != LTC_ASN1_CUSTOM_TYPE) { - return CRYPT_INVALID_PACKET; - } - - /* Alloc a copy of the data for primitive handling. */ - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - in_new = XMALLOC(inlen); - if (in_new == NULL) { - return CRYPT_MEM; - } - XMEMCPY(in_new, in, inlen); - in = in_new; - } - - y = inlen; - if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((ident.type != root->type) || - (ident.klass != root->klass) || - (ident.pc != root->pc) || - (ident.tag != root->tag)) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - x += y; - - list = root->data; - outlen = root->size; - } - - if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) { - if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) || - (der_asn1_type_to_identifier_map[root->used] == -1)) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - root->type = (ltc_asn1_type)root->used; - list = root; - outlen = 1; - - x -= 1; - in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type]; - blksize = inlen - x; - } else { - - y = inlen - x; - if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) { - goto LBL_ERR; - } - x += y; - } - - /* would this blksize overflow? */ - if (blksize > (inlen - x)) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* mark all as unused */ - for (i = 0; i < (int)outlen; i++) { - list[i].used = 0; - } - ordered = flags & LTC_DER_SEQ_ORDERED; - - /* ok read data */ - seq_err = CRYPT_OK; - blksize += x; - inlen -= x; - for (i = 0; i < (int)outlen; i++) { - z = 0; - type = list[i].type; - size = list[i].size; - data = list[i].data; - if (!ordered && list[i].used == 1) { continue; } - - if (type == LTC_ASN1_EOL) { - break; - } - - if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) { - err = CRYPT_PK_ASN1_ERROR; - goto LBL_ERR; - } - - switch (type) { - case LTC_ASN1_CUSTOM_TYPE: - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - break; - default: - /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */ - if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) { - if (in[x] & 0xE0u) { - err = CRYPT_PK_ASN1_ERROR; - goto LBL_ERR; - } - } - } - - switch (type) { - case LTC_ASN1_BOOLEAN: - z = inlen; - if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_boolean(&z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_INTEGER: - z = inlen; - if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_integer(data, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SHORT_INTEGER: - z = inlen; - if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { - goto LBL_ERR; - } - - break; - - case LTC_ASN1_BIT_STRING: - z = inlen; - if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_RAW_BIT_STRING: - z = inlen; - if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_OCTET_STRING: - z = inlen; - if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_NULL: - if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { - if (!ordered || list[i].optional) { continue; } - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - z = 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - z = inlen; - if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_TELETEX_STRING: - z = inlen; - if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_IA5_STRING: - z = inlen; - if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_PRINTABLE_STRING: - z = inlen; - if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTF8_STRING: - z = inlen; - if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - list[i].size = size; - if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTCTIME: - z = inlen; - if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - break; - - case LTC_ASN1_GENERALIZEDTIME: - z = inlen; - if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - break; - - case LTC_ASN1_SET: - z = inlen; - if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - /* detect if we have the right type */ - if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - z = inlen; - err = der_decode_sequence_ex(in + x, z, data, size, flags); - if (err == CRYPT_INPUT_TOO_LONG) { - seq_err = CRYPT_INPUT_TOO_LONG; - err = CRYPT_OK; - } - if (err != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CUSTOM_TYPE: - z = inlen; - err = der_decode_custom_type(in + x, z, &list[i]); - if (err == CRYPT_INPUT_TOO_LONG) { - seq_err = CRYPT_INPUT_TOO_LONG; - err = CRYPT_OK; - } - if (err != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CHOICE: - z = inlen; - if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { - if (!ordered || list[i].optional) { continue; } - goto LBL_ERR; - } - break; - - case LTC_ASN1_EOL: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - x += z; - inlen -= z; - list[i].used = 1; - if (!ordered) { - /* restart the decoder */ - i = -1; - } - } - - for (i = 0; i < (int)outlen; i++) { - if (list[i].used == 0 && list[i].optional == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - } - - if (blksize == x && seq_err == CRYPT_OK && inlen == 0) { - /* everything decoded and no errors in nested sequences */ - err = CRYPT_OK; - } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) { - /* a sequence reported too-long input, but now we've decoded everything */ - err = CRYPT_OK; - } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) { - err = CRYPT_INVALID_PACKET; - } else { - err = CRYPT_INPUT_TOO_LONG; - } - -LBL_ERR: - if (in_new != NULL) { - XFREE(in_new); - } - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c deleted file mode 100644 index 586fb31..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_encode_custom_type.c +++ /dev/null @@ -1,228 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -/** - @file der_encode_custom_type.c - ASN.1 DER, encode a Custom Type, Steffen Jaeckel -*/ - -#ifdef LTC_DER - -/** - Encode a Custom Type - - This function is a bit special compared to the others, as it requires the - root-ltc_asn1_list where the type is defined. - - @param root The root of the list of items to encode - @param out [out] The destination - @param outlen [in/out] The size of the output - @return CRYPT_OK on success -*/ -int der_encode_custom_type(const ltc_asn1_list *root, - unsigned char *out, unsigned long *outlen) -{ - int err; - ltc_asn1_type type; - const ltc_asn1_list *list; - unsigned long size, x, y, z, i, inlen, id_len; - void *data; - - LTC_ARGCHK(root != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get size of output that will be required */ - y = 0; z = 0; - if (der_length_custom_type(root, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; - - /* too big ? */ - if (*outlen < y) { - *outlen = y; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* get length of the identifier, so we know the offset where to start writing */ - if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG; - x = id_len; - - - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - list = root; - inlen = 1; - /* In case it's a PRIMITIVE type we encode directly to the output - * but leave space for a potentially longer identifier as it will - * simply be replaced afterwards. - */ - x -= 1; - } else { - list = root->data; - inlen = root->size; - /* store length, identifier will be added later */ - y = *outlen - x; - if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { - goto LBL_ERR; - } - x += y; - } - - /* store data */ - *outlen -= x; - for (i = 0; i < inlen; i++) { - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - type = (ltc_asn1_type)list[i].used; - } else { - type = list[i].type; - } - size = list[i].size; - data = list[i].data; - - if (type == LTC_ASN1_EOL) { - break; - } - - switch (type) { - case LTC_ASN1_BOOLEAN: - z = *outlen; - if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_INTEGER: - z = *outlen; - if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SHORT_INTEGER: - z = *outlen; - if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_BIT_STRING: - z = *outlen; - if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_RAW_BIT_STRING: - z = *outlen; - if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_OCTET_STRING: - z = *outlen; - if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_NULL: - out[x] = 0x05; - out[x+1] = 0x00; - z = 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - z = *outlen; - if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_IA5_STRING: - z = *outlen; - if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_PRINTABLE_STRING: - z = *outlen; - if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTF8_STRING: - z = *outlen; - if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTCTIME: - z = *outlen; - if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_GENERALIZEDTIME: - z = *outlen; - if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SET: - z = *outlen; - if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SETOF: - z = *outlen; - if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SEQUENCE: - z = *outlen; - if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CUSTOM_TYPE: - z = *outlen; - if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_EOL: - case LTC_ASN1_TELETEX_STRING: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - - - x += z; - *outlen -= z; - } - - if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) { - goto LBL_ERR; - } - *outlen = x; - err = CRYPT_OK; - -LBL_ERR: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c deleted file mode 100644 index 01e58ec..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/custom_type/der_length_custom_type.c +++ /dev/null @@ -1,203 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_custom_type.c - ASN.1 DER, length of a custom type, Steffen Jaeckel -*/ - -#ifdef LTC_DER - -/** - Get the length of a DER custom type - - This function is a bit special compared to the others, as it requires the - root-ltc_asn1_list where the type is defined. - - @param root The root of the struct to encode - @param outlen [out] The length required in octets to store it - @param payloadlen [out] The length of the payload in octets - @return CRYPT_OK on success -*/ -int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen) -{ - int err; - const ltc_asn1_list *list; - ltc_asn1_type type; - unsigned long size, x, y, i, inlen, id_len; - void *data; - - LTC_ARGCHK(root != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get size of output that will be required */ - if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) { - return err; - } - y = id_len; - - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - list = root; - inlen = 1; - } else { - list = root->data; - inlen = root->size; - } - for (i = 0; i < inlen; i++) { - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - type = (ltc_asn1_type)list[i].used; - } else { - type = list[i].type; - } - size = list[i].size; - data = list[i].data; - - if (type == LTC_ASN1_EOL) { - break; - } - - /* some items may be optional during import */ - if (!list[i].used && list[i].optional) continue; - - switch (type) { - case LTC_ASN1_BOOLEAN: - if ((err = der_length_boolean(&x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_INTEGER: - if ((err = der_length_integer(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SHORT_INTEGER: - if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_RAW_BIT_STRING: - if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_OCTET_STRING: - if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_NULL: - y += 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_IA5_STRING: - if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_TELETEX_STRING: - if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_PRINTABLE_STRING: - if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTCTIME: - if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_GENERALIZEDTIME: - if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTF8_STRING: - if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_CUSTOM_TYPE: - if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_EOL: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - } - - if (root->pc == LTC_ASN1_PC_PRIMITIVE) { - /* In case it's a PRIMITIVE element we're going - * to only replace the identifier of the one element - * by the custom identifier. - */ - y -= 1; - if (payloadlen != NULL) { - *payloadlen = y - id_len; - } - } else { - /* calc length of length */ - if ((err = der_length_asn1_length(y - id_len, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - if (payloadlen != NULL) { - *payloadlen = y - id_len; - } - y += x; - } - - /* store size */ - *outlen = y; - -LBL_ERR: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c deleted file mode 100644 index e98ab39..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_asn1_maps.c +++ /dev/null @@ -1,157 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_asn1_maps.c - ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel -*/ - -#ifdef LTC_DER - -/** - A Map from ltc_asn1_type to the regularly used ASN.1 identifier -*/ -const int der_asn1_type_to_identifier_map[] = -{ - /* 0 */ - -1, /* LTC_ASN1_EOL, */ - 1, /* LTC_ASN1_BOOLEAN, */ - 2, /* LTC_ASN1_INTEGER, */ - 2, /* LTC_ASN1_SHORT_INTEGER, */ - 3, /* LTC_ASN1_BIT_STRING, */ - /* 5 */ - 4, /* LTC_ASN1_OCTET_STRING, */ - 5, /* LTC_ASN1_NULL, */ - 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */ - 22, /* LTC_ASN1_IA5_STRING, */ - 19, /* LTC_ASN1_PRINTABLE_STRING, */ - /* 10 */ - 12, /* LTC_ASN1_UTF8_STRING, */ - 23, /* LTC_ASN1_UTCTIME, */ - -1, /* LTC_ASN1_CHOICE, */ - 48, /* LTC_ASN1_SEQUENCE, */ - 49, /* LTC_ASN1_SET, */ - /* 15 */ - 49, /* LTC_ASN1_SETOF, */ - 3, /* LTC_ASN1_RAW_BIT_STRING, */ - 20, /* LTC_ASN1_TELETEX_STRING, */ - 24, /* LTC_ASN1_GENERALIZEDTIME, */ - -1, /* LTC_ASN1_CUSTOM_TYPE, */ -}; -const unsigned long der_asn1_type_to_identifier_map_sz = LTC_ARRAY_SIZE(der_asn1_type_to_identifier_map); - -/** - A Map from the ASN.1 Class to its string -*/ -const char* der_asn1_class_to_string_map[] = -{ - "UNIVERSAL", - "APPLICATION", - "CONTEXT-SPECIFIC", - "PRIVATE", -}; -const unsigned long der_asn1_class_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_class_to_string_map); - -/** - A Map from the ASN.1 P/C-bit to its string -*/ -const char* der_asn1_pc_to_string_map[] = -{ - "PRIMITIVE", - "CONSTRUCTED", -}; -const unsigned long der_asn1_pc_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_pc_to_string_map); - -/** - A Map from the ASN.1 tag to its string -*/ -const char* der_asn1_tag_to_string_map[] = -{ - "Reserved for use by the encoding rules", - "Boolean type", - "Integer type", - "Bitstring type", - "Octetstring type", - "Null type", - "Object identifier type", - "Object descriptor type", - "External type and Instance-of type", - "Real type", - "Enumerated type", - "Embedded-pdv type", - "UTF8String type", - "Relative object identifier type", - "The time type", - "Reserved for future editions of this Recommendation | International Standard", - "Sequence and Sequence-of types", - "Set and Set-of types", - "NumericString type", - "PrintableString type", - "TeletexString (T61String) type", - "VideotexString type", - "IA5String type", - "UTCTime type", - "GeneralizedTime type", - "GraphicString type", - "VisibleString (ISO646String) type", - "GeneralString type", - "UniversalString type", - "UnrestrictedCharacterString type", - "BMPString type", - "Date type", - "TimeOfDay type", - "DateTime type", - "Duration type", - "OID internationalized resource identifier type", - "Relative OID internationalized resource identifier type", -}; -const unsigned long der_asn1_tag_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_tag_to_string_map); - -/** - A Map from ASN.1 Tags to ltc_asn1_type -*/ -const ltc_asn1_type der_asn1_tag_to_type_map[] = -{ - /* 0 */ - LTC_ASN1_EOL, /* Reserved for use by the encoding rules */ - LTC_ASN1_BOOLEAN, /* Boolean type */ - LTC_ASN1_INTEGER, /* Integer type */ - LTC_ASN1_BIT_STRING, /* Bitstring type */ - LTC_ASN1_OCTET_STRING, /* Octetstring type */ - /* 5 */ - LTC_ASN1_NULL, /* Null type */ - LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */ - LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */ - LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */ - LTC_ASN1_CUSTOM_TYPE, /* Real type */ - /* 10 */ - LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */ - LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */ - LTC_ASN1_UTF8_STRING, /* UTF8String type */ - LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */ - LTC_ASN1_CUSTOM_TYPE, /* The time type */ - /* 15 */ - LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */ - LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */ - LTC_ASN1_SET, /* Set and Set-of types */ - LTC_ASN1_CUSTOM_TYPE, /* NumericString types */ - LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */ - /* 20 */ - LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */ - LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */ - LTC_ASN1_IA5_STRING, /* IA5String types */ - LTC_ASN1_UTCTIME, /* UTCTime types */ - LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */ - /* 25 */ - LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */ - LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */ - LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */ - LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */ - LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */ - /* 30 */ - LTC_ASN1_CUSTOM_TYPE, /* BMPString types */ -}; -const unsigned long der_asn1_tag_to_type_map_sz = LTC_ARRAY_SIZE(der_asn1_tag_to_type_map); - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c deleted file mode 100644 index 78866c9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_identifier.c +++ /dev/null @@ -1,123 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_asn1_identifier.c - ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */ -static const unsigned char tag_constructed_map[] = -{ - /* 0 */ - 255, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - /* 5 */ - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - /* 10 */ - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - /* 15 */ - 255, - LTC_ASN1_PC_CONSTRUCTED, - LTC_ASN1_PC_CONSTRUCTED, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - /* 20 */ - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - /* 25 */ - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, - LTC_ASN1_PC_PRIMITIVE, -}; - static const unsigned long tag_constructed_map_sz = LTC_ARRAY_SIZE(tag_constructed_map); - -/** - Decode the ASN.1 Identifier - @param id Where to store the decoded Identifier - @param in Where to read the Identifier from - @param inlen [in/out] The size of in available/read - @return CRYPT_OK if successful -*/ -int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id) -{ - ulong64 tmp; - unsigned long tag_len; - int err; - - LTC_ARGCHK(id != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - - if (*inlen == 0) { - return CRYPT_BUFFER_OVERFLOW; - } - - tag_len = 1; - id->klass = (in[0] >> 6) & 0x3; - id->pc = (in[0] >> 5) & 0x1; - id->tag = in[0] & 0x1f; - - err = CRYPT_OK; - if (id->tag == 0x1f) { - id->tag = 0; - do { - if (*inlen < tag_len) { - /* break the loop and trigger the BOF error-code */ - tmp = 0xff; - break; - } - id->tag <<= 7; - id->tag |= in[tag_len] & 0x7f; - tmp = in[tag_len] & 0x80; - tag_len++; - } while ((tmp != 0) && (tag_len < 10)); - - if (tmp != 0) { - err = CRYPT_BUFFER_OVERFLOW; - } else if (id->tag < 0x1f) { - err = CRYPT_PK_ASN1_ERROR; - } - } - - if (err != CRYPT_OK) { - id->pc = 0; - id->klass = 0; - id->tag = 0; - } else { - *inlen = tag_len; - if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && - (id->tag < der_asn1_tag_to_type_map_sz) && - (id->tag < tag_constructed_map_sz) && - (id->pc == tag_constructed_map[id->tag])) { - id->type = der_asn1_tag_to_type_map[id->tag]; - } else { - if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) { - id->type = LTC_ASN1_EOL; - } else { - id->type = LTC_ASN1_CUSTOM_TYPE; - } - } - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c deleted file mode 100644 index 0e5a393..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_decode_asn1_length.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_asn1_length.c - ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/** - Decode the ASN.1 Length field - @param in Where to read the length field from - @param inlen [in/out] The size of in available/read - @param outlen [out] The decoded ASN.1 length - @return CRYPT_OK if successful -*/ -int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen) -{ - unsigned long real_len, decoded_len, offset, i; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - - if (*inlen < 1) { - return CRYPT_BUFFER_OVERFLOW; - } - - real_len = in[0]; - - if (real_len < 128) { - decoded_len = real_len; - offset = 1; - } else { - real_len &= 0x7F; - if (real_len == 0) { - return CRYPT_PK_ASN1_ERROR; - } - if (real_len > sizeof(decoded_len)) { - return CRYPT_OVERFLOW; - } - if (real_len > (*inlen - 1)) { - return CRYPT_BUFFER_OVERFLOW; - } - decoded_len = 0; - offset = 1 + real_len; - for (i = 0; i < real_len; i++) { - decoded_len = (decoded_len << 8) | in[1 + i]; - } - } - - if (outlen != NULL) *outlen = decoded_len; - if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW; - *inlen = offset; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c deleted file mode 100644 index 51d57ec..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_identifier.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_asn1_identifier.c - ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/** - Encode the ASN.1 Identifier - @param id The ASN.1 Identifer to encode - @param out Where to write the identifier to - @param outlen [in/out] The size of out available/written - @return CRYPT_OK if successful -*/ -int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen) -{ - ulong64 tmp; - unsigned long tag_len; - - LTC_ARGCHK(id != NULL); - LTC_ARGCHK(outlen != NULL); - - if (id->type != LTC_ASN1_CUSTOM_TYPE) { - if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) { - return CRYPT_INVALID_ARG; - } - if (der_asn1_type_to_identifier_map[id->type] == -1) { - return CRYPT_INVALID_ARG; - } - if (out != NULL) { - *out = der_asn1_type_to_identifier_map[id->type]; - } - *outlen = 1; - return CRYPT_OK; - } - if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) { - return CRYPT_INVALID_ARG; - } - if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) { - return CRYPT_INVALID_ARG; - } - if (id->tag > (ULONG_MAX >> (8 + 7))) { - return CRYPT_INVALID_ARG; - } - - if (out != NULL) { - if (*outlen < 1) { - return CRYPT_BUFFER_OVERFLOW; - } - - out[0] = id->klass << 6 | id->pc << 5; - } - - if (id->tag < 0x1f) { - if (out != NULL) { - out[0] |= id->tag & 0x1f; - } - *outlen = 1; - } else { - tag_len = 0; - tmp = id->tag; - do { - tag_len++; - tmp >>= 7; - } while (tmp); - - if (out != NULL) { - if (*outlen < tag_len + 1) { - return CRYPT_BUFFER_OVERFLOW; - } - out[0] |= 0x1f; - for (tmp = 1; tmp <= tag_len; ++tmp) { - out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80; - } - out[tag_len] &= ~0x80; - } - *outlen = tag_len + 1; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c deleted file mode 100644 index 7892eea..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_encode_asn1_length.c +++ /dev/null @@ -1,117 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_asn1_length.c - ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/** - Encode the ASN.1 length field - @param len The length to encode - @param out Where to write the length field to - @param outlen [in/out] The size of out available/written - @return CRYPT_OK if successful -*/ -int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y; - - LTC_ARGCHK(outlen != NULL); - - x = len; - y = 0; - - while(x != 0) { - y++; - x >>= 8; - } - if (y == 0) { - return CRYPT_PK_ASN1_ERROR; - } - - if (out == NULL) { - if (len < 128) { - x = y; - } else { - x = y + 1; - } - } else { - if (*outlen < y) { - return CRYPT_BUFFER_OVERFLOW; - } - x = 0; - if (len < 128) { - out[x++] = (unsigned char)len; - } else if (len <= 0xffUL) { - out[x++] = 0x81; - out[x++] = (unsigned char)len; - } else if (len <= 0xffffUL) { - out[x++] = 0x82; - out[x++] = (unsigned char)((len>>8UL)&255); - out[x++] = (unsigned char)(len&255); - } else if (len <= 0xffffffUL) { - out[x++] = 0x83; - out[x++] = (unsigned char)((len>>16UL)&255); - out[x++] = (unsigned char)((len>>8UL)&255); - out[x++] = (unsigned char)(len&255); - #if ULONG_MAX != ULLONG_MAX - } else { - out[x++] = 0x84; - out[x++] = (unsigned char)((len>>24UL)&255); - out[x++] = (unsigned char)((len>>16UL)&255); - out[x++] = (unsigned char)((len>>8UL)&255); - out[x++] = (unsigned char)(len&255); - } - #else - } else if (len <= 0xffffffffUL) { - out[x++] = 0x84; - out[x++] = (unsigned char)((len>>24UL)&255); - out[x++] = (unsigned char)((len>>16UL)&255); - out[x++] = (unsigned char)((len>>8UL)&255); - out[x++] = (unsigned char)(len&255); - } else if (len <= 0xffffffffffULL) { - out[x++] = 0x85; - out[x++] = (unsigned char)((len>>32ULL)&255); - out[x++] = (unsigned char)((len>>24ULL)&255); - out[x++] = (unsigned char)((len>>16ULL)&255); - out[x++] = (unsigned char)((len>>8ULL)&255); - out[x++] = (unsigned char)(len&255); - } else if (len <= 0xffffffffffffULL) { - out[x++] = 0x86; - out[x++] = (unsigned char)((len>>40ULL)&255); - out[x++] = (unsigned char)((len>>32ULL)&255); - out[x++] = (unsigned char)((len>>24ULL)&255); - out[x++] = (unsigned char)((len>>16ULL)&255); - out[x++] = (unsigned char)((len>>8ULL)&255); - out[x++] = (unsigned char)(len&255); - } else if (len <= 0xffffffffffffffULL) { - out[x++] = 0x87; - out[x++] = (unsigned char)((len>>48ULL)&255); - out[x++] = (unsigned char)((len>>40ULL)&255); - out[x++] = (unsigned char)((len>>32ULL)&255); - out[x++] = (unsigned char)((len>>24ULL)&255); - out[x++] = (unsigned char)((len>>16ULL)&255); - out[x++] = (unsigned char)((len>>8ULL)&255); - out[x++] = (unsigned char)(len&255); - } else { - out[x++] = 0x88; - out[x++] = (unsigned char)((len>>56ULL)&255); - out[x++] = (unsigned char)((len>>48ULL)&255); - out[x++] = (unsigned char)((len>>40ULL)&255); - out[x++] = (unsigned char)((len>>32ULL)&255); - out[x++] = (unsigned char)((len>>24ULL)&255); - out[x++] = (unsigned char)((len>>16ULL)&255); - out[x++] = (unsigned char)((len>>8ULL)&255); - out[x++] = (unsigned char)(len&255); - } - #endif - } - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c deleted file mode 100644 index 63e6bdd..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_identifier.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_asn1_identifier.c - ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/** - Determine the length required when encoding the ASN.1 Identifier - @param id The ASN.1 identifier to encode - @param idlen [out] The required length to encode list - @return CRYPT_OK if successful -*/ - -int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen) -{ - return der_encode_asn1_identifier(id, NULL, idlen); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c deleted file mode 100644 index 1c81adb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/general/der_length_asn1_length.c +++ /dev/null @@ -1,22 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_asn1_length.c - ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel -*/ - -#ifdef LTC_DER -/** - Determine the length required to encode len in the ASN.1 length field - @param len The length to encode - @param outlen [out] The length that's required to store len - @return CRYPT_OK if successful -*/ -int der_length_asn1_length(unsigned long len, unsigned long *outlen) -{ - return der_encode_asn1_length(len, NULL, outlen); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c deleted file mode 100644 index b9c7d49..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c +++ /dev/null @@ -1,141 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_generalizedtime.c - ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel - Based on der_decode_utctime.c -*/ - -#ifdef LTC_DER - -#ifndef LTC_DER_CHAR_TO_INT -#define LTC_DER_CHAR_TO_INT -static LTC_INLINE int s_char_to_int(unsigned char x) -{ - switch (x) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - default: return 100; - } -} -#endif - -#define DECODE_V(y, max) do {\ - y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ - if (y >= max) return CRYPT_INVALID_PACKET; \ - x += 2; \ -} while(0) - -#define DECODE_V4(y, max) do {\ - y = s_char_to_int(buf[x])*1000 + s_char_to_int(buf[x+1])*100 + s_char_to_int(buf[x+2])*10 + s_char_to_int(buf[x+3]); \ - if (y >= max) return CRYPT_INVALID_PACKET; \ - x += 4; \ -} while(0) - -/** - Decodes a Generalized time structure in DER format (reads all 6 valid encoding formats) - @param in Input buffer - @param inlen Length of input buffer in octets - @param out [out] Destination of Generalized time structure - @return CRYPT_OK if successful -*/ -int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, - ltc_generalizedtime *out) -{ - unsigned char buf[32]; - unsigned long x; - int y; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(out != NULL); - - /* check header */ - if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { - return CRYPT_INVALID_PACKET; - } - - /* decode the string */ - for (x = 0; x < in[1]; x++) { - y = der_ia5_value_decode(in[x+2]); - if (y == -1) { - return CRYPT_INVALID_PACKET; - } - if (!((y >= '0' && y <= '9') - || y == 'Z' || y == '.' - || y == '+' || y == '-')) { - return CRYPT_INVALID_PACKET; - } - buf[x] = y; - } - *inlen = 2 + x; - - if (x < 15) { - return CRYPT_INVALID_PACKET; - } - - /* possible encodings are -YYYYMMDDhhmmssZ -YYYYMMDDhhmmss+hh'mm' -YYYYMMDDhhmmss-hh'mm' -YYYYMMDDhhmmss.fsZ -YYYYMMDDhhmmss.fs+hh'mm' -YYYYMMDDhhmmss.fs-hh'mm' - - So let's do a trivial decode upto [including] ss - */ - - x = 0; - DECODE_V4(out->YYYY, 10000); - DECODE_V(out->MM, 13); - DECODE_V(out->DD, 32); - DECODE_V(out->hh, 24); - DECODE_V(out->mm, 60); - DECODE_V(out->ss, 60); - - /* clear fractional seconds info */ - out->fs = 0; - - /* now is it Z or . */ - if (buf[x] == 'Z') { - return CRYPT_OK; - } - if (buf[x] == '.') { - x++; - while (buf[x] >= '0' && buf[x] <= '9') { - unsigned fs = out->fs; - if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET; - out->fs *= 10; - out->fs += s_char_to_int(buf[x]); - if (fs > out->fs) return CRYPT_OVERFLOW; - x++; - } - } - - /* now is it Z, +, - */ - if (buf[x] == 'Z') { - return CRYPT_OK; - } - if (buf[x] == '+' || buf[x] == '-') { - out->off_dir = (buf[x++] == '+') ? 0 : 1; - DECODE_V(out->off_hh, 24); - DECODE_V(out->off_mm, 60); - return CRYPT_OK; - } - return CRYPT_INVALID_PACKET; -} - -#undef DECODE_V -#undef DECODE_V4 - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c deleted file mode 100644 index ec17a68..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c +++ /dev/null @@ -1,100 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_utctime.c - ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel - Based on der_encode_utctime.c -*/ - -#ifdef LTC_DER - -#define STORE_V(y) do {\ - out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ - out[x++] = der_ia5_char_encode(baseten[y % 10]); \ -} while(0) - -#define STORE_V4(y) do {\ - out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ - out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ - out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ - out[x++] = der_ia5_char_encode(baseten[y % 10]); \ -} while(0) - -/** - Encodes a Generalized time structure in DER format - @param gtime The GeneralizedTime structure to encode - @param out The destination of the DER encoding of the GeneralizedTime structure - @param outlen [in/out] The length of the DER encoding - @return CRYPT_OK if successful -*/ -int der_encode_generalizedtime(const ltc_generalizedtime *gtime, - unsigned char *out, unsigned long *outlen) -{ - const char * const baseten = "0123456789"; - unsigned long x, tmplen; - int err; - - LTC_ARGCHK(gtime != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { - return err; - } - if (tmplen > *outlen) { - *outlen = tmplen; - return CRYPT_BUFFER_OVERFLOW; - } - - /* store header */ - out[0] = 0x18; - - /* store values */ - x = 2; - STORE_V4(gtime->YYYY); - STORE_V(gtime->MM); - STORE_V(gtime->DD); - STORE_V(gtime->hh); - STORE_V(gtime->mm); - STORE_V(gtime->ss); - - if (gtime->fs) { - unsigned long divisor; - unsigned fs = gtime->fs; - unsigned len = 0; - out[x++] = der_ia5_char_encode('.'); - divisor = 1; - do { - fs /= 10; - divisor *= 10; - len++; - } while(fs != 0); - while (len-- > 1) { - divisor /= 10; - out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); - } - out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); - } - - if (gtime->off_mm || gtime->off_hh) { - out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); - STORE_V(gtime->off_hh); - STORE_V(gtime->off_mm); - } else { - out[x++] = der_ia5_char_encode('Z'); - } - - /* store length */ - out[1] = (unsigned char)(x - 2); - - /* all good let's return */ - *outlen = x; - return CRYPT_OK; -} - -#undef STORE_V -#undef STORE_V4 - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c deleted file mode 100644 index dc237d3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/generalizedtime/der_length_generalizedtime.c +++ /dev/null @@ -1,48 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_utctime.c - ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel - Based on der_length_utctime.c -*/ - -#ifdef LTC_DER - -/** - Gets length of DER encoding of GeneralizedTime - @param gtime The GeneralizedTime structure to get the size of - @param outlen [out] The length of the DER encoding - @return CRYPT_OK if successful -*/ -int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen) -{ - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(gtime != NULL); - - if (gtime->fs == 0) { - /* we encode as YYYYMMDDhhmmssZ */ - *outlen = 2 + 14 + 1; - } else { - unsigned long len = 2 + 14 + 1; - unsigned fs = gtime->fs; - do { - fs /= 10; - len++; - } while(fs != 0); - if (gtime->off_hh == 0 && gtime->off_mm == 0) { - /* we encode as YYYYMMDDhhmmss.fsZ */ - len += 1; - } - else { - /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */ - len += 5; - } - *outlen = len; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c deleted file mode 100644 index 8fd80cf..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_ia5_string.c - ASN.1 DER, encode a IA5 STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a IA5 STRING - @param in The DER encoded IA5 STRING - @param inlen The size of the DER IA5 STRING - @param out [out] The array of octets stored (one per char) - @param outlen [in/out] The number of octets stored - @return CRYPT_OK if successful -*/ -int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int t, err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* must have header at least */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check for 0x16 */ - if ((in[0] & 0x1F) != 0x16) { - return CRYPT_INVALID_PACKET; - } - x = 1; - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - /* is it too long? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - if (len > (inlen - x)) { - return CRYPT_INVALID_PACKET; - } - - /* read the data */ - for (y = 0; y < len; y++) { - t = der_ia5_value_decode(in[x++]); - if (t == -1) { - return CRYPT_INVALID_ARG; - } - out[y] = t; - } - - *outlen = y; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c deleted file mode 100644 index 8b8bd36..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_ia5_string.c - ASN.1 DER, encode a IA5 STRING, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Store an IA5 STRING - @param in The array of IA5 to store (one per char) - @param inlen The number of IA5 to store - @param out [out] The destination for the DER encoded IA5 STRING - @param outlen [in/out] The max size and resulting size of the DER IA5 STRING - @return CRYPT_OK if successful -*/ -int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get the size */ - if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { - return err; - } - - /* too big? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* encode the header+len */ - x = 0; - out[x++] = 0x16; - len = *outlen - x; - if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { - return err; - } - x += len; - - /* store octets */ - for (y = 0; y < inlen; y++) { - out[x++] = der_ia5_char_encode(in[y]); - } - - /* retun length */ - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c deleted file mode 100644 index 4bce85e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c +++ /dev/null @@ -1,172 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_ia5_string.c - ASN.1 DER, get length of IA5 STRING, Tom St Denis -*/ - -#ifdef LTC_DER - -static const struct { - int code, value; -} ia5_table[] = { -{ '\0', 0 }, -{ '\a', 7 }, -{ '\b', 8 }, -{ '\t', 9 }, -{ '\n', 10 }, -{ '\f', 12 }, -{ '\r', 13 }, -{ ' ', 32 }, -{ '!', 33 }, -{ '"', 34 }, -{ '#', 35 }, -{ '$', 36 }, -{ '%', 37 }, -{ '&', 38 }, -{ '\'', 39 }, -{ '(', 40 }, -{ ')', 41 }, -{ '*', 42 }, -{ '+', 43 }, -{ ',', 44 }, -{ '-', 45 }, -{ '.', 46 }, -{ '/', 47 }, -{ '0', 48 }, -{ '1', 49 }, -{ '2', 50 }, -{ '3', 51 }, -{ '4', 52 }, -{ '5', 53 }, -{ '6', 54 }, -{ '7', 55 }, -{ '8', 56 }, -{ '9', 57 }, -{ ':', 58 }, -{ ';', 59 }, -{ '<', 60 }, -{ '=', 61 }, -{ '>', 62 }, -{ '?', 63 }, -{ '@', 64 }, -{ 'A', 65 }, -{ 'B', 66 }, -{ 'C', 67 }, -{ 'D', 68 }, -{ 'E', 69 }, -{ 'F', 70 }, -{ 'G', 71 }, -{ 'H', 72 }, -{ 'I', 73 }, -{ 'J', 74 }, -{ 'K', 75 }, -{ 'L', 76 }, -{ 'M', 77 }, -{ 'N', 78 }, -{ 'O', 79 }, -{ 'P', 80 }, -{ 'Q', 81 }, -{ 'R', 82 }, -{ 'S', 83 }, -{ 'T', 84 }, -{ 'U', 85 }, -{ 'V', 86 }, -{ 'W', 87 }, -{ 'X', 88 }, -{ 'Y', 89 }, -{ 'Z', 90 }, -{ '[', 91 }, -{ '\\', 92 }, -{ ']', 93 }, -{ '^', 94 }, -{ '_', 95 }, -{ '`', 96 }, -{ 'a', 97 }, -{ 'b', 98 }, -{ 'c', 99 }, -{ 'd', 100 }, -{ 'e', 101 }, -{ 'f', 102 }, -{ 'g', 103 }, -{ 'h', 104 }, -{ 'i', 105 }, -{ 'j', 106 }, -{ 'k', 107 }, -{ 'l', 108 }, -{ 'm', 109 }, -{ 'n', 110 }, -{ 'o', 111 }, -{ 'p', 112 }, -{ 'q', 113 }, -{ 'r', 114 }, -{ 's', 115 }, -{ 't', 116 }, -{ 'u', 117 }, -{ 'v', 118 }, -{ 'w', 119 }, -{ 'x', 120 }, -{ 'y', 121 }, -{ 'z', 122 }, -{ '{', 123 }, -{ '|', 124 }, -{ '}', 125 }, -{ '~', 126 } -}; - -int der_ia5_char_encode(int c) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(ia5_table); x++) { - if (ia5_table[x].code == c) { - return ia5_table[x].value; - } - } - return -1; -} - -int der_ia5_value_decode(int v) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(ia5_table); x++) { - if (ia5_table[x].value == v) { - return ia5_table[x].code; - } - } - return -1; -} - -/** - Gets length of DER encoding of IA5 STRING - @param octets The values you want to encode - @param noctets The number of octets in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) -{ - unsigned long x; - int err; - - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(octets != NULL); - - /* scan string for validity */ - for (x = 0; x < noctets; x++) { - if (der_ia5_char_encode(octets[x]) == -1) { - return CRYPT_INVALID_ARG; - } - } - - if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + noctets; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c deleted file mode 100644 index e2555b9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c +++ /dev/null @@ -1,68 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_integer.c - ASN.1 DER, decode an integer, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Read a mp_int integer - @param in The DER encoded data - @param inlen Size of DER encoded data - @param num The first mp_int to decode - @return CRYPT_OK if successful -*/ -int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) -{ - unsigned long x, y; - int err; - - LTC_ARGCHK(num != NULL); - LTC_ARGCHK(in != NULL); - - /* min DER INTEGER is 0x02 01 00 == 0 */ - if (inlen < (1 + 1 + 1)) { - return CRYPT_INVALID_PACKET; - } - - /* ok expect 0x02 when we AND with 0001 1111 [1F] */ - x = 0; - if ((in[x++] & 0x1F) != 0x02) { - return CRYPT_INVALID_PACKET; - } - - /* get the length of the data */ - inlen -= x; - if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) { - return err; - } - x += inlen; - - if ((err = ltc_mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) { - return err; - } - - /* see if it's negative */ - if (in[x] & 0x80) { - void *tmp; - if (ltc_mp_init(&tmp) != CRYPT_OK) { - return CRYPT_MEM; - } - - if (ltc_mp_2expt(tmp, ltc_mp_count_bits(num)) != CRYPT_OK || ltc_mp_sub(num, tmp, num) != CRYPT_OK) { - ltc_mp_clear(tmp); - return CRYPT_MEM; - } - ltc_mp_clear(tmp); - } - - return CRYPT_OK; - -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c deleted file mode 100644 index f7bc0f9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file der_encode_integer.c - ASN.1 DER, encode an integer, Tom St Denis -*/ - - -#ifdef LTC_DER - -/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */ -/** - Store a mp_int integer - @param num The first mp_int to encode - @param out [out] The destination for the DER encoded integers - @param outlen [in/out] The max size and resulting size of the DER encoded integers - @return CRYPT_OK if successful -*/ -int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) -{ - unsigned long tmplen, y, len; - int err, leading_zero; - - LTC_ARGCHK(num != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* find out how big this will be */ - if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) { - return err; - } - - if (*outlen < tmplen) { - *outlen = tmplen; - return CRYPT_BUFFER_OVERFLOW; - } - - if (ltc_mp_cmp_d(num, 0) != LTC_MP_LT) { - /* we only need a leading zero if the msb of the first byte is one */ - if ((ltc_mp_count_bits(num) & 7) == 0 || ltc_mp_iszero(num) == LTC_MP_YES) { - leading_zero = 1; - } else { - leading_zero = 0; - } - - /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ - y = ltc_mp_unsigned_bin_size(num) + leading_zero; - } else { - leading_zero = 0; - y = ltc_mp_count_bits(num); - y = y + (8 - (y & 7)); - y = y >> 3; - if (((ltc_mp_cnt_lsb(num)+1)==ltc_mp_count_bits(num)) && ((ltc_mp_count_bits(num)&7)==0)) --y; - } - - /* now store initial data */ - *out++ = 0x02; - len = *outlen - 1; - if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) { - return err; - } - out += len; - - /* now store msbyte of zero if num is non-zero */ - if (leading_zero) { - *out++ = 0x00; - } - - /* if it's not zero store it as big endian */ - if (ltc_mp_cmp_d(num, 0) == LTC_MP_GT) { - /* now store the mpint */ - if ((err = ltc_mp_to_unsigned_bin(num, out)) != CRYPT_OK) { - return err; - } - } else if (ltc_mp_iszero(num) != LTC_MP_YES) { - void *tmp; - - /* negative */ - if (ltc_mp_init(&tmp) != CRYPT_OK) { - return CRYPT_MEM; - } - - /* 2^roundup and subtract */ - y = ltc_mp_count_bits(num); - y = y + (8 - (y & 7)); - if (((ltc_mp_cnt_lsb(num)+1)==ltc_mp_count_bits(num)) && ((ltc_mp_count_bits(num)&7)==0)) y -= 8; - if (ltc_mp_2expt(tmp, y) != CRYPT_OK || ltc_mp_add(tmp, num, tmp) != CRYPT_OK) { - ltc_mp_clear(tmp); - return CRYPT_MEM; - } - if ((err = ltc_mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { - ltc_mp_clear(tmp); - return err; - } - ltc_mp_clear(tmp); - } - - /* we good */ - *outlen = tmplen; - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_length_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_length_integer.c deleted file mode 100644 index 466f297..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/integer/der_length_integer.c +++ /dev/null @@ -1,55 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_integer.c - ASN.1 DER, get length of encoding, Tom St Denis -*/ - - -#ifdef LTC_DER -/** - Gets length of DER encoding of num - @param num The int to get the size of - @param outlen [out] The length of the DER encoding for the given integer - @return CRYPT_OK if successful -*/ -int der_length_integer(void *num, unsigned long *outlen) -{ - unsigned long z, len; - int leading_zero, err; - - LTC_ARGCHK(num != NULL); - LTC_ARGCHK(outlen != NULL); - - if (ltc_mp_cmp_d(num, 0) != LTC_MP_LT) { - /* positive */ - - /* we only need a leading zero if the msb of the first byte is one */ - if ((ltc_mp_count_bits(num) & 7) == 0 || ltc_mp_iszero(num) == LTC_MP_YES) { - leading_zero = 1; - } else { - leading_zero = 0; - } - - /* size for bignum */ - len = leading_zero + ltc_mp_unsigned_bin_size(num); - } else { - /* it's negative */ - /* find power of 2 that is a multiple of eight and greater than count bits */ - z = ltc_mp_count_bits(num); - z = z + (8 - (z & 7)); - if (((ltc_mp_cnt_lsb(num)+1)==ltc_mp_count_bits(num)) && ((ltc_mp_count_bits(num)&7)==0)) --z; - len = z >> 3; - } - - if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) { - return err; - } - *outlen = 1 + z + len; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c deleted file mode 100644 index 7251247..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_object_identifier.c - ASN.1 DER, Decode Object Identifier, Tom St Denis -*/ - -#ifdef LTC_DER -/** - Decode OID data and store the array of integers in words - @param in The OID DER encoded data - @param inlen The length of the OID data - @param words [out] The destination of the OID words - @param outlen [in/out] The number of OID words - @return CRYPT_OK if successful -*/ -int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, - unsigned long *words, unsigned long *outlen) -{ - unsigned long x, y, t, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(words != NULL); - LTC_ARGCHK(outlen != NULL); - - /* header is at least 3 bytes */ - if (inlen < 3) { - return CRYPT_INVALID_PACKET; - } - - /* must be room for at least two words */ - if (*outlen < 2) { - *outlen = 2; - return CRYPT_BUFFER_OVERFLOW; - } - - /* decode the packet header */ - x = 0; - if ((in[x++] & 0x1F) != 0x06) { - return CRYPT_INVALID_PACKET; - } - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - if ((len == 0) || (len > (inlen - x))) { - return CRYPT_INVALID_PACKET; - } - - /* decode words */ - y = 0; - t = 0; - while (len--) { - t = (t << 7) | (in[x] & 0x7F); - if (!(in[x++] & 0x80)) { - /* store t */ - if (y >= *outlen) { - y++; - } else { - if (y == 0) { - if (t <= 79) { - words[0] = t / 40; - words[1] = t % 40; - } else { - words[0] = 2; - words[1] = t - 80; - } - y = 2; - } else { - words[y++] = t; - } - } - t = 0; - } - } - - if (y > *outlen) { - err = CRYPT_BUFFER_OVERFLOW; - } else { - err = CRYPT_OK; - } - - *outlen = y; - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c deleted file mode 100644 index af56354..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_object_identifier.c - ASN.1 DER, Encode Object Identifier, Tom St Denis -*/ - -#ifdef LTC_DER -/** - Encode an OID - @param words The words to encode (upto 32-bits each) - @param nwords The number of words in the OID - @param out [out] Destination of OID data - @param outlen [in/out] The max and resulting size of the OID - @return CRYPT_OK if successful -*/ -int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, - unsigned char *out, unsigned long *outlen) -{ - unsigned long i, x, y, z, t, mask, wordbuf; - int err; - - LTC_ARGCHK(words != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* check length */ - if ((err = der_length_object_identifier_full(words, nwords, &x, &z)) != CRYPT_OK) { - return err; - } - if (x > *outlen) { - *outlen = x; - return CRYPT_BUFFER_OVERFLOW; - } - - /* store header + length */ - x = 0; - out[x++] = 0x06; - y = *outlen - x; - if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) { - return err; - } - x += y; - - /* store first byte */ - wordbuf = words[0] * 40 + words[1]; - for (i = 1; i < nwords; i++) { - /* store 7 bit words in little endian */ - t = wordbuf; - if (t) { - y = x; - mask = 0; - while (t) { - out[x++] = (unsigned char)((t & 0x7F) | mask); - t >>= 7; - mask |= 0x80; /* upper bit is set on all but the last byte */ - } - /* now swap bytes y...x-1 */ - z = x - 1; - while (y < z) { - t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; - ++y; - --z; - } - } else { - /* zero word */ - out[x++] = 0x00; - } - - if (i < nwords - 1) { - wordbuf = words[i + 1]; - } - } - - *outlen = x; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c deleted file mode 100644 index 8facf74..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c +++ /dev/null @@ -1,89 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_object_identifier.c - ASN.1 DER, get length of Object Identifier, Tom St Denis -*/ - -#ifdef LTC_DER - -static LTC_INLINE unsigned long s_der_object_identifier_bits(unsigned long x) -{ -#if defined(LTC_HAVE_CLZL_BUILTIN) - if (x == 0) - return 0; - return sizeof(unsigned long) * CHAR_BIT - __builtin_clzl(x); -#else - unsigned long c; - c = 0; - while (x) { - ++c; - x >>= 1; - } - return c; -#endif -} - -int der_length_object_identifier_full(const unsigned long *words, unsigned long nwords, unsigned long *outlen, unsigned long *datalen) -{ - unsigned long y, z, t, wordbuf; - - LTC_ARGCHK(words != NULL); - LTC_ARGCHK(outlen != NULL); - - - /* must be >= 2 words */ - if (nwords < 2) { - return CRYPT_INVALID_ARG; - } - - /* word1 = 0,1,2 and word2 0..39 */ - if (words[0] > 2 || (words[0] < 2 && words[1] > 39)) { - return CRYPT_INVALID_ARG; - } - - /* leading word is the first two */ - z = 0; - wordbuf = words[0] * 40 + words[1]; - for (y = 1; y < nwords; y++) { - t = s_der_object_identifier_bits(wordbuf); - z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); - if (y < nwords - 1) { - /* grab next word */ - wordbuf = words[y+1]; - } - } - - if (datalen) { - *datalen = z; - } - /* now depending on the length our length encoding changes */ - if (z < 128) { - z += 2; - } else if (z < 256) { - z += 3; - } else if (z < 65536UL) { - z += 4; - } else { - return CRYPT_INVALID_ARG; - } - - *outlen = z; - return CRYPT_OK; -} - -/** - Gets length of DER encoding of Object Identifier - @param nwords The number of OID words - @param words The actual OID words to get the size of - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen) -{ - return der_length_object_identifier_full(words, nwords, outlen, NULL); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c deleted file mode 100644 index df84721..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c +++ /dev/null @@ -1,69 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_octet_string.c - ASN.1 DER, encode a OCTET STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a OCTET STRING - @param in The DER encoded OCTET STRING - @param inlen The size of the DER OCTET STRING - @param out [out] The array of octets stored (one per char) - @param outlen [in/out] The number of octets stored - @return CRYPT_OK if successful -*/ -int der_decode_octet_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* must have header at least */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check for 0x04 */ - if ((in[0] & 0x1F) != 0x04) { - return CRYPT_INVALID_PACKET; - } - x = 1; - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - /* is it too long? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - if (len > (inlen - x)) { - return CRYPT_INVALID_PACKET; - } - - /* read the data */ - for (y = 0; y < len; y++) { - out[y] = in[x++]; - } - - *outlen = y; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c deleted file mode 100644 index 73f1ee7..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c +++ /dev/null @@ -1,62 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_octet_string.c - ASN.1 DER, encode a OCTET STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store an OCTET STRING - @param in The array of OCTETS to store (one per char) - @param inlen The number of OCTETS to store - @param out [out] The destination for the DER encoded OCTET STRING - @param outlen [in/out] The max size and resulting size of the DER OCTET STRING - @return CRYPT_OK if successful -*/ -int der_encode_octet_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get the size */ - if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { - return err; - } - - /* too big? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* encode the header+len */ - x = 0; - out[x++] = 0x04; - len = *outlen - x; - if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { - return err; - } - x += len; - - /* store octets */ - for (y = 0; y < inlen; y++) { - out[x++] = in[y]; - } - - /* retun length */ - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c deleted file mode 100644 index 67b071e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_octet_string.c - ASN.1 DER, get length of OCTET STRING, Tom St Denis -*/ - -#ifdef LTC_DER -/** - Gets length of DER encoding of OCTET STRING - @param noctets The number of octets in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_octet_string(unsigned long noctets, unsigned long *outlen) -{ - unsigned long x; - int err; - - LTC_ARGCHK(outlen != NULL); - - if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + noctets; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c deleted file mode 100644 index 3f9b533..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_printable_string.c - ASN.1 DER, encode a printable STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a printable STRING - @param in The DER encoded printable STRING - @param inlen The size of the DER printable STRING - @param out [out] The array of octets stored (one per char) - @param outlen [in/out] The number of octets stored - @return CRYPT_OK if successful -*/ -int der_decode_printable_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int t, err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* must have header at least */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check for 0x13 */ - if ((in[0] & 0x1F) != 0x13) { - return CRYPT_INVALID_PACKET; - } - x = 1; - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - /* is it too long? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - if (len > (inlen - x)) { - return CRYPT_INVALID_PACKET; - } - - /* read the data */ - for (y = 0; y < len; y++) { - t = der_printable_value_decode(in[x++]); - if (t == -1) { - return CRYPT_INVALID_ARG; - } - out[y] = t; - } - - *outlen = y; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c deleted file mode 100644 index 7b3aefd..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_printable_string.c - ASN.1 DER, encode a printable STRING, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Store an printable STRING - @param in The array of printable to store (one per char) - @param inlen The number of printable to store - @param out [out] The destination for the DER encoded printable STRING - @param outlen [in/out] The max size and resulting size of the DER printable STRING - @return CRYPT_OK if successful -*/ -int der_encode_printable_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get the size */ - if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { - return err; - } - - /* too big? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* encode the header+len */ - x = 0; - out[x++] = 0x13; - len = *outlen - x; - if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { - return err; - } - x += len; - - /* store octets */ - for (y = 0; y < inlen; y++) { - out[x++] = der_printable_char_encode(in[y]); - } - - /* retun length */ - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c deleted file mode 100644 index dcfcae9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c +++ /dev/null @@ -1,144 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_printable_string.c - ASN.1 DER, get length of Printable STRING, Tom St Denis -*/ - -#ifdef LTC_DER - -static const struct { - int code, value; -} printable_table[] = { -{ ' ', 32 }, -{ '\'', 39 }, -{ '(', 40 }, -{ ')', 41 }, -{ '+', 43 }, -{ ',', 44 }, -{ '-', 45 }, -{ '.', 46 }, -{ '/', 47 }, -{ '0', 48 }, -{ '1', 49 }, -{ '2', 50 }, -{ '3', 51 }, -{ '4', 52 }, -{ '5', 53 }, -{ '6', 54 }, -{ '7', 55 }, -{ '8', 56 }, -{ '9', 57 }, -{ ':', 58 }, -{ '=', 61 }, -{ '?', 63 }, -{ 'A', 65 }, -{ 'B', 66 }, -{ 'C', 67 }, -{ 'D', 68 }, -{ 'E', 69 }, -{ 'F', 70 }, -{ 'G', 71 }, -{ 'H', 72 }, -{ 'I', 73 }, -{ 'J', 74 }, -{ 'K', 75 }, -{ 'L', 76 }, -{ 'M', 77 }, -{ 'N', 78 }, -{ 'O', 79 }, -{ 'P', 80 }, -{ 'Q', 81 }, -{ 'R', 82 }, -{ 'S', 83 }, -{ 'T', 84 }, -{ 'U', 85 }, -{ 'V', 86 }, -{ 'W', 87 }, -{ 'X', 88 }, -{ 'Y', 89 }, -{ 'Z', 90 }, -{ 'a', 97 }, -{ 'b', 98 }, -{ 'c', 99 }, -{ 'd', 100 }, -{ 'e', 101 }, -{ 'f', 102 }, -{ 'g', 103 }, -{ 'h', 104 }, -{ 'i', 105 }, -{ 'j', 106 }, -{ 'k', 107 }, -{ 'l', 108 }, -{ 'm', 109 }, -{ 'n', 110 }, -{ 'o', 111 }, -{ 'p', 112 }, -{ 'q', 113 }, -{ 'r', 114 }, -{ 's', 115 }, -{ 't', 116 }, -{ 'u', 117 }, -{ 'v', 118 }, -{ 'w', 119 }, -{ 'x', 120 }, -{ 'y', 121 }, -{ 'z', 122 }, -}; - -int der_printable_char_encode(int c) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(printable_table); x++) { - if (printable_table[x].code == c) { - return printable_table[x].value; - } - } - return -1; -} - -int der_printable_value_decode(int v) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(printable_table); x++) { - if (printable_table[x].value == v) { - return printable_table[x].code; - } - } - return -1; -} - -/** - Gets length of DER encoding of Printable STRING - @param octets The values you want to encode - @param noctets The number of octets in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) -{ - unsigned long x; - int err; - - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(octets != NULL); - - /* scan string for validity */ - for (x = 0; x < noctets; x++) { - if (der_printable_char_encode(octets[x]) == -1) { - return CRYPT_INVALID_ARG; - } - } - - if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + noctets; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c deleted file mode 100644 index 6d7f846..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -/** - @file der_decode_sequence_ex.c - ASN.1 DER, decode a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Decode a SEQUENCE - @param in The DER encoded input - @param inlen The size of the input - @param list The list of items to decode - @param outlen The number of items in the list - @param flags c.f. enum ltc_der_seq - @return CRYPT_OK on success -*/ -int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *list, unsigned long outlen, unsigned int flags) -{ - return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c deleted file mode 100644 index e434f05..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c +++ /dev/null @@ -1,552 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file der_decode_sequence_flexi.c - ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis -*/ - -#ifdef LTC_DER - -static int s_new_element(ltc_asn1_list **l) -{ - /* alloc new link */ - if (*l == NULL) { - *l = XCALLOC(1, sizeof(ltc_asn1_list)); - if (*l == NULL) { - return CRYPT_MEM; - } - } else { - (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); - if ((*l)->next == NULL) { - return CRYPT_MEM; - } - (*l)->next->prev = *l; - *l = (*l)->next; - } - return CRYPT_OK; -} -#if defined(LTC_TEST_DBG) -void s_print_err(const char *errstr, ltc_asn1_list *l, int err, unsigned long identifier, unsigned long data_offset, unsigned long len) -{ -#if LTC_TEST_DBG <= 1 - if (err == CRYPT_OK) - return; -#endif - if (l->type == LTC_ASN1_CUSTOM_TYPE) { - fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s[%s %llu] (%s)\n", errstr, identifier, data_offset, len, der_asn1_class_to_string_map[l->klass], der_asn1_pc_to_string_map[l->pc], l->tag, error_to_string(err)); - } else { - fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s (%s)\n", errstr, identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); - } -} -#else -#define s_print_err(errstr, l, err, identifier, data_offset, len) LTC_UNUSED_PARAM(data_offset) -#endif - -/** - ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. - @param in The input buffer - @param inlen [in/out] The length of the input buffer and on output the amount of decoded data - @param out [out] A pointer to the linked list - @param depth The depth/level of decoding recursion we've already reached - @return CRYPT_OK on success. -*/ -static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth) -{ - ltc_asn1_list *l; - int err; - unsigned long identifier, len, totlen, data_offset, id_len, len_len; - void *realloc_tmp; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(out != NULL); - - l = NULL; - totlen = 0; - - if (*inlen == 0) { - /* alloc new link */ - if ((err = s_new_element(&l)) != CRYPT_OK) { - goto error; - } - } - - /* scan the input and and get lengths and what not */ - while (*inlen) { - /* alloc new link */ - if ((err = s_new_element(&l)) != CRYPT_OK) { - goto error; - } - - id_len = *inlen; - if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) { - goto error; - } - /* read the type byte */ - identifier = *in; - - if (l->type != LTC_ASN1_EOL) { - /* fetch length */ - len_len = *inlen - id_len; - /* init with dummy values for error cases */ - data_offset = 666; - len = 0; - if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) { - s_print_err("E1", l, err, identifier, data_offset, len); - goto error; - } else if (len > (*inlen - id_len - len_len)) { - err = CRYPT_INVALID_PACKET; - s_print_err("E2", l, err, identifier, data_offset, len); - goto error; - } - data_offset = id_len + len_len; - s_print_err("OK", l, err, identifier, data_offset, len); - len += data_offset; - - if (l->type == LTC_ASN1_CUSTOM_TYPE) { - /* Custom type, use the 'used' field to store the original identifier */ - l->used = identifier; - if (l->pc == LTC_ASN1_PC_CONSTRUCTED) { - /* treat constructed elements like SEQUENCEs */ - identifier = 0x20; - } else { - /* primitive elements are treated as opaque data */ - identifier = 0x80; - } - } - } else { - /* Init this so gcc won't complain, - * as this case will only be hit when we - * can't decode the identifier so the - * switch-case should go to default anyway... - */ - data_offset = 0; - len = 0; - } - - /* now switch on type */ - switch (identifier) { - case 0x01: /* BOOLEAN */ - if (l->type != LTC_ASN1_BOOLEAN) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = 1; - l->data = XCALLOC(1, sizeof(int)); - - if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_boolean(&len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x02: /* INTEGER */ - if (l->type != LTC_ASN1_INTEGER) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = 1; - if ((err = ltc_mp_init(&l->data)) != CRYPT_OK) { - goto error; - } - - /* decode field */ - if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { - goto error; - } - - /* calc length of object */ - if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x03: /* BIT */ - if (l->type != LTC_ASN1_BIT_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */ - - if ((l->data = XCALLOC(1, l->size)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x04: /* OCTET */ - if (l->type != LTC_ASN1_OCTET_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(1, l->size)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x05: /* NULL */ - if (l->type != LTC_ASN1_NULL) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* valid NULL is 0x05 0x00 */ - if (in[0] != 0x05 || in[1] != 0x00) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* simple to store ;-) */ - l->data = NULL; - l->size = 0; - len = 2; - - break; - - case 0x06: /* OID */ - if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { - goto error; - } - - /* resize it to save a bunch of mem */ - if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { - /* out of heap but this is not an error */ - break; - } - l->data = realloc_tmp; - break; - - case 0x0C: /* UTF8 */ - - /* init field */ - if (l->type != LTC_ASN1_UTF8_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - l->size = len; - - if ((l->data = XCALLOC(l->size, sizeof(wchar_t))) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x13: /* PRINTABLE */ - if (l->type != LTC_ASN1_PRINTABLE_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(1, l->size)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x14: /* TELETEXT */ - if (l->type != LTC_ASN1_TELETEX_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(1, l->size)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x16: /* IA5 */ - if (l->type != LTC_ASN1_IA5_STRING) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(1, l->size)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x17: /* UTC TIME */ - if (l->type != LTC_ASN1_UTCTIME) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = 1; - - if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { - err = CRYPT_MEM; - goto error; - } - - len = *inlen; - if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { - goto error; - } - break; - - case 0x18: - if (l->type != LTC_ASN1_GENERALIZEDTIME) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* init field */ - l->size = len; - - if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { - err = CRYPT_MEM; - goto error; - } - - if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { - goto error; - } - - if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { - goto error; - } - - break; - - case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ - case 0x30: /* SEQUENCE */ - case 0x31: /* SET */ - - /* init field */ - if (identifier == 0x20) { - if (l->type != LTC_ASN1_CUSTOM_TYPE) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - } - else if (identifier == 0x30) { - if (l->type != LTC_ASN1_SEQUENCE) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - } - else { - if (l->type != LTC_ASN1_SET) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - } - - /* check that we don't go over the recursion limit */ - if (depth > LTC_DER_MAX_RECURSION) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - if ((l->data = XMALLOC(len)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - XMEMCPY(l->data, in, len); - l->size = len; - - - /* jump to the start of the data */ - in += data_offset; - *inlen -= data_offset; - len -= data_offset; - - /* save the decoded ASN.1 len */ - len_len = len; - - /* Sequence elements go as child */ - if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) { - goto error; - } - if (len_len != len) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - /* len update */ - totlen += data_offset; - - /* the flexi decoder can also do nothing, so make sure a child has been allocated */ - if (l->child) { - /* link them up y0 */ - l->child->parent = l; - } - - break; - - case 0x80: /* Context-specific */ - if (l->type != LTC_ASN1_CUSTOM_TYPE) { - err = CRYPT_PK_ASN1_ERROR; - goto error; - } - - if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { - err = CRYPT_MEM; - goto error; - } - - XMEMCPY(l->data, in + data_offset, len - data_offset); - l->size = len - data_offset; - - break; - - default: - /* invalid byte ... this is a soft error */ - /* remove link */ - if (l->prev) { - l = l->prev; - XFREE(l->next); - l->next = NULL; - } - goto outside; - } - - /* advance pointers */ - totlen += len; - in += len; - *inlen -= len; - } - -outside: - - /* in case we processed anything */ - if (totlen) { - /* rewind l please */ - while (l->prev != NULL || l->parent != NULL) { - if (l->parent != NULL) { - l = l->parent; - } else { - l = l->prev; - } - } - } - - /* return */ - *out = l; - *inlen = totlen; - return CRYPT_OK; - -error: - /* free list */ - der_sequence_free(l); - - return err; -} - -/** - ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. - @param in The input buffer - @param inlen [in/out] The length of the input buffer and on output the amount of decoded data - @param out [out] A pointer to the linked list - @return CRYPT_OK on success. -*/ -int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) -{ - return s_der_decode_sequence_flexi(in, inlen, out, 0); -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c deleted file mode 100644 index 14849f8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c +++ /dev/null @@ -1,184 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file der_decode_sequence_multi.c - ASN.1 DER, decode a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Decode a SEQUENCE type using a VA list - @param in Input buffer - @param inlen Length of input in octets - @param a1 Initialized argument list #1 - @param a2 Initialized argument list #2 (copy of #1) - @param flags c.f. enum ltc_der_seq - @return CRYPT_OK on success -*/ -static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags) -{ - int err; - ltc_asn1_type type; - unsigned long size, x; - void *data; - ltc_asn1_list *list; - - LTC_ARGCHK(in != NULL); - - /* get size of output that will be required */ - x = 0; - for (;;) { - type = (ltc_asn1_type)va_arg(a1, int); - - if (type == LTC_ASN1_EOL) { - break; - } - - size = va_arg(a1, unsigned long); - data = va_arg(a1, void*); - LTC_UNUSED_PARAM(size); - LTC_UNUSED_PARAM(data); - - switch (type) { - case LTC_ASN1_BOOLEAN: - case LTC_ASN1_INTEGER: - case LTC_ASN1_SHORT_INTEGER: - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_OCTET_STRING: - case LTC_ASN1_NULL: - case LTC_ASN1_OBJECT_IDENTIFIER: - case LTC_ASN1_IA5_STRING: - case LTC_ASN1_PRINTABLE_STRING: - case LTC_ASN1_UTF8_STRING: - case LTC_ASN1_UTCTIME: - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - case LTC_ASN1_CHOICE: - case LTC_ASN1_RAW_BIT_STRING: - case LTC_ASN1_TELETEX_STRING: - case LTC_ASN1_GENERALIZEDTIME: - ++x; - break; - - case LTC_ASN1_EOL: - case LTC_ASN1_CUSTOM_TYPE: - return CRYPT_INVALID_ARG; - } - } - - /* allocate structure for x elements */ - if (x == 0) { - return CRYPT_NOP; - } - - list = XCALLOC(x, sizeof(*list)); - if (list == NULL) { - return CRYPT_MEM; - } - - /* fill in the structure */ - x = 0; - for (;;) { - type = (ltc_asn1_type)va_arg(a2, int); - size = va_arg(a2, unsigned long); - data = va_arg(a2, void*); - - if (type == LTC_ASN1_EOL) { - break; - } - - switch (type) { - case LTC_ASN1_BOOLEAN: - case LTC_ASN1_INTEGER: - case LTC_ASN1_SHORT_INTEGER: - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_OCTET_STRING: - case LTC_ASN1_NULL: - case LTC_ASN1_OBJECT_IDENTIFIER: - case LTC_ASN1_IA5_STRING: - case LTC_ASN1_PRINTABLE_STRING: - case LTC_ASN1_UTF8_STRING: - case LTC_ASN1_UTCTIME: - case LTC_ASN1_SEQUENCE: - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_CHOICE: - case LTC_ASN1_RAW_BIT_STRING: - case LTC_ASN1_TELETEX_STRING: - case LTC_ASN1_GENERALIZEDTIME: - LTC_SET_ASN1(list, x++, type, data, size); - break; - /* coverity[dead_error_line] */ - case LTC_ASN1_EOL: - case LTC_ASN1_CUSTOM_TYPE: - break; - } - } - - err = der_decode_sequence_ex(in, inlen, list, x, flags); - XFREE(list); - return err; -} - -/** - Decode a SEQUENCE type using a VA list - @param in Input buffer - @param inlen Length of input in octets - @remark <...> is of the form (int, unsigned long, void*) - @return CRYPT_OK on success -*/ -int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) -{ - va_list a1, a2; - int err; - - LTC_ARGCHK(in != NULL); - - va_start(a1, inlen); - va_start(a2, inlen); - - err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED); - - va_end(a2); - va_end(a1); - - return err; -} - -/** - Decode a SEQUENCE type using a VA list - @param in Input buffer - @param inlen Length of input in octets - @param flags c.f. enum ltc_der_seq - @remark <...> is of the form (int, unsigned long, void*) - @return CRYPT_OK on success -*/ -int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) -{ - va_list a1, a2; - int err; - - LTC_ARGCHK(in != NULL); - - va_start(a1, flags); - va_start(a2, flags); - - err = s_der_decode_sequence_va(in, inlen, a1, a2, flags); - - va_end(a2); - va_end(a1); - - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c deleted file mode 100644 index 2ea33a6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c +++ /dev/null @@ -1,202 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -/** - @file der_encode_sequence_ex.c - ASN.1 DER, encode a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Encode a SEQUENCE - @param list The list of items to encode - @param inlen The number of items in the list - @param out [out] The destination - @param outlen [in/out] The size of the output - @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF - @return CRYPT_OK on success -*/ -int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int type_of) -{ - int err; - ltc_asn1_type type; - unsigned long size, x, y, z, i; - void *data; - - LTC_ARGCHK(list != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get size of output that will be required */ - y = 0; z = 0; - if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; - - /* too big ? */ - if (*outlen < y) { - *outlen = y; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* store header */ - x = 0; - out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31; - - y = *outlen - x; - if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { - goto LBL_ERR; - } - x += y; - - /* store data */ - *outlen -= x; - for (i = 0; i < inlen; i++) { - type = list[i].type; - size = list[i].size; - data = list[i].data; - - if (type == LTC_ASN1_EOL) { - break; - } - - switch (type) { - case LTC_ASN1_BOOLEAN: - z = *outlen; - if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_INTEGER: - z = *outlen; - if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SHORT_INTEGER: - z = *outlen; - if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_BIT_STRING: - z = *outlen; - if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_RAW_BIT_STRING: - z = *outlen; - if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_OCTET_STRING: - z = *outlen; - if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_NULL: - out[x] = 0x05; - out[x+1] = 0x00; - z = 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - z = *outlen; - if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_IA5_STRING: - z = *outlen; - if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_PRINTABLE_STRING: - z = *outlen; - if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTF8_STRING: - z = *outlen; - if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_UTCTIME: - z = *outlen; - if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_GENERALIZEDTIME: - z = *outlen; - if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SET: - z = *outlen; - if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SETOF: - z = *outlen; - if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_SEQUENCE: - z = *outlen; - if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CUSTOM_TYPE: - z = *outlen; - if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { - goto LBL_ERR; - } - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_EOL: - case LTC_ASN1_TELETEX_STRING: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - - x += z; - *outlen -= z; - } - *outlen = x; - err = CRYPT_OK; - -LBL_ERR: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c deleted file mode 100644 index cd61d3a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c +++ /dev/null @@ -1,142 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file der_encode_sequence_multi.c - ASN.1 DER, encode a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Encode a SEQUENCE type using a VA list - @param out [out] Destination for data - @param outlen [in/out] Length of buffer and resulting length of output - @remark <...> is of the form (int, unsigned long, void*) - @return CRYPT_OK on success -*/ -int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) -{ - int err; - ltc_asn1_type type; - unsigned long size, x; - void *data; - va_list args; - ltc_asn1_list *list; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get size of output that will be required */ - va_start(args, outlen); - x = 0; - for (;;) { - type = (ltc_asn1_type)va_arg(args, int); - - if (type == LTC_ASN1_EOL) { - break; - } - - size = va_arg(args, unsigned long); - data = va_arg(args, void*); - LTC_UNUSED_PARAM(size); - LTC_UNUSED_PARAM(data); - - switch (type) { - case LTC_ASN1_BOOLEAN: - case LTC_ASN1_INTEGER: - case LTC_ASN1_SHORT_INTEGER: - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_OCTET_STRING: - case LTC_ASN1_NULL: - case LTC_ASN1_OBJECT_IDENTIFIER: - case LTC_ASN1_IA5_STRING: - case LTC_ASN1_PRINTABLE_STRING: - case LTC_ASN1_UTF8_STRING: - case LTC_ASN1_UTCTIME: - case LTC_ASN1_SEQUENCE: - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_RAW_BIT_STRING: - case LTC_ASN1_GENERALIZEDTIME: - ++x; - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_CUSTOM_TYPE: - case LTC_ASN1_EOL: - case LTC_ASN1_TELETEX_STRING: - va_end(args); - return CRYPT_INVALID_ARG; - } - } - va_end(args); - - /* allocate structure for x elements */ - if (x == 0) { - return CRYPT_NOP; - } - - list = XCALLOC(x, sizeof(*list)); - if (list == NULL) { - return CRYPT_MEM; - } - - /* fill in the structure */ - va_start(args, outlen); - x = 0; - for (;;) { - type = (ltc_asn1_type)va_arg(args, int); - - if (type == LTC_ASN1_EOL) { - break; - } - - size = va_arg(args, unsigned long); - data = va_arg(args, void*); - - switch (type) { - case LTC_ASN1_BOOLEAN: - case LTC_ASN1_INTEGER: - case LTC_ASN1_SHORT_INTEGER: - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_OCTET_STRING: - case LTC_ASN1_NULL: - case LTC_ASN1_OBJECT_IDENTIFIER: - case LTC_ASN1_IA5_STRING: - case LTC_ASN1_PRINTABLE_STRING: - case LTC_ASN1_UTF8_STRING: - case LTC_ASN1_UTCTIME: - case LTC_ASN1_SEQUENCE: - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_RAW_BIT_STRING: - case LTC_ASN1_GENERALIZEDTIME: - LTC_SET_ASN1(list, x++, type, data, size); - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_CUSTOM_TYPE: - case LTC_ASN1_EOL: - case LTC_ASN1_TELETEX_STRING: - va_end(args); - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - } - va_end(args); - - err = der_encode_sequence(list, x, out, outlen); -LBL_ERR: - XFREE(list); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c deleted file mode 100644 index 026eb50..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_flexi_sequence_cmp.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_sequence.c - ASN.1 DER, length a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Get the length of a DER sequence - @param list The sequences of items in the SEQUENCE - @param inlen The number of items - @param outlen [out] The length required in octets to store it - @return CRYPT_OK on success -*/ - -int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check) -{ - ltc_asn1_list *cur; - if (flexi->type != LTC_ASN1_SEQUENCE) { - return CRYPT_INVALID_PACKET; - } - cur = flexi->child; - while(check->t != LTC_ASN1_EOL) { - if (!LTC_ASN1_IS_TYPE(cur, check->t)) { - return CRYPT_INVALID_PACKET; - } - if (check->pp != NULL) *check->pp = cur; - cur = cur->next; - check++; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c deleted file mode 100644 index 6d25391..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c +++ /dev/null @@ -1,179 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_sequence.c - ASN.1 DER, length a SEQUENCE, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Get the length of a DER sequence - @param list The sequences of items in the SEQUENCE - @param inlen The number of items - @param outlen [out] The length required in octets to store it - @return CRYPT_OK on success -*/ -int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, - unsigned long *outlen) -{ - return der_length_sequence_ex(list, inlen, outlen, NULL); -} - -int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, - unsigned long *outlen, unsigned long *payloadlen) -{ - int err; - ltc_asn1_type type; - unsigned long size, x, y, i; - void *data; - - LTC_ARGCHK(list != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get size of output that will be required */ - y = 0; - for (i = 0; i < inlen; i++) { - type = list[i].type; - size = list[i].size; - data = list[i].data; - - if (type == LTC_ASN1_EOL) { - break; - } - - /* some items may be optional during import */ - if (!list[i].used && list[i].optional) continue; - - switch (type) { - case LTC_ASN1_BOOLEAN: - if ((err = der_length_boolean(&x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_INTEGER: - if ((err = der_length_integer(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SHORT_INTEGER: - if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_BIT_STRING: - case LTC_ASN1_RAW_BIT_STRING: - if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_OCTET_STRING: - if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_NULL: - y += 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_IA5_STRING: - if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_TELETEX_STRING: - if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_PRINTABLE_STRING: - if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTCTIME: - if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_GENERALIZEDTIME: - if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTF8_STRING: - if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_CUSTOM_TYPE: - if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_CHOICE: - case LTC_ASN1_EOL: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - } - - if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - - if (payloadlen != NULL) { - *payloadlen = y; - } - - /* store size */ - *outlen = y + x + 1; - err = CRYPT_OK; - -LBL_ERR: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c deleted file mode 100644 index 63908a5..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_sequence_free.c - ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Free memory allocated by der_decode_sequence_flexi() - @param in The list to free -*/ -void der_sequence_free(ltc_asn1_list *in) -{ - ltc_asn1_list *l; - - if (!in) return; - - /* walk to the start of the chain */ - while (in->prev != NULL || in->parent != NULL) { - if (in->parent != NULL) { - in = in->parent; - } else { - in = in->prev; - } - } - - /* now walk the list and free stuff */ - while (in != NULL) { - /* is there a child? */ - if (in->child) { - /* disconnect */ - in->child->parent = NULL; - der_sequence_free(in->child); - } - - switch (in->type) { - case LTC_ASN1_SETOF: break; - case LTC_ASN1_INTEGER : if (in->data != NULL) { ltc_mp_clear(in->data); } break; - default : if (in->data != NULL) { XFREE(in->data); } - } - - /* move to next and free current */ - l = in->next; - XFREE(in); - in = l; - } -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c deleted file mode 100644 index 22634a3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/sequence/der_sequence_shrink.c +++ /dev/null @@ -1,40 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_sequence_shrink.c - Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel -*/ - -#ifdef LTC_DER - -/** - Free memory allocated for CONSTRUCTED, - SET or SEQUENCE elements by der_decode_sequence_flexi() - @param in The list to shrink -*/ -void der_sequence_shrink(ltc_asn1_list *in) -{ - if (!in) return; - - /* now walk the list and free stuff */ - while (in != NULL) { - /* is there a child? */ - if (in->child) { - der_sequence_shrink(in->child); - } - - switch (in->type) { - case LTC_ASN1_CUSTOM_TYPE: - case LTC_ASN1_SET: - case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break; - default: break; - } - - /* move to next and free current */ - in = in->next; - } -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_set.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_set.c deleted file mode 100644 index f72bea3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_set.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file der_encode_set.c - ASN.1 DER, Encode a SET, Tom St Denis -*/ - -#ifdef LTC_DER - -/* LTC define to ASN.1 TAG */ -static int s_ltc_to_asn1(ltc_asn1_type v) -{ - return der_asn1_type_to_identifier_map[v]; -} - -#define s_qsort_helper s_set_qsort_helper -static int s_qsort_helper(const void *a, const void *b) -{ - ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; - int r; - - r = s_ltc_to_asn1(A->type) - s_ltc_to_asn1(B->type); - - /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */ - if (r == 0) { - /* their order in the original list now determines the position */ - return A->used - B->used; - } - return r; -} - -/* - Encode a SET type - @param list The list of items to encode - @param inlen The number of items in the list - @param out [out] The destination - @param outlen [in/out] The size of the output - @return CRYPT_OK on success -*/ -int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - ltc_asn1_list *copy; - unsigned long x; - int err; - - /* make copy of list */ - copy = XCALLOC(inlen, sizeof(*copy)); - if (copy == NULL) { - return CRYPT_MEM; - } - - /* fill in used member with index so we can fully sort it */ - for (x = 0; x < inlen; x++) { - copy[x] = list[x]; - copy[x].used = x; - } - - /* sort it by the "type" field */ - XQSORT(copy, inlen, sizeof(*copy), &s_qsort_helper); - - /* call der_encode_sequence_ex() */ - err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); - - /* free list */ - XFREE(copy); - - return err; -} - -#undef s_qsort_helper - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_setof.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_setof.c deleted file mode 100644 index 6cf44b3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/set/der_encode_setof.c +++ /dev/null @@ -1,154 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_setof.c - ASN.1 DER, Encode SET OF, Tom St Denis -*/ - -#ifdef LTC_DER - -struct edge { - unsigned char *start; - unsigned long size; -}; - -#define s_qsort_helper s_setof_qsort_helper -static int s_qsort_helper(const void *a, const void *b) -{ - struct edge *A = (struct edge *)a, *B = (struct edge *)b; - int r; - unsigned long x; - - /* compare min length */ - r = XMEMCMP(A->start, B->start, MIN(A->size, B->size)); - - if (r == 0 && A->size != B->size) { - if (A->size > B->size) { - for (x = B->size; x < A->size; x++) { - if (A->start[x]) { - return 1; - } - } - } else { - for (x = A->size; x < B->size; x++) { - if (B->start[x]) { - return -1; - } - } - } - } - - return r; -} - -/** - Encode a SETOF stucture - @param list The list of items to encode - @param inlen The number of items in the list - @param out [out] The destination - @param outlen [in/out] The size of the output - @return CRYPT_OK on success -*/ -int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, z; - ptrdiff_t hdrlen; - int err; - struct edge *edges; - unsigned char *ptr, *buf; - - /* check that they're all the same type */ - for (x = 1; x < inlen; x++) { - if (list[x].type != list[x-1].type) { - return CRYPT_INVALID_ARG; - } - } - - /* alloc buffer to store copy of output */ - buf = XCALLOC(1, *outlen); - if (buf == NULL) { - return CRYPT_MEM; - } - - /* encode list */ - if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) { - XFREE(buf); - return err; - } - - /* allocate edges */ - edges = XCALLOC(inlen, sizeof(*edges)); - if (edges == NULL) { - XFREE(buf); - return CRYPT_MEM; - } - - /* skip header */ - ptr = buf + 1; - - /* now skip length data */ - x = *ptr++; - if (x >= 0x80) { - ptr += (x & 0x7F); - } - - /* get the size of the static header */ - hdrlen = ptr - buf; - - - /* scan for edges */ - x = 0; - while (ptr < (buf + *outlen)) { - /* store start */ - edges[x].start = ptr; - - /* skip type */ - z = 1; - - /* parse length */ - y = ptr[z++]; - if (y < 128) { - edges[x].size = y; - } else { - y &= 0x7F; - edges[x].size = 0; - while (y--) { - edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]); - } - } - - /* skip content */ - edges[x].size += z; - ptr += edges[x].size; - ++x; - } - - /* sort based on contents (using edges) */ - XQSORT(edges, inlen, sizeof(*edges), &s_qsort_helper); - - /* copy static header */ - XMEMCPY(out, buf, hdrlen); - - /* copy+sort using edges+indecies to output from buffer */ - for (y = (unsigned long)hdrlen, x = 0; x < inlen; x++) { - XMEMCPY(out+y, edges[x].start, edges[x].size); - y += edges[x].size; - } - -#ifdef LTC_CLEAN_STACK - zeromem(buf, *outlen); -#endif - - /* free buffers */ - XFREE(edges); - XFREE(buf); - - return CRYPT_OK; -} - -#undef s_qsort_helper - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c deleted file mode 100644 index e00702d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c +++ /dev/null @@ -1,60 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_short_integer.c - ASN.1 DER, decode an integer, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Read a short integer - @param in The DER encoded data - @param inlen Size of data - @param num [out] The integer to decode - @return CRYPT_OK if successful -*/ -int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) -{ - unsigned long len, x, y; - - LTC_ARGCHK(num != NULL); - LTC_ARGCHK(in != NULL); - - /* check length */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check header */ - x = 0; - if ((in[x++] & 0x1F) != 0x02) { - return CRYPT_INVALID_PACKET; - } - - /* get the packet len */ - len = in[x++]; - - if (x + len > inlen) { - return CRYPT_INVALID_PACKET; - } - - if (len > sizeof(unsigned long)) { - return CRYPT_OVERFLOW; - } - - /* read number */ - y = 0; - while (len--) { - y = (y<<8) | (unsigned long)in[x++]; - } - *num = y; - - return CRYPT_OK; - -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c deleted file mode 100644 index 3af47c5..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c +++ /dev/null @@ -1,85 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_short_integer.c - ASN.1 DER, encode an integer, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store a short integer in the range (0,2^32-1) - @param num The integer to encode - @param out [out] The destination for the DER encoded integers - @param outlen [in/out] The max size and resulting size of the DER encoded integers - @return CRYPT_OK if successful -*/ -int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) -{ - unsigned long len, x, y, z; - int err; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* force to 32 bits */ - num &= 0xFFFFFFFFUL; - - /* find out how big this will be */ - if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) { - return err; - } - - if (*outlen < len) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - /* get len of output */ - z = 0; - y = num; - while (y) { - ++z; - y >>= 8; - } - - /* handle zero */ - if (z == 0) { - z = 1; - } - - /* see if msb is set */ - z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; - - /* adjust the number so the msB is non-zero */ - for (x = 0; (z <= 4) && (x < (4 - z)); x++) { - num <<= 8; - } - - /* store header */ - x = 0; - out[x++] = 0x02; - out[x++] = (unsigned char)z; - - /* if 31st bit is set output a leading zero and decrement count */ - if (z == 5) { - out[x++] = 0; - --z; - } - - /* store values */ - for (y = 0; y < z; y++) { - out[x++] = (unsigned char)((num >> 24) & 0xFF); - num <<= 8; - } - - /* we good */ - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c deleted file mode 100644 index aeee948..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c +++ /dev/null @@ -1,52 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_short_integer.c - ASN.1 DER, get length of encoding, Tom St Denis -*/ - - -#ifdef LTC_DER -/** - Gets length of DER encoding of num - @param num The integer to get the size of - @param outlen [out] The length of the DER encoding for the given integer - @return CRYPT_OK if successful -*/ -int der_length_short_integer(unsigned long num, unsigned long *outlen) -{ - unsigned long z, y; - int err; - - LTC_ARGCHK(outlen != NULL); - - /* force to 32 bits */ - num &= 0xFFFFFFFFUL; - - /* get the number of bytes */ - z = 0; - y = num; - while (y) { - ++z; - y >>= 8; - } - - /* handle zero */ - if (z == 0) { - z = 1; - } else if ((num&(1UL<<((z<<3) - 1))) != 0) { - /* in case msb is set */ - ++z; - } - - if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) { - return err; - } - *outlen = 1 + y + z; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c deleted file mode 100644 index 6779cd5..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_decode_teletex_string.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_teletex_string.c - ASN.1 DER, encode a teletex STRING -*/ - -#ifdef LTC_DER - -/** - Store a teletex STRING - @param in The DER encoded teletex STRING - @param inlen The size of the DER teletex STRING - @param out [out] The array of octets stored (one per char) - @param outlen [in/out] The number of octets stored - @return CRYPT_OK if successful -*/ -int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int t, err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* must have header at least */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check for 0x14 */ - if ((in[0] & 0x1F) != 0x14) { - return CRYPT_INVALID_PACKET; - } - x = 1; - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - /* is it too long? */ - if (len > *outlen) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - - if (len > (inlen - x)) { - return CRYPT_INVALID_PACKET; - } - - /* read the data */ - for (y = 0; y < len; y++) { - t = der_teletex_value_decode(in[x++]); - if (t == -1) { - return CRYPT_INVALID_ARG; - } - out[y] = t; - } - - *outlen = y; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c deleted file mode 100644 index 01b94a3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/teletex_string/der_length_teletex_string.c +++ /dev/null @@ -1,188 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_teletex_string.c - ASN.1 DER, get length of teletex STRING -*/ - -#ifdef LTC_DER - -static const struct { - int code, value; -} teletex_table[] = { -{ '\0', 0 }, -{ '\a', 7 }, -{ '\b', 8 }, -{ '\t', 9 }, -{ '\n', 10 }, -{ '\v', 11 }, -{ '\f', 12 }, -{ '\r', 13 }, -{ ' ', 32 }, -{ '!', 33 }, -{ '"', 34 }, -{ '%', 37 }, -{ '&', 38 }, -{ '\'', 39 }, -{ '(', 40 }, -{ ')', 41 }, -{ '+', 43 }, -{ ',', 44 }, -{ '-', 45 }, -{ '.', 46 }, -{ '/', 47 }, -{ '0', 48 }, -{ '1', 49 }, -{ '2', 50 }, -{ '3', 51 }, -{ '4', 52 }, -{ '5', 53 }, -{ '6', 54 }, -{ '7', 55 }, -{ '8', 56 }, -{ '9', 57 }, -{ ':', 58 }, -{ ';', 59 }, -{ '<', 60 }, -{ '=', 61 }, -{ '>', 62 }, -{ '?', 63 }, -{ '@', 64 }, -{ 'A', 65 }, -{ 'B', 66 }, -{ 'C', 67 }, -{ 'D', 68 }, -{ 'E', 69 }, -{ 'F', 70 }, -{ 'G', 71 }, -{ 'H', 72 }, -{ 'I', 73 }, -{ 'J', 74 }, -{ 'K', 75 }, -{ 'L', 76 }, -{ 'M', 77 }, -{ 'N', 78 }, -{ 'O', 79 }, -{ 'P', 80 }, -{ 'Q', 81 }, -{ 'R', 82 }, -{ 'S', 83 }, -{ 'T', 84 }, -{ 'U', 85 }, -{ 'V', 86 }, -{ 'W', 87 }, -{ 'X', 88 }, -{ 'Y', 89 }, -{ 'Z', 90 }, -{ '[', 91 }, -{ ']', 93 }, -{ '_', 95 }, -{ 'a', 97 }, -{ 'b', 98 }, -{ 'c', 99 }, -{ 'd', 100 }, -{ 'e', 101 }, -{ 'f', 102 }, -{ 'g', 103 }, -{ 'h', 104 }, -{ 'i', 105 }, -{ 'j', 106 }, -{ 'k', 107 }, -{ 'l', 108 }, -{ 'm', 109 }, -{ 'n', 110 }, -{ 'o', 111 }, -{ 'p', 112 }, -{ 'q', 113 }, -{ 'r', 114 }, -{ 's', 115 }, -{ 't', 116 }, -{ 'u', 117 }, -{ 'v', 118 }, -{ 'w', 119 }, -{ 'x', 120 }, -{ 'y', 121 }, -{ 'z', 122 }, -{ '|', 124 }, -{ ' ', 160 }, -{ 0xa1, 161 }, -{ 0xa2, 162 }, -{ 0xa3, 163 }, -{ '$', 164 }, -{ 0xa5, 165 }, -{ '#', 166 }, -{ 0xa7, 167 }, -{ 0xa4, 168 }, -{ 0xab, 171 }, -{ 0xb0, 176 }, -{ 0xb1, 177 }, -{ 0xb2, 178 }, -{ 0xb3, 179 }, -{ 0xd7, 180 }, -{ 0xb5, 181 }, -{ 0xb6, 182 }, -{ 0xb7, 183 }, -{ 0xf7, 184 }, -{ 0xbb, 187 }, -{ 0xbc, 188 }, -{ 0xbd, 189 }, -{ 0xbe, 190 }, -{ 0xbf, 191 }, -}; - -int der_teletex_char_encode(int c) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(teletex_table); x++) { - if (teletex_table[x].code == c) { - return teletex_table[x].value; - } - } - return -1; -} - -int der_teletex_value_decode(int v) -{ - int x; - for (x = 0; x < (int)LTC_ARRAY_SIZE(teletex_table); x++) { - if (teletex_table[x].value == v) { - return teletex_table[x].code; - } - } - return -1; -} - -/** - Gets length of DER encoding of teletex STRING - @param octets The values you want to encode - @param noctets The number of octets in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) -{ - unsigned long x; - int err; - - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(octets != NULL); - - /* scan string for validity */ - for (x = 0; x < noctets; x++) { - if (der_teletex_char_encode(octets[x]) == -1) { - return CRYPT_INVALID_ARG; - } - } - - if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + noctets; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c deleted file mode 100644 index 4c78c97..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c +++ /dev/null @@ -1,121 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_utctime.c - ASN.1 DER, decode a UTCTIME, Tom St Denis -*/ - -#ifdef LTC_DER - -#ifndef LTC_DER_CHAR_TO_INT -#define LTC_DER_CHAR_TO_INT -static LTC_INLINE int s_char_to_int(unsigned char x) -{ - switch (x) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - default: return 100; - } -} -#endif - -#define DECODE_V(y, max) \ - y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ - if (y >= max) return CRYPT_INVALID_PACKET; \ - x += 2; - -/** - Decodes a UTC time structure in DER format (reads all 6 valid encoding formats) - @param in Input buffer - @param inlen Length of input buffer in octets - @param out [out] Destination of UTC time structure - @return CRYPT_OK if successful -*/ -int der_decode_utctime(const unsigned char *in, unsigned long *inlen, - ltc_utctime *out) -{ - unsigned char buf[32] = { 0 }; /* initialize as all zeroes */ - unsigned long x; - int y; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - LTC_ARGCHK(out != NULL); - - /* check header */ - if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { - return CRYPT_INVALID_PACKET; - } - - /* decode the string */ - for (x = 0; x < in[1]; x++) { - y = der_ia5_value_decode(in[x+2]); - if (y == -1) { - return CRYPT_INVALID_PACKET; - } - buf[x] = y; - } - *inlen = 2 + x; - - - /* possible encodings are -YYMMDDhhmmZ -YYMMDDhhmm+hh'mm' -YYMMDDhhmm-hh'mm' -YYMMDDhhmmssZ -YYMMDDhhmmss+hh'mm' -YYMMDDhhmmss-hh'mm' - - So let's do a trivial decode upto [including] mm - */ - - x = 0; - DECODE_V(out->YY, 100); - DECODE_V(out->MM, 13); - DECODE_V(out->DD, 32); - DECODE_V(out->hh, 24); - DECODE_V(out->mm, 60); - - /* clear timezone and seconds info */ - out->off_dir = out->off_hh = out->off_mm = out->ss = 0; - - /* now is it Z, +, - or 0-9 */ - if (buf[x] == 'Z') { - return CRYPT_OK; - } - if (buf[x] == '+' || buf[x] == '-') { - out->off_dir = (buf[x++] == '+') ? 0 : 1; - DECODE_V(out->off_hh, 24); - DECODE_V(out->off_mm, 60); - return CRYPT_OK; - } - - /* decode seconds */ - DECODE_V(out->ss, 60); - - /* now is it Z, +, - */ - if (buf[x] == 'Z') { - return CRYPT_OK; - } - if (buf[x] == '+' || buf[x] == '-') { - out->off_dir = (buf[x++] == '+') ? 0 : 1; - DECODE_V(out->off_hh, 24); - DECODE_V(out->off_mm, 60); - return CRYPT_OK; - } - return CRYPT_INVALID_PACKET; -} - -#undef DECODE_V - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c deleted file mode 100644 index a48972e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c +++ /dev/null @@ -1,72 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_utctime.c - ASN.1 DER, encode a UTCTIME, Tom St Denis -*/ - -#ifdef LTC_DER - -#define STORE_V(y) \ - out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ - out[x++] = der_ia5_char_encode(baseten[y % 10]); - -/** - Encodes a UTC time structure in DER format - @param utctime The UTC time structure to encode - @param out The destination of the DER encoding of the UTC time structure - @param outlen [in/out] The length of the DER encoding - @return CRYPT_OK if successful -*/ -int der_encode_utctime(const ltc_utctime *utctime, - unsigned char *out, unsigned long *outlen) -{ - const char * const baseten = "0123456789"; - unsigned long x, tmplen; - int err; - - LTC_ARGCHK(utctime != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) { - return err; - } - if (tmplen > *outlen) { - *outlen = tmplen; - return CRYPT_BUFFER_OVERFLOW; - } - - /* store header */ - out[0] = 0x17; - - /* store values */ - x = 2; - STORE_V(utctime->YY); - STORE_V(utctime->MM); - STORE_V(utctime->DD); - STORE_V(utctime->hh); - STORE_V(utctime->mm); - STORE_V(utctime->ss); - - if (utctime->off_mm || utctime->off_hh) { - out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+'); - STORE_V(utctime->off_hh); - STORE_V(utctime->off_mm); - } else { - out[x++] = der_ia5_char_encode('Z'); - } - - /* store length */ - out[1] = (unsigned char)(x - 2); - - /* all good let's return */ - *outlen = x; - return CRYPT_OK; -} - -#undef STORE_V - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c deleted file mode 100644 index b93c25f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c +++ /dev/null @@ -1,34 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_utctime.c - ASN.1 DER, get length of UTCTIME, Tom St Denis -*/ - -#ifdef LTC_DER - -/** - Gets length of DER encoding of UTCTIME - @param utctime The UTC time structure to get the size of - @param outlen [out] The length of the DER encoding - @return CRYPT_OK if successful -*/ -int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen) -{ - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(utctime != NULL); - - if (utctime->off_hh == 0 && utctime->off_mm == 0) { - /* we encode as YYMMDDhhmmssZ */ - *outlen = 2 + 13; - } else { - /* we encode as YYMMDDhhmmss{+|-}hh'mm' */ - *outlen = 2 + 17; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c deleted file mode 100644 index ee543dd..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c +++ /dev/null @@ -1,118 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_decode_utf8_string.c - ASN.1 DER, encode a UTF8 STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Decode a UTF8 STRING and recover an array of unicode characters. - @param in The DER encoded UTF8 STRING - @param inlen The size of the DER UTF8 STRING - @param out [out] The array of unicode characters (wchar_t*) - @param outlen [in/out] The number of unicode characters in the array - @return CRYPT_OK if successful -*/ -int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, - wchar_t *out, unsigned long *outlen) -{ - wchar_t tmp; - unsigned long x, y, z, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* must have header at least */ - if (inlen < 2) { - return CRYPT_INVALID_PACKET; - } - - /* check for 0x0C */ - if ((in[0] & 0x1F) != 0x0C) { - return CRYPT_INVALID_PACKET; - } - x = 1; - - /* get the length of the data */ - y = inlen - x; - if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { - return err; - } - x += y; - - if (len > (inlen - x)) { - return CRYPT_INVALID_PACKET; - } - - /* proceed to recover unicode characters from utf8 data. - for reference see Section 3 of RFC 3629: - - https://tools.ietf.org/html/rfc3629#section-3 - */ - len += x; - for (y = 0; x < len; ) { - /* read first byte */ - tmp = in[x++]; - - /* a unicode character is recovered from a sequence of 1 to 4 utf8 bytes. - the form of those bytes must match a row in the following table: - - 0xxxxxxx - 110xxxxx 10xxxxxx - 1110xxxx 10xxxxxx 10xxxxxx - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - the number of leading ones in the first byte (0,2,3,4) determines the - number of remaining bytes to read (0,1,2,3) - */ - - /* determine z, the number of leading ones. - this is done by left-shifting tmp, which clears the ms-bits */ - for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); - - /* z should be in {0,2,3,4} */ - if (z == 1 || z > 4) { - return CRYPT_INVALID_PACKET; - } - - /* right-shift tmp to restore least-sig bits */ - tmp >>= z; - - /* now update z so it equals the number of additional bytes to read */ - if (z > 0) { --z; } - - if (x + z > len) { - return CRYPT_INVALID_PACKET; - } - - /* read remaining bytes */ - while (z-- != 0) { - if ((in[x] & 0xC0) != 0x80) { - return CRYPT_INVALID_PACKET; - } - tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); - } - - if (y < *outlen) { - out[y] = tmp; - } - y++; - } - if (y > *outlen) { - err = CRYPT_BUFFER_OVERFLOW; - } else { - err = CRYPT_OK; - } - *outlen = y; - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c deleted file mode 100644 index f2c07c2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c +++ /dev/null @@ -1,75 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_encode_utf8_string.c - ASN.1 DER, encode a UTF8 STRING, Tom St Denis -*/ - - -#ifdef LTC_DER - -/** - Store an UTF8 STRING - @param in The array of UTF8 to store (one per wchar_t) - @param inlen The number of UTF8 to store - @param out [out] The destination for the DER encoded UTF8 STRING - @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING - @return CRYPT_OK if successful -*/ -int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x, y, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get the size */ - for (x = len = 0; x < inlen; x++) { - if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; - len += der_utf8_charsize(in[x]); - } - if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { - return err; - } - x += len + 1; - - /* too big? */ - if (x > *outlen) { - *outlen = x; - return CRYPT_BUFFER_OVERFLOW; - } - - /* encode the header+len */ - x = 0; - out[x++] = 0x0C; - - y = *outlen - x; - if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) { - return err; - } - x += y; - - /* store UTF8 */ - for (y = 0; y < inlen; y++) { - switch (der_utf8_charsize(in[y])) { - case 1: out[x++] = (unsigned char)in[y]; break; - case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break; - case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; -#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF - case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; -#endif - } - } - - /* return length */ - *outlen = x; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c deleted file mode 100644 index 424002b..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file der_length_utf8_string.c - ASN.1 DER, get length of UTF8 STRING, Tom St Denis -*/ - -#ifdef LTC_DER - -/** Return the size in bytes of a UTF-8 character - @param c The UTF-8 character to measure - @return The size in bytes -*/ -unsigned long der_utf8_charsize(const wchar_t c) -{ - if (c <= 0x7F) { - return 1; - } - if (c <= 0x7FF) { - return 2; - } -#if LTC_WCHAR_MAX == 0xFFFF - return 3; -#else - if (c <= 0xFFFF) { - return 3; - } - return 4; -#endif -} - -/** - Test whether the given code point is valid character - @param c The UTF-8 character to test - @return 1 - valid, 0 - invalid -*/ -int der_utf8_valid_char(const wchar_t c) -{ - LTC_UNUSED_PARAM(c); -#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF - if (c > 0x10FFFF) return 0; -#endif -#if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF - if (c < 0) return 0; -#endif - return 1; -} - -/** - Gets length of DER encoding of UTF8 STRING - @param in The characters to measure the length of - @param noctets The number of octets in the string to encode - @param outlen [out] The length of the DER encoding for the given string - @return CRYPT_OK if successful -*/ -int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen) -{ - unsigned long x, len; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(outlen != NULL); - - len = 0; - for (x = 0; x < noctets; x++) { - if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; - len += der_utf8_charsize(in[x]); - } - - if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { - return err; - } - *outlen = 1 + x + len; - - return CRYPT_OK; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_get.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_get.c deleted file mode 100644 index 1fd5872..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_get.c +++ /dev/null @@ -1,106 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_DER - -typedef struct { - enum ltc_oid_id id; - enum ltc_pka_id pka; - const char* oid; -} oid_table_entry; - -static const oid_table_entry pka_oids[] = { - { LTC_OID_UNDEF, LTC_PKA_UNDEF, NULL }, - { LTC_OID_RSA, LTC_PKA_RSA, "1.2.840.113549.1.1.1" }, - { LTC_OID_DSA, LTC_PKA_DSA, "1.2.840.10040.4.1" }, - { LTC_OID_EC, LTC_PKA_EC, "1.2.840.10045.2.1" }, - { LTC_OID_EC_PRIMEF, LTC_PKA_EC, "1.2.840.10045.1.1" }, - { LTC_OID_X25519, LTC_PKA_X25519, "1.3.101.110" }, - { LTC_OID_ED25519, LTC_PKA_ED25519, "1.3.101.112" }, - { LTC_OID_DH, LTC_PKA_DH, "1.2.840.113549.1.3.1" }, -}; - -static LTC_INLINE const oid_table_entry* s_get_entry(enum ltc_oid_id id) -{ - if (id < LTC_OID_NUM) - return &pka_oids[id]; - return NULL; -} - -/* - Returns the OID requested. - @return CRYPT_OK if valid -*/ -int pk_get_oid(enum ltc_oid_id id, const char **st) -{ - const oid_table_entry* e = s_get_entry(id); - LTC_ARGCHK(st != NULL); - if (e != NULL) { - *st = e->oid; - return CRYPT_OK; - } - return CRYPT_INVALID_ARG; -} - -/* - Returns the PKA ID requested. - @return CRYPT_OK if valid -*/ -int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka) -{ - const oid_table_entry* e = s_get_entry(id); - LTC_ARGCHK(pka != NULL); - if (e != NULL) { - *pka = e->pka; - return CRYPT_OK; - } - return CRYPT_INVALID_ARG; -} - -/* - Returns the OID ID requested. - @return CRYPT_OK if valid -*/ -int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid) -{ - unsigned int i; - LTC_ARGCHK(oid != NULL); - for (i = 1; i < LTC_ARRAY_SIZE(pka_oids); ++i) { - if (pka_oids[i].pka == pka) { - *oid = pka_oids[i].id; - return CRYPT_OK; - } - } - return CRYPT_INVALID_ARG; -} - -/* - Returns the PKA ID of an OID. - @return CRYPT_OK if valid -*/ -int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id) -{ - unsigned long i; - char tmp[LTC_OID_MAX_STRLEN] = { 0 }; - int err; - - LTC_ARGCHK(oid != NULL); - LTC_ARGCHK(id != NULL); - - if (oid->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG; - - i = sizeof(tmp); - if ((err = pk_oid_num_to_str(oid->data, oid->size, tmp, &i)) != CRYPT_OK) { - return err; - } - - for (i = 1; i < LTC_ARRAY_SIZE(pka_oids); ++i) { - if (XSTRCMP(pka_oids[i].oid, tmp) == 0) { - *id = pka_oids[i].id; - return CRYPT_OK; - } - } - return CRYPT_INVALID_ARG; -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c deleted file mode 100644 index a62d2c6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_cmp.c +++ /dev/null @@ -1,44 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/* - Compare an OID string to an array of `unsigned long`. - @return CRYPT_OK if equal -*/ -int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size) -{ - unsigned long i; - char tmp[LTC_OID_MAX_STRLEN] = { 0 }; - int err; - - if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; - - i = sizeof(tmp); - if ((err = pk_oid_num_to_str(o2, o2size, tmp, &i)) != CRYPT_OK) { - return err; - } - - if (XSTRCMP(o1, tmp) != 0) { - return CRYPT_PK_INVALID_TYPE; - } - - return CRYPT_OK; -} - -#ifdef LTC_DER - -/* - Compare an OID string to an OID element decoded from ASN.1. - @return CRYPT_OK if equal -*/ -int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2) -{ - if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; - - if (o2->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG; - - return pk_oid_cmp_with_ulong(o1, o2->data, o2->size); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_str.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_str.c deleted file mode 100644 index e12cdf4..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/oid/pk_oid_str.c +++ /dev/null @@ -1,111 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen) -{ - unsigned long i, j, limit, oid_j; - - LTC_ARGCHK(oidlen != NULL); - - limit = *oidlen; - *oidlen = 0; /* make sure that we return zero oidlen on error */ - if (oid != NULL) { - XMEMSET(oid, 0, sizeof(*oid) * limit); - } - if (OID == NULL) return CRYPT_OK; - if (OID[0] == '\0') return CRYPT_OK; - - for (i = 0, j = 0; OID[i] != '\0'; i++) { - if (OID[i] == '.') { - if (++j >= limit) continue; - } - else if ((OID[i] >= '0') && (OID[i] <= '9')) { - if ((j >= limit) || (oid == NULL)) continue; - oid_j = oid[j]; - oid[j] = oid[j] * 10 + (OID[i] - '0'); - if (oid[j] < oid_j) return CRYPT_OVERFLOW; - } - else { - return CRYPT_ERROR; - } - } - if (j == 0) return CRYPT_ERROR; - *oidlen = j + 1; - if (j >= limit || oid == NULL) { - return CRYPT_BUFFER_OVERFLOW; - } - return CRYPT_OK; -} - -typedef struct num_to_str { - int err; - char *wr; - unsigned long max_len, res_len; -} num_to_str; - -static LTC_INLINE void s_wr(char c, num_to_str *w) -{ - if (w->res_len == ULONG_MAX) { - w->err = CRYPT_OVERFLOW; - return; - } - w->res_len++; - if (w->res_len > w->max_len) w->wr = NULL; - if (w->wr) w->wr[w->max_len - w->res_len] = c; -} - -int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen) -{ - int i; - num_to_str w; - unsigned long j; - - LTC_ARGCHK(oid != NULL); - LTC_ARGCHK(oidlen < INT_MAX); - LTC_ARGCHK(outlen != NULL); - - if (OID == NULL || *outlen == 0) { - w.max_len = ULONG_MAX; - w.wr = NULL; - } else { - w.max_len = *outlen; - w.wr = OID; - } - w.res_len = 0; - w.err = CRYPT_OK; - - s_wr('\0', &w); - for (i = oidlen; i --> 0;) { - j = oid[i]; - if (j == 0) { - s_wr('0', &w); - } else { - while (j > 0) { - s_wr('0' + (j % 10), &w); - j /= 10; - } - } - if (i > 0) { - s_wr('.', &w); - } - } - if (w.err != CRYPT_OK) { - return w.err; - } - if (*outlen < w.res_len || OID == NULL) { - *outlen = w.res_len; - return CRYPT_BUFFER_OVERFLOW; - } - LTC_ARGCHK(OID != NULL); - XMEMMOVE(OID, OID + (w.max_len - w.res_len), w.res_len); - *outlen = w.res_len; - return CRYPT_OK; -} - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c deleted file mode 100644 index 42eac45..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_decode_flexi.c +++ /dev/null @@ -1,106 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_PKCS_8 - -/** - PKCS#8 decrypt if necessary & flexi-decode - - @param in Pointer to the ASN.1 encoded input data - @param inlen Length of the input data - @param pwd Pointer to the password that was used when encrypting - @param pwdlen Length of the password - @param decoded_list Pointer to a pointer for the flexi-decoded list - @return CRYPT_OK on success -*/ -int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - ltc_asn1_list **decoded_list) -{ - unsigned long len = inlen; - unsigned long dec_size; - unsigned char *dec_data = NULL; - ltc_asn1_list *l = NULL; - int err; - pbes_arg pbes; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(decoded_list != NULL); - - XMEMSET(&pbes, 0, sizeof(pbes)); - - *decoded_list = NULL; - if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) { - /* the following "if" detects whether it is encrypted or not */ - /* PKCS8 Setup - * 0:d=0 hl=4 l= 380 cons: SEQUENCE - * 4:d=1 hl=2 l= 78 cons: SEQUENCE - * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid) - * 17:d=2 hl=2 l= 65 cons: SEQUENCE - * Stuff in between is dependent on whether it's PBES1 or PBES2 - * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) - */ - if (l->type == LTC_ASN1_SEQUENCE && - LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) && - LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) && - LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) && - LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) { - ltc_asn1_list *lalgoid = l->child->child; - - if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) { - err = CRYPT_PW_CTX_MISSING; - goto LBL_DONE; - } - - if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) { - /* Successfully extracted PBES1 parameters */ - } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) { - /* Successfully extracted PBES2 parameters */ - } else { - /* unsupported encryption */ - err = CRYPT_INVALID_PACKET; - goto LBL_DONE; - } - - if (pw_ctx->callback(&pbes.pw.pw, &pbes.pw.l, pw_ctx->userdata)) { - err = CRYPT_ERROR; - goto LBL_DONE; - } - - pbes.enc_data = l->child->next; - - dec_size = pbes.enc_data->size; - if ((dec_data = XMALLOC(dec_size)) == NULL) { - err = CRYPT_MEM; - goto LBL_DONE; - } - - if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE; - - der_free_sequence_flexi(l); - l = NULL; - err = der_decode_sequence_flexi(dec_data, &dec_size, &l); - if (err != CRYPT_OK) goto LBL_DONE; - *decoded_list = l; - } - else { - /* not encrypted */ - err = CRYPT_OK; - *decoded_list = l; - } - /* Set l to NULL so it won't be free'd */ - l = NULL; - } - -LBL_DONE: - if (dec_data) { - zeromem(dec_data, dec_size); - XFREE(dec_data); - } - password_free(&pbes.pw, pw_ctx); - if (l) der_free_sequence_flexi(l); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c deleted file mode 100644 index 1888c07..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/pkcs8/pkcs8_get.c +++ /dev/null @@ -1,54 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file pkcs8_get.c - PKCS#8 utility functions -*/ - -#ifdef LTC_PKCS_8 - -int pkcs8_get_children(const ltc_asn1_list *decoded_list, enum ltc_oid_id *pka, ltc_asn1_list **alg_id, ltc_asn1_list **priv_key) -{ - int err; - unsigned long n; - der_flexi_check flexi_should[4]; - ltc_asn1_list *seq_l, *version; - - LTC_ARGCHK(ltc_mp.name != NULL); - - if (alg_id == NULL) alg_id = &seq_l; - - /* Setup for basic structure */ - n=0; - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, alg_id); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, priv_key); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - - err = der_flexi_sequence_cmp(decoded_list, flexi_should); - switch (err) { - case CRYPT_OK: - case CRYPT_INPUT_TOO_LONG: - /* If there are attributes added after the private_key it is tagged with version 1 and - * we get an 'input too long' error but the rest is already decoded and can be - * handled the same as for version 0 - */ - if (ltc_mp_cmp_d(version->data, 0) != LTC_MP_EQ && ltc_mp_cmp_d(version->data, 1) != LTC_MP_EQ) { - return CRYPT_INVALID_PACKET; - } - break; - default: - return err; - } - return pk_get_oid_from_asn1((*alg_id)->child, pka); -} - -#endif /* LTC_PKCS_8 */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c deleted file mode 100644 index 45a1c6f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_public_key_from_certificate.c +++ /dev/null @@ -1,71 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x509_decode_public_key_from_certificate.c - ASN.1 DER/X.509, decode a certificate -*/ - -#ifdef LTC_DER - -/** - Try to decode the public key from a X.509 certificate - @param in The input buffer - @param inlen The length of the input buffer - @param algorithm One out of the enum #public_key_algorithms - @param param_type The parameters' type out of the enum ltc_asn1_type - @param parameters The parameters to include - @param parameters_len [in/out] The number of parameters to include - @param callback The callback - @param ctx The context passed to the callback - @return CRYPT_OK on success, - CRYPT_NOP if no SubjectPublicKeyInfo was found, - another error if decoding or memory allocation failed -*/ -int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, - enum ltc_oid_id algorithm, ltc_asn1_type param_type, - ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx) -{ - int err; - unsigned char *tmpbuf = NULL; - unsigned long tmpbuf_len; - ltc_asn1_list *decoded_list = NULL, *spki; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != 0); - LTC_ARGCHK(callback != NULL); - - if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { - return err; - } - - if (algorithm == LTC_OID_EC) { - err = callback(spki->data, spki->size, ctx); - } else { - - tmpbuf_len = inlen; - tmpbuf = XCALLOC(1, tmpbuf_len); - if (tmpbuf == NULL) { - err = CRYPT_MEM; - goto LBL_OUT; - } - - err = x509_decode_subject_public_key_info(spki->data, spki->size, - algorithm, tmpbuf, &tmpbuf_len, - param_type, parameters, parameters_len); - if (err == CRYPT_OK) { - err = callback(tmpbuf, tmpbuf_len, ctx); - goto LBL_OUT; - } - } - -LBL_OUT: - if (decoded_list) der_free_sequence_flexi(decoded_list); - if (tmpbuf != NULL) XFREE(tmpbuf); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_spki.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_spki.c deleted file mode 100644 index 147aaf1..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_spki.c +++ /dev/null @@ -1,82 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x509_decode_public_key_from_certificate.c - ASN.1 DER/X.509, decode a SubjectPublicKeyInfo -*/ - -#ifdef LTC_DER - -/* Check if it looks like a SubjectPublicKeyInfo */ -#define LOOKS_LIKE_SPKI(l) ((l) != NULL) \ -&& ((l)->type == LTC_ASN1_SEQUENCE) \ -&& ((l)->child != NULL) \ -&& ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \ -&& ((l)->next != NULL) \ -&& ((l)->next->type == LTC_ASN1_BIT_STRING) - -/** - DER decode a X.509 certificate and return the SubjectPublicKeyInfo - @param in The input buffer - @param inlen The length of the input buffer - @param out [out] A pointer to the decoded linked list (you take ownership of this one and - `der_free_sequence_flexi()` it when you're done) - @param spki [out] A pointer to the SubjectPublicKeyInfo - @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed -*/ -int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki) -{ - int err; - unsigned long tmp_inlen; - ltc_asn1_list *decoded_list = NULL, *l; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != 0); - - tmp_inlen = inlen; - if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) { - l = decoded_list; - - err = CRYPT_NOP; - - /* Move 2 levels up in the tree - SEQUENCE - SEQUENCE - ... - */ - if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { - l = l->child; - if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { - l = l->child; - - /* Move forward in the tree until we find this combination - ... - SEQUENCE - SEQUENCE - OBJECT IDENTIFIER - NULL - BIT STRING - */ - do { - /* The additional check for l->data is there to make sure - * we won't try to decode a list that has been 'shrunk' - */ - if ((l->type == LTC_ASN1_SEQUENCE) - && (l->data != NULL) - && LOOKS_LIKE_SPKI(l->child)) { - *out = decoded_list; - *spki = l; - return CRYPT_OK; - } - l = l->next; - } while(l); - } - } - } - if (decoded_list) der_free_sequence_flexi(decoded_list); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c deleted file mode 100644 index 0725611..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_decode_subject_public_key_info.c +++ /dev/null @@ -1,119 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x509_decode_subject_public_key_info.c - ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav -*/ - -#ifdef LTC_DER - -/* AlgorithmIdentifier := SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm - * } - * - * SubjectPublicKeyInfo := SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - */ -/** - Decode a SubjectPublicKeyInfo - @param in The input buffer - @param inlen The length of the input buffer - @param algorithm One out of the enum #public_key_algorithms - @param public_key The buffer for the public key - @param public_key_len [in/out] The length of the public key buffer and the written length - @param parameters_type The parameters' type out of the enum ltc_asn1_type - @param parameters The parameters to include - @param parameters_len [in/out] The number of parameters to include - @return CRYPT_OK on success -*/ -int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, - enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len, - ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len) -{ - int err; - unsigned long len, alg_id_num, tmplen; - const char* oid; - unsigned char *tmpbuf; - unsigned long tmpoid[16]; - unsigned long *_parameters_len; - ltc_asn1_list alg_id[2]; - ltc_asn1_list subject_pubkey[2]; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != 0); - LTC_ARGCHK(public_key_len != NULL); - - if (parameters_type != LTC_ASN1_EOL) { - if ((parameters == NULL) || (parameters_len == NULL)) { - tmplen = 0; - _parameters_len = &tmplen; - } else { - _parameters_len = parameters_len; - } - } - - err = pk_get_oid(algorithm, &oid); - if (err != CRYPT_OK) { - return err; - } - - /* see if the OpenSSL DER format RSA public key will work */ - tmpbuf = XCALLOC(1, inlen); - if (tmpbuf == NULL) { - err = CRYPT_MEM; - goto LBL_ERR; - } - - /* this includes the internal hash ID and optional params (NULL in this case) */ - LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, LTC_ARRAY_SIZE(tmpoid)); - if (parameters_type == LTC_ASN1_EOL) { - alg_id_num = 1; - } else { - LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len); - alg_id_num = 2; - } - - /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey - * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet - */ - LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num); - LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); - - err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); - if (err != CRYPT_OK) { - goto LBL_ERR; - } - if (parameters_type != LTC_ASN1_EOL) { - *_parameters_len = alg_id[1].size; - } - - if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { - /* OID mismatch */ - goto LBL_ERR; - } - - len = subject_pubkey[1].size/8; - if (*public_key_len >= len) { - XMEMCPY(public_key, subject_pubkey[1].data, len); - *public_key_len = len; - } else { - *public_key_len = len; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - err = CRYPT_OK; - -LBL_ERR: - - XFREE(tmpbuf); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c b/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c deleted file mode 100644 index 52a80a1..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/asn1/x509/x509_encode_subject_public_key_info.c +++ /dev/null @@ -1,66 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x509_encode_subject_public_key_info.c - ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav -*/ - -#ifdef LTC_DER - -/* AlgorithmIdentifier := SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm - * } - * - * SubjectPublicKeyInfo := SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - */ -/** - Encode a SubjectPublicKeyInfo - @param out The output buffer - @param outlen [in/out] Length of buffer and resulting length of output - @param algorithm One out of the enum #public_key_algorithms - @param public_key The buffer for the public key - @param public_key_len The length of the public key buffer - @param parameters_type The parameters' type out of the enum ltc_asn1_type - @param parameters The parameters to include - @param parameters_len The number of parameters to include - @return CRYPT_OK on success -*/ -int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, - enum ltc_oid_id algorithm, const void* public_key, unsigned long public_key_len, - ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) -{ - int err; - ltc_asn1_list alg_id[2]; - const char *OID; - unsigned long oid[16], oidlen; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = pk_get_oid(algorithm, &OID)) != CRYPT_OK) { - return err; - } - - oidlen = LTC_ARRAY_SIZE(oid); - if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { - return err; - } - - LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); - LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len); - - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_SEQUENCE, (unsigned long)LTC_ARRAY_SIZE(alg_id), alg_id, - LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key, - LTC_ASN1_EOL, 0UL, NULL); - -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh.c deleted file mode 100644 index 1b9034a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh.c +++ /dev/null @@ -1,248 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MDH - -/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ -const ltc_dh_set_type ltc_dh_sets[] = { -#ifdef LTC_DH768 -{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */ - 96, - "DH-768", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH1024 -{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */ - 128, - "DH-1024", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" - "FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH1536 -{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */ - 192, - "DH-1536", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH2048 -{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */ - 256, - "DH-2048", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AACAA68FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH3072 -{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */ - 384, - "DH-3072", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH4096 -{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */ - 512, - "DH-4096", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" - "FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH6144 -{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */ - 768, - "DH-6144", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" - "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" - "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" - "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" - "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" - "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" - "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" - "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" - "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" - "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" -}, -#endif -#ifdef LTC_DH8192 -{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */ - 1024, - "DH-8192", - "2", - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" - "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" - "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" - "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" - "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" - "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" - "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" - "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" - "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" - "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" - "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" - "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" - "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" - "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" - "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" - "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" - "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" - "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" - "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" - "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" - "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" -}, -#endif -{ - 0, - NULL, - NULL, - NULL -} -}; - -/** - Returns the DH group size (octets) for given key - @param key The DH key to get the size of - @return The group size in octets (0 on error) - */ -int dh_get_groupsize(const dh_key *key) -{ - if (key == NULL) return 0; - return ltc_mp_unsigned_bin_size(key->prime); -} - -/** - Init a DH key - @param key The DH key to initialize - @return CRYPT_OK if successful -*/ -int dh_init(dh_key *key) -{ - int err; - LTC_ARGCHK(key != NULL); - if ((err = ltc_mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { - return err; - } - return CRYPT_OK; -} - -#endif /* LTC_MDH */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_check_pubkey.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_check_pubkey.c deleted file mode 100644 index 88c252e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_check_pubkey.c +++ /dev/null @@ -1,55 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Check DH public key (INTERNAL ONLY, not part of public API) - @param key The key you wish to test - @return CRYPT_OK if successful -*/ -int dh_check_pubkey(const dh_key *key) -{ - void *p_minus1; - ltc_mp_digit digit; - int i, digit_count, bits_set = 0, err; - - LTC_ARGCHK(key != NULL); - - if ((err = ltc_mp_init(&p_minus1)) != CRYPT_OK) { - return err; - } - - /* avoid: y <= 1 OR y >= p-1 */ - if ((err = ltc_mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) { - goto error; - } - if (ltc_mp_cmp(key->y, p_minus1) != LTC_MP_LT || ltc_mp_cmp_d(key->y, 1) != LTC_MP_GT) { - err = CRYPT_INVALID_ARG; - goto error; - } - - /* public key must have more than one bit set */ - digit_count = ltc_mp_get_digit_count(key->y); - for (i = 0; i < digit_count && bits_set < 2; i++) { - digit = ltc_mp_get_digit(key->y, i); - while (digit > 0) { - if (digit & 1) bits_set++; - digit >>= 1; - } - } - if (bits_set > 1) { - err = CRYPT_OK; - } - else { - err = CRYPT_INVALID_ARG; - } - -error: - ltc_mp_clear(p_minus1); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export.c deleted file mode 100644 index 19112c4..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export.c +++ /dev/null @@ -1,52 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Export a DH key to a binary packet - @param out [out] The destination for the key - @param outlen [in/out] The max size and resulting size of the DH key - @param type Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key The key you wish to export - @return CRYPT_OK if successful -*/ -int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key) -{ - unsigned char flags[1]; - int err; - unsigned long version = 0; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - if (type == PK_PRIVATE) { - /* export x - private key */ - flags[0] = 1; - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->prime, - LTC_ASN1_INTEGER, 1UL, key->base, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL); - } - else { - /* export y - public key */ - flags[0] = 0; - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->prime, - LTC_ASN1_INTEGER, 1UL, key->base, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL); - } - - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export_key.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export_key.c deleted file mode 100644 index dd5bcb7..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_export_key.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Binary export a DH key to a buffer - @param out [out] The destination for the key - @param outlen [in/out] The max size and resulting size of the DH key - @param type Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key The key you wish to export - @return CRYPT_OK if successful -*/ -int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key) -{ - unsigned long len; - void *k; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - k = (type == PK_PRIVATE) ? key->x : key->y; - len = ltc_mp_unsigned_bin_size(k); - - if (*outlen < len) { - *outlen = len; - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = len; - - return ltc_mp_to_unsigned_bin(k, out); -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_free.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_free.c deleted file mode 100644 index 0801114..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_free.c +++ /dev/null @@ -1,18 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Free the allocated ram for a DH key - @param key The key which you wish to free -*/ -void dh_free(dh_key *key) -{ - LTC_ARGCHKVD(key != NULL); - ltc_mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL); -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_generate_key.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_generate_key.c deleted file mode 100644 index c12eaf1..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_generate_key.c +++ /dev/null @@ -1,96 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MDH - -static int s_dh_groupsize_to_keysize(int groupsize) -{ - /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8 - * We use "Estimate 2" to get an appropriate private key (exponent) size. - */ - if (groupsize <= 0) { - return 0; - } - if (groupsize <= 192) { - return 30; /* 1536-bit => key size 240-bit */ - } - if (groupsize <= 256) { - return 40; /* 2048-bit => key size 320-bit */ - } - if (groupsize <= 384) { - return 52; /* 3072-bit => key size 416-bit */ - } - if (groupsize <= 512) { - return 60; /* 4096-bit => key size 480-bit */ - } - if (groupsize <= 768) { - return 67; /* 6144-bit => key size 536-bit */ - } - if (groupsize <= 1024) { - return 77; /* 8192-bit => key size 616-bit */ - } - return 0; -} - -int dh_generate_key(prng_state *prng, int wprng, dh_key *key) -{ - unsigned char *buf; - unsigned long keysize; - int err, max_iterations = LTC_PK_MAX_RETRIES; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* good prng? */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - keysize = s_dh_groupsize_to_keysize(ltc_mp_unsigned_bin_size(key->prime)); - if (keysize == 0) { - err = CRYPT_INVALID_KEYSIZE; - goto freemp; - } - - /* allocate buffer */ - buf = XMALLOC(keysize); - if (buf == NULL) { - err = CRYPT_MEM; - goto freemp; - } - - key->type = PK_PRIVATE; - do { - /* make up random buf */ - if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) { - err = CRYPT_ERROR_READPRNG; - goto freebuf; - } - /* load the x value - private key */ - if ((err = ltc_mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { - goto freebuf; - } - /* compute the y value - public key */ - if ((err = ltc_mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { - goto freebuf; - } - err = dh_check_pubkey(key); - } while (err != CRYPT_OK && max_iterations-- > 0); - -freebuf: - zeromem(buf, keysize); - XFREE(buf); -freemp: - if (err != CRYPT_OK) dh_free(key); - return err; -} - -#endif /* LTC_MDH */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import.c deleted file mode 100644 index b18e439..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import.c +++ /dev/null @@ -1,89 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Import a DH key from a binary packet - @param in The packet to read - @param inlen The length of the input packet - @param key [out] Where to import the key to - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) -{ - unsigned char flags[1]; - int err; - unsigned long version; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - /* init */ - if ((err = dh_init(key)) != CRYPT_OK) { - return err; - } - - /* find out what type of key it is */ - err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_BIT_STRING, 1UL, &flags, - LTC_ASN1_EOL, 0UL, NULL); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - goto error; - } - - if (version == 0) { - if (flags[0] == 1) { - key->type = PK_PRIVATE; - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->prime, - LTC_ASN1_INTEGER, 1UL, key->base, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; - } - /* compute public key: y = (base ^ x) mod prime */ - if ((err = ltc_mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { - goto error; - } - } - else if (flags[0] == 0) { - key->type = PK_PUBLIC; - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->prime, - LTC_ASN1_INTEGER, 1UL, key->base, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; - } - } - else { - err = CRYPT_INVALID_PACKET; - goto error; - } - } - else { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* check public key */ - if ((err = dh_check_pubkey(key)) != CRYPT_OK) { - goto error; - } - - return CRYPT_OK; - -error: - dh_free(key); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import_pkcs8.c deleted file mode 100644 index d1fd792..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_import_pkcs8.c +++ /dev/null @@ -1,87 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - - if (!alg_id->child || - !LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_SEQUENCE) || - !LTC_ASN1_IS_TYPE(alg_id->child->next->child, LTC_ASN1_INTEGER) || - !LTC_ASN1_IS_TYPE(alg_id->child->next->child->next, LTC_ASN1_INTEGER)) { - return CRYPT_PK_INVALID_TYPE; - } - - if ((err = dh_init(key)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_copy(alg_id->child->next->child->data, key->prime)) != CRYPT_OK) { - goto error; - } - if ((err = ltc_mp_copy(alg_id->child->next->child->next->data, key->base)) != CRYPT_OK) { - goto error; - } - - if ((err = der_decode_integer(priv_key->data, priv_key->size, key->x)) != CRYPT_OK) { - goto error; - } - /* compute public key: y = (base ^ x) mod prime */ - if ((err = ltc_mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { - goto error; - } - /* check public key */ - if ((err = dh_check_pubkey(key)) != CRYPT_OK) { - goto error; - } - key->type = PK_PRIVATE; - - return CRYPT_OK; -error: - dh_free(key); - return err; -} - -/** - Import a DH key in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int dh_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, dh_key *key) -{ - int err; - ltc_asn1_list *l = NULL; - ltc_asn1_list *alg_id, *priv_key; - enum ltc_oid_id pka; - - LTC_ARGCHK(in != NULL); - - if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) { - return err; - } - if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto LBL_DER_FREE; - } - if (pka != LTC_OID_DH) { - err = CRYPT_INVALID_PACKET; - goto LBL_DER_FREE; - } - - err = dh_import_pkcs8_asn1(alg_id, priv_key, key); - -LBL_DER_FREE: - der_free_sequence_flexi(l); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set.c deleted file mode 100644 index 1cc044f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set.c +++ /dev/null @@ -1,115 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Import DH key parts p and g from raw numbers - - @param p DH's p (prime) - @param plen DH's p's length - @param g DH's g (group) - @param glen DH's g's length - @param key [out] the destination for the imported key - @return CRYPT_OK if successful -*/ -int dh_set_pg(const unsigned char *p, unsigned long plen, - const unsigned char *g, unsigned long glen, - dh_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(p != NULL); - LTC_ARGCHK(g != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if ((err = dh_init(key)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; } - - return CRYPT_OK; - -LBL_ERR: - dh_free(key); - return err; -} - -/** - Import DH key parts p and g from built-in DH groups - - @param groupsize The size of the DH group to use - @param key [out] Where the newly created DH key will be stored - @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. -*/ -int dh_set_pg_groupsize(int groupsize, dh_key *key) -{ - int err, i; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - LTC_ARGCHK(groupsize > 0); - - for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); - if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; - - if ((err = dh_init(key)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; } - - return CRYPT_OK; - -LBL_ERR: - dh_free(key); - return err; -} - -/** - Import DH public or private key part from raw numbers - - NB: The p & g parts must be set beforehand - - @param in The key-part to import, either public or private. - @param inlen The key-part's length - @param type Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key [out] the destination for the imported key - @return CRYPT_OK if successful -*/ -int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if (type == PK_PRIVATE) { - key->type = PK_PRIVATE; - if ((err = ltc_mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; } - } - else { - key->type = PK_PUBLIC; - if ((err = ltc_mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - } - - /* check public key */ - if ((err = dh_check_pubkey(key)) != CRYPT_OK) { - goto LBL_ERR; - } - - return CRYPT_OK; - -LBL_ERR: - dh_free(key); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set_pg_dhparam.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set_pg_dhparam.c deleted file mode 100644 index 4d254fd..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_set_pg_dhparam.c +++ /dev/null @@ -1,44 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Import DH key parts p and g from dhparam - - dhparam data: openssl dhparam -outform DER -out dhparam.der 2048 - - @param dhparam The DH param DER encoded data - @param dhparamlen The length of dhparam data - @param key [out] Where the newly created DH key will be stored - @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. -*/ -int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - LTC_ARGCHK(dhparam != NULL); - LTC_ARGCHK(dhparamlen > 0); - - if ((err = dh_init(key)) != CRYPT_OK) { - return err; - } - if ((err = der_decode_sequence_multi(dhparam, dhparamlen, - LTC_ASN1_INTEGER, 1UL, key->prime, - LTC_ASN1_INTEGER, 1UL, key->base, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - - return CRYPT_OK; - -LBL_ERR: - dh_free(key); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_shared_secret.c b/Sources/DataLiteC/libtomcrypt/pk/dh/dh_shared_secret.c deleted file mode 100644 index b60a848..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dh/dh_shared_secret.c +++ /dev/null @@ -1,70 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MDH - -/** - Create a DH shared secret. - @param private_key The private DH key in the pair - @param public_key The public DH key in the pair - @param out [out] The destination of the shared data - @param outlen [in/out] The max size and resulting size of the shared data. - @return CRYPT_OK if successful -*/ -int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, - unsigned char *out, unsigned long *outlen) -{ - void *tmp; - unsigned long x; - int err; - - LTC_ARGCHK(private_key != NULL); - LTC_ARGCHK(public_key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* types valid? */ - if (private_key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* same DH group? */ - if (ltc_mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } - if (ltc_mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } - - /* init big numbers */ - if ((err = ltc_mp_init(&tmp)) != CRYPT_OK) { - return err; - } - - /* check public key */ - if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) { - goto error; - } - - /* compute tmp = y^x mod p */ - if ((err = ltc_mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { - goto error; - } - - /* enough space for output? */ - x = (unsigned long)ltc_mp_unsigned_bin_size(tmp); - if (*outlen < x) { - *outlen = x; - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - if ((err = ltc_mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { - goto error; - } - *outlen = x; - err = CRYPT_OK; - -error: - ltc_mp_clear(tmp); - return err; -} - -#endif /* LTC_MDH */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_decrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_decrypt_key.c deleted file mode 100644 index 734a2e0..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_decrypt_key.c +++ /dev/null @@ -1,129 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_decrypt_key.c - DSA Crypto, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Decrypt an DSA encrypted key - @param in The ciphertext - @param inlen The length of the ciphertext (octets) - @param out [out] The plaintext - @param outlen [in/out] The max size and resulting size of the plaintext - @param key The corresponding private DSA key - @return CRYPT_OK if successful -*/ -int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const dsa_key *key) -{ - unsigned char *skey, *expt; - void *g_pub; - unsigned long x, y; - unsigned long hashOID[32] = { 0 }; - int hash, err; - ltc_asn1_list decode[3]; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* right key type? */ - if (key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* decode to find out hash */ - LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, LTC_ARRAY_SIZE(hashOID)); - err = der_decode_sequence(in, inlen, decode, 1); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - return err; - } - - hash = find_hash_oid(hashOID, decode[0].size); - if (hash_is_valid(hash) != CRYPT_OK) { - return CRYPT_INVALID_PACKET; - } - - /* we now have the hash! */ - - if ((err = ltc_mp_init(&g_pub)) != CRYPT_OK) { - return err; - } - - /* allocate memory */ - expt = XMALLOC(ltc_mp_unsigned_bin_size(key->p) + 1); - skey = XMALLOC(MAXBLOCKSIZE); - if (expt == NULL || skey == NULL) { - if (expt != NULL) { - XFREE(expt); - } - if (skey != NULL) { - XFREE(skey); - } - ltc_mp_clear(g_pub); - return CRYPT_MEM; - } - - LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL); - LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); - - /* read the structure in now */ - if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* make shared key */ - x = ltc_mp_unsigned_bin_size(key->p) + 1; - if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - - y = ltc_mp_unsigned_bin_size(key->p) + 1; - y = MIN(y, MAXBLOCKSIZE); - if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* ensure the hash of the shared secret is at least as big as the encrypt itself */ - if (decode[2].size > y) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* avoid buffer overflow */ - if (*outlen < decode[2].size) { - *outlen = decode[2].size; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* Decrypt the key */ - for (x = 0; x < decode[2].size; x++) { - out[x] = expt[x] ^ skey[x]; - } - *outlen = x; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(expt, ltc_mp_unsigned_bin_size(key->p) + 1); - zeromem(skey, MAXBLOCKSIZE); -#endif - - XFREE(expt); - XFREE(skey); - - ltc_mp_clear(g_pub); - - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_encrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_encrypt_key.c deleted file mode 100644 index 3009765..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_encrypt_key.c +++ /dev/null @@ -1,118 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_encrypt_key.c - DSA Crypto, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Encrypt a symmetric key with DSA - @param in The symmetric key you want to encrypt - @param inlen The length of the key to encrypt (octets) - @param out [out] The destination for the ciphertext - @param outlen [in/out] The max size and resulting size of the ciphertext - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param hash The index of the hash you want to use - @param key The DSA key you want to encrypt to - @return CRYPT_OK if successful -*/ -int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, - const dsa_key *key) -{ - unsigned char *expt, *skey; - void *g_pub, *g_priv; - unsigned long x, y; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* check that wprng/cipher/hash are not invalid */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (inlen > hash_descriptor[hash].hashsize) { - return CRYPT_INVALID_HASH; - } - - /* make a random key and export the public copy */ - if ((err = ltc_mp_init_multi(&g_pub, &g_priv, LTC_NULL)) != CRYPT_OK) { - return err; - } - - expt = XMALLOC(ltc_mp_unsigned_bin_size(key->p) + 1); - skey = XMALLOC(MAXBLOCKSIZE); - if (expt == NULL || skey == NULL) { - if (expt != NULL) { - XFREE(expt); - } - if (skey != NULL) { - XFREE(skey); - } - ltc_mp_deinit_multi(g_pub, g_priv, LTC_NULL); - return CRYPT_MEM; - } - - /* make a random g_priv, g_pub = g^x pair - private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) - */ - if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* compute y */ - if ((err = ltc_mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* make random key */ - x = ltc_mp_unsigned_bin_size(key->p) + 1; - if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - - y = MAXBLOCKSIZE; - if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* Encrypt key */ - for (x = 0; x < inlen; x++) { - skey[x] ^= in[x]; - } - - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, - LTC_ASN1_INTEGER, 1UL, g_pub, - LTC_ASN1_OCTET_STRING, inlen, skey, - LTC_ASN1_EOL, 0UL, NULL); - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - /* clean up */ - zeromem(expt, ltc_mp_unsigned_bin_size(key->p) + 1); - zeromem(skey, MAXBLOCKSIZE); -#endif - - XFREE(skey); - XFREE(expt); - - ltc_mp_deinit_multi(g_pub, g_priv, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_export.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_export.c deleted file mode 100644 index c26dd46..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_export.c +++ /dev/null @@ -1,100 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_export.c - DSA implementation, export key, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Export a DSA key to a binary packet - @param out [out] Where to store the packet - @param outlen [in/out] The max size and resulting size of the packet - @param type The type of key to export (PK_PRIVATE or PK_PUBLIC) - @param key The key to export - @return CRYPT_OK if successful -*/ -int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key) -{ - unsigned long zero=0; - unsigned char flags[1]; - int err, std; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - std = type & PK_STD; - type &= ~PK_STD; - - if (type == PK_PRIVATE && key->type != PK_PRIVATE) { - return CRYPT_PK_TYPE_MISMATCH; - } - - if (type == PK_PRIVATE) { - if (std) { - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL); - } - flags[0] = 1; - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL); - } - - if (type == PK_PUBLIC) { - if (std) { - unsigned long tmplen = (unsigned long)(ltc_mp_count_bits(key->y) / 8) + 8; - unsigned char* tmp = XMALLOC(tmplen); - ltc_asn1_list int_list[3]; - - if (tmp == NULL) { - return CRYPT_MEM; - } - - err = der_encode_integer(key->y, tmp, &tmplen); - if (err != CRYPT_OK) { - goto error; - } - - LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL); - LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); - LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); - - err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp, - tmplen, LTC_ASN1_SEQUENCE, int_list, - sizeof(int_list) / sizeof(int_list[0])); - -error: - XFREE(tmp); - return err; - } - flags[0] = 0; - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL); - } - - return CRYPT_INVALID_ARG; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_free.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_free.c deleted file mode 100644 index aa9294f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_free.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_free.c - DSA implementation, free a DSA key, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Free a DSA key - @param key The key to free from memory -*/ -void dsa_free(dsa_key *key) -{ - LTC_ARGCHKVD(key != NULL); - ltc_mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL); - key->type = key->qord = 0; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_key.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_key.c deleted file mode 100644 index 651cfb4..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_key.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_make_key.c - DSA implementation, generate a DSA key -*/ - -#ifdef LTC_MDSA - -/** - Create a DSA key - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param key [in/out] Where to store the created key - @return CRYPT_OK if successful. -*/ -int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* so now we have our DH structure, generator g, order q, modulus p - Now we need a random exponent [mod q] and it's power g^x mod p - */ - /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ - if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } - if ((err = ltc_mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } - key->type = PK_PRIVATE; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_pqg.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_pqg.c deleted file mode 100644 index a9887c0..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_generate_pqg.c +++ /dev/null @@ -1,235 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file dsa_generate_pqg.c - DSA implementation - generate DSA parameters p, q & g -*/ - -#ifdef LTC_MDSA - -/** - Create DSA parameters (INTERNAL ONLY, not part of public API) - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param group_size Size of the multiplicative group (octets) - @param modulus_size Size of the modulus (octets) - @param p [out] bignum where generated 'p' is stored (must be initialized by caller) - @param q [out] bignum where generated 'q' is stored (must be initialized by caller) - @param g [out] bignum where generated 'g' is stored (must be initialized by caller) - @return CRYPT_OK if successful, upon error this function will free all allocated memory -*/ -static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) -{ - unsigned long L, N, n, outbytes, seedbytes, counter, j, i; - int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; - unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; - void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; - const char *accepted_hashes[] = { "sha3-512", "sha512", "sha3-384", "sha384", "sha3-256", "sha256" }; - - /* check size */ - if (group_size > LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size || modulus_size > LTC_MDSA_MAX_MODULUS) { - return CRYPT_INVALID_ARG; - } - - /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function - * - * L = The desired length of the prime p (in bits e.g. L = 1024) - * N = The desired length of the prime q (in bits e.g. N = 160) - * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N - * outlen = The bit length of Hash function - * - * 1. Check that the (L, N) - * 2. If (seedlen = 2^(L-1)) { - * Test whether or not p is prime as specified in Appendix C.3. - * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter - * } - * offset = offset + n + 1 Comment: Increment offset - * } - */ - - seedbytes = group_size; - L = (unsigned long)modulus_size * 8; - N = (unsigned long)group_size * 8; - - /* XXX-TODO no Lucas test */ -#ifdef LTC_MPI_HAS_LUCAS_TEST - /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ - mr_tests_p = (L <= 2048) ? 3 : 2; - if (N <= 160) { mr_tests_q = 19; } - else if (N <= 224) { mr_tests_q = 24; } - else { mr_tests_q = 27; } -#else - /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ - if (L <= 1024) { mr_tests_p = 40; } - else if (L <= 2048) { mr_tests_p = 56; } - else { mr_tests_p = 64; } - - if (N <= 160) { mr_tests_q = 40; } - else if (N <= 224) { mr_tests_q = 56; } - else { mr_tests_q = 64; } -#endif - - hash = -1; - for (i = 0; i < LTC_ARRAY_SIZE(accepted_hashes); ++i) { - hash = find_hash(accepted_hashes[i]); - if (hash != -1) break; - } - if (hash == -1) { - return CRYPT_INVALID_ARG; /* no appropriate hash function found */ - } - if (N > hash_descriptor[hash].hashsize * 8) { - return CRYPT_INVALID_ARG; /* group_size too big */ - } - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } - outbytes = hash_descriptor[hash].hashsize; - - n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; - - if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } - if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } - - err = ltc_mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL); - if (err != CRYPT_OK) { goto cleanup1; } - - if ((err = ltc_mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } - /* t2L1 = 2^(L-1) */ - if ((err = ltc_mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } - /* t2N1 = 2^(N-1) */ - if ((err = ltc_mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } - /* t2seedlen = 2^seedlen */ - - for(found_p=0; !found_p;) { - /* q */ - for(found_q=0; !found_q;) { - if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } - i = outbytes; - if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } - if (!ltc_mp_isodd(q)) ltc_mp_add_d(q, 1, q); - if ((err = ltc_mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } - if (res == LTC_MP_YES) found_q = 1; - } - - /* p */ - if ((err = ltc_mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } - for(counter=0; counter < 4*L && !found_p; counter++) { - for(j=0; j<=n; j++) { - if ((err = ltc_mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } - /* seedinc = (seedinc+1) % 2^seed_bitlen */ - if ((i = ltc_mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } - zeromem(sbuf, seedbytes); - if ((err = ltc_mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } - i = outbytes; - err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); - if (err != CRYPT_OK) { goto cleanup; } - } - if ((err = ltc_mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } - if (ltc_mp_cmp(p, t2L1) != LTC_MP_LT) { - /* p >= 2^(L-1) */ - if ((err = ltc_mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } - if (res == LTC_MP_YES) { - found_p = 1; - } - } - } - } - - /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g - * 1. e = (p - 1)/q - * 2. h = any integer satisfying: 1 < h < (p - 1) - * h could be obtained from a random number generator or from a counter that changes after each use - * 3. g = h^e mod p - * 4. if (g == 1), then go to step 2. - * - */ - - if ((err = ltc_mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } - /* e = (p - 1)/q */ - i = ltc_mp_count_bits(p); - do { - do { - if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } - } while (ltc_mp_cmp(h, p) != LTC_MP_LT || ltc_mp_cmp_d(h, 2) != LTC_MP_GT); - if ((err = ltc_mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } - /* h is randon and 1 < h < (p-1) */ - if ((err = ltc_mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } - } while (ltc_mp_cmp_d(g, 1) == LTC_MP_EQ); - - err = CRYPT_OK; -cleanup: - ltc_mp_deinit_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL); -cleanup1: - XFREE(sbuf); -cleanup2: - XFREE(wbuf); -cleanup3: - return err; -} - -/** - Generate DSA parameters p, q & g - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param group_size Size of the multiplicative group (octets) - @param modulus_size Size of the modulus (octets) - @param key [out] Where to store the created key - @return CRYPT_OK if successful. -*/ -int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) -{ - int err; - - /* init key */ - if ((err = dsa_int_init(key)) != CRYPT_OK) return err; - /* generate params */ - err = s_dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); - if (err != CRYPT_OK) { - goto cleanup; - } - - key->qord = group_size; - - return CRYPT_OK; - -cleanup: - dsa_free(key); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import.c deleted file mode 100644 index a281b37..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import.c +++ /dev/null @@ -1,145 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file dsa_import.c - DSA implementation, import a DSA key, Tom St Denis -*/ - -#ifdef LTC_MDSA - -int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key) -{ - int err; - unsigned long zero = 0; - /* get key type */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { - - key->type = PK_PRIVATE; - } - return err; -} - -/** - Import a DSA key - @param in The binary packet to import from - @param inlen The length of the binary packet - @param key [out] Where to store the imported key - @return CRYPT_OK if successful, upon error this function will free all allocated memory -*/ -int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) -{ - int err, stat; - unsigned char* tmpbuf = NULL; - unsigned char flags[1]; - - LTC_ARGCHK(in != NULL); - - /* init key */ - if ((err = dsa_int_init(key)) != CRYPT_OK) return err; - - /* try to match the old libtomcrypt format */ - err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_EOL, 0UL, NULL); - - if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { - /* private key */ - if (flags[0] == 1) { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - key->type = PK_PRIVATE; - goto LBL_OK; - } - /* public key */ - else if (flags[0] == 0) { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - key->type = PK_PUBLIC; - goto LBL_OK; - } - else { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - } - - if (dsa_import_pkcs1(in, inlen, key) != CRYPT_OK) { - ltc_asn1_list params[3]; - unsigned long tmpbuf_len = inlen, len; - - LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); - LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); - LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); - len = 3; - - tmpbuf = XCALLOC(1, tmpbuf_len); - if (tmpbuf == NULL) { - return CRYPT_MEM; - } - - err = x509_decode_subject_public_key_info(in, inlen, - LTC_OID_DSA, tmpbuf, &tmpbuf_len, - LTC_ASN1_SEQUENCE, params, &len); - if (err != CRYPT_OK) { - XFREE(tmpbuf); - goto LBL_ERR; - } - - if ((err = der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { - XFREE(tmpbuf); - goto LBL_ERR; - } - - key->type = PK_PUBLIC; - XFREE(tmpbuf); - } - -LBL_OK: - key->qord = ltc_mp_unsigned_bin_size(key->q); - - /* quick p, q, g validation, without primality testing - * + x, y validation */ - if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) { - goto LBL_ERR; - } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - return CRYPT_OK; -LBL_ERR: - dsa_free(key); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import_pkcs8.c deleted file mode 100644 index 9df19be..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_import_pkcs8.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file dsa_import_pkcs8.c - Import a PKCS DSA key -*/ - -#ifdef LTC_MDSA - -int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key) -{ - int err, stat; - - LTC_UNUSED_PARAM(alg_id); - - if (!alg_id->child - || !LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_SEQUENCE) - || !LTC_ASN1_IS_TYPE(priv_key, LTC_ASN1_OCTET_STRING)) { - return CRYPT_INVALID_PACKET; - } - if ((err = dsa_set_pqg_dsaparam(alg_id->child->next->data, alg_id->child->next->size, key)) != CRYPT_OK) { - return err; - } - if ((err = der_decode_integer(priv_key->data, priv_key->size, key->x)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = ltc_mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* quick p, q, g validation, without primality testing - * + x, y validation */ - if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) { - goto LBL_ERR; - } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - key->qord = ltc_mp_unsigned_bin_size(key->q); - key->type = PK_PRIVATE; - - return err; -LBL_ERR: - dsa_free(key); - return err; -} -/** - Import an RSAPrivateKey in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int dsa_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - dsa_key *key) -{ - int err; - ltc_asn1_list *l = NULL; - ltc_asn1_list *alg_id, *priv_key; - enum ltc_oid_id pka; - - LTC_ARGCHK(in != NULL); - - if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) { - return err; - } - if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto LBL_DER_FREE; - } - if (pka != LTC_OID_DSA) { - err = CRYPT_INVALID_PACKET; - goto LBL_DER_FREE; - } - - err = dsa_import_pkcs8_asn1(alg_id, priv_key, key); - -LBL_DER_FREE: - der_free_sequence_flexi(l); - return err; -} - -#endif /* LTC_MRSA */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_init.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_init.c deleted file mode 100644 index 77625eb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_init.c +++ /dev/null @@ -1,22 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -#ifdef LTC_MDSA - -/** - Init DSA key - @param key [out] the key to init - @return CRYPT_OK if successful. -*/ -int dsa_int_init(dsa_key *key) -{ - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* init key */ - return ltc_mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_make_key.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_make_key.c deleted file mode 100644 index 5a205b2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_make_key.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_make_key.c - DSA implementation, generate a DSA key -*/ - -#ifdef LTC_MDSA - -/** - Old-style creation of a DSA key - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param group_size Size of the multiplicative group (octets) - @param modulus_size Size of the modulus (octets) - @param key [out] Where to store the created key - @return CRYPT_OK if successful. -*/ -int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) -{ - int err; - - if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } - if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set.c deleted file mode 100644 index 594dca8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set.c +++ /dev/null @@ -1,104 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MDSA - -/** - Import DSA's p, q & g from raw numbers - @param p DSA's p in binary representation - @param plen The length of p - @param q DSA's q in binary representation - @param qlen The length of q - @param g DSA's g in binary representation - @param glen The length of g - @param key [out] the destination for the imported key - @return CRYPT_OK if successful. -*/ -int dsa_set_pqg(const unsigned char *p, unsigned long plen, - const unsigned char *q, unsigned long qlen, - const unsigned char *g, unsigned long glen, - dsa_key *key) -{ - int err, stat; - - LTC_ARGCHK(p != NULL); - LTC_ARGCHK(q != NULL); - LTC_ARGCHK(g != NULL); - - /* init key */ - if ((err = dsa_int_init(key)) != CRYPT_OK) return err; - - if ((err = ltc_mp_read_unsigned_bin(key->p, p , plen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->g, g , glen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->q, q , qlen)) != CRYPT_OK) { goto LBL_ERR; } - - key->qord = ltc_mp_unsigned_bin_size(key->q); - - /* do only a quick validation, without primality testing */ - if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - return CRYPT_OK; - -LBL_ERR: - dsa_free(key); - return err; -} - -/** - Import DSA public or private key-part from raw numbers - - NB: The p, q & g parts must be set beforehand - - @param in The key-part to import, either public or private. - @param inlen The key-part's length - @param type Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key [out] the destination for the imported key - @return CRYPT_OK if successful. -*/ -int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key) -{ - int err, stat = 0; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(key->x != NULL); - LTC_ARGCHK(key->y != NULL); - LTC_ARGCHK(key->p != NULL); - LTC_ARGCHK(key->g != NULL); - LTC_ARGCHK(key->q != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if (type == PK_PRIVATE) { - key->type = PK_PRIVATE; - if ((err = ltc_mp_read_unsigned_bin(key->x, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; } - } - else { - key->type = PK_PUBLIC; - if ((err = ltc_mp_read_unsigned_bin(key->y, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } - } - - if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - return CRYPT_OK; - -LBL_ERR: - dsa_free(key); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c deleted file mode 100644 index e952d27..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_set_pqg_dsaparam.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MDSA - -/** - Import DSA's p, q & g from dsaparam - - dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 - - @param dsaparam The DSA param DER encoded data - @param dsaparamlen The length of dhparam data - @param key [out] the destination for the imported key - @return CRYPT_OK if successful. -*/ -int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, - dsa_key *key) -{ - int err, stat; - - LTC_ARGCHK(dsaparam != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* init key */ - if ((err = dsa_int_init(key)) != CRYPT_OK) return err; - - if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - - key->qord = ltc_mp_unsigned_bin_size(key->q); - - /* quick p, q, g validation, without primality testing */ - if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { - goto LBL_ERR; - } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - return CRYPT_OK; - -LBL_ERR: - dsa_free(key); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_shared_secret.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_shared_secret.c deleted file mode 100644 index 866832a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_shared_secret.c +++ /dev/null @@ -1,60 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_shared_secret.c - DSA Crypto, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Create a DSA shared secret between two keys - @param private_key The private DSA key (the exponent) - @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) - @param public_key The public key - @param out [out] Destination of the shared secret - @param outlen [in/out] The max size and resulting size of the shared secret - @return CRYPT_OK if successful -*/ -int dsa_shared_secret(void *private_key, void *base, - const dsa_key *public_key, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x; - void *res; - int err; - - LTC_ARGCHK(private_key != NULL); - LTC_ARGCHK(public_key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* make new point */ - if ((err = ltc_mp_init(&res)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) { - ltc_mp_clear(res); - return err; - } - - x = (unsigned long)ltc_mp_unsigned_bin_size(res); - if (*outlen < x) { - *outlen = x; - err = CRYPT_BUFFER_OVERFLOW; - goto done; - } - zeromem(out, x); - if ((err = ltc_mp_to_unsigned_bin(res, out + (x - ltc_mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; } - - err = CRYPT_OK; - *outlen = x; -done: - ltc_mp_clear(res); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_sign_hash.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_sign_hash.c deleted file mode 100644 index ab3e27a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_sign_hash.c +++ /dev/null @@ -1,142 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_sign_hash.c - DSA implementation, sign a hash, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Sign a hash with DSA - @param in The hash to sign - @param inlen The length of the hash to sign - @param r The "r" integer of the signature (caller must initialize with ltc_mp_init() first) - @param s The "s" integer of the signature (caller must initialize with ltc_mp_init() first) - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param key A private DSA key - @return CRYPT_OK if successful -*/ -int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, - void *r, void *s, - prng_state *prng, int wprng, const dsa_key *key) -{ - void *k, *kinv, *tmp; - unsigned char *buf; - int err, qbits; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(r != NULL); - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - if (key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* check group order size */ - if (key->qord >= LTC_MDSA_MAX_GROUP) { - return CRYPT_INVALID_ARG; - } - - buf = XMALLOC(LTC_MDSA_MAX_GROUP); - if (buf == NULL) { - return CRYPT_MEM; - } - - /* Init our temps */ - if ((err = ltc_mp_init_multi(&k, &kinv, &tmp, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; } - - qbits = ltc_mp_count_bits(key->q); -retry: - - do { - /* gen random k */ - if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; } - - /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */ - if (ltc_mp_cmp_d(k, 0) != LTC_MP_GT || ltc_mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; } - - /* test gcd */ - if ((err = ltc_mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; } - } while (ltc_mp_cmp_d(tmp, 1) != LTC_MP_EQ); - - /* now find 1/k mod q */ - if ((err = ltc_mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; } - - /* now find r = g^k mod p mod q */ - if ((err = ltc_mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; } - - if (ltc_mp_iszero(r) == LTC_MP_YES) { goto retry; } - - /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/ - inlen = MIN(inlen, (unsigned long)(key->qord)); - - /* now find s = (in + xr)/k mod q */ - if ((err = ltc_mp_read_unsigned_bin(tmp, in, inlen)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add(s, tmp, s)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; } - - if (ltc_mp_iszero(s) == LTC_MP_YES) { goto retry; } - - err = CRYPT_OK; -error: - ltc_mp_deinit_multi(k, kinv, tmp, LTC_NULL); -ERRBUF: -#ifdef LTC_CLEAN_STACK - zeromem(buf, LTC_MDSA_MAX_GROUP); -#endif - XFREE(buf); - return err; -} - -/** - Sign a hash with DSA - @param in The hash to sign - @param inlen The length of the hash to sign - @param out [out] Where to store the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param key A private DSA key - @return CRYPT_OK if successful -*/ -int dsa_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const dsa_key *key) -{ - void *r, *s; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - if (ltc_mp_init_multi(&r, &s, LTC_NULL) != CRYPT_OK) { - return CRYPT_MEM; - } - - if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) { - goto error; - } - - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_hash.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_hash.c deleted file mode 100644 index 230041a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_hash.c +++ /dev/null @@ -1,127 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_verify_hash.c - DSA implementation, verify a signature, Tom St Denis -*/ - - -#ifdef LTC_MDSA - -/** - Verify a DSA signature - @param r DSA "r" parameter - @param s DSA "s" parameter - @param hash The hash that was signed - @param hashlen The length of the hash that was signed - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param key The corresponding public DSA key - @return CRYPT_OK if successful (even if the signature is invalid) -*/ -int dsa_verify_hash_raw( void *r, void *s, - const unsigned char *hash, unsigned long hashlen, - int *stat, const dsa_key *key) -{ - void *w, *v, *u1, *u2; - int err; - - LTC_ARGCHK(r != NULL); - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - - /* default to invalid signature */ - *stat = 0; - - /* init our variables */ - if ((err = ltc_mp_init_multi(&w, &v, &u1, &u2, LTC_NULL)) != CRYPT_OK) { - return err; - } - - /* neither r or s can be null or >q*/ - if (ltc_mp_cmp_d(r, 0) != LTC_MP_GT || ltc_mp_cmp_d(s, 0) != LTC_MP_GT || ltc_mp_cmp(r, key->q) != LTC_MP_LT || ltc_mp_cmp(s, key->q) != LTC_MP_LT) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */ - hashlen = MIN(hashlen, (unsigned long)(key->qord)); - - /* w = 1/s mod q */ - if ((err = ltc_mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; } - - /* u1 = m * w mod q */ - if ((err = ltc_mp_read_unsigned_bin(u1, hash, hashlen)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; } - - /* u2 = r*w mod q */ - if ((err = ltc_mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } - - /* v = g^u1 * y^u2 mod p mod q */ - if ((err = ltc_mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; } - - /* if r = v then we're set */ - if (ltc_mp_cmp(r, v) == LTC_MP_EQ) { - *stat = 1; - } - - err = CRYPT_OK; -error: - ltc_mp_deinit_multi(w, v, u1, u2, LTC_NULL); - return err; -} - -/** - Verify a DSA signature - @param sig The signature - @param siglen The length of the signature (octets) - @param hash The hash that was signed - @param hashlen The length of the hash that was signed - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param key The corresponding public DSA key - @return CRYPT_OK if successful (even if the signature is invalid) -*/ -int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const dsa_key *key) -{ - int err; - void *r, *s; - ltc_asn1_list sig_seq[2]; - unsigned long reallen = 0; - - LTC_ARGCHK(stat != NULL); - *stat = 0; /* must be set before the first return */ - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) { - return err; - } - - LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL); - LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL); - - err = der_decode_sequence_strict(sig, siglen, sig_seq, 2); - if (err != CRYPT_OK) { - goto LBL_ERR; - } - - err = der_length_sequence(sig_seq, 2, &reallen); - if (err != CRYPT_OK || reallen != siglen) { - goto LBL_ERR; - } - - /* do the op */ - err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); - -LBL_ERR: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_key.c b/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_key.c deleted file mode 100644 index 9beae6c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/dsa/dsa_verify_key.c +++ /dev/null @@ -1,204 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file dsa_verify_key.c - DSA implementation, verify a key, Tom St Denis -*/ - -#ifdef LTC_MDSA - -/** - Validate a DSA key - - Yeah, this function should've been called dsa_validate_key() - in the first place and for compat-reasons we keep it - as it was (for now). - - @param key The key to validate - @param stat [out] Result of test, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int dsa_verify_key(const dsa_key *key, int *stat) -{ - int err; - - err = dsa_int_validate_primes(key, stat); - if (err != CRYPT_OK || *stat == 0) return err; - - return dsa_int_validate(key, stat); -} - -/** - Non-complex part (no primality testing) of the validation - of DSA params (p, q, g) - - @param key The key to validate - @param stat [out] Result of test, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int dsa_int_validate_pqg(const dsa_key *key, int *stat) -{ - void *tmp1, *tmp2; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(stat != NULL); - *stat = 0; - - /* check q-order */ - if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || - (unsigned long)key->qord >= ltc_mp_unsigned_bin_size(key->p) || - (ltc_mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) { - return CRYPT_OK; - } - - /* FIPS 186-4 chapter 4.1: 1 < g < p */ - if (ltc_mp_cmp_d(key->g, 1) != LTC_MP_GT || ltc_mp_cmp(key->g, key->p) != LTC_MP_LT) { - return CRYPT_OK; - } - - if ((err = ltc_mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } - - /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ - if ((err = ltc_mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; } - if (ltc_mp_iszero(tmp2) != LTC_MP_YES) { - err = CRYPT_OK; - goto error; - } - - /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in - * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1 - */ - if ((err = ltc_mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; } - if (ltc_mp_cmp_d(tmp1, 1) != LTC_MP_EQ) { - err = CRYPT_OK; - goto error; - } - - err = CRYPT_OK; - *stat = 1; -error: - ltc_mp_deinit_multi(tmp2, tmp1, LTC_NULL); - return err; -} - -/** - Primality testing of DSA params p and q - - @param key The key to validate - @param stat [out] Result of test, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int dsa_int_validate_primes(const dsa_key *key, int *stat) -{ - int err, res; - - *stat = 0; - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(stat != NULL); - - /* key->q prime? */ - if ((err = ltc_mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { - return err; - } - if (res == LTC_MP_NO) { - return CRYPT_OK; - } - - /* key->p prime? */ - if ((err = ltc_mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { - return err; - } - if (res == LTC_MP_NO) { - return CRYPT_OK; - } - - *stat = 1; - return CRYPT_OK; -} - -/** - Validation of a DSA key (x and y values) - - @param key The key to validate - @param stat [out] Result of test, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int dsa_int_validate_xy(const dsa_key *key, int *stat) -{ - void *tmp; - int err; - - *stat = 0; - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(stat != NULL); - - /* 1 < y < p-1 */ - if ((err = ltc_mp_init(&tmp)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { - goto error; - } - if (ltc_mp_cmp_d(key->y, 1) != LTC_MP_GT || ltc_mp_cmp(key->y, tmp) != LTC_MP_LT) { - err = CRYPT_OK; - goto error; - } - - if (key->type == PK_PRIVATE) { - /* FIPS 186-4 chapter 4.1: 0 < x < q */ - if (ltc_mp_cmp_d(key->x, 0) != LTC_MP_GT || ltc_mp_cmp(key->x, key->q) != LTC_MP_LT) { - err = CRYPT_OK; - goto error; - } - /* FIPS 186-4 chapter 4.1: y = g^x mod p */ - if ((err = ltc_mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) { - goto error; - } - if (ltc_mp_cmp(tmp, key->y) != LTC_MP_EQ) { - err = CRYPT_OK; - goto error; - } - } - else { - /* with just a public key we cannot test y = g^x mod p therefore we - * only test that y^q mod p = 1, which makes sure y is in g^x mod p - */ - if ((err = ltc_mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { - goto error; - } - if (ltc_mp_cmp_d(tmp, 1) != LTC_MP_EQ) { - err = CRYPT_OK; - goto error; - } - } - - err = CRYPT_OK; - *stat = 1; -error: - ltc_mp_clear(tmp); - return err; -} - -/** - Validation of DSA params (p, q, g) and DSA key (x and y) - - @param key The key to validate - @param stat [out] Result of test, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int dsa_int_validate(const dsa_key *key, int *stat) -{ - int err; - - err = dsa_int_validate_pqg(key, stat); - if (err != CRYPT_OK || *stat == 0) return err; - - return dsa_int_validate_xy(key, stat); - -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c b/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c deleted file mode 100644 index e1efb30..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_crypto_ctx.c +++ /dev/null @@ -1,41 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ec25519_crypto_ctx.c - curve25519 crypto context helper -*/ - -#ifdef LTC_CURVE25519 - -int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen) -{ - unsigned char *buf = out; - - const char *prefix = "SigEd25519 no Ed25519 collisions"; - const unsigned long prefix_len = XSTRLEN(prefix); - const unsigned char ctxlen8 = (unsigned char)ctxlen; - - if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG; - if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW; - - XMEMCPY(buf, prefix, prefix_len); - buf += prefix_len; - XMEMCPY(buf, &flag, 1); - buf++; - XMEMCPY(buf, &ctxlen8, 1); - buf++; - - if (ctxlen > 0u) { - LTC_ARGCHK(ctx != NULL); - XMEMCPY(buf, ctx, ctxlen); - buf += ctxlen; - } - - *outlen = buf-out; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_export.c b/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_export.c deleted file mode 100644 index 5cd7c10..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_export.c +++ /dev/null @@ -1,94 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ec25519_export.c - Generic export of a Curve/Ed25519 key to a binary packet, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Generic export of a Curve/Ed25519 key to a binary packet - @param out [out] The destination for the key - @param outlen [in/out] The max size and resulting size of the Ed25519 key - @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) - @param key The key you wish to export - @return CRYPT_OK if successful -*/ -int ec25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key) -{ - int err, std; - const char* OID; - unsigned long oid[16], oidlen; - ltc_asn1_list alg_id[1]; - enum ltc_oid_id oid_id; - unsigned char private_key[34]; - unsigned long version, private_key_len = sizeof(private_key); - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - std = which & PK_STD; - which &= ~PK_STD; - if ((err = pk_get_oid_id(key->pka, &oid_id)) != CRYPT_OK) { - return err; - } - - if (which == PK_PRIVATE) { - if(key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; - - if (std == PK_STD) { - if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) { - return err; - } - oidlen = LTC_ARRAY_SIZE(oid); - if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { - return err; - } - - LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); - - /* encode private key as PKCS#8 */ - if ((err = der_encode_octet_string(key->priv, 32uL, private_key, &private_key_len)) != CRYPT_OK) { - return err; - } - - version = 0; - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1uL, &version, - LTC_ASN1_SEQUENCE, 1uL, alg_id, - LTC_ASN1_OCTET_STRING, private_key_len, private_key, - LTC_ASN1_EOL, 0uL, NULL); - } else { - if (*outlen < sizeof(key->priv)) { - err = CRYPT_BUFFER_OVERFLOW; - } else { - XMEMCPY(out, key->priv, sizeof(key->priv)); - err = CRYPT_OK; - } - *outlen = sizeof(key->priv); - } - } else { - if (std == PK_STD) { - /* encode public key as SubjectPublicKeyInfo */ - err = x509_encode_subject_public_key_info(out, outlen, oid_id, key->pub, 32uL, LTC_ASN1_EOL, NULL, 0); - } else { - if (*outlen < sizeof(key->pub)) { - err = CRYPT_BUFFER_OVERFLOW; - } else { - XMEMCPY(out, key->pub, sizeof(key->pub)); - err = CRYPT_OK; - } - *outlen = sizeof(key->pub); - } - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c deleted file mode 100644 index 4a7f9fb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ec25519/ec25519_import_pkcs8.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ec25519_import_pkcs8.c - Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -typedef int (*sk_to_pk)(unsigned char *pk , const unsigned char *sk); - -int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - enum ltc_oid_id id, - curve25519_key *key) -{ - int err; - unsigned long key_len; - sk_to_pk fp; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - LTC_UNUSED_PARAM(alg_id); - - switch (id) { - case LTC_OID_ED25519: - fp = tweetnacl_crypto_sk_to_pk; - break; - case LTC_OID_X25519: - fp = tweetnacl_crypto_scalarmult_base; - break; - default: - return CRYPT_PK_INVALID_TYPE; - } - - key_len = sizeof(key->priv); - if ((err = der_decode_octet_string(priv_key->data, priv_key->size, key->priv, &key_len)) == CRYPT_OK) { - fp(key->pub, key->priv); - key->type = PK_PRIVATE; - err = pk_get_pka_id(id, &key->pka); - } - return err; -} - -/** - Generic import of a Curve/Ed25519 private key in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param id The type of the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - enum ltc_oid_id id, - curve25519_key *key) -{ - int err; - ltc_asn1_list *l = NULL; - ltc_asn1_list *alg_id, *priv_key; - enum ltc_oid_id pka; - - LTC_ARGCHK(in != NULL); - - err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l); - if (err != CRYPT_OK) return err; - - if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto LBL_DER_FREE; - } - if (pka != id) { - err = CRYPT_INVALID_PACKET; - goto LBL_DER_FREE; - } - - err = ec25519_import_pkcs8_asn1(alg_id, priv_key, id, key); - -LBL_DER_FREE: - der_free_sequence_flexi(l); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ec25519/tweetnacl.c b/Sources/DataLiteC/libtomcrypt/pk/ec25519/tweetnacl.c deleted file mode 100644 index 5959fbe..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ec25519/tweetnacl.c +++ /dev/null @@ -1,502 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/* automatically generated file, do not edit */ - -#define add tnacl_add -#define FOR(i,n) for (i = 0;i < n;++i) -#define sv static void - -typedef unsigned char u8; -typedef ulong32 u32; -typedef ulong64 u64; -typedef long64 i64; -typedef i64 gf[16]; - -static const u8 - nine[32] = {9}; -static const gf - gf0, - gf1 = {1}, - gf121665 = {0xDB41,1}, - D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, - D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, - X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, - Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, - I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; - -static int vn(const u8 *x,const u8 *y,int n) -{ - int i; - u32 d = 0; - FOR(i,n) d |= x[i]^y[i]; - return (1 & ((d - 1) >> 8)) - 1; -} - -static int tweetnacl_crypto_verify_32(const u8 *x,const u8 *y) -{ - return vn(x,y,32); -} - -sv set25519(gf r, const gf a) -{ - int i; - FOR(i,16) r[i]=a[i]; -} - -sv car25519(gf o) -{ - int i; - i64 c; - FOR(i,16) { - o[i]+=(1LL<<16); - c=o[i]>>16; - o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); - o[i]-=c<<16; - } -} - -sv sel25519(gf p,gf q,int b) -{ - i64 t,i,c=~(b-1); - FOR(i,16) { - t= c&(p[i]^q[i]); - p[i]^=t; - q[i]^=t; - } -} - -sv pack25519(u8 *o,const gf n) -{ - int i,j,b; - gf m,t; - FOR(i,16) t[i]=n[i]; - car25519(t); - car25519(t); - car25519(t); - FOR(j,2) { - m[0]=t[0]-0xffed; - for(i=1;i<15;i++) { - m[i]=t[i]-0xffff-((m[i-1]>>16)&1); - m[i-1]&=0xffff; - } - m[15]=t[15]-0x7fff-((m[14]>>16)&1); - b=(m[15]>>16)&1; - m[14]&=0xffff; - sel25519(t,m,1-b); - } - FOR(i,16) { - o[2*i]=t[i]&0xff; - o[2*i+1]=t[i]>>8; - } -} - -static int neq25519(const gf a, const gf b) -{ - u8 c[32],d[32]; - pack25519(c,a); - pack25519(d,b); - return tweetnacl_crypto_verify_32(c,d); -} - -static u8 par25519(const gf a) -{ - u8 d[32]; - pack25519(d,a); - return d[0]&1; -} - -sv unpack25519(gf o, const u8 *n) -{ - int i; - FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); - o[15]&=0x7fff; -} - -sv A(gf o,const gf a,const gf b) -{ - int i; - FOR(i,16) o[i]=a[i]+b[i]; -} - -sv Z(gf o,const gf a,const gf b) -{ - int i; - FOR(i,16) o[i]=a[i]-b[i]; -} - -sv M(gf o,const gf a,const gf b) -{ - i64 i,j,t[31]; - FOR(i,31) t[i]=0; - FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; - FOR(i,15) t[i]+=38*t[i+16]; - FOR(i,16) o[i]=t[i]; - car25519(o); - car25519(o); -} - -sv S(gf o,const gf a) -{ - M(o,a,a); -} - -sv inv25519(gf o,const gf i) -{ - gf c; - int a; - FOR(a,16) c[a]=i[a]; - for(a=253;a>=0;a--) { - S(c,c); - if(a!=2&&a!=4) M(c,c,i); - } - FOR(a,16) o[a]=c[a]; -} - -sv pow2523(gf o,const gf i) -{ - gf c; - int a; - FOR(a,16) c[a]=i[a]; - for(a=250;a>=0;a--) { - S(c,c); - if(a!=1) M(c,c,i); - } - FOR(a,16) o[a]=c[a]; -} - -int tweetnacl_crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) -{ - u8 z[32]; - i64 x[80],r,i; - gf a,b,c,d,e,f; - FOR(i,31) z[i]=n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - FOR(i,16) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for(i=254;i>=0;--i) { - r=(z[i>>3]>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,gf121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - FOR(i,16) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - inv25519(x+32,x+32); - M(x+16,x+16,x+32); - pack25519(q,x+16); - return 0; -} - -int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n) -{ - return tweetnacl_crypto_scalarmult(q,n,nine); -} - -static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs) -{ - unsigned long len = 64; - int hash_idx = find_hash("sha512"); - - if (n > ULONG_MAX) return CRYPT_OVERFLOW; - - if(cs == 0) - return hash_memory(hash_idx, m, n, out, &len); - - return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL); -} - -static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) -{ - return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0); -} - -sv add(gf p[4],gf q[4]) -{ - gf a,b,c,d,t,e,f,g,h; - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} - -sv cswap(gf p[4],gf q[4],u8 b) -{ - int i; - FOR(i,4) - sel25519(p[i],q[i],b); -} - -sv pack(u8 *r,gf p[4]) -{ - gf tx, ty, zi; - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} - -sv scalarmult(gf p[4],gf q[4],const u8 *s) -{ - int i; - set25519(p[0],gf0); - set25519(p[1],gf1); - set25519(p[2],gf1); - set25519(p[3],gf0); - for (i = 255;i >= 0;--i) { - u8 b = (s[i/8]>>(i&7))&1; - cswap(p,q,b); - add(q,p); - add(p,p); - cswap(p,q,b); - } -} - -sv scalarbase(gf p[4],const u8 *s) -{ - gf q[4]; - set25519(q[0],X); - set25519(q[1],Y); - set25519(q[2],gf1); - M(q[3],X,Y); - scalarmult(p,q,s); -} - -int tweetnacl_crypto_sk_to_pk(u8 *pk, const u8 *sk) -{ - u8 d[64]; - gf p[4]; - tweetnacl_crypto_hash(d, sk, 32); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p,d); - pack(pk,p); - - return 0; -} - -int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, u8 *pk, u8 *sk) -{ - int err; - - /* randombytes(sk,32); */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if (prng_descriptor[wprng].read(sk,32, prng) != 32) { - return CRYPT_ERROR_READPRNG; - } - - if ((err = tweetnacl_crypto_sk_to_pk(pk, sk)) != CRYPT_OK) { - return err; - } - - /* FOR(i,32) sk[32 + i] = pk[i]; - * we don't copy the pk in the sk */ - return CRYPT_OK; -} - -static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; - -sv modL(u8 *r,i64 x[64]) -{ - i64 carry,i,j; - for (i = 63;i >= 32;--i) { - carry = 0; - for (j = i - 32;j < i - 12;++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = (x[j] + 128) >> 8; - x[j] -= carry << 8; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - FOR(j,32) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - FOR(j,32) x[j] -= carry * L[j]; - FOR(i,32) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} - -sv reduce(u8 *r) -{ - i64 x[64],i; - FOR(i,64) x[i] = (u64) r[i]; - FOR(i,64) r[i] = 0; - modL(r,x); -} - -int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs) -{ - u8 d[64],h[64],r[64]; - i64 i,j,x[64]; - gf p[4]; - - tweetnacl_crypto_hash(d, sk, 32); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - *smlen = mlen+64; - FOR(i,(i64)mlen) sm[64 + i] = m[i]; - FOR(i,32) sm[32 + i] = d[32 + i]; - - tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs); - reduce(r); - scalarbase(p,r); - pack(sm,p); - - FOR(i,32) sm[i+32] = pk[i]; - tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs); - reduce(h); - - FOR(i,64) x[i] = 0; - FOR(i,32) x[i] = (u64) r[i]; - FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; - modL(sm + 32,x); - - return 0; -} - -static int unpackneg(gf r[4],const u8 p[32]) -{ - gf t, chk, num, den, den2, den4, den6; - set25519(r[2],gf1); - unpack25519(r[1],p); - S(num,r[1]); - M(den,num,D); - Z(num,num,r[2]); - A(den,r[2],den); - - S(den2,den); - S(den4,den2); - M(den6,den4,den2); - M(t,den6,num); - M(t,t,den); - - pow2523(t,t); - M(t,t,num); - M(t,t,den); - M(t,t,den); - M(r[0],t,den); - - S(chk,r[0]); - M(chk,chk,den); - if (neq25519(chk, num)) M(r[0],r[0],I); - - S(chk,r[0]); - M(chk,chk,den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); - - M(r[3],r[0],r[1]); - return 0; -} - -int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk) -{ - u64 i; - u8 s[32],t[32],h[64]; - gf p[4],q[4]; - - *stat = 0; - if (*mlen < smlen) return CRYPT_BUFFER_OVERFLOW; - *mlen = -1; - if (smlen < 64) return CRYPT_INVALID_ARG; - - if (unpackneg(q,pk)) return CRYPT_ERROR; - - XMEMMOVE(m,sm,smlen); - XMEMMOVE(s,m + 32,32); - XMEMMOVE(m + 32,pk,32); - tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs); - reduce(h); - scalarmult(p,q,h); - - scalarbase(q,s); - add(p,q); - pack(t,p); - - smlen -= 64; - if (tweetnacl_crypto_verify_32(sm, t)) { - FOR(i,smlen) m[i] = 0; - zeromem(m, smlen); - return CRYPT_OK; - } - - *stat = 1; - XMEMMOVE(m,m + 64,smlen); - *mlen = smlen; - return CRYPT_OK; -} - -int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen) -{ - return tweetnacl_crypto_hash(out, msg, msglen); -} - -#undef add -#undef FOR -#undef sv - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc.c deleted file mode 100644 index 84068a9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc.c +++ /dev/null @@ -1,435 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/* This array holds the curve parameters. - * Curves (prime field only) are taken from: - * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*) - * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*) - * - ANS X9.62 (named: PRIMEP*) - * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*) - */ -const ltc_ecc_curve ltc_ecc_curves[] = { -#ifdef LTC_ECC_SECP112R1 -{ - /* prime */ "DB7C2ABF62E35E668076BEAD208B", - /* A */ "DB7C2ABF62E35E668076BEAD2088", - /* B */ "659EF8BA043916EEDE8911702B22", - /* order */ "DB7C2ABF62E35E7628DFAC6561C5", - /* Gx */ "09487239995A5EE76B55F9C2F098", - /* Gy */ "A89CE5AF8724C0A23E0E0FF77500", - /* cofactor */ 1, - /* OID */ "1.3.132.0.6" -}, -#endif -#ifdef LTC_ECC_SECP112R2 -{ - /* prime */ "DB7C2ABF62E35E668076BEAD208B", - /* A */ "6127C24C05F38A0AAAF65C0EF02C", - /* B */ "51DEF1815DB5ED74FCC34C85D709", - /* order */ "36DF0AAFD8B8D7597CA10520D04B", - /* Gx */ "4BA30AB5E892B4E1649DD0928643", - /* Gy */ "ADCD46F5882E3747DEF36E956E97", - /* cofactor */ 4, - /* OID */ "1.3.132.0.7" -}, -#endif -#ifdef LTC_ECC_SECP128R1 -{ - /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", - /* B */ "E87579C11079F43DD824993C2CEE5ED3", - /* order */ "FFFFFFFE0000000075A30D1B9038A115", - /* Gx */ "161FF7528B899B2D0C28607CA52C5B86", - /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83", - /* cofactor */ 1, - /* OID */ "1.3.132.0.28" -}, -#endif -#ifdef LTC_ECC_SECP128R2 -{ - /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", - /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D", - /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3", - /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140", - /* Gy */ "27B6916A894D3AEE7106FE805FC34B44", - /* cofactor */ 4, - /* OID */ "1.3.132.0.29" -}, -#endif -#ifdef LTC_ECC_SECP160R1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", - /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", - /* order */ "0100000000000000000001F4C8F927AED3CA752257", - /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82", - /* Gy */ "23A628553168947D59DCC912042351377AC5FB32", - /* cofactor */ 1, - /* OID */ "1.3.132.0.8" -}, -#endif -#ifdef LTC_ECC_SECP160R2 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", - /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", - /* order */ "0100000000000000000000351EE786A818F3A1A16B", - /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", - /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", - /* cofactor */ 1, - /* OID */ "1.3.132.0.30" -}, -#endif -#ifdef LTC_ECC_SECP160K1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", - /* A */ "0000000000000000000000000000000000000000", - /* B */ "0000000000000000000000000000000000000007", - /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3", - /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", - /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE", - /* cofactor */ 1, - /* OID */ "1.3.132.0.9" -}, -#endif -#ifdef LTC_ECC_SECP192R1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", - /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.1" -}, -#endif -#ifdef LTC_ECC_PRIME192V2 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", - /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", - /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.2" -}, -#endif -#ifdef LTC_ECC_PRIME192V3 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", - /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", - /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.3" -}, -#endif -#ifdef LTC_ECC_SECP192K1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", - /* A */ "000000000000000000000000000000000000000000000000", - /* B */ "000000000000000000000000000000000000000000000003", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", - /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", - /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", - /* cofactor */ 1, - /* OID */ "1.3.132.0.31" -}, -#endif -#ifdef LTC_ECC_SECP224R1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", - /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", - /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", - /* cofactor */ 1, - /* OID */ "1.3.132.0.33" -}, -#endif -#ifdef LTC_ECC_SECP224K1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", - /* A */ "00000000000000000000000000000000000000000000000000000000", - /* B */ "00000000000000000000000000000000000000000000000000000005", - /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", - /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", - /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", - /* cofactor */ 1, - /* OID */ "1.3.132.0.32" -}, -#endif -#ifdef LTC_ECC_SECP256R1 -{ - /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.7" -}, -#endif -#ifdef LTC_ECC_SECP256K1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", - /* A */ "0000000000000000000000000000000000000000000000000000000000000000", - /* B */ "0000000000000000000000000000000000000000000000000000000000000007", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", - /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", - /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", - /* cofactor */ 1, - /* OID */ "1.3.132.0.10" -}, -#endif -#ifdef LTC_ECC_SECP384R1 -{ - /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", - /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", - /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", - /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", - /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", - /* cofactor */ 1, - /* OID */ "1.3.132.0.34" -}, -#endif -#ifdef LTC_ECC_SECP521R1 -{ - /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", - /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", - /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", - /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", - /* cofactor */ 1, - /* OID */ "1.3.132.0.35" -}, -#endif -#ifdef LTC_ECC_PRIME239V1 -{ - /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", - /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", - /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", - /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", - /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", - /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.4" -}, -#endif -#ifdef LTC_ECC_PRIME239V2 -{ - /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", - /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", - /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", - /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", - /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", - /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.5" -}, -#endif -#ifdef LTC_ECC_PRIME239V3 -{ - /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", - /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", - /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", - /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", - /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", - /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", - /* cofactor */ 1, - /* OID */ "1.2.840.10045.3.1.6" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP160R1 -{ - /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", - /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", - /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58", - /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", - /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", - /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.1" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP192R1 -{ - /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", - /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", - /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", - /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", - /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", - /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.3" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP224R1 -{ - /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", - /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", - /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", - /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", - /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", - /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.5" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP256R1 -{ - /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", - /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", - /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", - /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", - /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", - /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.7" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP320R1 -{ - /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", - /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", - /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", - /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", - /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", - /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.9" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP384R1 -{ - /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", - /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", - /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", - /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", - /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", - /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.11" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP512R1 -{ - /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", - /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", - /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", - /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", - /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", - /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.13" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP160T1 -{ - /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", - /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C", - /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", - /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", - /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378", - /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.2" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP192T1 -{ - /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", - /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", - /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", - /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", - /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129", - /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.4" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP224T1 -{ - /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", - /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", - /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", - /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", - /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580", - /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.6" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP256T1 -{ - /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", - /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", - /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", - /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", - /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", - /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.8" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP320T1 -{ - /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", - /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", - /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", - /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", - /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52", - /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.10" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP384T1 -{ - /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", - /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", - /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", - /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", - /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", - /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.12" -}, -#endif -#ifdef LTC_ECC_BRAINPOOLP512T1 -{ - /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", - /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", - /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", - /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", - /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", - /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", - /* cofactor */ 1, - /* OID */ "1.3.36.3.3.2.8.1.1.14" -}, -#endif -{ - NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL -} -}; - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c deleted file mode 100644 index 472e1b5..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_export.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_ansi_x963_export.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** ECC X9.63 (Sec. 4.3.6) uncompressed export - @param key Key to export - @param out [out] destination of export - @param outlen [in/out] Length of destination and final output size - Return CRYPT_OK on success -*/ -int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen) -{ - return ecc_get_key(out, outlen, PK_PUBLIC, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c deleted file mode 100644 index c877f6a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ansi_x963_import.c +++ /dev/null @@ -1,58 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file ecc_ansi_x963_import.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** Import an ANSI X9.63 format public key - @param in The input data to read - @param inlen The length of the input data - @param key [out] destination to store imported key \ -*/ -int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - return ecc_ansi_x963_import_ex(in, inlen, key, NULL); -} - -int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - /* must be odd */ - if ((inlen & 1) == 0) { - return CRYPT_INVALID_ARG; - } - - /* initialize key->dp */ - if (cu == NULL) { - /* this case works only for uncompressed public keys */ - if ((err = ecc_set_curve_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; } - } - else { - /* this one works for both compressed / uncompressed pubkeys */ - if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } - } - - /* load public key */ - if ((err = ecc_set_key(in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; } - - /* we're done */ - return CRYPT_OK; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_decrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_decrypt_key.c deleted file mode 100644 index 7a4fac2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_decrypt_key.c +++ /dev/null @@ -1,133 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_decrypt_key.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Decrypt an ECC encrypted key - @param in The ciphertext - @param inlen The length of the ciphertext (octets) - @param out [out] The plaintext - @param outlen [in/out] The max size and resulting size of the plaintext - @param key The corresponding private ECC key - @return CRYPT_OK if successful -*/ -int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const ecc_key *key) -{ - unsigned char *ecc_shared, *skey, *pub_expt; - unsigned long x, y; - unsigned long hashOID[32] = { 0 }; - int hash, err; - ecc_key pubkey; - ltc_asn1_list decode[3]; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* right key type? */ - if (key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* decode to find out hash */ - LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, LTC_ARRAY_SIZE(hashOID)); - err = der_decode_sequence(in, inlen, decode, 1); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - return err; - } - - hash = find_hash_oid(hashOID, decode[0].size); - if (hash_is_valid(hash) != CRYPT_OK) { - return CRYPT_INVALID_PACKET; - } - - /* we now have the hash! */ - - /* allocate memory */ - pub_expt = XMALLOC(ECC_BUF_SIZE); - ecc_shared = XMALLOC(ECC_BUF_SIZE); - skey = XMALLOC(MAXBLOCKSIZE); - if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { - if (pub_expt != NULL) { - XFREE(pub_expt); - } - if (ecc_shared != NULL) { - XFREE(ecc_shared); - } - if (skey != NULL) { - XFREE(skey); - } - return CRYPT_MEM; - } - LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); - LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); - - /* read the structure in now */ - if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* import ECC key from packet */ - if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } - - /* make shared key */ - x = ECC_BUF_SIZE; - if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { - ecc_free(&pubkey); - goto LBL_ERR; - } - ecc_free(&pubkey); - - y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE); - if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* ensure the hash of the shared secret is at least as big as the encrypt itself */ - if (decode[2].size > y) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* avoid buffer overflow */ - if (*outlen < decode[2].size) { - *outlen = decode[2].size; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* Decrypt the key */ - for (x = 0; x < decode[2].size; x++) { - out[x] = skey[x] ^ ecc_shared[x]; - } - *outlen = x; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(pub_expt, ECC_BUF_SIZE); - zeromem(ecc_shared, ECC_BUF_SIZE); - zeromem(skey, MAXBLOCKSIZE); -#endif - - XFREE(pub_expt); - XFREE(ecc_shared); - XFREE(skey); - - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_encrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_encrypt_key.c deleted file mode 100644 index bac62bf..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_encrypt_key.c +++ /dev/null @@ -1,120 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_encrypt_key.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Encrypt a symmetric key with ECC - @param in The symmetric key you want to encrypt - @param inlen The length of the key to encrypt (octets) - @param out [out] The destination for the ciphertext - @param outlen [in/out] The max size and resulting size of the ciphertext - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param hash The index of the hash you want to use - @param key The ECC key you want to encrypt to - @return CRYPT_OK if successful -*/ -int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, - const ecc_key *key) -{ - unsigned char *pub_expt, *ecc_shared, *skey; - ecc_key pubkey; - unsigned long x, y, pubkeysize; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (inlen > hash_descriptor[hash].hashsize) { - return CRYPT_INVALID_HASH; - } - - /* make a random key and export the public copy */ - if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; } - if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; } - - pub_expt = XMALLOC(ECC_BUF_SIZE); - ecc_shared = XMALLOC(ECC_BUF_SIZE); - skey = XMALLOC(MAXBLOCKSIZE); - if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { - if (pub_expt != NULL) { - XFREE(pub_expt); - } - if (ecc_shared != NULL) { - XFREE(ecc_shared); - } - if (skey != NULL) { - XFREE(skey); - } - ecc_free(&pubkey); - return CRYPT_MEM; - } - - pubkeysize = ECC_BUF_SIZE; - if (ltc_mp.sqrtmod_prime != NULL) { - /* PK_COMPRESSED requires sqrtmod_prime */ - err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey); - } - else { - err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey); - } - if (err != CRYPT_OK) { - ecc_free(&pubkey); - goto LBL_ERR; - } - - /* make random key */ - x = ECC_BUF_SIZE; - if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { - ecc_free(&pubkey); - goto LBL_ERR; - } - ecc_free(&pubkey); - y = MAXBLOCKSIZE; - if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* Encrypt key */ - for (x = 0; x < inlen; x++) { - skey[x] ^= in[x]; - } - - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, - LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, - LTC_ASN1_OCTET_STRING, inlen, skey, - LTC_ASN1_EOL, 0UL, NULL); - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - /* clean up */ - zeromem(pub_expt, ECC_BUF_SIZE); - zeromem(ecc_shared, ECC_BUF_SIZE); - zeromem(skey, MAXBLOCKSIZE); -#endif - - XFREE(skey); - XFREE(ecc_shared); - XFREE(pub_expt); - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export.c deleted file mode 100644 index 69b53bc..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_export.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Export an ECC key as a binary packet - @param out [out] Destination for the key - @param outlen [in/out] Max size and resulting size of the exported key - @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) - @param key The key to export - @return CRYPT_OK if successful -*/ -int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) -{ - int err; - unsigned char flags[1]; - unsigned long key_size; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* type valid? */ - if (key->type != PK_PRIVATE && type == PK_PRIVATE) { - return CRYPT_PK_TYPE_MISMATCH; - } - - /* we store the NIST byte size */ - key_size = key->dp.size; - - if (type == PK_PRIVATE) { - flags[0] = 1; - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, - LTC_ASN1_INTEGER, 1UL, key->pubkey.x, - LTC_ASN1_INTEGER, 1UL, key->pubkey.y, - LTC_ASN1_INTEGER, 1UL, key->k, - LTC_ASN1_EOL, 0UL, NULL); - } else { - flags[0] = 0; - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, - LTC_ASN1_INTEGER, 1UL, key->pubkey.x, - LTC_ASN1_INTEGER, 1UL, key->pubkey.y, - LTC_ASN1_EOL, 0UL, NULL); - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export_openssl.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export_openssl.c deleted file mode 100644 index a58f40e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_export_openssl.c +++ /dev/null @@ -1,167 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Export an ECC key as a binary packet - @param out [out] Destination for the key - @param outlen [in/out] Max size and resulting size of the exported key - @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) - @param key The key to export - @return CRYPT_OK if successful -*/ - -int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) -{ - int err; - void *prime, *order, *a, *b, *gx, *gy; - unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512]; - unsigned long len_a, len_b, len_k, len_g, len_xy; - unsigned long cofactor, one = 1; - const char *OID; - unsigned long oid[16], oidlen; - ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams; - int flag_oid = type & PK_CURVEOID ? 1 : 0; - int flag_com = type & PK_COMPRESSED ? 1 : 0; - int flag_pri = type & PK_PRIVATE ? 1 : 0; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH; - - if (flag_oid) { - /* http://tools.ietf.org/html/rfc5912 - ECParameters ::= CHOICE { - namedCurve CURVE.&id({NamedCurve}) # OBJECT - } - */ - if (key->dp.oidlen == 0) { err = CRYPT_INVALID_ARG; goto error; } - LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen); - } - else { - prime = key->dp.prime; - order = key->dp.order; - a = key->dp.A; - b = key->dp.B; - gx = key->dp.base.x; - gy = key->dp.base.y; - cofactor = key->dp.cofactor; - - /* curve param a */ - len_a = ltc_mp_unsigned_bin_size(a); - if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } - if ((err = ltc_mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } - if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ - - /* curve param b */ - len_b = ltc_mp_unsigned_bin_size(b); - if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } - if ((err = ltc_mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } - if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ - - /* base point - (un)compressed based on flag_com */ - len_g = sizeof(bin_g); - err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); - if (err != CRYPT_OK) { goto error; } - - /* we support only prime-field EC */ - if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } - - /* http://tools.ietf.org/html/rfc3279 - ECParameters ::= SEQUENCE { # SEQUENCE - version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01 - FieldID ::= SEQUENCE { # SEQUENCE - fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field - parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER - } - Curve ::= SEQUENCE { # SEQUENCE - a FieldElement ::= OCTET STRING # OCTET STRING - b FieldElement ::= OCTET STRING # OCTET STRING - seed BIT STRING OPTIONAL - } - base ECPoint ::= OCTET STRING # OCTET STRING - order INTEGER, # INTEGER - cofactor INTEGER OPTIONAL # INTEGER - } - */ - - oidlen = LTC_ARRAY_SIZE(oid); - if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { - goto error; - } - - /* FieldID SEQUENCE */ - LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); - LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); - - /* Curve SEQUENCE */ - LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a); - LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b); - - /* ECParameters SEQUENCE */ - LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); - LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); - LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL); - LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g); - LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); - LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); - - /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */ - LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); - } - - /* public key - (un)compressed based on flag_com */ - len_xy = sizeof(bin_xy); - err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); - if (err != CRYPT_OK) { - goto error; - } - - if (flag_pri) { - - /* http://tools.ietf.org/html/rfc5915 - ECPrivateKey ::= SEQUENCE { # SEQUENCE - version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01 - privateKey OCTET STRING, # OCTET STRING - [0] ECParameters # see above - [1] publicKey # BIT STRING - } - */ - - /* private key */ - len_k = ltc_mp_unsigned_bin_size(key->k); - if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } - if ((err = ltc_mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) { goto error; } - - LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy); - LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1); - LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k); - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */ - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */ - - err = der_encode_sequence(seq_priv, 4, out, outlen); - } - else { - /* http://tools.ietf.org/html/rfc5480 - SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE - AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE - algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey - ECParameters # see above - } - subjectPublicKey BIT STRING # BIT STRING - } - */ - err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy, - ecparams.type, ecparams.data, ecparams.size ); - } - -error: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_find_curve.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_find_curve.c deleted file mode 100644 index 87d6344..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_find_curve.c +++ /dev/null @@ -1,241 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -static const struct { - const char *OID; - const char *names[6]; -} s_curve_names[] = { -#ifdef LTC_ECC_SECP112R1 - { - "1.3.132.0.6", { "SECP112R1", "ECC-112", NULL } - }, -#endif -#ifdef LTC_ECC_SECP112R2 - { - "1.3.132.0.7", { "SECP112R2", NULL } - }, -#endif -#ifdef LTC_ECC_SECP128R1 - { - "1.3.132.0.28", { "SECP128R1", "ECC-128", NULL } - }, -#endif -#ifdef LTC_ECC_SECP128R2 - { - "1.3.132.0.29", { "SECP128R2", NULL } - }, -#endif -#ifdef LTC_ECC_SECP160R1 - { - "1.3.132.0.8", { "SECP160R1", "ECC-160", NULL } - }, -#endif -#ifdef LTC_ECC_SECP160R2 - { - "1.3.132.0.30", { "SECP160R2", NULL } - }, -#endif -#ifdef LTC_ECC_SECP160K1 - { - "1.3.132.0.9", { "SECP160K1", NULL } - }, -#endif -#ifdef LTC_ECC_SECP192R1 - { - "1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL } - }, -#endif -#ifdef LTC_ECC_PRIME192V2 - { - "1.2.840.10045.3.1.2", { "PRIME192V2", NULL } - }, -#endif -#ifdef LTC_ECC_PRIME192V3 - { - "1.2.840.10045.3.1.3", { "PRIME192V3", NULL } - }, -#endif -#ifdef LTC_ECC_SECP192K1 - { - "1.3.132.0.31", { "SECP192K1", NULL } - }, -#endif -#ifdef LTC_ECC_SECP224R1 - { - "1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL } - }, -#endif -#ifdef LTC_ECC_SECP224K1 - { - "1.3.132.0.32", { "SECP224K1", NULL } - }, -#endif -#ifdef LTC_ECC_SECP256R1 - { - "1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL } - }, -#endif -#ifdef LTC_ECC_SECP256K1 - { - "1.3.132.0.10", { "SECP256K1", NULL } - }, -#endif -#ifdef LTC_ECC_SECP384R1 - { - "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL } - }, -#endif -#ifdef LTC_ECC_SECP521R1 - { - "1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL } - }, -#endif -#ifdef LTC_ECC_PRIME239V1 - { - "1.2.840.10045.3.1.4", { "PRIME239V1", NULL } - }, -#endif -#ifdef LTC_ECC_PRIME239V2 - { - "1.2.840.10045.3.1.5", { "PRIME239V2", NULL } - }, -#endif -#ifdef LTC_ECC_PRIME239V3 - { - "1.2.840.10045.3.1.6", { "PRIME239V3", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP160R1 - { - "1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP192R1 - { - "1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP224R1 - { - "1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP256R1 - { - "1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP320R1 - { - "1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP384R1 - { - "1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP512R1 - { - "1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP160T1 - { - "1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP192T1 - { - "1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP224T1 - { - "1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP256T1 - { - "1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP320T1 - { - "1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP384T1 - { - "1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL } - }, -#endif -#ifdef LTC_ECC_BRAINPOOLP512T1 - { - "1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL } - }, -#endif - { - NULL, { NULL } - } -}; - -/* case-insensitive match + ignore '-', '_', ' ' */ -static int s_name_match(const char *left, const char *right) -{ - char lc_r, lc_l; - - while ((*left != '\0') && (*right != '\0')) { - while ((*left == ' ') || (*left == '-') || (*left == '_')) left++; - while ((*right == ' ') || (*right == '-') || (*right == '_')) right++; - if (*left == '\0' || *right == '\0') break; - lc_r = *right; - lc_l = *left; - if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32; - if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32; - if (lc_l != lc_r) return 0; - left++; - right++; - } - - if ((*left == '\0') && (*right == '\0')) return 1; - return 0; -} - -int ecc_find_curve(const char *name_or_oid, const ltc_ecc_curve **cu) -{ - int i, j; - const char *OID = NULL; - - LTC_ARGCHK(name_or_oid != NULL); - - if (cu) *cu = NULL; - - for (i = 0; s_curve_names[i].OID != NULL && !OID; i++) { - if (XSTRCMP(s_curve_names[i].OID, name_or_oid) == 0) { - OID = s_curve_names[i].OID; - } - for (j = 0; s_curve_names[i].names[j] != NULL && !OID; j++) { - if (s_name_match(s_curve_names[i].names[j], name_or_oid)) { - OID = s_curve_names[i].OID; - } - } - } - - if (OID != NULL) { - for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { - if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) { - if (cu) *cu = <c_ecc_curves[i]; - return CRYPT_OK; - } - } - } - - return CRYPT_INVALID_ARG; /* not found */ -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_free.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_free.c deleted file mode 100644 index fd954d6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_free.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_free.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Free an ECC key from memory - @param key The key you wish to free -*/ -void ecc_free(ecc_key *key) -{ - LTC_ARGCHKVD(key != NULL); - - ltc_mp_cleanup_multi(&key->dp.prime, &key->dp.order, - &key->dp.A, &key->dp.B, - &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, - &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, - &key->k, NULL); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_key.c deleted file mode 100644 index 05586ef..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_key.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes) - @param out [out] destination of export - @param outlen [in/out] Length of destination and final output size - @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED - @param key Key to export - Return CRYPT_OK on success -*/ - -int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) -{ - unsigned long size, ksize; - int err, compressed; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - size = key->dp.size; - compressed = type & PK_COMPRESSED ? 1 : 0; - type &= ~PK_COMPRESSED; - - if (type == PK_PUBLIC) { - if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) { - return err; - } - } - else if (type == PK_PRIVATE) { - if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; - if (size > *outlen) { - *outlen = size; - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = size; - if ((ksize = ltc_mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW; - /* pad and store k */ - if ((err = ltc_mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err; - zeromem(out, size - ksize); - } - else { - return CRYPT_INVALID_ARG; - } - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_oid_str.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_oid_str.c deleted file mode 100644 index 756f641..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_oid_str.c +++ /dev/null @@ -1,22 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** Extract OID as a string from ECC key - @param out [out] destination buffer - @param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte) - @param key The ECC key - Return CRYPT_OK on success -*/ - -int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key) -{ - LTC_ARGCHK(key != NULL); - - return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_size.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_size.c deleted file mode 100644 index e563339..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_get_size.c +++ /dev/null @@ -1,26 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_get_size.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Get the size of an ECC key - @param key The key to get the size of - @return The size (octets) of the key or INT_MAX on error -*/ -int ecc_get_size(const ecc_key *key) -{ - if (key == NULL) { - return INT_MAX; - } - return key->dp.size; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import.c deleted file mode 100644 index 32e1ef0..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import.c +++ /dev/null @@ -1,106 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file ecc_import.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Import an ECC key from a binary packet - @param in The packet to import - @param inlen The length of the packet - @param key [out] The destination of the import - @return CRYPT_OK if successful, upon error all allocated memory will be freed -*/ -int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - return ecc_import_ex(in, inlen, key, NULL); -} - -/** - Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones - @param in The packet to import - @param inlen The length of the packet - @param key [out] The destination of the import - @param cu pointer to user supplied params; must be the same as the params used when exporting - @return CRYPT_OK if successful, upon error all allocated memory will be freed -*/ -int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) -{ - unsigned long key_size; - unsigned char flags[1]; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* find out what type of key it is */ - err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, - LTC_ASN1_EOL, 0UL, NULL); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - return err; - } - - /* allocate & initialize the key */ - if (cu == NULL) { - if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; } - } else { - if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { goto done; } - } - - if (flags[0] == 1) { - /* private key */ - key->type = PK_PRIVATE; - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, - LTC_ASN1_INTEGER, 1UL, key->pubkey.x, - LTC_ASN1_INTEGER, 1UL, key->pubkey.y, - LTC_ASN1_INTEGER, 1UL, key->k, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto done; - } - } else if (flags[0] == 0) { - /* public key */ - key->type = PK_PUBLIC; - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, - LTC_ASN1_INTEGER, 1UL, key->pubkey.x, - LTC_ASN1_INTEGER, 1UL, key->pubkey.y, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto done; - } - } - else { - err = CRYPT_INVALID_PACKET; - goto done; - } - - /* set z */ - if ((err = ltc_mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } - - /* point on the curve + other checks */ - if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; } - - /* we're good */ - return CRYPT_OK; - -done: - ecc_free(key); - return err; -} -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_openssl.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_openssl.c deleted file mode 100644 index 7023b84..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_openssl.c +++ /dev/null @@ -1,142 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_DER) - -static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - ltc_asn1_list seq_priv[4], custom[2]; - unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE]; - unsigned long pkver = 0, curveoid[16]; - int err; - - /* ### try to load private key - no curve parameters just curve OID */ - - /* ECPrivateKey SEQUENCE */ - LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); - LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); - LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); - LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ - - /* try to load private key */ - err = der_decode_sequence(in, inlen, seq_priv, 4); - if (err != CRYPT_OK) { goto error; } - err = ecc_import_with_oid(bin_k, seq_priv[1].size, curveoid, custom[0].size, PK_PRIVATE, key); -error: - return err; -} - -int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key) -{ - char OID[256]; - unsigned long len; - const ltc_ecc_curve *curve; - int err; - - /* load curve parameters for given curve OID */ - len = sizeof(OID); - if ((err = pk_oid_num_to_str(oid, oid_len, OID, &len)) != CRYPT_OK) { goto error; } - if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } - if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } - /* load public key */ - err = ecc_set_key(in, inlen, type, key); -error: - return err; -} - -int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key) -{ - void *prime, *order, *a, *b, *gx, *gy; - ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; - unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; - unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; - unsigned long len_a, len_b, len_k, len_g, len_xy, len; - unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; - int err; - - if ((err = ltc_mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { - return err; - } - - /* FieldID SEQUENCE */ - LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); - LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); - /* Curve SEQUENCE */ - LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); - LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); - LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed)); - seq_curve[2].optional = 1; - /* ECParameters SEQUENCE */ - LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); - LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); - LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); - LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); - LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); - LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); - seq_ecparams[5].optional = 1; - if (type == PK_PRIVATE) { - /* ECPrivateKey SEQUENCE */ - LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); - LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); - LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); - LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ - LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ - /* try to load private key */ - err = der_decode_sequence(in, inlen, seq_priv, 4); - } else if (type == PK_PUBLIC) { - /* try to load public key */ - len_xy = sizeof(bin_xy); - len = 6; - err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); - } else { - err = CRYPT_PK_INVALID_TYPE; - } - if (err == CRYPT_OK) { - len_a = seq_curve[0].size; - len_b = seq_curve[1].size; - len_g = seq_ecparams[3].size; - /* create bignums */ - if ((err = ltc_mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } - if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } - /* load curve parameters */ - if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } - - if (type == PK_PRIVATE) { - len_k = seq_priv[1].size; - /* load private+public key */ - err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); - } else { - /* load public key */ - err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); - } - } -error: - ltc_mp_deinit_multi(prime, order, a, b, gx, gy, LTC_NULL); - return err; -} - -int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - int err; - - if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) { - goto success; - } - - if ((err = s_ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) { - goto success; - } - - err = ecc_import_with_curve(in, inlen, PK_PRIVATE, key); - -success: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_pkcs8.c deleted file mode 100644 index 5e37159..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_pkcs8.c +++ /dev/null @@ -1,173 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#if defined(LTC_MECC) && defined(LTC_DER) - -int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key) -{ - void *a, *b, *gx, *gy; - unsigned long len, cofactor, n; - int err; - char OID[256]; - const ltc_ecc_curve *curve; - ltc_asn1_list *p = NULL; - der_flexi_check case2_should[7]; - ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* init key */ - err = ltc_mp_init_multi(&a, &b, &gx, &gy, LTC_NULL); - if (err != CRYPT_OK) goto LBL_DER_FREE; - - /* Setup for CASE 2 */ - n=0; - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &version); - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_SEQUENCE, &field); - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_SEQUENCE, &point); - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_OCTET_STRING, &point_g); - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &order); - LTC_SET_DER_FLEXI_CHECK(case2_should, n++, LTC_ASN1_INTEGER, &p_cofactor); - LTC_SET_DER_FLEXI_CHECK(case2_should, n, LTC_ASN1_EOL, NULL); - - if (LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) { - /* CASE 1: curve by OID (AKA short variant): - * 0:d=0 hl=2 l= 100 cons: SEQUENCE - * 2:d=1 hl=2 l= 1 prim: INTEGER :00 - * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq) - * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey - * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10))) - * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) - */ - ltc_asn1_list *curve_oid = alg_id->child->next; - len = sizeof(OID); - if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; } - if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; } - if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; } - } else if (der_flexi_sequence_cmp(alg_id->child->next, case2_should) == CRYPT_OK) { - - /* CASE 2: explicit curve parameters (AKA long variant): - * 0:d=0 hl=3 l= 227 cons: SEQUENCE - * 3:d=1 hl=2 l= 1 prim: INTEGER :00 - * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq) - * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey - * 18:d=2 hl=3 l= 130 cons: SEQUENCE - * 21:d=3 hl=2 l= 1 prim: INTEGER :01 - * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field) - * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field - * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime) - * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point) - * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A) - * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B) - * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point) - * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order) - * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor) - * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) - */ - - if (ltc_mp_cmp_d(version->data, 1) != LTC_MP_EQ) { - goto LBL_DONE; - } - cofactor = ltc_mp_get_int(p_cofactor->data); - - if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) && - LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) && - LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) && - LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) { - - ltc_asn1_list *prime = field->child->next; - if ((err = ltc_mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) { - goto LBL_DONE; - } - if ((err = ltc_mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) { - goto LBL_DONE; - } - if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) { - goto LBL_DONE; - } - if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) { - goto LBL_DONE; - } - } - } else { - err = CRYPT_INVALID_PACKET; - goto LBL_DONE; - } - - /* load private key value 'k' */ - len = priv_key->size; - if (der_decode_sequence_flexi(priv_key->data, &len, &p) == CRYPT_OK) { - if (p->type == LTC_ASN1_SEQUENCE && - LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) && - LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) { - ltc_asn1_list *lk = p->child->next; - if (ltc_mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) { - err = CRYPT_INVALID_PACKET; - goto LBL_ECCFREE; - } - if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) { - goto LBL_ECCFREE; - } - goto LBL_DONE; /* success */ - } - } - err = CRYPT_INVALID_PACKET; - goto LBL_DONE; - -LBL_ECCFREE: - ecc_free(key); -LBL_DONE: - ltc_mp_deinit_multi(a, b, gx, gy, LTC_NULL); -LBL_DER_FREE: - if (p) der_free_sequence_flexi(p); - return err; -} - -/** - Import an ECC private from in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - ecc_key *key) -{ - int err; - ltc_asn1_list *l = NULL; - ltc_asn1_list *alg_id, *priv_key; - enum ltc_oid_id pka; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l); - if (err != CRYPT_OK) return err; - - if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto LBL_DER_FREE; - } - if (pka != LTC_OID_EC) { - err = CRYPT_INVALID_PACKET; - goto LBL_DER_FREE; - } - - err = ecc_import_pkcs8_asn1(alg_id, priv_key, key); - -LBL_DER_FREE: - der_free_sequence_flexi(l); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_x509.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_x509.c deleted file mode 100644 index 2b4ea77..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_import_x509.c +++ /dev/null @@ -1,54 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_DER) - -static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - unsigned char bin_xy[2*ECC_MAXSIZE+2]; - unsigned long curveoid[16]; - unsigned long len_xy, len_oid; - int err; - - len_xy = sizeof(bin_xy); - len_oid = 16; - err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, - LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); - if (err != CRYPT_OK) { goto error; } - err = ecc_import_with_oid(bin_xy, len_xy, curveoid, len_oid, PK_PUBLIC, key); -error: - return err; -} - -int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - int err; - - if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) { - goto success; - } - - err = ecc_import_with_curve(in, inlen, PK_PUBLIC, key); - -success: - return err; -} - -/** - Import an ECC key from a X.509 certificate - @param in The packet to import from - @param inlen It's length (octets) - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - return x509_decode_public_key_from_certificate(in, inlen, - LTC_OID_EC, - LTC_ASN1_EOL, NULL, NULL, - (public_key_decode_cb)ecc_import_subject_public_key_info, key); -} - -#endif /* LTC_MECC */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_make_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_make_key.c deleted file mode 100644 index c8239cf..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_make_key.c +++ /dev/null @@ -1,74 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_make_key.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Make a new ECC key - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param keysize The keysize for the new key (in octets from 20 to 65 bytes) - @param key [out] Destination of the newly created key - @return CRYPT_OK if successful, upon error all allocated memory will be freed -*/ -int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) -{ - int err; - - if ((err = ecc_set_curve_by_size(keysize, key)) != CRYPT_OK) { return err; } - if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } - return CRYPT_OK; -} - -int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu) -{ - int err; - if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } - if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } - return CRYPT_OK; -} - -int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key) -{ - int err; - - LTC_ARGCHK(ltc_mp.name != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(key->dp.size > 0); - - /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates): - * the generated private key k should be the range [1, order-1] - * a/ N = bitlen(order) - * b/ generate N random bits and convert them into big integer k - * c/ if k not in [1, order-1] go to b/ - * e/ Q = k*G - */ - if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) { - goto error; - } - - /* make the public key */ - if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) { - goto error; - } - key->type = PK_PRIVATE; - key->rfc6979_hash_alg = NULL; - - /* success */ - err = CRYPT_OK; - goto cleanup; - -error: - ecc_free(key); -cleanup: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_recover_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_recover_key.c deleted file mode 100644 index 10d2eb2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_recover_key.c +++ /dev/null @@ -1,265 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#if defined(LTC_MECC) && defined(LTC_ECC_SHAMIR) - -/** - @file ecc_recover_key.c - ECC Crypto, Russ Williams -*/ - -/** - Recover ECC public key from signature and hash - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param recid The recovery ID ("v"), can be -1 if signature contains it - @param sigformat The format of the signature (ecc_signature_type) - @param key The recovered public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_recover_key(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int recid, ecc_signature_type sigformat, ecc_key *key) -{ - ecc_point *mG = NULL, *mQ = NULL, *mR = NULL; - void *p, *m, *a, *b; - void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3; - void *mu = NULL, *ma = NULL; - void *mp = NULL; - int err; - unsigned long pbits, pbytes, i, shift_right; - unsigned char ch, buf[MAXBLOCKSIZE]; - - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(key != NULL); - - /* BEWARE: requires sqrtmod_prime */ - if (ltc_mp.sqrtmod_prime == NULL) { - return CRYPT_ERROR; - } - - /* allocate ints */ - if ((err = ltc_mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) { - return err; - } - - p = key->dp.order; - m = key->dp.prime; - a = key->dp.A; - b = key->dp.B; - if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { - goto error; - } - - /* allocate points */ - mG = ltc_ecc_new_point(); - mQ = ltc_ecc_new_point(); - mR = ltc_ecc_new_point(); - if (mR == NULL || mQ == NULL || mG == NULL) { - err = CRYPT_MEM; - goto error; - } - - if (sigformat == LTC_ECCSIG_RFC7518) { - /* RFC7518 format - raw (r,s) */ - i = ltc_mp_unsigned_bin_size(key->dp.order); - if (siglen != (2*i)) { - err = CRYPT_INVALID_PACKET; - goto error; - } - if ((err = ltc_mp_read_unsigned_bin(r, sig, i)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_unsigned_bin(s, sig+i, i)) != CRYPT_OK) { goto error; } - } - else if (sigformat == LTC_ECCSIG_ETH27) { - /* Ethereum (v,r,s) format */ - if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { - /* Only valid for secp256k1 - OID 1.3.132.0.10 */ - err = CRYPT_ERROR; goto error; - } - if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ - err = CRYPT_INVALID_PACKET; - goto error; - } - i = (unsigned long)sig[64]; - if ((i>=27) && (i<31)) i -= 27; /* Ethereum adds 27 to recovery ID */ - if (recid >= 0 && ((unsigned long)recid != i)) { - /* Recovery ID specified, but doesn't match signature */ - err = CRYPT_INVALID_PACKET; - goto error; - } - recid = i; - if ((err = ltc_mp_read_unsigned_bin(r, sig, 32)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_unsigned_bin(s, sig+32, 32)) != CRYPT_OK) { goto error; } - } -#ifdef LTC_DER - else if (sigformat == LTC_ECCSIG_ANSIX962) { - /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ - if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } - } -#endif -#ifdef LTC_SSH - else if (sigformat == LTC_ECCSIG_RFC5656) { - char name[64], name2[64]; - unsigned long namelen = sizeof(name); - unsigned long name2len = sizeof(name2); - - /* Decode as SSH data sequence, per RFC4251 */ - if ((err = ssh_decode_sequence_multi(sig, &siglen, - LTC_SSHDATA_STRING, name, &namelen, - LTC_SSHDATA_MPINT, r, - LTC_SSHDATA_MPINT, s, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) { goto error; } - - - /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } - if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { - err = CRYPT_INVALID_ARG; - goto error; - } - } -#endif - else { - /* Unknown signature format */ - err = CRYPT_ERROR; - goto error; - } - - if (recid < 0 || (unsigned long)recid >= 2*(key->dp.cofactor+1)) { - /* Recovery ID is out of range, reject it */ - err = CRYPT_INVALID_ARG; - goto error; - } - - /* check for zero */ - if (ltc_mp_cmp_d(r, 0) != LTC_MP_GT || ltc_mp_cmp_d(s, 0) != LTC_MP_GT || - ltc_mp_cmp(r, p) != LTC_MP_LT || ltc_mp_cmp(s, p) != LTC_MP_LT) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* read hash - truncate if needed */ - pbits = ltc_mp_count_bits(p); - pbytes = (pbits+7) >> 3; - if (pbits > hashlen*8) { - if ((err = ltc_mp_read_unsigned_bin(e, hash, hashlen)) != CRYPT_OK) { goto error; } - } - else if (pbits % 8 == 0) { - if ((err = ltc_mp_read_unsigned_bin(e, hash, pbytes)) != CRYPT_OK) { goto error; } - } - else { - shift_right = 8 - pbits % 8; - for (i=0, ch=0; i> shift_right); - } - if ((err = ltc_mp_read_unsigned_bin(e, buf, pbytes)) != CRYPT_OK) { goto error; } - } - - /* decompress point from r=(x mod p) - BEWARE: requires sqrtmod_prime */ - /* x = r + p*(recid/2) */ - if ((err = ltc_mp_set(x, recid/2)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(p, x, m, x)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add(x, r, x)) != CRYPT_OK) { goto error; } - /* compute x^3 */ - if ((err = ltc_mp_sqr(x, t1)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(t1, x, m, t1)) != CRYPT_OK) { goto error; } - /* compute x^3 + a*x */ - if ((err = ltc_mp_mulmod(a, x, m, t2)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto error; } - /* compute x^3 + a*x + b */ - if ((err = ltc_mp_add(t1, b, t1)) != CRYPT_OK) { goto error; } - /* compute sqrt(x^3 + a*x + b) */ - if ((err = ltc_mp_sqrtmod_prime(t1, m, t2)) != CRYPT_OK) { goto error; } - - /* fill in mR */ - if ((err = ltc_mp_copy(x, mR->x)) != CRYPT_OK) { goto error; } - if ((ltc_mp_isodd(t2) && (recid%2)) || (!ltc_mp_isodd(t2) && !(recid%2))) { - if ((err = ltc_mp_mod(t2, m, mR->y)) != CRYPT_OK) { goto error; } - } - else { - if ((err = ltc_mp_submod(m, t2, m, mR->y)) != CRYPT_OK) { goto error; } - } - if ((err = ltc_mp_set(mR->z, 1)) != CRYPT_OK) { goto error; } - - /* w = r^-1 mod n */ - if ((err = ltc_mp_invmod(r, p, w)) != CRYPT_OK) { goto error; } - /* v1 = sw */ - if ((err = ltc_mp_mulmod(s, w, p, v1)) != CRYPT_OK) { goto error; } - /* v2 = -ew */ - if ((err = ltc_mp_mulmod(e, w, p, v2)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_submod(p, v2, p, v2)) != CRYPT_OK) { goto error; } - - /* w = s^-1 mod n */ - if ((err = ltc_mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } - /* u1 = ew */ - if ((err = ltc_mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } - /* u2 = rw */ - if ((err = ltc_mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } - - /* find mG */ - if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } - - /* find the montgomery mp */ - if ((err = ltc_mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } - - /* for curves with a == -3 keep ma == NULL */ - if (ltc_mp_cmp(a_plus3, m) != LTC_MP_EQ) { - if ((err = ltc_mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } - } - - /* recover mQ from mR */ - /* compute v1*mR + v2*mG = mQ using Shamir's trick */ - if ((err = ltc_mp.ecc_mul2add(mR, v1, mG, v2, mQ, ma, m)) != CRYPT_OK) { goto error; } - - /* compute u1*mG + u2*mQ = mG using Shamir's trick */ - if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } - - /* v = X_x1 mod n */ - if ((err = ltc_mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } - - /* does v == r */ - if (ltc_mp_cmp(v, r) == LTC_MP_EQ) { - /* found public key which verifies signature */ - if ((err = ltc_ecc_copy_point(mQ, &key->pubkey)) != CRYPT_OK) { goto error; } - /* point on the curve + other checks */ - if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; } - - key->type = PK_PUBLIC; - - err = CRYPT_OK; - } - else { - /* not found - recid is wrong or we're unable to calculate public key for some other reason */ - err = CRYPT_INVALID_ARG; - } - -error: - if (ma != NULL) ltc_mp_clear(ma); - if (mu != NULL) ltc_mp_clear(mu); - if (mp != NULL) ltc_mp_montgomery_free(mp); - if (mR != NULL) ltc_ecc_del_point(mR); - if (mQ != NULL) ltc_ecc_del_point(mQ); - if (mG != NULL) ltc_ecc_del_point(mG); - ltc_mp_deinit_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c deleted file mode 100644 index ebd17eb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c +++ /dev/null @@ -1,162 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_rfc6979_key.c - ECC Crypto, Russ Williams -*/ - -#ifdef LTC_MECC -#ifdef LTC_SHA256 - -/** - Make deterministic ECC key using the RFC6979 method - @param priv [in] Private key for HMAC - @param in Message to sign for HMAC - @param inlen Length of the message - @param key [out] Newly created deterministic key - @return CRYPT_OK if successful, upon error all allocated memory will be freed -*/ -int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, ecc_key *key) -{ - int err, hash = -1; - unsigned char v[MAXBLOCKSIZE], k[MAXBLOCKSIZE]; - unsigned char buffer[256], sep[1], privkey[128]; - unsigned long order_bits, len_diff, pk_len, zero_extend, outlen, klen, vlen, buflen, qlen, hashsize; - void *r, *d; - - LTC_ARGCHK(ltc_mp.name != NULL); - LTC_ARGCHK(priv != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(key->dp.size > 0); - - if (priv->rfc6979_hash_alg == NULL) { - return CRYPT_INVALID_ARG; - } - hash = find_hash(priv->rfc6979_hash_alg); - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - hashsize = hash_descriptor[hash].hashsize; - - if ((err = ltc_mp_init_multi(&r, &d, NULL)) != CRYPT_OK) { - return err; - } - - /* Length, in bytes, of key */ - order_bits = ltc_mp_count_bits(key->dp.order); - qlen = (order_bits+7) >> 3; - len_diff = qlen > inlen ? qlen - inlen : 0; - pk_len = (ltc_mp_count_bits(priv->k)+7) >> 3; - zero_extend = qlen - pk_len; - XMEMSET(buffer, 0x00, len_diff + zero_extend); - - /* RFC6979 3.2b, set V */ - XMEMSET(v, 0x01, hashsize); - - /* RFC6979 3.2c, set K */ - XMEMSET(k, 0x00, hashsize); - - if ((err = ltc_mp_to_unsigned_bin(priv->k, privkey) != CRYPT_OK)) { goto error; } - /* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */ - sep[0] = 0; - klen = sizeof(k); - if((err = hmac_memory_multi(hash, - k, hashsize, - k, &klen, - v, hashsize, - sep, 1, - buffer, zero_extend, - privkey, qlen - zero_extend, - buffer, len_diff, - in, qlen - len_diff, - LTC_NULL)) != CRYPT_OK) { goto error; } - - /* RFC6979 3.2e, set V = HMAC_K(V) */ - vlen = sizeof(v); - if((err = hmac_memory(hash, k, klen, v, hashsize, v, &vlen)) != CRYPT_OK) { goto error; } - - /* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */ - sep[0] = 0x01; - outlen = sizeof(k); - if((err = hmac_memory_multi(hash, - k, klen, - k, &klen, - v, hashsize, - sep, 1, - buffer, zero_extend, - privkey, qlen - zero_extend, - buffer, len_diff, - in, qlen - len_diff, - LTC_NULL)) != CRYPT_OK) { goto error; } - - /* RFC6979 3.2g, set V = HMAC_K(V) */ - outlen = sizeof(v); - if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; } - - /* RFC6979 3.2h, generate and check key */ - do { - /* concatenate hash bits into T */ - buflen = 0; - while (buflen < qlen) { - if (buflen + hashsize >= sizeof(buffer) || buflen + hashsize < buflen) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - outlen = sizeof(v); - if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; } - XMEMCPY(&buffer[buflen], v, hashsize); - buflen += hashsize; - } - - /* key->k = bits2int(T) */ - if ((err = ltc_mp_read_unsigned_bin(r, buffer, qlen)) != CRYPT_OK) { goto error; } - if ((qlen * 8) > order_bits) { - if ((err = ltc_mp_2expt(d, (qlen * 8) - order_bits)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_div(r, d, r, NULL)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_to_unsigned_bin(r, buffer)) != CRYPT_OK) { goto error; } - qlen = ltc_mp_unsigned_bin_size(r); - } - - if ((err = ecc_set_key(buffer, qlen, PK_PRIVATE, key))!= CRYPT_OK) { goto error; } - - /* check that k is in range [1,q-1] */ - if (ltc_mp_cmp_d(key->k, 0) == LTC_MP_GT && ltc_mp_cmp(key->k, key->dp.order) == LTC_MP_LT) { - /* Check that pubkey.x != 0 (mod p) */ - if ((err = ltc_mp_mod(key->pubkey.x, key->dp.order, r)) != CRYPT_OK) { goto error; } - - /* if we have a valid key, exit loop */ - if (ltc_mp_iszero(r) == LTC_MP_NO) - break; - } else { - /* K = HMAC_K(V::0x00) */ - buffer[0] = 0x0; - outlen = sizeof(k); - if((err = hmac_memory_multi(hash, k, klen, k, &klen, v, hashsize, buffer, 1, LTC_NULL)) != CRYPT_OK) { goto error; } - - /* V = HMAC_K(V) */ - outlen = sizeof(v); - if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; } - - /* ... and try again! */ - } - } while (1); - - key->type = PK_PRIVATE; - - /* success */ - err = CRYPT_OK; - goto cleanup; - -error: - ecc_free(key); -cleanup: - ltc_mp_cleanup_multi(&d, &r, NULL); - return err; -} - -#endif -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve.c deleted file mode 100644 index f340776..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve.c +++ /dev/null @@ -1,88 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MECC - -int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(cu != NULL); - - if ((err = ltc_mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, - &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, - &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - NULL)) != CRYPT_OK) { - return err; - } - - key->rfc6979_hash_alg = NULL; - - /* A, B, order, prime, Gx, Gy */ - if ((err = ltc_mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_radix(key->dp.A, cu->A, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_radix(key->dp.B, cu->B, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_radix(key->dp.base.x, cu->Gx, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_radix(key->dp.base.y, cu->Gy, 16)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } - /* cofactor & size */ - key->dp.cofactor = cu->cofactor; - key->dp.size = ltc_mp_unsigned_bin_size(key->dp.prime); - /* OID string >> unsigned long oid[16] + oidlen */ - key->dp.oidlen = 16; - if ((err = pk_oid_str_to_num(cu->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; } - /* success */ - return CRYPT_OK; - -error: - ecc_free(key); - return err; -} - -int ecc_set_curve_by_size(int size, ecc_key *key) -{ - const ltc_ecc_curve *cu = NULL; - int err = CRYPT_ERROR; - - /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */ - if (size <= 14) { - err = ecc_find_curve("SECP112R1", &cu); - } - else if (size <= 16) { - err = ecc_find_curve("SECP128R1", &cu); - } - else if (size <= 20) { - err = ecc_find_curve("SECP160R1", &cu); - } - else if (size <= 24) { - err = ecc_find_curve("SECP192R1", &cu); - } - else if (size <= 28) { - err = ecc_find_curve("SECP224R1", &cu); - } - else if (size <= 32) { - err = ecc_find_curve("SECP256R1", &cu); - } - else if (size <= 48) { - err = ecc_find_curve("SECP384R1", &cu); - } - else if (size <= 66) { - err = ecc_find_curve("SECP521R1", &cu); - } - - if (err == CRYPT_OK && cu != NULL) return ecc_set_curve(cu, key); - - return CRYPT_INVALID_ARG; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve_internal.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve_internal.c deleted file mode 100644 index cdd5f2f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_curve_internal.c +++ /dev/null @@ -1,125 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_MECC - -static int s_ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn) -{ - if (ltc_mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0; - if (ltc_mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0; - return 1; -} - -static void s_ecc_oid_lookup(ecc_key *key) -{ - void *bn; - const ltc_ecc_curve *curve; - - key->dp.oidlen = 0; - if (ltc_mp_init(&bn) != CRYPT_OK) return; - for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) { - if (s_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue; - if (s_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue; - if (s_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue; - if (s_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue; - if (s_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue; - if (s_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue; - if (key->dp.cofactor != curve->cofactor) continue; - break; /* found */ - } - ltc_mp_clear(bn); - if (curve->prime && curve->OID) { - key->dp.oidlen = 16; /* size of key->dp.oid */ - pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen); - } -} - -int ecc_copy_curve(const ecc_key *srckey, ecc_key *key) -{ - unsigned long i; - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(srckey != NULL); - - if ((err = ltc_mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, - &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, - &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - NULL)) != CRYPT_OK) { - return err; - } - - /* A, B, order, prime, Gx, Gy */ - if ((err = ltc_mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; } - if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; } - /* cofactor & size */ - key->dp.cofactor = srckey->dp.cofactor; - key->dp.size = srckey->dp.size; - /* OID */ - if (srckey->dp.oidlen > 0) { - key->dp.oidlen = srckey->dp.oidlen; - for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i]; - } - else { - s_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */ - } - /* success */ - return CRYPT_OK; - -error: - ecc_free(key); - return err; -} - -int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(a != NULL); - LTC_ARGCHK(b != NULL); - LTC_ARGCHK(prime != NULL); - LTC_ARGCHK(order != NULL); - LTC_ARGCHK(gx != NULL); - LTC_ARGCHK(gy != NULL); - - if ((err = ltc_mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, - &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, - &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - NULL)) != CRYPT_OK) { - return err; - } - - /* A, B, order, prime, Gx, Gy */ - if ((err = ltc_mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } - /* cofactor & size */ - key->dp.cofactor = cofactor; - key->dp.size = ltc_mp_unsigned_bin_size(prime); - /* try to find OID in ltc_ecc_curves */ - s_ecc_oid_lookup(key); - /* success */ - return CRYPT_OK; - -error: - ecc_free(key); - return err; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_key.c deleted file mode 100644 index b7204b8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_set_key.c +++ /dev/null @@ -1,57 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key) -{ - int err; - void *prime, *a, *b; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - prime = key->dp.prime; - a = key->dp.A; - b = key->dp.B; - - if (type == PK_PRIVATE) { - /* load private key */ - if ((err = ltc_mp_read_unsigned_bin(key->k, in, inlen)) != CRYPT_OK) { - goto error; - } - if (ltc_mp_iszero(key->k) || (ltc_mp_cmp(key->k, key->dp.order) != LTC_MP_LT)) { - err = CRYPT_INVALID_PACKET; - goto error; - } - /* compute public key */ - if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; } - } - else if (type == PK_PUBLIC) { - /* load public key */ - if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } - } - else { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* point on the curve + other checks */ - if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { - goto error; - } - - key->type = type; - key->rfc6979_hash_alg = NULL; - return CRYPT_OK; - -error: - ecc_free(key); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_shared_secret.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_shared_secret.c deleted file mode 100644 index df879dc..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_shared_secret.c +++ /dev/null @@ -1,66 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ecc_shared_secret.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Create an ECC shared secret between two keys - @param private_key The private ECC key - @param public_key The public key - @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) - @param outlen [in/out] The max size and resulting size of the shared secret - @return CRYPT_OK if successful -*/ -int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, - unsigned char *out, unsigned long *outlen) -{ - unsigned long x; - ecc_point *result; - void *prime, *a; - int err; - - LTC_ARGCHK(private_key != NULL); - LTC_ARGCHK(public_key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* type valid? */ - if (private_key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* make new point */ - result = ltc_ecc_new_point(); - if (result == NULL) { - return CRYPT_MEM; - } - - prime = private_key->dp.prime; - a = private_key->dp.A; - - if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; } - - x = (unsigned long)ltc_mp_unsigned_bin_size(prime); - if (*outlen < x) { - *outlen = x; - err = CRYPT_BUFFER_OVERFLOW; - goto done; - } - zeromem(out, x); - if ((err = ltc_mp_to_unsigned_bin(result->x, out + (x - ltc_mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; } - - err = CRYPT_OK; - *outlen = x; -done: - ltc_ecc_del_point(result); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash.c deleted file mode 100644 index c9c278b..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Sign a message digest (ANSI X9.62 format) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) -{ - int err; - void *r, *s; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, NULL, key)) != CRYPT_OK) goto error; - - /* store as ASN.1 SEQUENCE { r, s -- integer } */ - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL); -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_eth27.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_eth27.c deleted file mode 100644 index dd06d14..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_eth27.c +++ /dev/null @@ -1,57 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** - Sign a message digest (Ethereum format with recovery_id+27) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) -{ - int err, recid; - void *r, *s; - unsigned long i; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* Only valid for secp256k1 - OID 1.3.132.0.10 */ - if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { - return CRYPT_ERROR; - } - if (*outlen < 65) { - *outlen = 65; - return CRYPT_BUFFER_OVERFLOW; - } - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, &recid, key)) != CRYPT_OK) goto error; - - zeromem(out, 65); - *outlen = 65; - i = ltc_mp_unsigned_bin_size(r); - if ((err = ltc_mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) goto error; - i = ltc_mp_unsigned_bin_size(s); - if ((err = ltc_mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) goto error; - out[64] = (unsigned char)(recid + 27); /* Recovery ID is 27/28 for Ethereum */ - err = CRYPT_OK; - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_internal.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_internal.c deleted file mode 100644 index 5321dde..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_internal.c +++ /dev/null @@ -1,115 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, - void *r, void *s, prng_state *prng, int wprng, - int *recid, const ecc_key *key) -{ - ecc_key pubkey; - void *e, *p, *b; - int v = 0; - int err, max_iterations = LTC_PK_MAX_RETRIES; - unsigned long pbits, pbytes, i, shift_right; - unsigned char ch, buf[MAXBLOCKSIZE]; - - LTC_ARGCHK(r != NULL); - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - /* is this a private key? */ - if (key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* init the bignums */ - if ((err = ltc_mp_init_multi(&e, &b, LTC_NULL)) != CRYPT_OK) { - return err; - } - - /* get the hash and load it as a bignum into 'e' */ - p = key->dp.order; - pbits = ltc_mp_count_bits(p); - pbytes = (pbits+7) >> 3; - if (pbits > inlen*8) { - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } - } - else if (pbits % 8 == 0) { - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } - } - else { - if (pbytes >= MAXBLOCKSIZE) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - shift_right = 8 - pbits % 8; - for (i=0, ch=0; i> shift_right); - } - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } - } - - /* make up a key and export the public copy */ - do { - if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } - if (key->rfc6979_hash_alg != NULL) { - if ((err = ecc_rfc6979_key(key, in, inlen, &pubkey)) != CRYPT_OK) { goto errnokey; } - } else { - if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } - } - - /* find r = x1 mod n */ - if ((err = ltc_mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } - - if (recid) { - /* find recovery ID (if needed) */ - v = 0; - if (ltc_mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; } - while (ltc_mp_cmp_d(s, 0) == LTC_MP_GT && ltc_mp_cmp(s, p) != LTC_MP_LT) { - /* Compute x1 div n... this will almost never be reached for curves with order 1 */ - v += 2; - if ((err = ltc_mp_sub(s, p, s)) != CRYPT_OK) { goto error; } - } - if (ltc_mp_isodd(pubkey.pubkey.y)) v += 1; - } - - if (ltc_mp_iszero(r) == LTC_MP_YES) { - ecc_free(&pubkey); - } else { - if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ - /* find s = (e + xr)/k */ - if ((err = ltc_mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ - if ((err = ltc_mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ - if ((err = ltc_mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ - if ((err = ltc_mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ - if ((err = ltc_mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ - if ((err = ltc_mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ - if ((err = ltc_mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ - ecc_free(&pubkey); - if (ltc_mp_iszero(s) == LTC_MP_NO) { - break; - } - } - } while (--max_iterations > 0); - - if (max_iterations == 0) { - goto errnokey; - } - - if (recid) *recid = v; - - goto errnokey; -error: - ecc_free(&pubkey); -errnokey: - ltc_mp_deinit_multi(e, b, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc5656.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc5656.c deleted file mode 100644 index fd9f10e..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc5656.c +++ /dev/null @@ -1,48 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_SSH) - -/** - Sign a message digest (RFC5656 / SSH format) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash_rfc5656(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) -{ - int err; - void *r, *s; - char name[64]; - unsigned long namelen = sizeof(name); - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* Get identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) return err; - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, NULL, key)) != CRYPT_OK) goto error; - - /* Store as SSH data sequence, per RFC4251 */ - err = ssh_encode_sequence_multi(out, outlen, - LTC_SSHDATA_STRING, name, namelen, - LTC_SSHDATA_MPINT, r, - LTC_SSHDATA_MPINT, s, - LTC_SSHDATA_EOL, LTC_NULL); -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc7518.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc7518.c deleted file mode 100644 index 1faefca..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sign_hash_rfc7518.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** - Sign a message digest (RFC7518 format + recovery_id) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param recid [out] Recovery ID - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash_rfc7518_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, - int *recid, const ecc_key *key) -{ - int err; - void *r, *s; - unsigned long pbytes, i; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* RFC7518 format - raw (r,s) */ - pbytes = ltc_mp_unsigned_bin_size(key->dp.order); - if (*outlen < 2 * pbytes) { - *outlen = 2 * pbytes; - return CRYPT_BUFFER_OVERFLOW; - } - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, recid, key)) != CRYPT_OK) goto error; - - zeromem(out, 2 * pbytes); - *outlen = 2 * pbytes; - i = ltc_mp_unsigned_bin_size(r); - if ((err = ltc_mp_to_unsigned_bin(r, out + pbytes - i)) != CRYPT_OK) goto error; - i = ltc_mp_unsigned_bin_size(s); - err = ltc_mp_to_unsigned_bin(s, out + 2 * pbytes - i); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -/** - Sign a message digest (RFC7518 format) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) -{ - return ecc_sign_hash_rfc7518_ex(in, inlen, out, outlen, prng, wprng, NULL, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sizes.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sizes.c deleted file mode 100644 index 0b66304..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_sizes.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file ecc_sizes.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -void ecc_sizes(int *low, int *high) -{ - int i, size; - void *prime; - - LTC_ARGCHKVD(low != NULL); - LTC_ARGCHKVD(high != NULL); - - *low = INT_MAX; - *high = 0; - - if (ltc_mp_init(&prime) == CRYPT_OK) { - for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { - if (ltc_mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) { - size = ltc_mp_unsigned_bin_size(prime); - if (size < *low) *low = size; - if (size > *high) *high = size; - } - } - ltc_mp_clear(prime); - } -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c deleted file mode 100644 index f10a2c6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_ssh_ecdsa_encode_name.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ecc_ssh_ecdsa_encode_name.c - Curve/OID to SSH+ECDSA name string mapping per RFC5656 - Russ Williams -*/ - -#ifdef LTC_SSH - -/** - Curve/OID to SSH+ECDSA name string mapping - @param buffer [out] The destination for the name - @param buflen [in/out] The max size and resulting size (including terminator) of the name - @param key A public or private ECC key - @return CRYPT_OK if successful -*/ -int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key) -{ - char oidstr[LTC_OID_MAX_STRLEN] = {0}; - unsigned long oidlen = sizeof(oidstr); - int err, size = 0; - - LTC_ARGCHK(buffer != NULL); - LTC_ARGCHK(buflen != NULL); - LTC_ARGCHK(key != NULL); - - /* Get the OID of the curve */ - if ((err = ecc_get_oid_str(oidstr, &oidlen, key)) != CRYPT_OK) goto error; - - /* Check for three named curves: nistp256, nistp384, nistp521 */ - if (XSTRCMP("1.2.840.10045.3.1.7", oidstr) == 0) { - /* nistp256 - secp256r1 - OID 1.2.840.10045.3.1.7 */ - size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp256"); - } - else if (XSTRCMP("1.3.132.0.34", oidstr) == 0) { - /* nistp384 - secp384r1 - OID 1.3.132.0.34 */ - size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp384"); - } - else if (XSTRCMP("1.3.132.0.35", oidstr) == 0) { - /* nistp521 - secp521r1 - OID 1.3.132.0.35 */ - size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp521"); - } else { - /* Otherwise we use the OID... */ - size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr); - } - - /* snprintf returns a negative value on error - * or the size that would have been written, but limits to buflen-1 chars plus terminator */ - if (size < 0) { - err = CRYPT_ERROR; - } else if ((unsigned)size >= *buflen) { - err = CRYPT_BUFFER_OVERFLOW; - } else { - err = CRYPT_OK; - } - *buflen = size + 1; /* the string length + NUL byte */ - -error: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash.c deleted file mode 100644 index 494c474..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash.c +++ /dev/null @@ -1,47 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - @file ecc_verify_hash.c - ECC Crypto, Tom St Denis -*/ - -/** - Verify an ECC signature (ANSI X9.62 format) - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat [out] Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) -{ - void *r, *s; - int err; - - LTC_ARGCHK(sig != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; - - /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ - if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } - - err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_eth27.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_eth27.c deleted file mode 100644 index 587ecd2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_eth27.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** - @file ecc_verify_hash.c - ECC Crypto, Tom St Denis -*/ - -/** - Verify an ECC signature (Ethereum format with recovery_id+27) - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat [out] Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash_eth27(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) -{ - void *r, *s; - int err; - - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(key != NULL); - - /* Only valid for secp256k1 - OID 1.3.132.0.10 */ - if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { - return CRYPT_ERROR; - } - /* Only secp256k1 curves uses this format, so must be 65 bytes long */ - if (siglen != 65) { - return CRYPT_INVALID_PACKET; - } - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ltc_mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) goto error; - if ((err = ltc_mp_read_unsigned_bin(s, (unsigned char *)sig + 32, 32)) != CRYPT_OK) goto error; - - err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_internal.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_internal.c deleted file mode 100644 index ae66611..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_internal.c +++ /dev/null @@ -1,137 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -int ecc_verify_hash_internal(void *r, void *s, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) -{ - ecc_point *mG = NULL, *mQ = NULL; - void *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; - void *mu = NULL, *ma = NULL; - void *mp = NULL; - int err; - unsigned long pbits, pbytes, i, shift_right; - unsigned char ch, buf[MAXBLOCKSIZE]; - - LTC_ARGCHK(r != NULL); - LTC_ARGCHK(s != NULL); - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - - /* default to invalid signature */ - *stat = 0; - - /* allocate ints */ - if ((err = ltc_mp_init_multi(&v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) { - return err; - } - - p = key->dp.order; - m = key->dp.prime; - a = key->dp.A; - if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { - goto error; - } - - /* allocate points */ - mG = ltc_ecc_new_point(); - mQ = ltc_ecc_new_point(); - if (mQ == NULL || mG == NULL) { - err = CRYPT_MEM; - goto error; - } - - /* check for zero */ - if (ltc_mp_cmp_d(r, 0) != LTC_MP_GT || ltc_mp_cmp_d(s, 0) != LTC_MP_GT || - ltc_mp_cmp(r, p) != LTC_MP_LT || ltc_mp_cmp(s, p) != LTC_MP_LT) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* read hash - truncate if needed */ - pbits = ltc_mp_count_bits(p); - pbytes = (pbits+7) >> 3; - if (pbits > hashlen*8) { - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } - } - else if (pbits % 8 == 0) { - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } - } - else { - if (pbytes >= MAXBLOCKSIZE) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - shift_right = 8 - pbits % 8; - for (i=0, ch=0; i> shift_right); - } - if ((err = ltc_mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } - } - - /* w = s^-1 mod n */ - if ((err = ltc_mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } - - /* u1 = ew */ - if ((err = ltc_mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } - - /* u2 = rw */ - if ((err = ltc_mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } - - /* find mG and mQ */ - if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } - if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } - - /* find the montgomery mp */ - if ((err = ltc_mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } - - /* for curves with a == -3 keep ma == NULL */ - if (ltc_mp_cmp(a_plus3, m) != LTC_MP_EQ) { - if ((err = ltc_mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } - } - - /* compute u1*mG + u2*mQ = mG */ - if (ltc_mp.ecc_mul2add == NULL) { - if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } - - /* add them */ - if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; } - - /* reduce */ - if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } - } else { - /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ - if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } - } - - /* v = X_x1 mod n */ - if ((err = ltc_mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } - - /* does v == r */ - if (ltc_mp_cmp(v, r) == LTC_MP_EQ) { - *stat = 1; - } - - /* clear up and return */ - err = CRYPT_OK; -error: - if (mG != NULL) ltc_ecc_del_point(mG); - if (mQ != NULL) ltc_ecc_del_point(mQ); - if (mu != NULL) ltc_mp_clear(mu); - if (ma != NULL) ltc_mp_clear(ma); - ltc_mp_deinit_multi(v, w, u1, u2, e, a_plus3, LTC_NULL); - if (mp != NULL) ltc_mp_montgomery_free(mp); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc5656.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc5656.c deleted file mode 100644 index 027e4a7..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc5656.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#if defined(LTC_MECC) && defined(LTC_SSH) - -/** - @file ecc_verify_hash.c - ECC Crypto, Tom St Denis -*/ - -/** - Verify an ECC signature (RFC5656 / SSH format) - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat [out] Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash_rfc5656(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) -{ - void *r, *s; - int err; - char name[64], name2[64]; - unsigned long namelen = sizeof(name); - unsigned long name2len = sizeof(name2); - unsigned long slen = siglen; - - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - - /* Decode as SSH data sequence, per RFC4251 */ - if ((err = ssh_decode_sequence_multi(sig, &slen, - LTC_SSHDATA_STRING, name, &namelen, - LTC_SSHDATA_MPINT, r, - LTC_SSHDATA_MPINT, s, - LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) goto error; - - if (slen != siglen) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) goto error; - if (XSTRCMP(name,name2) != 0) { - err = CRYPT_INVALID_ARG; - goto error; - } - - err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc7518.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc7518.c deleted file mode 100644 index b048bdc..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_verify_hash_rfc7518.c +++ /dev/null @@ -1,52 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** - @file ecc_verify_hash.c - ECC Crypto, Tom St Denis -*/ - -/** - Verify an ECC signature (RFC7518 format) - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat [out] Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) -{ - void *r, *s; - int err; - unsigned long i; - - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - - /* RFC7518 format - raw (r,s) */ - i = ltc_mp_unsigned_bin_size(key->dp.order); - if (siglen != (2 * i)) { - err = CRYPT_INVALID_PACKET; - goto error; - } - if ((err = ltc_mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) goto error; - if ((err = ltc_mp_read_unsigned_bin(s, (unsigned char *)sig + i, i)) != CRYPT_OK) goto error; - - err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_export_point.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_export_point.c deleted file mode 100644 index 1586633..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_export_point.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed) -{ - int err; - unsigned char buf[ECC_BUF_SIZE]; - unsigned long xsize, ysize; - - if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; - if ((xsize = ltc_mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW; - if ((ysize = ltc_mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW; - - if(compressed) { - if (*outlen < (1 + size)) { - *outlen = 1 + size; - return CRYPT_BUFFER_OVERFLOW; - } - /* store first byte */ - out[0] = ltc_mp_isodd(y) ? 0x03 : 0x02; - /* pad and store x */ - zeromem(buf, sizeof(buf)); - if ((err = ltc_mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; - XMEMCPY(out+1, buf, size); - /* adjust outlen */ - *outlen = 1 + size; - } - else { - if (*outlen < (1 + 2*size)) { - *outlen = 1 + 2*size; - return CRYPT_BUFFER_OVERFLOW; - } - /* store byte 0x04 */ - out[0] = 0x04; - /* pad and store x */ - zeromem(buf, sizeof(buf)); - if ((err = ltc_mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; - XMEMCPY(out+1, buf, size); - /* pad and store y */ - zeromem(buf, sizeof(buf)); - if ((err = ltc_mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err; - XMEMCPY(out+1+size, buf, size); - /* adjust outlen */ - *outlen = 1 + 2*size; - } - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_import_point.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_import_point.c deleted file mode 100644 index d16301f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_import_point.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y) -{ - int err; - unsigned long size; - void *t1, *t2; - - /* init key + temporary numbers */ - if (ltc_mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) { - return CRYPT_MEM; - } - - size = ltc_mp_unsigned_bin_size(prime); - - if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { - /* read uncompressed point */ - /* load x */ - if ((err = ltc_mp_read_unsigned_bin(x, in+1, size)) != CRYPT_OK) { goto cleanup; } - /* load y */ - if ((err = ltc_mp_read_unsigned_bin(y, in+1+size, size)) != CRYPT_OK) { goto cleanup; } - } - else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) { - /* read compressed point - BEWARE: requires sqrtmod_prime */ - /* load x */ - if ((err = ltc_mp_read_unsigned_bin(x, in+1, size)) != CRYPT_OK) { goto cleanup; } - /* compute x^3 */ - if ((err = ltc_mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } - /* compute x^3 + a*x */ - if ((err = ltc_mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } - /* compute x^3 + a*x + b */ - if ((err = ltc_mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } - /* compute sqrt(x^3 + a*x + b) */ - if ((err = ltc_mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } - /* adjust y */ - if ((ltc_mp_isodd(t2) && in[0] == 0x03) || (!ltc_mp_isodd(t2) && in[0] == 0x02)) { - if ((err = ltc_mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } - } - else { - if ((err = ltc_mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } - } - } - else { - err = CRYPT_INVALID_PACKET; - goto cleanup; - } - - err = CRYPT_OK; -cleanup: - ltc_mp_deinit_multi(t1, t2, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point.c deleted file mode 100644 index 9b55814..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point.c +++ /dev/null @@ -1,62 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/** Returns whether [x,y] is a point on curve defined by dp - @param dp curve parameters - @param x x point coordinate - @param y y point coordinate - @return CRYPT_OK if valid -*/ - -int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) -{ - void *prime, *a, *b, *t1, *t2; - int err; - - prime = dp->prime; - b = dp->B; - a = dp->A; - - if ((err = ltc_mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err; - - /* compute y^2 */ - if ((err = ltc_mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; - - /* compute x^3 */ - if ((err = ltc_mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; - if ((err = ltc_mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; - if ((err = ltc_mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; - - /* compute y^2 - x^3 */ - if ((err = ltc_mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; - - /* compute y^2 - x^3 - a*x */ - if ((err = ltc_mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; - if ((err = ltc_mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; - if ((err = ltc_mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; - - /* adjust range (0, prime) */ - while (ltc_mp_cmp_d(t1, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; - } - while (ltc_mp_cmp(t1, prime) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; - } - - /* compare to b */ - if (ltc_mp_cmp(t1, b) != LTC_MP_EQ) { - err = CRYPT_INVALID_PACKET; - } else { - err = CRYPT_OK; - } - -cleanup: - ltc_mp_deinit_multi(t1, t2, LTC_NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c deleted file mode 100644 index 1a4f796..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_is_point_at_infinity.c +++ /dev/null @@ -1,53 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_MECC - -/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates - * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0) - */ - -int ltc_ecc_is_point_at_infinity(const ecc_point *P, const void *modulus, int *retval) -{ - int err; - void *x3, *y2; - - /* trivial case */ - if (!ltc_mp_iszero(P->z)) { - *retval = 0; - return CRYPT_OK; - } - - /* point (0,0,0) is not at infinity */ - if (ltc_mp_iszero(P->x) && ltc_mp_iszero(P->y)) { - *retval = 0; - return CRYPT_OK; - } - - /* initialize */ - if ((err = ltc_mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done; - - /* compute y^2 */ - if ((err = ltc_mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup; - - /* compute x^3 */ - if ((err = ltc_mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup; - if ((err = ltc_mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup; - - /* test y^2 == x^3 */ - err = CRYPT_OK; - if ((ltc_mp_cmp(x3, y2) == LTC_MP_EQ) && !ltc_mp_iszero(y2)) { - *retval = 1; - } else { - *retval = 0; - } - -cleanup: - ltc_mp_deinit_multi(x3, y2, LTC_NULL); -done: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_map.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_map.c deleted file mode 100644 index 228978d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_map.c +++ /dev/null @@ -1,63 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_map.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Map a projective jacbobian point back to affine space - @param P [in/out] The point to map - @param modulus The modulus of the field the ECC curve is in - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success -*/ -int ltc_ecc_map(ecc_point *P, const void *modulus, void *mp) -{ - void *t1, *t2; - int err; - - LTC_ARGCHK(P != NULL); - LTC_ARGCHK(modulus != NULL); - LTC_ARGCHK(mp != NULL); - - if (ltc_mp_iszero(P->z)) { - return ltc_ecc_set_point_xyz(0, 0, 1, P); - } - - if ((err = ltc_mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { - return err; - } - - /* first map z back to normal */ - if ((err = ltc_mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; } - - /* get 1/z */ - if ((err = ltc_mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } - - /* get 1/z^2 and 1/z^3 */ - if ((err = ltc_mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; } - - /* multiply against x/y */ - if ((err = ltc_mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_set(P->z, 1)) != CRYPT_OK) { goto done; } - - err = CRYPT_OK; -done: - ltc_mp_deinit_multi(t1, t2, LTC_NULL); - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c deleted file mode 100644 index 05985c2..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mul2add.c +++ /dev/null @@ -1,198 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file ltc_ecc_mul2add.c - ECC Crypto, Shamir's Trick, Tom St Denis -*/ - -#ifdef LTC_MECC - -#ifdef LTC_ECC_SHAMIR - -/** Computes kA*A + kB*B = C using Shamir's Trick - @param A First point to multiply - @param kA What to multiple A by - @param B Second point to multiply - @param kB What to multiple B by - @param C [out] Destination point (can overlap with A or B) - @param ma ECC curve parameter a in montgomery form - @param modulus Modulus for curve - @return CRYPT_OK on success -*/ -int ltc_ecc_mul2add(const ecc_point *A, void *kA, - const ecc_point *B, void *kB, - ecc_point *C, - const void *ma, - const void *modulus) -{ - ecc_point *precomp[16]; - unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; - unsigned x, y; - unsigned char *tA, *tB; - int err, first; - void *mp, *mu; - - /* argchks */ - LTC_ARGCHK(A != NULL); - LTC_ARGCHK(B != NULL); - LTC_ARGCHK(C != NULL); - LTC_ARGCHK(kA != NULL); - LTC_ARGCHK(kB != NULL); - LTC_ARGCHK(modulus != NULL); - - /* allocate memory */ - tA = XCALLOC(1, ECC_BUF_SIZE); - if (tA == NULL) { - return CRYPT_MEM; - } - tB = XCALLOC(1, ECC_BUF_SIZE); - if (tB == NULL) { - XFREE(tA); - return CRYPT_MEM; - } - - /* get sizes */ - lenA = ltc_mp_unsigned_bin_size(kA); - lenB = ltc_mp_unsigned_bin_size(kB); - len = MAX(lenA, lenB); - - /* sanity check */ - if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) { - err = CRYPT_INVALID_ARG; - goto ERR_T; - } - - /* extract and justify kA */ - ltc_mp_to_unsigned_bin(kA, (len - lenA) + tA); - - /* extract and justify kB */ - ltc_mp_to_unsigned_bin(kB, (len - lenB) + tB); - - /* allocate the table */ - for (x = 0; x < 16; x++) { - precomp[x] = ltc_ecc_new_point(); - if (precomp[x] == NULL) { - for (y = 0; y < x; ++y) { - ltc_ecc_del_point(precomp[y]); - } - err = CRYPT_MEM; - goto ERR_T; - } - } - - /* init montgomery reduction */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { - goto ERR_P; - } - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto ERR_MP; - } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { - goto ERR_MU; - } - - /* copy ones ... */ - if ((err = ltc_mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; } - - if ((err = ltc_mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; } - - /* precomp [i,0](A + B) table */ - if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - - /* precomp [0,i](A + B) table */ - if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - - /* precomp [i,j](A + B) table (i != 0, j != 0) */ - for (x = 1; x < 4; x++) { - for (y = 1; y < 4; y++) { - if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - } - } - - nibble = 3; - first = 1; - bitbufA = tA[0]; - bitbufB = tB[0]; - - /* for every byte of the multiplicands */ - for (x = 0;; ) { - /* grab a nibble */ - if (++nibble == 4) { - if (x == len) break; - bitbufA = tA[x]; - bitbufB = tB[x]; - nibble = 0; - ++x; - } - - /* extract two bits from both, shift/update */ - nA = (bitbufA >> 6) & 0x03; - nB = (bitbufB >> 6) & 0x03; - bitbufA = (bitbufA << 2) & 0xFF; - bitbufB = (bitbufB << 2) & 0xFF; - - /* if both zero, if first, continue */ - if ((nA == 0) && (nB == 0) && (first == 1)) { - continue; - } - - /* double twice, only if this isn't the first */ - if (first == 0) { - /* double twice */ - if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - } - - /* if not both zero */ - if ((nA != 0) || (nB != 0)) { - if (first == 1) { - /* if first, copy from table */ - first = 0; - if ((err = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; } - } else { - /* if not first, add from table */ - if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } - } - } - } - - /* reduce to affine */ - err = ltc_ecc_map(C, modulus, mp); - - /* clean up */ -ERR_MU: - ltc_mp_clear(mu); -ERR_MP: - ltc_mp_montgomery_free(mp); -ERR_P: - for (x = 0; x < 16; x++) { - ltc_ecc_del_point(precomp[x]); - } -ERR_T: -#ifdef LTC_CLEAN_STACK - zeromem(tA, ECC_BUF_SIZE); - zeromem(tB, ECC_BUF_SIZE); -#endif - XFREE(tA); - XFREE(tB); - - return err; -} - -#endif -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c deleted file mode 100644 index 73e7556..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod.c +++ /dev/null @@ -1,205 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_mulmod.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC -#ifndef LTC_ECC_TIMING_RESISTANT - -/* size of sliding window, don't change this! */ -#define WINSIZE 4 - -/** - Perform a point multiplication - @param k The scalar to multiply by - @param G The base point - @param R [out] Destination for kG - @param a ECC curve parameter a - @param modulus The modulus of the field the ECC curve is in - @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) - @return CRYPT_OK on success -*/ -int ltc_ecc_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *a, const void *modulus, int map) -{ - ecc_point *tG, *M[8]; - int i, j, err, inf; - void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; - ltc_mp_digit buf; - int first, bitbuf, bitcpy, bitcnt, mode, digidx; - - LTC_ARGCHK(k != NULL); - LTC_ARGCHK(G != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - - if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* return the point at infinity */ - return ltc_ecc_set_point_xyz(1, 1, 0, R); - } - - /* init montgomery reduction */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } - - /* for curves with a == -3 keep ma == NULL */ - if ((err = ltc_mp_init(&a_plus3)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } - if (ltc_mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { - if ((err = ltc_mp_init(&ma)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } - } - - /* alloc ram for window temps */ - for (i = 0; i < 8; i++) { - M[i] = ltc_ecc_new_point(); - if (M[i] == NULL) { - for (j = 0; j < i; j++) { - ltc_ecc_del_point(M[j]); - } - err = CRYPT_MEM; - goto error; - } - } - - /* make a copy of G incase R==G */ - tG = ltc_ecc_new_point(); - if (tG == NULL) { err = CRYPT_MEM; goto done; } - - /* tG = G and convert to montgomery */ - if (ltc_mp_cmp_d(mu, 1) == LTC_MP_EQ) { - if ((err = ltc_ecc_copy_point(G, tG)) != CRYPT_OK) { goto done; } - } else { - if ((err = ltc_mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } - } - ltc_mp_clear(mu); - mu = NULL; - - /* calc the M tab, which holds kG for k==8..15 */ - /* M[0] == 8G */ - if ((err = ltc_mp.ecc_ptdbl(tG, M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } - - /* now find (8+k)G for k=1..7 */ - for (j = 9; j < 16; j++) { - if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - - /* setup sliding window */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = ltc_mp_get_digit_count(k) - 1; - bitcpy = bitbuf = 0; - first = 1; - - /* perform ops */ - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - if (digidx == -1) { - break; - } - buf = ltc_mp_get_digit(k, digidx); - bitcnt = (int) ltc_mp.bits_per_digit; - --digidx; - } - - /* grab the next msb from the ltiplicand */ - i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1; - buf <<= 1; - - /* skip leading zero bits */ - if (mode == 0 && i == 0) { - continue; - } - - /* if the bit is zero and mode == 1 then we double */ - if (mode == 1 && i == 0) { - if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } - continue; - } - - /* else we add it to the window */ - bitbuf |= (i << (WINSIZE - ++bitcpy)); - mode = 2; - - if (bitcpy == WINSIZE) { - /* if this is the first window we do a simple copy */ - if (first == 1) { - /* R = kG [k = first window] */ - if ((err = ltc_ecc_copy_point(M[bitbuf-8], R)) != CRYPT_OK) { goto done; } - first = 0; - } else { - /* normal window */ - /* ok window is filled so double as required and add */ - /* double first */ - for (j = 0; j < WINSIZE; j++) { - if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - - /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ - if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - /* empty window and reset */ - bitcpy = bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then double/add */ - if (mode == 2 && bitcpy > 0) { - /* double then add */ - for (j = 0; j < bitcpy; j++) { - /* only double if we have had at least one add first */ - if (first == 0) { - if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - - bitbuf <<= 1; - if ((bitbuf & (1 << WINSIZE)) != 0) { - if (first == 1){ - /* first add, so copy */ - if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; } - first = 0; - } else { - /* then add */ - if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - } - } - } - - /* map R back from projective space */ - if (map) { - err = ltc_ecc_map(R, modulus, mp); - } else { - err = CRYPT_OK; - } -done: - ltc_ecc_del_point(tG); - for (i = 0; i < 8; i++) { - ltc_ecc_del_point(M[i]); - } -error: - if (ma != NULL) ltc_mp_clear(ma); - if (a_plus3 != NULL) ltc_mp_clear(a_plus3); - if (mu != NULL) ltc_mp_clear(mu); - if (mp != NULL) ltc_mp_montgomery_free(mp); - return err; -} - -#endif - -#undef WINSIZE - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c deleted file mode 100644 index 04456af..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_mulmod_timing.c +++ /dev/null @@ -1,151 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_mulmod_timing.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -#ifdef LTC_ECC_TIMING_RESISTANT - -/** - Perform a point multiplication (timing resistant) - @param k The scalar to multiply by - @param G The base point - @param R [out] Destination for kG - @param a ECC curve parameter a - @param modulus The modulus of the field the ECC curve is in - @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) - @return CRYPT_OK on success -*/ -int ltc_ecc_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *a, const void *modulus, int map) -{ - ecc_point *tG, *M[3]; - int i, j, err, inf; - void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; - ltc_mp_digit buf; - int bitcnt, mode, digidx; - - LTC_ARGCHK(k != NULL); - LTC_ARGCHK(G != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - - if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* return the point at infinity */ - return ltc_ecc_set_point_xyz(1, 1, 0, R); - } - - /* init montgomery reduction */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } - - /* for curves with a == -3 keep ma == NULL */ - if ((err = ltc_mp_init(&a_plus3)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } - if (ltc_mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { - if ((err = ltc_mp_init(&ma)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } - } - - /* alloc ram for window temps */ - for (i = 0; i < 3; i++) { - M[i] = ltc_ecc_new_point(); - if (M[i] == NULL) { - for (j = 0; j < i; j++) { - ltc_ecc_del_point(M[j]); - } - ltc_mp_clear(mu); - ltc_mp_montgomery_free(mp); - return CRYPT_MEM; - } - } - - /* make a copy of G incase R==G */ - tG = ltc_ecc_new_point(); - if (tG == NULL) { err = CRYPT_MEM; goto done; } - - /* tG = G and convert to montgomery */ - if ((err = ltc_mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } - ltc_mp_clear(mu); - mu = NULL; - - /* calc the M tab */ - /* M[0] == G */ - if ((err = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; } - /* M[1] == 2G */ - if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; } - - /* setup sliding window */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = ltc_mp_get_digit_count(k) - 1; - - /* perform ops */ - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - if (digidx == -1) { - break; - } - buf = ltc_mp_get_digit(k, digidx); - bitcnt = (int) LTC_MP_DIGIT_BIT; - --digidx; - } - - /* grab the next msb from the ltiplicand */ - i = (int)((buf >> (LTC_MP_DIGIT_BIT - 1)) & 1); - buf <<= 1; - - if (mode == 0 && i == 0) { - /* dummy operations */ - if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } - continue; - } - - if (mode == 0 && i == 1) { - mode = 1; - /* dummy operations */ - if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } - continue; - } - - if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; } - } - - /* copy result out */ - if ((err = ltc_ecc_copy_point(M[0], R)) != CRYPT_OK) { goto done; } - - /* map R back from projective space */ - if (map) { - err = ltc_ecc_map(R, modulus, mp); - } else { - err = CRYPT_OK; - } -done: - ltc_ecc_del_point(tG); - for (i = 0; i < 3; i++) { - ltc_ecc_del_point(M[i]); - } -error: - if (ma != NULL) ltc_mp_clear(ma); - if (a_plus3 != NULL) ltc_mp_clear(a_plus3); - if (mu != NULL) ltc_mp_clear(mu); - if (mp != NULL) ltc_mp_montgomery_free(mp); - return err; -} - -#endif -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_points.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_points.c deleted file mode 100644 index 79adb55..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_points.c +++ /dev/null @@ -1,61 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_points.c - ECC Crypto, Tom St Denis -*/ - -#ifdef LTC_MECC - -/** - Allocate a new ECC point - @return A newly allocated point or NULL on error -*/ -ecc_point *ltc_ecc_new_point(void) -{ - ecc_point *p; - p = XCALLOC(1, sizeof(*p)); - if (p == NULL) { - return NULL; - } - if (ltc_mp_init_multi(&p->x, &p->y, &p->z, LTC_NULL) != CRYPT_OK) { - XFREE(p); - return NULL; - } - return p; -} - -/** Free an ECC point from memory - @param p The point to free -*/ -void ltc_ecc_del_point(ecc_point *p) -{ - /* prevents free'ing null arguments */ - if (p != NULL) { - ltc_mp_deinit_multi(p->x, p->y, p->z, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */ - XFREE(p); - } -} - -int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p) -{ - int err; - if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err; - if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err; - if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst) -{ - int err; - if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err; - if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err; - if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c deleted file mode 100644 index 1e03dd9..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_add_point.c +++ /dev/null @@ -1,199 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file ltc_ecc_projective_add_point.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) - -/** - Add two ECC points - @param P The point to add - @param Q The point to add - @param R [out] The destination of the double - @param ma ECC curve parameter a in montgomery form - @param modulus The modulus of the field the ECC curve is in - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success -*/ -int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, - const void *ma, const void *modulus, void *mp) -{ - void *t1, *t2, *x, *y, *z; - int err, inf; - - LTC_ARGCHK(P != NULL); - LTC_ARGCHK(Q != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - LTC_ARGCHK(mp != NULL); - - if ((err = ltc_mp_init_multi(&t1, &t2, &x, &y, &z, LTC_NULL)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* P is point at infinity >> Result = Q */ - err = ltc_ecc_copy_point(Q, R); - goto done; - } - - if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* Q is point at infinity >> Result = P */ - err = ltc_ecc_copy_point(P, R); - goto done; - } - - if ((ltc_mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (ltc_mp_cmp(P->z, Q->z) == LTC_MP_EQ)) { - if (ltc_mp_cmp(P->y, Q->y) == LTC_MP_EQ) { - /* here P = Q >> Result = 2 * P (use doubling) */ - ltc_mp_deinit_multi(t1, t2, x, y, z, LTC_NULL); - return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp); - } - if ((err = ltc_mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(P->y, t1) == LTC_MP_EQ) { - /* here Q = -P >>> Result = the point at infinity */ - err = ltc_ecc_set_point_xyz(1, 1, 0, R); - goto done; - } - } - - if ((err = ltc_mp_copy(P->x, x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_copy(P->y, y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_copy(P->z, z)) != CRYPT_OK) { goto done; } - - /* if Z is one then these are no-operations */ - if (Q->z != NULL) { - /* T1 = Z' * Z' */ - if ((err = ltc_mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* X = X * T1 */ - if ((err = ltc_mp_mul(t1, x, x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = Z' * T1 */ - if ((err = ltc_mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* Y = Y * T1 */ - if ((err = ltc_mp_mul(t1, y, y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; } - } - - /* T1 = Z*Z */ - if ((err = ltc_mp_sqr(z, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* T2 = X' * T1 */ - if ((err = ltc_mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = Z * T1 */ - if ((err = ltc_mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = Y' * T1 */ - if ((err = ltc_mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - - /* Y = Y - T1 */ - if ((err = ltc_mp_sub(y, t1, y)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(y, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } - } - /* T1 = 2T1 */ - if ((err = ltc_mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* T1 = Y + T1 */ - if ((err = ltc_mp_add(t1, y, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* X = X - T2 */ - if ((err = ltc_mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(x, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } - } - /* T2 = 2T2 */ - if ((err = ltc_mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t2, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - /* T2 = X + T2 */ - if ((err = ltc_mp_add(t2, x, t2)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t2, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - - /* if Z' != 1 */ - if (Q->z != NULL) { - /* Z = Z * Z' */ - if ((err = ltc_mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } - } - - /* Z = Z * X */ - if ((err = ltc_mp_mul(z, x, z)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } - - /* T1 = T1 * X */ - if ((err = ltc_mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* X = X * X */ - if ((err = ltc_mp_sqr(x, x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } - /* T2 = T2 * x */ - if ((err = ltc_mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = T1 * X */ - if ((err = ltc_mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - - /* X = Y*Y */ - if ((err = ltc_mp_sqr(y, x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } - /* X = X - T2 */ - if ((err = ltc_mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(x, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } - } - - /* T2 = T2 - X */ - if ((err = ltc_mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(t2, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - /* T2 = T2 - X */ - if ((err = ltc_mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(t2, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - /* T2 = T2 * Y */ - if ((err = ltc_mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* Y = T2 - T1 */ - if ((err = ltc_mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(y, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } - } - /* Y = Y/2 */ - if (ltc_mp_isodd(y)) { - if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } - } - if ((err = ltc_mp_div_2(y, y)) != CRYPT_OK) { goto done; } - - if ((err = ltc_mp_copy(x, R->x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_copy(y, R->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_copy(z, R->z)) != CRYPT_OK) { goto done; } - - err = CRYPT_OK; -done: - ltc_mp_deinit_multi(t1, t2, x, y, z, LTC_NULL); - return err; -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c deleted file mode 100644 index 764bfd0..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_projective_dbl_point.c +++ /dev/null @@ -1,182 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/* ### Point doubling in Jacobian coordinate system ### - * - * let us have a curve: y^2 = x^3 + a*x + b - * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 - * - * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: - * Xr = M^2 - 2*S - * Yr = M * (S - Xr) - 8*T - * Zr = 2 * Yp * Zp - * - * M = 3 * Xp^2 + a*Zp^4 - * T = Yp^4 - * S = 4 * Xp * Yp^2 - * - * SPECIAL CASE: when a == -3 we can compute M as - * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) - */ - -/** - @file ltc_ecc_projective_dbl_point.c - ECC Crypto, Tom St Denis -*/ - -#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) - -/** - Double an ECC point - @param P The point to double - @param R [out] The destination of the double - @param ma ECC curve parameter a in montgomery form - @param modulus The modulus of the field the ECC curve is in - @param mp The "b" value from montgomery_setup() - @return CRYPT_OK on success -*/ -int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, const void *ma, const void *modulus, void *mp) -{ - void *t1, *t2; - int err, inf; - - LTC_ARGCHK(P != NULL); - LTC_ARGCHK(R != NULL); - LTC_ARGCHK(modulus != NULL); - LTC_ARGCHK(mp != NULL); - - if ((err = ltc_mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { - return err; - } - - if (P != R) { - if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; } - } - - if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; - if (inf) { - /* if P is point at infinity >> Result = point at infinity */ - err = ltc_ecc_set_point_xyz(1, 1, 0, R); - goto done; - } - - /* t1 = Z * Z */ - if ((err = ltc_mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* Z = Y * Z */ - if ((err = ltc_mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; } - /* Z = 2Z */ - if ((err = ltc_mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(R->z, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } - } - - if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ - /* T2 = X - T1 */ - if ((err = ltc_mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(t2, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - /* T1 = X + T1 */ - if ((err = ltc_mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* T2 = T1 * T2 */ - if ((err = ltc_mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = 2T2 */ - if ((err = ltc_mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* T1 = T1 + T2 */ - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - } - else { - /* T2 = T1 * T1 */ - if ((err = ltc_mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = T2 * a */ - if ((err = ltc_mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - /* T2 = X * X */ - if ((err = ltc_mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T1 = T2 + T1 */ - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* T1 = T2 + T1 */ - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - /* T1 = T2 + T1 */ - if ((err = ltc_mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(t1, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } - } - } - - /* Y = 2Y */ - if ((err = ltc_mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp(R->y, modulus) != LTC_MP_LT) { - if ((err = ltc_mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } - } - /* Y = Y * Y */ - if ((err = ltc_mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } - /* T2 = Y * Y */ - if ((err = ltc_mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } - /* T2 = T2/2 */ - if (ltc_mp_isodd(t2)) { - if ((err = ltc_mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } - if ((err = ltc_mp_div_2(t2, t2)) != CRYPT_OK) { goto done; } - /* Y = Y * X */ - if ((err = ltc_mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } - - /* X = T1 * T1 */ - if ((err = ltc_mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; } - /* X = X - Y */ - if ((err = ltc_mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(R->x, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } - } - /* X = X - Y */ - if ((err = ltc_mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(R->x, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } - } - - /* Y = Y - X */ - if ((err = ltc_mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(R->y, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } - } - /* Y = Y * T1 */ - if ((err = ltc_mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; } - if ((err = ltc_mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } - /* Y = Y - T2 */ - if ((err = ltc_mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; } - if (ltc_mp_cmp_d(R->y, 0) == LTC_MP_LT) { - if ((err = ltc_mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } - } - - err = CRYPT_OK; -done: - ltc_mp_deinit_multi(t2, t1, LTC_NULL); - return err; -} -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c b/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c deleted file mode 100644 index 7c83d6a..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ecc/ltc_ecc_verify_key.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/* origin of this code - OLPC */ - -#ifdef LTC_MECC - -/** - Verify a key according to ANSI spec - @param key The key to validate - @return CRYPT_OK if successful -*/ - -int ltc_ecc_verify_key(const ecc_key *key) -{ - int err, inf; - ecc_point *point; - void *prime = key->dp.prime; - void *order = key->dp.order; - void *a = key->dp.A; - - /* Test 1: Are the x and y points of the public key in the field? */ - if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) { - if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) || - (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) || - (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) || - (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) || - (ltc_mp_iszero(key->pubkey.x) && ltc_mp_iszero(key->pubkey.y)) - ) - { - err = CRYPT_INVALID_PACKET; - goto done2; - } - } - - /* Test 2: is the public key on the curve? */ - if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; } - - /* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */ - point = ltc_ecc_new_point(); - if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; } - - err = ltc_ecc_is_point_at_infinity(point, prime, &inf); - if (err != CRYPT_OK || inf) { - err = CRYPT_ERROR; - } - else { - err = CRYPT_OK; - } - -done1: - ltc_ecc_del_point(point); -done2: - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_export.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_export.c deleted file mode 100644 index 5ec68eb..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_export.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_export.c - Export an Ed25519 key to a binary packet, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Export an Ed25519 key to a binary packet - @param out [out] The destination for the key - @param outlen [in/out] The max size and resulting size of the Ed25519 key - @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) - @param key The key you wish to export - @return CRYPT_OK if successful -*/ -int ed25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key) -{ - LTC_ARGCHK(key != NULL); - - if (key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE; - - return ec25519_export(out, outlen, which, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import.c deleted file mode 100644 index 634780c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_import.c - Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Import an Ed25519 public key - @param in The packet to read - @param inlen The length of the input packet - @param key [out] Where to import the key to - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - int err; - unsigned long key_len; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - key_len = sizeof(key->pub); - if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { - key->type = PK_PUBLIC; - key->pka = LTC_PKA_ED25519; - } - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c deleted file mode 100644 index b1e6833..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_pkcs8.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_import_pkcs8.c - Import an Ed25519 key in PKCS#8 format, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -int ed25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - curve25519_key *key) -{ - return ec25519_import_pkcs8_asn1(alg_id, priv_key, LTC_OID_ED25519, key); -} - -/** - Import an Ed25519 private key in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - curve25519_key *key) -{ - return ec25519_import_pkcs8(in, inlen, pw_ctx, LTC_OID_ED25519, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_raw.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_raw.c deleted file mode 100644 index 6d47073..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_raw.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_import_raw.c - Set the parameters of an Ed25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Set the parameters of an Ed25519 key - - @param in The key - @param inlen The length of the key - @param which Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key [out] Destination of the key - @return CRYPT_OK if successful -*/ -int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) -{ - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - if (which == PK_PRIVATE) { - LTC_ARGCHK(inlen == 32uL || inlen == 64uL); - XMEMCPY(key->priv, in, sizeof(key->priv)); - if (inlen == 32) { - tweetnacl_crypto_sk_to_pk(key->pub, key->priv); - } else { - XMEMCPY(key->pub, in + 32, sizeof(key->pub)); - } - } else if (which == PK_PUBLIC) { - LTC_ARGCHK(inlen == 32uL); - XMEMCPY(key->pub, in, sizeof(key->pub)); - } else { - return CRYPT_INVALID_ARG; - } - key->pka = LTC_PKA_ED25519; - key->type = which; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_x509.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_x509.c deleted file mode 100644 index 306a0e1..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_import_x509.c +++ /dev/null @@ -1,45 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_import_x509.c - Import an Ed25519 key from a X.509 certificate, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -static int s_ed25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; - XMEMCPY(key->pub, in, sizeof(key->pub)); - return CRYPT_OK; -} - -/** - Import an Ed25519 public key from a X.509 certificate - @param in The DER encoded X.509 certificate - @param inlen The length of the certificate - @param key [out] Where to import the key to - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = x509_decode_public_key_from_certificate(in, inlen, - LTC_OID_ED25519, - LTC_ASN1_EOL, NULL, NULL, - (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) { - return err; - } - key->type = PK_PUBLIC; - key->pka = LTC_PKA_ED25519; - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_make_key.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_make_key.c deleted file mode 100644 index 289313b..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_make_key.c +++ /dev/null @@ -1,36 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_make_key.c - Create an Ed25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Create an Ed25519 key - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful -*/ -int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = tweetnacl_crypto_sign_keypair(prng, wprng, key->pub, key->priv)) != CRYPT_OK) { - return err; - } - - key->type = PK_PRIVATE; - key->pka = LTC_PKA_ED25519; - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_sign.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_sign.c deleted file mode 100644 index 33c2405..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_sign.c +++ /dev/null @@ -1,126 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_shared_secret.c - Create an Ed25519 signature, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const unsigned char *ctx, unsigned long ctxlen, - const curve25519_key *private_key) -{ - unsigned char *s; - unsigned long long smlen; - int err; - - LTC_ARGCHK(msg != NULL); - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(siglen != NULL); - LTC_ARGCHK(private_key != NULL); - - if (private_key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE; - if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; - - if (*siglen < 64uL) { - *siglen = 64uL; - return CRYPT_BUFFER_OVERFLOW; - } - - smlen = msglen + 64; - s = XMALLOC(smlen); - if (s == NULL) return CRYPT_MEM; - - err = tweetnacl_crypto_sign(s, &smlen, - msg, msglen, - private_key->priv, private_key->pub, - ctx, ctxlen); - - XMEMCPY(sig, s, 64uL); - *siglen = 64uL; - -#ifdef LTC_CLEAN_STACK - zeromem(s, smlen); -#endif - XFREE(s); - - return err; -} - -/** - Create an Ed25519ctx signature. - @param msg The data to be signed - @param msglen [in] The size of the date to be signed - @param sig [out] The destination of the shared data - @param siglen [in/out] The max size and resulting size of the shared data. - @param ctx [in] The context is a constant null terminated string - @param private_key The private Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const unsigned char *ctx, unsigned long ctxlen, - const curve25519_key *private_key) -{ - int err; - unsigned char ctx_prefix[292]; - unsigned long ctx_prefix_size = sizeof(ctx_prefix); - - LTC_ARGCHK(ctx != NULL); - - if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK) - return err; - - return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key); -} - -/** - Create an Ed25519ph signature. - @param msg The data to be signed - @param msglen [in] The size of the date to be signed - @param sig [out] The destination of the shared data - @param siglen [in/out] The max size and resulting size of the shared data. - @param ctx [in] The context is a constant null terminated string - @param private_key The private Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const unsigned char *ctx, unsigned long ctxlen, - const curve25519_key *private_key) -{ - int err; - unsigned char msg_hash[64]; - unsigned char ctx_prefix[292]; - unsigned long ctx_prefix_size = sizeof(ctx_prefix); - - if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) - return err; - - if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) - return err; - - return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key); -} - -/** - Create an Ed25519 signature. - @param msg The data to be signed - @param msglen [in] The size of the date to be signed - @param sig [out] The destination of the shared data - @param siglen [in/out] The max size and resulting size of the shared data. - @param private_key The private Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const curve25519_key *private_key) -{ - return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_verify.c b/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_verify.c deleted file mode 100644 index 7afab7c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/ed25519/ed25519_verify.c +++ /dev/null @@ -1,134 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file ed25519_verify.c - Verify an Ed25519 signature, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - const unsigned char *ctx, unsigned long ctxlen, - int *stat, - const curve25519_key *public_key) -{ - unsigned char* m; - unsigned long long mlen; - int err; - - LTC_ARGCHK(msg != NULL); - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(public_key != NULL); - - *stat = 0; - - if (siglen != 64uL) return CRYPT_INVALID_ARG; - if (public_key->pka != LTC_PKA_ED25519) return CRYPT_PK_INVALID_TYPE; - - mlen = msglen + siglen; - if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW; - - m = XMALLOC(mlen); - if (m == NULL) return CRYPT_MEM; - - XMEMCPY(m, sig, siglen); - XMEMCPY(m + siglen, msg, msglen); - - err = tweetnacl_crypto_sign_open(stat, - m, &mlen, - m, mlen, - ctx, ctxlen, - public_key->pub); - -#ifdef LTC_CLEAN_STACK - zeromem(m, msglen + siglen); -#endif - XFREE(m); - - return err; -} - -/** - Verify an Ed25519ctx signature. - @param msg [in] The data to be verified - @param msglen [in] The size of the data to be verified - @param sig [in] The signature to be verified - @param siglen [in] The size of the signature to be verified - @param ctx [in] The context - @param ctxlen [in] The size of the context - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param public_key [in] The public Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - const unsigned char *ctx, unsigned long ctxlen, - int *stat, - const curve25519_key *public_key) -{ - unsigned char ctx_prefix[292]; - unsigned long ctx_prefix_size = sizeof(ctx_prefix); - - LTC_ARGCHK(ctx != NULL); - - if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK) - return CRYPT_INVALID_ARG; - - return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); -} - -/** - Verify an Ed25519ph signature. - @param msg [in] The data to be verified - @param msglen [in] The size of the data to be verified - @param sig [in] The signature to be verified - @param siglen [in] The size of the signature to be verified - @param ctx [in] The context - @param ctxlen [in] The size of the context - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param public_key [in] The public Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - const unsigned char *ctx, unsigned long ctxlen, - int *stat, - const curve25519_key *public_key) -{ - int err; - unsigned char msg_hash[64]; - unsigned char ctx_prefix[292]; - unsigned long ctx_prefix_size = sizeof(ctx_prefix); - - if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) - return err; - - if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) - return err; - - return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); -} - -/** - Verify an Ed25519 signature. - @param msg [in] The data to be verified - @param msglen [in] The size of the data to be verified - @param sig [in] The signature to be verified - @param siglen [in] The size of the signature to be verified - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param public_key [in] The public Ed25519 key in the pair - @return CRYPT_OK if successful -*/ -int ed25519_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - int *stat, - const curve25519_key *public_key) -{ - return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/pka_key.c b/Sources/DataLiteC/libtomcrypt/pk/pka_key.c deleted file mode 100644 index d88ee3d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pka_key.c +++ /dev/null @@ -1,45 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -void pka_key_destroy(ltc_pka_key **key) -{ - LTC_ARGCHKVD(key != NULL); - - if (!*key) - return; - - pka_key_free(*key); - zeromem(*key, sizeof(**key)); - XFREE(*key); - *key = NULL; -} - -void pka_key_free(ltc_pka_key *key) -{ - LTC_ARGCHKVD(key != NULL); - switch (key->id) { - case LTC_PKA_DH: -#if defined(LTC_MDH) - dh_free(&key->u.dh); -#endif - break; - case LTC_PKA_DSA: -#if defined(LTC_MDSA) - dsa_free(&key->u.dsa); -#endif - break; - case LTC_PKA_RSA: -#if defined(LTC_MRSA) - rsa_free(&key->u.rsa); -#endif - break; - case LTC_PKA_EC: -#if defined(LTC_MECC) - ecc_free(&key->u.ecc); -#endif - break; - default: - break; - } -} diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c deleted file mode 100644 index 513b03f..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c +++ /dev/null @@ -1,39 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_i2osp.c - Integer to Octet I2OSP, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/* always stores the same # of bytes, pads with leading zero bytes - as required - */ - -/** - PKCS #1 Integer to binary - @param n The integer to store - @param modulus_len The length of the RSA modulus - @param out [out] The destination for the integer - @return CRYPT_OK if successful -*/ -int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) -{ - unsigned long size; - - size = ltc_mp_unsigned_bin_size(n); - - if (size > modulus_len) { - return CRYPT_BUFFER_OVERFLOW; - } - - /* store it */ - zeromem(out, modulus_len); - return ltc_mp_to_unsigned_bin(n, out+(modulus_len-size)); -} - -#endif /* LTC_PKCS_1 */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c deleted file mode 100644 index 7a68e72..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c +++ /dev/null @@ -1,96 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_mgf1.c - The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/** - Perform PKCS #1 MGF1 (internal) - @param hash_idx The index of the hash desired - @param seed The seed for MGF1 - @param seedlen The length of the seed - @param mask [out] The destination - @param masklen The length of the mask desired - @return CRYPT_OK if successful -*/ -int pkcs_1_mgf1(int hash_idx, - const unsigned char *seed, unsigned long seedlen, - unsigned char *mask, unsigned long masklen) -{ - unsigned long hLen, x; - ulong32 counter; - int err; - hash_state *md; - unsigned char *buf; - - LTC_ARGCHK(seed != NULL); - LTC_ARGCHK(mask != NULL); - - /* ensure valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* get hash output size */ - hLen = hash_descriptor[hash_idx].hashsize; - - /* allocate memory */ - md = XMALLOC(sizeof(hash_state)); - buf = XMALLOC(hLen); - if (md == NULL || buf == NULL) { - if (md != NULL) { - XFREE(md); - } - if (buf != NULL) { - XFREE(buf); - } - return CRYPT_MEM; - } - - /* start counter */ - counter = 0; - - while (masklen > 0) { - /* handle counter */ - STORE32H(counter, buf); - ++counter; - - /* get hash of seed || counter */ - if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* store it */ - for (x = 0; x < hLen && masklen > 0; x++, masklen--) { - *mask++ = buf[x]; - } - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(buf, hLen); - zeromem(md, sizeof(hash_state)); -#endif - - XFREE(buf); - XFREE(md); - - return err; -} - -#endif /* LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c deleted file mode 100644 index 14519c1..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c +++ /dev/null @@ -1,185 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_oaep_decode.c - OAEP Padding for PKCS #1, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/** - PKCS #1 v2.00 OAEP decode - @param msg The encoded data to decode - @param msglen The length of the encoded data (octets) - @param lparam The session or system data (can be NULL) - @param lparamlen The length of the lparam - @param modulus_bitlen The bit length of the RSA modulus - @param mgf_hash The hash algorithm used for the MGF - @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) - @param out [out] Destination of decoding - @param outlen [in/out] The max size and resulting size of the decoding - @param res [out] Result of decoding, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen, - int *res) -{ - unsigned char *DB, *seed, *mask; - unsigned long hLen, x, y, modulus_len; - int err, ret, lparam_hash_used; - - LTC_ARGCHK(msg != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(res != NULL); - - /* default to invalid packet */ - *res = 0; - - /* test valid hash */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - if (lparam_hash != -1) { - if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { - return err; - } - lparam_hash_used = lparam_hash; - } else { - lparam_hash_used = mgf_hash; - } - hLen = hash_descriptor[lparam_hash_used].hashsize; - modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); - - /* test hash/message size */ - if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { - return CRYPT_PK_INVALID_SIZE; - } - - /* allocate ram for DB/mask/salt of size modulus_len */ - DB = XMALLOC(modulus_len); - mask = XMALLOC(modulus_len); - seed = XMALLOC(hLen); - if (DB == NULL || mask == NULL || seed == NULL) { - if (DB != NULL) { - XFREE(DB); - } - if (mask != NULL) { - XFREE(mask); - } - if (seed != NULL) { - XFREE(seed); - } - return CRYPT_MEM; - } - - /* ok so it's now in the form - - 0x00 || maskedseed || maskedDB - - 1 || hLen || modulus_len - hLen - 1 - - */ - - ret = CRYPT_OK; - - /* must have leading 0x00 byte */ - if (msg[0] != 0x00) { - ret = CRYPT_INVALID_PACKET; - } - - /* now read the masked seed */ - x = 1; - XMEMCPY(seed, msg + x, hLen); - x += hLen; - - /* now read the masked DB */ - XMEMCPY(DB, msg + x, modulus_len - hLen - 1); - x += modulus_len - hLen - 1; - - /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* XOR against seed */ - for (y = 0; y < hLen; y++) { - seed[y] ^= mask[y]; - } - - /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* xor against DB */ - for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; - } - - /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ - - /* compute lhash and store it in seed [reuse temps!] */ - x = modulus_len; - if (lparam != NULL) { - if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - } else { - /* can't pass hash_memory a NULL so use DB with zero length */ - if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* compare the lhash'es */ - if (XMEM_NEQ(seed, DB, hLen) != 0) { - ret = CRYPT_INVALID_PACKET; - } - - /* now zeroes before a 0x01 */ - for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { - /* step... */ - } - - /* error if wasn't 0x01 */ - if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { - ret = CRYPT_INVALID_PACKET; - } - - /* rest is the message (and skip 0x01) */ - if ((modulus_len - hLen - 1 - ++x) > *outlen) { - ret = CRYPT_INVALID_PACKET; - } - - if (ret == CRYPT_OK) { - /* copy message */ - *outlen = modulus_len - hLen - 1 - x; - XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); - - /* valid packet */ - *res = 1; - } - err = ret; - -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(seed, hLen); - zeromem(mask, modulus_len); -#endif - - XFREE(seed); - XFREE(mask); - XFREE(DB); - - return err; -} - -#endif /* LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c deleted file mode 100644 index 45aa5ce..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c +++ /dev/null @@ -1,172 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_oaep_encode.c - OAEP Padding for PKCS #1, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/** - PKCS #1 v2.00 OAEP encode - @param msg The data to encode - @param msglen The length of the data to encode (octets) - @param lparam A session or system parameter (can be NULL) - @param lparamlen The length of the lparam data - @param modulus_bitlen The bit length of the RSA modulus - @param prng An active PRNG state - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param out [out] The destination for the encoded data - @param outlen [in/out] The max size and resulting size of the encoded data - @return CRYPT_OK if successful -*/ -int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, prng_state *prng, - int prng_idx, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen) -{ - unsigned char *DB, *seed, *mask; - unsigned long hLen, x, y, modulus_len; - int err, lparam_hash_used; - - LTC_ARGCHK((msglen == 0) || (msg != NULL)); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* test valid hash */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - if (lparam_hash != -1) { - if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { - return err; - } - lparam_hash_used = lparam_hash; - } else { - lparam_hash_used = mgf_hash; - } - - /* valid prng */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - - hLen = hash_descriptor[lparam_hash_used].hashsize; - modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); - - /* test message size */ - if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { - return CRYPT_PK_INVALID_SIZE; - } - - /* allocate ram for DB/mask/salt of size modulus_len */ - DB = XMALLOC(modulus_len); - mask = XMALLOC(modulus_len); - seed = XMALLOC(hLen); - if (DB == NULL || mask == NULL || seed == NULL) { - if (DB != NULL) { - XFREE(DB); - } - if (mask != NULL) { - XFREE(mask); - } - if (seed != NULL) { - XFREE(seed); - } - return CRYPT_MEM; - } - - /* get lhash */ - /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ - x = modulus_len; - if (lparam != NULL) { - if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - } else { - /* can't pass hash_memory a NULL so use `out` with zero length */ - if ((err = hash_memory(lparam_hash_used, out, 0, DB, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - } - - /* append PS then 0x01 (to lhash) */ - x = hLen; - y = modulus_len - msglen - 2*hLen - 2; - XMEMSET(DB+x, 0, y); - x += y; - - /* 0x01 byte */ - DB[x++] = 0x01; - - if (msglen != 0) { - /* message (length = msglen) */ - XMEMCPY(DB+x, msg, msglen); - x += msglen; - } - - /* now choose a random seed */ - if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { - err = CRYPT_ERROR_READPRNG; - goto LBL_ERR; - } - - /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* xor against DB */ - for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; - } - - /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* XOR against seed */ - for (y = 0; y < hLen; y++) { - seed[y] ^= mask[y]; - } - - /* create string of length modulus_len */ - if (*outlen < modulus_len) { - *outlen = modulus_len; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* start output which is 0x00 || maskedSeed || maskedDB */ - x = 0; - out[x++] = 0x00; - XMEMCPY(out+x, seed, hLen); - x += hLen; - XMEMCPY(out+x, DB, modulus_len - hLen - 1); - x += modulus_len - hLen - 1; - - *outlen = x; - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(seed, hLen); - zeromem(mask, modulus_len); -#endif - - XFREE(seed); - XFREE(mask); - XFREE(DB); - - return err; -} - -#endif /* LTC_PKCS_1 */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c deleted file mode 100644 index e009cc3..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c +++ /dev/null @@ -1,24 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_os2ip.c - Octet to Integer OS2IP, Tom St Denis -*/ -#ifdef LTC_PKCS_1 - -/** - Read a binary string into an mp_int - @param n [out] The mp_int destination - @param in The binary string to read - @param inlen The length of the binary string - @return CRYPT_OK if successful -*/ -int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) -{ - return ltc_mp_read_unsigned_bin(n, in, inlen); -} - -#endif /* LTC_PKCS_1 */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c deleted file mode 100644 index fad401d..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c +++ /dev/null @@ -1,166 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_pss_decode.c - PKCS #1 PSS Signature Padding, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/** - PKCS #1 v2.00 PSS decode - @param msghash The hash to verify - @param msghashlen The length of the hash (octets) - @param sig The signature data (encoded data) - @param siglen The length of the signature data (octets) - @param saltlen The length of the salt used (octets) - @param hash_idx The index of the hash desired - @param modulus_bitlen The bit length of the RSA modulus - @param res [out] The result of the comparison, 1==valid, 0==invalid - @return CRYPT_OK if successful (even if the comparison failed) -*/ -int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, - unsigned long modulus_bitlen, int *res) -{ - unsigned char *DB, *mask, *salt, *hash; - unsigned long x, y, hLen, modulus_len; - int err; - hash_state md; - - LTC_ARGCHK(msghash != NULL); - LTC_ARGCHK(res != NULL); - - /* default to invalid */ - *res = 0; - - /* ensure hash is valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - hLen = hash_descriptor[hash_idx].hashsize; - modulus_bitlen--; - modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); - - /* check sizes */ - if ((saltlen > modulus_len) || - (modulus_len < hLen + saltlen + 2)) { - return CRYPT_PK_INVALID_SIZE; - } - - /* allocate ram for DB/mask/salt/hash of size modulus_len */ - DB = XMALLOC(modulus_len); - mask = XMALLOC(modulus_len); - salt = XMALLOC(modulus_len); - hash = XMALLOC(modulus_len); - if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { - if (DB != NULL) { - XFREE(DB); - } - if (mask != NULL) { - XFREE(mask); - } - if (salt != NULL) { - XFREE(salt); - } - if (hash != NULL) { - XFREE(hash); - } - return CRYPT_MEM; - } - - /* ensure the 0xBC byte */ - if (sig[siglen-1] != 0xBC) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* copy out the DB */ - x = 0; - XMEMCPY(DB, sig + x, modulus_len - hLen - 1); - x += modulus_len - hLen - 1; - - /* copy out the hash */ - XMEMCPY(hash, sig + x, hLen); - /* x += hLen; */ - - /* check the MSB */ - if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* xor against DB */ - for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; - } - - /* now clear the first byte [make sure smaller than modulus] */ - DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen)); - - /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ - - /* check for zeroes and 0x01 */ - for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { - if (DB[x] != 0x00) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - } - - /* check for the 0x01 */ - if (DB[x++] != 0x01) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; - } - - /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ - if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { - goto LBL_ERR; - } - zeromem(mask, 8); - if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* mask == hash means valid signature */ - if (XMEM_NEQ(mask, hash, hLen) == 0) { - *res = 1; - } - - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(mask, modulus_len); - zeromem(salt, modulus_len); - zeromem(hash, modulus_len); -#endif - - XFREE(hash); - XFREE(salt); - XFREE(mask); - XFREE(DB); - - return err; -} - -#endif /* LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c deleted file mode 100644 index 2a4e372..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c +++ /dev/null @@ -1,164 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file pkcs_1_pss_encode.c - PKCS #1 PSS Signature Padding, Tom St Denis -*/ - -#ifdef LTC_PKCS_1 - -/** - PKCS #1 v2.00 Signature Encoding - @param msghash The hash to encode - @param msghashlen The length of the hash (octets) - @param saltlen The length of the salt desired (octets) - @param prng An active PRNG context - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param modulus_bitlen The bit length of the RSA modulus - @param out [out] The destination of the encoding - @param outlen [in/out] The max size and resulting size of the encoded data - @return CRYPT_OK if successful -*/ -int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, prng_state *prng, - int prng_idx, int hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned char *DB, *mask, *salt, *hash; - unsigned long x, y, hLen, modulus_len; - int err; - hash_state md; - - LTC_ARGCHK(msghash != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* ensure hash and PRNG are valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - - hLen = hash_descriptor[hash_idx].hashsize; - modulus_bitlen--; - modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); - - /* check sizes */ - if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { - return CRYPT_PK_INVALID_SIZE; - } - - /* allocate ram for DB/mask/salt/hash of size modulus_len */ - DB = XMALLOC(modulus_len); - mask = XMALLOC(modulus_len); - salt = XMALLOC(modulus_len); - hash = XMALLOC(modulus_len); - if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { - if (DB != NULL) { - XFREE(DB); - } - if (mask != NULL) { - XFREE(mask); - } - if (salt != NULL) { - XFREE(salt); - } - if (hash != NULL) { - XFREE(hash); - } - return CRYPT_MEM; - } - - - /* generate random salt */ - if (saltlen > 0) { - if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { - err = CRYPT_ERROR_READPRNG; - goto LBL_ERR; - } - } - - /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ - if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { - goto LBL_ERR; - } - zeromem(DB, 8); - if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ - x = 0; - XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); - x += modulus_len - saltlen - hLen - 2; - DB[x++] = 0x01; - XMEMCPY(DB + x, salt, saltlen); - /* x += saltlen; */ - - /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { - goto LBL_ERR; - } - - /* xor against DB */ - for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; - } - - /* output is DB || hash || 0xBC */ - if (*outlen < modulus_len) { - *outlen = modulus_len; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* DB len = modulus_len - hLen - 1 */ - y = 0; - XMEMCPY(out + y, DB, modulus_len - hLen - 1); - y += modulus_len - hLen - 1; - - /* hash */ - XMEMCPY(out + y, hash, hLen); - y += hLen; - - /* 0xBC */ - out[y] = 0xBC; - - /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ - out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen); - - /* store output size */ - *outlen = modulus_len; - err = CRYPT_OK; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(mask, modulus_len); - zeromem(salt, modulus_len); - zeromem(hash, modulus_len); -#endif - - XFREE(hash); - XFREE(salt); - XFREE(mask); - XFREE(DB); - - return err; -} - -#endif /* LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c deleted file mode 100644 index e988060..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c +++ /dev/null @@ -1,102 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** @file pkcs_1_v1_5_decode.c - * - * PKCS #1 v1.5 Padding. (Andreas Lange) - */ - -#ifdef LTC_PKCS_1 - -/** @brief PKCS #1 v1.5 decode. - * - * @param msg The encoded data to decode - * @param msglen The length of the encoded data (octets) - * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) - * @param modulus_bitlen The bit length of the RSA modulus - * @param out [out] Destination of decoding - * @param outlen [in/out] The max size and resulting size of the decoding - * @param is_valid [out] Boolean whether the padding was valid - * - * @return CRYPT_OK if successful - */ -int pkcs_1_v1_5_decode(const unsigned char *msg, - unsigned long msglen, - int block_type, - unsigned long modulus_bitlen, - unsigned char *out, - unsigned long *outlen, - int *is_valid) -{ - unsigned long modulus_len, ps_len, i; - int result; - - /* default to invalid packet */ - *is_valid = 0; - - modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); - - /* test message size */ - - if ((msglen > modulus_len) || (modulus_len < 11)) { - return CRYPT_PK_INVALID_SIZE; - } - - result = CRYPT_OK; - - /* separate encoded message */ - - if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { - result = CRYPT_INVALID_PACKET; - } - - if (block_type == LTC_PKCS_1_EME) { - for (i = 2; i < modulus_len; i++) { - /* separator */ - if (msg[i] == 0x00) { break; } - } - ps_len = i++ - 2; - - if (i > modulus_len) { - /* There was no octet with hexadecimal value 0x00 to separate ps from m. - */ - result = CRYPT_INVALID_PACKET; - } - } else { - for (i = 2; i < modulus_len - 1; i++) { - if (msg[i] != 0xFF) { break; } - } - - /* separator check */ - if (msg[i] != 0) { - /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ - result = CRYPT_INVALID_PACKET; - } - - ps_len = i - 2; - } - - if (ps_len < 8) - { - /* The length of ps is less than 8 octets. - */ - result = CRYPT_INVALID_PACKET; - } - - if (*outlen < (msglen - (2 + ps_len + 1))) { - result = CRYPT_INVALID_PACKET; - } - - if (result == CRYPT_OK) { - *outlen = (msglen - (2 + ps_len + 1)); - XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); - - /* valid packet */ - *is_valid = 1; - } - - return result; -} /* pkcs_1_v1_5_decode */ - -#endif /* #ifdef LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c b/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c deleted file mode 100644 index a21df4b..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c +++ /dev/null @@ -1,105 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/*! \file pkcs_1_v1_5_encode.c - * - * PKCS #1 v1.5 Padding (Andreas Lange) - */ - -#ifdef LTC_PKCS_1 - -/*! \brief PKCS #1 v1.5 encode. - * - * \param msg The data to encode - * \param msglen The length of the data to encode (octets) - * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) - * \param modulus_bitlen The bit length of the RSA modulus - * \param prng An active PRNG state (only for LTC_PKCS_1_EME) - * \param prng_idx The index of the PRNG desired (only for LTC_PKCS_1_EME) - * \param out [out] The destination for the encoded data - * \param outlen [in/out] The max size and resulting size of the encoded data - * - * \return CRYPT_OK if successful - */ -int pkcs_1_v1_5_encode(const unsigned char *msg, - unsigned long msglen, - int block_type, - unsigned long modulus_bitlen, - prng_state *prng, - int prng_idx, - unsigned char *out, - unsigned long *outlen) -{ - unsigned long modulus_len, ps_len, i; - unsigned char *ps; - int result; - - LTC_ARGCHK((msglen == 0) || (msg != NULL)); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* valid block_type? */ - if ((block_type != LTC_PKCS_1_EMSA) && - (block_type != LTC_PKCS_1_EME)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (block_type == LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ - if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) { - return result; - } - } - - modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); - - /* test message size */ - if ((msglen + 11) > modulus_len) { - return CRYPT_PK_INVALID_SIZE; - } - - if (*outlen < modulus_len) { - *outlen = modulus_len; - result = CRYPT_BUFFER_OVERFLOW; - goto bail; - } - - /* generate an octets string PS */ - ps = &out[2]; - ps_len = modulus_len - msglen - 3; - - if (block_type == LTC_PKCS_1_EME) { - /* now choose a random ps */ - if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) { - result = CRYPT_ERROR_READPRNG; - goto bail; - } - - /* transform zero bytes (if any) to non-zero random bytes */ - for (i = 0; i < ps_len; i++) { - while (ps[i] == 0) { - if (prng_descriptor[prng_idx].read(&ps[i], 1, prng) != 1) { - result = CRYPT_ERROR_READPRNG; - goto bail; - } - } - } - } else { - XMEMSET(ps, 0xFF, ps_len); - } - - /* create string of length modulus_len */ - out[0] = 0x00; - out[1] = (unsigned char)block_type; /* block_type 1 or 2 */ - out[2 + ps_len] = 0x00; - if (msglen != 0) { - XMEMCPY(&out[2 + ps_len + 1], msg, msglen); - } - *outlen = modulus_len; - - result = CRYPT_OK; -bail: - return result; -} /* pkcs_1_v1_5_encode */ - -#endif /* #ifdef LTC_PKCS_1 */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_decrypt_key.c deleted file mode 100644 index d8e7a54..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_decrypt_key.c +++ /dev/null @@ -1,95 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_decrypt_key.c - RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange -*/ - -#ifdef LTC_MRSA - -/** - PKCS #1 decrypt then v1.5 or OAEP depad - @param in The ciphertext - @param inlen The length of the ciphertext (octets) - @param out [out] The plaintext - @param outlen [in/out] The max size and resulting size of the plaintext (octets) - @param lparam The system "lparam" value - @param lparamlen The length of the lparam value (octets) - @param mgf_hash The hash algorithm used for the MGF - @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) - @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) - @param stat [out] Result of the decryption, 1==valid, 0==invalid - @param key The corresponding private RSA key - @return CRYPT_OK if succcessul (even if invalid) -*/ -int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - int mgf_hash, int lparam_hash, - int padding, - int *stat, const rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - unsigned char *tmp; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(stat != NULL); - - /* default to invalid */ - *stat = 0; - - /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_OAEP)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (padding == LTC_PKCS_1_OAEP) { - /* valid hash ? */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - } - - /* get modulus len in bits */ - modulus_bitlen = ltc_mp_count_bits( (key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = ltc_mp_unsigned_bin_size( (key->N)); - if (modulus_bytelen != inlen) { - return CRYPT_INVALID_PACKET; - } - - /* allocate ram */ - tmp = XMALLOC(inlen); - if (tmp == NULL) { - return CRYPT_MEM; - } - - /* rsa decode the packet */ - x = inlen; - if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { - XFREE(tmp); - return err; - } - - if (padding == LTC_PKCS_1_OAEP) { - /* now OAEP decode the packet */ - err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash, - lparam_hash, out, outlen, stat); - } else { - /* now PKCS #1 v1.5 depad the packet */ - err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); - } - - XFREE(tmp); - return err; -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_encrypt_key.c deleted file mode 100644 index 17dd1af..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_encrypt_key.c +++ /dev/null @@ -1,93 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_encrypt_key.c - RSA PKCS #1 encryption, Tom St Denis and Andreas Lange -*/ - -#ifdef LTC_MRSA - -/** - (PKCS #1 v2.0) OAEP pad then encrypt - @param in The plaintext - @param inlen The length of the plaintext (octets) - @param out [out] The ciphertext - @param outlen [in/out] The max size and resulting size of the ciphertext - @param lparam The system "lparam" for the encryption - @param lparamlen The length of lparam (octets) - @param prng An active PRNG - @param prng_idx The index of the desired prng - @param hash_idx The index of the desired hash - @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) - @param key The RSA key to encrypt to - @return CRYPT_OK if successful -*/ -int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - prng_state *prng, int prng_idx, - int mgf_hash, int lparam_hash, - int padding, - const rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - - LTC_ARGCHK((inlen == 0) || (in != NULL)); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_OAEP)) { - return CRYPT_PK_INVALID_PADDING; - } - - /* valid prng? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - - if (padding == LTC_PKCS_1_OAEP) { - /* valid hash? */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - } - - /* get modulus len in bits */ - modulus_bitlen = ltc_mp_count_bits( (key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = ltc_mp_unsigned_bin_size( (key->N)); - if (modulus_bytelen > *outlen) { - *outlen = modulus_bytelen; - return CRYPT_BUFFER_OVERFLOW; - } - - if (padding == LTC_PKCS_1_OAEP) { - /* OAEP pad the key */ - x = *outlen; - if ((err = pkcs_1_oaep_encode(in, inlen, lparam, - lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash, - lparam_hash, out, &x)) != CRYPT_OK) { - return err; - } - } else { - /* PKCS #1 v1.5 pad the key */ - x = *outlen; - if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, - modulus_bitlen, prng, prng_idx, - out, &x)) != CRYPT_OK) { - return err; - } - } - - /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */ - return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_export.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_export.c deleted file mode 100644 index 7d99f47..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_export.c +++ /dev/null @@ -1,91 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_export.c - Export RSA PKCS keys, Tom St Denis -*/ - -#ifdef LTC_MRSA - -/** - This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] - @param out [out] Destination of the packet - @param outlen [in/out] The max size and resulting size of the packet - @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) - @param key The RSA key to export - @return CRYPT_OK if successful -*/ -int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key) -{ - unsigned long zero=0; - int err, std; - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - std = type & PK_STD; - type &= ~PK_STD; - - if (type == PK_PRIVATE && key->type != PK_PRIVATE) { - return CRYPT_PK_TYPE_MISMATCH; - } - - if (type == PK_PRIVATE) { - /* private key */ - /* output is - Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p - */ - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_EOL, 0UL, NULL); - } - - if (type == PK_PUBLIC) { - /* public key */ - unsigned long tmplen, *ptmplen; - unsigned char* tmp = NULL; - - if (std) { - tmplen = (unsigned long)(ltc_mp_count_bits(key->N) / 8) * 2 + 8; - tmp = XMALLOC(tmplen); - ptmplen = &tmplen; - if (tmp == NULL) { - return CRYPT_MEM; - } - } - else { - tmp = out; - ptmplen = outlen; - } - - err = der_encode_sequence_multi(tmp, ptmplen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL); - - if ((err != CRYPT_OK) || !std) { - goto finish; - } - - err = x509_encode_subject_public_key_info(out, outlen, - LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); - -finish: - if (tmp != out) XFREE(tmp); - return err; - } - - return CRYPT_INVALID_ARG; -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_exptmod.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_exptmod.c deleted file mode 100644 index 95dddde..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_exptmod.c +++ /dev/null @@ -1,172 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_exptmod.c - RSA PKCS exptmod, Tom St Denis - Added RSA blinding --nmav -*/ - -#ifdef LTC_MRSA - -/** - Compute an RSA modular exponentiation - @param in The input data to send into RSA - @param inlen The length of the input (octets) - @param out [out] The destination - @param outlen [in/out] The max size and resulting size of the output - @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC - @param key The RSA key to use - @return CRYPT_OK if successful -*/ -int rsa_exptmod(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int which, - const rsa_key *key) -{ - void *tmp, *tmpa, *tmpb; - #ifdef LTC_RSA_BLINDING - void *rnd, *rndi /* inverse of rnd */; - #endif - unsigned long x; - int err, has_crt_parameters; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* is the key of the right type for the operation? */ - if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* must be a private or public operation */ - if (which != PK_PRIVATE && which != PK_PUBLIC) { - return CRYPT_PK_INVALID_TYPE; - } - - /* init and copy into tmp */ - if ((err = ltc_mp_init_multi(&tmp, &tmpa, &tmpb, -#ifdef LTC_RSA_BLINDING - &rnd, &rndi, -#endif /* LTC_RSA_BLINDING */ - NULL)) != CRYPT_OK) - { return err; } - if ((err = ltc_mp_read_unsigned_bin(tmp, in, (int)inlen)) != CRYPT_OK) - { goto error; } - - - /* sanity check on the input */ - if (ltc_mp_cmp(key->N, tmp) == LTC_MP_LT) { - err = CRYPT_PK_INVALID_SIZE; - goto error; - } - - /* are we using the private exponent and is the key optimized? */ - if (which == PK_PRIVATE) { - #ifdef LTC_RSA_BLINDING - /* do blinding */ - err = ltc_mp_rand(rnd, ltc_mp_get_digit_count(key->N)); - if (err != CRYPT_OK) { - goto error; - } - - /* rndi = 1/rnd mod N */ - err = ltc_mp_invmod(rnd, key->N, rndi); - if (err != CRYPT_OK) { - goto error; - } - - /* rnd = rnd^e */ - err = ltc_mp_exptmod( rnd, key->e, key->N, rnd); - if (err != CRYPT_OK) { - goto error; - } - - /* tmp = tmp*rnd mod N */ - err = ltc_mp_mulmod( tmp, rnd, key->N, tmp); - if (err != CRYPT_OK) { - goto error; - } - #endif /* LTC_RSA_BLINDING */ - - has_crt_parameters = (key->p != NULL) && (ltc_mp_get_digit_count(key->p) != 0) && - (key->q != NULL) && (ltc_mp_get_digit_count(key->q) != 0) && - (key->dP != NULL) && (ltc_mp_get_digit_count(key->dP) != 0) && - (key->dQ != NULL) && (ltc_mp_get_digit_count(key->dQ) != 0) && - (key->qP != NULL) && (ltc_mp_get_digit_count(key->qP) != 0); - - if (!has_crt_parameters) { - /* - * In case CRT optimization parameters are not provided, - * the private key is directly used to exptmod it - */ - if ((err = ltc_mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } - } else { - /* tmpa = tmp^dP mod p */ - if ((err = ltc_mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } - - /* tmpb = tmp^dQ mod q */ - if ((err = ltc_mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ - if ((err = ltc_mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } - - /* tmp = tmpb + q * tmp */ - if ((err = ltc_mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } - } - - #ifdef LTC_RSA_BLINDING - /* unblind */ - err = ltc_mp_mulmod( tmp, rndi, key->N, tmp); - if (err != CRYPT_OK) { - goto error; - } - #endif - - #ifdef LTC_RSA_CRT_HARDENING - if (has_crt_parameters) { - if ((err = ltc_mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp_read_unsigned_bin(tmpb, in, (int)inlen)) != CRYPT_OK) { goto error; } - if (ltc_mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; } - } - #endif - } else { - /* exptmod it */ - if ((err = ltc_mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; } - } - - /* read it back */ - x = (unsigned long)ltc_mp_unsigned_bin_size(key->N); - if (x > *outlen) { - *outlen = x; - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - - /* this should never happen ... */ - if (ltc_mp_unsigned_bin_size(tmp) > ltc_mp_unsigned_bin_size(key->N)) { - err = CRYPT_ERROR; - goto error; - } - *outlen = x; - - /* convert it */ - zeromem(out, x); - if ((err = ltc_mp_to_unsigned_bin(tmp, out+(x-ltc_mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; } - - /* clean up and return */ - err = CRYPT_OK; -error: - ltc_mp_deinit_multi( -#ifdef LTC_RSA_BLINDING - rndi, rnd, -#endif /* LTC_RSA_BLINDING */ - tmpb, tmpa, tmp, NULL); - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_get_size.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_get_size.c deleted file mode 100644 index 7dae330..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_get_size.c +++ /dev/null @@ -1,36 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -/** - @file rsa_get_size.c - Retrieve the size of an RSA key, Steffen Jaeckel. -*/ - -#ifdef LTC_MRSA - -/** - Retrieve the size in bytes of an RSA key. - @param key The RSA key - @return The size in bytes of the RSA key or INT_MAX on error. -*/ -int rsa_get_size(const rsa_key *key) -{ - int ret = INT_MAX; - LTC_ARGCHK(key != NULL); - - if (key) - { - ret = ltc_mp_unsigned_bin_size(key->N); - } /* if */ - - return ret; -} - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import.c deleted file mode 100644 index 1240a77..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import.c +++ /dev/null @@ -1,143 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_import.c - Import a PKCS RSA key, Tom St Denis -*/ - -#ifdef LTC_MRSA - - -/** - Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] - - The `key` passed into this function has to be already initialized and will - NOT be free'd on error! - - @param in The packet to import from - @param inlen It's length (octets) - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful -*/ -int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) -{ - int err; - unsigned long version = -1; - - err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_EOL, 0UL, NULL); - - if (err == CRYPT_OVERFLOW) { - /* the version would fit into an LTC_ASN1_SHORT_INTEGER - * so we try to decode as a public key - */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { - key->type = PK_PUBLIC; - } - goto LBL_OUT; - } else if (err != CRYPT_INPUT_TOO_LONG) { - /* couldn't decode the version, so error out */ - goto LBL_OUT; - } - - if (version == 0) { - /* it's a private key */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &version, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_OUT; - } - key->type = PK_PRIVATE; - } else if (version == 1) { - /* we don't support multi-prime RSA */ - err = CRYPT_PK_INVALID_TYPE; - goto LBL_OUT; - } - err = CRYPT_OK; -LBL_OUT: - return err; -} - -/** - Import multiple formats of RSA public and private keys. - - RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] - SubjectPublicKeyInfo formatted public keys - - @param in The packet to import from - @param inlen It's length (octets) - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) -{ - int err; - unsigned char *tmpbuf=NULL; - unsigned long tmpbuf_len, len; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* init key */ - if ((err = rsa_init(key)) != CRYPT_OK) { - return err; - } - - /* see if the OpenSSL DER format RSA public key will work */ - tmpbuf_len = inlen; - tmpbuf = XCALLOC(1, tmpbuf_len); - if (tmpbuf == NULL) { - err = CRYPT_MEM; - goto LBL_ERR; - } - - len = 0; - err = x509_decode_subject_public_key_info(in, inlen, - LTC_OID_RSA, tmpbuf, &tmpbuf_len, - LTC_ASN1_NULL, NULL, &len); - - if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ - - /* now it should be SEQUENCE { INTEGER, INTEGER } */ - if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - key->type = PK_PUBLIC; - err = CRYPT_OK; - goto LBL_FREE; - } - - /* not SSL public key, try to match against PKCS #1 standards */ - if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { - goto LBL_FREE; - } - -LBL_ERR: - rsa_free(key); - -LBL_FREE: - if (tmpbuf != NULL) { - XFREE(tmpbuf); - } - return err; -} - -#endif /* LTC_MRSA */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_pkcs8.c deleted file mode 100644 index 0a4570c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_pkcs8.c +++ /dev/null @@ -1,70 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_import_pkcs8.c - Import a PKCS RSA key -*/ - -#ifdef LTC_MRSA - -int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - - LTC_UNUSED_PARAM(alg_id); - - if ((err = rsa_init(key)) != CRYPT_OK) { - return err; - } - - if ((err = rsa_import_pkcs1(priv_key->data, priv_key->size, key)) != CRYPT_OK) { - rsa_free(key); - return err; - } - key->type = PK_PRIVATE; - - return err; -} - -/** - Import an RSAPrivateKey in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - rsa_key *key) -{ - int err; - ltc_asn1_list *l = NULL; - ltc_asn1_list *alg_id, *priv_key; - enum ltc_oid_id pka; - - LTC_ARGCHK(in != NULL); - - if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) { - return err; - } - if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto LBL_DER_FREE; - } - if (pka != LTC_OID_RSA) { - err = CRYPT_INVALID_PACKET; - goto LBL_DER_FREE; - } - - err = rsa_import_pkcs8_asn1(alg_id, priv_key, key); - -LBL_DER_FREE: - der_free_sequence_flexi(l); - return err; -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_x509.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_x509.c deleted file mode 100644 index 4d157ea..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_import_x509.c +++ /dev/null @@ -1,54 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_import.c - Import an RSA key from a X.509 certificate, Steffen Jaeckel -*/ - -#ifdef LTC_MRSA - -static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) -{ - /* now it should be SEQUENCE { INTEGER, INTEGER } */ - return der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL); -} - -/** - Import an RSA key from a X.509 certificate - @param in The packet to import from - @param inlen It's length (octets) - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, upon error allocated memory is freed -*/ -int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* init key */ - if ((err = rsa_init(key)) != CRYPT_OK) { - return err; - } - - if ((err = x509_decode_public_key_from_certificate(in, inlen, - LTC_OID_RSA, - LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { - rsa_free(key); - } else { - key->type = PK_PUBLIC; - } - - return err; -} - -#endif /* LTC_MRSA */ - diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_key.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_key.c deleted file mode 100644 index 7eb21b8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_key.c +++ /dev/null @@ -1,101 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_key.c - Free an RSA key, Tom St Denis - Basic operations on an RSA key, Steffen Jaeckel -*/ - -#ifdef LTC_MRSA -static void s_mpi_shrink_multi(void **a, ...) -{ - void **cur; - unsigned n; - int err; - va_list args; - void *tmp[10] = { 0 }; - void **arg[10] = { 0 }; - - /* We re-allocate in the order that we received the varargs */ - n = 0; - err = CRYPT_ERROR; - cur = a; - va_start(args, a); - while (cur != NULL) { - if (n >= LTC_ARRAY_SIZE(tmp)) { - goto out; - } - if (*cur != NULL) { - arg[n] = cur; - if ((err = ltc_mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) { - goto out; - } - n++; - } - cur = va_arg(args, void**); - } - va_end(args); - - /* but we clear the old values in the reverse order */ - while (n != 0 && arg[--n] != NULL) { - ltc_mp_clear(*arg[n]); - *arg[n] = tmp[n]; - } -out: - va_end(args); - /* clean-up after an error - * or after this was called with too many args - */ - if ((err != CRYPT_OK) || - (n >= LTC_ARRAY_SIZE(tmp))) { - for (n = 0; n < LTC_ARRAY_SIZE(tmp); ++n) { - if (tmp[n] != NULL) { - ltc_mp_clear(tmp[n]); - } - } - } -} - -/** - This shrinks the allocated memory of a RSA key - - It will use up some more memory temporarily, - but then it will free-up the entire sequence that - was once allocated when the key was created/populated. - - This only works with libtommath >= 1.2.0 in earlier versions - it has the inverse effect due to the way it worked internally. - Also works for GNU MP, tomsfastmath naturally shows no effect. - - @param key The RSA key to shrink -*/ -void rsa_shrink_key(rsa_key *key) -{ - LTC_ARGCHKVD(key != NULL); - s_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); -} - -/** - Init an RSA key - @param key The RSA key to initialize - @return CRYPT_OK if successful -*/ -int rsa_init(rsa_key *key) -{ - LTC_ARGCHK(key != NULL); - return ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); -} - -/** - Free an RSA key from memory - @param key The RSA key to free -*/ -void rsa_free(rsa_key *key) -{ - LTC_ARGCHKVD(key != NULL); - ltc_mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_make_key.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_make_key.c deleted file mode 100644 index 7cbecaf..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_make_key.c +++ /dev/null @@ -1,165 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_make_key.c - RSA key generation, Tom St Denis -*/ - -#ifdef LTC_MRSA - -static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_key *key) -{ - void *p, *q, *tmp1, *tmp2; - int err; - - LTC_ARGCHK(ltc_mp.name != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(size > 0); - - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { - return err; - } - - /* make primes p and q (optimization provided by Wayne Scott) */ - - /* make prime "p" */ - do { - if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */ - if ((err = ltc_mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */ - } while (ltc_mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */ - - /* make prime "q" */ - do { - if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } - if ((err = ltc_mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */ - if ((err = ltc_mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */ - } while (ltc_mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */ - - /* tmp1 = lcm(p-1, q-1) */ - if ((err = ltc_mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */ - /* tmp1 = q-1 (previous do/while loop) */ - if ((err = ltc_mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */ - - /* make key */ - if ((err = rsa_init(key)) != CRYPT_OK) { - goto errkey; - } - - if ((err = ltc_mp_copy( e, key->e)) != CRYPT_OK) { goto errkey; } /* key->e = e */ - if ((err = ltc_mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */ - if ((err = ltc_mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */ - - /* optimize for CRT now */ - /* find d mod q-1 and d mod p-1 */ - if ((err = ltc_mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */ - if ((err = ltc_mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-1 */ - if ((err = ltc_mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */ - if ((err = ltc_mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */ - if ((err = ltc_mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */ - - if ((err = ltc_mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; } - if ((err = ltc_mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; } - - /* set key type (in this case it's CRT optimized) */ - key->type = PK_PRIVATE; - - /* return ok and free temps */ - err = CRYPT_OK; - goto cleanup; -errkey: - rsa_free(key); -cleanup: - ltc_mp_deinit_multi(tmp2, tmp1, q, p, LTC_NULL); - return err; -} - -/** - Create an RSA key based on a long public exponent type - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param size The size of the modulus (key size) desired (octets) - @param e The "e" value (public key). e==65537 is a good choice - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful, upon error all allocated ram is freed -*/ -int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) -{ - void *tltc_mp_e; - int err; - - if ((e < 3) || ((e & 1) == 0)) { - return CRYPT_INVALID_ARG; - } - - if ((err = ltc_mp_init(&tltc_mp_e)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_set_int(tltc_mp_e, e)) == CRYPT_OK) - err = s_rsa_make_key(prng, wprng, size, tltc_mp_e, key); - - ltc_mp_clear(tltc_mp_e); - - return err; -} - -/** - Create an RSA key based on a hexadecimal public exponent type - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param size The size of the modulus (key size) desired (octets) - @param e The "e" value (public key). e==65537 is a good choice - @param elen The length of e (octets) - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful, upon error all allocated ram is freed -*/ -int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, - const unsigned char *e, unsigned long elen, rsa_key *key) -{ - int err; - void *tmp_e; - - if ((err = ltc_mp_init(&tmp_e)) != CRYPT_OK) { - return err; - } - - if ((err = ltc_mp_read_unsigned_bin(tmp_e, e, elen)) == CRYPT_OK) - err = rsa_make_key_bn_e(prng, wprng, size, tmp_e, key); - - ltc_mp_clear(tmp_e); - - return err; -} - -/** - Create an RSA key based on a bignumber public exponent type - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param size The size of the modulus (key size) desired (octets) - @param e The "e" value (public key). e==65537 is a good choice - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful, upon error all allocated ram is freed -*/ -int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key) -{ - int err; - int e_bits; - - e_bits = ltc_mp_count_bits(e); - if ((e_bits > 1 && e_bits < 256) && (ltc_mp_get_digit(e, 0) & 1)) { - err = s_rsa_make_key(prng, wprng, size, e, key); - } else { - err = CRYPT_INVALID_ARG; - } - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_set.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_set.c deleted file mode 100644 index 55d6f7c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_set.c +++ /dev/null @@ -1,123 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - - -#ifdef LTC_MRSA - -/** - Import RSA key from raw numbers - - @param N RSA's N - @param Nlen RSA's N's length - @param e RSA's e - @param elen RSA's e's length - @param d RSA's d (only private key, NULL for public key) - @param dlen RSA's d's length - @param key [out] the destination for the imported key - @return CRYPT_OK if successful -*/ -int rsa_set_key(const unsigned char *N, unsigned long Nlen, - const unsigned char *e, unsigned long elen, - const unsigned char *d, unsigned long dlen, - rsa_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(N != NULL); - LTC_ARGCHK(e != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if ((err = rsa_init(key)) != CRYPT_OK) return err; - - if ((err = ltc_mp_read_unsigned_bin(key->N , N , Nlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->e , e , elen)) != CRYPT_OK) { goto LBL_ERR; } - if (d && dlen) { - if ((err = ltc_mp_read_unsigned_bin(key->d , d , dlen)) != CRYPT_OK) { goto LBL_ERR; } - key->type = PK_PRIVATE; - } - else { - key->type = PK_PUBLIC; - } - return CRYPT_OK; - -LBL_ERR: - rsa_free(key); - return err; -} - -/** - Import factors of an RSA key from raw numbers - - Only for private keys. - - @param p RSA's p - @param plen RSA's p's length - @param q RSA's q - @param qlen RSA's q's length - @param key [out] the destination for the imported key - @return CRYPT_OK if successful -*/ -int rsa_set_factors(const unsigned char *p, unsigned long plen, - const unsigned char *q, unsigned long qlen, - rsa_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(p != NULL); - LTC_ARGCHK(q != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; - - if ((err = ltc_mp_read_unsigned_bin(key->p , p , plen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->q , q , qlen)) != CRYPT_OK) { goto LBL_ERR; } - return CRYPT_OK; - -LBL_ERR: - rsa_free(key); - return err; -} - -/** - Import CRT parameters of an RSA key from raw numbers - - Only for private keys. - - @param dP RSA's dP - @param dPlen RSA's dP's length - @param dQ RSA's dQ - @param dQlen RSA's dQ's length - @param qP RSA's qP - @param qPlen RSA's qP's length - @param key [out] the destination for the imported key - @return CRYPT_OK if successful -*/ -int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, - const unsigned char *dQ, unsigned long dQlen, - const unsigned char *qP, unsigned long qPlen, - rsa_key *key) -{ - int err; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(dP != NULL); - LTC_ARGCHK(dQ != NULL); - LTC_ARGCHK(qP != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; - - if ((err = ltc_mp_read_unsigned_bin(key->dP, dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->dQ, dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = ltc_mp_read_unsigned_bin(key->qP, qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; } - return CRYPT_OK; - -LBL_ERR: - rsa_free(key); - return err; -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_hash.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_hash.c deleted file mode 100644 index bc5e0a8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_hash.c +++ /dev/null @@ -1,138 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_sign_hash.c - RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange -*/ - -#ifdef LTC_MRSA - -/** - PKCS #1 pad then sign - @param in The hash to sign - @param inlen The length of the hash to sign (octets) - @param out [out] The signature - @param outlen [in/out] The max size and resulting size of the signature - @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) - @param prng An active PRNG state - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param saltlen The length of the salt desired (octets) - @param key The private RSA key to use - @return CRYPT_OK if successful -*/ -int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - int padding, - prng_state *prng, int prng_idx, - int hash_idx, unsigned long saltlen, - const rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x, y; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_PSS) && - (padding != LTC_PKCS_1_V1_5_NA1)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (padding == LTC_PKCS_1_PSS) { - /* valid prng ? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - } - - if (padding != LTC_PKCS_1_V1_5_NA1) { - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - } - - /* get modulus len in bits */ - modulus_bitlen = ltc_mp_count_bits((key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = ltc_mp_unsigned_bin_size((key->N)); - if (modulus_bytelen > *outlen) { - *outlen = modulus_bytelen; - return CRYPT_BUFFER_OVERFLOW; - } - - if (padding == LTC_PKCS_1_PSS) { - /* PSS pad the key */ - x = *outlen; - if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, - hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { - return err; - } - } else { - /* PKCS #1 v1.5 pad the hash */ - unsigned char *tmpin = NULL; - const unsigned char *tmpin_ro; - - if (padding == LTC_PKCS_1_V1_5) { - ltc_asn1_list digestinfo[2], siginfo[2]; - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - return CRYPT_INVALID_ARG; - } - - /* construct the SEQUENCE - SEQUENCE { - SEQUENCE {hashoid OID - blah NULL - } - hash OCTET STRING - } - */ - LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); - LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); - LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); - - /* allocate memory for the encoding */ - y = ltc_mp_unsigned_bin_size(key->N); - tmpin = XMALLOC(y); - if (tmpin == NULL) { - return CRYPT_MEM; - } - - if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { - XFREE(tmpin); - return err; - } - tmpin_ro = tmpin; - } else { - /* set the pointer and data-length to the input values */ - tmpin_ro = in; - y = inlen; - } - - x = *outlen; - err = pkcs_1_v1_5_encode(tmpin_ro, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); - - if (padding == LTC_PKCS_1_V1_5) { - XFREE(tmpin); - } - - if (err != CRYPT_OK) { - return err; - } - } - - /* RSA encode it */ - return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c deleted file mode 100644 index f1ae263..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_sign_saltlen_get.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_sign_saltlen_get.c - Retrieve the maximum size of the salt, Steffen Jaeckel. -*/ - -#ifdef LTC_MRSA - -/** - Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. - @param padding Type of padding (LTC_PKCS_1_PSS only) - @param hash_idx The index of the desired hash - @param key The RSA key - @return The maximum salt length in bytes or INT_MAX on error. -*/ -int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key) -{ - int ret = INT_MAX; - LTC_ARGCHK(key != NULL); - - if ((hash_is_valid(hash_idx) == CRYPT_OK) && - (padding == LTC_PKCS_1_PSS)) - { - ret = rsa_get_size(key); - if (ret < INT_MAX) - { - ret -= (hash_descriptor[hash_idx].hashsize + 2); - } /* if */ - } /* if */ - - return ret; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_verify_hash.c b/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_verify_hash.c deleted file mode 100644 index 9ca1641..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/rsa/rsa_verify_hash.c +++ /dev/null @@ -1,183 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file rsa_verify_hash.c - RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange -*/ - -#ifdef LTC_MRSA - -/** - PKCS #1 de-sign then v1.5 or PSS depad - @param sig The signature data - @param siglen The length of the signature data (octets) - @param hash The hash of the message that was signed - @param hashlen The length of the hash of the message that was signed (octets) - @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) - @param hash_idx The index of the desired hash - @param saltlen The length of the salt used during signature - @param stat [out] The result of the signature comparison, 1==valid, 0==invalid - @param key The public RSA key corresponding to the key that performed the signature - @return CRYPT_OK on success (even if the signature is invalid) -*/ -int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int padding, - int hash_idx, unsigned long saltlen, - int *stat, const rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - unsigned char *tmpbuf; - - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - - /* default to invalid */ - *stat = 0; - - /* valid padding? */ - - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_PSS) && - (padding != LTC_PKCS_1_V1_5_NA1)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (padding != LTC_PKCS_1_V1_5_NA1) { - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - } - - /* get modulus len in bits */ - modulus_bitlen = ltc_mp_count_bits( (key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = ltc_mp_unsigned_bin_size( (key->N)); - if (modulus_bytelen != siglen) { - return CRYPT_INVALID_PACKET; - } - - /* allocate temp buffer for decoded sig */ - tmpbuf = XMALLOC(siglen); - if (tmpbuf == NULL) { - return CRYPT_MEM; - } - - /* RSA decode it */ - x = siglen; - if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { - XFREE(tmpbuf); - return err; - } - - /* make sure the output is the right size */ - if (x != siglen) { - XFREE(tmpbuf); - return CRYPT_INVALID_PACKET; - } - - if (padding == LTC_PKCS_1_PSS) { - /* PSS decode and verify it */ - - if(modulus_bitlen%8 == 1){ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); - } - else{ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); - } - - } else { - /* PKCS #1 v1.5 decode it */ - unsigned char *out; - unsigned long outlen; - int decoded; - - /* allocate temp buffer for decoded hash */ - outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; - out = XMALLOC(outlen); - if (out == NULL) { - err = CRYPT_MEM; - goto bail_2; - } - - if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { - XFREE(out); - goto bail_2; - } - - if (padding == LTC_PKCS_1_V1_5) { - unsigned long loid[16], reallen; - ltc_asn1_list digestinfo[2], siginfo[2]; - - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - err = CRYPT_INVALID_ARG; - goto bail_2; - } - - /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ - /* construct the SEQUENCE - SEQUENCE { - SEQUENCE {hashoid OID - blah NULL - } - hash OCTET STRING - } - */ - LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, LTC_ARRAY_SIZE(loid)); - LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); - LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); - - if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) { - /* fallback to Legacy:missing NULL */ - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); - if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { - XFREE(out); - goto bail_2; - } - } - - if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { - XFREE(out); - goto bail_2; - } - - /* test OID */ - if ((reallen == outlen) && - (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && - (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && - (siginfo[1].size == hashlen) && - (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { - *stat = 1; - } - } else { - /* only check if the hash is equal */ - if ((hashlen == outlen) && - (XMEMCMP(out, hash, hashlen) == 0)) { - *stat = 1; - } - } - -#ifdef LTC_CLEAN_STACK - zeromem(out, outlen); -#endif - XFREE(out); - } - -bail_2: -#ifdef LTC_CLEAN_STACK - zeromem(tmpbuf, siglen); -#endif - XFREE(tmpbuf); - return err; -} - -#endif /* LTC_MRSA */ diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_export.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_export.c deleted file mode 100644 index fd99722..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_export.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_export.c - Export a X25519 key to a binary packet, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Export a X25519 key to a binary packet - @param out [out] The destination for the key - @param outlen [in/out] The max size and resulting size of the X25519 key - @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) - @param key The key you wish to export - @return CRYPT_OK if successful -*/ -int x25519_export( unsigned char *out, unsigned long *outlen, - int which, - const curve25519_key *key) -{ - LTC_ARGCHK(key != NULL); - - if (key->pka != LTC_PKA_X25519) return CRYPT_PK_INVALID_TYPE; - - return ec25519_export(out, outlen, which, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import.c deleted file mode 100644 index a16c624..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_import.c - Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Import a X25519 key - @param in The packet to read - @param inlen The length of the input packet - @param key [out] Where to import the key to - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - int err; - unsigned long key_len; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - key_len = sizeof(key->pub); - if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { - key->type = PK_PUBLIC; - key->pka = LTC_PKA_X25519; - } - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_pkcs8.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_pkcs8.c deleted file mode 100644 index 5c8e9b6..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_pkcs8.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_import_pkcs8.c - Import a X25519 key in PKCS#8 format, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -int x25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, - curve25519_key *key) -{ - return ec25519_import_pkcs8_asn1(alg_id, priv_key, LTC_OID_X25519, key); -} -/** - Import a X25519 private key in PKCS#8 format - @param in The packet to import from - @param inlen It's length (octets) - @param pw_ctx The password context when decrypting the private key - @param key [out] Destination for newly imported key - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, - const password_ctx *pw_ctx, - curve25519_key *key) -{ - return ec25519_import_pkcs8(in, inlen, pw_ctx, LTC_OID_X25519, key); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_raw.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_raw.c deleted file mode 100644 index da65920..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_raw.c +++ /dev/null @@ -1,41 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_import_raw.c - Set the parameters of a X25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Set the parameters of a X25519 key - - @param in The key - @param inlen The length of the key - @param which Which type of key (PK_PRIVATE or PK_PUBLIC) - @param key [out] Destination of the key - @return CRYPT_OK if successful -*/ -int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) -{ - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen == 32uL); - LTC_ARGCHK(key != NULL); - - if (which == PK_PRIVATE) { - XMEMCPY(key->priv, in, sizeof(key->priv)); - tweetnacl_crypto_scalarmult_base(key->pub, key->priv); - } else if (which == PK_PUBLIC) { - XMEMCPY(key->pub, in, sizeof(key->pub)); - } else { - return CRYPT_INVALID_ARG; - } - key->pka = LTC_PKA_X25519; - key->type = which; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_x509.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_x509.c deleted file mode 100644 index a3d90cd..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_import_x509.c +++ /dev/null @@ -1,45 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_import_x509.c - Import a X25519 key from a X.509 certificate, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -static int s_x25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; - XMEMCPY(key->pub, in, sizeof(key->pub)); - return CRYPT_OK; -} - -/** - Import a X25519 public key from a X.509 certificate - @param in The DER encoded X.509 certificate - @param inlen The length of the certificate - @param key [out] Where to import the key to - @return CRYPT_OK if successful, on error all allocated memory is freed automatically -*/ -int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = x509_decode_public_key_from_certificate(in, inlen, - LTC_OID_X25519, - LTC_ASN1_EOL, NULL, NULL, - (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) { - return err; - } - key->type = PK_PUBLIC; - key->pka = LTC_PKA_X25519; - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_make_key.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_make_key.c deleted file mode 100644 index a30003c..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_make_key.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_make_key.c - Create a X25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Create a X25519 key - @param prng An active PRNG state - @param wprng The index of the PRNG desired - @param key [out] Destination of a newly created private key pair - @return CRYPT_OK if successful -*/ -int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(key != NULL); - - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if (prng_descriptor[wprng].read(key->priv, sizeof(key->priv), prng) != sizeof(key->priv)) { - return CRYPT_ERROR_READPRNG; - } - - tweetnacl_crypto_scalarmult_base(key->pub, key->priv); - - key->type = PK_PRIVATE; - key->pka = LTC_PKA_X25519; - - return err; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_shared_secret.c b/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_shared_secret.c deleted file mode 100644 index d7e9ea8..0000000 --- a/Sources/DataLiteC/libtomcrypt/pk/x25519/x25519_shared_secret.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file x25519_shared_secret.c - Create a X25519 shared secret, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Create a X25519 shared secret. - @param private_key The private X25519 key in the pair - @param public_key The public X25519 key in the pair - @param out [out] The destination of the shared data - @param outlen [in/out] The max size and resulting size of the shared data. - @return CRYPT_OK if successful -*/ -int x25519_shared_secret(const curve25519_key *private_key, - const curve25519_key *public_key, - unsigned char *out, unsigned long *outlen) -{ - LTC_ARGCHK(private_key != NULL); - LTC_ARGCHK(public_key != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if (public_key->pka != LTC_PKA_X25519) return CRYPT_PK_INVALID_TYPE; - if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; - - if (*outlen < 32uL) { - *outlen = 32uL; - return CRYPT_BUFFER_OVERFLOW; - } - - tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub); - *outlen = 32uL; - - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/prngs/chacha20.c b/Sources/DataLiteC/libtomcrypt/prngs/chacha20.c deleted file mode 100644 index d9bd7b0..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/chacha20.c +++ /dev/null @@ -1,218 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - - /* the idea of re-keying loosely follows the approach used in: - * http://bxr.su/OpenBSD/lib/libc/crypt/arc4random.c - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA20_PRNG - -const struct ltc_prng_descriptor chacha20_prng_desc = -{ - "chacha20", - 40, - &chacha20_prng_start, - &chacha20_prng_add_entropy, - &chacha20_prng_ready, - &chacha20_prng_read, - &chacha20_prng_done, - &chacha20_prng_export, - &chacha20_prng_import, - &chacha20_prng_test -}; - -/** - Start the PRNG - @param prng The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int chacha20_prng_start(prng_state *prng) -{ - LTC_ARGCHK(prng != NULL); - prng->ready = 0; - XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); - prng->u.chacha.idx = 0; - LTC_MUTEX_INIT(&prng->lock) - return CRYPT_OK; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - unsigned char buf[40]; - unsigned long i; - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { - /* chacha20_prng_ready() was already called, do "rekey" operation */ - if ((err = chacha_keystream(&prng->u.chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; - for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; - /* key 32 bytes, 20 rounds */ - if ((err = chacha_setup(&prng->u.chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; - /* iv 8 bytes */ - if ((err = chacha_ivctr64(&prng->u.chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; - /* clear KEY + IV */ - zeromem(buf, sizeof(buf)); - } - else { - /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */ - while (inlen--) prng->u.chacha.ent[prng->u.chacha.idx++ % sizeof(prng->u.chacha.ent)] ^= *in++; - } - err = CRYPT_OK; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int chacha20_prng_ready(prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } - /* key 32 bytes, 20 rounds */ - if ((err = chacha_setup(&prng->u.chacha.s, prng->u.chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; - /* iv 8 bytes */ - if ((err = chacha_ivctr64(&prng->u.chacha.s, prng->u.chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; - XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); - prng->u.chacha.idx = 0; - prng->ready = 1; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - if (outlen == 0 || prng == NULL || out == NULL) return 0; - LTC_MUTEX_LOCK(&prng->lock); - if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } - if (chacha_keystream(&prng->u.chacha.s, out, outlen) != CRYPT_OK) outlen = 0; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return outlen; -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int chacha20_prng_done(prng_state *prng) -{ - int err; - LTC_ARGCHK(prng != NULL); - LTC_MUTEX_LOCK(&prng->lock); - prng->ready = 0; - err = chacha_done(&prng->u.chacha.s); - LTC_MUTEX_UNLOCK(&prng->lock); - LTC_MUTEX_DESTROY(&prng->lock); - return err; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -LTC_PRNG_EXPORT(chacha20_prng) - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG; - - if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err; - if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int chacha20_prng_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - prng_state st; - unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; - unsigned char dmp[300]; - unsigned long dmplen = sizeof(dmp); - unsigned char out[500]; - unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 }; - unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE }; - unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 }; - int err; - - if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err; - /* add entropy to uninitialized prng */ - if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; - if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; - if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - /* add entropy to already initialized prng */ - if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; - if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; - if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; - if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err; - if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; - if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; - if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/prngs/fortuna.c b/Sources/DataLiteC/libtomcrypt/prngs/fortuna.c deleted file mode 100644 index 9c92595..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/fortuna.c +++ /dev/null @@ -1,532 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED -#if defined(_WIN32) - #include -#elif defined(LTC_CLOCK_GETTIME) - #include /* struct timespec + clock_gettime */ -#else - #include /* struct timeval + gettimeofday */ -#endif -#endif - -/** - @file fortuna.c - Fortuna PRNG, Tom St Denis -*/ - -/* Implementation of Fortuna by Tom St Denis - -We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" -in the AddEntropy function are fixed to 0. Second since no reliable timer is provided -we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ - -#ifdef LTC_FORTUNA - -/* requries LTC_SHA256 and AES */ -#if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) - #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) -#endif - -#ifndef LTC_FORTUNA_POOLS - #warning LTC_FORTUNA_POOLS was not previously defined (old headers?) - #define LTC_FORTUNA_POOLS 32 -#endif - -#if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 - #error LTC_FORTUNA_POOLS must be in [4..32] -#endif - -#ifdef LTC_FORTUNA_USE_ENCRYPT_ONLY -#define AES_SETUP aes_enc_setup -#define AES_ENC aes_enc_ecb_encrypt -#define AES_DONE aes_enc_done -#define AES_TEST aes_enc_test -#else -#define AES_SETUP aes_setup -#define AES_ENC aes_ecb_encrypt -#define AES_DONE aes_done -#define AES_TEST aes_test -#endif - -const struct ltc_prng_descriptor fortuna_desc = { - "fortuna", - 64, - &fortuna_start, - &fortuna_add_entropy, - &fortuna_ready, - &fortuna_read, - &fortuna_done, - &fortuna_export, - &fortuna_import, - &fortuna_test -}; - -/* update the IV */ -static void s_fortuna_update_iv(prng_state *prng) -{ - int x; - unsigned char *IV; - /* update IV */ - IV = prng->u.fortuna.IV; - for (x = 0; x < 16; x++) { - IV[x] = (IV[x] + 1) & 255; - if (IV[x] != 0) break; - } -} - -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED -/* get the current time in 100ms steps */ -static ulong64 s_fortuna_current_time(void) -{ - ulong64 cur_time; -#if defined(_WIN32) - FILETIME CurrentTime; - ULARGE_INTEGER ul; - GetSystemTimeAsFileTime(&CurrentTime); - ul.LowPart = CurrentTime.dwLowDateTime; - ul.HighPart = CurrentTime.dwHighDateTime; - cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */ - cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */ - cur_time /= 10; /* 100ns intervals > microseconds */ -#elif defined(LTC_CLOCK_GETTIME) - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - cur_time = (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */ -#else - struct timeval tv; - gettimeofday(&tv, NULL); - cur_time = (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */ -#endif - return cur_time / 100; -} -#endif - -/* reseed the PRNG */ -static int s_fortuna_reseed(prng_state *prng) -{ - unsigned char tmp[MAXBLOCKSIZE]; - hash_state md; - ulong64 reset_cnt; - int err, x; - -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED - ulong64 now = s_fortuna_current_time(); - if (now == prng->u.fortuna.wd) { - return CRYPT_OK; - } -#else - if (++prng->u.fortuna.wd < LTC_FORTUNA_WD) { - return CRYPT_OK; - } -#endif - - /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ - sha256_init(&md); - if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { - sha256_done(&md, tmp); - return err; - } - - reset_cnt = prng->u.fortuna.reset_cnt + 1; - - for (x = 0; x < LTC_FORTUNA_POOLS; x++) { - if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) { - /* terminate this hash */ - if ((err = sha256_done(&prng->u.fortuna.pool[x], tmp)) != CRYPT_OK) { - sha256_done(&md, tmp); - return err; - } - /* add it to the string */ - if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { - sha256_done(&md, tmp); - return err; - } - /* reset this pool */ - if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { - sha256_done(&md, tmp); - return err; - } - } else { - break; - } - } - - /* finish key */ - if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { - return err; - } - if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { - return err; - } - s_fortuna_update_iv(prng); - - /* reset/update internals */ - prng->u.fortuna.pool0_len = 0; -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED - prng->u.fortuna.wd = now; -#else - prng->u.fortuna.wd = 0; -#endif - prng->u.fortuna.reset_cnt = reset_cnt; - - -#ifdef LTC_CLEAN_STACK - zeromem(&md, sizeof(md)); - zeromem(tmp, sizeof(tmp)); -#endif - - return CRYPT_OK; -} - -/** - "Update Seed File"-compliant update of K - - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - unsigned char tmp[MAXBLOCKSIZE]; - hash_state md; - - LTC_MUTEX_LOCK(&prng->lock); - /* new K = LTC_SHA256(K || in) */ - sha256_init(&md); - if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { - sha256_done(&md, tmp); - goto LBL_UNLOCK; - } - if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) { - sha256_done(&md, tmp); - goto LBL_UNLOCK; - } - /* finish key */ - if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - s_fortuna_update_iv(prng); - -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); -#ifdef LTC_CLEAN_STACK - zeromem(&md, sizeof(md)); -#endif - - return err; -} - -/** - Start the PRNG - @param prng [out] The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int fortuna_start(prng_state *prng) -{ - int err, x, y; - unsigned char tmp[MAXBLOCKSIZE]; - - LTC_ARGCHK(prng != NULL); - prng->ready = 0; - - /* initialize the pools */ - for (x = 0; x < LTC_FORTUNA_POOLS; x++) { - if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { - for (y = 0; y < x; y++) { - sha256_done(&prng->u.fortuna.pool[y], tmp); - } - return err; - } - } - prng->u.fortuna.pool_idx = prng->u.fortuna.pool0_len = 0; - prng->u.fortuna.reset_cnt = prng->u.fortuna.wd = 0; - - /* reset bufs */ - zeromem(prng->u.fortuna.K, 32); - if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { - for (x = 0; x < LTC_FORTUNA_POOLS; x++) { - sha256_done(&prng->u.fortuna.pool[x], tmp); - } - return err; - } - zeromem(prng->u.fortuna.IV, 16); - - LTC_MUTEX_INIT(&prng->lock) - - return CRYPT_OK; -} - -static int s_fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - unsigned char tmp[2]; - int err; - - /* ensure inlen <= 32 */ - if (inlen > 32) { - inlen = 32; - } - - /* add s || length(in) || in to pool[pool_idx] */ - tmp[0] = (unsigned char)source; - tmp[1] = (unsigned char)inlen; - - if ((err = sha256_process(&prng->u.fortuna.pool[pool], tmp, 2)) != CRYPT_OK) { - return err; - } - if ((err = sha256_process(&prng->u.fortuna.pool[pool], in, inlen)) != CRYPT_OK) { - return err; - } - if (pool == 0) { - prng->u.fortuna.pool0_len += inlen; - } - return CRYPT_OK; /* success */ -} - -/** - Add random event to the PRNG state as proposed by the original paper. - @param source The source this random event comes from (0 .. 255) - @param pool The pool where to add the data to (0 .. LTC_FORTUNA_POOLS) - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - LTC_ARGCHK(source <= 255); - LTC_ARGCHK(pool < LTC_FORTUNA_POOLS); - - LTC_MUTEX_LOCK(&prng->lock); - - err = s_fortuna_add(source, pool, in, inlen, prng); - - LTC_MUTEX_UNLOCK(&prng->lock); - - return err; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - LTC_MUTEX_LOCK(&prng->lock); - - err = s_fortuna_add(0, prng->u.fortuna.pool_idx, in, inlen, prng); - - if (err == CRYPT_OK) { - ++(prng->u.fortuna.pool_idx); - prng->u.fortuna.pool_idx %= LTC_FORTUNA_POOLS; - } - - LTC_MUTEX_UNLOCK(&prng->lock); - - return err; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int fortuna_ready(prng_state *prng) -{ - int err; - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - /* make sure the reseed doesn't fail because - * of the chosen rate limit */ -#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED - prng->u.fortuna.wd = s_fortuna_current_time() - 1; -#else - prng->u.fortuna.wd = LTC_FORTUNA_WD; -#endif - err = s_fortuna_reseed(prng); - prng->ready = (err == CRYPT_OK) ? 1 : 0; - - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - unsigned char tmp[16]; - unsigned long tlen = 0; - - if (outlen == 0 || prng == NULL || out == NULL) return 0; - - LTC_MUTEX_LOCK(&prng->lock); - - if (!prng->ready) { - goto LBL_UNLOCK; - } - - /* do we have to reseed? */ - if (prng->u.fortuna.pool0_len >= 64) { - if (s_fortuna_reseed(prng) != CRYPT_OK) { - goto LBL_UNLOCK; - } - } - - /* ensure that one reseed happened before allowing to read */ - if (prng->u.fortuna.reset_cnt == 0) { - goto LBL_UNLOCK; - } - - /* now generate the blocks required */ - tlen = outlen; - - /* handle whole blocks without the extra XMEMCPY */ - while (outlen >= 16) { - /* encrypt the IV and store it */ - AES_ENC(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); - out += 16; - outlen -= 16; - s_fortuna_update_iv(prng); - } - - /* left over bytes? */ - if (outlen > 0) { - AES_ENC(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); - XMEMCPY(out, tmp, outlen); - s_fortuna_update_iv(prng); - } - - /* generate new key */ - AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); - s_fortuna_update_iv(prng); - - AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); - s_fortuna_update_iv(prng); - - if (AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { - tlen = 0; - } - -LBL_UNLOCK: -#ifdef LTC_CLEAN_STACK - zeromem(tmp, sizeof(tmp)); -#endif - LTC_MUTEX_UNLOCK(&prng->lock); - return tlen; -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int fortuna_done(prng_state *prng) -{ - int err, x; - unsigned char tmp[32]; - - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - prng->ready = 0; - - /* terminate all the hashes */ - for (x = 0; x < LTC_FORTUNA_POOLS; x++) { - if ((err = sha256_done(&(prng->u.fortuna.pool[x]), tmp)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - } - /* call cipher done when we invent one ;-) */ - err = CRYPT_OK; /* success */ - -LBL_UNLOCK: -#ifdef LTC_CLEAN_STACK - zeromem(tmp, sizeof(tmp)); -#endif - LTC_MUTEX_UNLOCK(&prng->lock); - LTC_MUTEX_DESTROY(&prng->lock); - return err; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -LTC_PRNG_EXPORT(fortuna) - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(prng != NULL); - - if (inlen < (unsigned long)fortuna_desc.export_size) { - return CRYPT_INVALID_ARG; - } - - if ((err = fortuna_start(prng)) != CRYPT_OK) { - return err; - } - - if ((err = fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) { - return err; - } - - return err; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int fortuna_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - int err; - - if ((err = sha256_test()) != CRYPT_OK) { - return err; - } - return AES_TEST(); -#endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/prngs/rc4.c b/Sources/DataLiteC/libtomcrypt/prngs/rc4.c deleted file mode 100644 index edcd73f..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/rc4.c +++ /dev/null @@ -1,221 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file prngs/rc4.c - RC4 PRNG, Tom St Denis -*/ - -#ifdef LTC_RC4 - -const struct ltc_prng_descriptor rc4_desc = -{ - "rc4", - 32, - &rc4_start, - &rc4_add_entropy, - &rc4_ready, - &rc4_read, - &rc4_done, - &rc4_export, - &rc4_import, - &rc4_test -}; - -/** - Start the PRNG - @param prng [out] The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int rc4_start(prng_state *prng) -{ - LTC_ARGCHK(prng != NULL); - prng->ready = 0; - /* set entropy (key) size to zero */ - prng->u.rc4.s.x = 0; - /* clear entropy (key) buffer */ - XMEMSET(&prng->u.rc4.s.buf, 0, sizeof(prng->u.rc4.s.buf)); - LTC_MUTEX_INIT(&prng->lock) - return CRYPT_OK; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - unsigned char buf[256]; - unsigned long i; - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { - /* rc4_ready() was already called, do "rekey" operation */ - if ((err = rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; - for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; - /* initialize RC4 */ - if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; - /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ - for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); - zeromem(buf, sizeof(buf)); - } - else { - /* rc4_ready() was not called yet, add entropy to the buffer */ - while (inlen--) prng->u.rc4.s.buf[prng->u.rc4.s.x++ % sizeof(prng->u.rc4.s.buf)] ^= *in++; - } - err = CRYPT_OK; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int rc4_ready(prng_state *prng) -{ - unsigned char buf[256] = { 0 }; - unsigned long len; - int err, i; - - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } - XMEMCPY(buf, prng->u.rc4.s.buf, sizeof(buf)); - /* initialize RC4 */ - len = MIN(prng->u.rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */ - if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK; - /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ - for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); - prng->ready = 1; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - if (outlen == 0 || prng == NULL || out == NULL) return 0; - LTC_MUTEX_LOCK(&prng->lock); - if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } - if (rc4_stream_keystream(&prng->u.rc4.s, out, outlen) != CRYPT_OK) outlen = 0; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return outlen; -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int rc4_done(prng_state *prng) -{ - int err; - LTC_ARGCHK(prng != NULL); - LTC_MUTEX_LOCK(&prng->lock); - prng->ready = 0; - err = rc4_stream_done(&prng->u.rc4.s); - LTC_MUTEX_UNLOCK(&prng->lock); - LTC_MUTEX_DESTROY(&prng->lock); - return err; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -LTC_PRNG_EXPORT(rc4) - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG; - - if ((err = rc4_start(prng)) != CRYPT_OK) return err; - if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int rc4_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - prng_state st; - unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; - unsigned char dmp[500]; - unsigned long dmplen = sizeof(dmp); - unsigned char out[1000]; - unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 }; - unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A }; - unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 }; - int err; - - if ((err = rc4_start(&st)) != CRYPT_OK) return err; - /* add entropy to uninitialized prng */ - if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if ((err = rc4_ready(&st)) != CRYPT_OK) return err; - if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; - if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - /* add entropy to already initialized prng */ - if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; - if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; - if ((err = rc4_done(&st)) != CRYPT_OK) return err; - if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err; - if ((err = rc4_ready(&st)) != CRYPT_OK) return err; - if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; - if ((err = rc4_done(&st)) != CRYPT_OK) return err; - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/prngs/rng_get_bytes.c b/Sources/DataLiteC/libtomcrypt/prngs/rng_get_bytes.c deleted file mode 100644 index 3a501f0..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/rng_get_bytes.c +++ /dev/null @@ -1,173 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_RNG_GET_BYTES -/** - @file rng_get_bytes.c - portable way to get secure random bits to feed a PRNG (Tom St Denis) -*/ - -#if defined(LTC_DEVRANDOM) && !defined(_WIN32) -/* on *NIX read /dev/random */ -static unsigned long s_rng_nix(unsigned char *buf, unsigned long len, - void (*callback)(void)) -{ -#ifdef LTC_NO_FILE - LTC_UNUSED_PARAM(callback); - LTC_UNUSED_PARAM(buf); - LTC_UNUSED_PARAM(len); - return 0; -#else - FILE *f; - unsigned long x; - LTC_UNUSED_PARAM(callback); -#ifdef LTC_TRY_URANDOM_FIRST - f = fopen("/dev/urandom", "rb"); - if (f == NULL) { - f = fopen("/dev/random", "rb"); - } -#else - f = fopen("/dev/random", "rb"); -#endif /* LTC_TRY_URANDOM_FIRST */ - - if (f == NULL) { - return 0; - } - - /* disable buffering */ - if (setvbuf(f, NULL, _IONBF, 0) != 0) { - fclose(f); - return 0; - } - - x = (unsigned long)fread(buf, 1, (size_t)len, f); - fclose(f); - return x; -#endif /* LTC_NO_FILE */ -} - -#endif /* LTC_DEVRANDOM */ - -#if !defined(_WIN32_WCE) - -#define ANSI_RNG - -static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len, - void (*callback)(void)) -{ - clock_t t1; - int l, acc, bits, a, b; - - l = len; - bits = 8; - acc = a = b = 0; - while (len--) { - if (callback != NULL) callback(); - while (bits--) { - do { - t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; - t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; - } while (a == b); - acc = (acc << 1) | a; - } - *buf++ = acc; - acc = 0; - bits = 8; - } - return l; -} - -#endif - -/* Try the Microsoft CSP */ -#if defined(_WIN32) || defined(_WIN32_WCE) -#if defined(LTC_WIN32_BCRYPT) - -#include -#include -#pragma comment(lib, "bcrypt.lib") - -static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, - void (*callback)(void)) -{ - LTC_UNUSED_PARAM(callback); - - return BCRYPT_SUCCESS(BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) ? len : 0; -} - -#else - -#ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 -#endif -#ifndef WINVER - #define WINVER 0x0501 -#endif - -#define WIN32_LEAN_AND_MEAN -#include -#include - -static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, - void (*callback)(void)) -{ - static HCRYPTPROV hProv = 0; - LTC_UNUSED_PARAM(callback); - - if (hProv == 0) { - HCRYPTPROV h = 0; - if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, - (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && - !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { - return 0; - } - hProv = h; - } - - return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0; -} -#endif /* Old WIN32 versions */ -#endif /* WIN32 */ - -/** - Read the system RNG - @param out Destination - @param outlen Length desired (octets) - @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL - @return Number of octets read -*/ -unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, - void (*callback)(void)) -{ - unsigned long x; - - LTC_ARGCHK(out != NULL); - -#ifdef LTC_PRNG_ENABLE_LTC_RNG - if (ltc_rng) { - x = ltc_rng(out, outlen, callback); - if (x != 0) { - return x; - } - } -#endif - -#if defined(_WIN32) || defined(_WIN32_WCE) - x = s_rng_win32(out, outlen, callback); if (x != 0) { return x; } -#elif defined(LTC_DEVRANDOM) - x = s_rng_nix(out, outlen, callback); if (x != 0) { return x; } -#endif -#ifdef ANSI_RNG - x = s_rng_ansic(out, outlen, callback); if (x != 0) { return x; } -#endif - return 0; -} -#endif /* #ifdef LTC_RNG_GET_BYTES */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/prngs/rng_make_prng.c b/Sources/DataLiteC/libtomcrypt/prngs/rng_make_prng.c deleted file mode 100644 index a7b726c..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/rng_make_prng.c +++ /dev/null @@ -1,81 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -#ifdef LTC_RNG_MAKE_PRNG -/** - @file rng_make_prng.c - portable way to get secure random bits to feed a PRNG (Tom St Denis) -*/ - -/** - Create a PRNG from a RNG - - In case you pass bits as '-1' the PRNG will be setup - as if the export/import functionality has been used, - but the imported data comes directly from the RNG. - - @param bits Number of bits of entropy desired (-1 or 64 ... 1024) - @param wprng Index of which PRNG to setup - @param prng [out] PRNG state to initialize - @param callback A pointer to a void function for when the RNG is slow, this can be NULL - @return CRYPT_OK if successful -*/ -int rng_make_prng(int bits, int wprng, prng_state *prng, - void (*callback)(void)) -{ - unsigned char* buf; - unsigned long bytes; - int err; - - LTC_ARGCHK(prng != NULL); - - /* check parameter */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if (bits == -1) { - bytes = prng_descriptor[wprng].export_size; - } else if (bits < 64 || bits > 1024) { - return CRYPT_INVALID_PRNGSIZE; - } else { - bytes = (unsigned long)((bits+7)/8) * 2; - } - - if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { - return err; - } - - buf = XMALLOC(bytes); - if (buf == NULL) { - return CRYPT_MEM; - } - - if (rng_get_bytes(buf, bytes, callback) != bytes) { - err = CRYPT_ERROR_READPRNG; - goto LBL_ERR; - } - - if (bits == -1) { - if ((err = prng_descriptor[wprng].pimport(buf, bytes, prng)) != CRYPT_OK) { - goto LBL_ERR; - } - } else { - if ((err = prng_descriptor[wprng].add_entropy(buf, bytes, prng)) != CRYPT_OK) { - goto LBL_ERR; - } - } - if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { - goto LBL_ERR; - } - -LBL_ERR: - #ifdef LTC_CLEAN_STACK - zeromem(buf, bytes); - #endif - XFREE(buf); - return err; -} -#endif /* #ifdef LTC_RNG_MAKE_PRNG */ - diff --git a/Sources/DataLiteC/libtomcrypt/prngs/sober128.c b/Sources/DataLiteC/libtomcrypt/prngs/sober128.c deleted file mode 100644 index 6454578..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/sober128.c +++ /dev/null @@ -1,220 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -/** - @file prngs/sober128.c - Implementation of SOBER-128 by Tom St Denis. - Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. -*/ - -#ifdef LTC_SOBER128 - -const struct ltc_prng_descriptor sober128_desc = -{ - "sober128", - 40, - &sober128_start, - &sober128_add_entropy, - &sober128_ready, - &sober128_read, - &sober128_done, - &sober128_export, - &sober128_import, - &sober128_test -}; - -/** - Start the PRNG - @param prng [out] The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int sober128_start(prng_state *prng) -{ - LTC_ARGCHK(prng != NULL); - prng->ready = 0; - XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); - prng->u.sober128.idx = 0; - LTC_MUTEX_INIT(&prng->lock) - return CRYPT_OK; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - unsigned char buf[40]; - unsigned long i; - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { - /* sober128_ready() was already called, do "rekey" operation */ - if ((err = sober128_stream_keystream(&prng->u.sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; - for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; - /* key 32 bytes, 20 rounds */ - if ((err = sober128_stream_setup(&prng->u.sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK; - /* iv 8 bytes */ - if ((err = sober128_stream_setiv(&prng->u.sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; - /* clear KEY + IV */ - zeromem(buf, sizeof(buf)); - } - else { - /* sober128_ready() was not called yet, add entropy to ent buffer */ - while (inlen--) prng->u.sober128.ent[prng->u.sober128.idx++ % sizeof(prng->u.sober128.ent)] ^= *in++; - } - err = CRYPT_OK; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int sober128_ready(prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } - /* key 32 bytes, 20 rounds */ - if ((err = sober128_stream_setup(&prng->u.sober128.s, prng->u.sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK; - /* iv 8 bytes */ - if ((err = sober128_stream_setiv(&prng->u.sober128.s, prng->u.sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; - XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); - prng->u.sober128.idx = 0; - prng->ready = 1; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - if (outlen == 0 || prng == NULL || out == NULL) return 0; - LTC_MUTEX_LOCK(&prng->lock); - if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } - if (sober128_stream_keystream(&prng->u.sober128.s, out, outlen) != CRYPT_OK) outlen = 0; -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return outlen; -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int sober128_done(prng_state *prng) -{ - int err; - LTC_ARGCHK(prng != NULL); - LTC_MUTEX_LOCK(&prng->lock); - prng->ready = 0; - err = sober128_stream_done(&prng->u.sober128.s); - LTC_MUTEX_UNLOCK(&prng->lock); - LTC_MUTEX_DESTROY(&prng->lock); - return err; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -LTC_PRNG_EXPORT(sober128) - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG; - - if ((err = sober128_start(prng)) != CRYPT_OK) return err; - if ((err = sober128_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int sober128_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - prng_state st; - unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; - unsigned char dmp[300]; - unsigned long dmplen = sizeof(dmp); - unsigned char out[500]; - unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A }; - unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 }; - unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 }; - int err; - - if ((err = sober128_start(&st)) != CRYPT_OK) return err; - /* add entropy to uninitialized prng */ - if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if ((err = sober128_ready(&st)) != CRYPT_OK) return err; - if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; - if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - /* add entropy to already initialized prng */ - if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; - if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; - if ((err = sober128_done(&st)) != CRYPT_OK) return err; - if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err; - if ((err = sober128_ready(&st)) != CRYPT_OK) return err; - if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ - if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; - if ((err = sober128_done(&st)) != CRYPT_OK) return err; - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/prngs/sprng.c b/Sources/DataLiteC/libtomcrypt/prngs/sprng.c deleted file mode 100644 index e404718..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/sprng.c +++ /dev/null @@ -1,152 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file sprng.c - Secure PRNG, Tom St Denis -*/ - -/* A secure PRNG using the RNG functions. Basically this is a - * wrapper that allows you to use a secure RNG as a PRNG - * in the various other functions. - */ - -#ifdef LTC_SPRNG - -const struct ltc_prng_descriptor sprng_desc = -{ - "sprng", 0, - &sprng_start, - &sprng_add_entropy, - &sprng_ready, - &sprng_read, - &sprng_done, - &sprng_export, - &sprng_import, - &sprng_test -}; - -/** - Start the PRNG - @param prng [out] The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int sprng_start(prng_state *prng) -{ - LTC_UNUSED_PARAM(prng); - return CRYPT_OK; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - LTC_UNUSED_PARAM(in); - LTC_UNUSED_PARAM(inlen); - LTC_UNUSED_PARAM(prng); - return CRYPT_OK; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int sprng_ready(prng_state *prng) -{ - LTC_UNUSED_PARAM(prng); - return CRYPT_OK; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - LTC_ARGCHK(out != NULL); - LTC_UNUSED_PARAM(prng); - return rng_get_bytes(out, outlen, NULL); -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int sprng_done(prng_state *prng) -{ - LTC_UNUSED_PARAM(prng); - return CRYPT_OK; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -/* NOLINTNEXTLINE(readability-non-const-parameter) - silence clang-tidy warning */ -int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) -{ - LTC_ARGCHK(outlen != NULL); - LTC_UNUSED_PARAM(out); - LTC_UNUSED_PARAM(prng); - - *outlen = 0; - return CRYPT_OK; -} - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - LTC_UNUSED_PARAM(in); - LTC_UNUSED_PARAM(inlen); - LTC_UNUSED_PARAM(prng); - return CRYPT_OK; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int sprng_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - prng_state st; - unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 }; - unsigned char out[1000]; - int err; - - if ((err = sprng_start(&st)) != CRYPT_OK) return err; - if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; - if ((err = sprng_ready(&st)) != CRYPT_OK) return err; - if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ - if ((err = sprng_done(&st)) != CRYPT_OK) return err; - - return CRYPT_OK; -#endif -} - -#endif - - - diff --git a/Sources/DataLiteC/libtomcrypt/prngs/yarrow.c b/Sources/DataLiteC/libtomcrypt/prngs/yarrow.c deleted file mode 100644 index 40cb46a..0000000 --- a/Sources/DataLiteC/libtomcrypt/prngs/yarrow.c +++ /dev/null @@ -1,323 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file yarrow.c - Yarrow PRNG, Tom St Denis -*/ - -#ifdef LTC_YARROW - -const struct ltc_prng_descriptor yarrow_desc = -{ - "yarrow", 64, - &yarrow_start, - &yarrow_add_entropy, - &yarrow_ready, - &yarrow_read, - &yarrow_done, - &yarrow_export, - &yarrow_import, - &yarrow_test -}; - -/** - Start the PRNG - @param prng [out] The PRNG state to initialize - @return CRYPT_OK if successful -*/ -int yarrow_start(prng_state *prng) -{ - int err; - - LTC_ARGCHK(prng != NULL); - prng->ready = 0; - - /* these are the default hash/cipher combo used */ -#ifdef LTC_RIJNDAEL -#if LTC_YARROW_AES==0 - prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc); -#elif LTC_YARROW_AES==1 - prng->u.yarrow.cipher = register_cipher(&aes_enc_desc); -#elif LTC_YARROW_AES==2 - prng->u.yarrow.cipher = register_cipher(&rijndael_desc); -#elif LTC_YARROW_AES==3 - prng->u.yarrow.cipher = register_cipher(&aes_desc); -#endif -#elif defined(LTC_BLOWFISH) - prng->u.yarrow.cipher = register_cipher(&blowfish_desc); -#elif defined(LTC_TWOFISH) - prng->u.yarrow.cipher = register_cipher(&twofish_desc); -#elif defined(LTC_RC6) - prng->u.yarrow.cipher = register_cipher(&rc6_desc); -#elif defined(LTC_RC5) - prng->u.yarrow.cipher = register_cipher(&rc5_desc); -#elif defined(LTC_SAFERP) - prng->u.yarrow.cipher = register_cipher(&saferp_desc); -#elif defined(LTC_RC2) - prng->u.yarrow.cipher = register_cipher(&rc2_desc); -#elif defined(LTC_NOEKEON) - prng->u.yarrow.cipher = register_cipher(&noekeon_desc); -#elif defined(LTC_ANUBIS) - prng->u.yarrow.cipher = register_cipher(&anubis_desc); -#elif defined(LTC_KSEED) - prng->u.yarrow.cipher = register_cipher(&kseed_desc); -#elif defined(LTC_KHAZAD) - prng->u.yarrow.cipher = register_cipher(&khazad_desc); -#elif defined(LTC_CAST5) - prng->u.yarrow.cipher = register_cipher(&cast5_desc); -#elif defined(LTC_XTEA) - prng->u.yarrow.cipher = register_cipher(&xtea_desc); -#elif defined(LTC_SAFER) - prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc); -#elif defined(LTC_DES) - prng->u.yarrow.cipher = register_cipher(&des3_desc); -#else - #error LTC_YARROW needs at least one CIPHER -#endif - if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { - return err; - } - -#ifdef LTC_SHA256 - prng->u.yarrow.hash = register_hash(&sha256_desc); -#elif defined(LTC_SHA512) - prng->u.yarrow.hash = register_hash(&sha512_desc); -#elif defined(LTC_TIGER) - prng->u.yarrow.hash = register_hash(&tiger_desc); -#elif defined(LTC_SHA1) - prng->u.yarrow.hash = register_hash(&sha1_desc); -#elif defined(LTC_RIPEMD320) - prng->u.yarrow.hash = register_hash(&rmd320_desc); -#elif defined(LTC_RIPEMD256) - prng->u.yarrow.hash = register_hash(&rmd256_desc); -#elif defined(LTC_RIPEMD160) - prng->u.yarrow.hash = register_hash(&rmd160_desc); -#elif defined(LTC_RIPEMD128) - prng->u.yarrow.hash = register_hash(&rmd128_desc); -#elif defined(LTC_MD5) - prng->u.yarrow.hash = register_hash(&md5_desc); -#elif defined(LTC_MD4) - prng->u.yarrow.hash = register_hash(&md4_desc); -#elif defined(LTC_MD2) - prng->u.yarrow.hash = register_hash(&md2_desc); -#elif defined(LTC_WHIRLPOOL) - prng->u.yarrow.hash = register_hash(&whirlpool_desc); -#else - #error LTC_YARROW needs at least one HASH -#endif - if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { - return err; - } - - /* zero the memory used */ - zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool)); - LTC_MUTEX_INIT(&prng->lock) - - return CRYPT_OK; -} - -/** - Add entropy to the PRNG state - @param in The data to add - @param inlen Length of the data to add - @param prng PRNG state to update - @return CRYPT_OK if successful -*/ -int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - hash_state md; - int err; - - LTC_ARGCHK(prng != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen > 0); - - LTC_MUTEX_LOCK(&prng->lock); - - if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - /* start the hash */ - if ((err = hash_descriptor[prng->u.yarrow.hash].init(&md)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - /* hash the current pool */ - if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, prng->u.yarrow.pool, - hash_descriptor[prng->u.yarrow.hash].hashsize)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - /* add the new entropy */ - if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - /* store result */ - err = hash_descriptor[prng->u.yarrow.hash].done(&md, prng->u.yarrow.pool); - -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Make the PRNG ready to read from - @param prng The PRNG to make active - @return CRYPT_OK if successful -*/ -int yarrow_ready(prng_state *prng) -{ - int ks, err; - - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - - if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - /* setup CTR mode using the "pool" as the key */ - ks = (int)hash_descriptor[prng->u.yarrow.hash].hashsize; - if ((err = cipher_descriptor[prng->u.yarrow.cipher].keysize(&ks)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - - if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */ - prng->u.yarrow.pool, /* IV */ - prng->u.yarrow.pool, ks, /* KEY and key size */ - 0, /* number of rounds */ - CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ - &prng->u.yarrow.ctr)) != CRYPT_OK) { - goto LBL_UNLOCK; - } - prng->ready = 1; - -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return err; -} - -/** - Read from the PRNG - @param out Destination - @param outlen Length of output - @param prng The active PRNG to read from - @return Number of octets read -*/ -unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) -{ - if (outlen == 0 || prng == NULL || out == NULL) return 0; - - LTC_MUTEX_LOCK(&prng->lock); - - if (!prng->ready) { - outlen = 0; - goto LBL_UNLOCK; - } - - /* put out in predictable state first */ - zeromem(out, outlen); - - /* now randomize it */ - if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) { - outlen = 0; - } - -LBL_UNLOCK: - LTC_MUTEX_UNLOCK(&prng->lock); - return outlen; -} - -/** - Terminate the PRNG - @param prng The PRNG to terminate - @return CRYPT_OK if successful -*/ -int yarrow_done(prng_state *prng) -{ - int err; - LTC_ARGCHK(prng != NULL); - - LTC_MUTEX_LOCK(&prng->lock); - prng->ready = 0; - - /* call cipher done when we invent one ;-) */ - - /* we invented one */ - err = ctr_done(&prng->u.yarrow.ctr); - - LTC_MUTEX_UNLOCK(&prng->lock); - LTC_MUTEX_DESTROY(&prng->lock); - return err; -} - -/** - Export the PRNG state - @param out [out] Destination - @param outlen [in/out] Max size and resulting size of the state - @param prng The PRNG to export - @return CRYPT_OK if successful -*/ -LTC_PRNG_EXPORT(yarrow) - -/** - Import a PRNG state - @param in The PRNG state - @param inlen Size of the state - @param prng The PRNG to import - @return CRYPT_OK if successful -*/ -int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) -{ - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(prng != NULL); - if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; - - if ((err = yarrow_start(prng)) != CRYPT_OK) return err; - if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; - return CRYPT_OK; -} - -/** - PRNG self-test - @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled -*/ -int yarrow_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - int err; - prng_state prng; - - if ((err = yarrow_start(&prng)) != CRYPT_OK) { - return err; - } - - /* now let's test the hash/cipher that was chosen */ - if (cipher_descriptor[prng.u.yarrow.cipher].test && - ((err = cipher_descriptor[prng.u.yarrow.cipher].test()) != CRYPT_OK)) { - return err; - } - if (hash_descriptor[prng.u.yarrow.hash].test && - ((err = hash_descriptor[prng.u.yarrow.hash].test()) != CRYPT_OK)) { - return err; - } - - return CRYPT_OK; -#endif -} - -#endif - diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_crypt.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_crypt.c deleted file mode 100644 index 91500f8..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_crypt.c +++ /dev/null @@ -1,93 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -#define QUARTERROUND(a,b,c,d) \ - x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \ - x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \ - x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \ - x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7); - -static void s_chacha_block(unsigned char *output, const ulong32 *input, int rounds) -{ - ulong32 x[16]; - int i; - XMEMCPY(x, input, sizeof(x)); - for (i = rounds; i > 0; i -= 2) { - QUARTERROUND(0, 4, 8,12) - QUARTERROUND(1, 5, 9,13) - QUARTERROUND(2, 6,10,14) - QUARTERROUND(3, 7,11,15) - QUARTERROUND(0, 5,10,15) - QUARTERROUND(1, 6,11,12) - QUARTERROUND(2, 7, 8,13) - QUARTERROUND(3, 4, 9,14) - } - for (i = 0; i < 16; ++i) { - x[i] += input[i]; - STORE32L(x[i], output + 4 * i); - } -} - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha - @param st The ChaCha state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char buf[64]; - unsigned long i, j; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(st->ivlen != 0); - - if (st->ksleft > 0) { - j = MIN(st->ksleft, inlen); - for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; - inlen -= j; - if (inlen == 0) return CRYPT_OK; - out += j; - in += j; - } - for (;;) { - s_chacha_block(buf, st->input, st->rounds); - if (st->ivlen == 8) { - /* IV-64bit, increment 64bit counter */ - if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; - } - else { - /* IV-96bit, increment 32bit counter */ - if (0 == ++st->input[12]) return CRYPT_OVERFLOW; - } - if (inlen <= 64) { - for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; - st->ksleft = 64 - inlen; - for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; - return CRYPT_OK; - } - for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; - inlen -= 64; - out += 64; - in += 64; - } -} - -#undef QUARTERROUND - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_done.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_done.c deleted file mode 100644 index 1dc641e..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_done.c +++ /dev/null @@ -1,20 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -/** - Terminate and clear ChaCha state - @param st The ChaCha state - @return CRYPT_OK on success -*/ -int chacha_done(chacha_state *st) -{ - LTC_ARGCHK(st != NULL); - zeromem(st, sizeof(chacha_state)); - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr32.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr32.c deleted file mode 100644 index 08416f5..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr32.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -/** - Set IV + counter data to the ChaCha state - @param st The ChaCha20 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 12) - @param counter 32bit (unsigned) initial counter value - @return CRYPT_OK on success - */ -int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - /* 96bit IV + 32bit counter */ - LTC_ARGCHK(ivlen == 12); - - st->input[12] = counter; - LOAD32L(st->input[13], iv + 0); - LOAD32L(st->input[14], iv + 4); - LOAD32L(st->input[15], iv + 8); - st->ksleft = 0; - st->ivlen = ivlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr64.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr64.c deleted file mode 100644 index 49c5459..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_ivctr64.c +++ /dev/null @@ -1,37 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -/** - Set IV + counter data to the ChaCha state - @param st The ChaCha20 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 8) - @param counter 64bit (unsigned) initial counter value - @return CRYPT_OK on success - */ -int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - /* 64bit IV + 64bit counter */ - LTC_ARGCHK(ivlen == 8); - - st->input[12] = (ulong32)(counter & 0xFFFFFFFF); - st->input[13] = (ulong32)(counter >> 32); - LOAD32L(st->input[14], iv + 0); - LOAD32L(st->input[15], iv + 4); - st->ksleft = 0; - st->ivlen = ivlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_keystream.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_keystream.c deleted file mode 100644 index b7fe688..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_keystream.c +++ /dev/null @@ -1,28 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -/** - Generate a stream of random bytes via ChaCha - @param st The ChaCha20 state - @param out [out] The output buffer - @param outlen The output length - @return CRYPT_OK on success - */ -int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return chacha_crypt(st, out, outlen, out); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_memory.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_memory.c deleted file mode 100644 index 0326469..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_memory.c +++ /dev/null @@ -1,57 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_CHACHA - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha - @param key The key - @param keylen The key length - @param rounds The number of rounds - @param iv The initial vector - @param ivlen The initial vector length - @param counter initial counter value, either ignored, 32- or 64-bit, depending on ivlen - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *iv, unsigned long ivlen, ulong64 counter, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout) -{ - chacha_state st; - int err; - const unsigned char *iv_ = iv; - unsigned long ivlen_ = ivlen; - ulong64 counter_ = counter; - - if (ivlen == 16) { - LOAD64L(counter_, iv); - iv_ += 8; - ivlen_ -=8; - } - - LTC_ARGCHK(ivlen_ <= 8 || counter_ < CONST64(4294967296)); /* 2**32 */ - - if ((err = chacha_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; - if (ivlen_ > 8) { - if ((err = chacha_ivctr32(&st, iv_, ivlen_, (ulong32)counter_)) != CRYPT_OK) goto WIPE_KEY; - } else { - if ((err = chacha_ivctr64(&st, iv_, ivlen_, counter_)) != CRYPT_OK) goto WIPE_KEY; - } - err = chacha_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - chacha_done(&st); - return err; -} - -#endif /* LTC_CHACHA */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_setup.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_setup.c deleted file mode 100644 index b04e0ea..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_setup.c +++ /dev/null @@ -1,56 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -/** - Initialize an ChaCha context (only the key) - @param st [out] The destination of the ChaCha state - @param key The secret key - @param keylen The length of the secret key (octets) - @param rounds Number of rounds (e.g. 20 for ChaCha20) - @return CRYPT_OK if successful -*/ -int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds) -{ - const char * const sigma = "expand 32-byte k"; - const char * const tau = "expand 16-byte k"; - const char *constants; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen == 32 || keylen == 16); - - if (rounds == 0) rounds = 20; - - LOAD32L(st->input[4], key + 0); - LOAD32L(st->input[5], key + 4); - LOAD32L(st->input[6], key + 8); - LOAD32L(st->input[7], key + 12); - if (keylen == 32) { /* 256bit */ - key += 16; - constants = sigma; - } else { /* 128bit */ - constants = tau; - } - LOAD32L(st->input[8], key + 0); - LOAD32L(st->input[9], key + 4); - LOAD32L(st->input[10], key + 8); - LOAD32L(st->input[11], key + 12); - LOAD32L(st->input[0], constants + 0); - LOAD32L(st->input[1], constants + 4); - LOAD32L(st->input[2], constants + 8); - LOAD32L(st->input[3], constants + 12); - st->rounds = rounds; /* e.g. 20 for chacha20 */ - st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */ - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_test.c b/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_test.c deleted file mode 100644 index cdd5f4f..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/chacha/chacha_test.c +++ /dev/null @@ -1,74 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_CHACHA - -int chacha_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned long len; - unsigned char out[1000]; - /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */ - unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 }; - unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81, - 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B, - 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57, - 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8, - 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E, - 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36, - 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42, - 0x87, 0x4D }; - char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; - chacha_state st; - int err; - - len = XSTRLEN(pt); - - /* crypt piece by piece - using chacha_ivctr32() */ - if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; - if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt, 35, out )) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35, out + 35)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt + 70, 5, out + 70)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt + 75, 5, out + 75)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in one go - using chacha_ivctr32() */ - if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; - if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in one go - using chacha_ivctr64() */ - if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; - if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK) return err; - if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in a single call using 32-bit counter with a value of 1 */ - if ((err = chacha_memory(k, sizeof(k), 20, - n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in a single call using 64-bit counter with a value of 1 */ - if ((err = chacha_memory(k, sizeof(k), 20, - n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit.c b/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit.c deleted file mode 100644 index 4633b15..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit.c +++ /dev/null @@ -1,453 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/****************************************************************************** - * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission - * and should run on any conforming C implementation (C90 or later). - * - * This implementation supports any key length up to 128 bits (16 bytes) and - * works in increments of 8-bit bytes. Keys must be submitted as whole bytes - * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv - * may be any length up to 8 bytes and will be padded out to 8 bytes. - * - * The eSTREAM submission was rather picky about the calling sequence of - * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed - * calling ECRYPT_process_blocks() multiple times for a multiple of whole - * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls - * were supported correctly. This implementation handles the keystream - * differently and rabbit_crypt() may be called as many times as desired, - * crypting any number of bytes each time. - * - * http://www.ecrypt.eu.org/stream/e2-rabbit.html - * - * NB: One of the test vectors distributed by the eSTREAM site in the file - * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" - * in that ZIP file, the 3rd line in "out1" should be - * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". - * - * Here is the original legal notice accompanying the Rabbit submission - * to the EU eSTREAM competition. - *--------------------------------------------------------------------------- - * Copyright (C) Cryptico A/S. All rights reserved. - * - * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. - * - * This software is developed by Cryptico A/S and/or its suppliers. - * All title and intellectual property rights in and to the software, - * including but not limited to patent rights and copyrights, are owned - * by Cryptico A/S and/or its suppliers. - * - * The software may be used solely for non-commercial purposes - * without the prior written consent of Cryptico A/S. For further - * information on licensing terms and conditions please contact - * Cryptico A/S at info@cryptico.com - * - * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" - * are either trademarks or registered trademarks of Cryptico A/S. - * - * Cryptico A/S shall not in any way be liable for any use of this - * software. The software is provided "as is" without any express or - * implied warranty. - *--------------------------------------------------------------------------- - * On October 6, 2008, Rabbit was "released into the public domain and - * may be used freely for any purpose." - * http://www.ecrypt.eu.org/stream/rabbitpf.html - * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 - ******************************************************************************/ - - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_RABBIT - -/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ -static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x); -static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance); -static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out); - -/* -------------------------------------------------------------------------- */ - -/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ -/* the upper 32 bits XOR the lower 32 bits */ -static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x) -{ - ulong32 a, b, h, l; - - /* Construct high and low argument for squaring */ - a = x & 0xFFFF; - b = x >> 16; - - /* Calculate high and low result of squaring */ - h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; - l = x * x; - - /* Return high XOR low */ - return (ulong32)(h^l); -} - -/* -------------------------------------------------------------------------- */ - -/* Calculate the next internal state */ -static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance) -{ - ulong32 g[8], c_old[8], i; - - /* Save old counter values */ - for (i=0; i<8; i++) { - c_old[i] = p_instance->c[i]; - } - - /* Calculate new counter values */ - p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); - p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); - p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); - p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); - p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); - p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); - p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); - p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); - p_instance->carry = (p_instance->c[7] < c_old[7]); - - /* Calculate the g-values */ - for (i=0;i<8;i++) { - g[i] = ss_rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); - } - - /* Calculate new state values */ - p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); - p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); - p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); - p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); - p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); - p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); - p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); - p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); -} - -/* ------------------------------------------------------------------------- */ - -static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out) -{ - ulong32 *ptr; - - /* Iterate the work context once */ - ss_rabbit_next_state(&(st->work_ctx)); - - /* Generate 16 bytes of pseudo-random data */ - ptr = (ulong32*)&(st->work_ctx.x); - STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); - STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); - STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); - STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); -} - -/* -------------------------------------------------------------------------- */ - -/* Key setup */ -int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) -{ - ulong32 k0, k1, k2, k3, i; - unsigned char tmpkey[16] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen <= 16); - - /* init state */ - XMEMSET(st, 0, sizeof(rabbit_state)); - - /* pad key in tmpkey */ - XMEMCPY(tmpkey, key, keylen); - - /* Generate four subkeys */ - LOAD32L(k0, tmpkey+ 0); - LOAD32L(k1, tmpkey+ 4); - LOAD32L(k2, tmpkey+ 8); - LOAD32L(k3, tmpkey+12); - -#ifdef LTC_CLEAN_STACK - /* done with tmpkey, wipe it */ - zeromem(tmpkey, sizeof(tmpkey)); -#endif - - /* Generate initial state variables */ - st->master_ctx.x[0] = k0; - st->master_ctx.x[2] = k1; - st->master_ctx.x[4] = k2; - st->master_ctx.x[6] = k3; - st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); - st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); - st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); - st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); - - /* Generate initial counter values */ - st->master_ctx.c[0] = ROLc(k2, 16); - st->master_ctx.c[2] = ROLc(k3, 16); - st->master_ctx.c[4] = ROLc(k0, 16); - st->master_ctx.c[6] = ROLc(k1, 16); - st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); - st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); - st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); - st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); - - /* Clear carry bit */ - st->master_ctx.carry = 0; - - /* Iterate the master context four times */ - for (i=0; i<4; i++) { - ss_rabbit_next_state(&(st->master_ctx)); - } - - /* Modify the counters */ - for (i=0; i<8; i++) { - st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; - } - - /* Copy master instance to work instance */ - for (i=0; i<8; i++) { - st->work_ctx.x[i] = st->master_ctx.x[i]; - st->work_ctx.c[i] = st->master_ctx.c[i]; - } - st->work_ctx.carry = st->master_ctx.carry; - /* ...and prepare block for crypt() */ - XMEMSET(&(st->block), 0, sizeof(st->block)); - st->unused = 0; - - return CRYPT_OK; -} - -/* -------------------------------------------------------------------------- */ - -/* IV setup */ -int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) -{ - ulong32 i0, i1, i2, i3, i; - unsigned char tmpiv[8] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL || ivlen == 0); - LTC_ARGCHK(ivlen <= 8); - - /* pad iv in tmpiv */ - if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); - - /* Generate four subvectors */ - LOAD32L(i0, tmpiv+0); - LOAD32L(i2, tmpiv+4); - i1 = (i0>>16) | (i2&0xFFFF0000); - i3 = (i2<<16) | (i0&0x0000FFFF); - - /* Modify counter values */ - st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; - st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; - st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; - st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; - st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; - st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; - st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; - st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; - - /* Copy state variables */ - for (i=0; i<8; i++) { - st->work_ctx.x[i] = st->master_ctx.x[i]; - } - st->work_ctx.carry = st->master_ctx.carry; - - /* Iterate the work context four times */ - for (i=0; i<4; i++) { - ss_rabbit_next_state(&(st->work_ctx)); - } - - /* reset keystream buffer and unused count */ - XMEMSET(&(st->block), 0, sizeof(st->block)); - st->unused = 0; - - return CRYPT_OK; -} - -/* ------------------------------------------------------------------------- */ - -/* Crypt a chunk of any size (encrypt/decrypt) */ -int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char buf[16]; - unsigned long i, j; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - if (st->unused > 0) { - j = MIN(st->unused, inlen); - for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; - inlen -= j; - if (inlen == 0) return CRYPT_OK; - out += j; - in += j; - } - for (;;) { - /* gen a block for buf */ - ss_rabbit_gen_1_block(st, buf); - if (inlen <= 16) { - /* XOR and send to out */ - for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; - st->unused = 16 - inlen; - /* copy remainder to block */ - for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; - return CRYPT_OK; - } - /* XOR entire buf and send to out */ - for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; - inlen -= 16; - out += 16; - in += 16; - } -} - -/* ------------------------------------------------------------------------- */ - -int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(out != NULL); - - XMEMSET(out, 0, outlen); - return rabbit_crypt(st, out, outlen, out); -} - -/* -------------------------------------------------------------------------- */ - -int rabbit_done(rabbit_state *st) -{ - LTC_ARGCHK(st != NULL); - - zeromem(st, sizeof(rabbit_state)); - return CRYPT_OK; -} - -/* -------------------------------------------------------------------------- */ - -int rabbit_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - rabbit_state st; - int err; - unsigned char out[1000] = { 0 }; - { - /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: - http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log - */ - - /* --- Test 1 (generate whole blocks) --------------------------------- */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[64] = { 0 }; - unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, - 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, - 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, - 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, - 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, - 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, - 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, - 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; - unsigned long ptlen = sizeof(pt); - - /* crypt 64 nulls */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - /* --- Test 2 (generate unusual number of bytes each time) ------------ */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[39] = { 0 }; - unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, - 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, - 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, - 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, - 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; - unsigned long ptlen = sizeof(pt); - - /* crypt piece by piece (hit at least one 16-byte boundary) */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - /* --- Test 3 (use non-null data) ------------------------------------- */ - - { - unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, - 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; - unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; - char pt[] = "Kilroy was here, there, and everywhere!"; - unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, - 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, - 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, - 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, - 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; - unsigned long ptlen = XSTRLEN(pt); - unsigned char out2[1000] = { 0 }; - unsigned char nulls[1000] = { 0 }; - - /* crypt piece by piece */ - if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* --- Test 4 (crypt in a single call) ------------------------------------ */ - - if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), - (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; - if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; - /* use 'out' (ciphertext) in the next decryption test */ - - /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ - - /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ - if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; - if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* --- Test 6 (wipe state, incl key) ---------------------------------- */ - - if ((err = rabbit_done(&st)) != CRYPT_OK) return err; - if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; - - } - - return CRYPT_OK; - } -#endif -} - -/* -------------------------------------------------------------------------- */ - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit_memory.c b/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit_memory.c deleted file mode 100644 index fee0234..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/rabbit/rabbit_memory.c +++ /dev/null @@ -1,40 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * chacha-ref.c version 20080118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_RABBIT - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Rabbit - @param key The key - @param keylen The key length - @param iv The initial vector - @param ivlen The initial vector length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int rabbit_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout) -{ - rabbit_state st; - int err; - - if ((err = rabbit_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; - if ((err = rabbit_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; - err = rabbit_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - rabbit_done(&st); - return err; -} - -#endif /* LTC_RABBIT */ diff --git a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream.c b/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream.c deleted file mode 100644 index 2587764..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream.c +++ /dev/null @@ -1,101 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_RC4_STREAM - -/** - Initialize an RC4 context (only the key) - @param st [out] The destination of the RC4 state - @param key The secret key - @param keylen The length of the secret key (8 - 256 bytes) - @return CRYPT_OK if successful -*/ -int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) -{ - unsigned char tmp, *s; - int x, y; - unsigned long j; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ - - s = st->buf; - for (x = 0; x < 256; x++) { - s[x] = x; - } - - for (j = x = y = 0; x < 256; x++) { - y = (y + s[x] + key[j++]) & 255; - if (j == keylen) { - j = 0; - } - tmp = s[x]; s[x] = s[y]; s[y] = tmp; - } - st->x = 0; - st->y = 0; - - return CRYPT_OK; -} - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 - @param st The RC4 state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char x, y, *s, tmp; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - x = st->x; - y = st->y; - s = st->buf; - while (inlen--) { - x = (x + 1) & 255; - y = (y + s[x]) & 255; - tmp = s[x]; s[x] = s[y]; s[y] = tmp; - tmp = (s[x] + s[y]) & 255; - *out++ = *in++ ^ s[tmp]; - } - st->x = x; - st->y = y; - return CRYPT_OK; -} - -/** - Generate a stream of random bytes via RC4 - @param st The RC420 state - @param out [out] The output buffer - @param outlen The output length - @return CRYPT_OK on success - */ -int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return rc4_stream_crypt(st, out, outlen, out); -} - -/** - Terminate and clear RC4 state - @param st The RC4 state - @return CRYPT_OK on success -*/ -int rc4_stream_done(rc4_state *st) -{ - LTC_ARGCHK(st != NULL); - zeromem(st, sizeof(rc4_state)); - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream_memory.c b/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream_memory.c deleted file mode 100644 index efe4888..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_stream_memory.c +++ /dev/null @@ -1,31 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_RC4_STREAM - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 - @param key The key - @param keylen The key length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int rc4_stream_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout) -{ - rc4_state st; - int err; - - if ((err = rc4_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; - err = rc4_stream_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - rc4_stream_done(&st); - return err; -} - -#endif /* LTC_RC4_STREAM */ diff --git a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_test.c b/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_test.c deleted file mode 100644 index d78022b..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/rc4/rc4_test.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_RC4_STREAM - -int rc4_stream_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - rc4_state st; - int err; - const unsigned char key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; - const unsigned char pt[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; - const unsigned char ct[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }; - unsigned char buf[10]; - - if ((err = rc4_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; - if ((err = rc4_stream_crypt(&st, pt, sizeof(pt), buf)) != CRYPT_OK) return err; - if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV1", 0)) return CRYPT_FAIL_TESTVECTOR; - if ((err = rc4_stream_done(&st)) != CRYPT_OK) return err; - - /* crypt in a single call */ - if ((err = rc4_stream_memory(key, sizeof(key), pt, sizeof(pt), buf)) != CRYPT_OK) return err; - if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV2", 0)) return CRYPT_FAIL_TESTVECTOR; - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_crypt.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_crypt.c deleted file mode 100644 index e076d69..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_crypt.c +++ /dev/null @@ -1,88 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -#define QUARTERROUND(a,b,c,d) \ - x[b] ^= (ROL((x[a] + x[d]), 7)); \ - x[c] ^= (ROL((x[b] + x[a]), 9)); \ - x[d] ^= (ROL((x[c] + x[b]), 13)); \ - x[a] ^= (ROL((x[d] + x[c]), 18)); - -static void s_salsa20_block(unsigned char *output, const ulong32 *input, int rounds) -{ - ulong32 x[16]; - int i; - XMEMCPY(x, input, sizeof(x)); - for (i = rounds; i > 0; i -= 2) { - QUARTERROUND( 0, 4, 8,12) - QUARTERROUND( 5, 9,13, 1) - QUARTERROUND(10,14, 2, 6) - QUARTERROUND(15, 3, 7,11) - QUARTERROUND( 0, 1, 2, 3) - QUARTERROUND( 5, 6, 7, 4) - QUARTERROUND(10,11, 8, 9) - QUARTERROUND(15,12,13,14) - } - for (i = 0; i < 16; ++i) { - x[i] += input[i]; - STORE32L(x[i], output + 4 * i); - } -} - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 - @param st The Salsa20 state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - unsigned char buf[64]; - unsigned long i, j; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24); - - if (st->ksleft > 0) { - j = MIN(st->ksleft, inlen); - for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; - inlen -= j; - if (inlen == 0) return CRYPT_OK; - out += j; - in += j; - } - for (;;) { - s_salsa20_block(buf, st->input, st->rounds); - /* Salsa20: 64-bit IV, increment 64-bit counter */ - if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW; - if (inlen <= 64) { - for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; - st->ksleft = 64 - inlen; - for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; - return CRYPT_OK; - } - for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; - inlen -= 64; - out += 64; - in += 64; - } -} - -#undef QUARTERROUND - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_done.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_done.c deleted file mode 100644 index 9b8cbb6..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_done.c +++ /dev/null @@ -1,20 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -/** - Terminate and clear Salsa20 state - @param st The Salsa20 state - @return CRYPT_OK on success -*/ -int salsa20_done(salsa20_state *st) -{ - LTC_ARGCHK(st != NULL); - zeromem(st, sizeof(salsa20_state)); - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_ivctr64.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_ivctr64.c deleted file mode 100644 index 8b25dfb..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_ivctr64.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -/** - Set IV + counter data to the Salsa20 state - @param st The Salsa20 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 8) - @param counter 64bit (unsigned) initial counter value - @return CRYPT_OK on success - */ -int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - /* Salsa20: 64-bit IV (nonce) + 64-bit counter */ - LTC_ARGCHK(ivlen == 8); - - LOAD32L(st->input[6], iv + 0); - LOAD32L(st->input[7], iv + 4); - st->input[8] = (ulong32)(counter & 0xFFFFFFFF); - st->input[9] = (ulong32)(counter >> 32); - st->ksleft = 0; - st->ivlen = ivlen; - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_keystream.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_keystream.c deleted file mode 100644 index c51d0d6..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_keystream.c +++ /dev/null @@ -1,29 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -/** - Generate a stream of random bytes via Salsa20 - @param st The Salsa20 state - @param out [out] The output buffer - @param outlen The output length - @return CRYPT_OK on success - */ -int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return salsa20_crypt(st, out, outlen, out); -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_memory.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_memory.c deleted file mode 100644 index 4737f88..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_memory.c +++ /dev/null @@ -1,41 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_SALSA20 - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 - @param key The key - @param keylen The key length - @param iv The initial vector - @param ivlen The initial vector length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param rounds The number of rounds - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *iv, unsigned long ivlen, ulong64 counter, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout) -{ - salsa20_state st; - int err; - - if ((err = salsa20_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; - if ((err = salsa20_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; - err = salsa20_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - salsa20_done(&st); - return err; -} - -#endif /* LTC_SALSA20 */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_setup.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_setup.c deleted file mode 100644 index e7c9f2d..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_setup.c +++ /dev/null @@ -1,58 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -/** - Initialize an Salsa20 context (only the key) - @param st [out] The destination of the Salsa20 state - @param key The secret key - @param keylen The length of the secret key (octets) - @param rounds Number of rounds (e.g. 20 for Salsa20) - @return CRYPT_OK if successful -*/ -int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds) -{ - const char * const sigma = "expand 32-byte k"; - const char * const tau = "expand 16-byte k"; - const char *constants; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen == 32 || keylen == 16); - - if (rounds == 0) rounds = 20; - LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ - - LOAD32L(st->input[1], key + 0); - LOAD32L(st->input[2], key + 4); - LOAD32L(st->input[3], key + 8); - LOAD32L(st->input[4], key + 12); - if (keylen == 32) { /* 256bit */ - key += 16; - constants = sigma; - } else { /* 128bit */ - constants = tau; - } - LOAD32L(st->input[11], key + 0); - LOAD32L(st->input[12], key + 4); - LOAD32L(st->input[13], key + 8); - LOAD32L(st->input[14], key + 12); - LOAD32L(st->input[ 0], constants + 0); - LOAD32L(st->input[ 5], constants + 4); - LOAD32L(st->input[10], constants + 8); - LOAD32L(st->input[15], constants + 12); - st->rounds = rounds; /* default is 20 for salsa20 */ - st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */ - return CRYPT_OK; -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_test.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_test.c deleted file mode 100644 index c924dbe..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/salsa20_test.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SALSA20 - -int salsa20_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - salsa20_state st; - unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a }; - unsigned char ct[] = { 0x37, 0x37, 0x2e, 0x60, 0xb8, 0xae, 0x88, 0x1f, 0xf8, 0xdf, 0x00, 0x26, 0x6c, 0x30, 0x34, 0x2d, - 0xa1, 0xd7, 0x79, 0x60, 0x67, 0x72, 0xe0, 0x67, 0x26, 0x22, 0xad, 0x00, 0x9e, 0xd5, 0x59, 0x44, - 0x51, 0xd9, 0xe6, 0xaa, 0xc9, 0x59, 0x9e, 0x60, 0xff, 0x87, 0x90, 0xc1, 0xc9, 0x1e }; - unsigned char ct2[] = { 0xec, 0x06, 0x32, 0xb3, 0x83, 0x5c, 0xae, 0x91, 0x01, 0x82, 0x7a, 0x71, 0xd9, 0x7d, 0x45, 0xd7, - 0xa6, 0x5b, 0xa0, 0x89, 0x9d, 0xd2, 0x6c, 0xaa, 0xbb, 0x2f, 0x5f, 0x30, 0x89, 0x54, 0xff, 0x3e, - 0x83, 0xc3, 0x34, 0x10, 0xb6, 0xe1, 0xab, 0xe7, 0xf5, 0xab, 0xab, 0xed, 0xa4, 0xff }; - char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ - unsigned long len; - unsigned char out[1000]; - int counter; - int rounds; - int err; - len = XSTRLEN(pt); - - /* crypt piece by piece */ - counter = 0; - rounds = 12; - if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; - if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "SALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in one go - using salsa20_ivctr64() */ - counter = 0; - rounds = 20; - if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; - if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in a single call */ - if ((err = salsa20_memory(k, sizeof(k), rounds, n, sizeof(n), counter, - (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - - { - /* keystream - * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup - * Set 6, vector 0 - */ - unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, - 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; - unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE }; - unsigned char ct3[] = { 0xF5, 0xFA, 0xD5, 0x3F, 0x79, 0xF9, 0xDF, 0x58, 0xC4, 0xAE, 0xA0, 0xD0, 0xED, 0x9A, 0x96, 0x01, - 0xF2, 0x78, 0x11, 0x2C, 0xA7, 0x18, 0x0D, 0x56, 0x5B, 0x42, 0x0A, 0x48, 0x01, 0x96, 0x70, 0xEA, - 0xF2, 0x4C, 0xE4, 0x93, 0xA8, 0x62, 0x63, 0xF6, 0x77, 0xB4, 0x6A, 0xCE, 0x19, 0x24, 0x77, 0x3D, - 0x2B, 0xB2, 0x55, 0x71, 0xE1, 0xAA, 0x85, 0x93, 0x75, 0x8F, 0xC3, 0x82, 0xB1, 0x28, 0x0B, 0x71 }; - int counter3 = 0; - int rounds3 = 20; - if ((err = salsa20_setup(&st, k3, sizeof(k3), rounds3)) != CRYPT_OK) return err; - if ((err = salsa20_ivctr64(&st, n3, sizeof(n3), counter3)) != CRYPT_OK) return err; - if ((err = salsa20_keystream(&st, out, 64)) != CRYPT_OK) return err; - if ((err = salsa20_done(&st)) != CRYPT_OK) return err; - if (compare_testvector(out, 64, ct3, sizeof(ct3), "SALSA20-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_memory.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_memory.c deleted file mode 100644 index c02f905..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_memory.c +++ /dev/null @@ -1,40 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_XSALSA20 - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with XSalsa20 - @param key The key - @param keylen The key length - @param nonce The initial vector - @param noncelen The initial vector length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param rounds The number of rounds - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *datain, unsigned long datalen, unsigned char *dataout) -{ - salsa20_state st; - int err; - - if ((err = xsalsa20_setup(&st, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY; - err = salsa20_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - salsa20_done(&st); - return err; -} - -#endif /* LTC_XSALSA20 */ - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_setup.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_setup.c deleted file mode 100644 index c764a89..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_setup.c +++ /dev/null @@ -1,126 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt.h" - -#ifdef LTC_XSALSA20 - -#define QUARTERROUND(a,b,c,d) \ - x[b] ^= (ROL((x[a] + x[d]), 7)); \ - x[c] ^= (ROL((x[b] + x[a]), 9)); \ - x[d] ^= (ROL((x[c] + x[b]), 13)); \ - x[a] ^= (ROL((x[d] + x[c]), 18)); - -/* use modified salsa20 doubleround (no final addition as in salsa20) */ -static void s_xsalsa20_doubleround(ulong32 *x, int rounds) -{ - int i; - - for (i = rounds; i > 0; i -= 2) { - /* columnround */ - QUARTERROUND( 0, 4, 8,12) - QUARTERROUND( 5, 9,13, 1) - QUARTERROUND(10,14, 2, 6) - QUARTERROUND(15, 3, 7,11) - /* rowround */ - QUARTERROUND( 0, 1, 2, 3) - QUARTERROUND( 5, 6, 7, 4) - QUARTERROUND(10,11, 8, 9) - QUARTERROUND(15,12,13,14) - } -} - -#undef QUARTERROUND - -/** - Initialize an XSalsa20 context - @param st [out] The destination of the XSalsa20 state - @param key The secret key - @param keylen The length of the secret key, must be 32 (octets) - @param nonce The nonce - @param noncelen The length of the nonce, must be 24 (octets) - @param rounds Number of rounds (must be evenly divisible by 2, default is 20) - @return CRYPT_OK if successful -*/ -int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - int rounds) -{ - const char * const constants = "expand 32-byte k"; - const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */ - ulong32 x[64]; /* input to & output fm doubleround */ - unsigned char subkey[32]; - int i; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen == 32); - LTC_ARGCHK(nonce != NULL); - LTC_ARGCHK(noncelen == 24); - if (rounds == 0) rounds = 20; - LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ - - /* load the state to "hash" the key */ - LOAD32L(x[ 0], constants + 0); - LOAD32L(x[ 5], constants + 4); - LOAD32L(x[10], constants + 8); - LOAD32L(x[15], constants + 12); - LOAD32L(x[ 1], key + 0); - LOAD32L(x[ 2], key + 4); - LOAD32L(x[ 3], key + 8); - LOAD32L(x[ 4], key + 12); - LOAD32L(x[11], key + 16); - LOAD32L(x[12], key + 20); - LOAD32L(x[13], key + 24); - LOAD32L(x[14], key + 28); - LOAD32L(x[ 6], nonce + 0); - LOAD32L(x[ 7], nonce + 4); - LOAD32L(x[ 8], nonce + 8); - LOAD32L(x[ 9], nonce + 12); - - /* use modified salsa20 doubleround (no final addition) */ - s_xsalsa20_doubleround(x, rounds); - - /* extract the subkey */ - for (i = 0; i < 8; ++i) { - STORE32L(x[sti[i]], subkey + 4 * i); - } - - /* load the final initial state */ - LOAD32L(st->input[ 0], constants + 0); - LOAD32L(st->input[ 5], constants + 4); - LOAD32L(st->input[10], constants + 8); - LOAD32L(st->input[15], constants + 12); - LOAD32L(st->input[ 1], subkey + 0); - LOAD32L(st->input[ 2], subkey + 4); - LOAD32L(st->input[ 3], subkey + 8); - LOAD32L(st->input[ 4], subkey + 12); - LOAD32L(st->input[11], subkey + 16); - LOAD32L(st->input[12], subkey + 20); - LOAD32L(st->input[13], subkey + 24); - LOAD32L(st->input[14], subkey + 28); - LOAD32L(st->input[ 6], &(nonce[16]) + 0); - LOAD32L(st->input[ 7], &(nonce[16]) + 4); - st->input[ 8] = 0; - st->input[ 9] = 0; - st->rounds = rounds; - st->ksleft = 0; - st->ivlen = 24; /* set switch to say nonce/IV has been loaded */ - -#ifdef LTC_CLEAN_STACK - zeromem(x, sizeof(x)); - zeromem(subkey, sizeof(subkey)); -#endif - - return CRYPT_OK; -} - - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_test.c b/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_test.c deleted file mode 100644 index 31522fe..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/salsa20/xsalsa20_test.c +++ /dev/null @@ -1,90 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* The implementation is based on: - * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf - * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf - * and salsa20-ref.c version 20051118 - * Public domain from D. J. Bernstein - */ - -#include "tomcrypt.h" - -#ifdef LTC_XSALSA20 - -#if defined(LTC_SHA256) && defined(LTC_TEST) -static int s_sha256(unsigned char *hash, const unsigned char *data, const int datalen) { - hash_state md; - sha256_init(&md); - sha256_process(&md, data, datalen); - sha256_done(&md, hash); - return CRYPT_OK; -} -#endif - -int xsalsa20_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - - /*************************************************************************** - * verify a round trip: - */ - { - const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; - const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; - const void *msg = "Kilroy was here!"; - unsigned char msglen = 17; /* includes trailing NULL */ - int rounds = 20; - unsigned char ciphertext[17]; - unsigned char msg2[17]; - salsa20_state st; - int err; - - if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, msg, msglen, ciphertext)) != CRYPT_OK) return err; - if ((err = salsa20_done(&st)) != CRYPT_OK) return err; - - if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; - if ((err = salsa20_crypt(&st, ciphertext, msglen, msg2)) != CRYPT_OK) return err; - if ((err = salsa20_done(&st)) != CRYPT_OK) return err; - - if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - - - /* round trip with two single function calls */ - if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), msg, msglen, ciphertext)) != CRYPT_OK) return err; - if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), ciphertext, msglen, msg2)) != CRYPT_OK) return err; - if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - } - -#ifdef LTC_SHA256 - /*************************************************************************** - * verify correct generation of a keystream - */ - { - const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; - const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; - const unsigned char expecthash[] = {0x6a,0x60,0x57,0x65,0x27,0xe0,0x00,0x51,0x6d,0xb0,0xda,0x60,0x46,0x20,0xf6,0xd0,0x95,0x65,0x45,0x39,0xf4,0x86,0x83,0x43,0x64,0xdf,0xd9,0x5a,0x6f,0x3f,0xbe,0xb7}; - int rounds = 20; - unsigned char keystream[91101]; - unsigned long keystreamlen = 91101; - unsigned char hash[32]; - salsa20_state st; - int err; - - if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; - if ((err = salsa20_keystream(&st, keystream, keystreamlen)) != CRYPT_OK) return err; - if ((err = salsa20_done(&st)) != CRYPT_OK) return err; - if ((err = s_sha256(hash, keystream, keystreamlen)) != CRYPT_OK) return err; - if (compare_testvector(hash, sizeof(hash), expecthash, sizeof(expecthash), "XSALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - } -#endif - - return CRYPT_OK; - -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream.c b/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream.c deleted file mode 100644 index ab1a7aa..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream.c +++ /dev/null @@ -1,347 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ -#include "tomcrypt_private.h" - -/** - @file sober128_stream.c - Implementation of SOBER-128 by Tom St Denis. - Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. -*/ - -#ifdef LTC_SOBER128 - -#ifndef LTC_SOBER128TAB_C -#define LTC_SOBER128TAB_C -#include "sober128tab.c" -#endif - -/* don't change these... */ -#define N 17 -#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ -#define KEYP 15 /* where to insert key words */ -#define FOLDP 4 /* where to insert non-linear feedback */ - -static ulong32 BYTE2WORD(const unsigned char *b) -{ - ulong32 t; - LOAD32L(t, b); - return t; -} - -static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) -{ - ulong32 t; - LOAD32L(t, in); - t ^= w; - STORE32L(t, out); -} - -/* give correct offset for the current position of the register, - * where logically R[0] is at position "zero". - */ -#define OFF(zero, i) (((zero)+(i)) % N) - -/* step the LFSR */ -/* After stepping, "zero" moves right one place */ -#define STEP(R,z) \ - R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; - -static void cycle(ulong32 *R) -{ - ulong32 t; - int i; - - STEP(R,0); - t = R[0]; - for (i = 1; i < N; ++i) { - R[i-1] = R[i]; - } - R[N-1] = t; -} - -/* Return a non-linear function of some parts of the register. - */ -#define NLFUNC(st,z) \ -{ \ - t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ - t ^= Sbox[(t >> 24) & 0xFF]; \ - t = RORc(t, 8); \ - t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ - t ^= Sbox[(t >> 24) & 0xFF]; \ - t = t + st->R[OFF(z,13)]; \ -} - -static ulong32 nltap(const sober128_state *st) -{ - ulong32 t; - NLFUNC(st, 0); - return t; -} - -/* Save the current register state - */ -static void s128_savestate(sober128_state *st) -{ - int i; - for (i = 0; i < N; ++i) { - st->initR[i] = st->R[i]; - } -} - -/* initialise to previously saved register state - */ -static void s128_reloadstate(sober128_state *st) -{ - int i; - - for (i = 0; i < N; ++i) { - st->R[i] = st->initR[i]; - } -} - -/* Initialise "konst" - */ -static void s128_genkonst(sober128_state *st) -{ - ulong32 newkonst; - - do { - cycle(st->R); - newkonst = nltap(st); - } while ((newkonst & 0xFF000000) == 0); - st->konst = newkonst; -} - -/* Load key material into the register - */ -#define ADDKEY(k) \ - st->R[KEYP] += (k); - -#define XORNL(nl) \ - st->R[FOLDP] ^= (nl); - -/* nonlinear diffusion of register for key */ -#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; -static void s128_diffuse(sober128_state *st) -{ - ulong32 t; - /* relies on FOLD == N == 17! */ - DROUND(0); - DROUND(1); - DROUND(2); - DROUND(3); - DROUND(4); - DROUND(5); - DROUND(6); - DROUND(7); - DROUND(8); - DROUND(9); - DROUND(10); - DROUND(11); - DROUND(12); - DROUND(13); - DROUND(14); - DROUND(15); - DROUND(16); -} - -/** - Initialize an Sober128 context (only the key) - @param st [out] The destination of the Sober128 state - @param key The secret key - @param keylen The length of the secret key (octets) - @return CRYPT_OK if successful -*/ -int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) -{ - ulong32 i, k; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen > 0); - - /* keylen must be multiple of 4 bytes */ - if ((keylen & 3) != 0) { - return CRYPT_INVALID_KEYSIZE; - } - - /* Register initialised to Fibonacci numbers */ - st->R[0] = 1; - st->R[1] = 1; - for (i = 2; i < N; ++i) { - st->R[i] = st->R[i-1] + st->R[i-2]; - } - st->konst = INITKONST; - - for (i = 0; i < keylen; i += 4) { - k = BYTE2WORD(&key[i]); - ADDKEY(k); - cycle(st->R); - XORNL(nltap(st)); - } - - /* also fold in the length of the key */ - ADDKEY(keylen); - - /* now diffuse */ - s128_diffuse(st); - s128_genkonst(st); - s128_savestate(st); - st->nbuf = 0; - - return CRYPT_OK; -} - -/** - Set IV to the Sober128 state - @param st The Sober12820 state - @param iv The IV data to add - @param ivlen The length of the IV (must be 12) - @return CRYPT_OK on success - */ -int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) -{ - ulong32 i, k; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(iv != NULL); - LTC_ARGCHK(ivlen > 0); - - /* ok we are adding an IV then... */ - s128_reloadstate(st); - - /* ivlen must be multiple of 4 bytes */ - if ((ivlen & 3) != 0) { - return CRYPT_INVALID_KEYSIZE; - } - - for (i = 0; i < ivlen; i += 4) { - k = BYTE2WORD(&iv[i]); - ADDKEY(k); - cycle(st->R); - XORNL(nltap(st)); - } - - /* also fold in the length of the key */ - ADDKEY(ivlen); - - /* now diffuse */ - s128_diffuse(st); - st->nbuf = 0; - - return CRYPT_OK; -} - -/* XOR pseudo-random bytes into buffer - */ -#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 - @param st The Sober128 state - @param in The plaintext (or ciphertext) - @param inlen The length of the input (octets) - @param out [out] The ciphertext (or plaintext), length inlen - @return CRYPT_OK if successful -*/ -int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - ulong32 t; - - if (inlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(st != NULL); - - /* handle any previously buffered bytes */ - while (st->nbuf != 0 && inlen != 0) { - *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); - st->sbuf >>= 8; - st->nbuf -= 8; - --inlen; - } - -#ifndef LTC_SMALL_CODE - /* do lots at a time, if there's enough to do */ - while (inlen >= N*4) { - SROUND(0); - SROUND(1); - SROUND(2); - SROUND(3); - SROUND(4); - SROUND(5); - SROUND(6); - SROUND(7); - SROUND(8); - SROUND(9); - SROUND(10); - SROUND(11); - SROUND(12); - SROUND(13); - SROUND(14); - SROUND(15); - SROUND(16); - out += 4*N; - in += 4*N; - inlen -= 4*N; - } -#endif - - /* do small or odd size buffers the slow way */ - while (4 <= inlen) { - cycle(st->R); - t = nltap(st); - XORWORD(t, in, out); - out += 4; - in += 4; - inlen -= 4; - } - - /* handle any trailing bytes */ - if (inlen != 0) { - cycle(st->R); - st->sbuf = nltap(st); - st->nbuf = 32; - while (st->nbuf != 0 && inlen != 0) { - *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); - st->sbuf >>= 8; - st->nbuf -= 8; - --inlen; - } - } - - return CRYPT_OK; -} - -int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return sober128_stream_crypt(st, out, outlen, out); -} - -/** - Terminate and clear Sober128 state - @param st The Sober128 state - @return CRYPT_OK on success -*/ -int sober128_stream_done(sober128_state *st) -{ - LTC_ARGCHK(st != NULL); - zeromem(st, sizeof(sober128_state)); - return CRYPT_OK; -} - -#undef N -#undef INITKONST -#undef KEYP -#undef FOLDP -#undef OFF -#undef STEP -#undef NLFUNC -#undef ADDKEY -#undef XORNL -#undef DROUND -#undef SROUND - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream_memory.c b/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream_memory.c deleted file mode 100644 index 5150b82..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_stream_memory.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SOBER128_STREAM - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with SOBER128 - @param key The key - @param keylen The key length - @param iv The initial vector - @param ivlen The initial vector length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int sober128_stream_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout) -{ - sober128_state st; - int err; - - if ((err = sober128_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; - if ((err = sober128_stream_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; - err = sober128_stream_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - sober128_stream_done(&st); - return err; -} - -#endif /* LTC_SOBER128_STREAM */ diff --git a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_test.c b/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_test.c deleted file mode 100644 index 52ea3a8..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128_test.c +++ /dev/null @@ -1,43 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SOBER128 - -int sober128_stream_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - unsigned char key[16] = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, - 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }; - unsigned char iv[4] = { 0x00, 0x00, 0x00, 0x00 }; - unsigned char out[20] = { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, - 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, - 0x40, 0x37, 0x8b, 0xbb }; - int err, len = 20; - unsigned char src[20], dst[20]; - sober128_state st; - - XMEMSET(src, 0, len); /* input */ - if ((err = sober128_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; - if ((err = sober128_stream_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; - if ((err = sober128_stream_crypt(&st, src, len, dst)) != CRYPT_OK) return err; - if ((err = sober128_stream_done(&st)) != CRYPT_OK) return err; - if (compare_testvector(dst, len, out, len, "SOBER-128-TV1", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - /* crypt in a single call */ - if ((err = sober128_stream_memory(key, sizeof(key), iv, sizeof(iv), - src, len, dst)) != CRYPT_OK) return err; - if (compare_testvector(dst, len, out, len, "SOBER-128-TV2", 0)) { - return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128tab.c b/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128tab.c deleted file mode 100644 index e067bb6..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sober128/sober128tab.c +++ /dev/null @@ -1,166 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/** - @file sober128tab.c - SOBER-128 Tables -*/ - -#ifdef LTC_SOBER128TAB_C - -/* $ID$ */ -/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ -/* Multiplication table for Turing using 0xD02B4367 */ -static const ulong32 Multab[256] = { - 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, - 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, - 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, - 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, - 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, - 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, - 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, - 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, - 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, - 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, - 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, - 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, - 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, - 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, - 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, - 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, - 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, - 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, - 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, - 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, - 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, - 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, - 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, - 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, - 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, - 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, - 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, - 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, - 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, - 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, - 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, - 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, - 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, - 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, - 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, - 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, - 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, - 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, - 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, - 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, - 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, - 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, - 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, - 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, - 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, - 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, - 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, - 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, - 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, - 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, - 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, - 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, - 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, - 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, - 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, - 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, - 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, - 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, - 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, - 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, - 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, - 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, - 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, - 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, -}; - -/* $ID$ */ -/* Sbox for SOBER-128 */ -/* - * This is really the combination of two SBoxes; the least significant - * 24 bits comes from: - * 8->32 Sbox generated by Millan et. al. at Queensland University of - * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, - * "On the Design of 8*32 S-boxes". Unpublished report, by the - * Information Systems Research Centre, - * Queensland University of Technology, 1999. - * - * The most significant 8 bits are the Skipjack "F table", which can be - * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . - * In this optimised table, though, the intent is to XOR the word from - * the table selected by the high byte with the input word. Thus, the - * high byte is actually the Skipjack F-table entry XORED with its - * table index. - */ -static const ulong32 Sbox[256] = { - 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, - 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, - 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, - 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, - 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, - 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, - 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, - 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, - 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, - 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, - 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, - 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, - 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, - 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, - 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, - 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, - 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, - 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, - 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, - 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, - 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, - 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, - 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, - 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, - 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, - 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, - 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, - 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, - 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, - 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, - 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, - 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, - 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, - 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, - 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, - 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, - 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, - 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, - 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, - 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, - 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, - 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, - 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, - 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, - 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, - 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, - 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, - 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, - 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, - 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, - 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, - 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, - 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, - 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, - 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, - 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, - 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, - 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, - 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, - 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, - 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, - 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, - 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, - 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, -}; - -#endif /* LTC_SOBER128TAB_C */ diff --git a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk.c b/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk.c deleted file mode 100644 index 0325701..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk.c +++ /dev/null @@ -1,813 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* - * This LTC implementation was adapted from: - * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html - */ - -/* - * SOSEMANUK reference implementation. - * - * This code is supposed to run on any conforming C implementation (C90 - * or later). - * - * (c) 2005 X-CRYPT project. This software is provided 'as-is', without - * any express or implied warranty. In no event will the authors be held - * liable for any damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to no restriction. - * - * Technical remarks and questions can be addressed to - * - */ - -#include "tomcrypt_private.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifdef LTC_SOSEMANUK - -/* ======================================================================== */ - -/* - * We want (and sometimes need) to perform explicit truncations to 32 bits. - */ -#define T32(x) ((x) & (ulong32)0xFFFFFFFF) - -/* - * Some of our functions will be tagged as "inline" to help the compiler - * optimize things. We use "inline" only if the compiler is advanced - * enough to understand it; C99 compilers, and pre-C99 versions of gcc, - * understand enough "inline" for our purposes. - */ - -/* ======================================================================== */ - -/* - * Serpent S-boxes, implemented in bitslice mode. These circuits have - * been published by Dag Arne Osvik ("Speeding up Serpent", published in - * the 3rd AES Candidate Conference) and work on five 32-bit registers: - * the four inputs, and a fifth scratch register. There are meant to be - * quite fast on Pentium-class processors. These are not the fastest - * published, but they are "fast enough" and they are unencumbered as - * far as intellectual property is concerned (note: these are rewritten - * from the article itself, and hence are not covered by the GPL on - * Dag's code, which was not used here). - * - * The output bits are permuted. Here is the correspondance: - * S0: 1420 - * S1: 2031 - * S2: 2314 - * S3: 1234 - * S4: 1403 - * S5: 1302 - * S6: 0142 - * S7: 4310 - * (for instance, the output of S0 is in "r1, r4, r2, r0"). - */ - -#define S0(r0, r1, r2, r3, r4) do { \ - r3 ^= r0; r4 = r1; \ - r1 &= r3; r4 ^= r2; \ - r1 ^= r0; r0 |= r3; \ - r0 ^= r4; r4 ^= r3; \ - r3 ^= r2; r2 |= r1; \ - r2 ^= r4; r4 = ~r4; \ - r4 |= r1; r1 ^= r3; \ - r1 ^= r4; r3 |= r0; \ - r1 ^= r3; r4 ^= r3; \ - } while (0) - -#define S1(r0, r1, r2, r3, r4) do { \ - r0 = ~r0; r2 = ~r2; \ - r4 = r0; r0 &= r1; \ - r2 ^= r0; r0 |= r3; \ - r3 ^= r2; r1 ^= r0; \ - r0 ^= r4; r4 |= r1; \ - r1 ^= r3; r2 |= r0; \ - r2 &= r4; r0 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; r0 &= r2; \ - r0 ^= r4; \ - } while (0) - -#define S2(r0, r1, r2, r3, r4) do { \ - r4 = r0; r0 &= r2; \ - r0 ^= r3; r2 ^= r1; \ - r2 ^= r0; r3 |= r4; \ - r3 ^= r1; r4 ^= r2; \ - r1 = r3; r3 |= r4; \ - r3 ^= r0; r0 &= r1; \ - r4 ^= r0; r1 ^= r3; \ - r1 ^= r4; r4 = ~r4; \ - } while (0) - -#define S3(r0, r1, r2, r3, r4) do { \ - r4 = r0; r0 |= r3; \ - r3 ^= r1; r1 &= r4; \ - r4 ^= r2; r2 ^= r3; \ - r3 &= r0; r4 |= r1; \ - r3 ^= r4; r0 ^= r1; \ - r4 &= r0; r1 ^= r3; \ - r4 ^= r2; r1 |= r0; \ - r1 ^= r2; r0 ^= r3; \ - r2 = r1; r1 |= r3; \ - r1 ^= r0; \ - } while (0) - -#define S4(r0, r1, r2, r3, r4) do { \ - r1 ^= r3; r3 = ~r3; \ - r2 ^= r3; r3 ^= r0; \ - r4 = r1; r1 &= r3; \ - r1 ^= r2; r4 ^= r3; \ - r0 ^= r4; r2 &= r4; \ - r2 ^= r0; r0 &= r1; \ - r3 ^= r0; r4 |= r1; \ - r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r2 &= r3; \ - r0 = ~r0; r4 ^= r2; \ - } while (0) - -#define S5(r0, r1, r2, r3, r4) do { \ - r0 ^= r1; r1 ^= r3; \ - r3 = ~r3; r4 = r1; \ - r1 &= r0; r2 ^= r3; \ - r1 ^= r2; r2 |= r4; \ - r4 ^= r3; r3 &= r1; \ - r3 ^= r0; r4 ^= r1; \ - r4 ^= r2; r2 ^= r0; \ - r0 &= r3; r2 = ~r2; \ - r0 ^= r4; r4 |= r3; \ - r2 ^= r4; \ - } while (0) - -#define S6(r0, r1, r2, r3, r4) do { \ - r2 = ~r2; r4 = r3; \ - r3 &= r0; r0 ^= r4; \ - r3 ^= r2; r2 |= r4; \ - r1 ^= r3; r2 ^= r0; \ - r0 |= r1; r2 ^= r1; \ - r4 ^= r0; r0 |= r3; \ - r0 ^= r2; r4 ^= r3; \ - r4 ^= r0; r3 = ~r3; \ - r2 &= r4; \ - r2 ^= r3; \ - } while (0) - -#define S7(r0, r1, r2, r3, r4) do { \ - r4 = r1; r1 |= r2; \ - r1 ^= r3; r4 ^= r2; \ - r2 ^= r1; r3 |= r4; \ - r3 &= r0; r4 ^= r2; \ - r3 ^= r1; r1 |= r4; \ - r1 ^= r0; r0 |= r4; \ - r0 ^= r2; r1 ^= r4; \ - r2 ^= r1; r1 &= r0; \ - r1 ^= r4; r2 = ~r2; \ - r2 |= r0; \ - r4 ^= r2; \ - } while (0) - -/* - * The Serpent linear transform. - */ -#define SERPENT_LT(x0, x1, x2, x3) do { \ - x0 = ROLc(x0, 13); \ - x2 = ROLc(x2, 3); \ - x1 = x1 ^ x0 ^ x2; \ - x3 = x3 ^ x2 ^ T32(x0 << 3); \ - x1 = ROLc(x1, 1); \ - x3 = ROLc(x3, 7); \ - x0 = x0 ^ x1 ^ x3; \ - x2 = x2 ^ x3 ^ T32(x1 << 7); \ - x0 = ROLc(x0, 5); \ - x2 = ROLc(x2, 22); \ - } while (0) - -/* ======================================================================== */ - -/* - * Initialize Sosemanuk's state by providing a key. The key is an array of - * 1 to 32 bytes. - * @param st The Sosemanuk state - * @param key Key - * @param keylen Length of key in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) -{ - /* - * This key schedule is actually a truncated Serpent key schedule. - * The key-derived words (w_i) are computed within the eight - * local variables w0 to w7, which are reused again and again. - */ - -#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ - ulong32 r0, r1, r2, r3, r4; \ - r0 = w ## o0; \ - r1 = w ## o1; \ - r2 = w ## o2; \ - r3 = w ## o3; \ - S(r0, r1, r2, r3, r4); \ - st->kc[i ++] = r ## d0; \ - st->kc[i ++] = r ## d1; \ - st->kc[i ++] = r ## d2; \ - st->kc[i ++] = r ## d3; \ - } while (0) - -#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) -#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) -#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) -#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) -#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) -#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) -#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) -#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) - -#define WUP(wi, wi5, wi3, wi1, cc) do { \ - ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ - ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ - (wi) = ROLc(tt, 11); \ - } while (0) - -#define WUP0(cc) do { \ - WUP(w0, w3, w5, w7, cc); \ - WUP(w1, w4, w6, w0, cc + 1); \ - WUP(w2, w5, w7, w1, cc + 2); \ - WUP(w3, w6, w0, w2, cc + 3); \ - } while (0) - -#define WUP1(cc) do { \ - WUP(w4, w7, w1, w3, cc); \ - WUP(w5, w0, w2, w4, cc + 1); \ - WUP(w6, w1, w3, w5, cc + 2); \ - WUP(w7, w2, w4, w6, cc + 3); \ - } while (0) - - unsigned char wbuf[32]; - ulong32 w0, w1, w2, w3, w4, w5, w6, w7; - int i = 0; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(keylen > 0 && keylen <= 32); - - /* - * The key is copied into the wbuf[] buffer and padded to 256 bits - * as described in the Serpent specification. - */ - XMEMCPY(wbuf, key, keylen); - if (keylen < 32) { - wbuf[keylen] = 0x01; - if (keylen < 31) { - XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); - } - } - - LOAD32L(w0, wbuf); - LOAD32L(w1, wbuf + 4); - LOAD32L(w2, wbuf + 8); - LOAD32L(w3, wbuf + 12); - LOAD32L(w4, wbuf + 16); - LOAD32L(w5, wbuf + 20); - LOAD32L(w6, wbuf + 24); - LOAD32L(w7, wbuf + 28); - - WUP0(0); SKS3; - WUP1(4); SKS2; - WUP0(8); SKS1; - WUP1(12); SKS0; - WUP0(16); SKS7; - WUP1(20); SKS6; - WUP0(24); SKS5; - WUP1(28); SKS4; - WUP0(32); SKS3; - WUP1(36); SKS2; - WUP0(40); SKS1; - WUP1(44); SKS0; - WUP0(48); SKS7; - WUP1(52); SKS6; - WUP0(56); SKS5; - WUP1(60); SKS4; - WUP0(64); SKS3; - WUP1(68); SKS2; - WUP0(72); SKS1; - WUP1(76); SKS0; - WUP0(80); SKS7; - WUP1(84); SKS6; - WUP0(88); SKS5; - WUP1(92); SKS4; - WUP0(96); SKS3; - -#undef SKS -#undef SKS0 -#undef SKS1 -#undef SKS2 -#undef SKS3 -#undef SKS4 -#undef SKS5 -#undef SKS6 -#undef SKS7 -#undef WUP -#undef WUP0 -#undef WUP1 - - return CRYPT_OK; -} - - -/* - * Initialization continues by setting the IV. The IV length is up to 16 bytes. - * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple - * encryptions/decryptions are to be performed with the same key and - * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called - * to set the state. - * @param st The Sosemanuk state - * @param iv Initialization vector - * @param ivlen Length of iv in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) -{ - - /* - * The Serpent key addition step. - */ -#define KA(zc, x0, x1, x2, x3) do { \ - x0 ^= st->kc[(zc)]; \ - x1 ^= st->kc[(zc) + 1]; \ - x2 ^= st->kc[(zc) + 2]; \ - x3 ^= st->kc[(zc) + 3]; \ - } while (0) - - /* - * One Serpent round. - * zc = current subkey counter - * S = S-box macro for this round - * i0 to i4 = input register numbers (the fifth is a scratch register) - * o0 to o3 = output register numbers - */ -#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ - KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ - S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ - SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ - } while (0) - - /* - * Last Serpent round. Contrary to the "true" Serpent, we keep - * the linear transformation for that last round. - */ -#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ - KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ - S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ - SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ - KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ - } while (0) - - ulong32 r0, r1, r2, r3, r4; - unsigned char ivtmp[16] = {0}; - - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(ivlen <= 16); - LTC_ARGCHK(iv != NULL || ivlen == 0); - - if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); - - /* - * Decode IV into four 32-bit words (little-endian). - */ - LOAD32L(r0, ivtmp); - LOAD32L(r1, ivtmp + 4); - LOAD32L(r2, ivtmp + 8); - LOAD32L(r3, ivtmp + 12); - - /* - * Encrypt IV with Serpent24. Some values are extracted from the - * output of the twelfth, eighteenth and twenty-fourth rounds. - */ - FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); - FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); - FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); - FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); - FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); - FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); - FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); - FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); - FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); - FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); - FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); - FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); - st->s09 = r3; - st->s08 = r1; - st->s07 = r0; - st->s06 = r2; - - FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); - FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); - FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); - FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); - FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); - FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); - st->r1 = r2; - st->s04 = r1; - st->r2 = r3; - st->s05 = r0; - - FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); - FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); - FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); - FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); - FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); - FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); - st->s03 = r0; - st->s02 = r1; - st->s01 = r2; - st->s00 = r3; - - st->ptr = sizeof(st->buf); - -#undef KA -#undef FSS -#undef FSF - - return CRYPT_OK; -} - -/* - * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24] - */ -static const ulong32 mul_a[] = { - 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, - 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, - 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, - 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, - 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, - 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, - 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, - 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, - 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, - 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, - 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, - 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, - 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, - 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, - 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, - 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, - 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, - 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, - 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, - 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, - 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, - 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, - 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, - 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, - 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, - 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, - 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, - 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, - 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, - 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, - 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, - 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, - 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, - 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, - 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, - 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, - 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, - 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, - 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, - 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, - 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, - 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, - 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, - 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, - 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, - 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, - 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, - 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, - 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, - 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, - 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, - 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, - 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, - 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, - 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, - 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, - 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, - 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, - 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, - 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, - 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, - 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, - 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, - 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB -}; - -/* - * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF] - */ -static const ulong32 mul_ia[] = { - 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, - 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, - 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, - 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, - 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, - 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, - 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, - 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, - 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, - 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, - 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, - 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, - 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, - 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, - 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, - 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, - 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, - 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, - 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, - 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, - 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, - 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, - 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, - 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, - 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, - 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, - 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, - 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, - 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, - 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, - 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, - 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, - 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, - 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, - 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, - 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, - 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, - 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, - 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, - 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, - 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, - 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, - 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, - 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, - 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, - 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, - 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, - 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, - 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, - 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, - 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, - 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, - 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, - 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, - 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, - 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, - 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, - 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, - 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, - 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, - 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, - 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, - 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, - 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 -}; - - -/* - * Compute the next block of bits of output stream. This is equivalent - * to one full rotation of the shift register. - */ -static LTC_INLINE void s_sosemanuk_internal(sosemanuk_state *st) -{ - /* - * MUL_A(x) computes alpha * x (in F_{2^32}). - * MUL_G(x) computes 1/alpha * x (in F_{2^32}). - */ -#define MUL_A(x) (T32((x) << 8) ^ mul_a[(x) >> 24]) -#define MUL_G(x) (((x) >> 8) ^ mul_ia[(x) & 0xFF]) - - /* - * This macro computes the special multiplexer, which chooses - * between "x" and "x xor y", depending on the least significant - * bit of the control word. We use the C "?:" selection operator - * (which most compilers know how to optimise) except for Alpha, - * where the manual sign extension seems to perform equally well - * with DEC/Compaq/HP compiler, and much better with gcc. - */ -#ifdef __alpha -#define XMUX(c, x, y) ((((signed int)((c) << 31) >> 31) & (y)) ^ (x)) -#else -#define XMUX(c, x, y) (((c) & 0x1) ? ((x) ^ (y)) : (x)) -#endif - - /* - * FSM() updates the finite state machine. - */ -#define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) do { \ - ulong32 tt, or1; \ - tt = XMUX(r1, s ## x1, s ## x8); \ - or1 = r1; \ - r1 = T32(r2 + tt); \ - tt = T32(or1 * 0x54655307); \ - r2 = ROLc(tt, 7); \ - } while (0) - - /* - * LRU updates the shift register; the dropped value is stored - * in variable "dd". - */ -#define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd) do { \ - dd = s ## x0; \ - s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \ - } while (0) - - /* - * CC1 stores into variable "ee" the next intermediate word - * (combination of the new states of the LFSR and the FSM). - */ -#define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee) do { \ - ee = T32(s ## x9 + r1) ^ r2; \ - } while (0) - - /* - * STEP computes one internal round. "dd" receives the "s_t" - * value (dropped from the LFSR) and "ee" gets the value computed - * from the LFSR and FSM. - */ -#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee) do { \ - FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \ - LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \ - CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \ - } while (0) - - /* - * Apply one Serpent round (with the provided S-box macro), XOR - * the result with the "v" values, and encode the result into - * the destination buffer, at the provided offset. The "x*" - * arguments encode the output permutation of the "S" macro. - */ -#define SRD(S, x0, x1, x2, x3, ooff) do { \ - S(u0, u1, u2, u3, u4); \ - STORE32L(u ## x0 ^ v0, st->buf + ooff); \ - STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \ - STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \ - STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \ - } while (0) - - ulong32 s00 = st->s00; - ulong32 s01 = st->s01; - ulong32 s02 = st->s02; - ulong32 s03 = st->s03; - ulong32 s04 = st->s04; - ulong32 s05 = st->s05; - ulong32 s06 = st->s06; - ulong32 s07 = st->s07; - ulong32 s08 = st->s08; - ulong32 s09 = st->s09; - ulong32 r1 = st->r1; - ulong32 r2 = st->r2; - ulong32 u0, u1, u2, u3, u4; - ulong32 v0, v1, v2, v3; - - STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0); - STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1); - STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2); - STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3); - SRD(S2, 2, 3, 1, 4, 0); - STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0); - STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1); - STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2); - STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3); - SRD(S2, 2, 3, 1, 4, 16); - STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0); - STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1); - STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2); - STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3); - SRD(S2, 2, 3, 1, 4, 32); - STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0); - STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1); - STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2); - STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3); - SRD(S2, 2, 3, 1, 4, 48); - STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0); - STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1); - STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2); - STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3); - SRD(S2, 2, 3, 1, 4, 64); - - st->s00 = s00; - st->s01 = s01; - st->s02 = s02; - st->s03 = s03; - st->s04 = s04; - st->s05 = s05; - st->s06 = s06; - st->s07 = s07; - st->s08 = s08; - st->s09 = s09; - st->r1 = r1; - st->r2 = r2; -} - -/* - * Combine buffers in1[] and in2[] by XOR, result in out[]. The length - * is "datalen" (in bytes). Partial overlap of out[] with either in1[] - * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) - * is allowed. - */ -static LTC_INLINE void s_xorbuf(const unsigned char *in1, const unsigned char *in2, - unsigned char *out, unsigned long datalen) -{ - while (datalen -- > 0) { - *out ++ = *in1 ++ ^ *in2 ++; - } -} - - -/* - * Cipher operation, as a stream cipher: data is read from the "in" - * buffer, combined by XOR with the stream, and the result is written - * in the "out" buffer. "in" and "out" must be either equal, or - * reference distinct buffers (no partial overlap is allowed). - * @param st The Sosemanuk state - * @param in Data in - * @param inlen Length of data in bytes - * @param out Data out - * @return CRYPT_OK on success - */ -int sosemanuk_crypt(sosemanuk_state *st, - const unsigned char *in, unsigned long inlen, unsigned char *out) -{ - LTC_ARGCHK(st != NULL); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - - if (st->ptr < (sizeof(st->buf))) { - unsigned long rlen = (sizeof(st->buf)) - st->ptr; - - if (rlen > inlen) { - rlen = inlen; - } - s_xorbuf(st->buf + st->ptr, in, out, rlen); - in += rlen; - out += rlen; - inlen -= rlen; - st->ptr += rlen; - } - while (inlen > 0) { - s_sosemanuk_internal(st); - if (inlen >= sizeof(st->buf)) { - s_xorbuf(st->buf, in, out, sizeof(st->buf)); - in += sizeof(st->buf); - out += sizeof(st->buf); - inlen -= sizeof(st->buf); - } else { - s_xorbuf(st->buf, in, out, inlen); - st->ptr = inlen; - inlen = 0; - } - } - return CRYPT_OK; -} - - - -/* - * Cipher operation, as a PRNG: the provided output buffer is filled with - * pseudo-random bytes as output from the stream cipher. - * @param st The Sosemanuk state - * @param out Data out - * @param outlen Length of output in bytes - * @return CRYPT_OK on success - */ -int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) -{ - if (outlen == 0) return CRYPT_OK; /* nothing to do */ - LTC_ARGCHK(out != NULL); - XMEMSET(out, 0, outlen); - return sosemanuk_crypt(st, out, outlen, out); -} - - -/* - * Terminate and clear Sosemanuk key context - * @param st The Sosemanuk state - * @return CRYPT_OK on success - */ -int sosemanuk_done(sosemanuk_state *st) -{ - LTC_ARGCHK(st != NULL); - zeromem(st, sizeof(sosemanuk_state)); - return CRYPT_OK; -} - - -#endif - -#pragma clang diagnostic pop diff --git a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c b/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c deleted file mode 100644 index c0fac25..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_memory.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SOSEMANUK - -/** - Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sosemanuk - @param key The key - @param keylen The key length - @param iv The initial vector - @param ivlen The initial vector length - @param datain The plaintext (or ciphertext) - @param datalen The length of the input and output (octets) - @param dataout [out] The ciphertext (or plaintext) - @return CRYPT_OK if successful -*/ -int sosemanuk_memory(const unsigned char *key, unsigned long keylen, - const unsigned char *iv, unsigned long ivlen, - const unsigned char *datain, unsigned long datalen, - unsigned char *dataout) -{ - sosemanuk_state st; - int err; - - if ((err = sosemanuk_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; - if ((err = sosemanuk_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; - err = sosemanuk_crypt(&st, datain, datalen, dataout); -WIPE_KEY: - sosemanuk_done(&st); - return err; -} - -#endif /* LTC_SOSEMANUK */ diff --git a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_test.c b/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_test.c deleted file mode 100644 index 2c0a887..0000000 --- a/Sources/DataLiteC/libtomcrypt/stream/sosemanuk/sosemanuk_test.c +++ /dev/null @@ -1,79 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -#include "tomcrypt_private.h" - -#ifdef LTC_SOSEMANUK -int sosemanuk_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - sosemanuk_state st; - int err; - unsigned char out[1000]; - - { - unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a, - 0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8, - 0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 }; - char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ - unsigned long len; - len = XSTRLEN(pt); - /* crypt piece by piece */ - if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; - if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; - if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; - if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; - if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in one go - using sosemanuk_ivctr64() */ - if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; - if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; - if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; - - /* crypt in a single call */ - if ((err = sosemanuk_memory(k, sizeof(k), n, sizeof(n), - (unsigned char*)pt, len, out)) != CRYPT_OK) return err; - if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; - - } - { - /* keystream - * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto - * Set 6, vector 0 - * key = 0053A6F94C9FF24598EB3E91E4378ADD - * 3083D6297CCF2275C81B6EC11467BA0D - * IV = 0D74DB42A91077DE45AC137AE148AF16 - * stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB - * 0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3 - * 4D2E8C4E016102607368FFA43A0F9155 - * 0706E3548AD9E5EA15A53EB6F0EDE9DC - * - */ - - unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, - 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; - unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 }; - unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB, - 0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3, - 0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55, - 0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC }; - if ((err = sosemanuk_setup(&st, k3, sizeof(k3))) != CRYPT_OK) return err; - if ((err = sosemanuk_setiv(&st, n3, sizeof(n3))) != CRYPT_OK) return err; - if ((err = sosemanuk_keystream(&st, out, 64)) != CRYPT_OK) return err; - if ((err = sosemanuk_done(&st)) != CRYPT_OK) return err; - if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; - } - - return CRYPT_OK; -#endif -} - -#endif diff --git a/Sources/DataLiteC/module.modulemap b/Sources/DataLiteC/module.modulemap new file mode 100644 index 0000000..2f51613 --- /dev/null +++ b/Sources/DataLiteC/module.modulemap @@ -0,0 +1,5 @@ +module DataLiteC [system] { + header "shim.h" + link "sqlite3" + export * +} diff --git a/Sources/DataLiteC/shim.h b/Sources/DataLiteC/shim.h new file mode 100644 index 0000000..08fc10f --- /dev/null +++ b/Sources/DataLiteC/shim.h @@ -0,0 +1,6 @@ +#ifndef C_SQLITE_H +#define C_SQLITE_H + +#include + +#endif diff --git a/Sources/DataLiteC/sqlcipher/sqlite3.c b/Sources/DataLiteC/sqlcipher/sqlite3.c deleted file mode 100644 index e6600b4..0000000 --- a/Sources/DataLiteC/sqlcipher/sqlite3.c +++ /dev/null @@ -1,268833 +0,0 @@ -/****************************************************************************** -** This file is an amalgamation of many separate C source files from SQLite -** version 3.50.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 -** of 5% or more are commonly seen when SQLite is compiled as a single -** translation unit. -** -** This file is all you need to compile SQLite. To use SQLite in other -** programs, you need this file and the "sqlite3.h" header file that defines -** the programming interface to the SQLite library. (If you do not have -** the "sqlite3.h" header file at hand, you will find a copy embedded within -** the text of this file. Search for "Begin file sqlite3.h" to find the start -** of the embedded sqlite3.h header file.) Additional code files may be needed -** if you want a wrapper to interface SQLite with your choice of programming -** language. The code for the "sqlite3" command-line shell is also in a -** separate file. This file contains only code for the core SQLite library. -** -** The content in this amalgamation comes from Fossil check-in -** 4d8adfb30e03f9cf27f800a2c1ba3c48fb4c with changes in files: -** -** .fossil-settings/binary-glob -** .fossil-settings/empty-dirs -** .fossil-settings/ignore-glob -** LICENSE.md -** Makefile.msc -** README.md -** main.mk -** src/attach.c -** src/backup.c -** src/global.c -** src/main.c -** src/malloc.c -** src/pager.c -** src/pager.h -** src/pragma.c -** src/shell.c.in -** src/sqlite.h.in -** src/sqliteInt.h -** src/tclsqlite.c -** src/test1.c -** src/test_config.c -** src/test_thread.c -** src/util.c -** src/vacuum.c -** src/wal.c -** test/tester.tcl -** tool/mkctimec.tcl -** tool/mkpragmatab.tcl -** tool/mksqlite3c.tcl -** -*/ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wshorten-64-to-32" - -#ifndef SQLITE_AMALGAMATION -#define SQLITE_CORE 1 -#define SQLITE_AMALGAMATION 1 -#ifndef SQLITE_PRIVATE -# define SQLITE_PRIVATE static -#endif -/************** Begin file sqliteInt.h ***************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Internal interface definitions for SQLite. -** -*/ -#ifndef SQLITEINT_H -#define SQLITEINT_H - -/* Special Comments: -** -** Some comments have special meaning to the tools that measure test -** coverage: -** -** NO_TEST - The branches on this line are not -** measured by branch coverage. This is -** used on lines of code that actually -** implement parts of coverage testing. -** -** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false -** and the correct answer is still obtained, -** though perhaps more slowly. -** -** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true -** and the correct answer is still obtained, -** though perhaps more slowly. -** -** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread -** that would be harmless and undetectable -** if it did occur. -** -** In all cases, the special comment must be enclosed in the usual -** slash-asterisk...asterisk-slash comment marks, with no spaces between the -** asterisks and the comment text. -*/ - -/* -** Make sure the Tcl calling convention macro is defined. This macro is -** only used by test code and Tcl integration code. -*/ -#ifndef SQLITE_TCLAPI -# define SQLITE_TCLAPI -#endif - -/* -** Include the header file used to customize the compiler options for MSVC. -** This should be done first so that it can successfully prevent spurious -** compiler warnings due to subsequent content in this file and other files -** that are included by this file. -*/ -/************** Include msvc.h in the middle of sqliteInt.h ******************/ -/************** Begin file msvc.h ********************************************/ -/* -** 2015 January 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that is specific to MSVC. -*/ -#ifndef SQLITE_MSVC_H -#define SQLITE_MSVC_H - -#if defined(_MSC_VER) -#pragma warning(disable : 4054) -#pragma warning(disable : 4055) -#pragma warning(disable : 4100) -#pragma warning(disable : 4127) -#pragma warning(disable : 4130) -#pragma warning(disable : 4152) -#pragma warning(disable : 4189) -#pragma warning(disable : 4206) -#pragma warning(disable : 4210) -#pragma warning(disable : 4232) -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) -#pragma warning(disable : 4306) -#pragma warning(disable : 4702) -#pragma warning(disable : 4706) -#endif /* defined(_MSC_VER) */ - -#if defined(_MSC_VER) && !defined(_WIN64) -#undef SQLITE_4_BYTE_ALIGNED_MALLOC -#define SQLITE_4_BYTE_ALIGNED_MALLOC -#endif /* defined(_MSC_VER) && !defined(_WIN64) */ - -#if !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 -#define HAVE_LOG2 0 -#endif /* !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 */ - -#endif /* SQLITE_MSVC_H */ - -/************** End of msvc.h ************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* -** Special setup for VxWorks -*/ -/************** Include vxworks.h in the middle of sqliteInt.h ***************/ -/************** Begin file vxworks.h *****************************************/ -/* -** 2015-03-02 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that is specific to Wind River's VxWorks -*/ -#if defined(__RTP__) || defined(_WRS_KERNEL) -/* This is VxWorks. Set up things specially for that OS -*/ -#include -#include /* amalgamator: dontcache */ -#define OS_VXWORKS 1 -#define SQLITE_OS_OTHER 0 -#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1 -#define SQLITE_OMIT_LOAD_EXTENSION 1 -#define SQLITE_ENABLE_LOCKING_STYLE 0 -#define HAVE_UTIME 1 -#else -/* This is not VxWorks. */ -#define OS_VXWORKS 0 -#define HAVE_FCHOWN 1 -#define HAVE_READLINK 1 -#define HAVE_LSTAT 1 -#endif /* defined(_WRS_KERNEL) */ - -/************** End of vxworks.h *********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* -** These #defines should enable >2GB file support on POSIX if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any -** system #includes. Hence, this block of code must be the very first -** code in all source files. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: Red Hat 7.2) but you want your code to work -** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in Red Hat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** The previous paragraph was written in 2005. (This paragraph is written -** on 2008-11-28.) These days, all Linux kernels support large files, so -** you should probably leave LFS enabled. But some embedded platforms might -** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful. -** -** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif - -/* The GCC_VERSION and MSVC_VERSION macros are used to -** conditionally include optimizations for each of these compilers. A -** value of 0 means that compiler is not being used. The -** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific -** optimizations, and hence set all compiler macros to 0 -** -** There was once also a CLANG_VERSION macro. However, we learn that the -** version numbers in clang are for "marketing" only and are inconsistent -** and unreliable. Fortunately, all versions of clang also recognize the -** gcc version numbers and have reasonable settings for gcc version numbers, -** so the GCC_VERSION macro will be set to a correct non-zero value even -** when compiling with clang. -*/ -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# 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 -#endif - -#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) -# define _BSD_SOURCE -#endif - -/* -** Macro to disable warnings about missing "break" at the end of a "case". -*/ -#if defined(__has_attribute) -# if __has_attribute(fallthrough) -# define deliberate_fall_through __attribute__((fallthrough)); -# endif -#endif -#if !defined(deliberate_fall_through) -# define deliberate_fall_through -#endif - -/* -** For MinGW, check to see if we can include the header file containing its -** version information, among other things. Normally, this internal MinGW -** header file would [only] be included automatically by other MinGW header -** files; however, the contained version information is now required by this -** header file to work around binary compatibility issues (see below) and -** this is the only known way to reliably obtain it. This entire #if block -** would be completely unnecessary if there was any other way of detecting -** MinGW via their preprocessor (e.g. if they customized their GCC to define -** some MinGW-specific macros). When compiling for MinGW, either the -** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be -** defined; otherwise, detection of conditions specific to MinGW will be -** disabled. -*/ -#if defined(_HAVE_MINGW_H) -# include "mingw.h" -#elif defined(_HAVE__MINGW_H) -# include "_mingw.h" -#endif - -/* -** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T -** define is required to maintain binary compatibility with the MSVC runtime -** library in use (e.g. for Windows XP). -*/ -#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ - defined(_WIN32) && !defined(_WIN64) && \ - defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ - defined(__MSVCRT__) -# define _USE_32BIT_TIME_T -#endif - -/* 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. -*/ -/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001-09-15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve the right to make minor changes -** if experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are supposed to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -*/ -#ifndef SQLITE3_H -#define SQLITE3_H -#include /* Needed for the definition of va_list */ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** 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 -#endif -#ifndef SQLITE_API -# define SQLITE_API -#endif -#ifndef SQLITE_CDECL -# define SQLITE_CDECL -#endif -#ifndef SQLITE_APICALL -# define SQLITE_APICALL -#endif -#ifndef SQLITE_STDCALL -# define SQLITE_STDCALL SQLITE_APICALL -#endif -#ifndef SQLITE_CALLBACK -# define SQLITE_CALLBACK -#endif -#ifndef SQLITE_SYSAPI -# define SQLITE_SYSAPI -#endif - -/* -** These no-op macros are used in front of interfaces to mark those -** interfaces as either deprecated or experimental. New applications -** should not use deprecated interfaces - they are supported for backwards -** compatibility only. Application writers should be aware that -** experimental interfaces are subject to change in point releases. -** -** These macros used to resolve to various kinds of compiler magic that -** would generate warning messages when they were used. But that -** compiler magic ended up generating such a flurry of bug reports -** that we have taken it all out and gone back to using simple -** noop macros. -*/ -#define SQLITE_DEPRECATED -#define SQLITE_EXPERIMENTAL - -/* -** Ensure these symbols were not defined by some previous header file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers -** -** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header -** evaluates to a string literal that is the SQLite version in the -** format "X.Y.Z" where X is the major version number (always 3 for -** SQLite3) and Y is the minor version number and Z is the release number.)^ -** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same -** numbers used in [SQLITE_VERSION].)^ -** The SQLITE_VERSION_NUMBER for any given release of SQLite will also -** be larger than the release from which it is derived. Either Y will -** be held constant and Z will be incremented or else Y will be incremented -** and Z will be reset to zero. -** -** Since [version 3.6.18] ([dateof:3.6.18]), -** SQLite source code has been stored in the -** Fossil configuration management -** system. ^The SQLITE_SOURCE_ID macro evaluates to -** a string which identifies a particular check-in of SQLite -** within its configuration management system. ^The SQLITE_SOURCE_ID -** string contains the date and time of the check-in (UTC) and a SHA1 -** or SHA3-256 hash of the entire source tree. If the source code has -** been edited in any way since it was last checked in, then the last -** four hexadecimal digits of the hash may be modified. -** -** See also: [sqlite3_libversion()], -** [sqlite3_libversion_number()], [sqlite3_sourceid()], -** [sqlite_version()] and [sqlite_source_id()]. -*/ -#define SQLITE_VERSION "3.50.4" -#define SQLITE_VERSION_NUMBER 3050004 -#define SQLITE_SOURCE_ID "2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45ealt1" - -/* -** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version sqlite3_sourceid -** -** These interfaces provide the same information as the [SQLITE_VERSION], -** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros -** but are associated with the library instead of the header file. ^(Cautious -** programmers might include assert() statements in their application to -** verify that values returned by these interfaces match the macros in -** the header, and thus ensure that the application is -** compiled with matching library and header files. -** -**
-** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
-** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
-** 
)^ -** -** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] -** macro. ^The sqlite3_libversion() function returns a pointer to the -** to the sqlite3_version[] string constant. The sqlite3_libversion() -** function is provided for use in DLLs since DLL users usually do not have -** direct access to string constants within the DLL. ^The -** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns -** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built -** using an edited copy of [the amalgamation], then the last four characters -** of the hash might be different from [SQLITE_SOURCE_ID].)^ -** -** See also: [sqlite_version()] and [sqlite_source_id()]. -*/ -SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -SQLITE_API const char *sqlite3_libversion(void); -SQLITE_API const char *sqlite3_sourceid(void); -SQLITE_API int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Run-Time Library Compilation Options Diagnostics -** -** ^The sqlite3_compileoption_used() function returns 0 or 1 -** indicating whether the specified option was defined at -** compile time. ^The SQLITE_ prefix may be omitted from the -** option name passed to sqlite3_compileoption_used(). -** -** ^The sqlite3_compileoption_get() function allows iterating -** over the list of options that were defined at compile time by -** returning the N-th compile time option string. ^If N is out of range, -** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ -** prefix is omitted from any strings returned by -** sqlite3_compileoption_get(). -** -** ^Support for the diagnostic functions sqlite3_compileoption_used() -** and sqlite3_compileoption_get() may be omitted by specifying the -** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. -** -** See also: SQL functions [sqlite_compileoption_used()] and -** [sqlite_compileoption_get()] and the [compile_options pragma]. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *sqlite3_compileoption_get(int N); -#else -# define sqlite3_compileoption_used(X) 0 -# define sqlite3_compileoption_get(X) ((void*)0) -#endif - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe -** -** ^The sqlite3_threadsafe() function returns zero if and only if -** SQLite was compiled with mutexing code omitted due to the -** [SQLITE_THREADSAFE] compile-time option being set to 0. -** -** SQLite can be compiled with or without mutexes. When -** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes -** are enabled and SQLite is threadsafe. When the -** [SQLITE_THREADSAFE] macro is 0, -** the mutexes are omitted. Without the mutexes, it is not safe -** to use SQLite concurrently from more than one thread. -** -** Enabling mutexes incurs a measurable performance penalty. -** So if speed is of utmost importance, it makes sense to disable -** the mutexes. But for maximum safety, mutexes should be enabled. -** ^The default behavior is for mutexes to be enabled. -** -** This interface can be used by an application to make sure that the -** version of SQLite that it is linking against was compiled with -** the desired setting of the [SQLITE_THREADSAFE] macro. -** -** This interface only reports on the compile-time mutex setting -** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with -** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but -** can be fully or partially disabled using a call to [sqlite3_config()] -** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], -** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the -** sqlite3_threadsafe() function shows only the compile-time setting of -** thread safety, not any run-time changes to that setting made by -** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() -** is unchanged by calls to sqlite3_config().)^ -** -** See the [threading mode] documentation for additional information. -*/ -SQLITE_API int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle -** KEYWORDS: {database connection} {database connections} -** -** Each open SQLite database is represented by a pointer to an instance of -** the opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] -** and [sqlite3_close_v2()] are its destructors. There are many other -** interfaces (such as -** [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on an -** sqlite3 object. -*/ -typedef struct sqlite3 sqlite3; - -/* -** CAPI3REF: 64-Bit Integer Types -** KEYWORDS: sqlite_int64 sqlite_uint64 -** -** Because there is no cross-platform way to specify 64-bit integer types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. -** The sqlite_int64 and sqlite_uint64 types are supported for backwards -** compatibility only. -** -** ^The sqlite3_int64 and sqlite_int64 types can store integer values -** between -9223372036854775808 and +9223372036854775807 inclusive. ^The -** sqlite3_uint64 and sqlite_uint64 types can store integer values -** between 0 and +18446744073709551615 inclusive. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; -# ifdef SQLITE_UINT64_TYPE - typedef SQLITE_UINT64_TYPE sqlite_uint64; -# else - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -# endif -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection -** DESTRUCTOR: sqlite3 -** -** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors -** for the [sqlite3] object. -** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if -** the [sqlite3] object is successfully destroyed and all associated -** resources are deallocated. -** -** Ideally, applications should [sqlite3_finalize | finalize] all -** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and -** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated -** with the [sqlite3] object prior to attempting to close the object. -** ^If the database connection is associated with unfinalized prepared -** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then -** sqlite3_close() will leave the database connection open and return -** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared -** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups, -** it returns [SQLITE_OK] regardless, but instead of deallocating the database -** connection immediately, it marks the database connection as an unusable -** "zombie" and makes arrangements to automatically deallocate the database -** connection after all prepared statements are finalized, all BLOB handles -** are closed, and all backups have finished. The sqlite3_close_v2() interface -** is intended for use with host languages that are garbage collected, and -** where the order in which destructors are called is arbitrary. -** -** ^If an [sqlite3] object is destroyed while a transaction is open, -** the transaction is automatically rolled back. -** -** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] -** must be either a NULL -** pointer or an [sqlite3] object pointer obtained -** from [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()], and not previously closed. -** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer -** argument is a harmless no-op. -*/ -SQLITE_API int sqlite3_close(sqlite3*); -SQLITE_API int sqlite3_close_v2(sqlite3*); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface -** METHOD: sqlite3 -** -** The sqlite3_exec() interface is a convenience wrapper around -** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], -** that allows an application to run multiple statements of SQL -** without having to use a lot of C code. -** -** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, -** semicolon-separate SQL statements passed into its 2nd argument, -** in the context of the [database connection] passed in as its 1st -** argument. ^If the callback function of the 3rd argument to -** sqlite3_exec() is not NULL, then it is invoked for each result row -** coming out of the evaluated SQL statements. ^The 4th argument to -** sqlite3_exec() is relayed through to the 1st argument of each -** callback invocation. ^If the callback pointer to sqlite3_exec() -** is NULL, then no callback is ever invoked and result rows are -** ignored. -** -** ^If an error occurs while evaluating the SQL statements passed into -** sqlite3_exec(), then execution of the current statement stops and -** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() -** is not NULL then any error message is written into memory obtained -** from [sqlite3_malloc()] and passed back through the 5th parameter. -** To avoid memory leaks, the application should invoke [sqlite3_free()] -** on error message strings returned through the 5th parameter of -** sqlite3_exec() after the error message string is no longer needed. -** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors -** occur, then sqlite3_exec() sets the pointer in its 5th parameter to -** NULL before returning. -** -** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() -** routine returns SQLITE_ABORT without invoking the callback again and -** without running any subsequent SQL statements. -** -** ^The 2nd argument to the sqlite3_exec() callback function is the -** number of columns in the result. ^The 3rd argument to the sqlite3_exec() -** callback is an array of pointers to strings obtained as if from -** [sqlite3_column_text()], one for each column. ^If an element of a -** result row is NULL then the corresponding string pointer for the -** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the -** sqlite3_exec() callback is an array of pointers to strings where each -** entry represents the name of corresponding result column as obtained -** from [sqlite3_column_name()]. -** -** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer -** to an empty string, or a pointer that contains only whitespace and/or -** SQL comments, then no SQL statements are evaluated and the database -** is not changed. -** -** Restrictions: -** -**
    -**
  • The application must ensure that the 1st parameter to sqlite3_exec() -** is a valid and open [database connection]. -**
  • The application must not close the [database connection] specified by -** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. -**
  • The application must not modify the SQL statement text passed into -** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. -**
  • The application must not dereference the arrays or string pointers -** passed as the 3rd and 4th callback parameters after it returns. -**
-*/ -SQLITE_API int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluated */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes -** KEYWORDS: {result code definitions} -** -** Many SQLite functions return an integer result code from the set shown -** here in order to indicate success or failure. -** -** New error codes may be added in future versions of SQLite. -** -** See also: [extended result code definitions] -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* Generic error */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Internal use only */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Not used */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ -#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes -** KEYWORDS: {extended result code definitions} -** -** In its default configuration, SQLite API routines return one of 30 integer -** [result codes]. However, experience has shown that many of -** these result codes are too coarse-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] -** and later) include -** support for additional result codes that provide more detailed information -** about errors. These [extended result codes] are enabled or disabled -** on a per database connection basis using the -** [sqlite3_extended_result_codes()] API. Or, the extended code for -** the most recent error can be obtained using -** [sqlite3_extended_errcode()]. -*/ -#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) -#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) -#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) -#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) -#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) -#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) -#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) -#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) -#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) -#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) -#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) -#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) -#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) -#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) -#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) -#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) -#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) -#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) -#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) -#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) -#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) -#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) -#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) -#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) -#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) -#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) -#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) -#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) -#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) -#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) -#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) -#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) -#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) -#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) -#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ -#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) -#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) -#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) -#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) -#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) -#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) -#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) -#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) -#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) -#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) -#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) -#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) -#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) -#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) -#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) -#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) -#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) -#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) -#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) -#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) -#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) -#define SQLITE_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_NOTICE_RBU (SQLITE_NOTICE | (3<<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)) /* internal use only */ - -/* -** CAPI3REF: Flags For File Open Operations -** -** These bit values are intended for use in the -** 3rd parameter to the [sqlite3_open_v2()] interface and -** in the 4th parameter to the [sqlite3_vfs.xOpen] method. -** -** Only those flags marked as "Ok for sqlite3_open_v2()" may be -** used as the third argument to the [sqlite3_open_v2()] interface. -** The other flags have historically been ignored by 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 sqlite3_open_v2(). -** Applications should not depend on the historical behavior. -** -** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into -** [sqlite3_open_v2()] does *not* cause the underlying database file -** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into -** [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 sqlite3_open_v2() */ -#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ -#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ -#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ -#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ -#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ -#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ -#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ - -/* Reserved: 0x00F00000 */ -/* Legacy compatibility: */ -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ - - -/* -** CAPI3REF: Device Characteristics -** -** The xDeviceCharacteristics method of the [sqlite3_io_methods] -** object returns an integer which is a vector of these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. -** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that -** after reboot following a crash or power loss, the only bytes in a -** file that were written at the application level might have changed -** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN -** flag indicates that a file cannot be deleted when open. The -** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on -** read-only media and cannot be changed even by processes with -** elevated privileges. -** -** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying -** filesystem supports doing multiple write operations atomically when those -** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and -** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. -** -** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read -** from the database file in amounts that are not a multiple of the -** page size and that do not begin at a page boundary. Without this -** property, SQLite is careful to only do full-page reads and write -** on aligned pages, with the one exception that it will do a sub-page -** read of the first page to access the database header. -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 -#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 -#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 -#define SQLITE_IOCAP_IMMUTABLE 0x00002000 -#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 -#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000 - -/* -** CAPI3REF: File Locking Levels -** -** SQLite uses one of these integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. These values are ordered from -** lest restrictive to most restrictive. -** -** The argument to xLock() is always SHARED or higher. The argument to -** xUnlock is either SHARED or NONE. -*/ -#define SQLITE_LOCK_NONE 0 /* xUnlock() only */ -#define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */ -#define SQLITE_LOCK_RESERVED 2 /* xLock() only */ -#define SQLITE_LOCK_PENDING 3 /* xLock() only */ -#define SQLITE_LOCK_EXCLUSIVE 4 /* xLock() only */ - -/* -** CAPI3REF: Synchronization Type Flags -** -** When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of -** these integer values as the second argument. -** -** When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. If the lower four bits of the flag -** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. -** If the lower four bits equal SQLITE_SYNC_FULL, that means -** to use Mac OS X style fullsync instead of fsync(). -** -** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags -** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL -** settings. The [synchronous pragma] determines when calls to the -** xSync VFS method occur and applies uniformly across all platforms. -** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how -** energetic or rigorous or forceful the sync operations are and -** only make a difference on Mac OSX for the default SQLite code. -** (Third-party VFS implementations might also make the distinction -** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the -** operating systems natively supported by SQLite, only Mac OSX -** cares about the difference.) -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - -/* -** CAPI3REF: OS Interface Open File Handle -** -** An [sqlite3_file] object represents an open file in the -** [sqlite3_vfs | OS interface layer]. Individual OS interface -** implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object -** -** Every file opened by the [sqlite3_vfs.xOpen] method populates an -** [sqlite3_file] object (or, more commonly, a subclass of the -** [sqlite3_file] object) with a pointer to an instance of this object. -** This object defines the methods used to perform various operations -** against the open file represented by the [sqlite3_file] object. -** -** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element -** to a non-NULL pointer, then the sqlite3_io_methods.xClose method -** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The -** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] -** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element -** to NULL. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] -** flag may be ORed in to indicate that only the data of the file -** and not its inode needs to be synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() upgrades the database file lock. In other words, xLock() moves the -** database file lock in the direction NONE toward EXCLUSIVE. The argument to -** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never -** SQLITE_LOCK_NONE. If the database file lock is already at or above the -** requested lock, then the call to xLock() is a no-op. -** xUnlock() downgrades the database file lock to either SHARED or NONE. -** If the lock is already at or below the requested lock state, then the call -** to xUnlock() is a no-op. -** The xCheckReservedLock() method checks whether any database connection, -** either in this process or in some other process, is holding a RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns, via its output -** pointer parameter, true if such a lock exists and false otherwise. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument is an -** integer opcode. The third argument is a generic pointer intended to -** point to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves all opcodes less than 100 for its own use. -** A [file control opcodes | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. VFS implementations should -** return [SQLITE_NOTFOUND] for file control opcodes that they do not -** recognize. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] -**
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] -**
  • [SQLITE_IOCAP_IMMUTABLE] -**
  • [SQLITE_IOCAP_BATCH_ATOMIC] -**
  • [SQLITE_IOCAP_SUBPAGE_READ] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -** -** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill -** in the unread portions of the buffer with zeros. A VFS that -** fails to zero-fill short reads might seem to work. However, -** failure to zero-fill short reads will eventually lead to -** database corruption. -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Methods above are valid for version 1 */ - int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); - int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); - void (*xShmBarrier)(sqlite3_file*); - int (*xShmUnmap)(sqlite3_file*, int deleteFlag); - /* Methods above are valid for version 2 */ - int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); - int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); - /* Methods above are valid for version 3 */ - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes -** KEYWORDS: {file control opcodes} {file control opcode} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] -** interface. -** -**
    -**
  • [[SQLITE_FCNTL_LOCKSTATE]] -** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode causes the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. -** This capability is only available if SQLite is compiled with [SQLITE_DEBUG]. -** -**
  • [[SQLITE_FCNTL_SIZE_HINT]] -** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS -** layer a hint of how large the database file will grow to be during the -** current transaction. This hint is not guaranteed to be accurate but it -** is often close. The underlying VFS might choose to preallocate database -** file space based on this hint in order to help writes to the database -** file run faster. -** -**
  • [[SQLITE_FCNTL_SIZE_LIMIT]] -** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that -** implements [sqlite3_deserialize()] to set an upper bound on the size -** of the in-memory database. The argument is a pointer to a [sqlite3_int64]. -** If the integer pointed to is negative, then it is filled in with the -** current limit. Otherwise the limit is set to the larger of the value -** of the integer pointed to and the current database size. The integer -** pointed to is set to the new limit. -** -**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] -** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS -** extends and truncates the database file in chunks of a size specified -** by the user. The fourth argument to [sqlite3_file_control()] should -** point to an integer (type int) containing the new chunk-size to use -** for the nominated database. Allocating database file space in large -** chunks (say 1MB at a time), may reduce file-system fragmentation and -** improve performance on some systems. -** -**
  • [[SQLITE_FCNTL_FILE_POINTER]] -** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer -** to the [sqlite3_file] object associated with a particular database -** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER]. -** -**
  • [[SQLITE_FCNTL_JOURNAL_POINTER]] -** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer -** to the [sqlite3_file] object associated with the journal file (either -** the [rollback journal] or the [write-ahead log]) for a particular database -** connection. See also [SQLITE_FCNTL_FILE_POINTER]. -** -**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] -** No longer in use. -** -**
  • [[SQLITE_FCNTL_SYNC]] -** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and -** sent to the VFS immediately before the xSync method is invoked on a -** database file descriptor. Or, if the xSync method is not invoked -** because the user has configured SQLite with -** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place -** of the xSync method. In most cases, the pointer argument passed with -** this file-control is NULL. However, if the database file is being synced -** as part of a multi-database commit, the argument points to a nul-terminated -** string containing the transactions super-journal file name. VFSes that -** do not need this signal should silently ignore this opcode. Applications -** should not call [sqlite3_file_control()] with this opcode as doing so may -** disrupt the operation of the specialized VFSes that do require it. -** -**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] -** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite -** and sent to the VFS after a transaction has been committed immediately -** but before the database is unlocked. VFSes that do not need this signal -** should silently ignore this opcode. Applications should not call -** [sqlite3_file_control()] with this opcode as doing so may disrupt the -** operation of the specialized VFSes that do require it. -** -**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] -** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic -** retry counts and intervals for certain disk I/O operations for the -** windows [VFS] in order to provide robustness in the presence of -** anti-virus programs. By default, the windows VFS will retry file read, -** file write, and file delete operations up to 10 times, with a delay -** of 25 milliseconds before the first retry and with the delay increasing -** by an additional 25 milliseconds with each subsequent retry. This -** opcode allows these two values (10 retries and 25 milliseconds of delay) -** to be adjusted. The values are changed for all database connections -** within the same process. The argument is a pointer to an array of two -** integers where the first integer is the new retry count and the second -** integer is the delay. If either integer is negative, then the setting -** is not changed but instead the prior value of that setting is written -** into the array entry, allowing the current retry settings to be -** interrogated. The zDbName parameter is ignored. -** -**
  • [[SQLITE_FCNTL_PERSIST_WAL]] -** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the -** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary -** write ahead log ([WAL file]) and shared memory -** files used for transaction control -** are automatically deleted when the latest connection to the database -** closes. Setting persistent WAL mode causes those files to persist after -** close. Persisting the files is useful when other processes that do not -** have write permission on the directory containing the database file want -** to read the database file, as the WAL and shared memory files must exist -** in order for the database to be readable. The fourth parameter to -** [sqlite3_file_control()] for this opcode should be a pointer to an integer. -** That integer is 0 to disable persistent WAL mode or 1 to enable persistent -** WAL mode. If the integer is -1, then it is overwritten with the current -** WAL persistence setting. -** -**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] -** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the -** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting -** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the -** xDeviceCharacteristics methods. The fourth parameter to -** [sqlite3_file_control()] for this opcode should be a pointer to an integer. -** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage -** mode. If the integer is -1, then it is overwritten with the current -** zero-damage mode setting. -** -**
  • [[SQLITE_FCNTL_OVERWRITE]] -** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening -** a write transaction to indicate that, unless it is rolled back for some -** reason, the entire database file will be overwritten by the current -** transaction. This is used by VACUUM operations. -** -**
  • [[SQLITE_FCNTL_VFSNAME]] -** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of -** all [VFSes] in the VFS stack. The names are of all VFS shims and the -** final bottom-level VFS are written into memory obtained from -** [sqlite3_malloc()] and the result is stored in the char* variable -** that the fourth parameter of [sqlite3_file_control()] points to. -** The caller is responsible for freeing the memory when done. As with -** all file-control actions, there is no guarantee that this will actually -** do anything. Callers should initialize the char* variable to a NULL -** pointer in case this file-control is not implemented. This file-control -** is intended for diagnostic use only. -** -**
  • [[SQLITE_FCNTL_VFS_POINTER]] -** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level -** [VFSes] currently in use. ^(The argument X in -** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be -** of type "[sqlite3_vfs] **". This opcodes will set *X -** to a pointer to the top-level VFS.)^ -** ^When there are multiple VFS shims in the stack, this opcode finds the -** upper-most shim only. -** -**
  • [[SQLITE_FCNTL_PRAGMA]] -** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] -** file control is sent to the open [sqlite3_file] object corresponding -** to the database file to which the pragma statement refers. ^The argument -** to the [SQLITE_FCNTL_PRAGMA] file control is an array of -** pointers to strings (char**) in which the second element of the array -** is the name of the pragma and the third element is the argument to the -** pragma or NULL if the pragma has no argument. ^The handler for an -** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element -** of the char** argument point to a string obtained from [sqlite3_mprintf()] -** or the equivalent and that string will become the result of the pragma or -** the error message if the pragma fails. ^If the -** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal -** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] -** file control returns [SQLITE_OK], then the parser assumes that the -** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement if result string is NULL, or that returns a copy -** of the result string if the string is non-NULL. -** ^If the [SQLITE_FCNTL_PRAGMA] file control returns -** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means -** that the VFS encountered an error while handling the [PRAGMA] and the -** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] -** file control occurs at the beginning of pragma statement analysis and so -** it is able to override built-in [PRAGMA] statements. -** -**
  • [[SQLITE_FCNTL_BUSYHANDLER]] -** ^The [SQLITE_FCNTL_BUSYHANDLER] -** file-control may be invoked by SQLite on the database file handle -** shortly after it is opened in order to provide a custom VFS with access -** to the connection's busy-handler callback. The argument is of type (void**) -** - an array of two (void *) values. The first (void *) actually points -** to a function of type (int (*)(void *)). In order to invoke the connection's -** busy-handler, this function should be invoked with the second (void *) in -** the array as the only argument. If it returns non-zero, then the operation -** should be retried. If it returns zero, the custom VFS should abandon the -** current operation. -** -**
  • [[SQLITE_FCNTL_TEMPFILENAME]] -** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control -** to have SQLite generate a -** temporary filename using the same algorithm that is followed to generate -** temporary filenames for TEMP tables and other internal uses. The -** argument should be a char** which will be filled with the filename -** written into memory obtained from [sqlite3_malloc()]. The caller should -** invoke [sqlite3_free()] on the result to avoid a memory leak. -** -**
  • [[SQLITE_FCNTL_MMAP_SIZE]] -** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the -** maximum number of bytes that will be used for memory-mapped I/O. -** The argument is a pointer to a value of type sqlite3_int64 that -** is an advisory maximum number of bytes in the file to memory map. The -** pointer is overwritten with the old value. The limit is not changed if -** the value originally pointed to is negative, and so the current limit -** can be queried by passing in a pointer to a negative number. This -** file-control is used internally to implement [PRAGMA mmap_size]. -** -**
  • [[SQLITE_FCNTL_TRACE]] -** The [SQLITE_FCNTL_TRACE] file control provides advisory information -** to the VFS about what the higher layers of the SQLite stack are doing. -** This file control is used by some VFS activity tracing [shims]. -** The argument is a zero-terminated string. Higher layers in the -** SQLite stack may generate instances of this file control if -** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. -** -**
  • [[SQLITE_FCNTL_HAS_MOVED]] -** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a -** pointer to an integer and it writes a boolean into that integer depending -** on whether or not the file has been renamed, moved, or deleted since it -** was first opened. -** -**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] -** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the -** underlying native file handle associated with a file handle. This file -** control interprets its argument as a pointer to a native file handle and -** writes the resulting value there. -** -**
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] -** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This -** opcode causes the xFileControl method to swap the file handle with the one -** pointed to by the pArg argument. This capability is used during testing -** and only needs to be supported when SQLITE_TEST is defined. -** -**
  • [[SQLITE_FCNTL_NULL_IO]] -** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor -** or file handle for the [sqlite3_file] object such that it will no longer -** read or write to the database file. -** -**
  • [[SQLITE_FCNTL_WAL_BLOCK]] -** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might -** be advantageous to block on the next WAL lock if the lock is not immediately -** available. The WAL subsystem issues this signal during rare -** circumstances in order to fix a problem with priority inversion. -** Applications should not use this file-control. -** -**
  • [[SQLITE_FCNTL_ZIPVFS]] -** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other -** VFS should return SQLITE_NOTFOUND for this opcode. -** -**
  • [[SQLITE_FCNTL_RBU]] -** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by -** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for -** this opcode. -** -**
  • [[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] -** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then -** the file descriptor is placed in "batch write mode", which -** means all subsequent write operations will be deferred and done -** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems -** that do not support batch atomic writes will return SQLITE_NOTFOUND. -** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to -** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or -** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make -** no VFS interface calls on the same [sqlite3_file] file descriptor -** except for calls to the xWrite method and the xFileControl method -** with [SQLITE_FCNTL_SIZE_HINT]. -** -**
  • [[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] -** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write -** operations since the previous successful call to -** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. -** This file control returns [SQLITE_OK] if and only if the writes were -** all performed successfully and have been committed to persistent storage. -** ^Regardless of whether or not it is successful, this file control takes -** the file descriptor out of batch write mode so that all subsequent -** write operations are independent. -** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without -** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. -** -**
  • [[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] -** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write -** operations since the previous successful call to -** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. -** ^This file control takes the file descriptor out of batch write mode -** so that all subsequent write operations are independent. -** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without -** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. -** -**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] -** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS -** to block for up to M milliseconds before failing when attempting to -** obtain a file lock using the xLock or xShmLock methods of the VFS. -** The parameter is a pointer to a 32-bit signed integer that contains -** the value that M is to be set to. Before returning, the 32-bit signed -** integer is overwritten with the previous value of M. -** -**
  • [[SQLITE_FCNTL_BLOCK_ON_CONNECT]] -** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the -** VFS to block when taking a SHARED lock to connect to a wal mode database. -** This is used to implement the functionality associated with -** SQLITE_SETLK_BLOCK_ON_CONNECT. -** -**
  • [[SQLITE_FCNTL_DATA_VERSION]] -** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to -** a database file. The argument is a pointer to a 32-bit unsigned integer. -** The "data version" for the pager is written into the pointer. The -** "data version" changes whenever any change occurs to the corresponding -** database file, either through SQL statements on the same database -** connection or through transactions committed by separate database -** connections possibly in other processes. The [sqlite3_total_changes()] -** interface can be used to find if any database on the connection has changed, -** but that interface responds to changes on TEMP as well as MAIN and does -** not provide a mechanism to detect changes to MAIN only. Also, the -** [sqlite3_total_changes()] interface responds to internal changes only and -** omits changes made by other database connections. The -** [PRAGMA data_version] command provides a mechanism to detect changes to -** a single attached database that occur due to other database connections, -** but omits changes implemented by the database connection on which it is -** called. This file control is the only mechanism to detect changes that -** happen either internally or externally and that are associated with -** a particular attached database. -** -**
  • [[SQLITE_FCNTL_CKPT_START]] -** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint -** in wal mode before the client starts to copy pages from the wal -** file to the database file. -** -**
  • [[SQLITE_FCNTL_CKPT_DONE]] -** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint -** in wal mode after the client has finished copying pages from the wal -** file to the database file, but before the *-shm file is updated to -** record the fact that the pages have been checkpointed. -** -**
  • [[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. -** -**
  • [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the -** [checksum VFS shim] only. -** -**
  • [[SQLITE_FCNTL_RESET_CACHE]] -** If there is currently no transaction open on the database, and the -** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control -** purges the contents of the in-memory page cache. If there is an open -** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. -**
-*/ -#define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 -#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 -#define SQLITE_FCNTL_LAST_ERRNO 4 -#define SQLITE_FCNTL_SIZE_HINT 5 -#define SQLITE_FCNTL_CHUNK_SIZE 6 -#define SQLITE_FCNTL_FILE_POINTER 7 -#define SQLITE_FCNTL_SYNC_OMITTED 8 -#define SQLITE_FCNTL_WIN32_AV_RETRY 9 -#define SQLITE_FCNTL_PERSIST_WAL 10 -#define SQLITE_FCNTL_OVERWRITE 11 -#define SQLITE_FCNTL_VFSNAME 12 -#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 -#define SQLITE_FCNTL_PRAGMA 14 -#define SQLITE_FCNTL_BUSYHANDLER 15 -#define SQLITE_FCNTL_TEMPFILENAME 16 -#define SQLITE_FCNTL_MMAP_SIZE 18 -#define SQLITE_FCNTL_TRACE 19 -#define SQLITE_FCNTL_HAS_MOVED 20 -#define SQLITE_FCNTL_SYNC 21 -#define SQLITE_FCNTL_COMMIT_PHASETWO 22 -#define SQLITE_FCNTL_WIN32_SET_HANDLE 23 -#define SQLITE_FCNTL_WAL_BLOCK 24 -#define SQLITE_FCNTL_ZIPVFS 25 -#define SQLITE_FCNTL_RBU 26 -#define SQLITE_FCNTL_VFS_POINTER 27 -#define SQLITE_FCNTL_JOURNAL_POINTER 28 -#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 -#define SQLITE_FCNTL_PDB 30 -#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 -#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 -#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 -#define SQLITE_FCNTL_LOCK_TIMEOUT 34 -#define SQLITE_FCNTL_DATA_VERSION 35 -#define SQLITE_FCNTL_SIZE_LIMIT 36 -#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 -#define SQLITE_FCNTL_RESET_CACHE 42 -#define SQLITE_FCNTL_NULL_IO 43 -#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 - -/* deprecated names */ -#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE -#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE -#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO - - -/* -** CAPI3REF: Mutex Handle -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: Loadable Extension Thunk -** -** A pointer to the opaque sqlite3_api_routines structure is passed as -** the third parameter to entry points of [loadable extensions]. This -** structure must be typedefed in order to work around compiler warnings -** on some platforms. -*/ -typedef struct sqlite3_api_routines sqlite3_api_routines; - -/* -** CAPI3REF: File Name -** -** Type [sqlite3_filename] is used by SQLite to pass filenames to the -** xOpen method of a [VFS]. It may be cast to (const char*) and treated -** as a normal, nul-terminated, UTF-8 buffer containing the filename, but -** may also be passed to special APIs such as: -** -**
    -**
  • sqlite3_filename_database() -**
  • sqlite3_filename_journal() -**
  • sqlite3_filename_wal() -**
  • sqlite3_uri_parameter() -**
  • sqlite3_uri_boolean() -**
  • sqlite3_uri_int64() -**
  • sqlite3_uri_key() -**
-*/ -typedef const char *sqlite3_filename; - -/* -** CAPI3REF: OS Interface Object -** -** An instance of the sqlite3_vfs object defines the interface between -** the SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". See -** the [VFS | VFS documentation] for further information. -** -** The VFS interface is sometimes extended by adding new methods onto -** the end. Each time such an extension occurs, the iVersion field -** is incremented. The iVersion value started out as 1 in -** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 -** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased -** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields -** may be appended to the sqlite3_vfs object and the iVersion value -** may increase again in future versions of SQLite. -** Note that due to an oversight, the structure -** of the sqlite3_vfs object changed in the transition from -** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] -** and yet the iVersion field was not increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered sqlite3_vfs objects are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. Neither the application code nor the VFS -** implementation should use the pNext pointer. -** -** The pNext field is the only field in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** [[sqlite3_vfs.xOpen]] -** ^SQLite guarantees that the zFilename parameter to xOpen -** is either a NULL pointer or string obtained -** from xFullPathname() with an optional suffix added. -** ^If a suffix is added to the zFilename parameter, it will -** consist of a single "-" character followed by no more than -** 11 alphanumeric and/or "-" characters. -** ^SQLite further guarantees that -** the string will be valid and unchanged until xClose() is -** called. Because of the previous sentence, -** the [sqlite3_file] can safely store a pointer to the -** filename if it needs to remember the filename for some reason. -** If the zFilename parameter to xOpen is a NULL pointer then xOpen -** must invent its own temporary name for the file. ^Whenever the -** xFilename parameter is NULL it will also be the case that the -** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. -** -** The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. -** -** ^(SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_SUPER_JOURNAL] -**
  • [SQLITE_OPEN_WAL] -**
)^ -** -** The file I/O implementation can use the object type flags to -** change the way it deals with files. For example, an application -** that does not care about crash recovery or rollback might make -** the open of a journal file a no-op. Writes to this journal would -** also be no-ops, and any attempt to read the journal would return -** SQLITE_IOERR. Or the implementation might recognize that a database -** file will be doing page-aligned sector reads and writes in a random -** order and set up its I/O subsystem accordingly. -** -** SQLite might also add one of the following flags to the xOpen method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases and their journals, transient -** databases, and subjournals. -** -** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction -** with the [SQLITE_OPEN_CREATE] flag, which are both directly -** analogous to the O_EXCL and O_CREAT flags of the POSIX open() -** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the -** SQLITE_OPEN_CREATE, is used to indicate that file should always -** be created, and that it is an error if it already exists. -** It is not used to indicate the file should be opened -** for exclusive access. -** -** ^At least szOsFile bytes of memory are allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. The xOpen method does not have to -** allocate the structure; it should just fill it in. Note that -** the xOpen method must set the sqlite3_file.pMethods to either -** a valid [sqlite3_io_methods] object or to NULL. xOpen must do -** this even if the open fails. SQLite expects that the sqlite3_file.pMethods -** element will be valid after xOpen returns regardless of the success -** or failure of the xOpen call. -** -** [[sqlite3_vfs.xAccess]] -** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to -** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test whether a file is at least readable. The SQLITE_ACCESS_READ -** flag is never actually used and is not implemented in the built-in -** VFSes of SQLite. The file is named by the second argument and can be a -** directory. The xAccess method returns [SQLITE_OK] on success or some -** non-zero error code if there is an I/O error or if the name of -** the file given in the second argument is illegal. If SQLITE_OK -** is returned, then non-zero or zero is written into *pResOut to indicate -** whether or not the file is accessible. -** -** ^SQLite will always allocate at least mxPathname+1 bytes for the -** output buffer xFullPathname. The exact size of the output buffer -** is also passed as a parameter to both methods. If the output buffer -** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is -** handled as a fatal error by SQLite, vfs implementations should endeavor -** to prevent this by setting mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() -** interfaces are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. -** The xSleep() method causes the calling thread to sleep for at -** least the number of microseconds given. ^The xCurrentTime() -** method returns a Julian Day Number for the current date and time as -** a floating point value. -** ^The xCurrentTimeInt64() method returns, as an integer, the Julian -** Day Number multiplied by 86400000 (the number of milliseconds in -** a 24-hour day). -** ^SQLite will use the xCurrentTimeInt64() method to get the current -** date and time if that method is available (if iVersion is 2 or -** greater and the function pointer is not NULL) and will fall back -** to xCurrentTime() if xCurrentTimeInt64() is unavailable. -** -** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces -** are not used by the SQLite core. These optional interfaces are provided -** by some VFSes to facilitate testing of the VFS code. By overriding -** system calls with functions under its control, a test program can -** simulate faults and error conditions that would otherwise be difficult -** or impossible to induce. The set of system calls that can be overridden -** varies from one VFS to another, and from one version of the same VFS to the -** next. Applications that use these interfaces must be prepared for any -** or all of these interfaces to be NULL or for their behavior to change -** from one release to the next. Applications must not attempt to access -** any of these methods if the iVersion of the VFS is less than 3. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -typedef void (*sqlite3_syscall_ptr)(void); -struct sqlite3_vfs { - int iVersion; /* Structure version number (currently 3) */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - int (*xGetLastError)(sqlite3_vfs*, int, char *); - /* - ** The methods above are in version 1 of the sqlite_vfs object - ** definition. Those that follow are added in version 2 or later - */ - int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); - /* - ** The methods above are in versions 1 and 2 of the sqlite_vfs object. - ** Those below are for version 3 and greater. - */ - int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); - sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); - const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); - /* - ** The methods above are in versions 1 through 3 of the sqlite_vfs object. - ** New fields may be appended in future versions. The iVersion - ** value will increment whenever this happens. - */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method -** -** These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. They determine -** what kind of permissions the xAccess method is looking for. -** With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks whether the file exists. -** With SQLITE_ACCESS_READWRITE, the xAccess method -** checks whether the named directory is both readable and writable -** (in other words, if files can be added, removed, and renamed within -** the directory). -** The SQLITE_ACCESS_READWRITE constant is currently used only by the -** [temp_store_directory pragma], though this could change in a future -** release of SQLite. -** With SQLITE_ACCESS_READ, the xAccess method -** checks whether the file is readable. The SQLITE_ACCESS_READ constant is -** currently unused, though it might be used in a future release of -** SQLite. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ -#define SQLITE_ACCESS_READ 2 /* Unused */ - -/* -** CAPI3REF: Flags for the xShmLock VFS method -** -** These integer constants define the various locking operations -** allowed by the xShmLock method of [sqlite3_io_methods]. The -** following are the only legal combinations of flags to the -** xShmLock method: -** -**
    -**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED -**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE -**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED -**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE -**
-** -** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given on the corresponding lock. -** -** The xShmLock method can transition between unlocked and SHARED or -** between unlocked and EXCLUSIVE. It cannot transition between SHARED -** and EXCLUSIVE. -*/ -#define SQLITE_SHM_UNLOCK 1 -#define SQLITE_SHM_LOCK 2 -#define SQLITE_SHM_SHARED 4 -#define SQLITE_SHM_EXCLUSIVE 8 - -/* -** CAPI3REF: Maximum xShmLock index -** -** The xShmLock method on [sqlite3_io_methods] may use values -** between 0 and this upper bound as its "offset" argument. -** The SQLite core will never attempt to acquire or release a -** lock outside of this range -*/ -#define SQLITE_SHM_NLOCK 8 - - -/* -** CAPI3REF: Initialize The SQLite Library -** -** ^The sqlite3_initialize() routine initializes the -** SQLite library. ^The sqlite3_shutdown() routine -** deallocates any resources that were allocated by sqlite3_initialize(). -** These routines are designed to aid in process initialization and -** shutdown on embedded systems. Workstation applications using -** SQLite normally do not need to invoke either of these routines. -** -** A call to sqlite3_initialize() is an "effective" call if it is -** the first time sqlite3_initialize() is invoked during the lifetime of -** the process, or if it is the first time sqlite3_initialize() is invoked -** following a call to sqlite3_shutdown(). ^(Only an effective call -** of sqlite3_initialize() does any initialization. All other calls -** are harmless no-ops.)^ -** -** A call to sqlite3_shutdown() is an "effective" call if it is the first -** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only -** an effective call to sqlite3_shutdown() does any deinitialization. -** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ -** -** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() -** is not. The sqlite3_shutdown() interface must only be called from a -** single thread. All open [database connections] must be closed and all -** other SQLite resources must be deallocated prior to invoking -** sqlite3_shutdown(). -** -** Among other things, ^sqlite3_initialize() will invoke -** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() -** will invoke sqlite3_os_end(). -** -** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. -** ^If for some reason, sqlite3_initialize() is unable to initialize -** the library (perhaps it is unable to allocate a needed resource such -** as a mutex) it returns an [error code] other than [SQLITE_OK]. -** -** ^The sqlite3_initialize() routine is called internally by many other -** SQLite interfaces so that an application usually does not need to -** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] -** calls sqlite3_initialize() so the SQLite library will be automatically -** initialized when [sqlite3_open()] is called if it has not be initialized -** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] -** compile-time option, then the automatic calls to sqlite3_initialize() -** are omitted and the application must call sqlite3_initialize() directly -** prior to using any other SQLite interface. For maximum portability, -** it is recommended that applications always invoke sqlite3_initialize() -** directly prior to using any other SQLite interface. Future releases -** of SQLite may require this. In other words, the behavior exhibited -** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the -** default behavior in some future release of SQLite. -** -** The sqlite3_os_init() routine does operating-system specific -** initialization of the SQLite library. The sqlite3_os_end() -** routine undoes the effect of sqlite3_os_init(). Typical tasks -** performed by these routines include allocation or deallocation -** of static resources, initialization of global variables, -** setting up a default [sqlite3_vfs] module, or setting up -** a default configuration using [sqlite3_config()]. -** -** The application should never invoke either sqlite3_os_init() -** or sqlite3_os_end() directly. The application should only invoke -** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() -** interface is called automatically by sqlite3_initialize() and -** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate -** implementations for sqlite3_os_init() and sqlite3_os_end() -** are built into SQLite when it is compiled for Unix, Windows, or OS/2. -** When [custom builds | built for other platforms] -** (using the [SQLITE_OS_OTHER=1] compile-time -** option) the application must supply a suitable implementation for -** sqlite3_os_init() and sqlite3_os_end(). An application-supplied -** implementation of sqlite3_os_init() or sqlite3_os_end() -** must return [SQLITE_OK] on success and some other [error code] upon -** failure. -*/ -SQLITE_API int sqlite3_initialize(void); -SQLITE_API int sqlite3_shutdown(void); -SQLITE_API int sqlite3_os_init(void); -SQLITE_API int sqlite3_os_end(void); - -/* -** CAPI3REF: Configuring The SQLite Library -** -** The sqlite3_config() interface is used to make global configuration -** changes to SQLite in order to tune SQLite to the specific needs of -** the application. The default configuration is recommended for most -** applications and so this routine is usually not necessary. It is -** provided to support rare applications with unusual needs. -** -** The sqlite3_config() interface is not threadsafe. The application -** must ensure that no other SQLite interfaces are invoked by other -** threads while sqlite3_config() is running. -** -** The first argument to sqlite3_config() is an integer -** [configuration option] that determines -** what property of SQLite is to be configured. Subsequent arguments -** vary depending on the [configuration option] -** in the first argument. -** -** For most configuration options, the sqlite3_config() interface -** may only be invoked prior to library initialization using -** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. -** The exceptional configuration options that may be invoked at any time -** are called "anytime configuration options". -** ^If sqlite3_config() is called after [sqlite3_initialize()] and before -** [sqlite3_shutdown()] with a first argument that is not an anytime -** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE. -** Note, however, that ^sqlite3_config() can be called as part of the -** implementation of an application-defined [sqlite3_os_init()]. -** -** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. -** ^If the option is unknown or SQLite is unable to set the option -** then this routine returns a non-zero [error code]. -*/ -SQLITE_API int sqlite3_config(int, ...); - -/* -** CAPI3REF: Configure database connections -** METHOD: sqlite3 -** -** The sqlite3_db_config() interface is used to make configuration -** changes to a [database connection]. The interface is similar to -** [sqlite3_config()] except that the changes apply to a single -** [database connection] (specified in the first argument). -** -** The second argument to sqlite3_db_config(D,V,...) is the -** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code -** that indicates what aspect of the [database connection] is being configured. -** Subsequent arguments vary depending on the configuration verb. -** -** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if -** the call is considered successful. -*/ -SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); - -/* -** CAPI3REF: Memory Allocation Routines -** -** An instance of this object defines the interface between SQLite -** and low-level memory allocation routines. -** -** This object is used in only one place in the SQLite interface. -** A pointer to an instance of this object is the argument to -** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. -** By creating an instance of this object -** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) -** during configuration, an application can specify an alternative -** memory allocation subsystem for SQLite to use for all of its -** dynamic memory needs. -** -** Note that SQLite comes with several [built-in memory allocators] -** that are perfectly adequate for the overwhelming majority of applications -** and that this object is only useful to a tiny minority of applications -** with specialized memory allocation requirements. This object is -** also used during testing of SQLite in order to specify an alternative -** memory allocator that simulates memory out-of-memory conditions in -** order to verify that SQLite recovers gracefully from such -** conditions. -** -** The xMalloc, xRealloc, and xFree methods must work like the -** malloc(), realloc() and free() functions from the standard C library. -** ^SQLite guarantees that the second argument to -** xRealloc is always a value returned by a prior call to xRoundup. -** -** xSize should return the allocated size of a memory allocation -** previously obtained from xMalloc or xRealloc. The allocated size -** is always at least as big as the requested size but may be larger. -** -** The xRoundup method returns what would be the allocated size of -** a memory allocation given a particular requested size. Most memory -** allocators round up memory allocations at least to the next multiple -** of 8. Some allocators round up to a larger multiple or to a power of 2. -** Every memory allocation request coming in through [sqlite3_malloc()] -** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, -** that causes the corresponding memory allocation to fail. -** -** The xInit method initializes the memory allocator. For example, -** it might allocate any required mutexes or initialize internal data -** structures. The xShutdown method is invoked (indirectly) by -** [sqlite3_shutdown()] and should deallocate any resources acquired -** by xInit. The pAppData pointer is used as the only parameter to -** xInit and xShutdown. -** -** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes -** the xInit method, so the xInit method need not be threadsafe. The -** xShutdown method is only called from [sqlite3_shutdown()] so it does -** not need to be threadsafe either. For all other methods, SQLite -** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the -** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which -** it is by default) and so the methods are automatically serialized. -** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other -** methods must be threadsafe or else make their own arrangements for -** serialization. -** -** SQLite will never invoke xInit() more than once without an intervening -** call to xShutdown(). -*/ -typedef struct sqlite3_mem_methods sqlite3_mem_methods; -struct sqlite3_mem_methods { - void *(*xMalloc)(int); /* Memory allocation function */ - void (*xFree)(void*); /* Free a prior allocation */ - void *(*xRealloc)(void*,int); /* Resize an allocation */ - int (*xSize)(void*); /* Return the size of an allocation */ - int (*xRoundup)(int); /* Round up request size to allocation size */ - int (*xInit)(void*); /* Initialize the memory allocator */ - void (*xShutdown)(void*); /* Deinitialize the memory allocator */ - void *pAppData; /* Argument to xInit() and xShutdown() */ -}; - -/* -** CAPI3REF: Configuration Options -** KEYWORDS: {configuration option} -** -** These constants are the available integer configuration options that -** can be passed as the first argument to the [sqlite3_config()] interface. -** -** Most of the configuration options for sqlite3_config() -** will only work if invoked prior to [sqlite3_initialize()] or after -** [sqlite3_shutdown()]. The few exceptions to this rule are called -** "anytime configuration options". -** ^Calling [sqlite3_config()] with a first argument that is not an -** anytime configuration option in between calls to [sqlite3_initialize()] and -** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE. -** -** The set of anytime configuration options can change (by insertions -** and/or deletions) from one release of SQLite to the next. -** As of SQLite version 3.42.0, the complete set of anytime configuration -** options is: -**
    -**
  • SQLITE_CONFIG_LOG -**
  • SQLITE_CONFIG_PCACHE_HDRSZ -**
-** -** New configuration options may be added in future releases of SQLite. -** Existing configuration options might be discontinued. Applications -** should check the return code from [sqlite3_config()] to make sure that -** the call worked. The [sqlite3_config()] interface will return a -** non-zero [error code] if a discontinued or unsupported configuration option -** is invoked. -** -**
-** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Single-thread. In other words, it disables -** all mutexing and puts SQLite into a mode where it can only be used -** by a single thread. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to change the [threading mode] from its default -** value of Single-thread and so [sqlite3_config()] will return -** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD -** configuration option.
-** -** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Multi-thread. In other words, it disables -** mutexing on [database connection] and [prepared statement] objects. -** The application is responsible for serializing access to -** [database connections] and [prepared statements]. But other mutexes -** are enabled so that SQLite will be safe to use in a multi-threaded -** environment as long as no two threads attempt to use the same -** [database connection] at the same time. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Multi-thread [threading mode] and -** [sqlite3_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_MULTITHREAD configuration option.
-** -** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Serialized. In other words, this option enables -** all mutexes including the recursive -** mutexes on [database connection] and [prepared statement] objects. -** In this mode (which is the default when SQLite is compiled with -** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access -** to [database connections] and [prepared statements] so that the -** application is free to use the same [database connection] or the -** same [prepared statement] in different threads at the same time. -** ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Serialized [threading mode] and -** [sqlite3_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_SERIALIZED configuration option.
-** -** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
-**
^(The SQLITE_CONFIG_MALLOC option takes a single argument which is -** a pointer to an instance of the [sqlite3_mem_methods] structure. -** The argument specifies -** alternative low-level memory allocation routines to be used in place of -** the memory allocation routines built into SQLite.)^ ^SQLite makes -** its own private copy of the content of the [sqlite3_mem_methods] structure -** before the [sqlite3_config()] call returns.
-** -** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
-**
^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which -** is a pointer to an instance of the [sqlite3_mem_methods] structure. -** The [sqlite3_mem_methods] -** structure is filled with the currently defined memory allocation routines.)^ -** This option can be used to overload the default memory allocation -** routines with a wrapper that simulations memory allocation failure or -** tracks memory usage, for example.
-** -** [[SQLITE_CONFIG_SMALL_MALLOC]]
SQLITE_CONFIG_SMALL_MALLOC
-**
^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of -** type int, interpreted as a boolean, which if true provides a hint to -** SQLite that it should avoid large memory allocations if possible. -** SQLite will run faster if it is free to make large memory allocations, -** but some application might prefer to run slower in exchange for -** guarantees about memory fragmentation that are possible if large -** allocations are avoided. This hint is normally off. -**
-** -** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
-**
^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, -** interpreted as a boolean, which enables or disables the collection of -** memory allocation statistics. ^(When memory allocation statistics are -** disabled, the following SQLite interfaces become non-operational: -**
    -**
  • [sqlite3_hard_heap_limit64()] -**
  • [sqlite3_memory_used()] -**
  • [sqlite3_memory_highwater()] -**
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status64()] -**
)^ -** ^Memory allocation statistics are enabled by default unless SQLite is -** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory -** allocation statistics are disabled by default. -**
-** -** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
-**
The SQLITE_CONFIG_SCRATCH option is no longer used. -**
-** -** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
-**
^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool -** that SQLite can use for the database page cache with the default page -** cache implementation. -** This configuration option is a no-op if an application-defined page -** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. -** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to -** 8-byte aligned memory (pMem), the size of each page cache line (sz), -** and the number of cache lines (N). -** The sz argument should be the size of the largest database page -** (a power of two between 512 and 65536) plus some extra bytes for each -** page header. ^The number of extra bytes needed by the page header -** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ]. -** ^It is harmless, apart from the wasted memory, -** for the sz parameter to be larger than necessary. The pMem -** argument must be either a NULL pointer or a pointer to an 8-byte -** aligned block of memory of at least sz*N bytes, otherwise -** subsequent behavior is undefined. -** ^When pMem is not NULL, SQLite will strive to use the memory provided -** to satisfy page cache needs, falling back to [sqlite3_malloc()] if -** a page cache line is larger than sz bytes or if all of the pMem buffer -** is exhausted. -** ^If pMem is NULL and N is non-zero, then each database connection -** does an initial bulk allocation for page cache memory -** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or -** of -1024*N bytes if N is negative, . ^If additional -** page cache memory is needed beyond what is provided by the initial -** allocation, then SQLite goes to [sqlite3_malloc()] separately for each -** additional cache line.
-** -** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
-**
^The SQLITE_CONFIG_HEAP option specifies a static memory buffer -** that SQLite will use for all of its dynamic memory allocation needs -** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. -** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled -** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns -** [SQLITE_ERROR] if invoked otherwise. -** ^There are three arguments to SQLITE_CONFIG_HEAP: -** An 8-byte aligned pointer to the memory, -** the number of bytes in the memory buffer, and the minimum allocation size. -** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts -** to using its default memory allocator (the system malloc() implementation), -** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the -** memory pointer is not NULL then the alternative memory -** allocator is engaged to handle all of SQLites memory allocation needs. -** The first pointer (the memory pointer) must be aligned to an 8-byte -** boundary or subsequent behavior of SQLite will be undefined. -** The minimum allocation size is capped at 2**12. Reasonable values -** for the minimum allocation size are 2**5 through 2**8.
-** -** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
-**
^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a -** pointer to an instance of the [sqlite3_mutex_methods] structure. -** The argument specifies alternative low-level mutex routines to be used -** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of -** the content of the [sqlite3_mutex_methods] structure before the call to -** [sqlite3_config()] returns. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
-**
^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which -** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The -** [sqlite3_mutex_methods] -** structure is filled with the currently defined mutex routines.)^ -** This option can be used to overload the default mutex allocation -** routines with a wrapper used to track mutex usage for performance -** profiling or testing, for example. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
-**
^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine -** the default size of [lookaside memory] on each [database connection]. -** The first argument is the -** size of each lookaside buffer slot ("sz") and the second is the number of -** slots allocated to each database connection ("cnt").)^ -** ^(SQLITE_CONFIG_LOOKASIDE sets the default lookaside size. -** The [SQLITE_DBCONFIG_LOOKASIDE] option to [sqlite3_db_config()] can -** be used to change the lookaside configuration on individual connections.)^ -** The [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to change the -** default lookaside configuration at compile-time. -**
-** -** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
-**
^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is -** a pointer to an [sqlite3_pcache_methods2] object. This object specifies -** the interface to a custom page cache implementation.)^ -** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
-** -** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
-**
^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of -** the current page cache implementation into that object.)^
-** -** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
-**
The SQLITE_CONFIG_LOG option is used to configure the SQLite -** global [error log]. -** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,int,const char*), -** and a pointer to void. ^If the function pointer is not NULL, it is -** invoked by [sqlite3_log()] to process each logging event. ^If the -** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. -** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is -** passed through as the first parameter to the application-defined logger -** function whenever that function is invoked. ^The second parameter to -** the logger function is a copy of the first parameter to the corresponding -** [sqlite3_log()] call and is intended to be a [result code] or an -** [extended result code]. ^The third parameter passed to the logger is -** log message after formatting via [sqlite3_snprintf()]. -** The SQLite logging interface is not reentrant; the logger function -** supplied by the application must not invoke any SQLite interface. -** In a multi-threaded application, the application-defined logger -** function must be threadsafe.
-** -** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI -**
^(The SQLITE_CONFIG_URI option takes a single argument of type int. -** If non-zero, then URI handling is globally enabled. If the parameter is zero, -** then URI handling is globally disabled.)^ ^If URI handling is globally -** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], -** [sqlite3_open16()] or -** specified as part of [ATTACH] commands are interpreted as URIs, regardless -** of whether or not the [SQLITE_OPEN_URI] flag is set when the database -** connection is opened. ^If it is globally disabled, filenames are -** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the -** database connection is opened. ^(By default, URI handling is globally -** disabled. The default value may be changed by compiling with the -** [SQLITE_USE_URI] symbol defined.)^ -** -** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN -**
^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer -** argument which is interpreted as a boolean in order to enable or disable -** the use of covering indices for full table scans in the query optimizer. -** ^The default setting is determined -** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" -** if that compile-time option is omitted. -** The ability to disable the use of covering indices for full table scans -** is because some incorrectly coded legacy applications might malfunction -** when the optimization is enabled. Providing the ability to -** disable the optimization allows the older, buggy application code to work -** without change even with newer versions of SQLite. -** -** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] -**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE -**
These options are obsolete and should not be used by new code. -** They are retained for backwards compatibility but are now no-ops. -**
-** -** [[SQLITE_CONFIG_SQLLOG]] -**
SQLITE_CONFIG_SQLLOG -**
This option is only available if sqlite is compiled with the -** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should -** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). -** The second should be of type (void*). The callback is invoked by the library -** in three separate circumstances, identified by the value passed as the -** fourth parameter. If the fourth parameter is 0, then the database connection -** passed as the second argument has just been opened. The third argument -** points to a buffer containing the name of the main database file. If the -** fourth parameter is 1, then the SQL statement that the third parameter -** points to has just been executed. Or, if the fourth parameter is 2, then -** the connection being passed as the second parameter is being closed. The -** third parameter is passed NULL In this case. An example of using this -** configuration option can be seen in the "test_sqllog.c" source file in -** the canonical SQLite source tree.
-** -** [[SQLITE_CONFIG_MMAP_SIZE]] -**
SQLITE_CONFIG_MMAP_SIZE -**
^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values -** that are the default mmap size limit (the default setting for -** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. -** ^The default setting can be overridden by each database connection using -** either the [PRAGMA mmap_size] command, or by using the -** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size -** will be silently truncated if necessary so that it does not exceed the -** compile-time maximum mmap size set by the -** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ -** ^If either argument to this option is negative, then that argument is -** changed to its compile-time default. -** -** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] -**
SQLITE_CONFIG_WIN32_HEAPSIZE -**
^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is -** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro -** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value -** that specifies the maximum size of the created heap. -** -** [[SQLITE_CONFIG_PCACHE_HDRSZ]] -**
SQLITE_CONFIG_PCACHE_HDRSZ -**
^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which -** is a pointer to an integer and writes into that integer the number of extra -** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. -** The amount of extra space required can change depending on the compiler, -** target platform, and SQLite version. -** -** [[SQLITE_CONFIG_PMASZ]] -**
SQLITE_CONFIG_PMASZ -**
^The SQLITE_CONFIG_PMASZ option takes a single parameter which -** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded -** sorter to that integer. The default minimum PMA Size is set by the -** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched -** to help with sort operations when multithreaded sorting -** is enabled (using the [PRAGMA threads] command) and the amount of content -** to be sorted exceeds the page size times the minimum of the -** [PRAGMA cache_size] setting and this value. -** -** [[SQLITE_CONFIG_STMTJRNL_SPILL]] -**
SQLITE_CONFIG_STMTJRNL_SPILL -**
^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which -** becomes the [statement journal] spill-to-disk threshold. -** [Statement journals] are held in memory until their size (in bytes) -** exceeds this threshold, at which point they are written to disk. -** Or if the threshold is -1, statement journals are always held -** exclusively in memory. -** Since many statement journals never become large, setting the spill -** threshold to a value such as 64KiB can greatly reduce the amount of -** I/O required to support statement rollback. -** The default value for this setting is controlled by the -** [SQLITE_STMTJRNL_SPILL] compile-time option. -** -** [[SQLITE_CONFIG_SORTERREF_SIZE]] -**
SQLITE_CONFIG_SORTERREF_SIZE -**
The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter -** of type (int) - the new value of the sorter-reference size threshold. -** Usually, when SQLite uses an external sort to order records according -** to an ORDER BY clause, all fields required by the caller are present in the -** sorted records. However, if SQLite determines based on the declared type -** of a table column that its values are likely to be very large - larger -** than the configured sorter-reference size threshold - then a reference -** is stored in each sorted record and the required column values loaded -** from the database as records are returned in sorted order. The default -** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behavior. -** This option is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. -** -** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] -**
SQLITE_CONFIG_MEMDB_MAXSIZE -**
The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter -** [sqlite3_int64] parameter which is the default maximum size for an in-memory -** database created using [sqlite3_deserialize()]. This default maximum -** size can be adjusted up or down for individual databases using the -** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this -** configuration setting is never used, then the default maximum is determined -** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that -** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_ROWID_IN_VIEW]] -**
SQLITE_CONFIG_ROWID_IN_VIEW -**
The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability -** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is -** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability -** defaults to on. This configuration option queries the current setting or -** changes the setting to off or on. The argument is a pointer to an integer. -** If that integer initially holds a value of 1, then the ability for VIEWs to -** have ROWIDs is activated. If the integer initially holds zero, then the -** ability is deactivated. Any other initial value for the integer leaves the -** setting unchanged. After changes, if any, the integer is written with -** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite -** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and -** recommended case) then the integer is always filled with zero, regardless -** if its initial value. -**
-*/ -#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ -#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ -#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ -#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ -#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ -#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ -#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ -#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ -#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ -/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ -#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ -#define SQLITE_CONFIG_PCACHE 14 /* no-op */ -#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ -#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ -#define SQLITE_CONFIG_URI 17 /* int */ -#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ -#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ -#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ -#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ -#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ -#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ -#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ -#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ -#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ -#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ - -/* -** CAPI3REF: Database Connection Configuration Options -** -** These constants are the available integer configuration options that -** can be passed as the second parameter to the [sqlite3_db_config()] interface. -** -** The [sqlite3_db_config()] interface is a var-args functions. It takes a -** variable number of parameters, though always at least two. The number of -** parameters passed into sqlite3_db_config() depends on which of these -** constants is given as the second parameter. This documentation page -** refers to parameters beyond the second as "arguments". Thus, when this -** page says "the N-th argument" it means "the N-th parameter past the -** configuration option" or "the (N+2)-th parameter to sqlite3_db_config()". -** -** New configuration options may be added in future releases of SQLite. -** Existing configuration options might be discontinued. Applications -** should check the return code from [sqlite3_db_config()] to make sure that -** the call worked. ^The [sqlite3_db_config()] interface will return a -** non-zero [error code] if a discontinued or unsupported configuration option -** is invoked. -** -**
-** [[SQLITE_DBCONFIG_LOOKASIDE]] -**
SQLITE_DBCONFIG_LOOKASIDE
-**
The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the -** configuration of the [lookaside memory allocator] within a database -** connection. -** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are not -** in the [DBCONFIG arguments|usual format]. -** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two, -** so that a call to [sqlite3_db_config()] that uses SQLITE_DBCONFIG_LOOKASIDE -** should have a total of five parameters. -**
    -**
  1. The first argument ("buf") is a -** pointer to a memory buffer to use for lookaside memory. -** The first argument may be NULL in which case SQLite will allocate the -** lookaside buffer itself using [sqlite3_malloc()]. -**

  2. The second argument ("sz") is the -** size of each lookaside buffer slot. Lookaside is disabled if "sz" -** is less than 8. The "sz" argument should be a multiple of 8 less than -** 65536. If "sz" does not meet this constraint, it is reduced in size until -** it does. -**

  3. The third argument ("cnt") is the number of slots. Lookaside is disabled -** if "cnt"is less than 1. The "cnt" value will be reduced, if necessary, so -** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt" -** parameter is usually chosen so that the product of "sz" and "cnt" is less -** than 1,000,000. -**

-**

If the "buf" argument is not NULL, then it must -** point to a memory buffer with a size that is greater than -** or equal to the product of "sz" and "cnt". -** The buffer must be aligned to an 8-byte boundary. -** The lookaside memory -** configuration for a database connection can only be changed when that -** connection is not currently using lookaside memory, or in other words -** when the value returned by [SQLITE_DBSTATUS_LOOKASIDE_USED] is zero. -** Any attempt to change the lookaside memory configuration when lookaside -** memory is in use leaves the configuration unchanged and returns -** [SQLITE_BUSY]. -** If the "buf" argument is NULL and an attempt -** to allocate memory based on "sz" and "cnt" fails, then -** lookaside is silently disabled. -**

-** The [SQLITE_CONFIG_LOOKASIDE] configuration option can be used to set the -** default lookaside configuration at initialization. The -** [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to set the default lookaside -** configuration at compile-time. Typical values for lookaside are 1200 for -** "sz" and 40 to 100 for "cnt". -**

-** -** [[SQLITE_DBCONFIG_ENABLE_FKEY]] -**
SQLITE_DBCONFIG_ENABLE_FKEY
-**
^This option is used to enable or disable the enforcement of -** [foreign key constraints]. This is the same setting that is -** enabled or disabled by the [PRAGMA foreign_keys] statement. -** The first argument is an integer which is 0 to disable FK enforcement, -** positive to enable FK enforcement or negative to leave FK enforcement -** unchanged. The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether FK enforcement is off or on -** following this call. The second parameter may be a NULL pointer, in -** which case the FK enforcement setting is not reported back.
-** -** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] -**
SQLITE_DBCONFIG_ENABLE_TRIGGER
-**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. -** There should be two additional arguments. -** The first argument is an integer which is 0 to disable triggers, -** positive to enable triggers or negative to leave the setting unchanged. -** 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. -** -**

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.)^

-** -** [[SQLITE_DBCONFIG_ENABLE_VIEW]] -**
SQLITE_DBCONFIG_ENABLE_VIEW
-**
^This option is used to enable or disable [CREATE VIEW | views]. -** There must be two additional arguments. -** The first argument is an integer which is 0 to disable views, -** positive to enable views or negative to leave the setting unchanged. -** 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. -** -**

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.)^

-** -** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] -**
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
-**
^This option is used to enable or disable the -** [fts3_tokenizer()] function which is part of the -** [FTS3] full-text search engine extension. -** There must be two additional arguments. -** The first argument is an integer which is 0 to disable fts3_tokenizer() or -** positive to enable fts3_tokenizer() or negative to leave the setting -** unchanged. -** The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled -** following this call. The second parameter may be a NULL pointer, in -** which case the new setting is not reported back.
-** -** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] -**
SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
-**
^This option is used to enable or disable the [sqlite3_load_extension()] -** interface independently of the [load_extension()] SQL function. -** The [sqlite3_enable_load_extension()] API enables or disables both the -** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. -** There must be two additional arguments. -** When the first argument to this interface is 1, then only the C-API is -** enabled and the SQL function remains disabled. If the first argument to -** this interface is 0, then both the C-API and the SQL function are disabled. -** If the first argument is -1, then no changes are made to state of either the -** C-API or the SQL function. -** The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface -** is disabled or enabled following this call. The second parameter may -** be a NULL pointer, in which case the new setting is not reported back. -**
-** -** [[SQLITE_DBCONFIG_MAINDBNAME]]
SQLITE_DBCONFIG_MAINDBNAME
-**
^This option is used to change the name of the "main" database -** schema. This option does not follow the -** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format]. -** This option takes exactly one additional argument so that the -** [sqlite3_db_config()] call has a total of three parameters. The -** extra argument must be a pointer to a constant UTF8 string which -** will become the new schema name in place of "main". ^SQLite does -** not make a copy of the new main schema name string, so the application -** must ensure that the argument passed into SQLITE_DBCONFIG MAINDBNAME -** is unchanged until after the database connection closes. -**
-** -** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] -**
SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
-**
Usually, when a database in [WAL mode] is closed or detached from a -** database handle, SQLite checks if if there are other connections to the -** same database, and if there are no other database connection (if the -** connection being closed is the last open connection to the database), -** then SQLite performs a [checkpoint] before closing the connection and -** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can -** be used to override that behavior. The first argument passed to this -** operation (the third parameter to [sqlite3_db_config()]) is an integer -** which is positive to disable checkpoints-on-close, or zero (the default) -** to enable them, and negative to leave the setting unchanged. -** The second argument (the fourth parameter) is a pointer to an integer -** into which is written 0 or 1 to indicate whether checkpoints-on-close -** have been disabled - 0 if they are not disabled, 1 if they are. -**
-** -** [[SQLITE_DBCONFIG_ENABLE_QPSG]]
SQLITE_DBCONFIG_ENABLE_QPSG
-**
^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates -** the [query planner stability guarantee] (QPSG). When the QPSG is active, -** a single SQL query statement will always use the same algorithm regardless -** of values of [bound parameters].)^ The QPSG disables some query optimizations -** that look at the values of bound parameters, which can make some queries -** slower. But the QPSG has the advantage of more predictable behavior. With -** the QPSG active, SQLite will always use the same query plan in the field as -** was used during testing in the lab. -** The first argument to this setting is an integer which is 0 to disable -** the QPSG, positive to enable QPSG, or negative to leave the setting -** unchanged. The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether the QPSG is disabled or enabled -** following this call. -**
-** -** [[SQLITE_DBCONFIG_TRIGGER_EQP]]
SQLITE_DBCONFIG_TRIGGER_EQP
-**
By default, the output of EXPLAIN QUERY PLAN commands does not -** include output for any operations performed by trigger programs. This -** option is used to set or clear (the default) a flag that governs this -** behavior. The first parameter passed to this operation is an integer - -** positive to enable output for trigger programs, or zero to disable it, -** or negative to leave the setting unchanged. -** The second parameter is a pointer to an integer into which is written -** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if -** it is not disabled, 1 if it is. -**
-** -** [[SQLITE_DBCONFIG_RESET_DATABASE]]
SQLITE_DBCONFIG_RESET_DATABASE
-**
Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run -** [VACUUM] in order to reset a database back to an empty database -** with no schema and no content. The following process works even for -** a badly corrupted database file: -**
    -**
  1. If the database connection is newly opened, make sure it has read the -** database schema by preparing then discarding some query against the -** database, or calling sqlite3_table_column_metadata(), ignoring any -** errors. This step is only necessary if the application desires to keep -** the database in WAL mode after the reset if it was in WAL mode before -** the reset. -**
  2. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); -**
  3. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); -**
  4. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); -**
-** Because resetting a database is destructive and irreversible, the -** process requires the use of this obscure API and multiple steps to -** help ensure that it does not happen by accident. Because this -** feature must be capable of resetting corrupt databases, and -** shutting down virtual tables may require access to that corrupt -** storage, the library must abandon any installed virtual tables -** without calling their xDestroy() methods. -** -** [[SQLITE_DBCONFIG_DEFENSIVE]]
SQLITE_DBCONFIG_DEFENSIVE
-**
The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the -** "defensive" flag for a database connection. When the defensive -** flag is enabled, language features that allow ordinary SQL to -** deliberately corrupt the database file are disabled. The disabled -** features include but are not limited to the following: -**
    -**
  • The [PRAGMA writable_schema=ON] statement. -**
  • The [PRAGMA journal_mode=OFF] statement. -**
  • The [PRAGMA schema_version=N] statement. -**
  • Writes to the [sqlite_dbpage] virtual table. -**
  • Direct writes to [shadow tables]. -**
-**
-** -** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
SQLITE_DBCONFIG_WRITABLE_SCHEMA
-**
The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the -** "writable_schema" flag. This has the same effect and is logically equivalent -** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. -** The first argument to this setting is an integer which is 0 to disable -** the writable_schema, positive to enable writable_schema, or negative to -** leave the setting unchanged. The second parameter is a pointer to an -** integer into which is written 0 or 1 to indicate whether the writable_schema -** is enabled or disabled following this call. -**
-** -** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] -**
SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
-**
The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates -** the legacy behavior of the [ALTER TABLE RENAME] command such it -** behaves as it did prior to [version 3.24.0] (2018-06-04). See the -** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for -** additional information. This feature can also be turned on and off -** using the [PRAGMA legacy_alter_table] statement. -**
-** -** [[SQLITE_DBCONFIG_DQS_DML]] -**
SQLITE_DBCONFIG_DQS_DML
-**
The SQLITE_DBCONFIG_DQS_DML option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DML statements -** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
-** -** [[SQLITE_DBCONFIG_DQS_DDL]] -**
SQLITE_DBCONFIG_DQS_DDL
-**
The SQLITE_DBCONFIG_DQS option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DDL statements, -** such as CREATE TABLE and CREATE INDEX. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
-** -** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] -**
SQLITE_DBCONFIG_TRUSTED_SCHEMA
-**
The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to -** assume that database schemas are untainted by malicious content. -** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite -** takes additional defensive steps to protect the application from harm -** including: -**
    -**
  • Prohibit the use of SQL functions inside triggers, views, -** CHECK constraints, DEFAULT clauses, expression indexes, -** partial indexes, or generated columns -** unless those functions are tagged with [SQLITE_INNOCUOUS]. -**
  • Prohibit the use of virtual tables inside of triggers or views -** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS]. -**
-** This setting defaults to "on" for legacy compatibility, however -** all applications are advised to turn it off if possible. This setting -** can also be controlled using the [PRAGMA trusted_schema] statement. -**
-** -** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] -**
SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
-**
The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates -** the legacy file format flag. When activated, this flag causes all newly -** created database file to have a schema format version number (the 4-byte -** integer found at offset 44 into the database header) of 1. This in turn -** means that the resulting database file will be readable and writable by -** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, -** newly created databases are generally not understandable by SQLite versions -** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there -** is now scarcely any need to generate database files that are compatible -** all the way back to version 3.0.0, and so this setting is of little -** practical use, but is provided so that SQLite can continue to claim the -** ability to generate new database files that are compatible with version -** 3.0.0. -**

Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, -** the [VACUUM] command will fail with an obscure error when attempting to -** process a table with generated columns and a descending index. This is -** not considered a bug since SQLite versions 3.3.0 and earlier do not support -** either generated columns or descending indexes. -**

-** -** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] -**
SQLITE_DBCONFIG_STMT_SCANSTATUS
-**
The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears -** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() -** statistics. For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is prepared and when it -** is stepped. The flag is set (collection of statistics is enabled) -** by default.

This option takes two arguments: an integer and a pointer to -** an integer.. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the statement scanstatus option. If the second argument -** is not NULL, then the value of the statement scanstatus setting after -** processing the first argument is written into the integer that the second -** argument points to. -**

-** -** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]] -**
SQLITE_DBCONFIG_REVERSE_SCANORDER
-**
The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order -** in which tables and indexes are scanned so that the scans start at the end -** and work toward the beginning rather than starting at the beginning and -** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the -** same as setting [PRAGMA reverse_unordered_selects].

This option takes -** two arguments which are an integer and a pointer to an integer. The first -** argument is 1, 0, or -1 to enable, disable, or leave unchanged the -** reverse scan order flag, respectively. If the second argument is not NULL, -** then 0 or 1 is written into the integer that the second argument points to -** depending on if the reverse scan order flag is set after processing the -** first argument. -**

-** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]] -**
SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
-**
The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables -** the ability of the [ATTACH DATABASE] SQL command to create a new database -** file if the database filed named in the ATTACH command does not already -** exist. This ability of ATTACH to create a new database is enabled by -** default. Applications can disable or reenable the ability for ATTACH to -** create new database files using this DBCONFIG option.

-** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the attach-create flag, respectively. If the second -** argument is not NULL, then 0 or 1 is written into the integer that the -** second argument points to depending on if the attach-create flag is set -** after processing the first argument. -**

-** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]] -**
SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
-**
The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the -** ability of the [ATTACH DATABASE] SQL command to open a database for writing. -** This capability is enabled by default. Applications can disable or -** reenable this capability using the current DBCONFIG option. If the -** the this capability is disabled, the [ATTACH] command will still work, -** but the database will be opened read-only. If this option is disabled, -** then the ability to create a new database using [ATTACH] is also disabled, -** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] -** option.

-** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to ATTACH another database for writing, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer to which the second argument points, depending on whether -** the ability to ATTACH a read/write database is enabled or disabled -** after processing the first argument. -**

-** -** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]] -**
SQLITE_DBCONFIG_ENABLE_COMMENTS
-**
The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the -** ability to include comments in SQL text. Comments are enabled by default. -** An application can disable or reenable comments in SQL text using this -** DBCONFIG option.

-** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to use comments in SQL text, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer that the second argument points to depending on if -** comments are allowed in SQL text after processing the first argument. -**

-** -**
-** -** [[DBCONFIG arguments]]

Arguments To SQLITE_DBCONFIG Options

-** -**

Most of the SQLITE_DBCONFIG options take two arguments, so that the -** overall call to [sqlite3_db_config()] has a total of four parameters. -** The first argument (the third parameter to sqlite3_db_config()) is a integer. -** The second argument is a pointer to an integer. If the first argument is 1, -** then the option becomes enabled. If the first integer argument is 0, then the -** option is disabled. If the first argument is -1, then the option setting -** is unchanged. The second argument, the pointer to an integer, may be NULL. -** If the second argument is not NULL, then a value of 0 or 1 is written into -** the integer to which the second argument points, depending on whether the -** setting is disabled or enabled after applying any changes specified by -** the first argument. -** -**

While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] -** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the -** documentation of those exceptional options for details. -*/ -#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ -#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ -#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ -#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ -#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ -#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ -#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ -#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ -#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */ -#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes -** METHOD: sqlite3 -** -** ^The sqlite3_extended_result_codes() routine enables or disables the -** [extended result codes] feature of SQLite. ^The extended result -** codes are disabled by default for historical compatibility. -*/ -SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid -** METHOD: sqlite3 -** -** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) -** has a unique 64-bit signed -** integer key called the [ROWID | "rowid"]. ^The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. ^If -** the table has a column of type [INTEGER PRIMARY KEY] then that column -** is another alias for the rowid. -** -** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of -** the most recent successful [INSERT] into a rowid table or [virtual table] -** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not -** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred -** on the database connection D, then sqlite3_last_insert_rowid(D) returns -** zero. -** -** As well as being set automatically as rows are inserted into database -** tables, the value returned by this function may be set explicitly by -** [sqlite3_set_last_insert_rowid()] -** -** Some virtual table implementations may INSERT rows into rowid tables as -** part of committing a transaction (e.g. to flush data accumulated in memory -** to disk). In this case subsequent calls to this function return the rowid -** associated with these internal INSERT operations, which leads to -** unintuitive results. Virtual table implementations that do write to rowid -** tables in this way can avoid this problem by restoring the original -** rowid value using [sqlite3_set_last_insert_rowid()] before returning -** control to the user. -** -** ^(If an [INSERT] occurs within a trigger then this routine will -** return the [rowid] of the inserted row as long as the trigger is -** running. Once the trigger program ends, the value returned -** by this routine reverts to what it was before the trigger was fired.)^ -** -** ^An [INSERT] that fails due to a constraint violation is not a -** successful [INSERT] and does not change the value returned by this -** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. ^(When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface.)^ -** -** ^For the purposes of this routine, an [INSERT] is considered to -** be successful even if it is subsequently rolled back. -** -** This function is accessible to SQL statements via the -** [last_insert_rowid() SQL function]. -** -** If a separate thread performs a new [INSERT] on the same -** database connection while the [sqlite3_last_insert_rowid()] -** function is running and thus changes the last insert [rowid], -** then the value returned by [sqlite3_last_insert_rowid()] is -** unpredictable and might not equal either the old or the new -** last insert [rowid]. -*/ -SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Set the Last Insert Rowid value. -** METHOD: sqlite3 -** -** The sqlite3_set_last_insert_rowid(D, R) method allows the application to -** set the value returned by calling sqlite3_last_insert_rowid(D) to R -** without inserting a row into the database. -*/ -SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); - -/* -** CAPI3REF: Count The Number Of Rows Modified -** METHOD: sqlite3 -** -** ^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. -** 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 sqlite3_changes() is undefined. ^Executing any other -** type of SQL statement does not modify the value returned by these functions. -** For the purposes of this interface, a CREATE TABLE AS SELECT statement -** does not count as an INSERT, UPDATE or DELETE statement and hence the rows -** added to the new table by the CREATE TABLE AS SELECT statement are not -** counted. -** -** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are -** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], -** [foreign key actions] or [REPLACE] constraint resolution are not counted. -** -** Changes to a view that are intercepted by -** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value -** returned by sqlite3_changes() immediately after an INSERT, UPDATE or -** DELETE statement run on a view is always zero. Only changes made to real -** tables are counted. -** -** Things are more complicated if the sqlite3_changes() function is -** executed while a trigger program is running. This may happen if the -** program uses the [changes() SQL function], or if some other callback -** function invokes sqlite3_changes() directly. Essentially: -** -**

    -**
  • ^(Before entering a trigger program the value returned by -** sqlite3_changes() function is saved. After the trigger program -** has finished, the original value is restored.)^ -** -**
  • ^(Within a trigger program each INSERT, UPDATE and DELETE -** statement sets the value returned by sqlite3_changes() -** upon completion as normal. Of course, this value will not include -** any changes performed by sub-triggers, as the sqlite3_changes() -** value will be saved and restored after each sub-trigger has run.)^ -**
-** -** ^This means that if the changes() SQL function (or similar) is used -** by the first INSERT, UPDATE or DELETE statement within a trigger, it -** returns the value as set when the calling statement began executing. -** ^If it is used by the second or subsequent such statement within a trigger -** program, the value returned reflects the number of rows modified by the -** previous INSERT, UPDATE or DELETE statement within the same trigger. -** -** If a separate thread makes changes on the same database connection -** while [sqlite3_changes()] is running then the value returned -** is unpredictable and not meaningful. -** -** See also: -**
    -**
  • the [sqlite3_total_changes()] interface -**
  • the [count_changes pragma] -**
  • the [changes() SQL function] -**
  • the [data_version pragma] -**
-*/ -SQLITE_API int sqlite3_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified -** METHOD: sqlite3 -** -** ^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. 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 sqlite3_total_changes() is undefined. ^Executing -** any other type of SQL statement does not affect the value returned by -** 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 -** not. ^Changes to a view that are intercepted by INSTEAD OF triggers -** are not counted. -** -** The [sqlite3_total_changes(D)] interface only reports the number -** of rows that changed due to SQL statement run against database -** connection D. Any changes by other database connections are ignored. -** To detect changes against a database file from other database -** connections use the [PRAGMA data_version] command or the -** [SQLITE_FCNTL_DATA_VERSION] [file control]. -** -** If a separate thread makes changes on the same database connection -** while [sqlite3_total_changes()] is running then the value -** returned is unpredictable and not meaningful. -** -** See also: -**
    -**
  • the [sqlite3_changes()] interface -**
  • the [count_changes pragma] -**
  • the [changes() SQL function] -**
  • the [data_version pragma] -**
  • the [SQLITE_FCNTL_DATA_VERSION] [file control] -**
-*/ -SQLITE_API int sqlite3_total_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query -** METHOD: sqlite3 -** -** ^This function causes any pending database operation to abort and -** return at its earliest opportunity. This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** ^It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. But it -** is not safe to call this routine with a [database connection] that -** is closed or might close before sqlite3_interrupt() returns. -** -** ^If an SQL operation is very nearly finished at the time when -** sqlite3_interrupt() is called, then it might not have an opportunity -** to be interrupted and might continue to completion. -** -** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. -** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE -** that is inside an explicit transaction, then the entire transaction -** will be rolled back automatically. -** -** ^The sqlite3_interrupt(D) call is in effect until all currently running -** SQL statements on [database connection] D complete. ^Any new SQL statements -** that are started after the sqlite3_interrupt() call and before the -** running statement count reaches zero are interrupted as if they had been -** running prior to the sqlite3_interrupt() call. ^New SQL statements -** that are started after the running statement count reaches zero are -** not effected by the sqlite3_interrupt(). -** ^A call to sqlite3_interrupt(D) that occurs when there are no running -** SQL statements is a no-op and has no effect on SQL statements -** that are started after the sqlite3_interrupt() call returns. -** -** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether -** or not an interrupt is currently in effect for [database connection] D. -** It returns 1 if an interrupt is currently in effect, or 0 otherwise. -*/ -SQLITE_API void sqlite3_interrupt(sqlite3*); -SQLITE_API int sqlite3_is_interrupted(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete -** -** These routines are useful during command-line input to determine if the -** currently entered text seems to form a complete SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. ^These routines return 1 if the input string -** appears to be a complete SQL statement. ^A statement is judged to be -** complete if it ends with a semicolon token and is not a prefix of a -** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within -** string literals or quoted identifier names or comments are not -** independent tokens (they are part of the token in which they are -** embedded) and thus do not count as a statement terminator. ^Whitespace -** and comments that follow the final semicolon are ignored. -** -** ^These routines return 0 if the statement is incomplete. ^If a -** memory allocation fails, then SQLITE_NOMEM is returned. -** -** ^These routines do not parse the SQL statements thus -** will not detect syntactically incorrect SQL. -** -** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior -** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked -** automatically by sqlite3_complete16(). If that initialization fails, -** then the return value from sqlite3_complete16() will be non-zero -** regardless of whether or not the input SQL is complete.)^ -** -** The input to [sqlite3_complete()] must be a zero-terminated -** UTF-8 string. -** -** The input to [sqlite3_complete16()] must be a zero-terminated -** UTF-16 string in native byte order. -*/ -SQLITE_API int sqlite3_complete(const char *sql); -SQLITE_API int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors -** KEYWORDS: {busy-handler callback} {busy handler} -** METHOD: sqlite3 -** -** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X -** that might be invoked with argument P whenever -** an attempt is made to access a database table associated with -** [database connection] D when another thread -** or process has the table locked. -** The sqlite3_busy_handler() interface is used to implement -** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. -** -** ^If the busy callback is NULL, then [SQLITE_BUSY] -** is returned immediately upon encountering the lock. ^If the busy callback -** is not NULL, then the callback might be invoked with two arguments. -** -** ^The first argument to the busy handler is a copy of the void* pointer which -** is the third argument to sqlite3_busy_handler(). ^The second argument to -** the busy handler callback is the number of times that the busy handler has -** been invoked previously for the same locking event. ^If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] is returned -** to the application. -** ^If the callback returns non-zero, then another attempt -** is made to access the database and the cycle repeats. -** -** The presence of a busy handler does not guarantee that it will be invoked -** when there is lock contention. ^If SQLite determines that invoking the busy -** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] -** to the application instead of invoking the -** busy handler. -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** ^The default busy callback is NULL. -** -** ^(There can only be a single busy handler defined for each -** [database connection]. Setting a new busy handler clears any -** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] -** or evaluating [PRAGMA busy_timeout=N] will change the -** busy handler and thus clear any previously set busy handler. -** -** The busy callback should not take any actions which modify the -** database connection that invoked the busy handler. In other words, -** the busy handler is not reentrant. Any such actions -** result in undefined behavior. -** -** A busy handler must not close the database connection -** or [prepared statement] that invoked the busy handler. -*/ -SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); - -/* -** CAPI3REF: Set A Busy Timeout -** METHOD: sqlite3 -** -** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps -** for a specified amount of time when a table is locked. ^The handler -** will sleep multiple times until at least "ms" milliseconds of sleeping -** have accumulated. ^After at least "ms" milliseconds of sleeping, -** the handler returns 0 which causes [sqlite3_step()] to return -** [SQLITE_BUSY]. -** -** ^Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** ^(There can only be a single busy handler for a particular -** [database connection] at any given moment. If another busy handler -** was defined (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared.)^ -** -** See also: [PRAGMA busy_timeout] -*/ -SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Set the Setlk Timeout -** METHOD: sqlite3 -** -** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If -** the VFS supports blocking locks, it sets the timeout in ms used by -** eligible locks taken on wal mode databases by the specified database -** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does -** not support blocking locks, this function is a no-op. -** -** Passing 0 to this function disables blocking locks altogether. Passing -** -1 to this function requests that the VFS blocks for a long time - -** indefinitely if possible. The results of passing any other negative value -** are undefined. -** -** Internally, each SQLite database handle store two timeout values - the -** busy-timeout (used for rollback mode databases, or if the VFS does not -** support blocking locks) and the setlk-timeout (used for blocking locks -** on wal-mode databases). The sqlite3_busy_timeout() method sets both -** values, this function sets only the setlk-timeout value. Therefore, -** to configure separate busy-timeout and setlk-timeout values for a single -** database handle, call sqlite3_busy_timeout() followed by this function. -** -** Whenever the number of connections to a wal mode database falls from -** 1 to 0, the last connection takes an exclusive lock on the database, -** then checkpoints and deletes the wal file. While it is doing this, any -** new connection that tries to read from the database fails with an -** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is -** passed to this API, the new connection blocks until the exclusive lock -** has been released. -*/ -SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags); - -/* -** CAPI3REF: Flags for sqlite3_setlk_timeout() -*/ -#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01 - -/* -** CAPI3REF: Convenience Routines For Running Queries -** METHOD: sqlite3 -** -** This is a legacy interface that is preserved for backwards compatibility. -** Use of this interface is not recommended. -** -** Definition: A result table is memory data structure created by the -** [sqlite3_get_table()] interface. A result table records the -** complete query results from one or more queries. -** -** The table conceptually has a number of rows and columns. But -** these numbers are not part of the result table itself. These -** numbers are obtained separately. Let N be the number of rows -** and M be the number of columns. -** -** A result table is an array of pointers to zero-terminated UTF-8 strings. -** There are (N+1)*M elements in the array. The first M pointers point -** to zero-terminated strings that contain the names of the columns. -** The remaining entries all point to query results. NULL values result -** in NULL pointers. All other values are in their UTF-8 zero-terminated -** string representation as returned by [sqlite3_column_text()]. -** -** A result table might consist of one or more memory allocations. -** It is not safe to pass a result table directly to [sqlite3_free()]. -** A result table should be deallocated using [sqlite3_free_table()]. -** -** ^(As an example of the result table format, suppose a query result -** is as follows: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** There are two columns (M==2) and three rows (N==3). Thus the -** result table has 8 entries. Suppose the result table is stored -** in an array named azResult. Then azResult holds this content: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
)^ -** -** ^The sqlite3_get_table() function evaluates one or more -** semicolon-separated SQL statements in the zero-terminated UTF-8 -** string of its 2nd parameter and returns a result table to the -** pointer given in its 3rd parameter. -** -** After the application has finished with the result from sqlite3_get_table(), -** it must pass the result table pointer to sqlite3_free_table() in order to -** release the memory that was malloced. Because of the way the -** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling -** function must not try to call [sqlite3_free()] directly. Only -** [sqlite3_free_table()] is able to release the memory properly and safely. -** -** The sqlite3_get_table() interface is implemented as a wrapper around -** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access -** to any internal data structures of SQLite. It uses only the public -** interface defined here. As a consequence, errors that occur in the -** wrapper layer outside of the internal [sqlite3_exec()] call are not -** reflected in subsequent calls to [sqlite3_errcode()] or -** [sqlite3_errmsg()]. -*/ -SQLITE_API int sqlite3_get_table( - sqlite3 *db, /* An open database */ - const char *zSql, /* SQL to be evaluated */ - char ***pazResult, /* Results of the query */ - int *pnRow, /* Number of result rows written here */ - int *pnColumn, /* Number of result columns written here */ - char **pzErrmsg /* Error msg written here */ -); -SQLITE_API void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions -** -** These routines are work-alikes of the "printf()" family of functions -** from the standard C library. -** These routines understand most of the common formatting options from -** the standard library printf() -** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). -** See the [built-in printf()] documentation for details. -** -** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc64()]. -** The strings returned by these two routines should be -** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough -** memory to hold the resulting string. -** -** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. Note that the order of the -** first two parameters is reversed from snprintf().)^ This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. ^(Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer.)^ We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** ^As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. ^The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. So the longest string that can be completely -** written will be n-1 characters. -** -** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). -** -** See also: [built-in printf()], [printf() SQL function] -*/ -SQLITE_API char *sqlite3_mprintf(const char*,...); -SQLITE_API char *sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); - -/* -** CAPI3REF: Memory Allocation Subsystem -** -** The SQLite core uses these three routines for all of its own -** internal memory allocation needs. "Core" in the previous sentence -** does not include operating-system specific [VFS] implementation. The -** Windows VFS uses native malloc() and free() for some operations. -** -** ^The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** ^If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. ^If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** ^The sqlite3_malloc64(N) routine works just like -** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead -** of a signed 32-bit integer. -** -** ^Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. ^The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_realloc(). -** -** ^The sqlite3_realloc(X,N) interface attempts to resize a -** prior memory allocation X to be at least N bytes. -** ^If the X parameter to sqlite3_realloc(X,N) -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N). -** ^If the N parameter to sqlite3_realloc(X,N) is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(X). -** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation -** of at least N bytes in size or NULL if insufficient memory is available. -** ^If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc(X,N) and the prior allocation is freed. -** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the -** prior allocation is not freed. -** -** ^The sqlite3_realloc64(X,N) interfaces works the same as -** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead -** of a 32-bit signed integer. -** -** ^If X is a memory allocation previously obtained from sqlite3_malloc(), -** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then -** sqlite3_msize(X) returns the size of that memory allocation in bytes. -** ^The value returned by sqlite3_msize(X) might be larger than the number -** of bytes requested when X was allocated. ^If X is a NULL pointer then -** sqlite3_msize(X) returns zero. If X points to something that is not -** the beginning of memory allocation, or if it points to a formerly -** valid memory allocation that has now been freed, then the behavior -** of sqlite3_msize(X) is undefined and possibly harmful. -** -** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), -** sqlite3_malloc64(), and sqlite3_realloc64() -** is always aligned to at least an 8 byte boundary, or to a -** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time -** option is used. -** -** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] -** must be either NULL or else pointers obtained from a prior -** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have -** not yet been released. -** -** The application must not read or write any part of -** a block of memory after it has been released using -** [sqlite3_free()] or [sqlite3_realloc()]. -*/ -SQLITE_API void *sqlite3_malloc(int); -SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *sqlite3_realloc(void*, int); -SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void sqlite3_free(void*); -SQLITE_API sqlite3_uint64 sqlite3_msize(void*); - -/* -** CAPI3REF: Memory Allocator Statistics -** -** SQLite provides these two interfaces for reporting on the status -** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] -** routines, which form the built-in memory allocation subsystem. -** -** ^The [sqlite3_memory_used()] routine returns the number of bytes -** of memory currently outstanding (malloced but not freed). -** ^The [sqlite3_memory_highwater()] routine returns the maximum -** value of [sqlite3_memory_used()] since the high-water mark -** was last reset. ^The values returned by [sqlite3_memory_used()] and -** [sqlite3_memory_highwater()] include any overhead -** added by SQLite in its implementation of [sqlite3_malloc()], -** but not overhead added by the any underlying system library -** routines that [sqlite3_malloc()] may call. -** -** ^The memory high-water mark is reset to the current value of -** [sqlite3_memory_used()] if and only if the parameter to -** [sqlite3_memory_highwater()] is true. ^The value returned -** by [sqlite3_memory_highwater(1)] is the high-water mark -** prior to the reset. -*/ -SQLITE_API sqlite3_int64 sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Pseudo-Random Number Generator -** -** SQLite contains a high-quality pseudo-random number generator (PRNG) used to -** select random [ROWID | ROWIDs] when inserting new records into a table that -** already uses the largest possible [ROWID]. The PRNG is also used for -** the built-in random() and randomblob() SQL functions. This interface allows -** applications to access the same PRNG for other purposes. -** -** ^A call to this routine stores N bytes of randomness into buffer P. -** ^The P parameter can be a NULL pointer. -** -** ^If this routine has not been previously called or if the previous -** call had N less than one or a NULL pointer for P, then the PRNG is -** seeded using randomness obtained from the xRandomness method of -** the default [sqlite3_vfs] object. -** ^If the previous call to this routine had an N of 1 or more and a -** non-NULL P then the pseudo-randomness is generated -** internally and without recourse to the [sqlite3_vfs] xRandomness -** method. -*/ -SQLITE_API void sqlite3_randomness(int N, void *P); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks -** METHOD: sqlite3 -** KEYWORDS: {authorizer callback} -** -** ^This routine registers an authorizer callback with a particular -** [database connection], supplied in the first argument. -** ^The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()], -** and [sqlite3_prepare16_v3()]. ^At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. ^The authorizer callback should -** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. ^If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then the [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer will fail with an error message. -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. ^When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer will fail with an error message explaining that -** access is denied. -** -** ^The first parameter to the authorizer callback is a copy of the third -** parameter to the sqlite3_set_authorizer() interface. ^The second parameter -** to the callback is an integer [SQLITE_COPY | action code] that specifies -** the particular action to be authorized. ^The third through sixth parameters -** to the callback are either NULL pointers or zero-terminated strings -** that contain additional details about the action to be authorized. -** Applications must always be prepared to encounter a NULL pointer in any -** of the third through the sixth parameters of the authorization callback. -** -** ^If the action code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the -** [prepared statement] statement is constructed to substitute -** a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] -** return can be used to deny an untrusted user access to individual -** columns of a table. -** ^When a table is referenced by a [SELECT] but no column values are -** extracted from that table (for example in a query like -** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback -** is invoked once for that table with a column name that is an empty string. -** ^If the action code is [SQLITE_DELETE] and the callback returns -** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the -** [truncate optimization] is disabled and all rows are deleted individually. -** -** An authorizer is used when [sqlite3_prepare | preparing] -** SQL statements from an untrusted source, to ensure that the SQL statements -** do not try to access data they are not allowed to see, or that they do not -** try to execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being [sqlite3_prepare | prepared] that -** disallows everything except [SELECT] statements. -** -** Applications that need to process SQL from untrusted sources -** might also consider lowering resource limits using [sqlite3_limit()] -** and limiting database size using the [max_page_count] [PRAGMA] -** in addition to using an authorizer. -** -** ^(Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call.)^ ^Disable the authorizer by installing a NULL callback. -** The authorizer is disabled by default. -** -** The authorizer callback must not do anything that will modify -** the database connection that invoked the authorizer callback. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be re-prepared during [sqlite3_step()] due to a -** schema change. Hence, the application should ensure that the -** correct authorizer callback remains in place during the [sqlite3_step()]. -** -** ^Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. Authorization is not -** performed during statement evaluation in [sqlite3_step()], unless -** as stated in the previous paragraph, sqlite3_step() invokes -** sqlite3_prepare_v2() to reprepare a statement after a schema change. -*/ -SQLITE_API int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -** -** Note that SQLITE_IGNORE is also used as a [conflict resolution mode] -** returned from the [sqlite3_vtab_on_conflict()] interface. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorize certain SQL statement actions. The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. -** -** These action code values signify what kind of operation is to be -** authorized. The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. ^(The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* Operation NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* NULL Function Name */ -#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ -#define SQLITE_COPY 0 /* No longer used */ -#define SQLITE_RECURSIVE 33 /* NULL NULL */ - -/* -** CAPI3REF: Deprecated Tracing And Profiling Functions -** DEPRECATED -** -** These routines are deprecated. Use the [sqlite3_trace_v2()] interface -** instead of the routines described here. -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** ^The callback function registered by sqlite3_trace() is invoked at -** various times when an SQL statement is being run by [sqlite3_step()]. -** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the -** SQL statement text as the statement first begins executing. -** ^(Additional sqlite3_trace() callbacks might occur -** as each triggered subprogram is entered. The callbacks for triggers -** contain a UTF-8 SQL comment that identifies the trigger.)^ -** -** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit -** the length of [bound parameter] expansion in the output of sqlite3_trace(). -** -** ^The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. ^The profile callback contains -** the original statement text and an estimate of wall-clock time -** of how long that statement took to run. ^The profile callback -** time is in units of nanoseconds, however the current implementation -** is only capable of millisecond resolution so the six least significant -** digits in the time are meaningless. Future versions of SQLite -** might provide greater resolution on the profiler callback. Invoking -** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the -** profile callback. -*/ -SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, - void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: SQL Trace Event Codes -** KEYWORDS: SQLITE_TRACE -** -** These constants identify classes of events that can be monitored -** using the [sqlite3_trace_v2()] tracing logic. The M argument -** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of -** the following constants. ^The first argument to the trace callback -** is one of the following constants. -** -** New tracing constants may be added in future releases. -** -** ^A trace callback has four arguments: xCallback(T,C,P,X). -** ^The T argument is one of the integer type codes above. -** ^The C argument is a copy of the context pointer passed in as the -** fourth argument to [sqlite3_trace_v2()]. -** The P and X arguments are pointers whose meanings depend on T. -** -**
-** [[SQLITE_TRACE_STMT]]
SQLITE_TRACE_STMT
-**
^An SQLITE_TRACE_STMT callback is invoked when a prepared statement -** first begins running and possibly at other times during the -** execution of the prepared statement, such as at the start of each -** trigger subprogram. ^The P argument is a pointer to the -** [prepared statement]. ^The X argument is a pointer to a string which -** is the unexpanded SQL text of the prepared statement or an SQL comment -** that indicates the invocation of a trigger. ^The callback can compute -** the same text that would have been returned by the legacy [sqlite3_trace()] -** interface by using the X argument when X begins with "--" and invoking -** [sqlite3_expanded_sql(P)] otherwise. -** -** [[SQLITE_TRACE_PROFILE]]
SQLITE_TRACE_PROFILE
-**
^An SQLITE_TRACE_PROFILE callback provides approximately the same -** information as is provided by the [sqlite3_profile()] callback. -** ^The P argument is a pointer to the [prepared statement] and the -** X argument points to a 64-bit integer which is approximately -** the number of nanoseconds that the prepared statement took to run. -** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. -** -** [[SQLITE_TRACE_ROW]]
SQLITE_TRACE_ROW
-**
^An SQLITE_TRACE_ROW callback is invoked whenever a prepared -** statement generates a single row of result. -** ^The P argument is a pointer to the [prepared statement] and the -** X argument is unused. -** -** [[SQLITE_TRACE_CLOSE]]
SQLITE_TRACE_CLOSE
-**
^An SQLITE_TRACE_CLOSE callback is invoked when a database -** connection closes. -** ^The P argument is a pointer to the [database connection] object -** and the X argument is unused. -**
-*/ -#define SQLITE_TRACE_STMT 0x01 -#define SQLITE_TRACE_PROFILE 0x02 -#define SQLITE_TRACE_ROW 0x04 -#define SQLITE_TRACE_CLOSE 0x08 - -/* -** CAPI3REF: SQL Trace Hook -** METHOD: sqlite3 -** -** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback -** function X against [database connection] D, using property mask M -** and context pointer P. ^If the X callback is -** NULL or if the M mask is zero, then tracing is disabled. The -** M argument should be the bitwise OR-ed combination of -** zero or more [SQLITE_TRACE] constants. -** -** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P) -** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or -** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each -** database connection may have at most one trace callback. -** -** ^The X callback is invoked whenever any of the events identified by -** mask M occur. ^The integer return value from the callback is currently -** ignored, though this may change in future releases. Callback -** implementations should return zero to ensure future compatibility. -** -** ^A trace callback is invoked with four arguments: callback(T,C,P,X). -** ^The T argument is one of the [SQLITE_TRACE] -** constants to indicate why the callback was invoked. -** ^The C argument is a copy of the context pointer. -** The P and X arguments are pointers whose meanings depend on T. -** -** The sqlite3_trace_v2() interface is intended to replace the legacy -** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which -** are deprecated. -*/ -SQLITE_API int sqlite3_trace_v2( - sqlite3*, - unsigned uMask, - int(*xCallback)(unsigned,void*,void*,void*), - void *pCtx -); - -/* -** CAPI3REF: Query Progress Callbacks -** METHOD: sqlite3 -** -** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback -** function X to be invoked periodically during long running calls to -** [sqlite3_step()] and [sqlite3_prepare()] and similar for -** database connection D. An example use for this -** interface is to keep a GUI updated during a large query. -** -** ^The parameter P is passed through as the only parameter to the -** callback function X. ^The parameter N is the approximate number of -** [virtual machine instructions] that are evaluated between successive -** invocations of the callback X. ^If N is less than one then the progress -** handler is disabled. -** -** ^Only a single progress handler may be defined at one time per -** [database connection]; setting a new progress handler cancels the -** old one. ^Setting parameter X to NULL disables the progress handler. -** ^The progress handler is also disabled by setting N to a value less -** than 1. -** -** ^If the progress callback returns non-zero, the operation is -** interrupted. This feature can be used to implement a -** "Cancel" button on a GUI progress dialog box. -** -** The progress handler callback must not do anything that will modify -** the database connection that invoked the progress handler. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -** The progress handler callback would originally only be invoked from the -** bytecode engine. It still might be invoked during [sqlite3_prepare()] -** and similar because those routines might force a reparse of the schema -** which involves running the bytecode engine. However, beginning with -** SQLite version 3.41.0, the progress handler callback might also be -** invoked directly from [sqlite3_prepare()] while analyzing and generating -** code for complex queries. -*/ -SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection -** CONSTRUCTOR: sqlite3 -** -** ^These routines open an SQLite database file as specified by the -** filename argument. ^The filename argument is interpreted as UTF-8 for -** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte -** order for sqlite3_open16(). ^(A [database connection] handle is usually -** returned in *ppDb, even if an error occurs. The only exception is that -** if SQLite is unable to allocate memory to hold the [sqlite3] object, -** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] -** object.)^ ^(If the database is opened (and/or created) successfully, then -** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error following a failure of any -** of the sqlite3_open() routines. -** -** ^The default encoding will be UTF-8 for databases created using -** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases -** created using sqlite3_open16() will be UTF-16 in the native byte order. -** -** Whether or not an error occurs when it is opened, resources -** associated with the [database connection] handle should be released by -** passing it to [sqlite3_close()] when it is no longer required. -** -** The sqlite3_open_v2() interface works like sqlite3_open() -** except that it accepts two additional parameters for additional control -** over the new database connection. ^(The flags parameter to -** sqlite3_open_v2() must include, at a minimum, one of the following -** three flag combinations:)^ -** -**
-** ^(
[SQLITE_OPEN_READONLY]
-**
The database is opened in read-only mode. If the database does -** not already exist, an error is returned.
)^ -** -** ^(
[SQLITE_OPEN_READWRITE]
-**
The database is opened for reading and writing if possible, or -** reading only if the file is write protected by the operating -** system. In either case the database must already exist, otherwise -** an error is returned. For historical reasons, if opening in -** read-write mode fails due to OS-level permissions, an attempt is -** made to open it in read-only mode. [sqlite3_db_readonly()] can be -** used to determine whether the database is actually -** read-write.
)^ -** -** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
-**
The database is opened for reading and writing, and is created if -** it does not already exist. This is the behavior that is always used for -** sqlite3_open() and sqlite3_open16().
)^ -**
-** -** In addition to the required flags, the following optional flags are -** also supported: -** -**
-** ^(
[SQLITE_OPEN_URI]
-**
The filename can be interpreted as a URI if this flag is set.
)^ -** -** ^(
[SQLITE_OPEN_MEMORY]
-**
The database will be opened as an in-memory database. The database -** is named by the "filename" argument for the purposes of cache-sharing, -** if shared cache mode is enabled, but the "filename" is otherwise ignored. -**
)^ -** -** ^(
[SQLITE_OPEN_NOMUTEX]
-**
The new database connection will use the "multi-thread" -** [threading mode].)^ This means that separate threads are allowed -** to use SQLite at the same time, as long as each thread is using -** a different [database connection]. -** -** ^(
[SQLITE_OPEN_FULLMUTEX]
-**
The new database connection will use the "serialized" -** [threading mode].)^ This means the multiple threads can safely -** attempt to use the same database connection at the same time. -** (Mutexes will block any actual concurrency, but in this mode -** there is no harm in trying.) -** -** ^(
[SQLITE_OPEN_SHAREDCACHE]
-**
The database is opened [shared cache] enabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** The [use of shared cache mode is discouraged] and hence shared cache -** capabilities may be omitted from many builds of SQLite. In such cases, -** this option is a no-op. -** -** ^(
[SQLITE_OPEN_PRIVATECACHE]
-**
The database is opened [shared cache] disabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** -** [[OPEN_EXRESCODE]] ^(
[SQLITE_OPEN_EXRESCODE]
-**
The database connection comes up in "extended result code mode". -** In other words, the database behaves as if -** [sqlite3_extended_result_codes(db,1)] were 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 [sqlite3_open_v2()] -** to return an extended result code.
-** -** [[OPEN_NOFOLLOW]] ^(
[SQLITE_OPEN_NOFOLLOW]
-**
The database filename is not allowed to contain a symbolic link
-**
)^ -** -** If the 3rd parameter to 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. Historic versions of SQLite -** have silently ignored surplus bits in the flags parameter to -** 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 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 [sqlite3_vfs|VFS interface] only, and not -** by sqlite3_open_v2(). -** -** ^The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system interface that -** the new database connection should use. ^If the fourth parameter is -** a NULL pointer then the default [sqlite3_vfs] object is used. -** -** ^If the filename is ":memory:", then a private, temporary in-memory database -** is created for the connection. ^This in-memory database will vanish when -** the database connection is closed. Future versions of SQLite might -** make use of additional special filenames that begin with the ":" character. -** It is recommended that when a database filename actually does begin with -** a ":" character you should prefix the filename with a pathname such as -** "./" to avoid ambiguity. -** -** ^If the filename is an empty string, then a private, temporary -** on-disk database will be created. ^This private database will be -** automatically deleted as soon as the database connection is closed. -** -** [[URI filenames in sqlite3_open()]]

URI Filenames

-** -** ^If [URI filename] interpretation is enabled, and the filename argument -** begins with "file:", then the filename is interpreted as a URI. ^URI -** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is -** set in the third argument to sqlite3_open_v2(), or if it has -** been enabled globally using the [SQLITE_CONFIG_URI] option with the -** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. -** URI filename interpretation is turned off -** by default, but future releases of SQLite might enable URI filename -** interpretation by default. See "[URI filenames]" for additional -** information. -** -** URI filenames are parsed according to RFC 3986. ^If the URI contains an -** authority, then it must be either an empty string or the string -** "localhost". ^If the authority is not an empty string or "localhost", an -** error is returned to the caller. ^The fragment component of a URI, if -** present, is ignored. -** -** ^SQLite uses the path component of the URI as the name of the disk file -** which contains the database. ^If the path begins with a '/' character, -** then it is interpreted as an absolute path. ^If the path does not begin -** with a '/' (meaning that the authority section is omitted from the URI) -** then the path is interpreted as a relative path. -** ^(On windows, the first component of an absolute path -** is a drive specification (e.g. "C:").)^ -** -** [[core URI query parameters]] -** The query component of a URI may contain parameters that are interpreted -** either by SQLite itself, or by a [VFS | custom VFS implementation]. -** SQLite and its built-in [VFSes] interpret the -** following query parameters: -** -**
    -**
  • vfs: ^The "vfs" parameter may be used to specify the name of -** a VFS object that provides the operating system interface that should -** be used to access the database file on disk. ^If this option is set to -** an empty string the default VFS object is used. ^Specifying an unknown -** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is -** present, then the VFS specified by the option takes precedence over -** the value passed as the fourth parameter to sqlite3_open_v2(). -** -**
  • mode: ^(The mode parameter may be set to either "ro", "rw", -** "rwc", or "memory". Attempting to set it to any other value is -** an error)^. -** ^If "ro" is specified, then the database is opened for read-only -** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the -** third argument to sqlite3_open_v2(). ^If the mode option is set to -** "rw", then the database is opened for read-write (but not create) -** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had -** been set. ^Value "rwc" is equivalent to setting both -** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is -** set to "memory" then a pure [in-memory database] that never reads -** or writes from disk is used. ^It is an error to specify a value for -** the mode parameter that is less restrictive than that specified by -** the flags passed in the third parameter to sqlite3_open_v2(). -** -**
  • cache: ^The cache parameter may be set to either "shared" or -** "private". ^Setting it to "shared" is equivalent to setting the -** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to -** sqlite3_open_v2(). ^Setting the cache parameter to "private" is -** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. -** ^If sqlite3_open_v2() is used and the "cache" parameter is present in -** a URI filename, its value overrides any behavior requested by setting -** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. -** -**
  • psow: ^The psow parameter indicates whether or not the -** [powersafe overwrite] property does or does not apply to the -** storage media on which the database file resides. -** -**
  • nolock: ^The nolock parameter is a boolean query parameter -** which if set disables file locking in rollback journal modes. This -** is useful for accessing a database on a filesystem that does not -** support locking. Caution: Database corruption might result if two -** or more processes write to the same database and any one of those -** processes uses nolock=1. -** -**
  • immutable: ^The immutable parameter is a boolean query -** parameter that indicates that the database file is stored on -** read-only media. ^When immutable is set, SQLite assumes that the -** database file cannot be changed, even by a process with higher -** privilege, and so the database is opened read-only and all locking -** and change detection is disabled. Caution: Setting the immutable -** property on a database file that does in fact change can result -** in incorrect query results and/or [SQLITE_CORRUPT] errors. -** See also: [SQLITE_IOCAP_IMMUTABLE]. -** -**
-** -** ^Specifying an unknown parameter in the query component of a URI is not an -** error. Future versions of SQLite might understand additional query -** parameters. See "[query parameters with special meaning to SQLite]" for -** additional information. -** -** [[URI filename examples]]

URI filename examples

-** -** -**
URI filenames Results -**
file:data.db -** Open the file "data.db" in the current directory. -**
file:/home/fred/data.db
-** file:///home/fred/data.db
-** file://localhost/home/fred/data.db
-** Open the database file "/home/fred/data.db". -**
file://darkstar/home/fred/data.db -** An error. "darkstar" is not a recognized authority. -**
-** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db -** Windows only: Open the file "data.db" on fred's desktop on drive -** C:. Note that the %20 escaping in this example is not strictly -** necessary - space characters can be used literally -** in URI filenames. -**
file:data.db?mode=ro&cache=private -** Open file "data.db" in the current directory for read-only access. -** Regardless of whether or not shared-cache mode is enabled by -** default, use a private cache. -**
file:/home/fred/data.db?vfs=unix-dotfile -** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" -** that uses dot-files in place of posix advisory locking. -**
file:data.db?mode=readonly -** An error. "readonly" is not a valid option for the "mode" parameter. -** Use "ro" instead: "file:data.db?mode=ro". -**
-** -** ^URI hexadecimal escape sequences (%HH) are supported within the path and -** query components of a URI. A hexadecimal escape sequence consists of a -** percent sign - "%" - followed by exactly two hexadecimal digits -** specifying an octet value. ^Before the path or query components of a -** URI filename are interpreted, they are encoded using UTF-8 and all -** hexadecimal escape sequences replaced by a single byte containing the -** corresponding octet. If this process generates an invalid UTF-8 encoding, -** the results are undefined. -** -** Note to Windows users: The encoding used for the filename argument -** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** sqlite3_open() or sqlite3_open_v2(). -** -** Note to Windows Runtime users: The temporary directory must be set -** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various -** features that require the use of temporary files may fail. -** -** See also: [sqlite3_temp_directory] -*/ -SQLITE_API int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -SQLITE_API int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -SQLITE_API int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Obtain Values For URI Parameters -** -** These are utility routines, useful to [VFS|custom VFS implementations], -** that check if a database file was a URI that contained a specific query -** parameter, and if so obtains the value of that query parameter. -** -** The first parameter to these interfaces (hereafter referred to -** as F) must be one of: -**
    -**
  • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implementation, or -**
  • A filename obtained from [sqlite3_db_filename()], or -**
  • A new filename constructed using [sqlite3_create_filename()]. -**
-** If the F parameter is not one of the above, then the behavior is -** undefined and probably undesirable. Older versions of SQLite were -** more tolerant of invalid F parameters than newer versions. -** -** If F is a suitable filename (as described in the previous paragraph) -** and if P is the name of the query parameter, then -** sqlite3_uri_parameter(F,P) returns the value of the P -** parameter if it exists or a NULL pointer if P does not appear as a -** query parameter on F. If P is a query parameter of F and it -** has no explicit value, then sqlite3_uri_parameter(F,P) returns -** a pointer to an empty string. -** -** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean -** parameter and returns true (1) or false (0) according to the value -** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the -** value of query parameter P is one of "yes", "true", or "on" in any -** case or if the value begins with a non-zero number. The -** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of -** query parameter P is one of "no", "false", or "off" in any case or -** if the value begins with a numeric zero. If P is not a query -** parameter on F or if the value of P does not match any of the -** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). -** -** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a -** 64-bit signed integer and returns that integer, or D if P does not -** exist. If the value of P is something other than an integer, then -** zero is returned. -** -** The sqlite3_uri_key(F,N) returns a pointer to the name (not -** the value) of the N-th query parameter for filename F, or a NULL -** pointer if N is less than zero or greater than the number of query -** parameters minus 1. The N value is zero-based so N should be 0 to obtain -** the name of the first query parameter, 1 for the second parameter, and -** so forth. -** -** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and -** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and -** is not a database file pathname pointer that the SQLite core passed -** into the xOpen VFS method, then the behavior of this routine is undefined -** and probably undesirable. -** -** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F -** parameter can also be the name of a rollback journal file or WAL file -** in addition to the main database file. Prior to version 3.31.0, these -** routines would only work if F was the name of the main database file. -** When the F parameter is the name of the rollback journal or WAL file, -** it has access to all the same query parameters as were found on the -** main database file. -** -** See the [URI filename] documentation for additional information. -*/ -SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64); -SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N); - -/* -** CAPI3REF: Translate filenames -** -** These routines are available to [VFS|custom VFS implementations] for -** translating filenames between the main database file, the journal file, -** and the WAL file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, then sqlite3_filename_database(F) -** returns the name of the corresponding database file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, or if F is a database filename -** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F) -** returns the name of the corresponding rollback journal file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** that was passed by the SQLite core into the VFS, or if F is a database -** filename obtained from [sqlite3_db_filename()], then -** sqlite3_filename_wal(F) returns the name of the corresponding -** WAL file. -** -** In all of the above, if F is not the name of a database, journal or WAL -** filename passed into the VFS from the SQLite core and F is not the -** return value from [sqlite3_db_filename()], then the result is -** undefined and is likely a memory access violation. -*/ -SQLITE_API const char *sqlite3_filename_database(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename); - -/* -** CAPI3REF: Database File Corresponding To A Journal -** -** ^If X is the name of a rollback or WAL-mode journal file that is -** passed into the xOpen method of [sqlite3_vfs], then -** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file] -** object that represents the main database file. -** -** This routine is intended for use in custom [VFS] implementations -** only. It is not a general-purpose interface. -** The argument sqlite3_file_object(X) must be a filename pointer that -** has been passed into [sqlite3_vfs].xOpen method where the -** flags parameter to xOpen contains one of the bits -** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use -** of this routine results in undefined and probably undesirable -** behavior. -*/ -SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); - -/* -** CAPI3REF: Create and Destroy VFS Filenames -** -** These interfaces are provided for use by [VFS shim] implementations and -** are not useful outside of that context. -** -** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of -** database filename D with corresponding journal file J and WAL file W and -** an array P of N URI Key/Value pairs. The result from -** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that -** is safe to pass to routines like: -**
    -**
  • [sqlite3_uri_parameter()], -**
  • [sqlite3_uri_boolean()], -**
  • [sqlite3_uri_int64()], -**
  • [sqlite3_uri_key()], -**
  • [sqlite3_filename_database()], -**
  • [sqlite3_filename_journal()], or -**
  • [sqlite3_filename_wal()]. -**
-** If a memory allocation error occurs, sqlite3_create_filename() might -** return a NULL pointer. The memory obtained from sqlite3_create_filename(X) -** must be released by a corresponding call to sqlite3_free_filename(Y). -** -** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array -** of 2*N pointers to strings. Each pair of pointers in this array corresponds -** to a key and value for a query parameter. The P parameter may be a NULL -** pointer if N is zero. None of the 2*N pointers in the P array may be -** NULL pointers and key pointers should not be empty strings. -** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may -** be NULL pointers, though they can be empty strings. -** -** The sqlite3_free_filename(Y) routine releases a memory allocation -** previously obtained from sqlite3_create_filename(). Invoking -** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op. -** -** If the Y parameter to sqlite3_free_filename(Y) is anything other -** than a NULL pointer or a pointer previously acquired from -** sqlite3_create_filename(), then bad things such as heap -** corruption or segfaults may occur. The value Y should not be -** used again after sqlite3_free_filename(Y) has been called. This means -** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y, -** then the corresponding [sqlite3_module.xClose() method should also be -** invoked prior to calling sqlite3_free_filename(Y). -*/ -SQLITE_API sqlite3_filename sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam -); -SQLITE_API void sqlite3_free_filename(sqlite3_filename); - -/* -** CAPI3REF: Error Codes And Messages -** METHOD: sqlite3 -** -** ^If the most recent sqlite3_* API call associated with -** [database connection] D failed, then the sqlite3_errcode(D) interface -** returns the numeric [result code] or [extended result code] for that -** API call. -** ^The sqlite3_extended_errcode() -** interface is the same except that it always returns the -** [extended result code] even when extended result codes are -** disabled. -** -** The values returned by sqlite3_errcode() and/or -** 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 include the following: -** -**
    -**
  • sqlite3_errcode() -**
  • sqlite3_extended_errcode() -**
  • sqlite3_errmsg() -**
  • sqlite3_errmsg16() -**
  • sqlite3_error_offset() -**
-** -** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively, -** or NULL if no error message is available. -** (See how SQLite handles [invalid UTF] for exceptions to this rule.) -** ^(Memory to hold the error message string is managed internally. -** The application does not need to worry about freeing the result. -** However, the error string might be overwritten or deallocated by -** subsequent calls to other SQLite interface functions.)^ -** -** ^The sqlite3_errstr(E) interface returns the English-language text -** that describes the [result code] E, as UTF-8, or NULL if E is not an -** result code for which a text error message is available. -** ^(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 sqlite3_error_offset() interface returns the byte offset -** of the start of that token. ^The byte offset returned by -** 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 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. -** When that happens, the second error will be reported since these -** interfaces always report the most recent result. To avoid -** this, each thread can obtain exclusive use of the [database connection] D -** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning -** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after -** all calls to the interfaces listed here are completed. -** -** If an interface fails with SQLITE_MISUSE, that means the interface -** was invoked incorrectly by the application. In that case, the -** error code and message may or may not be set. -*/ -SQLITE_API int sqlite3_errcode(sqlite3 *db); -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *sqlite3_errmsg(sqlite3*); -SQLITE_API const void *sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *sqlite3_errstr(int); -SQLITE_API int sqlite3_error_offset(sqlite3 *db); - -/* -** CAPI3REF: Prepared Statement Object -** KEYWORDS: {prepared statement} {prepared statements} -** -** An instance of this object represents a single SQL statement that -** has been compiled into binary form and is ready to be evaluated. -** -** Think of each SQL statement as a separate computer program. The -** original SQL text is source code. A prepared statement object -** is the compiled object code. All SQL must be converted into a -** prepared statement before it can be run. -** -** The life-cycle of a prepared statement object usually goes like this: -** -**
    -**
  1. Create the prepared statement object using [sqlite3_prepare_v2()]. -**
  2. Bind values to [parameters] using the sqlite3_bind_*() -** interfaces. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the prepared statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Run-time Limits -** METHOD: sqlite3 -** -** ^(This interface allows the size of various constructs to be limited -** on a connection by connection basis. The first parameter is the -** [database connection] whose limit is to be set or queried. The -** second parameter is one of the [limit categories] that define a -** class of constructs to be size limited. The third parameter is the -** new limit for that construct.)^ -** -** ^If the new limit is a negative number, the limit is unchanged. -** ^(For each limit category SQLITE_LIMIT_NAME there is a -** [limits | hard upper bound] -** set at compile-time by a C preprocessor macro called -** [limits | SQLITE_MAX_NAME]. -** (The "_LIMIT_" in the name is changed to "_MAX_".))^ -** ^Attempts to increase a limit above its hard upper bound are -** silently truncated to the hard upper bound. -** -** ^Regardless of whether or not the limit was changed, the -** [sqlite3_limit()] interface returns the prior value of the limit. -** ^Hence, to find the current value of a limit without changing it, -** simply invoke this interface with the third parameter set to -1. -** -** Run-time limits are intended for use in applications that manage -** both their own internal database and also databases that are controlled -** by untrusted external sources. An example application might be a -** web browser that has its own databases for storing history and -** separate databases controlled by JavaScript applications downloaded -** off the Internet. The internal databases can be given the -** large, default limits. Databases managed by external sources can -** be given much smaller limits designed to prevent a denial of service -** attack. Developers might also want to use the [sqlite3_set_authorizer()] -** interface to further control untrusted SQL. The size of the database -** created by an untrusted script can be contained using the -** [max_page_count] [PRAGMA]. -** -** New run-time limit categories may be added in future releases. -*/ -SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); - -/* -** CAPI3REF: Run-Time Limit Categories -** KEYWORDS: {limit category} {*limit categories} -** -** These constants define various performance limits -** that can be lowered at run-time using [sqlite3_limit()]. -** The synopsis of the meanings of the various limits is shown below. -** Additional information is available at [limits | Limits in SQLite]. -** -**
-** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
-**
The maximum size of any string or BLOB or table row, in bytes.
)^ -** -** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
-**
The maximum length of an SQL statement, in bytes.
)^ -** -** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
-**
The maximum number of columns in a table definition or in the -** result set of a [SELECT] or the maximum number of columns in an index -** or in an ORDER BY or GROUP BY clause.
)^ -** -** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
-**
The maximum depth of the parse tree on any expression.
)^ -** -** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
-**
The maximum number of terms in a compound SELECT statement.
)^ -** -** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
-**
The maximum number of instructions in a virtual machine program -** used to implement an SQL statement. If [sqlite3_prepare_v2()] or -** the equivalent tries to allocate space for more than this many opcodes -** in a single prepared statement, an SQLITE_NOMEM error is returned.
)^ -** -** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
-**
The maximum number of arguments on a function.
)^ -** -** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
-**
The maximum number of [ATTACH | attached databases].)^
-** -** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] -** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
-**
The maximum length of the pattern argument to the [LIKE] or -** [GLOB] operators.
)^ -** -** [[SQLITE_LIMIT_VARIABLE_NUMBER]] -** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
-**
The maximum index number of any [parameter] in an SQL statement.)^ -** -** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
-**
The maximum depth of recursion for triggers.
)^ -** -** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
SQLITE_LIMIT_WORKER_THREADS
-**
The maximum number of auxiliary worker threads that a single -** [prepared statement] may start.
)^ -**
-*/ -#define SQLITE_LIMIT_LENGTH 0 -#define SQLITE_LIMIT_SQL_LENGTH 1 -#define SQLITE_LIMIT_COLUMN 2 -#define SQLITE_LIMIT_EXPR_DEPTH 3 -#define SQLITE_LIMIT_COMPOUND_SELECT 4 -#define SQLITE_LIMIT_VDBE_OP 5 -#define SQLITE_LIMIT_FUNCTION_ARG 6 -#define SQLITE_LIMIT_ATTACHED 7 -#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 -#define SQLITE_LIMIT_VARIABLE_NUMBER 9 -#define SQLITE_LIMIT_TRIGGER_DEPTH 10 -#define SQLITE_LIMIT_WORKER_THREADS 11 - -/* -** CAPI3REF: Prepare Flags -** -** These constants define various flags that can be passed into -** "prepFlags" parameter of the [sqlite3_prepare_v3()] and -** [sqlite3_prepare16_v3()] interfaces. -** -** New flags may be added in future releases of SQLite. -** -**
-** [[SQLITE_PREPARE_PERSISTENT]] ^(
SQLITE_PREPARE_PERSISTENT
-**
The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner -** that the prepared statement will be retained for a long time and -** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()] -** and [sqlite3_prepare16_v3()] assume that the prepared statement will -** be used just once or at most a few times and then destroyed using -** [sqlite3_finalize()] relatively soon. The current implementation acts -** on this hint by avoiding the use of [lookaside memory] so as not to -** deplete the limited store of lookaside memory. Future versions of -** SQLite may act on this hint differently. -** -** [[SQLITE_PREPARE_NORMALIZE]]
SQLITE_PREPARE_NORMALIZE
-**
The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used -** to be required for any prepared statement that wanted to use the -** [sqlite3_normalized_sql()] interface. However, the -** [sqlite3_normalized_sql()] interface is now available to all -** prepared statements, regardless of whether or not they use this -** flag. -** -** [[SQLITE_PREPARE_NO_VTAB]]
SQLITE_PREPARE_NO_VTAB
-**
The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler -** to return an error (error code SQLITE_ERROR) if the statement uses -** any virtual tables. -** -** [[SQLITE_PREPARE_DONT_LOG]]
SQLITE_PREPARE_DONT_LOG
-**
The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler -** errors from being sent to the error log defined by -** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test -** compiles to see if some SQL syntax is well-formed, without generating -** messages on the global error log when it is not. If the test compile -** fails, the sqlite3_prepare_v3() call returns the same error indications -** with or without this flag; it just omits the call to [sqlite3_log()] that -** logs the error. -**
-*/ -#define SQLITE_PREPARE_PERSISTENT 0x01 -#define SQLITE_PREPARE_NORMALIZE 0x02 -#define SQLITE_PREPARE_NO_VTAB 0x04 -#define SQLITE_PREPARE_DONT_LOG 0x10 - -/* -** CAPI3REF: Compiling An SQL Statement -** KEYWORDS: {SQL statement compiler} -** METHOD: sqlite3 -** CONSTRUCTOR: sqlite3_stmt -** -** To execute an SQL statement, it must first be compiled into a byte-code -** program using one of these routines. Or, in other words, these routines -** are constructors for the [prepared statement] object. -** -** The preferred routine to use is [sqlite3_prepare_v2()]. The -** [sqlite3_prepare()] interface is legacy and should be avoided. -** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used -** for special purposes. -** -** The use of the UTF-8 interfaces is preferred, as SQLite currently -** does all parsing using UTF-8. The UTF-16 interfaces are provided -** as a convenience. The UTF-16 interfaces work by converting the -** input text into UTF-8, then invoking the corresponding UTF-8 interface. -** -** The first argument, "db", is a [database connection] obtained from a -** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or -** [sqlite3_open16()]. The database connection must not have been closed. -** -** The second argument, "zSql", is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(), -** and sqlite3_prepare_v3() -** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(), -** and sqlite3_prepare16_v3() use UTF-16. -** -** ^If the nByte argument is negative, then zSql is read up to the -** first zero terminator. ^If nByte is positive, then it is the maximum -** number of bytes read from zSql. When nByte is positive, zSql is read -** up to the first zero terminator or until the nByte bytes have been read, -** whichever comes first. ^If nByte is zero, then no prepared -** statement is generated. -** If the caller knows that the supplied string is nul-terminated, then -** there is a small performance advantage to passing an nByte parameter that -** is the number of bytes in the input string including -** the nul-terminator. -** Note that nByte measure the length of the input in bytes, not -** characters, even for the UTF-16 interfaces. -** -** ^If pzTail is not NULL then *pzTail is made to point to the first byte -** past the end of the first SQL statement in zSql. These routines only -** compile the first statement in zSql, so *pzTail is left pointing to -** what remains uncompiled. -** -** ^*ppStmt is left pointing to a compiled [prepared statement] that can be -** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set -** to NULL. ^If the input text contains no SQL (if the input is an empty -** string or a comment) then *ppStmt is set to NULL. -** The calling procedure is responsible for deleting the compiled -** SQL statement using [sqlite3_finalize()] after it has finished with it. -** ppStmt may not be NULL. -** -** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; -** otherwise an [error code] is returned. -** -** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(), -** and sqlite3_prepare16_v3() interfaces are recommended for all new programs. -** The older interfaces (sqlite3_prepare() and sqlite3_prepare16()) -** are retained for backwards compatibility, but their use is discouraged. -** ^In the "vX" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. This causes the [sqlite3_step()] interface to -** behave differently in three ways: -** -**
    -**
  1. -** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] -** retries will occur before sqlite3_step() gives up and returns an error. -**
  2. -** -**
  3. -** ^When an error occurs, [sqlite3_step()] will return one of the detailed -** [error codes] or [extended error codes]. ^The legacy behavior was that -** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code -** and the application would have to make a second call to [sqlite3_reset()] -** in order to find the underlying cause of the problem. With the "v2" prepare -** interfaces, the underlying reason for the error is returned immediately. -**
  4. -** -**
  5. -** ^If the specific value bound to a [parameter | host parameter] in the -** WHERE clause might influence the choice of query plan for a statement, -** then the statement will be automatically recompiled, as if there had been -** a schema change, on the first [sqlite3_step()] call following any change -** to the [sqlite3_bind_text | bindings] of that [parameter]. -** ^The specific value of a WHERE-clause [parameter] might influence the -** choice of query plan if the parameter is the left-hand side of a [LIKE] -** or [GLOB] operator or if the parameter is compared to an indexed column -** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. -**
  6. -**
-** -**

^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having -** the extra prepFlags parameter, which is a bit array consisting of zero or -** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The -** sqlite3_prepare_v2() interface works exactly the same as -** sqlite3_prepare_v3() with a zero prepFlags parameter. -*/ -SQLITE_API int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare_v3( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare16_v3( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPI3REF: Retrieving Statement SQL -** METHOD: sqlite3_stmt -** -** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8 -** SQL text used to create [prepared statement] P if P was -** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], -** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. -** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 -** string containing the SQL text of prepared statement P with -** [bound parameters] expanded. -** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 -** string containing the normalized SQL text of prepared statement P. The -** semantics used to normalize a SQL statement are unspecified and subject -** to change. At a minimum, literal values will be replaced with suitable -** placeholders. -** -** ^(For example, if a prepared statement is created using the SQL -** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 -** and parameter :xyz is unbound, then sqlite3_sql() will return -** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() -** will return "SELECT 2345,NULL".)^ -** -** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory -** is available to hold the result, or if the result would exceed the -** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. -** -** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of -** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time -** option causes sqlite3_expanded_sql() to always return NULL. -** -** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) -** are managed by SQLite and are automatically freed when the prepared -** statement is finalized. -** ^The string returned by sqlite3_expanded_sql(P), on the other hand, -** is obtained from [sqlite3_malloc()] and must be freed by the application -** by passing it to [sqlite3_free()]. -** -** ^The sqlite3_normalized_sql() interface is only available if -** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. -*/ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); -SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); -#endif - -/* -** CAPI3REF: Determine If An SQL Statement Writes The Database -** METHOD: sqlite3_stmt -** -** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if -** and only if the [prepared statement] X makes no direct changes to -** the content of the database file. -** -** Note that [application-defined SQL functions] or -** [virtual tables] might change the database indirectly as a side effect. -** ^(For example, if an application defines a function "eval()" that -** calls [sqlite3_exec()], then the following SQL statement would -** change the database file through side-effects: -** -**

-**    SELECT eval('DELETE FROM t1') FROM t2;
-** 
-** -** But because the [SELECT] statement does not change the database file -** directly, sqlite3_stmt_readonly() would still return true.)^ -** -** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], -** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, -** since the statements themselves do not actually modify the database but -** rather they control the timing of when other statements modify the -** database. ^The [ATTACH] and [DETACH] statements also cause -** sqlite3_stmt_readonly() to return true since, while those statements -** change the configuration of a database connection, they do not make -** changes to the content of the database files on disk. -** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since -** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and -** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so -** 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 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 -** sqlite3_stmt_readonly() still returns false for such a statement. -** -** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN] -** statement, then sqlite3_stmt_readonly(X) returns the same value as -** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted. -*/ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement -** METHOD: sqlite3_stmt -** -** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the -** prepared statement S is an EXPLAIN statement, or 2 if the -** statement S is an EXPLAIN QUERY PLAN. -** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is -** an ordinary statement or a NULL pointer. -*/ -SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement -** METHOD: sqlite3_stmt -** -** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN -** setting for [prepared statement] S. If E is zero, then S becomes -** a normal prepared statement. If E is 1, then S behaves as if -** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if -** its SQL text began with "[EXPLAIN QUERY PLAN]". -** -** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared. -** SQLite tries to avoid a reprepare, but a reprepare might be necessary -** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode. -** -** Because of the potential need to reprepare, a call to -** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be -** reprepared because it was created using [sqlite3_prepare()] instead of -** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and -** hence has no saved SQL text with which to reprepare. -** -** Changing the explain setting for a prepared statement does not change -** the original SQL text for the statement. Hence, if the SQL text originally -** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0) -** is called to convert the statement into an ordinary statement, the EXPLAIN -** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S) -** output, even though the statement now acts like a normal SQL statement. -** -** This routine returns SQLITE_OK if the explain mode is successfully -** changed, or an error code if the explain mode could not be changed. -** The explain mode cannot be changed while a statement is active. -** Hence, it is good practice to call [sqlite3_reset(S)] -** immediately prior to calling sqlite3_stmt_explain(S,E). -*/ -SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode); - -/* -** CAPI3REF: Determine If A Prepared Statement Has Been Reset -** METHOD: sqlite3_stmt -** -** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the -** [prepared statement] S has been stepped at least once using -** [sqlite3_step(S)] but has neither run to completion (returned -** [SQLITE_DONE] from [sqlite3_step(S)]) nor -** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) -** interface returns false if S is a NULL pointer. If S is not a -** NULL pointer and is not a pointer to a valid [prepared statement] -** object, then the behavior is undefined and probably undesirable. -** -** This interface can be used in combination [sqlite3_next_stmt()] -** to locate all prepared statements associated with a database -** connection that are in need of being reset. This can be used, -** for example, in diagnostic routines to search for prepared -** statements that are holding a transaction open. -*/ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); - -/* -** CAPI3REF: Dynamically Typed Value Object -** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} -** -** SQLite uses the sqlite3_value object to represent all values -** that can be stored in a database table. SQLite uses dynamic typing -** for the values it stores. ^Values stored in sqlite3_value objects -** can be integers, floating point values, strings, BLOBs, or NULL. -** -** An sqlite3_value object may be either "protected" or "unprotected". -** Some interfaces require a protected sqlite3_value. Other interfaces -** will accept either a protected or an unprotected sqlite3_value. -** Every interface that accepts sqlite3_value arguments specifies -** whether or not it requires a protected sqlite3_value. The -** [sqlite3_value_dup()] interface can be used to construct a new -** protected sqlite3_value from an unprotected sqlite3_value. -** -** The terms "protected" and "unprotected" refer to whether or not -** a mutex is held. An internal mutex is held for a protected -** sqlite3_value object but no mutex is held for an unprotected -** sqlite3_value object. If SQLite is compiled to be single-threaded -** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) -** or if SQLite is run in one of reduced mutex modes -** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] -** then there is no distinction between protected and unprotected -** sqlite3_value objects and they can be used interchangeably. However, -** for maximum code portability it is recommended that applications -** still make the distinction between protected and unprotected -** sqlite3_value objects even when not strictly required. -** -** ^The sqlite3_value objects that are passed as parameters into the -** implementation of [application-defined SQL functions] are protected. -** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] -** are protected. -** ^The sqlite3_value object returned by -** [sqlite3_column_value()] is unprotected. -** Unprotected sqlite3_value objects may only be used as arguments -** to [sqlite3_result_value()], [sqlite3_bind_value()], and -** [sqlite3_value_dup()]. -** The [sqlite3_value_blob | sqlite3_value_type()] family of -** interfaces require protected sqlite3_value objects. -*/ -typedef struct sqlite3_value sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. ^A pointer to an sqlite3_context object -** is always first parameter to [application-defined SQL functions]. -** The application-defined SQL function implementation will pass this -** pointer through into calls to [sqlite3_result_int | sqlite3_result()], -** [sqlite3_aggregate_context()], [sqlite3_user_data()], -** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], -** and/or [sqlite3_set_auxdata()]. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements -** KEYWORDS: {host parameter} {host parameters} {host parameter name} -** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} -** METHOD: sqlite3_stmt -** -** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, -** literals may be replaced by a [parameter] that matches one of the following -** templates: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :VVV -**
  • @VVV -**
  • $VVV -**
-** -** In the templates above, NNN represents an integer literal, -** and VVV represents an alphanumeric identifier.)^ ^The values of these -** parameters (also called "host parameter names" or "SQL parameters") -** can be set using the sqlite3_bind_*() routines defined here. -** -** ^The first argument to the sqlite3_bind_*() routines is always -** a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. -** -** ^The second argument is the index of the SQL parameter to be set. -** ^The leftmost SQL parameter has an index of 1. ^When the same named -** SQL parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** ^The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_index()] API if desired. ^The index -** for "?NNN" parameters is the value of NNN. -** ^The NNN value must be between 1 and the [sqlite3_limit()] -** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766). -** -** ^The third argument is the value to bind to the parameter. -** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() -** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter -** is ignored and the end result is the same as sqlite3_bind_null(). -** ^If the third parameter to sqlite3_bind_text() is not NULL, then -** it should be a pointer to well-formed UTF8 text. -** ^If the third parameter to sqlite3_bind_text16() is not NULL, then -** it should be a pointer to well-formed UTF16 text. -** ^If the third parameter to sqlite3_bind_text64() is not NULL, then -** it should be a pointer to a well-formed unicode string that is -** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 -** otherwise. -** -** [[byte-order determination rules]] ^The byte-order of -** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) -** found in the first character, which is removed, or in the absence of a BOM -** the byte order is the native byte order of the host -** machine for sqlite3_bind_text16() or the byte order specified in -** the 6th parameter for sqlite3_bind_text64().)^ -** ^If UTF16 input text contains invalid unicode -** characters, then SQLite might change those invalid characters -** into the unicode replacement character: U+FFFD. -** -** ^(In those routines that have a fourth argument, its value is the -** number of bytes in the parameter. To be clear: the value is the -** number of bytes in the value, not the number of characters.)^ -** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() -** is negative, then the length of the string is -** the number of bytes up to the first zero terminator. -** If the fourth parameter to sqlite3_bind_blob() is negative, then -** the behavior is undefined. -** If a non-negative fourth parameter is provided to sqlite3_bind_text() -** or sqlite3_bind_text16() or sqlite3_bind_text64() then -** that parameter must be the byte offset -** where the NUL terminator would occur assuming the string were NUL -** terminated. If any NUL characters occur at byte offsets less than -** the value of the fourth parameter then the resulting string value will -** contain embedded NULs. The result of expressions involving strings -** with embedded NULs is undefined. -** -** ^The fifth argument to 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 passed 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 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 sqlite3_bind_text64() must be one of -** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] -** to specify the encoding of the text in the third parameter. If -** the sixth argument to sqlite3_bind_text64() is not one of the -** allowed values shown above, or if the text encoding is different -** from the encoding specified by the sixth parameter, then the behavior -** is undefined. -** -** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeroes. ^A zeroblob uses a fixed amount of memory -** (just an integer to hold its size) while it is being processed. -** Zeroblobs are intended to serve as placeholders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | incremental BLOB I/O] routines. -** ^A negative value for the zeroblob results in a zero-length BLOB. -** -** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in -** [prepared statement] S to have an SQL value of NULL, but to also be -** associated with the pointer P of type T. ^D is either a NULL pointer or -** a pointer to a destructor function for P. ^SQLite will invoke the -** destructor D with a single argument of P when it is finished using -** P. The T parameter should be a static string, preferably a string -** literal. The sqlite3_bind_pointer() routine is part of the -** [pointer passing interface] added for SQLite 3.20.0. -** -** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer -** for the [prepared statement] or with a prepared statement for which -** [sqlite3_step()] has been called more recently than [sqlite3_reset()], -** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() -** routine is passed a [prepared statement] that has been finalized, the -** result is undefined and probably harmful. -** -** ^Bindings are not cleared by the [sqlite3_reset()] routine. -** ^Unbound parameters are interpreted as NULL. -** -** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an -** [error code] if anything goes wrong. -** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB -** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or -** [SQLITE_MAX_LENGTH]. -** ^[SQLITE_RANGE] is returned if the parameter -** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. -** -** See also: [sqlite3_bind_parameter_count()], -** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, - void(*)(void*)); -SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, - void(*)(void*), unsigned char encoding); -SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*)); -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); - -/* -** CAPI3REF: Number Of SQL Parameters -** METHOD: sqlite3_stmt -** -** ^This routine can be used to find the number of [SQL parameters] -** in a [prepared statement]. SQL parameters are tokens of the -** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as -** placeholders for values that are [sqlite3_bind_blob | bound] -** to the parameters at a later time. -** -** ^(This routine actually returns the index of the largest (rightmost) -** parameter. For all forms except ?NNN, this will correspond to the -** number of unique parameters. If parameters of the ?NNN form are used, -** there may be gaps in the list.)^ -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_name()], and -** [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter -** METHOD: sqlite3_stmt -** -** ^The sqlite3_bind_parameter_name(P,N) interface returns -** the name of the N-th [SQL parameter] in the [prepared statement] P. -** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" -** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" -** respectively. -** In other words, the initial ":" or "$" or "@" or "?" -** is included as part of the name.)^ -** ^Parameters of the form "?" without a following integer have no name -** and are referred to as "nameless" or "anonymous parameters". -** -** ^The first host parameter has an index of 1, not 0. -** -** ^If the value N is out of range or if the N-th parameter is -** nameless, then NULL is returned. ^The returned string is -** always in UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()], -** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_count()], and -** [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name -** METHOD: sqlite3_stmt -** -** ^Return the index of an SQL parameter given its name. ^The -** index value returned is suitable for use as the second -** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero -** is returned if no matching parameter is found. ^The parameter -** name must be given in UTF-8 even if the original statement -** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or -** [sqlite3_prepare16_v3()]. -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_count()], and -** [sqlite3_bind_parameter_name()]. -*/ -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement -** METHOD: sqlite3_stmt -** -** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset -** the [sqlite3_bind_blob | bindings] on a [prepared statement]. -** ^Use this routine to reset all host parameters to NULL. -*/ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set -** METHOD: sqlite3_stmt -** -** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^If this routine returns 0, that means the -** [prepared statement] returns no data (for example an [UPDATE]). -** ^However, just because this routine returns a positive number does not -** mean that one or more rows of data will be returned. ^A SELECT statement -** will always have a positive sqlite3_column_count() but depending on the -** WHERE clause constraints and the table content, it might return no rows. -** -** See also: [sqlite3_data_count()] -*/ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set -** METHOD: sqlite3_stmt -** -** ^These routines return the name assigned to a particular column -** in the result set of a [SELECT] statement. ^The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF-8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF-16 string. ^The first parameter is the [prepared statement] -** that implements the [SELECT] statement. ^The second parameter is the -** column number. ^The leftmost column is number 0. -** -** ^The returned string pointer is valid until either the [prepared statement] -** is destroyed by [sqlite3_finalize()] or until the statement is automatically -** reprepared by the first call to [sqlite3_step()] for a particular run -** or until the next call to -** sqlite3_column_name() or sqlite3_column_name16() on the same column. -** -** ^If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -** -** ^The name of a result column is the value of the "AS" clause for -** that column, if there is an AS clause. If there is no AS clause -** then the name of the column is unspecified and may change from -** one release of SQLite to the next. -*/ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result -** METHOD: sqlite3_stmt -** -** ^These routines provide a means to determine the database, table, and -** table column that is the origin of a particular result column in a -** [SELECT] statement. -** ^The name of the database or table or column can be returned as -** either a UTF-8 or UTF-16 string. ^The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. -** ^The returned string is valid until the [prepared statement] is destroyed -** using [sqlite3_finalize()] or until the statement is automatically -** reprepared by the first call to [sqlite3_step()] for a particular run -** or until the same information is requested -** again in a different encoding. -** -** ^The names returned are the original un-aliased names of the -** database, table, and column. -** -** ^The first argument to these interfaces is a [prepared statement]. -** ^These functions return information about the Nth result column returned by -** the statement, where N is the second function argument. -** ^The left-most column is column 0 for these routines. -** -** ^If the Nth column returned by the statement is an expression or -** subquery and is not a column value, then all of these functions return -** NULL. ^These routines might also return NULL if a memory allocation error -** occurs. ^Otherwise, they return the name of the attached database, table, -** or column that query result column was extracted from. -** -** ^As with all other SQLite APIs, those whose names end with "16" return -** UTF-16 encoded strings and the other functions return UTF-8. -** -** ^These APIs are only available if the library was compiled with the -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. -** -** If two or more threads call one or more -** [sqlite3_column_database_name | column metadata interfaces] -** for the same [prepared statement] and result column -** at the same time then the results are undefined. -*/ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result -** METHOD: sqlite3_stmt -** -** ^(The first parameter is a [prepared statement]. -** If this statement is a [SELECT] statement and the Nth column of the -** returned result set of that [SELECT] is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned.)^ ^If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** ^The returned string is always UTF-8 encoded. -** -** ^(For example, given the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** and the following statement to be compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** this routine would return the string "VARIANT" for the second result -** column (i==1), and a NULL pointer for the first result column (i==0).)^ -** -** ^SQLite uses dynamic run-time typing. ^So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. ^Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement -** METHOD: sqlite3_stmt -** -** After a [prepared statement] has been prepared using any of -** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()], -** or [sqlite3_prepare16_v3()] or one of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function -** must be called one or more times to evaluate the statement. -** -** The details of the behavior of the sqlite3_step() interface depend -** on whether the statement was prepared using the newer "vX" interfaces -** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()], -** [sqlite3_prepare16_v2()] or the older legacy -** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "vX" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** ^In the legacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** ^With the "v2" interface, any of the other [result codes] or -** [extended result codes] might be returned as well. -** -** ^[SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. ^If the statement is a [COMMIT] -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a [COMMIT] and occurs within an -** explicit transaction then you should rollback the transaction before -** continuing. -** -** ^[SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] -** is returned each time a new row of data is ready for processing by the -** caller. The values may be accessed using the [column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** ^[SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** ^With the legacy interface, a more specific error code (for example, -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [prepared statement]. ^In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** For all versions of SQLite up to and including 3.6.23.1, a call to -** [sqlite3_reset()] was required after sqlite3_step() returned anything -** other than [SQLITE_ROW] before any subsequent invocation of -** sqlite3_step(). Failure to reset the prepared statement using -** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from -** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]), -** sqlite3_step() began -** calling [sqlite3_reset()] automatically in this circumstance rather -** than returning [SQLITE_MISUSE]. This is not considered a compatibility -** break because any application that ever receives an SQLITE_MISUSE error -** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option -** can be used to restore the legacy behavior. -** -** Goofy Interface Alert: In the legacy interface, the sqlite3_step() -** API always returns a generic error code, [SQLITE_ERROR], following any -** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call -** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the -** specific [error codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()] -** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, -** then the more specific [error codes] are returned directly -** by sqlite3_step(). The use of the "vX" interfaces is recommended. -*/ -SQLITE_API int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set -** METHOD: sqlite3_stmt -** -** ^The sqlite3_data_count(P) interface returns the number of columns in the -** current row of the result set of [prepared statement] P. -** ^If prepared statement P does not have results ready to return -** (via calls to the [sqlite3_column_int | sqlite3_column()] family of -** interfaces) then sqlite3_data_count(P) returns 0. -** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. -** ^The sqlite3_data_count(P) routine returns 0 if the previous call to -** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) -** will return non-zero if previous call to [sqlite3_step](P) returned -** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] -** where it always returns zero since each step of that multi-step -** pragma returns 0 columns of data. -** -** See also: [sqlite3_column_count()] -*/ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes -** KEYWORDS: SQLITE_TEXT -** -** ^(Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
)^ -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Result Values From A Query -** KEYWORDS: {column access functions} -** METHOD: sqlite3_stmt -** -** Summary: -**
-**
sqlite3_column_blobBLOB result -**
sqlite3_column_doubleREAL result -**
sqlite3_column_int32-bit INTEGER result -**
sqlite3_column_int6464-bit INTEGER result -**
sqlite3_column_textUTF-8 TEXT result -**
sqlite3_column_text16UTF-16 TEXT result -**
sqlite3_column_valueThe result as an -** [sqlite3_value|unprotected sqlite3_value] object. -**
    -**
sqlite3_column_bytesSize of a BLOB -** or a UTF-8 TEXT result in bytes -**
sqlite3_column_bytes16   -** →  Size of UTF-16 -** TEXT in bytes -**
sqlite3_column_typeDefault -** datatype of the result -**
-** -** Details: -** -** ^These routines return information about a single column of the current -** result row of a query. ^In every case the first argument is a pointer -** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] -** that was returned from [sqlite3_prepare_v2()] or one of its variants) -** and the second argument is the index of the column for which information -** should be returned. ^The leftmost column of the result set has the index 0. -** ^The number of columns in the result can be determined using -** [sqlite3_column_count()]. -** -** If the SQL statement does not currently point to a valid row, or if the -** column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16) -** each return the value of a result column in a specific data format. If -** the result column is not initially in the requested format (for example, -** if the query returns an integer but the sqlite3_column_text() interface -** is used to extract the value) then an automatic type conversion is performed. -** -** ^The sqlite3_column_type() routine returns the -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. ^The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. -** The return value of sqlite3_column_type() can be used to decide which -** of the first six interface should be used to extract the column value. -** The value returned by sqlite3_column_type() is only meaningful if no -** automatic type conversions have occurred for the value in question. -** After a type conversion, the result of calling sqlite3_column_type() -** is undefined, though harmless. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes() -** or sqlite3_column_bytes16() interfaces can be used to determine the size -** of that BLOB or string. -** -** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** ^If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** ^If the result is NULL, then sqlite3_column_bytes() returns zero. -** -** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() -** routine returns the number of bytes in that BLOB or string. -** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts -** the string to UTF-16 and then returns the number of bytes. -** ^If the result is a numeric value then sqlite3_column_bytes16() uses -** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns -** the number of bytes in that string. -** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. -** -** ^The values returned by [sqlite3_column_bytes()] and -** [sqlite3_column_bytes16()] do not include the zero terminators at the end -** of the string. ^For clarity: the values returned by -** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of -** bytes in the string, not the number of characters. -** -** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even empty strings, are always zero-terminated. ^The return -** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. -** -** ^Strings returned by sqlite3_column_text16() always have the endianness -** which is native to the platform, regardless of the text encoding set -** for the database. -** -** Warning: ^The object returned by [sqlite3_column_value()] is an -** [unprotected sqlite3_value] object. In a multithreaded environment, -** an unprotected sqlite3_value object may only be used safely with -** [sqlite3_bind_value()] and [sqlite3_result_value()]. -** If the [unprotected sqlite3_value] object returned by -** [sqlite3_column_value()] is used in any other way, including calls -** to routines like [sqlite3_value_int()], [sqlite3_value_text()], -** or [sqlite3_value_bytes()], the behavior is not threadsafe. -** Hence, the sqlite3_column_value() interface -** is normally only useful within the implementation of -** [application-defined SQL functions] or [virtual tables], not within -** top-level application code. -** -** 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, [sqlite3_snprintf()] is used internally to perform the -** conversion automatically. ^(The following table details the conversions -** that are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is a NULL pointer -**
NULL BLOB Result is a NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as INTEGER->TEXT -**
FLOAT INTEGER [CAST] to INTEGER -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB [CAST] to BLOB -**
TEXT INTEGER [CAST] to INTEGER -**
TEXT FLOAT [CAST] to REAL -**
TEXT BLOB No change -**
BLOB INTEGER [CAST] to INTEGER -**
BLOB FLOAT [CAST] to REAL -**
BLOB TEXT [CAST] to TEXT, ensure zero terminator -**
-**
)^ -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() or -** sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.
  • -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.
  • -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.
  • -**
-** -** ^Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer references will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometimes they -** are not possible and in those cases prior pointers are invalidated. -** -** The safest policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), -** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result -** into the desired format, then invoke sqlite3_column_bytes() or -** sqlite3_column_bytes16() to find the size of the result. Do not mix calls -** to sqlite3_column_text() or sqlite3_column_blob() with calls to -** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() -** with calls to sqlite3_column_bytes(). -** -** ^The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. ^The memory space used to hold strings -** and BLOBs is freed automatically. Do not pass the pointers returned -** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** As long as the input parameters are correct, these routines will only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -**
    -**
  • sqlite3_column_blob() -**
  • sqlite3_column_text() -**
  • sqlite3_column_text16() -**
  • sqlite3_column_bytes() -**
  • sqlite3_column_bytes16() -**
-** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. -*/ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object -** DESTRUCTOR: sqlite3_stmt -** -** ^The sqlite3_finalize() function is called to delete a [prepared statement]. -** ^If the most recent evaluation of the statement encountered no errors -** or if the statement is never been evaluated, then sqlite3_finalize() returns -** SQLITE_OK. ^If the most recent evaluation of statement S failed, then -** sqlite3_finalize(S) returns the appropriate [error code] or -** [extended error code]. -** -** ^The sqlite3_finalize(S) routine can be called at any point during -** the life cycle of [prepared statement] S: -** before statement S is ever evaluated, after -** one or more calls to [sqlite3_reset()], or after any call -** to [sqlite3_step()] regardless of whether or not the statement has -** completed execution. -** -** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. -** -** The application must finalize every [prepared statement] in order to avoid -** resource leaks. It is a grievous error for the application to try to use -** a prepared statement after it has been finalized. Any use of a prepared -** statement after it has been finalized can result in undefined and -** undesirable behavior such as segfaults and heap corruption. -*/ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object -** METHOD: sqlite3_stmt -** -** The sqlite3_reset() function is called to reset a [prepared statement] -** object back to its initial state, ready to be re-executed. -** ^Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -** -** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S -** back to the beginning of its program. -** -** ^The return code from [sqlite3_reset(S)] indicates whether or not -** the previous evaluation of prepared statement S completed successfully. -** ^If [sqlite3_step(S)] has never before been called on S or if -** [sqlite3_step(S)] has not been called since the previous call -** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return -** [SQLITE_OK]. -** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S indicated an error, then -** [sqlite3_reset(S)] returns an appropriate [error code]. -** ^The [sqlite3_reset(S)] interface might also return an [error code] -** if there were no prior errors but the process of resetting -** the prepared statement caused a new error. ^For example, if an -** [INSERT] statement with a [RETURNING] clause is only stepped one time, -** that one call to [sqlite3_step(S)] might return SQLITE_ROW but -** the overall statement might still fail and the [sqlite3_reset(S)] call -** might return SQLITE_BUSY if locking constraints prevent the -** database change from committing. Therefore, it is important that -** applications check the return code from [sqlite3_reset(S)] even if -** no prior call to [sqlite3_step(S)] indicated a problem. -** -** ^The [sqlite3_reset(S)] interface does not change the values -** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. -*/ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); - - -/* -** CAPI3REF: Create Or Redefine SQL Functions -** KEYWORDS: {function creation routines} -** METHOD: sqlite3 -** -** ^These functions (collectively known as "function creation routines") -** are used to add SQL functions or aggregates or to redefine the behavior -** of existing SQL functions or aggregates. The only differences between -** the three "sqlite3_create_function*" routines are the text encoding -** expected for the second parameter (the name of the function being -** created) and the presence or absence of a destructor callback for -** the application data pointer. Function sqlite3_create_window_function() -** is similar, but allows the user to supply the extra callback functions -** needed by [aggregate window functions]. -** -** ^The first parameter is the [database connection] to which the SQL -** function is to be added. ^If an application uses more than one database -** connection then application-defined SQL functions must be added -** to each database connection separately. -** -** ^The second parameter is the name of the SQL function to be created or -** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 -** representation, exclusive of the zero-terminator. ^Note that the name -** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. -** ^Any attempt to create a function with a longer name -** will result in [SQLITE_MISUSE] being returned. -** -** ^The third parameter (nArg) -** is the number of arguments that the SQL function or -** aggregate takes. ^If this parameter is -1, then the SQL function or -** aggregate may take any number of arguments between 0 and the limit -** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third -** parameter is less than -1 or greater than 127 then the behavior is -** undefined. -** -** ^The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. The application should set this parameter to -** [SQLITE_UTF16LE] if the function implementation invokes -** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the -** implementation invokes [sqlite3_value_text16be()] on an input, or -** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] -** otherwise. ^The same SQL function may be registered multiple times using -** different preferred text encodings, with different implementations for -** each encoding. -** ^When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** -** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] -** to signal that the function will always return the same result given -** the same inputs within a single SQL statement. Most SQL functions are -** deterministic. The built-in [random()] SQL function is an example of a -** function that is not deterministic. The SQLite query planner is able to -** perform additional optimizations on deterministic functions, so use -** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. -** -** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] -** flag, which if present prevents the function from being invoked from -** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, -** index expressions, or the WHERE clause of partial indexes. -** -** 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, views, CHECK constraints, or other elements of -** the database schema. This flag is especially recommended for SQL -** functions that have side effects or reveal internal application state. -** Without this flag, an attacker might be able to modify the schema of -** 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. -** -** ^(The fifth parameter is an arbitrary pointer. The implementation of the -** function can gain access to this pointer using [sqlite3_user_data()].)^ -** -** ^The sixth, seventh and eighth parameters passed to the three -** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL function or -** aggregate. ^A scalar SQL function requires an implementation of the xFunc -** callback only; NULL pointers must be passed as the xStep and xFinal -** parameters. ^An aggregate SQL function requires an implementation of xStep -** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing -** SQL function or aggregate, pass NULL pointers for all three function -** callbacks. -** -** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue -** and xInverse) passed to sqlite3_create_window_function are pointers to -** C-language callbacks that implement the new function. xStep and xFinal -** must both be non-NULL. xValue and xInverse may either both be NULL, in -** which case a regular aggregate function is created, or must both be -** non-NULL, in which case the new function may be used as either an aggregate -** or aggregate window function. More details regarding the implementation -** of aggregate window functions are -** [user-defined window functions|available here]. -** -** ^(If the final parameter to sqlite3_create_function_v2() or -** sqlite3_create_window_function() is not NULL, then it is the destructor for -** the application data pointer. The destructor is invoked when the function -** is deleted, either by being overloaded or when the database connection -** closes.)^ ^The destructor is also invoked if the call to -** sqlite3_create_function_v2() fails. ^When the destructor callback is -** invoked, it is passed a single argument which is a copy of the application -** data pointer which was the fifth parameter to sqlite3_create_function_v2(). -** -** ^It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing preferred text encodings. ^SQLite will use -** the implementation that most closely matches the way in which the -** SQL function is used. ^A function implementation with a non-negative -** nArg parameter is a better match than a function implementation with -** a negative nArg. ^A function where the preferred text encoding -** matches the database encoding is a better -** match than a function where the encoding is different. -** ^A function where the encoding difference is between UTF16le and UTF16be -** is a closer match than a function where the encoding difference is -** between UTF8 and UTF16. -** -** ^Built-in functions may be overloaded by new application-defined functions. -** -** ^An application-defined function is permitted to call other -** SQLite interfaces. However, such calls must not -** close the database connection nor finalize or reset the prepared -** statement in which the function is running. -*/ -SQLITE_API int sqlite3_create_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -SQLITE_API int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -SQLITE_API int sqlite3_create_function_v2( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*) -); -SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) -); - -/* -** CAPI3REF: Text Encodings -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ -#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ -#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */ -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* Deprecated */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Function Flags -** -** These constants may be ORed together with the -** [SQLITE_UTF8 | preferred text encoding] as the fourth argument -** to [sqlite3_create_function()], [sqlite3_create_function16()], or -** [sqlite3_create_function_v2()]. -** -**
-** [[SQLITE_DETERMINISTIC]]
SQLITE_DETERMINISTIC
-** The SQLITE_DETERMINISTIC flag means that the new function always gives -** the same output when the input parameters are the same. -** The [abs|abs() function] is deterministic, for example, but -** [randomblob|randomblob()] is not. Functions must -** be deterministic in order to be used in certain contexts such as -** with the WHERE clause of [partial indexes] or in [generated columns]. -** SQLite might also optimize deterministic functions by factoring them -** out of inner loops. -**
-** -** [[SQLITE_DIRECTONLY]]
SQLITE_DIRECTONLY
-** The SQLITE_DIRECTONLY flag means that the function may only be invoked -** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], or [generated columns]. -**

-** The SQLITE_DIRECTONLY flag is recommended for any -** [application-defined SQL function] -** that has side-effects or that could potentially leak sensitive information. -** This will prevent attacks in which an application is tricked -** into using a database file that has had its schema surreptitiously -** modified to invoke the application-defined function in ways that are -** harmful. -**

-** Some people say it is good practice to set SQLITE_DIRECTONLY on all -** [application-defined SQL functions], regardless of whether or not they -** are security sensitive, as doing so prevents those functions from being used -** inside of the database schema, and thus ensures that the database -** can be inspected and modified using generic tools (such as the [CLI]) -** that do not have access to the application-defined functions. -**

-** -** [[SQLITE_INNOCUOUS]]
SQLITE_INNOCUOUS
-** The SQLITE_INNOCUOUS flag means that the function is unlikely -** to cause problems even if misused. An innocuous function should have -** no side effects and should not depend on any values other than its -** input parameters. The [abs|abs() function] is an example of an -** innocuous function. -** The [load_extension() SQL function] is not innocuous because of its -** side effects. -**

SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not -** exactly the same. The [random|random() function] is an example of a -** function that is innocuous but not deterministic. -**

Some heightened security settings -** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF]) -** disable the use of SQL functions inside views and triggers and in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], and [generated columns] unless -** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions -** are innocuous. Developers are advised to avoid using the -** SQLITE_INNOCUOUS flag for application-defined functions unless the -** function has been carefully audited and found to be free of potentially -** security-adverse side-effects and information-leaks. -**

-** -** [[SQLITE_SUBTYPE]]
SQLITE_SUBTYPE
-** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** This flag instructs SQLite to omit some corner-case optimizations that -** might disrupt the operation of the [sqlite3_value_subtype()] function, -** causing it to return zero rather than the correct subtype(). -** All SQL functions that invoke [sqlite3_value_subtype()] should have this -** property. If the SQLITE_SUBTYPE property is omitted, then the return -** value from [sqlite3_value_subtype()] might sometimes be zero even though -** a non-zero subtype was specified by the function argument expression. -** -** [[SQLITE_RESULT_SUBTYPE]]
SQLITE_RESULT_SUBTYPE
-** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_result_subtype()] to cause a sub-type to be associated with its -** result. -** Every function that invokes [sqlite3_result_subtype()] should have this -** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as term in an -** [expression index]. On the other hand, SQL functions that never invoke -** [sqlite3_result_subtype()] should avoid setting this property, as the -** purpose of this property is to disable certain optimizations that are -** incompatible with subtypes. -** -** [[SQLITE_SELFORDER1]]
SQLITE_SELFORDER1
-** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate -** that internally orders the values provided to the first argument. The -** ordered-set aggregate SQL notation with a single ORDER BY term can be -** used to invoke this function. If the ordered-set aggregate notation is -** used on a function that lacks this flag, then an error is raised. Note -** that the ordered-set aggregate syntax is only available if SQLite is -** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option. -**
-**
-*/ -#define SQLITE_DETERMINISTIC 0x000000800 -#define SQLITE_DIRECTONLY 0x000080000 -#define SQLITE_SUBTYPE 0x000100000 -#define SQLITE_INNOCUOUS 0x000200000 -#define SQLITE_RESULT_SUBTYPE 0x001000000 -#define SQLITE_SELFORDER1 0x002000000 - -/* -** CAPI3REF: Deprecated Functions -** DEPRECATED -** -** These functions are [deprecated]. In order to maintain -** backwards compatibility with older code, these functions continue -** to be supported. However, new applications should avoid -** the use of these functions. To encourage programmers to avoid -** these functions, we will not explain what they do. -*/ -#ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), - void*,sqlite3_int64); -#endif - -/* -** CAPI3REF: Obtaining SQL Values -** METHOD: sqlite3_value -** -** Summary: -**
-**
sqlite3_value_blobBLOB value -**
sqlite3_value_doubleREAL value -**
sqlite3_value_int32-bit INTEGER value -**
sqlite3_value_int6464-bit INTEGER value -**
sqlite3_value_pointerPointer value -**
sqlite3_value_textUTF-8 TEXT value -**
sqlite3_value_text16UTF-16 TEXT value in -** the native byteorder -**
sqlite3_value_text16beUTF-16be TEXT value -**
sqlite3_value_text16leUTF-16le TEXT value -**
    -**
sqlite3_value_bytesSize of a BLOB -** or a UTF-8 TEXT in bytes -**
sqlite3_value_bytes16   -** →  Size of UTF-16 -** TEXT in bytes -**
sqlite3_value_typeDefault -** datatype of the value -**
sqlite3_value_numeric_type   -** →  Best numeric datatype of the value -**
sqlite3_value_nochange   -** →  True if the column is unchanged in an UPDATE -** against a virtual table. -**
sqlite3_value_frombind   -** →  True if value originated from a [bound parameter] -**
-** -** Details: -** -** These routines extract type, size, and content information from -** [protected sqlite3_value] objects. Protected sqlite3_value objects -** are used to pass parameter information into the functions that -** implement [application-defined SQL functions] and [virtual tables]. -** -** These routines work only with [protected sqlite3_value] objects. -** Any attempt to use these routines on an [unprotected sqlite3_value] -** is not threadsafe. -** -** ^These routines work just like the corresponding [column access functions] -** except that these routines take a single [protected sqlite3_value] object -** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. -** -** ^The sqlite3_value_text16() interface extracts a UTF-16 string -** in the native byte-order of the host machine. ^The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF-16 strings as big-endian and little-endian respectively. -** -** ^If [sqlite3_value] object V was initialized -** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)] -** and if X and Y are strings that compare equal according to strcmp(X,Y), -** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise, -** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer() -** routine is part of the [pointer passing interface] added for SQLite 3.20.0. -** -** ^(The sqlite3_value_type(V) interface returns the -** [SQLITE_INTEGER | datatype code] for the initial datatype of the -** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^ -** Other interfaces might change the datatype for an sqlite3_value object. -** For example, if the datatype is initially SQLITE_INTEGER and -** sqlite3_value_text(V) is called to extract a text value for that -** integer, then subsequent calls to sqlite3_value_type(V) might return -** SQLITE_TEXT. Whether or not a persistent internal datatype conversion -** occurs is undefined and may change from one release of SQLite to the next. -** -** ^(The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words, if the value is a string that looks like a number) -** then the conversion is performed. Otherwise no conversion occurs. -** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ -** -** ^Within the [xUpdate] method of a [virtual table], the -** sqlite3_value_nochange(X) interface returns true if and only if -** the column corresponding to X is unchanged by the UPDATE operation -** that the xUpdate method call was invoked to implement and if -** and the prior [xColumn] method call that was invoked to extracted -** the value for that column returned without setting a result (probably -** because it queried [sqlite3_vtab_nochange()] and found that the column -** was unchanging). ^Within an [xUpdate] method, any value for which -** sqlite3_value_nochange(X) is true will in all other respects appear -** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other -** than within an [xUpdate] method call for an UPDATE statement, then -** the return value is arbitrary and meaningless. -** -** ^The sqlite3_value_frombind(X) interface returns non-zero if the -** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] -** interfaces. ^If X comes from an SQL literal value, or a table column, -** or an expression, then sqlite3_value_frombind(X) returns zero. -** -** Please pay particular attention to the fact that the pointer returned -** from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the [sqlite3_value*] parameters. -** -** As long as the input parameter is correct, these routines can only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -**
    -**
  • sqlite3_value_blob() -**
  • sqlite3_value_text() -**
  • sqlite3_value_text16() -**
  • sqlite3_value_text16le() -**
  • sqlite3_value_text16be() -**
  • sqlite3_value_bytes() -**
  • sqlite3_value_bytes16() -**
-** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. -*/ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API double sqlite3_value_double(sqlite3_value*); -SQLITE_API int sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*); -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API int sqlite3_value_type(sqlite3_value*); -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); -SQLITE_API int sqlite3_value_nochange(sqlite3_value*); -SQLITE_API int sqlite3_value_frombind(sqlite3_value*); - -/* -** CAPI3REF: Report the internal text encoding state of an sqlite3_value object -** METHOD: sqlite3_value -** -** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding -** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X) -** returns something other than SQLITE_TEXT, then the return value from -** sqlite3_value_encoding(X) is meaningless. ^Calls to -** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)], -** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or -** [sqlite3_value_bytes16(X)] might change the encoding of the value X and -** thus change the return from subsequent calls to sqlite3_value_encoding(X). -** -** This routine is intended for used by applications that test and validate -** the SQLite implementation. This routine is inquiring about the opaque -** internal state of an [sqlite3_value] object. Ordinary applications should -** not need to know what the internal state of an sqlite3_value object is and -** hence should not need to use this interface. -*/ -SQLITE_API int sqlite3_value_encoding(sqlite3_value*); - -/* -** CAPI3REF: Finding The Subtype Of SQL Values -** METHOD: sqlite3_value -** -** The sqlite3_value_subtype(V) function returns the subtype for -** an [application-defined SQL function] argument V. The subtype -** information can be used to pass a limited amount of context from -** one SQL function to another. Use the [sqlite3_result_subtype()] -** routine to set the subtype for the return value of an SQL function. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_SUBTYPE] property in the text -** encoding argument when the function is [sqlite3_create_function|registered]. -** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() -** might return zero instead of the upstream subtype in some corner cases. -*/ -SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); - -/* -** CAPI3REF: Copy And Free SQL Values -** METHOD: sqlite3_value -** -** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] -** object V and returns a pointer to that copy. ^The [sqlite3_value] returned -** is a [protected sqlite3_value] object even if the input is not. -** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. ^If V is a [pointer value], then the result -** of sqlite3_value_dup(V) is a NULL value. -** -** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object -** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer -** then sqlite3_value_free(V) is a harmless no-op. -*/ -SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void sqlite3_value_free(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context -** METHOD: sqlite3_context -** -** Implementations of aggregate SQL functions use this -** routine to allocate memory for storing their state. -** -** ^The first time the sqlite3_aggregate_context(C,N) routine is called -** for a particular aggregate function, SQLite allocates -** N bytes of memory, zeroes out that memory, and returns a pointer -** to the new memory. ^On second and subsequent calls to -** sqlite3_aggregate_context() for the same aggregate function instance, -** the same buffer is returned. Sqlite3_aggregate_context() is normally -** called once for each invocation of the xStep callback and then one -** last time when the xFinal callback is invoked. ^(When no rows match -** an aggregate query, the xStep() callback of the aggregate function -** implementation is never called and xFinal() is called exactly once. -** In those cases, sqlite3_aggregate_context() might be called for the -** first time from within xFinal().)^ -** -** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer -** when first called if N is less than or equal to zero or if a memory -** allocation error occurs. -** -** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is -** determined by the N parameter on the first successful call. Changing the -** value of N in any subsequent call to sqlite3_aggregate_context() within -** the same aggregate function instance will not resize the memory -** allocation.)^ Within the xFinal callback, it is customary to set -** N=0 in calls to sqlite3_aggregate_context(C,N) so that no -** pointless memory allocations occur. -** -** ^SQLite automatically frees the memory allocated by -** sqlite3_aggregate_context() when the aggregate query concludes. -** -** The first parameter must be a copy of the -** [sqlite3_context | SQL function context] that is the first parameter -** to the xStep or xFinal callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions -** METHOD: sqlite3_context -** -** ^The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. -** -** This routine must be called from the same thread in which -** the application-defined function is running. -*/ -SQLITE_API void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Database Connection For Functions -** METHOD: sqlite3_context -** -** ^The sqlite3_context_db_handle() interface returns a copy of -** the pointer to the [database connection] (the 1st parameter) -** of the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. -*/ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data -** METHOD: sqlite3_context -** -** These functions may be used by (non-aggregate) SQL functions to -** associate auxiliary data with argument values. If the same argument -** value is passed to multiple invocations of the same SQL function during -** query execution, under some circumstances the associated auxiliary data -** might be preserved. An example of where this might be useful is in a -** regular-expression matching function. The compiled version of the regular -** expression can be stored as auxiliary data associated with the pattern string. -** Then as long as the pattern string remains the same, -** the compiled regular expression can be reused on multiple -** invocations of the same function. -** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data -** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument -** value to the application-defined function. ^N is zero for the left-most -** function argument. ^If there is no auxiliary data -** associated with the function argument, the sqlite3_get_auxdata(C,N) interface -** returns a NULL pointer. -** -** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the -** N-th argument of the application-defined function. ^Subsequent -** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or -** NULL if the auxiliary data has been discarded. -** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, -** SQLite will invoke the destructor function X with parameter P exactly -** once, when the auxiliary data is discarded. -** SQLite is free to discard the auxiliary data at any time, including:
    -**
  • ^(when the corresponding function parameter changes)^, or -**
  • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the -** SQL statement)^, or -**
  • ^(when sqlite3_set_auxdata() is invoked again on the same -** parameter)^, or -**
  • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ -**
  • ^(during the original sqlite3_set_auxdata() call if the function -** is evaluated during query planning instead of during query execution, -** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
-** -** Note the last two bullets in particular. The destructor X in -** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the -** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() -** should be called near the end of the function implementation and the -** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. Furthermore, a call to -** sqlite3_get_auxdata() that occurs immediately after a corresponding call -** to sqlite3_set_auxdata() might still return NULL if an out-of-memory -** condition occurred during the sqlite3_set_auxdata() call or if the -** function is being evaluated during query planning rather than during -** query execution. -** -** ^(In practice, auxiliary data is preserved between function calls for -** function parameters that are compile-time constants, including literal -** values and [parameters] and expressions composed from the same.)^ -** -** The value of the N parameter to these interfaces should be non-negative. -** Future enhancements may make use of negative N values to define new -** kinds of function caching behavior. -** -** These routines must be called from the same thread in which -** the SQL function is running. -** -** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. -*/ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - -/* -** CAPI3REF: Database Connection Client Data -** METHOD: sqlite3 -** -** These functions are used to associate one or more named pointers -** with a [database connection]. -** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P -** to be attached to [database connection] D using name N. Subsequent -** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P -** or a NULL pointer if there were no prior calls to -** sqlite3_set_clientdata() with the same values of D and N. -** Names are compared using strcmp() and are thus case sensitive. -** -** If P and X are both non-NULL, then the destructor X is invoked with -** argument P on the first of the following occurrences: -**
    -**
  • An out-of-memory error occurs during the call to -** sqlite3_set_clientdata() which attempts to register pointer P. -**
  • A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made -** with the same D and N parameters. -**
  • The database connection closes. SQLite does not make any guarantees -** about the order in which destructors are called, only that all -** destructors will be called exactly once at some point during the -** database connection closing process. -**
-** -** SQLite does not do anything with client data other than invoke -** destructors on the client data at the appropriate time. The intended -** use for client data is to provide a mechanism for wrapper libraries -** to store additional information about an SQLite database connection. -** -** There is no limit (other than available memory) on the number of different -** client data pointers (with different names) that can be attached to a -** single database connection. However, the implementation is optimized -** for the case of having only one or two different client data names. -** Applications and wrapper libraries are discouraged from using more than -** one client data name each. -** -** There is no way to enumerate the client data pointers -** associated with a database connection. The N parameter can be thought -** of as a secret key such that only code that knows the secret key is able -** to access the associated data. -** -** Security Warning: These interfaces should not be exposed in scripting -** languages or in other circumstances where it might be possible for an -** attacker to invoke them. Any agent that can invoke these interfaces -** can probably also take control of the process. -** -** Database connection client data is only available for SQLite -** version 3.44.0 ([dateof:3.44.0]) and later. -** -** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. -*/ -SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*); -SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior -** -** These are special values for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. ^If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. ^The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function -** METHOD: sqlite3_context -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the [parameter binding] family of -** functions used to bind values to host parameters in prepared statements. -** Refer to the [SQL parameter] documentation for additional information. -** -** ^The sqlite3_result_blob() interface sets the result from -** an application-defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** -** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) -** interfaces set the result of the application-defined function to be -** a BLOB containing all zero bytes and N bytes in size. -** -** ^The sqlite3_result_double() interface sets the result from -** an application-defined function to be a floating point value specified -** by its 2nd argument. -** -** ^The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** ^SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. ^SQLite interprets the error -** message string from sqlite3_result_error() as UTF-8. ^SQLite -** interprets the string from sqlite3_result_error16() as UTF-16 using -** the same [byte-order determination rules] as [sqlite3_bind_text16()]. -** ^If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** ^If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** ^The sqlite3_result_error() and sqlite3_result_error16() -** routines make a private copy of the error message text before -** they return. Hence, the calling function can deallocate or -** modify the text after they return without harm. -** ^The sqlite3_result_error_code() function changes the error code -** returned by SQLite as a result of an error in a function. ^By default, -** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() -** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. -** -** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an -** error indicating that a string or BLOB is too long to represent. -** -** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an -** error indicating that a memory allocation failed. -** -** ^The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** ^The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** ^The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** ^The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64() interface sets the return value of an -** application-defined function to be a text string in an encoding -** specified by the fifth (and last) parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. -** ^SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces -** other than sqlite3_result_text64() is negative, then SQLite computes -** the string length itself by searching the 2nd parameter for the first -** zero character. -** ^If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. If the 3rd parameter is non-negative, then it -** must be the byte offset into the string where the NUL terminator would -** appear if the string were NUL terminated. If any NUL characters occur -** in the string at a byte offset that is less than the value of the 3rd -** parameter, then the resulting string will contain embedded NULs and the -** result of expressions operating on strings with embedded NULs is undefined. -** ^If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or BLOB result when it has -** finished using that result. -** ^If the 4th parameter to the sqlite3_result_text* interfaces or to -** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite -** assumes that the text or BLOB result is in constant space and does not -** copy the content of the parameter nor call a destructor on the content -** when it has finished using that result. -** ^If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained -** from [sqlite3_malloc()] before it returns. -** -** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and -** sqlite3_result_text16be() routines, and for sqlite3_result_text64() -** when the encoding is not UTF8, if the input UTF16 begins with a -** byte-order mark (BOM, U+FEFF) then the BOM is removed from the -** string and the rest of the string is interpreted according to the -** byte-order specified by the BOM. ^The byte-order specified by -** the BOM at the beginning of the text overrides the byte-order -** specified by the interface procedure. ^So, for example, if -** sqlite3_result_text16le() is invoked with text that begins -** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the -** first two bytes of input are skipped and the remaining input -** is interpreted as UTF16BE text. -** -** ^For UTF16 input text to the sqlite3_result_text16(), -** sqlite3_result_text16be(), sqlite3_result_text16le(), and -** sqlite3_result_text64() routines, if the text contains invalid -** UTF16 characters, the invalid characters might be converted -** into the unicode replacement character, U+FFFD. -** -** ^The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy of the -** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that the [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** ^A [protected sqlite3_value] object may always be used where an -** [unprotected sqlite3_value] object is required, so either -** kind of [sqlite3_value] object can be used with this interface. -** -** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an -** SQL NULL value, just like [sqlite3_result_null(C)], except that it -** also associates the host-language pointer P or type T with that -** NULL value such that the pointer can be retrieved within an -** [application-defined SQL function] using [sqlite3_value_pointer()]. -** ^If the D parameter is not NULL, then it is a pointer to a destructor -** for the P parameter. ^SQLite invokes D with P as its only argument -** when SQLite is finished with P. The T parameter should be a static -** string and preferably a string literal. The sqlite3_result_pointer() -** routine is part of the [pointer passing interface] added for SQLite 3.20.0. -** -** If these routines are called from within a different thread -** than the one containing the application-defined function that received -** the [sqlite3_context] pointer, the results are undefined. -*/ -SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, - sqlite3_uint64,void(*)(void*)); -SQLITE_API void sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void sqlite3_result_null(sqlite3_context*); -SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, - void(*)(void*), unsigned char encoding); -SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*)); -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); - - -/* -** CAPI3REF: Setting The Subtype Of An SQL Function -** METHOD: sqlite3_context -** -** The sqlite3_result_subtype(C,T) function causes the subtype of -** the result from the [application-defined SQL function] with -** [sqlite3_context] C to be the value T. Only the lower 8 bits -** of the subtype T are preserved in current versions of SQLite; -** higher order bits are discarded. -** The number of subtype bytes preserved by SQLite might increase -** in future releases of SQLite. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_RESULT_SUBTYPE] property in its -** text encoding argument when the SQL function is -** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] -** property is omitted from the function that invokes sqlite3_result_subtype(), -** then in some cases the sqlite3_result_subtype() might fail to set -** the result subtype. -** -** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any -** SQL function that invokes the sqlite3_result_subtype() interface -** and that does not have the SQLITE_RESULT_SUBTYPE property will raise -** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 -** by default. -*/ -SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); - -/* -** CAPI3REF: Define New Collating Sequences -** METHOD: sqlite3 -** -** ^These functions add, remove, or modify a [collation] associated -** with the [database connection] specified as the first argument. -** -** ^The name of the collation is a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string in native byte order for sqlite3_create_collation16(). -** ^Collation names that compare equal according to [sqlite3_strnicmp()] are -** considered to be the same name. -** -** ^(The third argument (eTextRep) must be one of the constants: -**
    -**
  • [SQLITE_UTF8], -**
  • [SQLITE_UTF16LE], -**
  • [SQLITE_UTF16BE], -**
  • [SQLITE_UTF16], or -**
  • [SQLITE_UTF16_ALIGNED]. -**
)^ -** ^The eTextRep argument determines the encoding of strings passed -** to the collating function callback, xCompare. -** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep -** force strings to be UTF16 with native byte order. -** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin -** on an even byte address. -** -** ^The fourth argument, pArg, is an application data pointer that is passed -** through as the first argument to the collating function callback. -** -** ^The fifth argument, xCompare, is a pointer to the collating function. -** ^Multiple collating functions can be registered using the same name but -** with different eTextRep parameters and SQLite will use whichever -** function requires the least amount of data transformation. -** ^If the xCompare argument is NULL then the collating function is -** deleted. ^When all collating functions having the same name are deleted, -** that collation is no longer usable. -** -** ^The collating function callback is invoked with a copy of the pArg -** application data pointer and with two strings in the encoding specified -** by the eTextRep argument. The two integer parameters to the collating -** function callback are the length of the two strings, in bytes. The collating -** function must return an integer that is negative, zero, or positive -** if the first string is less than, equal to, or greater than the second, -** respectively. A collating function must always return the same answer -** given the same inputs. If two or more collating functions are registered -** to the same collation name (using different eTextRep values) then all -** must give an equivalent answer when invoked with equivalent strings. -** The collating function must obey the following properties for all -** strings A, B, and C: -** -**
    -**
  1. If A==B then B==A. -**
  2. If A==B and B==C then A==C. -**
  3. If A<B THEN B>A. -**
  4. If A<B and B<C then A<C. -**
-** -** If a collating function fails any of the above constraints and that -** collating function is registered and used, then the behavior of SQLite -** is undefined. -** -** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** with the addition that the xDestroy callback is invoked on pArg when -** the collating function is deleted. -** ^Collating functions are deleted when they are overridden by later -** calls to the collation creation functions or when the -** [database connection] is closed using [sqlite3_close()]. -** -** ^The xDestroy callback is not called if the -** sqlite3_create_collation_v2() function fails. Applications that invoke -** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should -** check the return code and dispose of the application data pointer -** themselves rather than expecting SQLite to deal with it for them. -** This is different from every other SQLite interface. The inconsistency -** is unfortunate but cannot be changed without breaking backwards -** compatibility. -** -** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. -*/ -SQLITE_API int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); -SQLITE_API int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -SQLITE_API int sqlite3_create_collation16( - sqlite3*, - const void *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks -** METHOD: sqlite3 -** -** ^To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** [database connection] to be invoked whenever an undefined collation -** sequence is required. -** -** ^If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, -** the names are passed as UTF-16 in machine native byte order. -** ^A call to either function replaces the existing collation-needed callback. -** -** ^(When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). The second argument is the database -** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE], indicating the most desirable form of the collation -** sequence function required. The fourth parameter is the name of the -** required collation sequence.)^ -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -SQLITE_API int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -SQLITE_API int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -SQLITE_API int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); -SQLITE_API int sqlite3_key_v2( - sqlite3 *db, /* Database to be rekeyed */ - const char *zDbName, /* Name of the database */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** 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 sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); -SQLITE_API int sqlite3_rekey_v2( - sqlite3 *db, /* Database to be rekeyed */ - const char *zDbName, /* Name of the database */ - const void *pKey, int nKey /* The new key */ -); - -/* -** Specify the activation key for a SEE database. Unless -** activated, none of the SEE routines will work. -*/ -SQLITE_API void sqlite3_activate_see( - const char *zPassPhrase /* Activation phrase */ -); -#endif -/* END SQLCIPHER */ - -#ifdef SQLITE_ENABLE_CEROD -/* -** Specify the activation key for a CEROD database. Unless -** activated, none of the CEROD routines will work. -*/ -SQLITE_API void sqlite3_activate_cerod( - const char *zPassPhrase /* Activation phrase */ -); -#endif - -/* -** CAPI3REF: Suspend Execution For A Short Time -** -** The sqlite3_sleep() function causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** ^SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. If the xSleep() method -** of the default VFS is not implemented correctly, or not implemented at -** all, then the behavior of sqlite3_sleep() may deviate from the description -** in the previous paragraphs. -** -** If a negative argument is passed to sqlite3_sleep() the results vary by -** VFS and operating system. Some system treat a negative argument as an -** instruction to sleep forever. Others understand it to mean do not sleep -** at all. ^In SQLite version 3.42.0 and later, a negative -** argument passed into sqlite3_sleep() is changed to zero before it is relayed -** down into the xSleep method of the VFS. -*/ -SQLITE_API int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files -** -** ^(If this global variable is made to point to a string which is -** the name of a folder (a.k.a. directory), then all temporary files -** created by SQLite when using a built-in [sqlite3_vfs | VFS] -** will be placed in that directory.)^ ^If this variable -** is a NULL pointer, then SQLite performs a search for an appropriate -** temporary file directory. -** -** Applications are strongly discouraged from using this global variable. -** It is required to set a temporary folder on Windows Runtime (WinRT). -** But for all other platforms, it is highly recommended that applications -** neither read nor write this variable. This global variable is a relic -** that exists for backwards compatibility of legacy applications and should -** be avoided in new projects. -** -** It is not safe to read or modify this variable in more than one -** thread at a time. It is not safe to read or modify this variable -** if a [database connection] is being used at the same time in a separate -** thread. -** It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been called and that this variable remain unchanged -** thereafter. -** -** ^The [temp_store_directory pragma] may modify this variable and cause -** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, -** the [temp_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from -** [sqlite3_malloc] and the pragma may attempt to free that memory -** using [sqlite3_free]. -** Hence, if this variable is modified directly, either it should be -** made NULL or made to point to memory obtained from [sqlite3_malloc] -** or else the use of the [temp_store_directory pragma] should be avoided. -** Except when requested by the [temp_store_directory pragma], SQLite -** does not free the memory that sqlite3_temp_directory points to. If -** the application wants that memory to be freed, it must do -** so itself, taking care to only do so after all [database connection] -** objects have been destroyed. -** -** Note to Windows Runtime users: The temporary directory must be set -** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various -** features that require the use of temporary files may fail. Here is an -** example of how to do this using C++ with the Windows Runtime: -** -**
-** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
-**       TemporaryFolder->Path->Data();
-** char zPathBuf[MAX_PATH + 1];
-** memset(zPathBuf, 0, sizeof(zPathBuf));
-** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
-**       NULL, NULL);
-** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
-** 
-*/ -SQLITE_API char *sqlite3_temp_directory; - -/* -** CAPI3REF: Name Of The Folder Holding Database Files -** -** ^(If this global variable is made to point to a string which is -** the name of a folder (a.k.a. directory), then all database files -** specified with a relative pathname and created or accessed by -** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed -** to be relative to that directory.)^ ^If this variable is a NULL -** pointer, then SQLite assumes that all database files specified -** with a relative pathname are relative to the current directory -** for the process. Only the windows VFS makes use of this global -** variable; it is ignored by the unix VFS. -** -** Changing the value of this variable while a database connection is -** open can result in a corrupt database. -** -** It is not safe to read or modify this variable in more than one -** thread at a time. It is not safe to read or modify this variable -** if a [database connection] is being used at the same time in a separate -** thread. -** It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been called and that this variable remain unchanged -** thereafter. -** -** ^The [data_store_directory pragma] may modify this variable and cause -** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, -** the [data_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from -** [sqlite3_malloc] and the pragma may attempt to free that memory -** using [sqlite3_free]. -** Hence, if this variable is modified directly, either it should be -** made NULL or made to point to memory obtained from [sqlite3_malloc] -** or else the use of the [data_store_directory pragma] should be avoided. -*/ -SQLITE_API char *sqlite3_data_directory; - -/* -** CAPI3REF: Win32 Specific Interface -** -** These interfaces are available only on Windows. The -** [sqlite3_win32_set_directory] interface is used to set the value associated -** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to -** zValue, depending on the value of the type parameter. The zValue parameter -** should be NULL to cause the previous value to be freed via [sqlite3_free]; -** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] -** prior to being used. The [sqlite3_win32_set_directory] interface returns -** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, -** or [SQLITE_NOMEM] if memory could not be allocated. The value of the -** [sqlite3_data_directory] variable is intended to act as a replacement for -** the current directory on the sub-platforms of Win32 where that concept is -** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and -** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the -** sqlite3_win32_set_directory interface except the string parameter must be -** UTF-8 or UTF-16, respectively. -*/ -SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ -); -SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); -SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); - -/* -** CAPI3REF: Win32 Directory Types -** -** These macros are only available on Windows. They define the allowed values -** for the type argument to the [sqlite3_win32_set_directory] interface. -*/ -#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 -#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 - -/* -** CAPI3REF: Test For Auto-Commit Mode -** KEYWORDS: {autocommit mode} -** METHOD: sqlite3 -** -** ^The sqlite3_get_autocommit() interface returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. ^Autocommit mode is on by default. -** ^Autocommit mode is disabled by a [BEGIN] statement. -** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. -** -** If certain kinds of errors occur on a statement within a multi-statement -** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. The only way to -** find out whether SQLite automatically rolled back the transaction after -** an error is to use this function. -** -** If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. -*/ -SQLITE_API int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement -** METHOD: sqlite3_stmt -** -** ^The sqlite3_db_handle interface returns the [database connection] handle -** to which a [prepared statement] belongs. ^The [database connection] -** returned by sqlite3_db_handle is the same [database connection] -** that was the first argument -** to the [sqlite3_prepare_v2()] call (or its variants) that was used to -** create the statement in the first place. -*/ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - -/* -** CAPI3REF: Return The Schema Name For A Database Connection -** METHOD: sqlite3 -** -** ^The 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 if 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 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 -** [sqlite3_serialize()] or [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 *sqlite3_db_name(sqlite3 *db, int N); - -/* -** CAPI3REF: Return The Filename For A Database Connection -** METHOD: sqlite3 -** -** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename -** associated with database N of connection D. -** ^If there is no attached database N on the database -** connection D, or if database N is a temporary or in-memory database, then -** this function will return either a NULL pointer or an empty string. -** -** ^The string value returned by this routine is owned and managed by -** the database connection. ^The value will be valid until the database N -** is [DETACH]-ed or until the database connection closes. -** -** ^The filename returned by this function is the output of the -** xFullPathname method of the [VFS]. ^In other words, the filename -** will be an absolute pathname, even if the filename used -** to open the database originally was a URI or relative pathname. -** -** If the filename pointer returned by this routine is not NULL, then it -** can be used as the filename input parameter to these routines: -**
    -**
  • [sqlite3_uri_parameter()] -**
  • [sqlite3_uri_boolean()] -**
  • [sqlite3_uri_int64()] -**
  • [sqlite3_filename_database()] -**
  • [sqlite3_filename_journal()] -**
  • [sqlite3_filename_wal()] -**
-*/ -SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName); - -/* -** CAPI3REF: Determine if a database is read-only -** METHOD: sqlite3 -** -** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N -** of connection D is read-only, 0 if it is read/write, or -1 if N is not -** the name of a database on connection D. -*/ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); - -/* -** CAPI3REF: Determine the transaction state of a database -** METHOD: sqlite3 -** -** ^The sqlite3_txn_state(D,S) interface returns the current -** [transaction state] of schema S in database connection D. ^If S is NULL, -** then the highest transaction state of any schema on database connection D -** is returned. Transaction states are (in order of lowest to highest): -**
    -**
  1. SQLITE_TXN_NONE -**
  2. SQLITE_TXN_READ -**
  3. SQLITE_TXN_WRITE -**
-** ^If the S argument to sqlite3_txn_state(D,S) is not the name of -** a valid schema, then -1 is returned. -*/ -SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); - -/* -** CAPI3REF: Allowed return values from sqlite3_txn_state() -** KEYWORDS: {transaction state} -** -** These constants define the current transaction state of a database file. -** ^The [sqlite3_txn_state(D,S)] interface returns one of these -** constants in order to describe the transaction state of schema S -** in [database connection] D. -** -**
-** [[SQLITE_TXN_NONE]]
SQLITE_TXN_NONE
-**
The SQLITE_TXN_NONE state means that no transaction is currently -** pending.
-** -** [[SQLITE_TXN_READ]]
SQLITE_TXN_READ
-**
The SQLITE_TXN_READ state means that the database is currently -** in a read transaction. Content has been read from the database file -** but nothing in the database file has changed. The transaction state -** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are -** no other conflicting concurrent write transactions. The transaction -** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or -** [COMMIT].
-** -** [[SQLITE_TXN_WRITE]]
SQLITE_TXN_WRITE
-**
The SQLITE_TXN_WRITE state means that the database is currently -** in a write transaction. Content has been written to the database file -** but has not yet committed. The transaction state will change to -** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
-*/ -#define SQLITE_TXN_NONE 0 -#define SQLITE_TXN_READ 1 -#define SQLITE_TXN_WRITE 2 - -/* -** CAPI3REF: Find the next prepared statement -** METHOD: sqlite3 -** -** ^This interface returns a pointer to the next [prepared statement] after -** pStmt associated with the [database connection] pDb. ^If pStmt is NULL -** then this interface returns a pointer to the first prepared statement -** associated with the database connection pDb. ^If no prepared statement -** satisfies the conditions of this routine, it returns NULL. -** -** The [database connection] pointer D in a call to -** [sqlite3_next_stmt(D,S)] must refer to an open database -** connection and in particular must not be a NULL pointer. -*/ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks -** METHOD: sqlite3 -** -** ^The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is [COMMIT | committed]. -** ^Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** ^The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. -** ^Any callback set by a previous call to sqlite3_rollback_hook() -** for the same database connection is overridden. -** ^The pArg argument is passed through to the callback. -** ^If the callback on a commit hook function returns non-zero, -** then the commit is converted into a rollback. -** -** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions -** return the P argument from the previous call of the same function -** on the same [database connection] D, or NULL for -** the first call for each function on D. -** -** The commit and rollback hook callbacks are not reentrant. -** The callback implementation must not do anything that will modify -** the database connection that invoked the callback. Any actions -** to modify the database connection must be deferred until after the -** completion of the [sqlite3_step()] call that triggered the commit -** or rollback hook in the first place. -** Note that running any other SQL statements, including SELECT statements, -** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify -** the database connections for the meaning of "modify" in this paragraph. -** -** ^Registering a NULL function disables the callback. -** -** ^When the commit hook callback routine returns zero, the [COMMIT] -** operation is allowed to continue normally. ^If the commit hook -** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. -** ^The rollback hook is invoked on a rollback that results from a commit -** hook returning non-zero, just as it would be with any other rollback. -** -** ^For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** ^The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** -** See also the [sqlite3_update_hook()] interface. -*/ -SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Autovacuum Compaction Amount Callback -** METHOD: sqlite3 -** -** ^The 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 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. -** -**

^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. -** -**

The callback is not reentrant. 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 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 sqlite3_autovacuum_pages(). -** -**

^There is only one autovacuum pages callback per database connection. -** ^Each call to the sqlite3_autovacuum_pages() interface overrides all -** previous invocations for that database connection. ^If the callback -** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is canceled. The return value -** from 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. -** -**

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: -** -**

-**     unsigned int demonstration_autovac_pages_callback(
-**       void *pClientData,
-**       const char *zSchema,
-**       unsigned int nDbPage,
-**       unsigned int nFreePage,
-**       unsigned int nBytePerPage
-**     ){
-**       return nFreePage;
-**     }
-** 
-*/ -SQLITE_API int sqlite3_autovacuum_pages( - sqlite3 *db, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, - void(*)(void*) -); - - -/* -** CAPI3REF: Data Change Notification Callbacks -** METHOD: sqlite3 -** -** ^The sqlite3_update_hook() interface registers a callback function -** with the [database connection] identified by the first argument -** to be invoked whenever a row is updated, inserted or deleted in -** a [rowid table]. -** ^Any callback set by a previous call to this function -** for the same database connection is overridden. -** -** ^The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted in a rowid table. -** ^The update hook is disabled by invoking sqlite3_update_hook() -** with a NULL pointer as the second parameter. -** ^The first argument to the callback is a copy of the third argument -** to sqlite3_update_hook(). -** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], -** or [SQLITE_UPDATE], depending on the operation that caused the callback -** to be invoked. -** ^The third and fourth arguments to the callback contain pointers to the -** database and table name containing the affected row. -** ^The final callback parameter is the [rowid] of the row. -** ^In the case of an update, this is the [rowid] after the update takes place. -** -** ^(The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_sequence).)^ -** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. -** -** ^In the current implementation, the update hook -** is not invoked when conflicting rows are deleted because of an -** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook -** invoked when rows are deleted using the [truncate optimization]. -** The exceptions defined in this paragraph might change in a future -** release of SQLite. -** -** Whether the update hook is invoked before or after the -** corresponding change is currently unspecified and may differ -** depending on the type of change. Do not rely on the order of the -** hook call with regards to the final result of the operation which -** triggers the hook. -** -** The update hook implementation must not do anything that will modify -** the database connection that invoked the update hook. Any actions -** to modify the database connection must be deferred until after the -** completion of the [sqlite3_step()] call that triggered the update hook. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -** ^The sqlite3_update_hook(D,C,P) function -** returns the P argument from the previous call -** on the same [database connection] D, or NULL for -** the first call on D. -** -** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], -** and [sqlite3_preupdate_hook()] interfaces. -*/ -SQLITE_API void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache -** -** ^(This routine enables or disables the sharing of the database cache -** and schema data structures between [database connection | connections] -** to the same database. Sharing is enabled if the argument is true -** and disabled if the argument is false.)^ -** -** This interface is omitted if SQLite is compiled with -** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE] -** compile-time option is recommended because the -** [use of shared cache mode is discouraged]. -** -** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). -** In prior versions of SQLite, -** sharing was enabled or disabled for each thread separately. -** -** ^(The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** Existing database connections continue to use the sharing mode -** that was in effect at the time they were opened.)^ -** -** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled -** successfully. An [error code] is returned otherwise.)^ -** -** ^Shared cache is disabled by default. It is recommended that it stay -** that way. In other words, do not use this routine. This interface -** continues to be provided for historical compatibility, but its use is -** discouraged. Any use of shared cache is discouraged. If shared cache -** must be used, it is recommended that shared cache only be enabled for -** individual database connections using the [sqlite3_open_v2()] interface -** with the [SQLITE_OPEN_SHAREDCACHE] flag. -** -** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 -** and will always return SQLITE_MISUSE. On those systems, -** shared cache mode should be enabled per-database connection via -** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. -** -** This interface is threadsafe on processors where writing a -** 32-bit integer is atomic. -** -** See Also: [SQLite Shared-Cache Mode] -*/ -SQLITE_API int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory -** -** ^The sqlite3_release_memory() interface attempts to free N bytes -** of heap memory by deallocating non-essential memory allocations -** held by the database library. Memory used to cache database -** pages to improve performance is an example of non-essential memory. -** ^sqlite3_release_memory() returns the number of bytes actually freed, -** which might be more or less than the amount requested. -** ^The sqlite3_release_memory() routine is a no-op returning zero -** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. -** -** See also: [sqlite3_db_release_memory()] -*/ -SQLITE_API int sqlite3_release_memory(int); - -/* -** CAPI3REF: Free Memory Used By A Database Connection -** METHOD: sqlite3 -** -** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap -** memory as possible from database connection D. Unlike the -** [sqlite3_release_memory()] interface, this interface is in effect even -** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is -** omitted. -** -** See also: [sqlite3_release_memory()] -*/ -SQLITE_API int sqlite3_db_release_memory(sqlite3*); - -/* -** CAPI3REF: Impose A Limit On Heap Size -** -** These interfaces impose limits on the amount of heap memory that will be -** used by all database connections within a single process. -** -** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the -** soft limit on the amount of heap memory that may be allocated by SQLite. -** ^SQLite strives to keep heap memory utilization below the soft heap -** limit by reducing the number of pages held in the page cache -** as heap memory usages approaches the limit. -** ^The soft heap limit is "soft" because even though SQLite strives to stay -** below the limit, it will exceed the limit rather than generate -** an [SQLITE_NOMEM] error. In other words, the soft heap limit -** is advisory only. -** -** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of -** N bytes on the amount of memory that will be allocated. ^The -** sqlite3_hard_heap_limit64(N) interface is similar to -** sqlite3_soft_heap_limit64(N) except that memory allocations will fail -** when the hard heap limit is reached. -** -** ^The return value from both sqlite3_soft_heap_limit64() and -** sqlite3_hard_heap_limit64() is the size of -** the heap limit prior to the call, or negative in the case of an -** error. ^If the argument N is negative -** then no change is made to the heap limit. Hence, the current -** size of heap limits can be determined by invoking -** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1). -** -** ^Setting the heap limits to zero disables the heap limiter mechanism. -** -** ^The soft heap limit may not be greater than the hard heap limit. -** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) -** is invoked with a value of N that is greater than the hard heap limit, -** the soft heap limit is set to the value of the hard heap limit. -** ^The soft heap limit is automatically enabled whenever the hard heap -** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and -** the soft heap limit is outside the range of 1..N, then the soft heap -** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the -** hard heap limit is enabled makes the soft heap limit equal to the -** hard heap limit. -** -** The memory allocation limits can also be adjusted using -** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit]. -** -** ^(The heap limits are not enforced in the current implementation -** if one or more of following conditions are true: -** -**
    -**
  • The limit value is set to zero. -**
  • Memory accounting is disabled using a combination of the -** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and -** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. -**
  • An alternative page cache implementation is specified using -** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). -**
  • The page cache allocates from its own memory pool supplied -** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than -** from the heap. -**
)^ -** -** The circumstances under which SQLite will enforce the heap limits may -** change in future releases of SQLite. -*/ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); -SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); - -/* -** CAPI3REF: Deprecated Soft Heap Limit Interface -** DEPRECATED -** -** This is a deprecated version of the [sqlite3_soft_heap_limit64()] -** interface. This routine is provided for historical compatibility -** only. All new applications should use the -** [sqlite3_soft_heap_limit64()] interface rather than this one. -*/ -SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); - - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table -** METHOD: sqlite3 -** -** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns -** information about column C of table T in database D -** on [database connection] X.)^ ^The sqlite3_table_column_metadata() -** interface returns SQLITE_OK and fills in the non-NULL pointers in -** the final five arguments with appropriate values if the specified -** column exists. ^The sqlite3_table_column_metadata() interface returns -** SQLITE_ERROR if the specified column does not exist. -** ^If the column-name parameter to sqlite3_table_column_metadata() is a -** NULL pointer, then this routine simply checks for the existence of the -** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it -** does not. If the table name parameter T in a call to -** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is -** undefined behavior. -** -** ^The column is identified by the second, third and fourth parameters to -** this function. ^(The second parameter is either the name of the database -** (i.e. "main", "temp", or an attached database) containing the specified -** table or NULL.)^ ^If it is NULL, then all attached databases are searched -** for the table using the same algorithm used by the database engine to -** resolve unqualified table references. -** -** ^The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. -** -** ^Metadata is returned by writing to the memory locations passed as the 5th -** and subsequent parameters to this function. ^Any of these arguments may be -** NULL, in which case the corresponding element of metadata is omitted. -** -** ^(
-** -**
Parameter Output
Type
Description -** -**
5th const char* Data type -**
6th const char* Name of default collation sequence -**
7th int True if column has a NOT NULL constraint -**
8th int True if column is part of the PRIMARY KEY -**
9th int True if column is [AUTOINCREMENT] -**
-**
)^ -** -** ^The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid until the next -** call to any SQLite API function. -** -** ^If the specified table is actually a view, an [error code] is returned. -** -** ^If the specified column is "rowid", "oid" or "_rowid_" and the table -** is not a [WITHOUT ROWID] table and an -** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. ^(If there is no -** [INTEGER PRIMARY KEY] column, then the outputs -** for the [rowid] are set as follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
)^ -** -** ^This function causes all database schemas to be read from disk and -** parsed, if that has not already been done, and returns an error if -** any errors are encountered while loading the schema. -*/ -SQLITE_API int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension -** METHOD: sqlite3 -** -** ^This interface loads an SQLite extension library from the named file. -** -** ^The sqlite3_load_extension() interface attempts to load an -** [SQLite extension] library contained in the file zFile. If -** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific extensions added. -** So for example, if "samplelib" cannot be loaded, then names like -** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might -** be tried also. -** -** ^The entry point is zProc. -** ^(zProc may be 0, in which case SQLite will try to come up with an -** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it constructs a name "sqlite3_X_init" where -** X consists of the lower-case equivalent of all ASCII alphabetic -** characters in the filename from the last "/" to the first following -** "." and omitting any initial "lib".)^ -** ^The sqlite3_load_extension() interface returns -** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** ^If an error occurs and pzErrMsg is not 0, then the -** [sqlite3_load_extension()] interface shall attempt to -** fill *pzErrMsg with error message text stored in memory -** obtained from [sqlite3_malloc()]. The calling function -** should free this memory by calling [sqlite3_free()]. -** -** ^Extension loading must be enabled using -** [sqlite3_enable_load_extension()] or -** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) -** prior to calling this API, -** otherwise an error will be returned. -** -** Security warning: It is recommended that the -** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this -** interface. The use of the [sqlite3_enable_load_extension()] interface -** should be avoided. This will keep the SQL function [load_extension()] -** disabled and prevent SQL injections from giving attackers -** access to extension loading capabilities. -** -** See also the [load_extension() SQL function]. -*/ -SQLITE_API int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading -** METHOD: sqlite3 -** -** ^So as not to open security holes in older applications that are -** unprepared to deal with [extension loading], and as a means of disabling -** [extension loading] while evaluating user-entered SQL, the following API -** is provided to turn the [sqlite3_load_extension()] mechanism on and off. -** -** ^Extension loading is off by default. -** ^Call the sqlite3_enable_load_extension() routine with onoff==1 -** to turn extension loading on and call it with onoff==0 to turn -** it back off again. -** -** ^This interface enables or disables both the C-API -** [sqlite3_load_extension()] and the SQL function [load_extension()]. -** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) -** to enable or disable only the C-API.)^ -** -** Security warning: It is recommended that extension loading -** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method -** rather than this interface, so the [load_extension()] SQL function -** remains disabled. This will prevent SQL injections from giving attackers -** access to extension loading capabilities. -*/ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Automatically Load Statically Linked Extensions -** -** ^This interface causes the xEntryPoint() function to be invoked for -** each new [database connection] that is created. The idea here is that -** xEntryPoint() is the entry point for a statically linked [SQLite extension] -** that is to be automatically loaded into all new database connections. -** -** ^(Even though the function prototype shows that xEntryPoint() takes -** no arguments and returns void, SQLite invokes xEntryPoint() with three -** arguments and expects an integer result as if the signature of the -** entry point were as follows: -** -**
-**    int xEntryPoint(
-**      sqlite3 *db,
-**      const char **pzErrMsg,
-**      const struct sqlite3_api_routines *pThunk
-**    );
-** 
)^ -** -** If the xEntryPoint routine encounters an error, it should make *pzErrMsg -** point to an appropriate error message (obtained from [sqlite3_mprintf()]) -** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg -** is NULL before calling the xEntryPoint(). ^SQLite will invoke -** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any -** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], -** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. -** -** ^Calling sqlite3_auto_extension(X) with an entry point X that is already -** on the list of automatic extensions is a harmless no-op. ^No entry point -** will be called more than once for each database connection that is opened. -** -** See also: [sqlite3_reset_auto_extension()] -** and [sqlite3_cancel_auto_extension()] -*/ -SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void)); - -/* -** CAPI3REF: Cancel Automatic Extension Loading -** -** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the -** initialization routine X that was registered using a prior call to -** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] -** routine returns 1 if initialization routine X was successfully -** unregistered and it returns 0 if X was not on the list of initialization -** routines. -*/ -SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); - -/* -** CAPI3REF: Reset Automatic Extension Loading -** -** ^This interface disables all automatic extensions previously -** registered using [sqlite3_auto_extension()]. -*/ -SQLITE_API void sqlite3_reset_auto_extension(void); - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** CAPI3REF: Virtual Table Object -** KEYWORDS: sqlite3_module {virtual table module} -** -** This structure, sometimes called a "virtual table module", -** defines the implementation of a [virtual table]. -** This structure consists mostly of methods for the module. -** -** ^A virtual table module is created by filling in a persistent -** instance of this structure and passing a pointer to that instance -** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. -** ^The registration remains valid until it is replaced by a different -** module or until the [database connection] closes. The content -** of this structure must not change while it is registered with -** any database connection. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those - ** below are for version 2 and greater. */ - int (*xSavepoint)(sqlite3_vtab *pVTab, int); - int (*xRelease)(sqlite3_vtab *pVTab, int); - int (*xRollbackTo)(sqlite3_vtab *pVTab, int); - /* The methods above are in versions 1 and 2 of the sqlite_module object. - ** Those below are for version 3 and greater. */ - int (*xShadowName)(const char*); - /* The methods above are in versions 1 through 3 of the sqlite_module object. - ** Those below are for version 4 and greater. */ - int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, - const char *zTabName, int mFlags, char **pzErr); -}; - -/* -** CAPI3REF: Virtual Table Indexing Information -** KEYWORDS: sqlite3_index_info -** -** The sqlite3_index_info structure and its substructures is used as part -** of the [virtual table] interface to -** pass information into and receive the reply from the [xBestIndex] -** method of a [virtual table module]. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** ^(The aConstraint[] array records WHERE clause constraints of the form: -** -**
column OP expr
-** -** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is -** stored in aConstraint[].op using one of the -** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ -** ^(The index of the column is stored in -** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot.)^ -** -** ^The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** ^The aConstraint[] array only reports WHERE clause terms that are -** relevant to the particular virtual table being queried. -** -** ^Information about the ORDER BY clause is stored in aOrderBy[]. -** ^Each term of aOrderBy records a column of the ORDER BY clause. -** -** The colUsed field indicates which columns of the virtual table may be -** required by the current scan. Virtual table columns are numbered from -** zero in the order in which they appear within the CREATE TABLE statement -** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), -** the corresponding bit is set within the colUsed mask if the column may be -** required by SQLite. If the table has at least 64 columns and any column -** to the right of the first 63 is required, then bit 63 of colUsed is also -** set. In other words, column iCol may be required if the expression -** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to -** non-zero. -** -** The [xBestIndex] method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. ^If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and might not be checked again by the byte code.)^ ^(The -** aConstraintUsage[].omit flag is an optimization hint. When the omit flag -** is left in its default setting of false, the constraint will always be -** checked separately in byte code. If the omit flag is changed to true, then -** the constraint may or may not be checked in byte code. In other words, -** when the omit flag is true there is no guarantee that the constraint will -** not be checked again using byte code.)^ -** -** ^The idxNum and idxStr values are recorded and passed into the -** [xFilter] method. -** ^[sqlite3_free()] is used to free idxStr if and only if -** needToFreeIdxStr is true. -** -** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** ^The estimatedCost value is an estimate of the cost of a particular -** strategy. A cost of N indicates that the cost of the strategy is similar -** to a linear scan of an SQLite table with N rows. A cost of log(N) -** indicates that the expense of the operation is similar to that of a -** binary search on a unique indexed field of an SQLite table with N rows. -** -** ^The estimatedRows value is an estimate of the number of rows that -** will be returned by the strategy. -** -** The xBestIndex method may optionally populate the idxFlags field with a -** mask of SQLITE_INDEX_SCAN_* flags. One such flag is -** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN] -** output to show the idxNum as hex instead of as decimal. Another flag is -** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will -** return at most one row. -** -** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then -** SQLite also assumes that if a call to the xUpdate() method is made as -** part of the same statement to delete or update a virtual table row and the -** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback -** any database changes. In other words, if the xUpdate() returns -** SQLITE_CONSTRAINT, the database contents must be exactly as they were -** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not -** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by -** the xUpdate method are automatically rolled back by SQLite. -** -** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). -** If a virtual table extension is -** used with an SQLite version earlier than 3.8.2, the results of attempting -** to read or write the estimatedRows field are undefined (but are likely -** to include crashing the application). The estimatedRows field should -** therefore only be used if [sqlite3_libversion_number()] returns a -** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for [version 3.9.0] ([dateof:3.9.0]). -** It may therefore only be used if -** sqlite3_libversion_number() returns a value greater than or equal to -** 3009000. -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column constrained. -1 for ROWID */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ - /* Fields below are only available in SQLite 3.8.2 and later */ - sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ - /* Fields below are only available in SQLite 3.9.0 and later */ - int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ - /* Fields below are only available in SQLite 3.10.0 and later */ - sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ -}; - -/* -** CAPI3REF: Virtual Table Scan Flags -** -** Virtual table implementations are allowed to set the -** [sqlite3_index_info].idxFlags field to some combination of -** these bits. -*/ -#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */ -#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */ - /* in EXPLAIN QUERY PLAN */ - -/* -** CAPI3REF: Virtual Table Constraint Operator Codes -** -** These macros define the allowed values for the -** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the WHERE clause of -** a query that uses a [virtual table]. -** -** ^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 [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 -** 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 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 [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 sqlite3_vtab_collation() -** interface is not 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 -** METHOD: sqlite3 -** -** ^These routines are used to register a new [virtual table module] name. -** ^Module names must be registered before -** creating a new [virtual table] using the module and before using a -** preexisting [virtual table] for the module. -** -** ^The module name is registered on the [database connection] specified -** by the first parameter. ^The name of the module is given by the -** second parameter. ^The third parameter is a pointer to -** the implementation of the [virtual table module]. ^The fourth -** parameter is an arbitrary client data pointer that is passed through -** into the [xCreate] and [xConnect] methods of the virtual table module -** when a new virtual table is being created or reinitialized. -** -** ^The sqlite3_create_module_v2() interface has a fifth parameter which -** is a pointer to a destructor for the pClientData. ^SQLite will -** invoke the destructor function (if it is not NULL) when SQLite -** no longer needs the pClientData pointer. ^The destructor will also -** be invoked if the call to sqlite3_create_module_v2() fails. -** ^The sqlite3_create_module() -** interface is equivalent to sqlite3_create_module_v2() with a NULL -** destructor. -** -** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is created and any existing modules with the -** same name are dropped. -** -** See also: [sqlite3_drop_modules()] -*/ -SQLITE_API int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData /* Client data for xCreate/xConnect */ -); -SQLITE_API int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** CAPI3REF: Remove Unnecessary Virtual Table Implementations -** METHOD: sqlite3 -** -** ^The sqlite3_drop_modules(D,L) interface removes all virtual -** table modules from database connection D except those named on list L. -** The L parameter must be either NULL or a pointer to an array of pointers -** to strings where the array is terminated by a single NULL pointer. -** ^If the L parameter is NULL, then all virtual table modules are removed. -** -** See also: [sqlite3_create_module()] -*/ -SQLITE_API int sqlite3_drop_modules( - sqlite3 *db, /* Remove modules from this connection */ - const char **azKeep /* Except, do not remove the ones named here */ -); - -/* -** CAPI3REF: Virtual Table Instance Object -** KEYWORDS: sqlite3_vtab -** -** Every [virtual table module] implementation uses a subclass -** of this object to describe a particular instance -** of the [virtual table]. Each subclass will -** be tailored to the specific needs of the module implementation. -** The purpose of this superclass is to define certain fields that are -** common to all module implementations. -** -** ^Virtual tables methods can set an error message by assigning a -** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should -** take care that any prior string is freed by a call to [sqlite3_free()] -** prior to assigning a new string to zErrMsg. ^After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Number of open cursors */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** CAPI3REF: Virtual Table Cursor Object -** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} -** -** Every [virtual table module] implementation uses a subclass of the -** following structure to describe cursors that point into the -** [virtual table] and are used -** to loop through the virtual table. Cursors are created using the -** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed -** by the [sqlite3_module.xClose | xClose] method. Cursors are used -** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods -** of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** CAPI3REF: Declare The Schema Of A Virtual Table -** -** ^The [xCreate] and [xConnect] methods of a -** [virtual table module] call this interface -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); - -/* -** CAPI3REF: Overload A Function For A Virtual Table -** METHOD: sqlite3 -** -** ^(Virtual tables can provide alternative implementations of functions -** using the [xFindFunction] method of the [virtual table module]. -** But global versions of those functions -** must exist in order to be overloaded.)^ -** -** ^(This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created.)^ ^The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a placeholder function that can be overloaded -** by a [virtual table]. -*/ -SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** CAPI3REF: A Handle To An Open BLOB -** KEYWORDS: {BLOB handle} {BLOB handles} -** -** An instance of this object represents an open BLOB on which -** [sqlite3_blob_open | incremental BLOB I/O] can be performed. -** ^Objects of this type are created by [sqlite3_blob_open()] -** and destroyed by [sqlite3_blob_close()]. -** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the BLOB. -** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O -** METHOD: sqlite3 -** CONSTRUCTOR: sqlite3_blob -** -** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located -** in row iRow, column zColumn, table zTable in database zDb; -** in other words, the same BLOB that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
-** 
)^ -** -** ^(Parameter zDb is not the filename that contains the database, but -** rather the symbolic name of the database. For attached databases, this is -** the name that appears after the AS keyword in the [ATTACH] statement. -** For the main database file, the database name is "main". For TEMP -** tables, the database name is "temp".)^ -** -** ^If the flags parameter is non-zero, then the BLOB is opened for read -** and write access. ^If the flags parameter is zero, the BLOB is opened for -** read-only access. -** -** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored -** in *ppBlob. Otherwise an [error code] is returned and, unless the error -** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided -** the API is not misused, it is always safe to call [sqlite3_blob_close()] -** on *ppBlob after this function returns. -** -** This function fails with SQLITE_ERROR if any of the following are true: -**
    -**
  • ^(Database zDb does not exist)^, -**
  • ^(Table zTable does not exist within database zDb)^, -**
  • ^(Table zTable is a WITHOUT ROWID table)^, -**
  • ^(Column zColumn does not exist)^, -**
  • ^(Row iRow is not present in the table)^, -**
  • ^(The specified column of row iRow contains a value that is not -** a TEXT or BLOB value)^, -**
  • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE -** constraint and the blob is being opened for read/write access)^, -**
  • ^([foreign key constraints | Foreign key constraints] are enabled, -** column zColumn is part of a [child key] definition and the blob is -** being opened for read/write access)^. -**
-** -** ^Unless it returns SQLITE_MISUSE, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. -** -** A BLOB referenced by sqlite3_blob_open() may be read using the -** [sqlite3_blob_read()] interface and modified by using -** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a -** different row of the same table using the [sqlite3_blob_reopen()] -** interface. However, the column, table, or database of a [BLOB handle] -** cannot be changed after the [BLOB handle] is opened. -** -** ^(If the row that a BLOB handle points to is modified by an -** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects -** then the BLOB handle is marked as "expired". -** This is true if any column of the row is changed, even a column -** other than the one the BLOB handle is open on.)^ -** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for -** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. -** ^(Changes written into a BLOB prior to the BLOB expiring are not -** rolled back by the expiration of the BLOB. Such changes will eventually -** commit if the transaction continues to completion.)^ -** -** ^Use the [sqlite3_blob_bytes()] interface to determine the size of -** the opened blob. ^The size of a blob may not be changed by this -** interface. Use the [UPDATE] SQL command to change the size of a -** blob. -** -** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces -** and the built-in [zeroblob] SQL function may be used to create a -** zero-filled blob to read or write using the incremental-blob interface. -** -** To avoid a resource leak, every open [BLOB handle] should eventually -** be released by a call to [sqlite3_blob_close()]. -** -** See also: [sqlite3_blob_close()], -** [sqlite3_blob_reopen()], [sqlite3_blob_read()], -** [sqlite3_blob_bytes()], [sqlite3_blob_write()]. -*/ -SQLITE_API int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Move a BLOB Handle to a New Row -** METHOD: sqlite3_blob -** -** ^This function is used to move an existing [BLOB handle] so that it points -** to a different row of the same database table. ^The new row is identified -** by the rowid value passed as the second argument. Only the row can be -** changed. ^The database, table and column on which the blob handle is open -** remain the same. Moving an existing [BLOB handle] to a new row is -** faster than closing the existing handle and opening a new one. -** -** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - -** it must exist and there must be either a blob or text value stored in -** the nominated column.)^ ^If the new row is not present in the table, or if -** it does not contain a blob or text value, or if another error occurs, an -** SQLite error code is returned and the blob handle is considered aborted. -** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or -** [sqlite3_blob_reopen()] on an aborted blob handle immediately return -** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle -** always returns zero. -** -** ^This function sets the database handle error code and message. -*/ -SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); - -/* -** CAPI3REF: Close A BLOB Handle -** DESTRUCTOR: sqlite3_blob -** -** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed -** unconditionally. Even if this routine returns an error code, the -** handle is still closed.)^ -** -** ^If the blob handle being closed was opened for read-write access, and if -** the database is in auto-commit mode and there are no other open read-write -** blob handles or active write statements, the current transaction is -** committed. ^If an error occurs while committing the transaction, an error -** code is returned and the transaction rolled back. -** -** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behavior. ^Calling this routine -** with a null pointer (such as would be returned by a failed call to -** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function -** is passed a valid open blob handle, the values returned by the -** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. -*/ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB -** METHOD: sqlite3_blob -** -** ^Returns the size in bytes of the BLOB accessible via the -** successfully opened [BLOB handle] in its only argument. ^The -** incremental blob I/O routines can only read or overwrite existing -** blob content; they cannot change the size of a blob. -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -*/ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally -** METHOD: sqlite3_blob -** -** ^(This function is used to read data from an open [BLOB handle] into a -** caller-supplied buffer. N bytes of data are copied into buffer Z -** from the open BLOB, starting at offset iOffset.)^ -** -** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is -** less than zero, [SQLITE_ERROR] is returned and no data is read. -** ^The size of the blob (and hence the maximum value of N+iOffset) -** can be determined using the [sqlite3_blob_bytes()] interface. -** -** ^An attempt to read from an expired [BLOB handle] fails with an -** error code of [SQLITE_ABORT]. -** -** ^(On success, sqlite3_blob_read() returns SQLITE_OK. -** Otherwise, an [error code] or an [extended error code] is returned.)^ -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -** -** See also: [sqlite3_blob_write()]. -*/ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally -** METHOD: sqlite3_blob -** -** ^(This function is used to write data into an open [BLOB handle] from a -** caller-supplied buffer. N bytes of data are copied from the buffer Z -** into the open BLOB, starting at offset iOffset.)^ -** -** ^(On success, sqlite3_blob_write() returns SQLITE_OK. -** Otherwise, an [error code] or an [extended error code] is returned.)^ -** ^Unless SQLITE_MISUSE is returned, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. -** -** ^If the [BLOB handle] passed as the first argument was not opened for -** writing (the flags parameter to [sqlite3_blob_open()] was zero), -** this function returns [SQLITE_READONLY]. -** -** This function may only modify the contents of the BLOB; it is -** not possible to increase the size of a BLOB using this API. -** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is written. The size of the -** BLOB (and hence the maximum value of N+iOffset) can be determined -** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less -** than zero [SQLITE_ERROR] is returned and no data is written. -** -** ^An attempt to write to an expired [BLOB handle] fails with an -** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred -** before the [BLOB handle] expired are not rolled back by the -** expiration of the handle, though of course those changes might -** have been overwritten by the statement that expired the BLOB handle -** or by other independent statements. -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -** -** See also: [sqlite3_blob_read()]. -*/ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most SQLite builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. -** ^Names are case sensitive. -** ^Names are zero-terminated UTF-8 strings. -** ^If there is no match, a NULL pointer is returned. -** ^If zVfsName is NULL then the default VFS is returned. -** -** ^New VFSes are registered with sqlite3_vfs_register(). -** ^Each new VFS becomes the default VFS if the makeDflt flag is set. -** ^The same VFS can be registered multiple times without injury. -** ^To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. If two different VFSes with the -** same name are registered, the behavior is undefined. If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. -** ^(If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary.)^ -*/ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_PTHREADS -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_PTHREADS and -** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix -** and Windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. In this case the -** application must supply a custom mutex implementation using the -** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function -** before calling sqlite3_initialize() or any other public sqlite3_ -** function that calls sqlite3_initialize(). -** -** ^The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc() -** routine returns NULL if it is unable to allocate the requested -** mutex. The argument to sqlite3_mutex_alloc() must be one of these -** integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MAIN -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 -**
-** -** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) -** cause sqlite3_mutex_alloc() to create -** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. SQLite will only request a recursive mutex in -** cases where it really needs one. If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other -** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return -** a pointer to a static preexisting mutex. ^Nine static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. ^For the static -** mutex types, the same mutex is returned on every call that has -** the same type number. -** -** ^The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. Attempting to deallocate a static -** mutex results in undefined behavior. -** -** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. ^If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] -** upon successful entry. ^(Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** In such cases, the -** mutex must be exited an equal number of times before another thread -** can enter.)^ If the same thread tries to enter any mutex other -** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. -** -** ^(Some systems (for example, Windows 95) do not support the operation -** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() -** will always return SQLITE_BUSY. In most cases the SQLite core only uses -** sqlite3_mutex_try() as an optimization, so this is acceptable -** behavior. The exceptions are unix builds that set the -** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working -** sqlite3_mutex_try() is required.)^ -** -** ^The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. -** -** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), -** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer, -** then any of the four routines behaves as a no-op. -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Methods Object -** -** An instance of this structure defines the low-level routines -** used to allocate and use mutexes. -** -** Usually, the default mutex implementations provided by SQLite are -** sufficient, however the application has the option of substituting a custom -** implementation for specialized deployments or systems for which SQLite -** does not provide a suitable implementation. In this case, the application -** creates and populates an instance of this structure to pass -** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. -** Additionally, an instance of this structure can be used as an -** output variable when querying the system for the current mutex -** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. -** -** ^The xMutexInit method defined by this structure is invoked as -** part of system initialization by the sqlite3_initialize() function. -** ^The xMutexInit routine is called by SQLite exactly once for each -** effective call to [sqlite3_initialize()]. -** -** ^The xMutexEnd method defined by this structure is invoked as -** part of system shutdown by the sqlite3_shutdown() function. The -** implementation of this method is expected to release all outstanding -** resources obtained by the mutex methods implementation, especially -** those obtained by the xMutexInit method. ^The xMutexEnd() -** interface is invoked exactly once for each call to [sqlite3_shutdown()]. -** -** ^(The remaining seven methods defined by this structure (xMutexAlloc, -** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and -** xMutexNotheld) implement the following interfaces (respectively): -** -**
    -**
  • [sqlite3_mutex_alloc()]
  • -**
  • [sqlite3_mutex_free()]
  • -**
  • [sqlite3_mutex_enter()]
  • -**
  • [sqlite3_mutex_try()]
  • -**
  • [sqlite3_mutex_leave()]
  • -**
  • [sqlite3_mutex_held()]
  • -**
  • [sqlite3_mutex_notheld()]
  • -**
)^ -** -** The only difference is that the public sqlite3_XXX functions enumerated -** above silently ignore any invocations that pass a NULL pointer instead -** of a valid mutex handle. The implementations of the methods defined -** by this structure are not required to handle this case. The results -** of passing a NULL pointer instead of a valid mutex handle are undefined -** (i.e. it is acceptable to provide an implementation that segfaults if -** it is passed a NULL pointer). -** -** The xMutexInit() method must be threadsafe. It must be harmless to -** invoke xMutexInit() multiple times within the same process and without -** intervening calls to xMutexEnd(). Second and subsequent calls to -** xMutexInit() must be no-ops. -** -** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] -** and its associates). Similarly, xMutexAlloc() must not use SQLite memory -** allocation for a static mutex. ^However xMutexAlloc() may use SQLite -** memory allocation for a fast or recursive mutex. -** -** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is -** called, but only if the prior call to xMutexInit returned SQLITE_OK. -** If xMutexInit fails in any way, it is expected to clean up after itself -** prior to returning. -*/ -typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; -struct sqlite3_mutex_methods { - int (*xMutexInit)(void); - int (*xMutexEnd)(void); - sqlite3_mutex *(*xMutexAlloc)(int); - void (*xMutexFree)(sqlite3_mutex *); - void (*xMutexEnter)(sqlite3_mutex *); - int (*xMutexTry)(sqlite3_mutex *); - void (*xMutexLeave)(sqlite3_mutex *); - int (*xMutexHeld)(sqlite3_mutex *); - int (*xMutexNotheld)(sqlite3_mutex *); -}; - -/* -** CAPI3REF: Mutex Verification Routines -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. The SQLite core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. -** -** The implementation is not required to provide versions of these -** routines that actually work. If the implementation does not provide working -** versions of these routines, it should at least provide stubs that always -** return true so that one does not get spurious assertion failures. -** -** If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -#ifndef NDEBUG -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); -#endif - -/* -** CAPI3REF: Mutex Types -** -** The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. -** -** The set of static mutexes may change from one SQLite release to the -** next. Applications that override the built-in mutex logic must be -** prepared to accommodate additional static mutexes. -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MAIN 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ -#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ -#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */ -#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ -#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ -#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ -#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ -#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ - -/* Legacy compatibility: */ -#define SQLITE_MUTEX_STATIC_MASTER 2 - - -/* -** CAPI3REF: Retrieve the mutex for a database connection -** METHOD: sqlite3 -** -** ^This interface returns a pointer to the [sqlite3_mutex] object that -** serializes access to the [database connection] given in the argument -** when the [threading mode] is Serialized. -** ^If the [threading mode] is Single-thread or Multi-thread then this -** routine returns a NULL pointer. -*/ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); - -/* -** CAPI3REF: Low-Level Control Of Database Files -** METHOD: sqlite3 -** KEYWORDS: {file control} -** -** ^The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. ^The -** name of the database is "main" for the main database or "temp" for the -** TEMP database, or the name that appears after the AS keyword for -** databases that are added using the [ATTACH] SQL command. -** ^A NULL pointer can be used in place of "main" to refer to the -** main database file. -** ^The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. ^The return value of the xFileControl -** method becomes the return value of this routine. -** -** A few opcodes for [sqlite3_file_control()] are handled directly -** by the SQLite core and never invoke the -** sqlite3_io_methods.xFileControl method. -** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes -** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. The -** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns -** the [sqlite3_file] object associated with the journal file instead of -** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns -** a pointer to the underlying [sqlite3_vfs] object for the file. -** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter -** from the pager. -** -** ^If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. ^This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. The underlying xFileControl method might -** also return SQLITE_ERROR. There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. -** -** See also: [file control opcodes] -*/ -SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** CAPI3REF: Testing Interface -** -** ^The sqlite3_test_control() interface is used to read out internal -** state of SQLite and to inject faults into SQLite for testing -** purposes. ^The first parameter is an operation code that determines -** the number, meaning, and operation of all subsequent parameters. -** -** This interface is not for use by applications. It exists solely -** for verifying the correct operation of the SQLite library. Depending -** on how the SQLite library is compiled, this interface might not exist. -** -** The details of the operation codes, their meanings, the parameters -** they take, and what they do are all subject to change without notice. -** Unlike most of the SQLite API, this function is not guaranteed to -** operate consistently from one release to the next. -*/ -SQLITE_API int sqlite3_test_control(int op, ...); - -/* -** CAPI3REF: Testing Interface Operation Codes -** -** These constants are the valid operation code parameters used -** as the first argument to [sqlite3_test_control()]. -** -** These parameters and their meanings are subject to change -** without notice. These values are for testing purposes only. -** Applications should not use any of these parameters or the -** [sqlite3_test_control()] interface. -*/ -#define SQLITE_TESTCTRL_FIRST 5 -#define SQLITE_TESTCTRL_PRNG_SAVE 5 -#define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ -#define SQLITE_TESTCTRL_FK_NO_ACTION 7 -#define SQLITE_TESTCTRL_BITVEC_TEST 8 -#define SQLITE_TESTCTRL_FAULT_INSTALL 9 -#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 -#define SQLITE_TESTCTRL_PENDING_BYTE 11 -#define SQLITE_TESTCTRL_ASSERT 12 -#define SQLITE_TESTCTRL_ALWAYS 13 -#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ -#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 -#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ -#define SQLITE_TESTCTRL_GETOPT 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ -#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 -#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 -#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ -#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 -#define SQLITE_TESTCTRL_NEVER_CORRUPT 20 -#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 -#define SQLITE_TESTCTRL_BYTEORDER 22 -#define SQLITE_TESTCTRL_ISINIT 23 -#define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 -#define SQLITE_TESTCTRL_RESULT_INTREAL 27 -#define SQLITE_TESTCTRL_PRNG_SEED 28 -#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 -#define SQLITE_TESTCTRL_SEEK_COUNT 30 -#define SQLITE_TESTCTRL_TRACEFLAGS 31 -#define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ -#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ - -/* -** CAPI3REF: SQL Keyword Checking -** -** These routines provide access to the set of SQL language keywords -** recognized by SQLite. Applications can use these routines to determine -** whether or not a specific identifier needs to be escaped (for example, -** by enclosing in double-quotes) so as not to confuse the parser. -** -** The sqlite3_keyword_count() interface returns the number of distinct -** keywords understood by SQLite. -** -** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and -** makes *Z point to that keyword expressed as UTF8 and writes the number -** of bytes in the keyword into *L. The string that *Z points to is not -** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns -** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z -** or L are NULL or invalid pointers then calls to -** sqlite3_keyword_name(N,Z,L) result in undefined behavior. -** -** The sqlite3_keyword_check(Z,L) interface checks to see whether or not -** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero -** if it is and zero if not. -** -** The parser used by SQLite is forgiving. It is often possible to use -** a keyword as an identifier as long as such use does not result in a -** parsing ambiguity. For example, the statement -** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and -** creates a new table named "BEGIN" with three columns named -** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid -** using keywords as identifiers. Common techniques used to avoid keyword -** name collisions include: -**
    -**
  • Put all identifier names inside double-quotes. This is the official -** SQL way to escape identifier names. -**
  • Put identifier names inside [...]. This is not standard SQL, -** but it is what SQL Server does and so lots of programmers use this -** technique. -**
  • Begin every identifier with the letter "Z" as no SQL keywords start -** with "Z". -**
  • Include a digit somewhere in every identifier name. -**
-** -** Note that the number of keywords understood by SQLite can depend on -** compile-time options. For example, "VACUUM" is not a keyword if -** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, -** new keywords may be added to future releases of SQLite. -*/ -SQLITE_API int sqlite3_keyword_count(void); -SQLITE_API int sqlite3_keyword_name(int,const char**,int*); -SQLITE_API int sqlite3_keyword_check(const char*,int); - -/* -** CAPI3REF: Dynamic String Object -** KEYWORDS: {dynamic string} -** -** An instance of the sqlite3_str object contains a dynamically-sized -** string under construction. -** -** The lifecycle of an sqlite3_str object is as follows: -**
    -**
  1. ^The sqlite3_str object is created using [sqlite3_str_new()]. -**
  2. ^Text is appended to the sqlite3_str object using various -** methods, such as [sqlite3_str_appendf()]. -**
  3. ^The sqlite3_str object is destroyed and the string it created -** is returned using the [sqlite3_str_finish()] interface. -**
-*/ -typedef struct sqlite3_str sqlite3_str; - -/* -** CAPI3REF: Create A New Dynamic String Object -** CONSTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_new(D)] interface allocates and initializes -** a new [sqlite3_str] object. To avoid memory leaks, the object returned by -** [sqlite3_str_new()] must be freed by a subsequent call to -** [sqlite3_str_finish(X)]. -** -** ^The [sqlite3_str_new(D)] interface always returns a pointer to a -** valid [sqlite3_str] object, though in the event of an out-of-memory -** error the returned object might be a special singleton that will -** silently reject new text, always return SQLITE_NOMEM from -** [sqlite3_str_errcode()], always return 0 for -** [sqlite3_str_length()], and always return NULL from -** [sqlite3_str_finish(X)]. It is always safe to use the value -** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter -** to any of the other [sqlite3_str] methods. -** -** The D parameter to [sqlite3_str_new(D)] may be NULL. If the -** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum -** length of the string contained in the [sqlite3_str] object will be -** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead -** of [SQLITE_MAX_LENGTH]. -*/ -SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); - -/* -** CAPI3REF: Finalize A Dynamic String -** DESTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X -** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] -** that contains the constructed string. The calling application should -** pass the returned value to [sqlite3_free()] to avoid a memory leak. -** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any -** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the -** string in [sqlite3_str] object X is zero bytes long. -*/ -SQLITE_API char *sqlite3_str_finish(sqlite3_str*); - -/* -** CAPI3REF: Add Content To A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces add content to an sqlite3_str object previously obtained -** from [sqlite3_str_new()]. -** -** ^The [sqlite3_str_appendf(X,F,...)] and -** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] -** functionality of SQLite to append formatted text onto the end of -** [sqlite3_str] object X. -** -** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S -** onto the end of the [sqlite3_str] object X. N must be non-negative. -** S must contain at least N non-zero bytes of content. To append a -** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] -** method instead. -** -** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of -** zero-terminated string S onto the end of [sqlite3_str] object X. -** -** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the -** single-byte character C onto the end of [sqlite3_str] object X. -** ^This method can be used, for example, to add whitespace indentation. -** -** ^The [sqlite3_str_reset(X)] method resets the string under construction -** inside [sqlite3_str] object X back to zero bytes in length. -** -** These methods do not return a result code. ^If an error occurs, that fact -** is recorded in the [sqlite3_str] object and can be recovered by a -** subsequent call to [sqlite3_str_errcode(X)]. -*/ -SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); -SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); -SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); -SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); -SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); -SQLITE_API void sqlite3_str_reset(sqlite3_str*); - -/* -** CAPI3REF: Status Of A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces return the current status of an [sqlite3_str] object. -** -** ^If any prior errors have occurred while constructing the dynamic string -** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return -** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns -** [SQLITE_NOMEM] following any out-of-memory error, or -** [SQLITE_TOOBIG] if the size of the dynamic string exceeds -** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. -** -** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, -** of the dynamic string under construction in [sqlite3_str] object X. -** ^The length returned by [sqlite3_str_length(X)] does not include the -** zero-termination byte. -** -** ^The [sqlite3_str_value(X)] method returns a pointer to the current -** content of the dynamic string under construction in X. The value -** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X -** and might be freed or altered by any subsequent method on the same -** [sqlite3_str] object. Applications must not use the pointer returned by -** [sqlite3_str_value(X)] after any subsequent method call on the same -** object. ^Applications may change the content of the string returned -** by [sqlite3_str_value(X)] as long as they do not write into any bytes -** outside the range of 0 to [sqlite3_str_length(X)] and do not read or -** write any byte after any subsequent sqlite3_str method call. -*/ -SQLITE_API int sqlite3_str_errcode(sqlite3_str*); -SQLITE_API int sqlite3_str_length(sqlite3_str*); -SQLITE_API char *sqlite3_str_value(sqlite3_str*); - -/* -** CAPI3REF: SQLite Runtime Status -** -** ^These interfaces are used to retrieve runtime status information -** about the performance of SQLite, and optionally to reset various -** highwater marks. ^The first argument is an integer code for -** the specific parameter to measure. ^(Recognized integer codes -** are of the form [status parameters | SQLITE_STATUS_...].)^ -** ^The current value of the parameter is returned into *pCurrent. -** ^The highest recorded value is returned in *pHighwater. ^If the -** resetFlag is true, then the highest record value is reset after -** *pHighwater is written. ^(Some parameters do not record the highest -** value. For those parameters -** nothing is written into *pHighwater and the resetFlag is ignored.)^ -** ^(Other parameters record only the highwater mark and not the current -** value. For these latter parameters nothing is written into *pCurrent.)^ -** -** ^The sqlite3_status() and sqlite3_status64() routines return -** SQLITE_OK on success and a non-zero [error code] on failure. -** -** If either the current value or the highwater mark is too large to -** be represented by a 32-bit integer, then the values returned by -** sqlite3_status() are undefined. -** -** See also: [sqlite3_db_status()] -*/ -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); -SQLITE_API int sqlite3_status64( - int op, - sqlite3_int64 *pCurrent, - sqlite3_int64 *pHighwater, - int resetFlag -); - - -/* -** CAPI3REF: Status Parameters -** KEYWORDS: {status parameters} -** -** These integer constants designate various run-time status parameters -** that can be returned by [sqlite3_status()]. -** -**
-** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
-**
This parameter is the current amount of memory checked out -** using [sqlite3_malloc()], either directly or indirectly. The -** figure includes calls made to [sqlite3_malloc()] by the application -** and internal memory usage by the SQLite library. Auxiliary page-cache -** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in -** this parameter. The amount returned is the sum of the allocation -** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ -** -** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
-**
This parameter records the largest memory allocation request -** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their -** internal equivalents). Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.
)^ -** -** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
-**
This parameter records the number of separate memory allocations -** currently checked out.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
-**
This parameter returns the number of pages used out of the -** [pagecache memory allocator] that was configured using -** [SQLITE_CONFIG_PAGECACHE]. The -** value returned is in pages, not in bytes.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] -** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
-**
This parameter returns the number of bytes of page cache -** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] -** buffer and where forced to overflow to [sqlite3_malloc()]. The -** returned value includes allocations that overflowed because they -** were too large (they were larger than the "sz" parameter to -** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because -** no space was left in the page cache.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
-**
This parameter records the largest memory allocation request -** handed to the [pagecache memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.
)^ -** -** [[SQLITE_STATUS_SCRATCH_USED]]
SQLITE_STATUS_SCRATCH_USED
-**
No longer used.
-** -** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
-**
No longer used.
-** -** [[SQLITE_STATUS_SCRATCH_SIZE]]
SQLITE_STATUS_SCRATCH_SIZE
-**
No longer used.
-** -** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
-**
The *pHighwater parameter records the deepest parser stack. -** The *pCurrent value is undefined. The *pHighwater value is only -** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ -**
-** -** New status parameters may be added from time to time. -*/ -#define SQLITE_STATUS_MEMORY_USED 0 -#define SQLITE_STATUS_PAGECACHE_USED 1 -#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ -#define SQLITE_STATUS_MALLOC_SIZE 5 -#define SQLITE_STATUS_PARSER_STACK 6 -#define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ -#define SQLITE_STATUS_MALLOC_COUNT 9 - -/* -** CAPI3REF: Database Connection Status -** METHOD: sqlite3 -** -** ^This interface is used to retrieve runtime status information -** about a single [database connection]. ^The first argument is the -** database connection object to be interrogated. ^The second argument -** is an integer constant, taken from the set of -** [SQLITE_DBSTATUS options], that -** determines the parameter to interrogate. The set of -** [SQLITE_DBSTATUS options] is likely -** to grow in future releases of SQLite. -** -** ^The current value of the requested parameter is written into *pCur -** and the highest instantaneous value is written into *pHiwtr. ^If -** the resetFlg is true, then the highest instantaneous value is -** reset back down to the current value. -** -** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. -** -** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. -*/ -SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); - -/* -** CAPI3REF: Status Parameters for database connections -** KEYWORDS: {SQLITE_DBSTATUS options} -** -** These constants are the available integer "verbs" that can be passed as -** the second argument to the [sqlite3_db_status()] interface. -** -** New verbs may be added in future releases of SQLite. Existing verbs -** might be discontinued. Applications should check the return code from -** [sqlite3_db_status()] to make sure that the call worked. -** The [sqlite3_db_status()] interface will return a non-zero error code -** if a discontinued or unsupported verb is invoked. -** -**
-** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
-**
This parameter returns the number of lookaside memory slots currently -** checked out.
)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
-**
This parameter returns the number of malloc attempts that were -** satisfied using lookaside memory. Only the high-water value is meaningful; -** the current value is always zero.
)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] -** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
-**
This parameter returns the number of malloc attempts that might have -** been satisfied using lookaside memory but failed due to the amount of -** memory requested being larger than the lookaside slot size. -** Only the high-water value is meaningful; -** the current value is always zero.
)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] -** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
-**
This parameter returns the number of malloc attempts that might have -** been satisfied using lookaside memory but failed due to all lookaside -** memory already being in use. -** Only the high-water value is meaningful; -** the current value is always zero.
)^ -** -** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
-**
This parameter returns the approximate number of bytes of heap -** memory used by all pager caches associated with the database connection.)^ -** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] -** ^(
SQLITE_DBSTATUS_CACHE_USED_SHARED
-**
This parameter is similar to DBSTATUS_CACHE_USED, except that if a -** pager cache is shared between two or more connections the bytes of heap -** memory used by that pager cache is divided evenly between the attached -** connections.)^ In other words, if none of the pager caches associated -** with the database connection are shared, this request returns the same -** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are -** shared, the value returned by this call will be smaller than that returned -** by DBSTATUS_CACHE_USED. ^The highwater mark associated with -** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
-** -** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
-**
This parameter returns the approximate number of bytes of heap -** memory used to store the schema for all databases associated -** with the connection - main, temp, and any [ATTACH]-ed databases.)^ -** ^The full amount of memory used by the schemas is reported, even if the -** schema memory is shared with other database connections due to -** [shared cache mode] being enabled. -** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. -**
-** -** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
-**
This parameter returns the approximate number of bytes of heap -** and lookaside memory used by all prepared statements associated with -** the database connection.)^ -** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
-**
This parameter returns the number of pager cache hits that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT -** is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
-**
This parameter returns the number of pager cache misses that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS -** is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
-**
This parameter returns the number of dirty cache entries that have -** been written to disk. Specifically, the number of pages written to the -** wal file in wal mode databases, or the number of pages written to the -** database file in rollback mode databases. Any pages written as part of -** transaction rollback or database recovery operations are not included. -** If an IO or other error occurs while writing a page to disk, the effect -** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The -** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
SQLITE_DBSTATUS_CACHE_SPILL
-**
This parameter returns the number of dirty cache entries that have -** been written to disk in the middle of a transaction due to the page -** cache overflowing. Transactions are more efficient if they are written -** to disk all at once. When pages spill mid-transaction, that introduces -** additional overhead. This parameter can be used to help identify -** inefficiencies that can be resolved by increasing the cache size. -**
-** -** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
-**
This parameter returns zero for the current value if and only if -** all foreign key constraints (deferred or immediate) have been -** resolved.)^ ^The highwater mark is always 0. -**
-**
-*/ -#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 -#define SQLITE_DBSTATUS_CACHE_USED 1 -#define SQLITE_DBSTATUS_SCHEMA_USED 2 -#define SQLITE_DBSTATUS_STMT_USED 3 -#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 -#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 -#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 -#define SQLITE_DBSTATUS_CACHE_HIT 7 -#define SQLITE_DBSTATUS_CACHE_MISS 8 -#define SQLITE_DBSTATUS_CACHE_WRITE 9 -#define SQLITE_DBSTATUS_DEFERRED_FKS 10 -#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_CACHE_SPILL 12 -#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ - - -/* -** CAPI3REF: Prepared Statement Status -** METHOD: sqlite3_stmt -** -** ^(Each prepared statement maintains various -** [SQLITE_STMTSTATUS counters] that measure the number -** of times it has performed specific operations.)^ These counters can -** be used to monitor the performance characteristics of the prepared -** statements. For example, if the number of table steps greatly exceeds -** the number of table searches or result rows, that would tend to indicate -** that the prepared statement is using a full table scan rather than -** an index. -** -** ^(This interface is used to retrieve and reset counter values from -** a [prepared statement]. The first argument is the prepared statement -** object to be interrogated. The second argument -** is an integer code for a specific [SQLITE_STMTSTATUS counter] -** to be interrogated.)^ -** ^The current value of the requested counter is returned. -** ^If the resetFlg is true, then the counter is reset to zero after this -** interface call returns. -** -** See also: [sqlite3_status()] and [sqlite3_db_status()]. -*/ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); - -/* -** CAPI3REF: Status Parameters for prepared statements -** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} -** -** These preprocessor macros define integer codes that name counter -** values associated with the [sqlite3_stmt_status()] interface. -** The meanings of the various counters are as follows: -** -**
-** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
-**
^This is the number of times that SQLite has stepped forward in -** a table as part of a full table scan. Large numbers for this counter -** may indicate opportunities for performance improvement through -** careful use of indices.
-** -** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
-**
^This is the number of sort operations that have occurred. -** A non-zero value in this counter may indicate an opportunity to -** improve performance through careful use of indices.
-** -** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
-**
^This is the number of rows inserted into transient indices that -** were created automatically in order to help joins run faster. -** A non-zero value in this counter may indicate an opportunity to -** improve performance by adding permanent indices that do not -** need to be reinitialized each time the statement is run.
-** -** [[SQLITE_STMTSTATUS_VM_STEP]]
SQLITE_STMTSTATUS_VM_STEP
-**
^This is the number of virtual machine operations executed -** by the prepared statement if that number is less than or equal -** to 2147483647. The number of virtual machine operations can be -** used as a proxy for the total work done by the prepared statement. -** If the number of virtual machine operations exceeds 2147483647 -** then the value returned by this statement status code is undefined.
-** -** [[SQLITE_STMTSTATUS_REPREPARE]]
SQLITE_STMTSTATUS_REPREPARE
-**
^This is the number of times that the prepare statement has been -** automatically regenerated due to schema changes or changes to -** [bound parameters] that might affect the query plan.
-** -** [[SQLITE_STMTSTATUS_RUN]]
SQLITE_STMTSTATUS_RUN
-**
^This is the number of times that the prepared statement has -** been run. A single "run" for the purposes of this counter is one -** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. -** The counter is incremented on the first [sqlite3_step()] call of each -** cycle.
-** -** [[SQLITE_STMTSTATUS_FILTER_MISS]] -** [[SQLITE_STMTSTATUS_FILTER HIT]] -**
SQLITE_STMTSTATUS_FILTER_HIT
-** SQLITE_STMTSTATUS_FILTER_MISS
-**
^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]]
SQLITE_STMTSTATUS_MEMUSED
-**
^This is the approximate number of bytes of heap memory -** used to store the prepared statement. ^This value is not actually -** a counter, and so the resetFlg parameter to sqlite3_stmt_status() -** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. -**
-**
-*/ -#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 -#define SQLITE_STMTSTATUS_SORT 2 -#define SQLITE_STMTSTATUS_AUTOINDEX 3 -#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 - -/* -** CAPI3REF: Custom Page Cache Object -** -** The sqlite3_pcache type is opaque. It is implemented by -** the pluggable module. The SQLite core has no knowledge of -** its size or internal structure and never deals with the -** sqlite3_pcache object except by holding and passing pointers -** to the object. -** -** See [sqlite3_pcache_methods2] for additional information. -*/ -typedef struct sqlite3_pcache sqlite3_pcache; - -/* -** CAPI3REF: Custom Page Cache Object -** -** The sqlite3_pcache_page object represents a single page in the -** page cache. The page cache will allocate instances of this -** object. Various methods of the page cache use pointers to instances -** of this object as parameters or as their return value. -** -** See [sqlite3_pcache_methods2] for additional information. -*/ -typedef struct sqlite3_pcache_page sqlite3_pcache_page; -struct sqlite3_pcache_page { - void *pBuf; /* The content of the page */ - void *pExtra; /* Extra information associated with the page */ -}; - -/* -** CAPI3REF: Application Defined Page Cache. -** KEYWORDS: {page cache} -** -** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can -** register an alternative page cache implementation by passing in an -** instance of the sqlite3_pcache_methods2 structure.)^ -** In many applications, most of the heap memory allocated by -** SQLite is used for the page cache. -** By implementing a -** custom page cache using this API, an application can better control -** the amount of memory consumed by SQLite, the way in which -** that memory is allocated and released, and the policies used to -** determine exactly which parts of a database file are cached and for -** how long. -** -** The alternative page cache mechanism is an -** extreme measure that is only needed by the most demanding applications. -** The built-in page cache is recommended for most uses. -** -** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an -** internal buffer by SQLite within the call to [sqlite3_config]. Hence -** the application may discard the parameter after the call to -** [sqlite3_config()] returns.)^ -** -** [[the xInit() page cache method]] -** ^(The xInit() method is called once for each effective -** call to [sqlite3_initialize()])^ -** (usually only once during the lifetime of the process). ^(The xInit() -** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ -** The intent of the xInit() method is to set up global data structures -** required by the custom page cache implementation. -** ^(If the xInit() method is NULL, then the -** built-in default page cache is used instead of the application defined -** page cache.)^ -** -** [[the xShutdown() page cache method]] -** ^The xShutdown() method is called by [sqlite3_shutdown()]. -** It can be used to clean up -** any outstanding resources before process shutdown, if required. -** ^The xShutdown() method may be NULL. -** -** ^SQLite automatically serializes calls to the xInit method, -** so the xInit method need not be threadsafe. ^The -** xShutdown method is only called from [sqlite3_shutdown()] so it does -** not need to be threadsafe either. All other methods must be threadsafe -** in multithreaded applications. -** -** ^SQLite will never invoke xInit() more than once without an intervening -** call to xShutdown(). -** -** [[the xCreate() page cache methods]] -** ^SQLite invokes the xCreate() method to construct a new cache instance. -** SQLite will typically create one cache instance for each open database file, -** though this is not guaranteed. ^The -** first parameter, szPage, is the size in bytes of the pages that must -** be allocated by the cache. ^szPage will always be a power of two. ^The -** second parameter szExtra is a number of bytes of extra storage -** associated with each page cache entry. ^The szExtra parameter will be -** a number less than 250. SQLite will use the -** extra szExtra bytes on each page to store metadata about the underlying -** database page on disk. The value passed into szExtra depends -** on the SQLite version, the target platform, and how SQLite was compiled. -** ^The third argument to xCreate(), bPurgeable, is true if the cache being -** created will be used to cache database pages of a file stored on disk, or -** false if it is used for an in-memory database. The cache implementation -** does not have to do anything special based upon the value of bPurgeable; -** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will -** never invoke xUnpin() except to deliberately delete a page. -** ^In other words, calls to xUnpin() on a cache with bPurgeable set to -** false will always have the "discard" flag set to true. -** ^Hence, a cache created with bPurgeable set to false will -** never contain any unpinned pages. -** -** [[the xCachesize() page cache method]] -** ^(The xCachesize() method may be called at any time by SQLite to set the -** suggested maximum cache-size (number of pages stored) for the cache -** instance passed as the first argument. This is the value configured using -** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable -** parameter, the implementation is not required to do anything with this -** value; it is advisory only. -** -** [[the xPagecount() page cache methods]] -** The xPagecount() method must return the number of pages currently -** stored in the cache, both pinned and unpinned. -** -** [[the xFetch() page cache methods]] -** The xFetch() method locates a page in the cache and returns a pointer to -** an sqlite3_pcache_page object associated with that page, or a NULL pointer. -** The pBuf element of the returned sqlite3_pcache_page object will be a -** pointer to a buffer of szPage bytes used to store the content of a -** single database page. The pExtra element of sqlite3_pcache_page will be -** a pointer to the szExtra bytes of extra storage that SQLite has requested -** for each entry in the page cache. -** -** The page to be fetched is determined by the key. ^The minimum key value -** is 1. After it has been retrieved using xFetch, the page is considered -** to be "pinned". -** -** If the requested page is already in the page cache, then the page cache -** implementation must return a pointer to the page buffer with its content -** intact. If the requested page is not already in the cache, then the -** cache implementation should use the value of the createFlag -** parameter to help it determine what action to take: -** -** -**
createFlag Behavior when page is not already in cache -**
0 Do not allocate a new page. Return NULL. -**
1 Allocate a new page if it is easy and convenient to do so. -** Otherwise return NULL. -**
2 Make every effort to allocate a new page. Only return -** NULL if allocating a new page is effectively impossible. -**
-** -** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite -** will only use a createFlag of 2 after a prior call with a createFlag of 1 -** failed.)^ In between the xFetch() calls, SQLite may -** attempt to unpin one or more cache pages by spilling the content of -** pinned pages to disk and synching the operating system disk cache. -** -** [[the xUnpin() page cache method]] -** ^xUnpin() is called by SQLite with a pointer to a currently pinned page -** as its second argument. If the third parameter, discard, is non-zero, -** then the page must be evicted from the cache. -** ^If the discard parameter is -** zero, then the page may be discarded or retained at the discretion of the -** page cache implementation. ^The page cache implementation -** may choose to evict unpinned pages at any time. -** -** The cache must not perform any reference counting. A single -** call to xUnpin() unpins the page regardless of the number of prior calls -** to xFetch(). -** -** [[the xRekey() page cache methods]] -** The xRekey() method is used to change the key value associated with the -** page passed as the second argument. If the cache -** previously contains an entry associated with newKey, it must be -** discarded. ^Any prior cache entry associated with newKey is guaranteed not -** to be pinned. -** -** When SQLite calls the xTruncate() method, the cache must discard all -** existing cache entries with page numbers (keys) greater than or equal -** to the value of the iLimit parameter passed to xTruncate(). If any -** of these pages are pinned, they become implicitly unpinned, meaning that -** they can be safely discarded. -** -** [[the xDestroy() page cache method]] -** ^The xDestroy() method is used to delete a cache allocated by xCreate(). -** All resources associated with the specified cache should be freed. ^After -** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] -** handle invalid, and will not use it with any other sqlite3_pcache_methods2 -** functions. -** -** [[the xShrink() page cache method]] -** ^SQLite invokes the xShrink() method when it wants the page cache to -** free up as much of heap memory as possible. The page cache implementation -** is not obligated to free any memory, but well-behaved implementations should -** do their best. -*/ -typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; -struct sqlite3_pcache_methods2 { - int iVersion; - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, - unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); - void (*xShrink)(sqlite3_pcache*); -}; - -/* -** This is the obsolete pcache_methods object that has now been replaced -** by sqlite3_pcache_methods2. This object is not used by SQLite. It is -** retained in the header file for backwards compatibility only. -*/ -typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; -struct sqlite3_pcache_methods { - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, void*, int discard); - void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); -}; - - -/* -** CAPI3REF: Online Backup Object -** -** The sqlite3_backup object records state information about an ongoing -** online backup operation. ^The sqlite3_backup object is created by -** a call to [sqlite3_backup_init()] and is destroyed by a call to -** [sqlite3_backup_finish()]. -** -** See Also: [Using the SQLite Online Backup API] -*/ -typedef struct sqlite3_backup sqlite3_backup; - -/* -** CAPI3REF: Online Backup API. -** -** The backup API copies the content of one database into another. -** It is useful either for creating backups of databases or -** for copying in-memory databases to or from persistent files. -** -** See Also: [Using the SQLite Online Backup API] -** -** ^SQLite holds a write transaction open on the destination database file -** for the duration of the backup operation. -** ^The source database is read-locked only while it is being read; -** it is not locked continuously for the entire backup operation. -** ^Thus, the backup may be performed on a live source database without -** preventing other database connections from -** reading or writing to the source database while the backup is underway. -** -** ^(To perform a backup operation: -**
    -**
  1. sqlite3_backup_init() is called once to initialize the -** backup, -**
  2. sqlite3_backup_step() is called one or more times to transfer -** the data between the two databases, and finally -**
  3. sqlite3_backup_finish() is called to release all resources -** associated with the backup operation. -**
)^ -** There should be exactly one call to sqlite3_backup_finish() for each -** successful call to sqlite3_backup_init(). -** -** [[sqlite3_backup_init()]] sqlite3_backup_init() -** -** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the -** [database connection] associated with the destination database -** and the database name, respectively. -** ^The database name is "main" for the main database, "temp" for the -** temporary database, or the name specified after the AS keyword in -** an [ATTACH] statement for an attached database. -** ^The S and M arguments passed to -** sqlite3_backup_init(D,N,S,M) identify the [database connection] -** and database name of the source database, respectively. -** ^The source and destination [database connections] (parameters S and D) -** must be different or else sqlite3_backup_init(D,N,S,M) will fail with -** an error. -** -** ^A call to sqlite3_backup_init() will fail, returning NULL, if -** there is already a read or read-write transaction open on the -** destination database. -** -** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is -** returned and an error code and error message are stored in the -** destination [database connection] D. -** ^The error code and message for the failed call to sqlite3_backup_init() -** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or -** [sqlite3_errmsg16()] functions. -** ^A successful call to sqlite3_backup_init() returns a pointer to an -** [sqlite3_backup] object. -** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and -** sqlite3_backup_finish() functions to perform the specified backup -** operation. -** -** [[sqlite3_backup_step()]] sqlite3_backup_step() -** -** ^Function sqlite3_backup_step(B,N) will copy up to N pages between -** the source and destination databases specified by [sqlite3_backup] object B. -** ^If N is negative, all remaining source pages are copied. -** ^If sqlite3_backup_step(B,N) successfully copies N pages and there -** are still more pages to be copied, then the function returns [SQLITE_OK]. -** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages -** from source to destination, then it returns [SQLITE_DONE]. -** ^If an error occurs while running sqlite3_backup_step(B,N), -** then an [error code] is returned. ^As well as [SQLITE_OK] and -** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], -** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an -** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. -** -** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if -**
    -**
  1. the destination database was opened read-only, or -**
  2. the destination database is using write-ahead-log journaling -** and the destination and source page sizes differ, or -**
  3. the destination database is an in-memory database and the -** destination and source page sizes differ. -**
)^ -** -** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then -** the [sqlite3_busy_handler | busy-handler function] -** is invoked (if one is specified). ^If the -** busy-handler returns non-zero before the lock is available, then -** [SQLITE_BUSY] is returned to the caller. ^In this case the call to -** sqlite3_backup_step() can be retried later. ^If the source -** [database connection] -** is being used to write to the source database when sqlite3_backup_step() -** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this -** case the call to sqlite3_backup_step() can be retried later on. ^(If -** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or -** [SQLITE_READONLY] is returned, then -** there is no point in retrying the call to sqlite3_backup_step(). These -** errors are considered fatal.)^ The application must accept -** that the backup operation has failed and pass the backup operation handle -** to the sqlite3_backup_finish() to release associated resources. -** -** ^The first call to sqlite3_backup_step() obtains an exclusive lock -** on the destination file. ^The exclusive lock is not released until either -** sqlite3_backup_finish() is called or the backup operation is complete -** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to -** sqlite3_backup_step() obtains a [shared lock] on the source database that -** lasts for the duration of the sqlite3_backup_step() call. -** ^Because the source database is not locked between calls to -** sqlite3_backup_step(), the source database may be modified mid-way -** through the backup process. ^If the source database is modified by an -** external process or via a database connection other than the one being -** used by the backup operation, then the backup will be automatically -** restarted by the next call to sqlite3_backup_step(). ^If the source -** database is modified by using the same database connection as is used -** by the backup operation, then the backup database is automatically -** updated at the same time. -** -** [[sqlite3_backup_finish()]] sqlite3_backup_finish() -** -** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the -** application wishes to abandon the backup operation, the application -** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). -** ^The sqlite3_backup_finish() interfaces releases all -** resources associated with the [sqlite3_backup] object. -** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any -** active write-transaction on the destination database is rolled back. -** The [sqlite3_backup] object is invalid -** and may not be used following a call to sqlite3_backup_finish(). -** -** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no -** sqlite3_backup_step() errors occurred, regardless of whether or not -** sqlite3_backup_step() completed. -** ^If an out-of-memory condition or IO error occurred during any prior -** sqlite3_backup_step() call on the same [sqlite3_backup] object, then -** sqlite3_backup_finish() returns the corresponding [error code]. -** -** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() -** is not a permanent error and does not affect the return value of -** sqlite3_backup_finish(). -** -** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] -** sqlite3_backup_remaining() and sqlite3_backup_pagecount() -** -** ^The sqlite3_backup_remaining() routine returns the number of pages still -** to be backed up at the conclusion of the most recent sqlite3_backup_step(). -** ^The sqlite3_backup_pagecount() routine returns the total number of pages -** in the source database at the conclusion of the most recent -** sqlite3_backup_step(). -** ^(The values returned by these functions are only updated by -** sqlite3_backup_step(). If the source database is modified in a way that -** changes the size of the source database or the number of pages remaining, -** those changes are not reflected in the output of sqlite3_backup_pagecount() -** and sqlite3_backup_remaining() until after the next -** sqlite3_backup_step().)^ -** -** Concurrent Usage of Database Handles -** -** ^The source [database connection] may be used by the application for other -** purposes while a backup operation is underway or being initialized. -** ^If SQLite is compiled and configured to support threadsafe database -** connections, then the source database connection may be used concurrently -** from within other threads. -** -** However, the application must guarantee that the destination -** [database connection] is not passed to any other API (by any thread) after -** sqlite3_backup_init() is called and before the corresponding call to -** sqlite3_backup_finish(). SQLite does not currently check to see -** if the application incorrectly accesses the destination [database connection] -** and so no error code is reported, but the operations may malfunction -** nevertheless. Use of the destination database connection while a -** backup is in progress might also cause a mutex deadlock. -** -** If running in [shared cache mode], the application must -** guarantee that the shared cache used by the destination database -** is not accessed while the backup is running. In practice this means -** that the application must guarantee that the disk file being -** backed up to is not accessed by any connection within the process, -** not just the specific connection that was passed to sqlite3_backup_init(). -** -** The [sqlite3_backup] object itself is partially threadsafe. Multiple -** threads may safely make multiple concurrent calls to sqlite3_backup_step(). -** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() -** APIs are not strictly speaking threadsafe. If they are invoked at the -** same time as another thread is invoking sqlite3_backup_step() it is -** possible that they return invalid values. -** -** Alternatives To Using The Backup API -** -** Other techniques for safely creating a consistent backup of an SQLite -** database include: -** -**
    -**
  • The [VACUUM INTO] command. -**
  • The [sqlite3_rsync] utility program. -**
-*/ -SQLITE_API sqlite3_backup *sqlite3_backup_init( - sqlite3 *pDest, /* Destination database handle */ - const char *zDestName, /* Destination database name */ - sqlite3 *pSource, /* Source database handle */ - const char *zSourceName /* Source database name */ -); -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); - -/* -** CAPI3REF: Unlock Notification -** METHOD: sqlite3 -** -** ^When running in shared-cache mode, a database operation may fail with -** an [SQLITE_LOCKED] error if the required locks on the shared-cache or -** individual tables within the shared-cache cannot be obtained. See -** [SQLite Shared-Cache Mode] for a description of shared-cache locking. -** ^This API may be used to register a callback that SQLite will invoke -** when the connection currently holding the required lock relinquishes it. -** ^This API is only available if the library was compiled with the -** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. -** -** See Also: [Using the SQLite Unlock Notification Feature]. -** -** ^Shared-cache locks are released when a database connection concludes -** its current transaction, either by committing it or rolling it back. -** -** ^When a connection (known as the blocked connection) fails to obtain a -** shared-cache lock and SQLITE_LOCKED is returned to the caller, the -** identity of the database connection (the blocking connection) that -** has locked the required resource is stored internally. ^After an -** application receives an SQLITE_LOCKED error, it may call the -** sqlite3_unlock_notify() method with the blocked connection handle as -** the first argument to register for a callback that will be invoked -** when the blocking connection's current transaction is concluded. ^The -** callback is invoked from within the [sqlite3_step] or [sqlite3_close] -** call that concludes the blocking connection's transaction. -** -** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, -** there is a chance that the blocking connection will have already -** concluded its transaction by the time sqlite3_unlock_notify() is invoked. -** If this happens, then the specified callback is invoked immediately, -** from within the call to sqlite3_unlock_notify().)^ -** -** ^If the blocked connection is attempting to obtain a write-lock on a -** shared-cache table, and more than one other connection currently holds -** a read-lock on the same table, then SQLite arbitrarily selects one of -** the other connections to use as the blocking connection. -** -** ^(There may be at most one unlock-notify callback registered by a -** blocked connection. If sqlite3_unlock_notify() is called when the -** blocked connection already has a registered unlock-notify callback, -** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is -** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connection's -** unlock-notify callback may also be canceled by closing the blocked -** connection using [sqlite3_close()]. -** -** The unlock-notify callback is not reentrant. If an application invokes -** any sqlite3_xxx API functions from within an unlock-notify callback, a -** crash or deadlock may be the result. -** -** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always -** returns SQLITE_OK. -** -** Callback Invocation Details -** -** When an unlock-notify callback is registered, the application provides a -** single void* pointer that is passed to the callback when it is invoked. -** However, the signature of the callback function allows SQLite to pass -** it an array of void* context pointers. The first argument passed to -** an unlock-notify callback is a pointer to an array of void* pointers, -** and the second is the number of entries in the array. -** -** When a blocking connection's transaction is concluded, there may be -** more than one blocked connection that has registered for an unlock-notify -** callback. ^If two or more such blocked connections have specified the -** same callback function, then instead of invoking the callback function -** multiple times, it is invoked once with the set of void* context pointers -** specified by the blocked connections bundled together into an array. -** This gives the application an opportunity to prioritize any actions -** related to the set of unblocked database connections. -** -** Deadlock Detection -** -** Assuming that after registering for an unlock-notify callback a -** database waits for the callback to be issued before taking any further -** action (a reasonable assumption), then using this API may cause the -** application to deadlock. For example, if connection X is waiting for -** connection Y's transaction to be concluded, and similarly connection -** Y is waiting on connection X's transaction, then neither connection -** will proceed and the system may remain deadlocked indefinitely. -** -** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock -** detection. ^If a given call to sqlite3_unlock_notify() would put the -** system in a deadlocked state, then SQLITE_LOCKED is returned and no -** unlock-notify callback is registered. The system is said to be in -** a deadlocked state if connection A has registered for an unlock-notify -** callback on the conclusion of connection B's transaction, and connection -** B has itself registered for an unlock-notify callback when connection -** A's transaction is concluded. ^Indirect deadlock is also detected, so -** the system is also considered to be deadlocked if connection B has -** registered for an unlock-notify callback on the conclusion of connection -** C's transaction, where connection C is waiting on connection A. ^Any -** number of levels of indirection are allowed. -** -** The "DROP TABLE" Exception -** -** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost -** always appropriate to call sqlite3_unlock_notify(). There is however, -** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, -** SQLite checks if there are any currently executing SELECT statements -** that belong to the same connection. If there are, SQLITE_LOCKED is -** returned. In this case there is no "blocking connection", so invoking -** sqlite3_unlock_notify() results in the unlock-notify callback being -** invoked immediately. If the application then re-attempts the "DROP TABLE" -** or "DROP INDEX" query, an infinite loop might be the result. -** -** One way around this problem is to check the extended error code returned -** by an sqlite3_step() call. ^(If there is a blocking connection, then the -** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in -** the special "DROP TABLE/INDEX" case, the extended error code is just -** SQLITE_LOCKED.)^ -*/ -SQLITE_API int sqlite3_unlock_notify( - sqlite3 *pBlocked, /* Waiting connection */ - void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ - void *pNotifyArg /* Argument to pass to xNotify */ -); - - -/* -** CAPI3REF: String Comparison -** -** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications -** and extensions to compare the contents of two buffers containing UTF-8 -** strings in a case-independent fashion, using the same definition of "case -** independence" that SQLite uses internally when comparing identifiers. -*/ -SQLITE_API int sqlite3_stricmp(const char *, const char *); -SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); - -/* -** CAPI3REF: String Globbing -* -** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if -** string X matches the [GLOB] pattern P. -** ^The definition of [GLOB] pattern matching used in -** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the -** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function -** is case sensitive. -** -** Note that this routine returns zero on a match and non-zero if the strings -** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. -** -** See also: [sqlite3_strlike()]. -*/ -SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); - -/* -** CAPI3REF: String LIKE Matching -* -** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if -** string X matches the [LIKE] pattern P with escape character E. -** ^The definition of [LIKE] pattern matching used in -** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E" -** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without -** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0. -** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case -** insensitive - equivalent upper and lower case ASCII characters match -** one another. -** -** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though -** only ASCII characters are case folded. -** -** Note that this routine returns zero on a match and non-zero if the strings -** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. -** -** See also: [sqlite3_strglob()]. -*/ -SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); - -/* -** CAPI3REF: Error Logging Interface -** -** ^The [sqlite3_log()] interface writes a message into the [error log] -** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. -** ^If logging is enabled, the zFormat string and subsequent arguments are -** used with [sqlite3_snprintf()] to generate the final output string. -** -** The sqlite3_log() interface is intended for use by extensions such as -** virtual tables, collating functions, and SQL functions. While there is -** nothing to prevent an application from calling sqlite3_log(), doing so -** is considered bad form. -** -** The zFormat string must not be NULL. -** -** To avoid deadlocks and other threading problems, the sqlite3_log() routine -** will not use dynamically allocated memory. The log message is stored in -** a fixed-length buffer on the stack. If the log message is longer than -** a few hundred characters, it will be truncated to the length of the -** buffer. -*/ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); - -/* -** CAPI3REF: Write-Ahead Log Commit Hook -** METHOD: sqlite3 -** -** ^The [sqlite3_wal_hook()] function is used to register a callback that -** is invoked each time data is committed to a database in wal mode. -** -** ^(The callback is invoked by SQLite after the commit has taken place and -** the associated write-lock on the database released)^, so the implementation -** may read, write or [checkpoint] the database as required. -** -** ^The first parameter passed to the callback function when it is invoked -** is a copy of the third parameter passed to sqlite3_wal_hook() when -** registering the callback. ^The second is a copy of the database handle. -** ^The third parameter is the name of the database that was written to - -** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter -** is the number of pages currently in the write-ahead log file, -** including those that were just committed. -** -** The callback function should normally return [SQLITE_OK]. ^If an error -** code is returned, that error will propagate back up through the -** SQLite code base to cause the statement that provoked the callback -** to report an error, though the commit will have still occurred. If the -** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value -** that does not correspond to any valid SQLite error code, the results -** are undefined. -** -** A single database handle may have at most a single write-ahead log callback -** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any -** 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 [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will -** overwrite any prior [sqlite3_wal_hook()] settings. -*/ -SQLITE_API void *sqlite3_wal_hook( - sqlite3*, - int(*)(void *,sqlite3*,const char*,int), - void* -); - -/* -** CAPI3REF: Configure an auto-checkpoint -** METHOD: sqlite3 -** -** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around -** [sqlite3_wal_hook()] that causes any database on [database connection] D -** to automatically [checkpoint] -** after committing a transaction if there are N or -** more frames in the [write-ahead log] file. ^Passing zero or -** a negative value as the nFrame parameter disables automatic -** checkpoints entirely. -** -** ^The callback registered by this function replaces any existing callback -** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback -** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism -** configured by this function. -** -** ^The [wal_autocheckpoint pragma] can be used to invoke this interface -** from SQL. -** -** ^Checkpoints initiated by this mechanism are -** [sqlite3_wal_checkpoint_v2|PASSIVE]. -** -** ^Every new [database connection] defaults to having the auto-checkpoint -** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] -** pages. The use of this interface -** is only necessary if the default setting is found to be suboptimal -** for a particular application. -*/ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); - -/* -** CAPI3REF: Checkpoint a database -** METHOD: sqlite3 -** -** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to -** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ -** -** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the -** [write-ahead log] for database X on [database connection] D to be -** transferred into the database file and for the write-ahead log to -** be reset. See the [checkpointing] documentation for addition -** information. -** -** This interface used to be the only way to cause a checkpoint to -** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] -** interface was added. This interface is retained for backwards -** compatibility and as a convenience for applications that need to manually -** start a callback but which do not need the full power (and corresponding -** complication) of [sqlite3_wal_checkpoint_v2()]. -*/ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); - -/* -** CAPI3REF: Checkpoint a database -** METHOD: sqlite3 -** -** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint -** operation on database X of [database connection] D in mode M. Status -** information is written back into integers pointed to by L and C.)^ -** ^(The M parameter must be a valid [checkpoint mode]:)^ -** -**
-**
SQLITE_CHECKPOINT_PASSIVE
-** ^Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish, then sync the database file if all frames -** in the log were checkpointed. ^The [busy-handler callback] -** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. -** ^On the other hand, passive mode might leave the checkpoint unfinished -** if there are concurrent readers or writers. -** -**
SQLITE_CHECKPOINT_FULL
-** ^This mode blocks (it invokes the -** [sqlite3_busy_handler|busy-handler callback]) until there is no -** database writer and all readers are reading from the most recent database -** snapshot. ^It then checkpoints all frames in the log file and syncs the -** database file. ^This mode blocks new database writers while it is pending, -** but new database readers are allowed to continue unimpeded. -** -**
SQLITE_CHECKPOINT_RESTART
-** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition -** that after checkpointing the log file it blocks (calls the -** [busy-handler callback]) -** until all readers are reading from the database file only. ^This ensures -** that the next writer will restart the log file from the beginning. -** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new -** database writer attempts while it is pending, but does not impede readers. -** -**
SQLITE_CHECKPOINT_TRUNCATE
-** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the -** addition that it also truncates the log file to zero bytes just prior -** to a successful return. -**
-** -** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in -** the log file or to -1 if the checkpoint could not run because -** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not -** NULL,then *pnCkpt is set to the total number of checkpointed frames in the -** log file (including any that were already checkpointed before the function -** was called) or to -1 if the checkpoint could not run due to an error or -** because the database is not in WAL mode. ^Note that upon successful -** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been -** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. -** -** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If -** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a -** busy-handler configured, it will not be invoked in this case. -** -** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the -** exclusive "writer" lock on the database file. ^If the writer lock cannot be -** obtained immediately, and a busy-handler is configured, it is invoked and -** the writer lock retried until either the busy-handler returns 0 or the lock -** is successfully obtained. ^The busy-handler is also invoked while waiting for -** database readers as described above. ^If the busy-handler returns 0 before -** the writer lock is obtained or while waiting for database readers, the -** checkpoint operation proceeds from that point in the same way as -** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible -** without blocking any further. ^SQLITE_BUSY is returned in this case. -** -** ^If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases [attached] to -** [database connection] db. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. ^If -** an SQLITE_BUSY error is encountered when processing one or more of the -** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned at the end. ^If any other -** error occurs while processing an attached database, processing is abandoned -** and the error code is returned to the caller immediately. ^If no error -** (SQLITE_BUSY or otherwise) is encountered while processing the attached -** databases, SQLITE_OK is returned. -** -** ^If database zDb is the name of an attached database that is not in WAL -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If -** zDb is not NULL (or a zero length string) and is not the name of any -** attached database, SQLITE_ERROR is returned to the caller. -** -** ^Unless it returns SQLITE_MISUSE, -** the sqlite3_wal_checkpoint_v2() interface -** sets the error information that is queried by -** [sqlite3_errcode()] and [sqlite3_errmsg()]. -** -** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface -** from SQL. -*/ -SQLITE_API int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ -); - -/* -** CAPI3REF: Checkpoint Mode Values -** KEYWORDS: {checkpoint mode} -** -** These constants define all valid values for the "checkpoint mode" passed -** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. -** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the -** meaning of each of these checkpoint modes. -*/ -#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ -#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ -#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ -#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ - -/* -** CAPI3REF: Virtual Table Interface Configuration -** -** This function may be called by either the [xConnect] or [xCreate] method -** of a [virtual table] implementation to configure -** various facets of the virtual table interface. -** -** If this interface is invoked outside the context of an xConnect or -** xCreate virtual table method then the behavior is undefined. -** -** In the call sqlite3_vtab_config(D,C,...) the D parameter is the -** [database connection] in which the virtual table is being created and -** which is passed in as the first argument to the [xConnect] or [xCreate] -** method that is invoking sqlite3_vtab_config(). The C parameter is one -** of the [virtual table configuration options]. The presence and meaning -** of parameters after C depend on which [virtual table configuration option] -** is used. -*/ -SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); - -/* -** CAPI3REF: Virtual Table Configuration Options -** KEYWORDS: {virtual table configuration options} -** KEYWORDS: {virtual table configuration option} -** -** These macros define the various options to the -** [sqlite3_vtab_config()] interface that [virtual table] implementations -** can use to customize and optimize their behavior. -** -**
-** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] -**
SQLITE_VTAB_CONSTRAINT_SUPPORT
-**
Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, -** where X is an integer. If X is zero, then the [virtual table] whose -** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not -** support constraints. In this configuration (which is the default) if -** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire -** statement is rolled back as if [ON CONFLICT | OR ABORT] had been -** specified as part of the user's SQL statement, regardless of the actual -** ON CONFLICT mode specified. -** -** If X is non-zero, then the virtual table implementation guarantees -** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before -** any modifications to internal or persistent data structures have been made. -** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite -** is able to roll back a statement or database transaction, and abandon -** or continue processing the current SQL statement as appropriate. -** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns -** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode -** had been ABORT. -** -** Virtual table implementations that are required to handle OR REPLACE -** must do so within the [xUpdate] method. If a call to the -** [sqlite3_vtab_on_conflict()] function indicates that the current ON -** CONFLICT policy is REPLACE, the virtual table implementation should -** silently replace the appropriate rows within the xUpdate callback and -** return SQLITE_OK. Or, if this is not possible, it may return -** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT -** constraint handling. -**
-** -** [[SQLITE_VTAB_DIRECTONLY]]
SQLITE_VTAB_DIRECTONLY
-**
Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** prohibits that virtual table from being used from within triggers and -** views. -**
-** -** [[SQLITE_VTAB_INNOCUOUS]]
SQLITE_VTAB_INNOCUOUS
-**
Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the -** [xConnect] or [xCreate] methods of a [virtual table] implementation -** identify that virtual table as being safe to use from within triggers -** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the -** virtual table can do no serious harm even if it is controlled by a -** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS -** flag unless absolutely necessary. -**
-** -** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]
SQLITE_VTAB_USES_ALL_SCHEMAS
-**
Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** instruct the query planner to begin at least a read transaction on -** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the -** virtual table is used. -**
-**
-*/ -#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 -#define SQLITE_VTAB_INNOCUOUS 2 -#define SQLITE_VTAB_DIRECTONLY 3 -#define SQLITE_VTAB_USES_ALL_SCHEMAS 4 - -/* -** CAPI3REF: Determine The Virtual Table Conflict Policy -** -** This function may only be called from within a call to the [xUpdate] method -** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The -** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], -** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode -** of the SQL statement that triggered the call to the [xUpdate] method of the -** [virtual table]. -*/ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); - -/* -** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE -** -** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] -** method of a [virtual table], then it might return true if the -** column is being fetched as part of an UPDATE operation during which the -** column value will not change. The virtual table implementation can use -** this hint as permission to substitute a return value that is less -** expensive to compute and that the corresponding -** [xUpdate] method understands as a "no-change" value. -** -** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that -** the column is not changed by the UPDATE statement, then the xColumn -** method can optionally return without setting a result, without calling -** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. -** In that case, [sqlite3_value_nochange(X)] will return true for the -** same column in the [xUpdate] method. -** -** The sqlite3_vtab_nochange() routine is an optimization. Virtual table -** implementations should continue to give a correct answer even if the -** sqlite3_vtab_nochange() interface were to always return false. In the -** current implementation, the sqlite3_vtab_nochange() interface does always -** returns false for the enhanced [UPDATE FROM] statement. -*/ -SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); - -/* -** CAPI3REF: Determine The Collation For a Virtual Table Constraint -** METHOD: sqlite3_index_info -** -** This function may only be called from within a call to the [xBestIndex] -** 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 [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 -** 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 [sqlite3_index_info] object, even an exact copy. -** -** The return value is computed as follows: -** -**
    -**
  1. 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. -**

  2. 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 [sqlite3_declare_vtab()], then the -** name of that alternative collating sequence is returned. -**

  3. Otherwise, "BINARY" is returned. -**

-*/ -SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); - -/* -** CAPI3REF: Determine if a virtual table query is DISTINCT -** METHOD: 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 sqlite3_vtab_distinct() interface returns an integer between 0 and -** 3. The integer returned by 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. -** -**
  1. -** ^If the 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 -** [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 sqlite3_vtab_distinct(). -**

  2. -** ^(If the 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. -**

  3. -** ^(If the 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 columns identified -** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows -** contain the same values for all columns identified by "colUsed", all but -** one such row may optionally be omitted from the result.)^ -** The virtual table is not required to omit rows that are duplicates -** over the "colUsed" columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for a DISTINCT query. -**

  4. -** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the -** virtual table must return rows in the order defined by "aOrderBy" as -** if the sqlite3_vtab_distinct() interface had returned 0. However if -** two or more rows in the result have the same values for all columns -** identified by "colUsed", then all but one such row may optionally be -** omitted.)^ Like when the return value is 2, the virtual table -** is not required to omit rows that are duplicates over the "colUsed" -** columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for queries -** that have both DISTINCT and ORDER BY clauses. -**

-** -**

The following table summarizes the conditions under which the -** virtual table is allowed to set the "orderByConsumed" flag based on -** the value returned by sqlite3_vtab_distinct(). This table is a -** restatement of the previous four paragraphs: -** -** -** -**
sqlite3_vtab_distinct() return value -** Rows are returned in aOrderBy order -** Rows with the same value in all aOrderBy columns are adjacent -** Duplicates over all colUsed columns may be omitted -**
0yesyesno -**
1noyesno -**
2noyesyes -**
3yesyesyes -**
-** -** ^For the purposes of comparing virtual table output values to see if the -** values are the 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 -** [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 -** "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 -** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful -** use of the 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 sqlite3_vtab_distinct(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 positive 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 sqlite3_vtab_in() interfaces facilitates this in two ways: -** -**

    -**
  1. -** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) -** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint -** is an [IN operator] that can be processed all at once. ^In other words, -** 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. -** -**

  2. -** ^A call to 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. -**

-** -** ^The 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 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: -** -**
    -**
  1. 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. -** -**

  2. The last call to sqlite3_vtab_in(P,N,F) for which F was -** non-negative had F>=1. -**

)^ -** -** ^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 [sqlite3_value] that appears to be NULL, -** but which can be passed to [sqlite3_vtab_in_first()] and -** [sqlite3_vtab_in_next()] to find all values on the right-hand side -** of the IN constraint. -*/ -SQLITE_API int sqlite3_vtab_in(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 sqlite3_vtab_in_first(X,P) or -** sqlite3_vtab_in_next(X,P) should 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 using the [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_ERROR].)^ -** -** ^(Use these routines to access all values on the right-hand side -** of the IN constraint using code like the following: -** -**
-**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
-**        rc==SQLITE_OK && pVal;
-**        rc=sqlite3_vtab_in_next(pList, &pVal)
-**    ){
-**      // do something with pVal
-**    }
-**    if( rc!=SQLITE_OK ){
-**      // an error has occurred
-**    }
-** 
)^ -** -** ^On success, the sqlite3_vtab_in_first(X,P) and 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 sqlite3_value|protected]. -*/ -SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); -SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); - -/* -** CAPI3REF: Constraint values in xBestIndex() -** METHOD: 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 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 [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 sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if -** and only if *V is set to a value. ^The 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 sqlite3_vtab_rhs_value() interface -** can return a result code other than SQLITE_OK or SQLITE_NOTFOUND if -** something goes wrong. -** -** The 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 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, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ -** -** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value -** and remains valid for the duration of the xBestIndex method call. -** ^When xBestIndex returns, the sqlite3_value object returned by -** 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 sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); - -/* -** CAPI3REF: Conflict resolution modes -** KEYWORDS: {conflict resolution mode} -** -** These constants are returned by [sqlite3_vtab_on_conflict()] to -** inform a [virtual table] implementation of the [ON CONFLICT] mode -** for the SQL statement being evaluated. -** -** Note that the [SQLITE_IGNORE] constant is also used as a potential -** return value from the [sqlite3_set_authorizer()] callback and that -** [SQLITE_ABORT] is also a [result code]. -*/ -#define SQLITE_ROLLBACK 1 -/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ -#define SQLITE_FAIL 3 -/* #define SQLITE_ABORT 4 // Also an error code */ -#define SQLITE_REPLACE 5 - -/* -** CAPI3REF: Prepared Statement Scan Status Opcodes -** KEYWORDS: {scanstatus options} -** -** The following constants can be used for the T parameter to the -** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a -** different metric for sqlite3_stmt_scanstatus() to return. -** -** When the value returned to V is a string, space to hold that string is -** managed by the prepared statement S and will be automatically freed when -** S is finalized. -** -** Not all values are available for all query elements. When a value is -** not available, the output variable is set to -1 if the value is numeric, -** or to NULL if it is a string (SQLITE_SCANSTAT_NAME). -** -**
-** [[SQLITE_SCANSTAT_NLOOP]]
SQLITE_SCANSTAT_NLOOP
-**
^The [sqlite3_int64] variable pointed to by the V parameter will be -** set to the total number of times that the X-th loop has run.
-** -** [[SQLITE_SCANSTAT_NVISIT]]
SQLITE_SCANSTAT_NVISIT
-**
^The [sqlite3_int64] variable pointed to by the V parameter will be set -** to the total number of rows examined by all iterations of the X-th loop.
-** -** [[SQLITE_SCANSTAT_EST]]
SQLITE_SCANSTAT_EST
-**
^The "double" variable pointed to by the V parameter will be set to the -** query planner's estimate for the average number of rows output from each -** iteration of the X-th loop. If the query planner's estimate was accurate, -** then this value will approximate the quotient NVISIT/NLOOP and the -** product of this value for all prior loops with the same SELECTID will -** be the NLOOP value for the current loop.
-** -** [[SQLITE_SCANSTAT_NAME]]
SQLITE_SCANSTAT_NAME
-**
^The "const char *" variable pointed to by the V parameter will be set -** to a zero-terminated UTF-8 string containing the name of the index or table -** used for the X-th loop.
-** -** [[SQLITE_SCANSTAT_EXPLAIN]]
SQLITE_SCANSTAT_EXPLAIN
-**
^The "const char *" variable pointed to by the V parameter will be set -** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] -** description for the X-th loop.
-** -** [[SQLITE_SCANSTAT_SELECTID]]
SQLITE_SCANSTAT_SELECTID
-**
^The "int" variable pointed to by the V parameter will be set to the -** id for the X-th query plan element. The id value is unique within the -** statement. The select-id is the same value as is output in the first -** column of an [EXPLAIN QUERY PLAN] query.
-** -** [[SQLITE_SCANSTAT_PARENTID]]
SQLITE_SCANSTAT_PARENTID
-**
The "int" variable pointed to by the V parameter will be set to the -** id of the parent of the current query element, if applicable, or -** to zero if the query element has no parent. This is the same value as -** returned in the second column of an [EXPLAIN QUERY PLAN] query.
-** -** [[SQLITE_SCANSTAT_NCYCLE]]
SQLITE_SCANSTAT_NCYCLE
-**
The sqlite3_int64 output value is set to the number of cycles, -** according to the processor time-stamp counter, that elapsed while the -** query element was being processed. This value is not available for -** all query elements - if it is unavailable the output variable is -** set to -1.
-**
-*/ -#define SQLITE_SCANSTAT_NLOOP 0 -#define SQLITE_SCANSTAT_NVISIT 1 -#define SQLITE_SCANSTAT_EST 2 -#define SQLITE_SCANSTAT_NAME 3 -#define SQLITE_SCANSTAT_EXPLAIN 4 -#define SQLITE_SCANSTAT_SELECTID 5 -#define SQLITE_SCANSTAT_PARENTID 6 -#define SQLITE_SCANSTAT_NCYCLE 7 - -/* -** CAPI3REF: Prepared Statement Scan Status -** METHOD: sqlite3_stmt -** -** These interfaces return information about the predicted and measured -** performance for pStmt. Advanced applications can use this -** interface to compare the predicted and the measured performance and -** issue warnings and/or rerun [ANALYZE] if discrepancies are found. -** -** Since this interface is expected to be rarely used, it is only -** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] -** compile-time option. -** -** The "iScanStatusOp" parameter determines which status information to return. -** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior -** of this interface is undefined. ^The requested measurement is written into -** a variable pointed to by the "pOut" parameter. -** -** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX -** is specified, then status information is available for all elements -** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If -** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements -** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of -** the EXPLAIN QUERY PLAN output) are available. Invoking API -** sqlite3_stmt_scanstatus() is equivalent to calling -** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter. -** -** Parameter "idx" identifies the specific query element to retrieve statistics -** for. Query elements are numbered starting from zero. A value of -1 may -** retrieve statistics for the entire query. ^If idx is out of range -** - less than -1 or greater than or equal to the total number of query -** elements used to implement the statement - a non-zero value is returned and -** the variable that pOut points to is unchanged. -** -** See also: [sqlite3_stmt_scanstatus_reset()] -*/ -SQLITE_API int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - void *pOut /* Result written here */ -); -SQLITE_API int sqlite3_stmt_scanstatus_v2( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - int flags, /* Mask of flags defined below */ - void *pOut /* Result written here */ -); - -/* -** CAPI3REF: Prepared Statement Scan Status -** KEYWORDS: {scan status flags} -*/ -#define SQLITE_SCANSTAT_COMPLEX 0x0001 - -/* -** CAPI3REF: Zero Scan-Status Counters -** METHOD: sqlite3_stmt -** -** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. -** -** This API is only available if the library is built with pre-processor -** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. -*/ -SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); - -/* -** CAPI3REF: Flush caches to disk mid-transaction -** METHOD: sqlite3 -** -** ^If a write-transaction is open on [database connection] D when the -** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty -** pages in the pager-cache that are not currently in use are written out -** to disk. A dirty page may be in use if a database cursor created by an -** active SQL statement is reading from it, or if it is page 1 of a database -** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)] -** interface flushes caches for all schemas - "main", "temp", and -** any [attached] databases. -** -** ^If this function needs to obtain extra database locks before dirty pages -** can be flushed to disk, it does so. ^If those locks cannot be obtained -** immediately and there is a busy-handler callback configured, it is invoked -** in the usual manner. ^If the required lock still cannot be obtained, then -** the database is skipped and an attempt made to flush any dirty pages -** belonging to the next (if any) database. ^If any databases are skipped -** because locks cannot be obtained, but no other error occurs, this -** function returns SQLITE_BUSY. -** -** ^If any other error occurs while flushing dirty pages to disk (for -** example an IO error or out-of-memory condition), then processing is -** abandoned and an SQLite [error code] is returned to the caller immediately. -** -** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK. -** -** ^This function does not set the database handle error code or message -** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. -*/ -SQLITE_API int sqlite3_db_cacheflush(sqlite3*); - -/* -** CAPI3REF: The pre-update hook. -** METHOD: sqlite3 -** -** ^These interfaces are only available if SQLite is compiled using the -** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. -** -** ^The [sqlite3_preupdate_hook()] interface registers a callback function -** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation -** on a database table. -** ^At most one preupdate hook may be registered at a time on a single -** [database connection]; each call to [sqlite3_preupdate_hook()] overrides -** the previous setting. -** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] -** with a NULL pointer as the second parameter. -** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as -** the first parameter to callbacks. -** -** ^The preupdate hook only fires for changes to real database tables; the -** preupdate hook is not invoked for changes to [virtual tables] or to -** system tables like sqlite_sequence or sqlite_stat1. -** -** ^The second parameter to the preupdate callback is a pointer to -** the [database connection] that registered the preupdate hook. -** ^The third parameter to the preupdate callback is one of the constants -** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the -** kind of update operation that is about to occur. -** ^(The fourth parameter to the preupdate callback is the name of the -** database within the database connection that is being modified. This -** will be "main" for the main database or "temp" for TEMP tables or -** the name given after the AS keyword in the [ATTACH] statement for attached -** databases.)^ -** ^The fifth parameter to the preupdate callback is the name of the -** table that is being modified. -** -** For an UPDATE or DELETE operation on a [rowid table], the sixth -** parameter passed to the preupdate callback is the initial [rowid] of the -** row being modified or deleted. For an INSERT operation on a rowid table, -** or any operation on a WITHOUT ROWID table, the value of the sixth -** parameter is undefined. For an INSERT or UPDATE on a rowid table the -** seventh parameter is the final rowid value of the row being inserted -** or updated. The value of the seventh parameter passed to the callback -** function is not defined for operations on WITHOUT ROWID tables, or for -** DELETE operations on rowid tables. -** -** ^The sqlite3_preupdate_hook(D,C,P) function returns the P argument from -** the previous call on the same [database connection] D, or NULL for -** the first call on D. -** -** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], -** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces -** provide additional information about a preupdate event. These routines -** may only be called from within a preupdate callback. Invoking any of -** these routines from outside of a preupdate callback or with a -** [database connection] pointer that is different from the one supplied -** to the preupdate callback results in undefined and probably undesirable -** behavior. -** -** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns -** in the row that is being inserted, updated, or deleted. -** -** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to -** a [protected sqlite3_value] that contains the value of the Nth column of -** the table row before it is updated. The N parameter must be between 0 -** and one less than the number of columns or the behavior will be -** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE -** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the -** behavior is undefined. The [sqlite3_value] that P points to -** will be destroyed when the preupdate callback returns. -** -** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to -** a [protected sqlite3_value] that contains the value of the Nth column of -** the table row after it is updated. The N parameter must be between 0 -** and one less than the number of columns or the behavior will be -** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE -** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the -** behavior is undefined. The [sqlite3_value] that P points to -** will be destroyed when the preupdate callback returns. -** -** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate -** callback was invoked as a result of a direct insert, update, or delete -** operation; or 1 for inserts, updates, or deletes invoked by top-level -** triggers; or 2 for changes resulting from triggers called by top-level -** triggers; and so forth. -** -** When the [sqlite3_blob_write()] API is used to update a blob column, -** the pre-update hook is invoked with SQLITE_DELETE, because -** the new values are not yet available. In this case, when a -** callback made with op==SQLITE_DELETE is actually a write using the -** sqlite3_blob_write() API, the [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, sqlite3_preupdate_blobwrite() returns -1. -** -** See also: [sqlite3_update_hook()] -*/ -#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) -SQLITE_API void *sqlite3_preupdate_hook( - sqlite3 *db, - void(*xPreUpdate)( - void *pCtx, /* Copy of third arg to preupdate_hook() */ - sqlite3 *db, /* Database handle */ - int op, /* SQLITE_UPDATE, DELETE or INSERT */ - char const *zDb, /* Database name */ - char const *zName, /* Table name */ - sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ - sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ - ), - void* -); -SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_count(sqlite3 *); -SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); -SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); -#endif - -/* -** CAPI3REF: Low-level system error code -** METHOD: sqlite3 -** -** ^Attempt to return the underlying operating system error code or error -** number that caused the most recent I/O error or failure to open a file. -** The return value is OS-dependent. For example, on unix systems, after -** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be -** called to get back the underlying "errno" that caused the problem, such -** as ENOSPC, EAUTH, EISDIR, and so forth. -*/ -SQLITE_API int sqlite3_system_errno(sqlite3*); - -/* -** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} {sqlite3_snapshot} -** -** An instance of the snapshot object records the state of a [WAL mode] -** database for some specific point in history. -** -** In [WAL mode], multiple [database connections] that are open on the -** same database file can each be reading a different historical version -** of the database file. When a [database connection] begins a read -** transaction, that connection sees an unchanging copy of the database -** as it existed for the point in time when the transaction first started. -** Subsequent changes to the database from other connections are not seen -** by the reader until a new read transaction is started. -** -** The sqlite3_snapshot object records state information about an historical -** version of the database file so that it is possible to later open a new read -** transaction that sees that historical version of the database rather than -** the most recent version. -*/ -typedef struct sqlite3_snapshot { - unsigned char hidden[48]; -} sqlite3_snapshot; - -/* -** CAPI3REF: Record A Database Snapshot -** CONSTRUCTOR: sqlite3_snapshot -** -** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a -** new [sqlite3_snapshot] object that records the current state of -** schema S in database connection D. ^On success, the -** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly -** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** If there is not already a read-transaction open on schema S when -** this function is called, one is opened automatically. -** -** If a read-transaction is opened by this function, then it is guaranteed -** that the returned snapshot object may not be invalidated by a database -** writer or checkpointer until after the read-transaction is closed. This -** is not guaranteed if a read-transaction is already open when this -** function is called. In that case, any subsequent write or checkpoint -** operation on the database may invalidate the returned snapshot handle, -** even while the read-transaction remains open. -** -** The following must be true for this function to succeed. If any of -** the following statements are false when sqlite3_snapshot_get() is -** called, SQLITE_ERROR is returned. The final value of *P is undefined -** in this case. -** -**
    -**
  • The database handle must not be in [autocommit mode]. -** -**
  • Schema S of [database connection] D must be a [WAL mode] database. -** -**
  • There must not be a write transaction open on schema S of database -** connection D. -** -**
  • One or more transactions must have been written to the current wal -** file since it was created on disk (by any connection). This means -** that a snapshot cannot be taken on a wal mode database with no wal -** file immediately after it is first opened. At least one transaction -** must be written to it first. -**
-** -** This function may also return SQLITE_NOMEM. If it is called with the -** database handle in autocommit mode but fails for some other reason, -** whether or not a read transaction is opened on schema S is undefined. -** -** The [sqlite3_snapshot] object returned from a successful call to -** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] -** to avoid a memory leak. -** -** The [sqlite3_snapshot_get()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot **ppSnapshot -); - -/* -** CAPI3REF: Start a read transaction on an historical snapshot -** METHOD: sqlite3_snapshot -** -** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read -** transaction or upgrades an existing one for schema S of -** [database connection] D such that the read transaction refers to -** historical [snapshot] P, rather than the most recent change to the -** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK -** on success or an appropriate [error code] if it fails. -** -** ^In order to succeed, the database connection must not be in -** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there -** is already a read transaction open on schema S, then the database handle -** must have no active statements (SELECT statements that have been passed -** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). -** SQLITE_ERROR is returned if either of these conditions is violated, or -** if schema S does not exist, or if the snapshot object is invalid. -** -** ^A call to sqlite3_snapshot_open() will fail to open if the specified -** snapshot has been overwritten by a [checkpoint]. In this case -** SQLITE_ERROR_SNAPSHOT is returned. -** -** If there is already a read transaction open when this function is -** invoked, then the same read transaction remains open (on the same -** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT -** is returned. If another error code - for example SQLITE_PROTOCOL or an -** SQLITE_IOERR error code - is returned, then the final state of the -** read transaction is undefined. If SQLITE_OK is returned, then the -** read transaction is now open on database snapshot P. -** -** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the -** database connection D does not know that the database file for -** schema S is in [WAL mode]. A database connection might not know -** that the database file is in [WAL mode] if there has been no prior -** I/O on that database connection, or if the database entered [WAL mode] -** after the most recent I/O on the database connection.)^ -** (Hint: Run "[PRAGMA application_id]" against a newly opened -** database connection in order to make it ready to use snapshots.) -** -** The [sqlite3_snapshot_open()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot *pSnapshot -); - -/* -** CAPI3REF: Destroy a snapshot -** DESTRUCTOR: sqlite3_snapshot -** -** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. -** The application must eventually free every [sqlite3_snapshot] object -** using this routine to avoid a memory leak. -** -** The [sqlite3_snapshot_free()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); - -/* -** CAPI3REF: Compare the ages of two snapshot handles. -** METHOD: sqlite3_snapshot -** -** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages -** of two valid snapshot handles. -** -** If the two snapshot handles are not associated with the same database -** file, the result of the comparison is undefined. -** -** Additionally, the result of the comparison is only valid if both of the -** snapshot handles were obtained by calling sqlite3_snapshot_get() since the -** last time the wal file was deleted. The wal file is deleted when the -** database is changed back to rollback mode or when the number of database -** clients drops to zero. If either snapshot handle was obtained before the -** wal file was last deleted, the value returned by this function -** is undefined. -** -** Otherwise, this API returns a negative value if P1 refers to an older -** snapshot than P2, zero if the two handles refer to the same database -** snapshot, and a positive value if P1 is a newer snapshot than P2. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( - sqlite3_snapshot *p1, - sqlite3_snapshot *p2 -); - -/* -** CAPI3REF: Recover snapshots from a wal file -** METHOD: sqlite3_snapshot -** -** If a [WAL file] remains on disk after all database connections close -** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] -** or because the last process to have the database opened exited without -** calling [sqlite3_close()]) and a new connection is subsequently opened -** on that database and [WAL file], the [sqlite3_snapshot_open()] interface -** will only be able to open the last transaction added to the WAL file -** even though the WAL file contains other valid transactions. -** -** This function attempts to scan the WAL file associated with database zDb -** of database handle db and make all valid snapshots available to -** sqlite3_snapshot_open(). It is an error if there is already a read -** transaction open on the database, or if the database is not a WAL mode -** database. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); - -/* -** CAPI3REF: Serialize a database -** -** The sqlite3_serialize(D,S,P,F) interface returns a pointer to -** memory that is a serialization of the S database on -** [database connection] D. If S is a NULL pointer, the main database is used. -** If P is not a NULL pointer, then the size of the database in bytes -** is written into *P. -** -** For an ordinary on-disk database file, the serialization is just a -** copy of the disk file. For an in-memory database or a "TEMP" database, -** the serialization is the same sequence of bytes which would be written -** to disk if that database were backed up to disk. -** -** The usual case is that sqlite3_serialize() copies the serialization of -** the database into memory obtained from [sqlite3_malloc64()] and returns -** a pointer to that memory. The caller is responsible for freeing the -** returned value to avoid a memory leak. However, if the F argument -** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations -** are made, and the sqlite3_serialize() function will return a pointer -** to the contiguous memory representation of the database that SQLite -** is currently using for that database, or NULL if no such contiguous -** memory representation of the database exists. A contiguous memory -** representation of the database will usually only exist if there has -** been a prior call to [sqlite3_deserialize(D,S,...)] with the same -** values of D and S. -** The size of the database is written into *P even if the -** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy -** of the database exists. -** -** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, -** the returned buffer content will remain accessible and unchanged -** until either the next write operation on the connection or when -** the connection is closed, and applications must not modify the -** buffer. If the bit had been clear, the returned buffer will not -** be accessed by SQLite after the call. -** -** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the -** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory -** allocation error occurs. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ - sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ - unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_serialize -** -** Zero or more of the following constants can be OR-ed together for -** the F argument to [sqlite3_serialize(D,S,P,F)]. -** -** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return -** a pointer to contiguous in-memory database that it is currently using, -** without making a copy of the database. If SQLite is not currently using -** a contiguous in-memory database, then this option causes -** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be -** using a contiguous in-memory database if it has been initialized by a -** prior call to [sqlite3_deserialize()]. -*/ -#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ - -/* -** CAPI3REF: Deserialize a database -** -** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the -** [database connection] D to disconnect from database S and then -** reopen S as an in-memory database based on the serialization contained -** in P. The serialized database P is N bytes in size. M is the size of -** the buffer P, which might be larger than N. If M is larger than N, and -** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is -** permitted to add content to the in-memory database as long as the total -** size does not exceed M bytes. -** -** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will -** invoke sqlite3_free() on the serialization buffer when the database -** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then -** SQLite will try to increase the buffer size using sqlite3_realloc64() -** if writes on the database cause it to grow larger than M bytes. -** -** Applications must not modify the buffer P or invalidate it before -** the database connection D is closed. -** -** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the -** database is currently in a read transaction or is involved in a backup -** operation. -** -** It is not possible to deserialize into the TEMP database. If the -** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the -** function returns SQLITE_ERROR. -** -** The deserialized database should not be in [WAL mode]. If the database -** is in WAL mode, then any attempt to use the database file will result -** in an [SQLITE_CANTOPEN] error. The application can set the -** [file format version numbers] (bytes 18 and 19) of the input database P -** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the -** database file into rollback mode and work around this limitation. -** -** If 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 -** [sqlite3_free()] is invoked on argument P prior to returning. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number of bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_deserialize() -** -** The following are allowed values for the 6th argument (the F argument) to -** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. -** -** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization -** in the P argument is held in memory obtained from [sqlite3_malloc64()] -** and that SQLite should take ownership of this memory and automatically -** free it when it has finished using it. Without this flag, the caller -** is responsible for freeing any dynamically allocated memory. -** -** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to -** grow the size of the database using calls to [sqlite3_realloc64()]. This -** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. -** Without this flag, the deserialized database cannot increase in size beyond -** the number of bytes specified by the M parameter. -** -** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database -** should be treated as read-only. -*/ -#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ -#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ -#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if defined(__wasi__) -# undef SQLITE_WASI -# define SQLITE_WASI 1 -# ifndef SQLITE_OMIT_LOAD_EXTENSION -# define SQLITE_OMIT_LOAD_EXTENSION -# endif -# ifndef SQLITE_THREADSAFE -# define SQLITE_THREADSAFE 0 -# endif -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -/* #endif for SQLITE3_H will be added by mksqlite3.tcl */ - -/******** Begin file sqlite3rtree.h *********/ -/* -** 2010 August 30 -** -** 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. -** -************************************************************************* -*/ - -#ifndef _SQLITE3RTREE_H_ -#define _SQLITE3RTREE_H_ - - -#if 0 -extern "C" { -#endif - -typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; -typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; - -/* The double-precision datatype used by RTree depends on the -** SQLITE_RTREE_INT_ONLY compile-time option. -*/ -#ifdef SQLITE_RTREE_INT_ONLY - typedef sqlite3_int64 sqlite3_rtree_dbl; -#else - typedef double sqlite3_rtree_dbl; -#endif - -/* -** Register a geometry callback named zGeom that can be used as part of an -** R-Tree geometry query as follows: -** -** SELECT ... FROM WHERE MATCH $zGeom(... params ...) -*/ -SQLITE_API int sqlite3_rtree_geometry_callback( - sqlite3 *db, - const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), - void *pContext -); - - -/* -** A pointer to a structure of the following type is passed as the first -** argument to callbacks registered using rtree_geometry_callback(). -*/ -struct sqlite3_rtree_geometry { - void *pContext; /* Copy of pContext passed to s_r_g_c() */ - int nParam; /* Size of array aParam[] */ - sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ - void *pUser; /* Callback implementation user data */ - void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ -}; - -/* -** Register a 2nd-generation geometry callback named zScore that can be -** used as part of an R-Tree geometry query as follows: -** -** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) -*/ -SQLITE_API int sqlite3_rtree_query_callback( - sqlite3 *db, - const char *zQueryFunc, - int (*xQueryFunc)(sqlite3_rtree_query_info*), - void *pContext, - void (*xDestructor)(void*) -); - - -/* -** A pointer to a structure of the following type is passed as the -** argument to scored geometry callback registered using -** sqlite3_rtree_query_callback(). -** -** Note that the first 5 fields of this structure are identical to -** sqlite3_rtree_geometry. This structure is a subclass of -** sqlite3_rtree_geometry. -*/ -struct sqlite3_rtree_query_info { - void *pContext; /* pContext from when function registered */ - int nParam; /* Number of function parameters */ - sqlite3_rtree_dbl *aParam; /* value of function parameters */ - void *pUser; /* callback can use this, if desired */ - void (*xDelUser)(void*); /* function to free pUser */ - sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ - unsigned int *anQueue; /* Number of pending entries in the queue */ - int nCoord; /* Number of coordinates */ - int iLevel; /* Level of current node or entry */ - int mxLevel; /* The largest iLevel value in the tree */ - sqlite3_int64 iRowid; /* Rowid for current entry */ - sqlite3_rtree_dbl rParentScore; /* Score of parent node */ - int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visibility */ - sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ - /* The following fields are only available in 3.8.11 and later */ - sqlite3_value **apSqlParam; /* Original SQL values of parameters */ -}; - -/* -** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. -*/ -#define NOT_WITHIN 0 /* Object completely outside of query region */ -#define PARTLY_WITHIN 1 /* Object partially overlaps query region */ -#define FULLY_WITHIN 2 /* Object fully contained within query region */ - - -#if 0 -} /* end of the 'extern "C"' block */ -#endif - -#endif /* ifndef _SQLITE3RTREE_H_ */ - -/******** End of sqlite3rtree.h *********/ -/******** Begin file sqlite3session.h *********/ - -#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) -#define __SQLITESESSION_H_ 1 - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** CAPI3REF: Session Object Handle -** -** An instance of this object is a [session] that can be used to -** record changes to a database. -*/ -typedef struct sqlite3_session sqlite3_session; - -/* -** CAPI3REF: Changeset Iterator Handle -** -** An instance of this object acts as a cursor for iterating -** over the elements of a [changeset] or [patchset]. -*/ -typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; - -/* -** CAPI3REF: Create A New Session Object -** CONSTRUCTOR: sqlite3_session -** -** Create a new session object attached to database handle db. If successful, -** a pointer to the new object is written to *ppSession and SQLITE_OK is -** returned. If an error occurs, *ppSession is set to NULL and an SQLite -** error code (e.g. SQLITE_NOMEM) is returned. -** -** It is possible to create multiple session objects attached to a single -** database handle. -** -** Session objects created using this function should be deleted using the -** [sqlite3session_delete()] function before the database handle that they -** are attached to is itself closed. If the database handle is closed before -** the session object is deleted, then the results of calling any session -** module function, including [sqlite3session_delete()] on the session object -** are undefined. -** -** Because the session module uses the [sqlite3_preupdate_hook()] API, it -** is not possible for an application to register a pre-update hook on a -** database handle that has one or more session objects attached. Nor is -** it possible to create a session object attached to a database handle for -** which a pre-update hook is already defined. The results of attempting -** either of these things are undefined. -** -** The session object will be used to create changesets for tables in -** database zDb, where zDb is either "main", or "temp", or the name of an -** attached database. It is not an error if database zDb is not attached -** to the database when the session object is created. -*/ -SQLITE_API int sqlite3session_create( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of db (e.g. "main") */ - sqlite3_session **ppSession /* OUT: New session object */ -); - -/* -** CAPI3REF: Delete A Session Object -** DESTRUCTOR: sqlite3_session -** -** Delete a session object previously allocated using -** [sqlite3session_create()]. Once a session object has been deleted, the -** results of attempting to use pSession with any other session module -** function are undefined. -** -** Session objects must be deleted before the database handle to which they -** are attached is closed. Refer to the documentation for -** [sqlite3session_create()] for details. -*/ -SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); - -/* -** CAPI3REF: Configure a Session Object -** METHOD: sqlite3_session -** -** This method is used to configure a session object after it has been -** created. At present the only valid values for the second parameter are -** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. -** -*/ -SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); - -/* -** CAPI3REF: Options for sqlite3session_object_config -** -** The following values may passed as the the 2nd parameter to -** sqlite3session_object_config(). -** -**
SQLITE_SESSION_OBJCONFIG_SIZE
-** This option is used to set, clear or query the flag that enables -** the [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 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 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_SESSION_OBJCONFIG_ROWID
-** This option is used to set, clear or query the flag that enables -** collection of data for tables with no explicit PRIMARY KEY. -** -** Normally, tables with no explicit PRIMARY KEY are simply ignored -** by the sessions module. However, if this flag is set, it behaves -** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted -** as their leftmost columns. -** -** It is an error (SQLITE_MISUSE) to attempt to modify this setting after -** the first table has been attached to the session object. -*/ -#define SQLITE_SESSION_OBJCONFIG_SIZE 1 -#define SQLITE_SESSION_OBJCONFIG_ROWID 2 - -/* -** CAPI3REF: Enable Or Disable A Session Object -** METHOD: sqlite3_session -** -** Enable or disable the recording of changes by a session object. When -** enabled, a session object records changes made to the database. When -** disabled - it does not. A newly created session object is enabled. -** Refer to the documentation for [sqlite3session_changeset()] for further -** details regarding how enabling and disabling a session object affects -** the eventual changesets. -** -** Passing zero to this function disables the session. Passing a value -** greater than zero enables it. Passing a value less than zero is a -** no-op, and may be used to query the current state of the session. -** -** The return value indicates the final state of the session object: 0 if -** the session is disabled, or 1 if it is enabled. -*/ -SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); - -/* -** CAPI3REF: Set Or Clear the Indirect Change Flag -** METHOD: sqlite3_session -** -** Each change recorded by a session object is marked as either direct or -** indirect. A change is marked as indirect if either: -** -**
    -**
  • The session object "indirect" flag is set when the change is -** made, or -**
  • The change is made by an SQL trigger or foreign key action -** instead of directly as a result of a users SQL statement. -**
-** -** If a single row is affected by more than one operation within a session, -** then the change is considered indirect if all operations meet the criteria -** for an indirect change above, or direct otherwise. -** -** This function is used to set, clear or query the session object indirect -** flag. If the second argument passed to this function is zero, then the -** indirect flag is cleared. If it is greater than zero, the indirect flag -** is set. Passing a value less than zero does not modify the current value -** of the indirect flag, and may be used to query the current state of the -** indirect flag for the specified session object. -** -** The return value indicates the final state of the indirect flag: 0 if -** it is clear, or 1 if it is set. -*/ -SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); - -/* -** CAPI3REF: Attach A Table To A Session Object -** METHOD: sqlite3_session -** -** If argument zTab is not NULL, then it is the name of a table to attach -** to the session object passed as the first argument. All subsequent changes -** made to the table while the session object is enabled will be recorded. See -** documentation for [sqlite3session_changeset()] for further details. -** -** Or, if argument zTab is NULL, then changes are recorded for all tables -** in the database. If additional tables are added to the database (by -** executing "CREATE TABLE" statements) after this call is made, changes for -** the new tables are also recorded. -** -** Changes can only be recorded for tables that have a PRIMARY KEY explicitly -** defined as part of their CREATE TABLE statement. It does not matter if the -** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY -** KEY may consist of a single column, or may be a composite key. -** -** It is not an error if the named table does not exist in the database. Nor -** is it an error if the named table does not have a PRIMARY KEY. However, -** no changes will be recorded in either of these scenarios. -** -** Changes are not recorded for individual rows that have NULL values stored -** in one or more of their PRIMARY KEY columns. -** -** SQLITE_OK is returned if the call completes without error. Or, if an error -** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. -** -**

Special sqlite_stat1 Handling

-** -** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to -** some of the rules above. In SQLite, the schema of sqlite_stat1 is: -**
-**        CREATE TABLE sqlite_stat1(tbl,idx,stat)
-**  
-** -** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are -** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes -** are recorded for rows for which (idx IS NULL) is true. However, for such -** rows a zero-length blob (SQL value X'') is stored in the changeset or -** patchset instead of a NULL value. This allows such changesets to be -** manipulated by legacy implementations of sqlite3changeset_invert(), -** concat() and similar. -** -** The sqlite3changeset_apply() function automatically converts the -** zero-length blob back to a NULL value when updating the sqlite_stat1 -** table. However, if the application calls sqlite3changeset_new(), -** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset -** iterator directly (including on a changeset iterator passed to a -** conflict-handler callback) then the X'' value is returned. The application -** must translate X'' to NULL itself if required. -** -** Legacy (older than 3.22.0) versions of the sessions module cannot capture -** changes made to the sqlite_stat1 table. Legacy versions of the -** sqlite3changeset_apply() function silently ignore any modifications to the -** sqlite_stat1 table that are part of a changeset or patchset. -*/ -SQLITE_API int sqlite3session_attach( - sqlite3_session *pSession, /* Session object */ - const char *zTab /* Table name */ -); - -/* -** CAPI3REF: Set a table filter on a Session Object. -** METHOD: sqlite3_session -** -** The second argument (xFilter) is the "filter callback". For changes to rows -** in tables that are not attached to the Session object, the filter is called -** to determine whether changes to the table's rows should be tracked or not. -** If xFilter returns 0, changes are not tracked. Note that once a table is -** attached, xFilter will not be called again. -*/ -SQLITE_API void sqlite3session_table_filter( - sqlite3_session *pSession, /* Session object */ - int(*xFilter)( - void *pCtx, /* Copy of third arg to _filter_table() */ - const char *zTab /* Table name */ - ), - void *pCtx /* First argument passed to xFilter */ -); - -/* -** CAPI3REF: Generate A Changeset From A Session Object -** METHOD: sqlite3_session -** -** Obtain a changeset containing changes to the tables attached to the -** session object passed as the first argument. If successful, -** set *ppChangeset to point to a buffer containing the changeset -** and *pnChangeset to the size of the changeset in bytes before returning -** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to -** zero and return an SQLite error code. -** -** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, -** each representing a change to a single row of an attached table. An INSERT -** change contains the values of each field of a new database row. A DELETE -** contains the original values of each field of a deleted database row. An -** UPDATE change contains the original values of each field of an updated -** database row along with the updated values for each updated non-primary-key -** column. It is not possible for an UPDATE change to represent a change that -** modifies the values of primary key columns. If such a change is made, it -** is represented in a changeset as a DELETE followed by an INSERT. -** -** Changes are not recorded for rows that have NULL values stored in one or -** more of their PRIMARY KEY columns. If such a row is inserted or deleted, -** no corresponding change is present in the changesets returned by this -** function. If an existing row with one or more NULL values stored in -** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, -** only an INSERT is appears in the changeset. Similarly, if an existing row -** with non-NULL PRIMARY KEY values is updated so that one or more of its -** PRIMARY KEY columns are set to NULL, the resulting changeset contains a -** DELETE change only. -** -** The contents of a changeset may be traversed using an iterator created -** using the [sqlite3changeset_start()] API. A changeset may be applied to -** a database with a compatible schema using the [sqlite3changeset_apply()] -** API. -** -** Within a changeset generated by this function, all changes related to a -** single table are grouped together. In other words, when iterating through -** a changeset or when applying a changeset to a database, all changes related -** to a single table are processed before moving on to the next table. Tables -** are sorted in the same order in which they were attached (or auto-attached) -** to the sqlite3_session object. The order in which the changes related to -** a single table are stored is undefined. -** -** Following a successful call to this function, it is the responsibility of -** the caller to eventually free the buffer that *ppChangeset points to using -** [sqlite3_free()]. -** -**

Changeset Generation

-** -** Once a table has been attached to a session object, the session object -** records the primary key values of all new rows inserted into the table. -** It also records the original primary key and other column values of any -** deleted or updated rows. For each unique primary key value, data is only -** recorded once - the first time a row with said primary key is inserted, -** updated or deleted in the lifetime of the session. -** -** There is one exception to the previous paragraph: when a row is inserted, -** updated or deleted, if one or more of its primary key columns contain a -** NULL value, no record of the change is made. -** -** The session object therefore accumulates two types of records - those -** that consist of primary key values only (created when the user inserts -** a new record) and those that consist of the primary key values and the -** original values of other table columns (created when the users deletes -** or updates a record). -** -** When this function is called, the requested changeset is created using -** both the accumulated records and the current contents of the database -** file. Specifically: -** -**
    -**
  • For each record generated by an insert, the database is queried -** for a row with a matching primary key. If one is found, an INSERT -** change is added to the changeset. If no such row is found, no change -** is added to the changeset. -** -**
  • For each record generated by an update or delete, the database is -** queried for a row with a matching primary key. If such a row is -** found and one or more of the non-primary key fields have been -** modified from their original values, an UPDATE change is added to -** the changeset. Or, if no such row is found in the table, a DELETE -** change is added to the changeset. If there is a row with a matching -** primary key in the database, but all fields contain their original -** values, no change is added to the changeset. -**
-** -** This means, amongst other things, that if a row is inserted and then later -** deleted while a session object is active, neither the insert nor the delete -** will be present in the changeset. Or if a row is deleted and then later a -** row with the same primary key values inserted while a session object is -** active, the resulting changeset will contain an UPDATE change instead of -** a DELETE and an INSERT. -** -** When a session object is disabled (see the [sqlite3session_enable()] API), -** it does not accumulate records when rows are inserted, updated or deleted. -** This may appear to have some counter-intuitive effects if a single row -** is written to more than once during a session. For example, if a row -** is inserted while a session object is enabled, then later deleted while -** the same session object is disabled, no INSERT record will appear in the -** changeset, even though the delete took place while the session was disabled. -** Or, if one field of a row is updated while a session is enabled, and -** then another field of the same row is updated while the session is disabled, -** the resulting changeset will contain an UPDATE change that updates both -** fields. -*/ -SQLITE_API int sqlite3session_changeset( - sqlite3_session *pSession, /* Session object */ - int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ - void **ppChangeset /* OUT: Buffer containing changeset */ -); - -/* -** CAPI3REF: Return An Upper-limit For The Size Of The Changeset -** METHOD: sqlite3_session -** -** By default, this function always returns 0. For it to return -** a useful result, the sqlite3_session object must have been configured -** to enable this API using 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 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 sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); - -/* -** CAPI3REF: Load The Difference Between Tables Into A Session -** METHOD: sqlite3_session -** -** If it is not already attached to the session object passed as the first -** argument, this function attaches table zTbl in the same manner as the -** [sqlite3session_attach()] function. If zTbl does not exist, or if it -** does not have a primary key, this function is a no-op (but does not return -** an error). -** -** Argument zFromDb must be the name of a database ("main", "temp" etc.) -** attached to the same database handle as the session object that contains -** a table compatible with the table attached to the session by this function. -** A table is considered compatible if it: -** -**
    -**
  • Has the same name, -**
  • Has the same set of columns declared in the same order, and -**
  • Has the same PRIMARY KEY definition. -**
-** -** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables -** are compatible but do not have any PRIMARY KEY columns, it is not an error -** but no changes are added to the session object. As with other session -** APIs, tables without PRIMARY KEYs are simply ignored. -** -** This function adds a set of changes to the session object that could be -** used to update the table in database zFrom (call this the "from-table") -** so that its content is the same as the table attached to the session -** object (call this the "to-table"). Specifically: -** -**
    -**
  • For each row (primary key) that exists in the to-table but not in -** the from-table, an INSERT record is added to the session object. -** -**
  • For each row (primary key) that exists in the to-table but not in -** the from-table, a DELETE record is added to the session object. -** -**
  • For each row (primary key) that exists in both tables, but features -** different non-PK values in each, an UPDATE record is added to the -** session. -**
-** -** To clarify, if this function is called and then a changeset constructed -** using [sqlite3session_changeset()], then after applying that changeset to -** database zFrom the contents of the two compatible tables would be -** identical. -** -** Unless the call to this function is a no-op as described above, it is an -** error if database zFrom does not exist or does not contain the required -** compatible table. -** -** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite -** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg -** may be set to point to a buffer containing an English language error -** message. It is the responsibility of the caller to free this buffer using -** sqlite3_free(). -*/ -SQLITE_API int sqlite3session_diff( - sqlite3_session *pSession, - const char *zFromDb, - const char *zTbl, - char **pzErrMsg -); - - -/* -** CAPI3REF: Generate A Patchset From A Session Object -** METHOD: sqlite3_session -** -** The differences between a patchset and a changeset are that: -** -**
    -**
  • DELETE records consist of the primary key fields only. The -** original values of other fields are omitted. -**
  • The original values of any modified fields are omitted from -** UPDATE records. -**
-** -** A patchset blob may be used with up to date versions of all -** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), -** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, -** attempting to use a patchset blob with old versions of the -** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. -** -** Because the non-primary key "old.*" fields are omitted, no -** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset -** is passed to the sqlite3changeset_apply() API. Other conflict types work -** in the same way as for changesets. -** -** Changes within a patchset are ordered in the same way as for changesets -** generated by the sqlite3session_changeset() function (i.e. all changes for -** a single table are grouped together, tables appear in the order in which -** they were attached to the session object). -*/ -SQLITE_API int sqlite3session_patchset( - sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ - void **ppPatchset /* OUT: Buffer containing patchset */ -); - -/* -** CAPI3REF: Test if a changeset has recorded any changes. -** -** Return non-zero if no changes to attached tables have been recorded by -** the session object passed as the first argument. Otherwise, if one or -** more changes have been recorded, return zero. -** -** Even if this function returns zero, it is possible that calling -** [sqlite3session_changeset()] on the session handle may still return a -** changeset that contains no changes. This can happen when a row in -** an attached table is modified and then later on the original values -** are restored. However, if this function returns non-zero, then it is -** guaranteed that a call to sqlite3session_changeset() will return a -** changeset containing zero changes. -*/ -SQLITE_API int sqlite3session_isempty(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 sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession); - -/* -** CAPI3REF: Create An Iterator To Traverse A Changeset -** CONSTRUCTOR: sqlite3_changeset_iter -** -** Create an iterator used to iterate through the contents of a changeset. -** If successful, *pp is set to point to the iterator handle and SQLITE_OK -** is returned. Otherwise, if an error occurs, *pp is set to zero and an -** SQLite error code is returned. -** -** The following functions can be used to advance and query a changeset -** iterator created by this function: -** -**
    -**
  • [sqlite3changeset_next()] -**
  • [sqlite3changeset_op()] -**
  • [sqlite3changeset_new()] -**
  • [sqlite3changeset_old()] -**
-** -** It is the responsibility of the caller to eventually destroy the iterator -** by passing it to [sqlite3changeset_finalize()]. The buffer containing the -** changeset (pChangeset) must remain valid until after the iterator is -** destroyed. -** -** Assuming the changeset blob was created by one of the -** [sqlite3session_changeset()], [sqlite3changeset_concat()] or -** [sqlite3changeset_invert()] functions, all changes within the changeset -** that apply to a single table are grouped together. This means that when -** an application iterates through a changeset using an iterator created by -** this function, all changes that relate to a single table are visited -** consecutively. There is no chance that the iterator will visit a change -** the applies to table X, then one for table Y, and then later on visit -** another change for table X. -** -** The behavior of sqlite3changeset_start_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. -** -** Note that the sqlite3changeset_start_v2() API is still experimental -** and therefore subject to change. -*/ -SQLITE_API int sqlite3changeset_start( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset /* Pointer to blob containing changeset */ -); -SQLITE_API int sqlite3changeset_start_v2( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset, /* Pointer to blob containing changeset */ - int flags /* SESSION_CHANGESETSTART_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_start_v2 -** -** The following flags may passed via the 4th parameter to -** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: -** -**
SQLITE_CHANGESETSTART_INVERT
-** Invert the changeset while iterating through it. This is equivalent to -** inverting a changeset using sqlite3changeset_invert() before applying it. -** It is an error to specify this flag with a patchset. -*/ -#define SQLITE_CHANGESETSTART_INVERT 0x0002 - - -/* -** CAPI3REF: Advance A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** This function may only be used with iterators created by the function -** [sqlite3changeset_start()]. If it is called on an iterator passed to -** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE -** is returned and the call has no effect. -** -** Immediately after an iterator is created by sqlite3changeset_start(), it -** does not point to any change in the changeset. Assuming the changeset -** is not empty, the first call to this function advances the iterator to -** point to the first change in the changeset. Each subsequent call advances -** the iterator to point to the next change in the changeset (if any). If -** no error occurs and the iterator points to a valid change after a call -** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. -** Otherwise, if all changes in the changeset have already been visited, -** SQLITE_DONE is returned. -** -** If an error occurs, an SQLite error code is returned. Possible error -** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or -** SQLITE_NOMEM. -*/ -SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); - -/* -** CAPI3REF: Obtain The Current Operation From A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** The pIter argument passed to this function may either be an iterator -** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator -** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this -** is not the case, this function returns [SQLITE_MISUSE]. -** -** 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 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 -** [sqlite3session_indirect()] for a description of direct and indirect -** 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 -** be trusted in this case. -*/ -SQLITE_API int sqlite3changeset_op( - sqlite3_changeset_iter *pIter, /* Iterator object */ - const char **pzTab, /* OUT: Pointer to table name */ - int *pnCol, /* OUT: Number of columns in table */ - int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ - int *pbIndirect /* OUT: True for an 'indirect' change */ -); - -/* -** CAPI3REF: Obtain The Primary Key Definition Of A Table -** METHOD: sqlite3_changeset_iter -** -** For each modified table, a changeset includes the following: -** -**
    -**
  • The number of columns in the table, and -**
  • Which of those columns make up the tables PRIMARY KEY. -**
-** -** This function is used to find which columns comprise the PRIMARY KEY of -** the table modified by the change that iterator pIter currently points to. -** If successful, *pabPK is set to point to an array of nCol entries, where -** nCol is the number of columns in the table. Elements of *pabPK are set to -** 0x01 if the corresponding column is part of the tables primary key, or -** 0x00 if it is not. -** -** If argument pnCol is not NULL, then *pnCol is set to the number of columns -** in the table. -** -** If this function is called when the iterator does not point to a valid -** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, -** SQLITE_OK is returned and the output variables populated as described -** above. -*/ -SQLITE_API int sqlite3changeset_pk( - sqlite3_changeset_iter *pIter, /* Iterator object */ - unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ - int *pnCol /* OUT: Number of entries in output array */ -); - -/* -** CAPI3REF: Obtain old.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** The pIter argument passed to this function may either be an iterator -** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator -** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. -** Furthermore, it may only be called if the type of change that the iterator -** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, -** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. -** -** Argument iVal must be greater than or equal to 0, and less than the number -** of columns in the table affected by the current change. Otherwise, -** [SQLITE_RANGE] is returned and *ppValue is set to NULL. -** -** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of -** original row values stored as part of the UPDATE or DELETE change and -** returns SQLITE_OK. The name of the function comes from the fact that this -** is similar to the "old.*" columns available to update or delete triggers. -** -** If some other error occurs (e.g. an OOM condition), an SQLite error code -** is returned and *ppValue is set to NULL. -*/ -SQLITE_API int sqlite3changeset_old( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ -); - -/* -** CAPI3REF: Obtain new.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** The pIter argument passed to this function may either be an iterator -** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator -** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. -** Furthermore, it may only be called if the type of change that the iterator -** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, -** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. -** -** Argument iVal must be greater than or equal to 0, and less than the number -** of columns in the table affected by the current change. Otherwise, -** [SQLITE_RANGE] is returned and *ppValue is set to NULL. -** -** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of -** new row values stored as part of the UPDATE or INSERT change and -** returns SQLITE_OK. If the change is an UPDATE and does not include -** a new value for the requested column, *ppValue is set to NULL and -** SQLITE_OK returned. The name of the function comes from the fact that -** this is similar to the "new.*" columns available to update or delete -** triggers. -** -** If some other error occurs (e.g. an OOM condition), an SQLite error code -** is returned and *ppValue is set to NULL. -*/ -SQLITE_API int sqlite3changeset_new( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ -); - -/* -** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** This function should only be used with iterator objects passed to a -** conflict-handler callback by [sqlite3changeset_apply()] with either -** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function -** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue -** is set to NULL. -** -** Argument iVal must be greater than or equal to 0, and less than the number -** of columns in the table affected by the current change. Otherwise, -** [SQLITE_RANGE] is returned and *ppValue is set to NULL. -** -** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the -** "conflicting row" associated with the current conflict-handler callback -** and returns SQLITE_OK. -** -** If some other error occurs (e.g. an OOM condition), an SQLite error code -** is returned and *ppValue is set to NULL. -*/ -SQLITE_API int sqlite3changeset_conflict( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: Value from conflicting row */ -); - -/* -** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations -** METHOD: sqlite3_changeset_iter -** -** This function may only be called with an iterator passed to an -** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case -** it sets the output variable to the total number of known foreign key -** violations in the destination database and returns SQLITE_OK. -** -** In all other cases this function returns SQLITE_MISUSE. -*/ -SQLITE_API int sqlite3changeset_fk_conflicts( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int *pnOut /* OUT: Number of FK violations */ -); - - -/* -** CAPI3REF: Finalize A Changeset Iterator -** METHOD: sqlite3_changeset_iter -** -** This function is used to finalize an iterator allocated with -** [sqlite3changeset_start()]. -** -** This function should only be called on iterators created using the -** [sqlite3changeset_start()] function. If an application calls this -** function with an iterator passed to a conflict-handler by -** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the -** call has no effect. -** -** If an error was encountered within a call to an sqlite3changeset_xxx() -** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an -** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding -** to that error is returned by this function. Otherwise, SQLITE_OK is -** returned. This is to allow the following pattern (pseudo-code): -** -**
-**   sqlite3changeset_start();
-**   while( SQLITE_ROW==sqlite3changeset_next() ){
-**     // Do something with change.
-**   }
-**   rc = sqlite3changeset_finalize();
-**   if( rc!=SQLITE_OK ){
-**     // An error has occurred
-**   }
-** 
-*/ -SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); - -/* -** CAPI3REF: Invert A Changeset -** -** This function is used to "invert" a changeset object. Applying an inverted -** changeset to a database reverses the effects of applying the uninverted -** changeset. Specifically: -** -**
    -**
  • Each DELETE change is changed to an INSERT, and -**
  • Each INSERT change is changed to a DELETE, and -**
  • For each UPDATE change, the old.* and new.* values are exchanged. -**
-** -** This function does not change the order in which changes appear within -** the changeset. It merely reverses the sense of each individual change. -** -** If successful, a pointer to a buffer containing the inverted changeset -** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and -** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are -** zeroed and an SQLite error code returned. -** -** It is the responsibility of the caller to eventually call sqlite3_free() -** on the *ppOut pointer to free the buffer allocation following a successful -** call to this function. -** -** WARNING/TODO: This function currently assumes that the input is a valid -** changeset. If it is not, the results are undefined. -*/ -SQLITE_API int sqlite3changeset_invert( - int nIn, const void *pIn, /* Input changeset */ - int *pnOut, void **ppOut /* OUT: Inverse of input */ -); - -/* -** CAPI3REF: Concatenate Two Changeset Objects -** -** This function is used to concatenate two changesets, A and B, into a -** single changeset. The result is a changeset equivalent to applying -** changeset A followed by changeset B. -** -** This function combines the two input changesets using an -** sqlite3_changegroup object. Calling it produces similar results as the -** following code fragment: -** -**
-**   sqlite3_changegroup *pGrp;
-**   rc = sqlite3_changegroup_new(&pGrp);
-**   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
-**   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
-**   if( rc==SQLITE_OK ){
-**     rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
-**   }else{
-**     *ppOut = 0;
-**     *pnOut = 0;
-**   }
-** 
-** -** Refer to the sqlite3_changegroup documentation below for details. -*/ -SQLITE_API int sqlite3changeset_concat( - int nA, /* Number of bytes in buffer pA */ - void *pA, /* Pointer to buffer containing changeset A */ - int nB, /* Number of bytes in buffer pB */ - void *pB, /* Pointer to buffer containing changeset B */ - int *pnOut, /* OUT: Number of bytes in output changeset */ - void **ppOut /* OUT: Buffer containing output changeset */ -); - -/* -** CAPI3REF: Changegroup Handle -** -** A changegroup is an object used to combine two or more -** [changesets] or [patchsets] -*/ -typedef struct sqlite3_changegroup sqlite3_changegroup; - -/* -** CAPI3REF: Create A New Changegroup Object -** CONSTRUCTOR: sqlite3_changegroup -** -** An sqlite3_changegroup object is used to combine two or more changesets -** (or patchsets) into a single changeset (or patchset). A single changegroup -** object may combine changesets or patchsets, but not both. The output is -** always in the same format as the input. -** -** If successful, this function returns SQLITE_OK and populates (*pp) with -** a pointer to a new sqlite3_changegroup object before returning. The caller -** should eventually free the returned object using a call to -** sqlite3changegroup_delete(). If an error occurs, an SQLite error code -** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. -** -** The usual usage pattern for an sqlite3_changegroup object is as follows: -** -**
    -**
  • It is created using a call to sqlite3changegroup_new(). -** -**
  • Zero or more changesets (or patchsets) are added to the object -** by calling sqlite3changegroup_add(). -** -**
  • The result of combining all input changesets together is obtained -** by the application via a call to sqlite3changegroup_output(). -** -**
  • The object is deleted using a call to sqlite3changegroup_delete(). -**
-** -** Any number of calls to add() and output() may be made between the calls to -** new() and delete(), and in any order. -** -** As well as the regular sqlite3changegroup_add() and -** sqlite3changegroup_output() functions, also available are the streaming -** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). -*/ -SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); - -/* -** CAPI3REF: Add a Schema to a Changegroup -** METHOD: sqlite3_changegroup_schema -** -** This method may be used to optionally enforce the rule that the changesets -** added to the changegroup handle must match the schema of database zDb -** ("main", "temp", or the name of an attached database). If -** sqlite3changegroup_add() is called to add a changeset that is not compatible -** with the configured schema, SQLITE_SCHEMA is returned and the changegroup -** object is left in an undefined state. -** -** A changeset schema is considered compatible with the database schema in -** the same way as for sqlite3changeset_apply(). Specifically, for each -** table in the changeset, there exists a database table with: -** -**
    -**
  • The name identified by the changeset, and -**
  • at least as many columns as recorded in the changeset, and -**
  • the primary key columns in the same position as recorded in -** the changeset. -**
-** -** The output of the changegroup object always has the same schema as the -** database nominated using this function. In cases where changesets passed -** to sqlite3changegroup_add() have fewer columns than the corresponding table -** in the database schema, these are filled in using the default column -** values from the database schema. This makes it possible to combined -** changesets that have different numbers of columns for a single table -** within a changegroup, provided that they are otherwise compatible. -*/ -SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb); - -/* -** CAPI3REF: Add A Changeset To A Changegroup -** METHOD: sqlite3_changegroup -** -** Add all changes within the changeset (or patchset) in buffer pData (size -** nData bytes) to the changegroup. -** -** If the buffer contains a patchset, then all prior calls to this function -** on the same changegroup object must also have specified patchsets. Or, if -** the buffer contains a changeset, so must have the earlier calls to this -** function. Otherwise, SQLITE_ERROR is returned and no changes are added -** to the changegroup. -** -** Rows within the changeset and changegroup are identified by the values in -** their PRIMARY KEY columns. A change in the changeset is considered to -** apply to the same row as a change already present in the changegroup if -** the two rows have the same primary key. -** -** Changes to rows that do not already appear in the changegroup are -** simply copied into it. Or, if both the new changeset and the changegroup -** contain changes that apply to a single row, the final contents of the -** changegroup depends on the type of each change, as follows: -** -** -** -** -**
Existing Change New Change Output Change -**
INSERT INSERT -** The new change is ignored. This case does not occur if the new -** changeset was recorded immediately after the changesets already -** added to the changegroup. -**
INSERT UPDATE -** The INSERT change remains in the changegroup. The values in the -** INSERT change are modified as if the row was inserted by the -** existing change and then updated according to the new change. -**
INSERT DELETE -** The existing INSERT is removed from the changegroup. The DELETE is -** not added. -**
UPDATE INSERT -** The new change is ignored. This case does not occur if the new -** changeset was recorded immediately after the changesets already -** added to the changegroup. -**
UPDATE UPDATE -** The existing UPDATE remains within the changegroup. It is amended -** so that the accompanying values are as if the row was updated once -** by the existing change and then again by the new change. -**
UPDATE DELETE -** The existing UPDATE is replaced by the new DELETE within the -** changegroup. -**
DELETE INSERT -** If one or more of the column values in the row inserted by the -** new change differ from those in the row deleted by the existing -** change, the existing DELETE is replaced by an UPDATE within the -** changegroup. Otherwise, if the inserted row is exactly the same -** as the deleted row, the existing DELETE is simply discarded. -**
DELETE UPDATE -** The new change is ignored. This case does not occur if the new -** changeset was recorded immediately after the changesets already -** added to the changegroup. -**
DELETE DELETE -** The new change is ignored. This case does not occur if the new -** changeset was recorded immediately after the changesets already -** added to the changegroup. -**
-** -** If the new changeset contains changes to a table that is already present -** in the changegroup, then the number of columns and the position of the -** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup -** object has been configured with a database schema using the -** sqlite3changegroup_schema() API, then it is possible to combine changesets -** with different numbers of columns for a single table, provided that -** they are otherwise compatible. -** -** If the input changeset appears to be corrupt and the corruption is -** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition -** occurs during processing, this function returns SQLITE_NOMEM. -** -** In all cases, if an error occurs the state of the final contents of the -** changegroup is undefined. If no error occurs, SQLITE_OK is returned. -*/ -SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); - -/* -** CAPI3REF: Add A Single Change To A Changegroup -** METHOD: sqlite3_changegroup -** -** This function adds the single change currently indicated by the iterator -** passed as the second argument to the changegroup object. The rules for -** adding the change are just as described for [sqlite3changegroup_add()]. -** -** If the change is successfully added to the changegroup, SQLITE_OK is -** returned. Otherwise, an SQLite error code is returned. -** -** The iterator must point to a valid entry when this function is called. -** If it does not, SQLITE_ERROR is returned and no change is added to the -** changegroup. Additionally, the iterator must not have been opened with -** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also -** returned. -*/ -SQLITE_API int sqlite3changegroup_add_change( - sqlite3_changegroup*, - sqlite3_changeset_iter* -); - - - -/* -** CAPI3REF: Obtain A Composite Changeset From A Changegroup -** METHOD: sqlite3_changegroup -** -** Obtain a buffer containing a changeset (or patchset) representing the -** current contents of the changegroup. If the inputs to the changegroup -** were themselves changesets, the output is a changeset. Or, if the -** inputs were patchsets, the output is also a patchset. -** -** As with the output of the sqlite3session_changeset() and -** sqlite3session_patchset() functions, all changes related to a single -** table are grouped together in the output of this function. Tables appear -** in the same order as for the very first changeset added to the changegroup. -** If the second or subsequent changesets added to the changegroup contain -** changes for tables that do not appear in the first changeset, they are -** appended onto the end of the output changeset, again in the order in -** which they are first encountered. -** -** If an error occurs, an SQLite error code is returned and the output -** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK -** is returned and the output variables are set to the size of and a -** pointer to the output buffer, respectively. In this case it is the -** responsibility of the caller to eventually free the buffer using a -** call to sqlite3_free(). -*/ -SQLITE_API int sqlite3changegroup_output( - sqlite3_changegroup*, - int *pnData, /* OUT: Size of output buffer in bytes */ - void **ppData /* OUT: Pointer to output buffer */ -); - -/* -** CAPI3REF: Delete A Changegroup Object -** DESTRUCTOR: sqlite3_changegroup -*/ -SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); - -/* -** CAPI3REF: Apply A Changeset To A Database -** -** Apply a changeset or patchset to a database. These functions attempt to -** update the "main" database attached to handle db with the changes found in -** the changeset passed via the second and third arguments. -** -** The fourth argument (xFilter) passed to these functions is the "filter -** callback". If it is not NULL, then for each table affected by at least one -** change in the changeset, the filter callback is invoked with -** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument as the first. If the "filter callback" -** returns zero, then no attempt is made to apply any changes to the table. -** Otherwise, if the return value is non-zero or the xFilter argument to -** is NULL, all changes related to the table are attempted. -** -** For each table that is not excluded by the filter callback, this function -** tests that the target database contains a compatible table. A table is -** considered compatible if all of the following are true: -** -**
    -**
  • The table has the same name as the name recorded in the -** changeset, and -**
  • The table has at least as many columns as recorded in the -** changeset, and -**
  • The table has primary key columns in the same position as -** recorded in the changeset. -**
-** -** If there is no compatible table, it is not an error, but none of the -** changes associated with the table are applied. A warning message is issued -** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most -** one such warning is issued for each table in the changeset. -** -** For each change for which there is a compatible table, an attempt is made -** to modify the table contents according to the UPDATE, INSERT or DELETE -** change. If a change cannot be applied cleanly, the conflict handler -** function passed as the fifth argument to sqlite3changeset_apply() may be -** invoked. A description of exactly when the conflict handler is invoked for -** each type of change is below. -** -** Unlike the xFilter argument, xConflict may not be passed NULL. The results -** of passing anything other than a valid function pointer as the xConflict -** argument are undefined. -** -** Each time the conflict handler function is invoked, it must return one -** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or -** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned -** if the second argument passed to the conflict handler is either -** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler -** returns an illegal value, any changes already made are rolled back and -** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different -** actions are taken by sqlite3changeset_apply() depending on the value -** returned by each invocation of the conflict-handler function. Refer to -** the documentation for the three -** [SQLITE_CHANGESET_OMIT|available return values] for details. -** -**
-**
DELETE Changes
-** For each DELETE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values -** stored in all non-primary key columns also match the values stored in -** the changeset the row is deleted from the target database. -** -** If a row with matching primary key values is found, but one or more of -** the non-primary key fields contains a value different from the original -** row value stored in the changeset, the conflict-handler function is -** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the -** database table has more columns than are recorded in the changeset, -** only the values of those non-primary key fields are compared against -** the current database contents - any trailing database table columns -** are ignored. -** -** If no row with matching primary key values is found in the database, -** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] -** passed as the second argument. -** -** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT -** (which can only happen if a foreign key constraint is violated), the -** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] -** passed as the second argument. This includes the case where the DELETE -** operation is attempted because an earlier call to the conflict handler -** function returned [SQLITE_CHANGESET_REPLACE]. -** -**
INSERT Changes
-** For each INSERT change, an attempt is made to insert the new row into -** the database. If the changeset row contains fewer fields than the -** database table, the trailing fields are populated with their default -** values. -** -** If the attempt to insert the row fails because the database already -** contains a row with the same primary key values, the conflict handler -** function is invoked with the second argument set to -** [SQLITE_CHANGESET_CONFLICT]. -** -** If the attempt to insert the row fails because of some other constraint -** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is -** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. -** This includes the case where the INSERT operation is re-attempted because -** an earlier call to the conflict handler function returned -** [SQLITE_CHANGESET_REPLACE]. -** -**
UPDATE Changes
-** For each UPDATE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values -** stored in all modified non-primary key columns also match the values -** stored in the changeset the row is updated within the target database. -** -** If a row with matching primary key values is found, but one or more of -** the modified non-primary key fields contains a value different from an -** original row value stored in the changeset, the conflict-handler function -** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since -** UPDATE changes only contain values for non-primary key fields that are -** to be modified, only those fields need to match the original values to -** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. -** -** If no row with matching primary key values is found in the database, -** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] -** passed as the second argument. -** -** If the UPDATE operation is attempted, but SQLite returns -** SQLITE_CONSTRAINT, the conflict-handler function is invoked with -** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. -** This includes the case where the UPDATE operation is attempted after -** an earlier call to the conflict handler function returned -** [SQLITE_CHANGESET_REPLACE]. -**
-** -** It is safe to execute SQL statements, including those that write to the -** table that the callback related to, from within the xConflict callback. -** This can be used to further customize the application's conflict -** resolution strategy. -** -** All changes made by these functions are enclosed in a savepoint transaction. -** If any other error (aside from a constraint failure when attempting to -** write to the target database) occurs, then the savepoint transaction is -** rolled back, restoring the target database to its original state, and an -** SQLite error code returned. -** -** If the output parameters (ppRebase) and (pnRebase) are non-NULL and -** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() -** may set (*ppRebase) to point to a "rebase" that may be used with the -** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) -** is set to the size of the buffer in bytes. It is the responsibility of the -** caller to eventually free any such buffer using sqlite3_free(). The buffer -** is only allocated and populated if one or more conflicts were encountered -** while applying the patchset. See comments surrounding the sqlite3_rebaser -** APIs for further details. -** -** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. -** -** Note that the sqlite3changeset_apply_v2() API is still experimental -** and therefore subject to change. -*/ -SQLITE_API int sqlite3changeset_apply( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx /* First argument passed to xConflict */ -); -SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_apply_v2 -** -** The following flags may passed via the 9th parameter to -** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: -** -**
-**
SQLITE_CHANGESETAPPLY_NOSAVEPOINT
-** Usually, the sessions module encloses all operations performed by -** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The -** SAVEPOINT is committed if the changeset or patchset is successfully -** applied, or rolled back if an error occurs. Specifying this flag -** causes the sessions module to omit this savepoint. In this case, if the -** caller has an open transaction or savepoint when apply_v2() is called, -** it may revert the partially applied changeset by rolling it back. -** -**
SQLITE_CHANGESETAPPLY_INVERT
-** Invert the changeset before applying it. This is equivalent to inverting -** a changeset using sqlite3changeset_invert() before applying it. It is -** an error to specify this flag with a patchset. -** -**
SQLITE_CHANGESETAPPLY_IGNORENOOP
-** Do not invoke the conflict handler callback for any changes that -** would not actually modify the database even if they were applied. -** Specifically, this means that the conflict handler is not invoked -** for: -**
    -**
  • a delete change if the row being deleted cannot be found, -**
  • an update change if the modified fields are already set to -** their new values in the conflicting row, or -**
  • an insert change if all fields of the conflicting row match -** the row being inserted. -**
-** -**
SQLITE_CHANGESETAPPLY_FKNOACTION
-** If this flag it set, then all foreign key constraints in the target -** database behave as if they were declared with "ON UPDATE NO ACTION ON -** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL -** or SET DEFAULT. -*/ -#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 -#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 -#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 -#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 - -/* -** CAPI3REF: Constants Passed To The Conflict Handler -** -** Values that may be passed as the second argument to a conflict-handler. -** -**
-**
SQLITE_CHANGESET_DATA
-** The conflict handler is invoked with CHANGESET_DATA as the second argument -** when processing a DELETE or UPDATE change if a row with the required -** PRIMARY KEY fields is present in the database, but one or more other -** (non primary-key) fields modified by the update do not contain the -** expected "before" values. -** -** The conflicting row, in this case, is the database row with the matching -** primary key. -** -**
SQLITE_CHANGESET_NOTFOUND
-** The conflict handler is invoked with CHANGESET_NOTFOUND as the second -** argument when processing a DELETE or UPDATE change if a row with the -** required PRIMARY KEY fields is not present in the database. -** -** There is no conflicting row in this case. The results of invoking the -** sqlite3changeset_conflict() API are undefined. -** -**
SQLITE_CHANGESET_CONFLICT
-** CHANGESET_CONFLICT is passed as the second argument to the conflict -** handler while processing an INSERT change if the operation would result -** in duplicate primary key values. -** -** The conflicting row in this case is the database row with the matching -** primary key. -** -**
SQLITE_CHANGESET_FOREIGN_KEY
-** If foreign key handling is enabled, and applying a changeset leaves the -** database in a state containing foreign key violations, the conflict -** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument -** exactly once before the changeset is committed. If the conflict handler -** returns CHANGESET_OMIT, the changes, including those that caused the -** foreign key constraint violation, are committed. Or, if it returns -** CHANGESET_ABORT, the changeset is rolled back. -** -** No current or conflicting row information is provided. The only function -** it is possible to call on the supplied sqlite3_changeset_iter handle -** is sqlite3changeset_fk_conflicts(). -** -**
SQLITE_CHANGESET_CONSTRAINT
-** If any other constraint violation occurs while applying a change (i.e. -** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is -** invoked with CHANGESET_CONSTRAINT as the second argument. -** -** There is no conflicting row in this case. The results of invoking the -** sqlite3changeset_conflict() API are undefined. -** -**
-*/ -#define SQLITE_CHANGESET_DATA 1 -#define SQLITE_CHANGESET_NOTFOUND 2 -#define SQLITE_CHANGESET_CONFLICT 3 -#define SQLITE_CHANGESET_CONSTRAINT 4 -#define SQLITE_CHANGESET_FOREIGN_KEY 5 - -/* -** CAPI3REF: Constants Returned By The Conflict Handler -** -** A conflict handler callback must return one of the following three values. -** -**
-**
SQLITE_CHANGESET_OMIT
-** If a conflict handler returns this value no special action is taken. The -** change that caused the conflict is not applied. The session module -** continues to the next change in the changeset. -** -**
SQLITE_CHANGESET_REPLACE
-** This value may only be returned if the second argument to the conflict -** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this -** is not the case, any changes applied so far are rolled back and the -** call to sqlite3changeset_apply() returns SQLITE_MISUSE. -** -** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict -** handler, then the conflicting row is either updated or deleted, depending -** on the type of change. -** -** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict -** handler, then the conflicting row is removed from the database and a -** second attempt to apply the change is made. If this second attempt fails, -** the original row is restored to the database before continuing. -** -**
SQLITE_CHANGESET_ABORT
-** If this value is returned, any changes applied so far are rolled back -** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. -**
-*/ -#define SQLITE_CHANGESET_OMIT 0 -#define SQLITE_CHANGESET_REPLACE 1 -#define SQLITE_CHANGESET_ABORT 2 - -/* -** CAPI3REF: Rebasing changesets -** EXPERIMENTAL -** -** Suppose there is a site hosting a database in state S0. And that -** modifications are made that move that database to state S1 and a -** changeset recorded (the "local" changeset). Then, a changeset based -** on S0 is received from another site (the "remote" changeset) and -** applied to the database. The database is then in state -** (S1+"remote"), where the exact state depends on any conflict -** resolution decisions (OMIT or REPLACE) made while applying "remote". -** Rebasing a changeset is to update it to take those conflict -** resolution decisions into account, so that the same conflicts -** do not have to be resolved elsewhere in the network. -** -** For example, if both the local and remote changesets contain an -** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": -** -** local: INSERT INTO t1 VALUES(1, 'v1'); -** remote: INSERT INTO t1 VALUES(1, 'v2'); -** -** and the conflict resolution is REPLACE, then the INSERT change is -** removed from the local changeset (it was overridden). Or, if the -** conflict resolution was "OMIT", then the local changeset is modified -** to instead contain: -** -** UPDATE t1 SET b = 'v2' WHERE a=1; -** -** Changes within the local changeset are rebased as follows: -** -**
-**
Local INSERT
-** This may only conflict with a remote INSERT. If the conflict -** resolution was OMIT, then add an UPDATE change to the rebased -** changeset. Or, if the conflict resolution was REPLACE, add -** nothing to the rebased changeset. -** -**
Local DELETE
-** This may conflict with a remote UPDATE or DELETE. In both cases the -** only possible resolution is OMIT. If the remote operation was a -** DELETE, then add no change to the rebased changeset. If the remote -** operation was an UPDATE, then the old.* fields of change are updated -** to reflect the new.* values in the UPDATE. -** -**
Local UPDATE
-** This may conflict with a remote UPDATE or DELETE. If it conflicts -** with a DELETE, and the conflict resolution was OMIT, then the update -** is changed into an INSERT. Any undefined values in the new.* record -** from the update change are filled in using the old.* values from -** the conflicting DELETE. Or, if the conflict resolution was REPLACE, -** the UPDATE change is simply omitted from the rebased changeset. -** -** If conflict is with a remote UPDATE and the resolution is OMIT, then -** the old.* values are rebased using the new.* values in the remote -** change. Or, if the resolution is REPLACE, then the change is copied -** into the rebased changeset with updates to columns also updated by -** the conflicting remote UPDATE removed. If this means no columns would -** be updated, the change is omitted. -**
-** -** A local change may be rebased against multiple remote changes -** simultaneously. If a single key is modified by multiple remote -** changesets, they are combined as follows before the local changeset -** is rebased: -** -**
    -**
  • If there has been one or more REPLACE resolutions on a -** key, it is rebased according to a REPLACE. -** -**
  • If there have been no REPLACE resolutions on a key, then -** the local changeset is rebased according to the most recent -** of the OMIT resolutions. -**
-** -** Note that conflict resolutions from multiple remote changesets are -** combined on a per-field basis, not per-row. This means that in the -** case of multiple remote UPDATE operations, some fields of a single -** local change may be rebased for REPLACE while others are rebased for -** OMIT. -** -** In order to rebase a local changeset, the remote changeset must first -** be applied to the local database using sqlite3changeset_apply_v2() and -** the buffer of rebase information captured. Then: -** -**
    -**
  1. An sqlite3_rebaser object is created by calling -** sqlite3rebaser_create(). -**
  2. The new object is configured with the rebase buffer obtained from -** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). -** If the local changeset is to be rebased against multiple remote -** changesets, then sqlite3rebaser_configure() should be called -** multiple times, in the same order that the multiple -** sqlite3changeset_apply_v2() calls were made. -**
  3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). -**
  4. The sqlite3_rebaser object is deleted by calling -** sqlite3rebaser_delete(). -**
-*/ -typedef struct sqlite3_rebaser sqlite3_rebaser; - -/* -** CAPI3REF: Create a changeset rebaser object. -** EXPERIMENTAL -** -** Allocate a new changeset rebaser object. If successful, set (*ppNew) to -** point to the new object and return SQLITE_OK. Otherwise, if an error -** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) -** to NULL. -*/ -SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); - -/* -** CAPI3REF: Configure a changeset rebaser object. -** EXPERIMENTAL -** -** Configure the changeset rebaser object to rebase changesets according -** to the conflict resolutions described by buffer pRebase (size nRebase -** bytes), which must have been obtained from a previous call to -** sqlite3changeset_apply_v2(). -*/ -SQLITE_API int sqlite3rebaser_configure( - sqlite3_rebaser*, - int nRebase, const void *pRebase -); - -/* -** CAPI3REF: Rebase a changeset -** EXPERIMENTAL -** -** Argument pIn must point to a buffer containing a changeset nIn bytes -** in size. This function allocates and populates a buffer with a copy -** of the changeset rebased according to the configuration of the -** rebaser object passed as the first argument. If successful, (*ppOut) -** is set to point to the new buffer containing the rebased changeset and -** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the -** responsibility of the caller to eventually free the new buffer using -** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) -** are set to zero and an SQLite error code returned. -*/ -SQLITE_API int sqlite3rebaser_rebase( - sqlite3_rebaser*, - int nIn, const void *pIn, - int *pnOut, void **ppOut -); - -/* -** CAPI3REF: Delete a changeset rebaser object. -** EXPERIMENTAL -** -** Delete the changeset rebaser object and all associated resources. There -** should be one call to this function for each successful invocation -** of sqlite3rebaser_create(). -*/ -SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); - -/* -** CAPI3REF: Streaming Versions of API functions. -** -** The six streaming API xxx_strm() functions serve similar purposes to the -** corresponding non-streaming API functions: -** -** -** -**
Streaming functionNon-streaming equivalent
sqlite3changeset_apply_strm[sqlite3changeset_apply] -**
sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] -**
sqlite3changeset_concat_strm[sqlite3changeset_concat] -**
sqlite3changeset_invert_strm[sqlite3changeset_invert] -**
sqlite3changeset_start_strm[sqlite3changeset_start] -**
sqlite3session_changeset_strm[sqlite3session_changeset] -**
sqlite3session_patchset_strm[sqlite3session_patchset] -**
-** -** Non-streaming functions that accept changesets (or patchsets) as input -** require that the entire changeset be stored in a single buffer in memory. -** Similarly, those that return a changeset or patchset do so by returning -** a pointer to a single large buffer allocated using sqlite3_malloc(). -** Normally this is convenient. However, if an application running in a -** low-memory environment is required to handle very large changesets, the -** large contiguous memory allocations required can become onerous. -** -** In order to avoid this problem, instead of a single large buffer, input -** is passed to a streaming API functions by way of a callback function that -** the sessions module invokes to incrementally request input data as it is -** required. In all cases, a pair of API function parameters such as -** -**
-**        int nChangeset,
-**        void *pChangeset,
-**  
-** -** Is replaced by: -** -**
-**        int (*xInput)(void *pIn, void *pData, int *pnData),
-**        void *pIn,
-**  
-** -** Each time the xInput callback is invoked by the sessions module, the first -** argument passed is a copy of the supplied pIn context pointer. The second -** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no -** error occurs the xInput method should copy up to (*pnData) bytes of data -** into the buffer and set (*pnData) to the actual number of bytes copied -** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) -** should be set to zero to indicate this. Or, if an error occurs, an SQLite -** error code should be returned. In all cases, if an xInput callback returns -** an error, all processing is abandoned and the streaming API function -** returns a copy of the error code to the caller. -** -** In the case of sqlite3changeset_start_strm(), the xInput callback may be -** invoked by the sessions module at any point during the lifetime of the -** iterator. If such an xInput callback returns an error, the iterator enters -** an error state, whereby all subsequent calls to iterator functions -** immediately fail with the same error code as returned by xInput. -** -** Similarly, streaming API functions that return changesets (or patchsets) -** return them in chunks by way of a callback function instead of via a -** pointer to a single large buffer. In this case, a pair of parameters such -** as: -** -**
-**        int *pnChangeset,
-**        void **ppChangeset,
-**  
-** -** Is replaced by: -** -**
-**        int (*xOutput)(void *pOut, const void *pData, int nData),
-**        void *pOut
-**  
-** -** The xOutput callback is invoked zero or more times to return data to -** the application. The first parameter passed to each call is a copy of the -** pOut pointer supplied by the application. The second parameter, pData, -** points to a buffer nData bytes in size containing the chunk of output -** data being returned. If the xOutput callback successfully processes the -** supplied data, it should return SQLITE_OK to indicate success. Otherwise, -** it should return some other SQLite error code. In this case processing -** is immediately abandoned and the streaming API function returns a copy -** of the xOutput error code to the application. -** -** The sessions module never invokes an xOutput callback with the third -** parameter set to a value less than or equal to zero. Other than this, -** no guarantees are made as to the size of the chunks of data returned. -*/ -SQLITE_API int sqlite3changeset_apply_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx /* First argument passed to xConflict */ -); -SQLITE_API int sqlite3changeset_apply_v2_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -); -SQLITE_API int sqlite3changeset_concat_strm( - int (*xInputA)(void *pIn, void *pData, int *pnData), - void *pInA, - int (*xInputB)(void *pIn, void *pData, int *pnData), - void *pInB, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3changeset_invert_strm( - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3changeset_start_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn -); -SQLITE_API int sqlite3changeset_start_v2_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int flags -); -SQLITE_API int sqlite3session_changeset_strm( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3session_patchset_strm( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn -); -SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3rebaser_rebase_strm( - sqlite3_rebaser *pRebaser, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - -/* -** CAPI3REF: Configure global parameters -** -** The sqlite3session_config() interface is used to make global configuration -** changes to the sessions module in order to tune it to the specific needs -** of the application. -** -** The sqlite3session_config() interface is not threadsafe. If it is invoked -** while any other thread is inside any other sessions method then the -** results are undefined. Furthermore, if it is invoked after any sessions -** related objects have been created, the results are also undefined. -** -** The first argument to the sqlite3session_config() function must be one -** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The -** interpretation of the (void*) value passed as the second parameter and -** the effect of calling this function depends on the value of the first -** parameter. -** -**
-**
SQLITE_SESSION_CONFIG_STRMSIZE
-** By default, the sessions module streaming interfaces attempt to input -** and output data in approximately 1 KiB chunks. This operand may be used -** to set and query the value of this configuration setting. The pointer -** passed as the second argument must point to a value of type (int). -** If this value is greater than 0, it is used as the new streaming data -** chunk size for both input and output. Before returning, the (int) value -** pointed to by pArg is set to the final value of the streaming interface -** chunk size. -**
-** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -SQLITE_API int sqlite3session_config(int op, void *pArg); - -/* -** CAPI3REF: Values for sqlite3session_config(). -*/ -#define SQLITE_SESSION_CONFIG_STRMSIZE 1 - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -} -#endif - -#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ - -/******** End of sqlite3session.h *********/ -/******** Begin file fts5.h *********/ -/* -** 2014 May 31 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** Interfaces to extend FTS5. Using the interfaces defined in this file, -** FTS5 may be extended with: -** -** * custom tokenizers, and -** * custom auxiliary functions. -*/ - - -#ifndef _FTS5_H -#define _FTS5_H - - -#if 0 -extern "C" { -#endif - -/************************************************************************* -** CUSTOM AUXILIARY FUNCTIONS -** -** Virtual table implementations may overload SQL functions by implementing -** the sqlite3_module.xFindFunction() method. -*/ - -typedef struct Fts5ExtensionApi Fts5ExtensionApi; -typedef struct Fts5Context Fts5Context; -typedef struct Fts5PhraseIter Fts5PhraseIter; - -typedef void (*fts5_extension_function)( - const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ - Fts5Context *pFts, /* First arg to pass to pApi functions */ - sqlite3_context *pCtx, /* Context for returning result/error */ - int nVal, /* Number of values in apVal[] array */ - sqlite3_value **apVal /* Array of trailing arguments */ -); - -struct Fts5PhraseIter { - const unsigned char *a; - const unsigned char *b; -}; - -/* -** EXTENSION API FUNCTIONS -** -** xUserData(pFts): -** Return a copy of the pUserData pointer passed to the xCreateFunction() -** API when the extension function was registered. -** -** xColumnTotalSize(pFts, iCol, pnToken): -** If parameter iCol is less than zero, set output variable *pnToken -** to the total number of tokens in the FTS5 table. Or, if iCol is -** non-negative but less than the number of columns in the table, return -** the total number of tokens in column iCol, considering all rows in -** the FTS5 table. -** -** If parameter iCol is greater than or equal to the number of columns -** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is -** returned. -** -** xColumnCount(pFts): -** Return the number of columns in the table. -** -** xColumnSize(pFts, iCol, pnToken): -** If parameter iCol is less than zero, set output variable *pnToken -** to the total number of tokens in the current row. Or, if iCol is -** non-negative but less than the number of columns in the table, set -** *pnToken to the number of tokens in column iCol of the current row. -** -** If parameter iCol is greater than or equal to the number of columns -** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is -** returned. -** -** This function may be quite inefficient if used with an FTS5 table -** created with the "columnsize=0" option. -** -** xColumnText: -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the text of column iCol of -** the current document. If successful, (*pz) is set to point to a buffer -** containing the text in utf-8 encoding, (*pn) is set to the size in bytes -** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, -** if an error occurs, an SQLite error code is returned and the final values -** of (*pz) and (*pn) are undefined. -** -** xPhraseCount: -** Returns the number of phrases in the current query expression. -** -** xPhraseSize: -** If parameter iCol is less than zero, or greater than or equal to the -** number of phrases in the current query, as returned by xPhraseCount, -** 0 is returned. Otherwise, this function returns the number of tokens in -** phrase iPhrase of the query. Phrases are numbered starting from zero. -** -** xInstCount: -** Set *pnInst to the total number of occurrences of all phrases within -** the query within the current row. Return SQLITE_OK if successful, or -** an error code (i.e. SQLITE_NOMEM) if an error occurs. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option -** (i.e. if it is a contentless table), then this API always returns 0. -** -** xInst: -** Query for the details of phrase match iIdx within the current row. -** Phrase matches are numbered starting from zero, so the iIdx argument -** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). If iIdx is less than zero or greater than -** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. -** -** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol -** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. SQLITE_OK is returned if successful, or an -** error code (i.e. SQLITE_NOMEM) if an error occurs. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. -** -** xRowid: -** Returns the rowid of the current row. -** -** xTokenize: -** Tokenize text using the tokenizer belonging to the FTS5 table. -** -** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): -** This API function is used to query the FTS table for phrase iPhrase -** of the current query. Specifically, a query equivalent to: -** -** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid -** -** with $p set to a phrase equivalent to the phrase iPhrase of the -** current query is executed. Any column filter that applies to -** phrase iPhrase of the current query is included in $p. For each -** row visited, the callback function passed as the fourth argument -** is invoked. The context and API objects passed to the callback -** function may be used to access the properties of each matched row. -** Invoking Api.xUserData() returns a copy of the pointer passed as -** the third argument to pUserData. -** -** If parameter iPhrase is less than zero, or greater than or equal to -** the number of phrases in the query, as returned by xPhraseCount(), -** this function returns SQLITE_RANGE. -** -** If the callback function returns any value other than SQLITE_OK, the -** query is abandoned and the xQueryPhrase function returns immediately. -** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. -** Otherwise, the error code is propagated upwards. -** -** If the query runs to completion without incident, SQLITE_OK is returned. -** Or, if some error occurs before the query completes or is aborted by -** the callback, an SQLite error code is returned. -** -** -** xSetAuxdata(pFts5, pAux, xDelete) -** -** Save the pointer passed as the second argument as the extension function's -** "auxiliary data". The pointer may then be retrieved by the current or any -** future invocation of the same fts5 extension function made as part of -** the same MATCH query using the xGetAuxdata() API. -** -** Each extension function is allocated a single auxiliary data slot for -** each FTS query (MATCH expression). If the extension function is invoked -** more than once for a single FTS query, then all invocations share a -** single auxiliary data context. -** -** If there is already an auxiliary data pointer when this function is -** invoked, then it is replaced by the new pointer. If an xDelete callback -** was specified along with the original pointer, it is invoked at this -** point. -** -** The xDelete callback, if one is specified, is also invoked on the -** auxiliary data pointer after the FTS5 query has finished. -** -** If an error (e.g. an OOM condition) occurs within this function, -** the auxiliary data is set to NULL and an error code returned. If the -** xDelete parameter was not NULL, it is invoked on the auxiliary data -** pointer before returning. -** -** -** xGetAuxdata(pFts5, bClear) -** -** Returns the current auxiliary data pointer for the fts5 extension -** function. See the xSetAuxdata() method for details. -** -** If the bClear argument is non-zero, then the auxiliary data is cleared -** (set to NULL) before this function returns. In this case the xDelete, -** if any, is not invoked. -** -** -** xRowCount(pFts5, pnRow) -** -** This function is used to retrieve the total number of rows in the table. -** In other words, the same value that would be returned by: -** -** SELECT count(*) FROM ftstable; -** -** xPhraseFirst() -** This function is used, along with type Fts5PhraseIter and the xPhraseNext -** method, to iterate through all instances of a single query phrase within -** the current row. This is the same information as is accessible via the -** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -** to use, this API may be faster under some circumstances. To iterate -** through instances of phrase iPhrase, use the following code: -** -** Fts5PhraseIter iter; -** int iCol, iOff; -** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); -** iCol>=0; -** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) -** ){ -** // An instance of phrase iPhrase at offset iOff of column iCol -** } -** -** The Fts5PhraseIter structure is defined above. Applications should not -** modify this structure directly - it should only be used as shown above -** with the xPhraseFirst() and xPhraseNext() API methods (and by -** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option -** (i.e. if it is a contentless table), then this API always iterates -** through an empty set (all calls to xPhraseFirst() set iCol to -1). -** -** In all cases, matches are visited in (column ASC, offset ASC) order. -** i.e. all those in column 0, sorted by offset, followed by those in -** column 1, etc. -** -** xPhraseNext() -** See xPhraseFirst above. -** -** xPhraseFirstColumn() -** This function and xPhraseNextColumn() are similar to the xPhraseFirst() -** and xPhraseNext() APIs described above. The difference is that instead -** of iterating through all instances of a phrase in the current row, these -** APIs are used to iterate through the set of columns in the current row -** that contain one or more instances of a specified phrase. For example: -** -** Fts5PhraseIter iter; -** int iCol; -** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); -** iCol>=0; -** pApi->xPhraseNextColumn(pFts, &iter, &iCol) -** ){ -** // Column iCol contains at least one instance of phrase iPhrase -** } -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" option. If the FTS5 table is created with either -** "detail=none" "content=" option (i.e. if it is a contentless table), -** then this API always iterates through an empty set (all calls to -** xPhraseFirstColumn() set iCol to -1). -** -** The information accessed using this API and its companion -** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext -** (or xInst/xInstCount). The chief advantage of this API is that it is -** significantly more efficient than those alternatives when used with -** "detail=column" tables. -** -** xPhraseNextColumn() -** See xPhraseFirstColumn above. -** -** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase iPhrase of the current -** query. Before returning, output parameter *ppToken is set to point -** to a buffer containing the requested token, and *pnToken to the -** size of this buffer in bytes. -** -** If iPhrase or iToken are less than zero, or if iPhrase is greater than -** or equal to the number of phrases in the query as reported by -** xPhraseCount(), or if iToken is equal to or greater than the number of -** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken - are both zeroed. -** -** The output text is not a copy of the query text that specified the -** token. It is the output of the tokenizer module. For tokendata=1 -** tables, this includes any embedded 0x00 and trailing data. -** -** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase hit iIdx within the -** current row. If iIdx is less than zero or greater than or equal to the -** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, -** output variable (*ppToken) is set to point to a buffer containing the -** matching document token, and (*pnToken) to the size of that buffer in -** bytes. -** -** The output text is not a copy of the document text that was tokenized. -** It is the output of the tokenizer module. For tokendata=1 tables, this -** includes any embedded 0x00 and trailing data. -** -** This API may be slow in some cases if the token identified by parameters -** iIdx and iToken matched a prefix token in the query. In most cases, the -** first call to this API for each prefix token in the query is forced -** to scan the portion of the full-text index that matches the prefix -** token to collect the extra data required by this API. If the prefix -** token matches a large number of token instances in the document set, -** this may be a performance problem. -** -** If the user knows in advance that a query may use this API for a -** prefix token, FTS5 may be configured to collect all required data as part -** of the initial querying of the full-text index, avoiding the second scan -** entirely. This also causes prefix queries that do not use this API to -** run more slowly and use more memory. FTS5 may be configured in this way -** either on a per-table basis using the [FTS5 insttoken | 'insttoken'] -** option, or on a per-query basis using the -** [fts5_insttoken | fts5_insttoken()] user function. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. -** -** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale) -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the locale associated -** with column iCol of the current row. Usually, there is no associated -** locale, and output parameters (*pzLocale) and (*pnLocale) are set -** to NULL and 0, respectively. However, if the fts5_locale() function -** was used to associate a locale with the value when it was inserted -** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated -** buffer containing the name of the locale in utf-8 encoding. (*pnLocale) -** is set to the size in bytes of the buffer, not including the -** nul-terminator. -** -** If successful, SQLITE_OK is returned. Or, if an error occurs, an -** SQLite error code is returned. The final value of the output parameters -** is undefined in this case. -** -** xTokenize_v2: -** Tokenize text using the tokenizer belonging to the FTS5 table. This -** API is the same as the xTokenize() API, except that it allows a tokenizer -** locale to be specified. -*/ -struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 4 */ - - void *(*xUserData)(Fts5Context*); - - int (*xColumnCount)(Fts5Context*); - int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); - int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - - int (*xTokenize)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); - - int (*xPhraseCount)(Fts5Context*); - int (*xPhraseSize)(Fts5Context*, int iPhrase); - - int (*xInstCount)(Fts5Context*, int *pnInst); - int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); - - sqlite3_int64 (*xRowid)(Fts5Context*); - int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); - - int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, - int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) - ); - int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); - void *(*xGetAuxdata)(Fts5Context*, int bClear); - - int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); - void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); - - int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); - void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); - - /* Below this point are iVersion>=3 only */ - int (*xQueryToken)(Fts5Context*, - int iPhrase, int iToken, - const char **ppToken, int *pnToken - ); - int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); - - /* Below this point are iVersion>=4 only */ - int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xTokenize_v2)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - const char *pLocale, int nLocale, /* Locale to pass to tokenizer */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); -}; - -/* -** CUSTOM AUXILIARY FUNCTIONS -*************************************************************************/ - -/************************************************************************* -** CUSTOM TOKENIZERS -** -** Applications may also register custom tokenizer types. A tokenizer -** is registered by providing fts5 with a populated instance of the -** following structure. All structure methods must be defined, setting -** any member of the fts5_tokenizer struct to NULL leads to undefined -** behaviour. The structure methods are expected to function as follows: -** -** xCreate: -** This function is used to allocate and initialize a tokenizer instance. -** A tokenizer instance is required to actually tokenize text. -** -** The first argument passed to this function is a copy of the (void*) -** pointer provided by the application when the fts5_tokenizer_v2 object -** was registered with FTS5 (the third argument to xCreateTokenizer()). -** The second and third arguments are an array of nul-terminated strings -** containing the tokenizer arguments, if any, specified following the -** tokenizer name as part of the CREATE VIRTUAL TABLE statement used -** to create the FTS5 table. -** -** The final argument is an output variable. If successful, (*ppOut) -** should be set to point to the new tokenizer handle and SQLITE_OK -** returned. If an error occurs, some value other than SQLITE_OK should -** be returned. In this case, fts5 assumes that the final value of *ppOut -** is undefined. -** -** xDelete: -** This function is invoked to delete a tokenizer handle previously -** allocated using xCreate(). Fts5 guarantees that this function will -** be invoked exactly once for each successful call to xCreate(). -** -** xTokenize: -** This function is expected to tokenize the nText byte string indicated -** by argument pText. pText may or may not be nul-terminated. The first -** argument passed to this function is a pointer to an Fts5Tokenizer object -** returned by an earlier call to xCreate(). -** -** The third argument indicates the reason that FTS5 is requesting -** tokenization of the supplied text. This is always one of the following -** four values: -** -**
  • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into -** or removed from the FTS table. The tokenizer is being invoked to -** determine the set of tokens to add to (or delete from) the -** FTS index. -** -**
  • FTS5_TOKENIZE_QUERY - A MATCH query is being executed -** against the FTS index. The tokenizer is being called to tokenize -** a bareword or quoted string specified as part of the query. -** -**
  • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as -** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is -** followed by a "*" character, indicating that the last token -** returned by the tokenizer will be treated as a token prefix. -** -**
  • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to -** satisfy an fts5_api.xTokenize() request made by an auxiliary -** function. Or an fts5_api.xColumnSize() request made by the same -** on a columnsize=0 database. -**
-** -** The sixth and seventh arguments passed to xTokenize() - pLocale and -** nLocale - are a pointer to a buffer containing the locale to use for -** tokenization (e.g. "en_US") and its size in bytes, respectively. The -** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in -** which case nLocale is always 0) to indicate that the tokenizer should -** use its default locale. -** -** For each token in the input string, the supplied callback xToken() must -** be invoked. The first argument to it should be a copy of the pointer -** passed as the second argument to xTokenize(). The third and fourth -** arguments are a pointer to a buffer containing the token text, and the -** size of the token in bytes. The 4th and 5th arguments are the byte offsets -** of the first byte of and first byte immediately following the text from -** which the token is derived within the input. -** -** The second argument passed to the xToken() callback ("tflags") should -** normally be set to 0. The exception is if the tokenizer supports -** synonyms. In this case see the discussion below for details. -** -** FTS5 assumes the xToken() callback is invoked for each token in the -** order that they occur within the input text. -** -** If an xToken() callback returns any value other than SQLITE_OK, then -** the tokenization should be abandoned and the xTokenize() method should -** immediately return a copy of the xToken() return value. Or, if the -** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, -** if an error occurs with the xTokenize() implementation itself, it -** may abandon the tokenization and return any error code other than -** SQLITE_OK or SQLITE_DONE. -** -** If the tokenizer is registered using an fts5_tokenizer_v2 object, -** then the xTokenize() method has two additional arguments - pLocale -** and nLocale. These specify the locale that the tokenizer should use -** for the current request. If pLocale and nLocale are both 0, then the -** tokenizer should use its default locale. Otherwise, pLocale points to -** an nLocale byte buffer containing the name of the locale to use as utf-8 -** text. pLocale is not nul-terminated. -** -** FTS5_TOKENIZER -** -** There is also an fts5_tokenizer object. This is an older, deprecated, -** version of fts5_tokenizer_v2. It is similar except that: -** -**
    -**
  • There is no "iVersion" field, and -**
  • The xTokenize() method does not take a locale argument. -**
-** -** Legacy fts5_tokenizer tokenizers must be registered using the -** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2(). -** -** Tokenizer implementations registered using either API may be retrieved -** using both xFindTokenizer() and xFindTokenizer_v2(). -** -** SYNONYM SUPPORT -** -** Custom tokenizers may also support synonyms. Consider a case in which a -** user wishes to query for a phrase such as "first place". Using the -** built-in tokenizers, the FTS5 query 'first + place' will match instances -** of "first place" within the document set, but not alternative forms -** such as "1st place". In some applications, it would be better to match -** all instances of "first place" or "1st place" regardless of which form -** the user specified in the MATCH query text. -** -** There are several ways to approach this in FTS5: -** -**
  1. By mapping all synonyms to a single token. In this case, using -** the above example, this means that the tokenizer returns the -** same token for inputs "first" and "1st". Say that token is in -** fact "first", so that when the user inserts the document "I won -** 1st place" entries are added to the index for tokens "i", "won", -** "first" and "place". If the user then queries for '1st + place', -** the tokenizer substitutes "first" for "1st" and the query works -** as expected. -** -**
  2. By querying the index for all synonyms of each query term -** separately. In this case, when tokenizing query text, the -** tokenizer may provide multiple synonyms for a single term -** within the document. FTS5 then queries the index for each -** synonym individually. For example, faced with the query: -** -** -** ... MATCH 'first place' -** -** the tokenizer offers both "1st" and "first" as synonyms for the -** first token in the MATCH query and FTS5 effectively runs a query -** similar to: -** -** -** ... MATCH '(first OR 1st) place' -** -** except that, for the purposes of auxiliary functions, the query -** still appears to contain just two phrases - "(first OR 1st)" -** being treated as a single phrase. -** -**
  3. By adding multiple synonyms for a single term to the FTS index. -** Using this method, when tokenizing document text, the tokenizer -** provides multiple synonyms for each token. So that when a -** document such as "I won first place" is tokenized, entries are -** added to the FTS index for "i", "won", "first", "1st" and -** "place". -** -** This way, even if the tokenizer does not provide synonyms -** when tokenizing query text (it should not - to do so would be -** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entries in the -** FTS index corresponding to both forms of the first token. -**
-** -** Whether it is parsing document or query text, any call to xToken that -** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit -** is considered to supply a synonym for the previous token. For example, -** when parsing the document "I won first place", a tokenizer that supports -** synonyms would call xToken() 5 times, as follows: -** -** -** xToken(pCtx, 0, "i", 1, 0, 1); -** xToken(pCtx, 0, "won", 3, 2, 5); -** xToken(pCtx, 0, "first", 5, 6, 11); -** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11); -** xToken(pCtx, 0, "place", 5, 12, 17); -** -** -** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time -** xToken() is called. Multiple synonyms may be specified for a single token -** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. -** There is no limit to the number of synonyms that may be provided for a -** single token. -** -** In many cases, method (1) above is the best approach. It does not add -** extra data to the FTS index or require FTS5 to query for multiple terms, -** so it is efficient in terms of disk space and query speed. However, it -** does not support prefix queries very well. If, as suggested above, the -** token "first" is substituted for "1st" by the tokenizer, then the query: -** -** -** ... MATCH '1s*' -** -** will not match documents that contain the token "1st" (as the tokenizer -** will probably not map "1s" to any prefix of "first"). -** -** For full prefix support, method (3) may be preferred. In this case, -** because the index contains entries for both "first" and "1st", prefix -** queries such as 'fi*' or '1s*' will match correctly. However, because -** extra entries are added to the FTS index, this method uses more space -** within the database. -** -** Method (2) offers a midpoint between (1) and (3). Using this method, -** a query such as '1s*' will match documents that contain the literal -** token "1st", but not "first" (assuming the tokenizer is not able to -** provide synonyms for prefixes). However, a non-prefix query like '1st' -** will match against "1st" and "first". This method does not require -** extra disk space, as no extra entries are added to the FTS index. -** On the other hand, it may require more CPU cycles to run MATCH queries, -** as separate queries of the FTS index are required for each synonym. -** -** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (3)) or query -** text (method (2)), not both. Doing so will not cause any errors, but is -** inefficient. -*/ -typedef struct Fts5Tokenizer Fts5Tokenizer; -typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2; -struct fts5_tokenizer_v2 { - int iVersion; /* Currently always 2 */ - - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - const char *pLocale, int nLocale, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - -/* -** New code should use the fts5_tokenizer_v2 type to define tokenizer -** implementations. The following type is included for legacy applications -** that still use it. -*/ -typedef struct fts5_tokenizer fts5_tokenizer; -struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - - -/* Flags that may be passed as the third argument to xTokenize() */ -#define FTS5_TOKENIZE_QUERY 0x0001 -#define FTS5_TOKENIZE_PREFIX 0x0002 -#define FTS5_TOKENIZE_DOCUMENT 0x0004 -#define FTS5_TOKENIZE_AUX 0x0008 - -/* Flags that may be passed by the tokenizer implementation back to FTS5 -** as the third argument to the supplied xToken callback. */ -#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */ - -/* -** END OF CUSTOM TOKENIZERS -*************************************************************************/ - -/************************************************************************* -** FTS5 EXTENSION REGISTRATION API -*/ -typedef struct fts5_api fts5_api; -struct fts5_api { - int iVersion; /* Currently always set to 3 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_tokenizer *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer)( - fts5_api *pApi, - const char *zName, - void **ppUserData, - fts5_tokenizer *pTokenizer - ); - - /* Create a new auxiliary function */ - int (*xCreateFunction)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_extension_function xFunction, - void (*xDestroy)(void*) - ); - - /* APIs below this point are only available if iVersion>=3 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_tokenizer_v2 *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void **ppUserData, - fts5_tokenizer_v2 **ppTokenizer - ); -}; - -/* -** END OF REGISTRATION API -*************************************************************************/ - -#if 0 -} /* end of the 'extern "C"' block */ -#endif - -#endif /* _FTS5_H */ - -/******** End of fts5.h *********/ -#endif /* SQLITE3_H */ - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* -** Reuse the STATIC_LRU for mutex access to 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 "sqlite_cfg.h" -#define SQLITECONFIG_H 1 -#endif - -/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ -/************** Begin file sqliteLimit.h *************************************/ -/* -** 2007 May 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file defines various limits of what SQLite can process. -*/ - -/* -** The maximum length of a TEXT or BLOB in bytes. This also -** limits the size of a row in a table or index. -** -** The hard limit is the ability of a 32-bit signed integer -** to count the size: 2^31-1 or 2147483647. -*/ -#ifndef SQLITE_MAX_LENGTH -# define SQLITE_MAX_LENGTH 1000000000 -#endif -#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */ - -/* -** This is the maximum number of -** -** * Columns in a table -** * Columns in an index -** * Columns in a view -** * Terms in the SET clause of an UPDATE statement -** * Terms in the result set of a SELECT statement -** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. -** * Terms in the VALUES clause of an INSERT statement -** -** The hard upper limit here is 32767. Most database people will -** tell you that in a well-normalized database, you usually should -** not have more than a dozen or so columns in any table. And if -** that is the case, there is no point in having more than a few -** dozen values in any of the other situations described above. -** -** An index can only have SQLITE_MAX_COLUMN columns from the user -** point of view, but the underlying b-tree that implements the index -** might have up to twice as many columns in a WITHOUT ROWID table, -** since must also store the primary key at the end. Hence the -** column count for Index is u16 instead of i16. -*/ -#if !defined(SQLITE_MAX_COLUMN) -# define SQLITE_MAX_COLUMN 2000 -#elif SQLITE_MAX_COLUMN>32767 -# error SQLITE_MAX_COLUMN may not exceed 32767 -#endif - -/* -** The maximum length of a single SQL statement in bytes. -** -** It used to be the case that setting this value to zero would -** turn the limit off. That is no longer true. It is not possible -** to turn this limit off. -*/ -#ifndef SQLITE_MAX_SQL_LENGTH -# define SQLITE_MAX_SQL_LENGTH 1000000000 -#endif - -/* -** The maximum depth of an expression tree. This is limited to -** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might -** want to place more severe limits on the complexity of an -** expression. A value of 0 means that there is no limit. -*/ -#ifndef SQLITE_MAX_EXPR_DEPTH -# define SQLITE_MAX_EXPR_DEPTH 1000 -#endif - -/* -** The maximum number of terms in a compound SELECT statement. -** The code generator for compound SELECT statements does one -** level of recursion for each term. A stack overflow can result -** if the number of terms is too large. In practice, most SQL -** never has more than 3 or 4 terms. Use a value of 0 to disable -** any limit on the number of terms in a compound SELECT. -*/ -#ifndef SQLITE_MAX_COMPOUND_SELECT -# define SQLITE_MAX_COMPOUND_SELECT 500 -#endif - -/* -** The maximum number of opcodes in a VDBE program. -** Not currently enforced. -*/ -#ifndef SQLITE_MAX_VDBE_OP -# define SQLITE_MAX_VDBE_OP 250000000 -#endif - -/* -** The maximum number of arguments to an SQL function. -** -** This value has a hard upper limit of 32767 due to storage -** constraints (it needs to fit inside a i16). We keep it -** lower than that to prevent abuse. -*/ -#ifndef SQLITE_MAX_FUNCTION_ARG -# define SQLITE_MAX_FUNCTION_ARG 1000 -#endif - -/* -** The suggested maximum number of in-memory pages to use for -** the main database table and for temporary tables. -** -** IMPLEMENTATION-OF: R-30185-15359 The default suggested cache size is -2000, -** which means the cache size is limited to 2048000 bytes of memory. -** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be -** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. -*/ -#ifndef SQLITE_DEFAULT_CACHE_SIZE -# define SQLITE_DEFAULT_CACHE_SIZE -2000 -#endif - -/* -** The default number of frames to accumulate in the log file before -** checkpointing the database in WAL mode. -*/ -#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT -# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 -#endif - -/* -** The maximum number of attached databases. This must be between 0 -** and 125. The upper bound of 125 is because the attached databases are -** counted using a signed 8-bit integer which has a maximum value of 127 -** and we have to allow 2 extra counts for the "main" and "temp" databases. -*/ -#ifndef SQLITE_MAX_ATTACHED -# define SQLITE_MAX_ATTACHED 10 -#endif - - -/* -** The maximum value of a ?nnn wildcard that the parser will accept. -** If the value exceeds 32767 then extra space is required for the Expr -** structure. But otherwise, we believe that the number can be as large -** as a signed 32-bit integer can hold. -*/ -#ifndef SQLITE_MAX_VARIABLE_NUMBER -# define SQLITE_MAX_VARIABLE_NUMBER 32766 -#endif - -/* Maximum page size. The upper bound on this value is 65536. This a limit -** imposed by the use of 16-bit offsets within each page. -** -** Earlier versions of SQLite allowed the user to change this value at -** compile time. This is no longer permitted, on the grounds that it creates -** a library that is technically incompatible with an SQLite library -** compiled with a different limit. If a process operating on a database -** with a page-size of 65536 bytes crashes, then an instance of SQLite -** compiled with the default page-size limit will not be able to rollback -** the aborted transaction. This could lead to database corruption. -*/ -#ifdef SQLITE_MAX_PAGE_SIZE -# undef SQLITE_MAX_PAGE_SIZE -#endif -#define SQLITE_MAX_PAGE_SIZE 65536 - - -/* -** The default size of a database page. -*/ -#ifndef SQLITE_DEFAULT_PAGE_SIZE -# define SQLITE_DEFAULT_PAGE_SIZE 4096 -#endif -#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE -# undef SQLITE_DEFAULT_PAGE_SIZE -# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE -#endif - -/* -** Ordinarily, if no value is explicitly provided, SQLite creates databases -** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain -** device characteristics (sector-size and atomic write() support), -** SQLite may choose a larger value. This constant is the maximum value -** SQLite will choose on its own. -*/ -#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE -# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 -#endif -#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE -# undef SQLITE_MAX_DEFAULT_PAGE_SIZE -# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE -#endif - - -/* -** Maximum number of pages in one database file. -** -** This is really just the default value for the max_page_count pragma. -** This value can be lowered (or raised) at run-time using that the -** max_page_count macro. -*/ -#ifndef SQLITE_MAX_PAGE_COUNT -# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */ -#endif - -/* -** Maximum length (in bytes) of the pattern in a LIKE or GLOB -** operator. -*/ -#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH -# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 -#endif - -/* -** Maximum depth of recursion for triggers. -** -** A value of 1 means that a trigger program will not be able to itself -** fire any triggers. A value of 0 means that no trigger programs at all -** may be executed. -*/ -#ifndef SQLITE_MAX_TRIGGER_DEPTH -# define SQLITE_MAX_TRIGGER_DEPTH 1000 -#endif - -/************** End of sqliteLimit.h *****************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* Disable nuisance warnings on Borland compilers */ -#if defined(__BORLANDC__) -#pragma warn -rch /* unreachable code */ -#pragma warn -ccc /* Condition is always true or false */ -#pragma warn -aus /* Assigned value is never used */ -#pragma warn -csu /* Comparing signed and unsigned */ -#pragma warn -spa /* Suspicious pointer arithmetic */ -#endif - -/* -** A few places in the code require atomic load/store of aligned -** integer values. -*/ -#ifndef __has_extension -# 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 - -/* -** Include standard header files as necessary -*/ -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif - -/* -** The following macros are used to cast pointers to integers and -** integers to pointers. The way you do this varies from one compiler -** to the next, so we have developed the following set of #if statements -** to generate appropriate macros for a wide range of compilers. -** -** The correct "ANSI" way to do this is to use the intptr_t type. -** Unfortunately, that typedef is not available on all compilers, or -** if it is available, it requires an #include of specific headers -** that vary from one machine to the next. -** -** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on -** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). -** So we have to define the macros in different ways depending on the -** compiler. -*/ -#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ -# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) -#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ -# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) -#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ -# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) -# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) -#else /* Generates a warning - but it always works */ -# define SQLITE_INT_TO_PTR(X) ((void*)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(X)) -#endif - -/* -** Macros to hint to the compiler that a function should or should not be -** inlined. -*/ -#if defined(__GNUC__) -# define SQLITE_NOINLINE __attribute__((noinline)) -# define SQLITE_INLINE __attribute__((always_inline)) inline -#elif defined(_MSC_VER) && _MSC_VER>=1310 -# define SQLITE_NOINLINE __declspec(noinline) -# define SQLITE_INLINE __forceinline -#else -# define SQLITE_NOINLINE -# define SQLITE_INLINE -#endif -#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__) -# undef SQLITE_INLINE -# define SQLITE_INLINE -#endif - -/* -** Make sure that the compiler intrinsics we desire are enabled when -** compiling with an appropriate version of MSVC unless prevented by -** the SQLITE_DISABLE_INTRINSIC define. -*/ -#if !defined(SQLITE_DISABLE_INTRINSIC) -# if defined(_MSC_VER) && _MSC_VER>=1400 -# if !defined(_WIN32_WCE) -# include -# pragma intrinsic(_byteswap_ushort) -# pragma intrinsic(_byteswap_ulong) -# pragma intrinsic(_byteswap_uint64) -# pragma intrinsic(_ReadWriteBarrier) -# else -# include -# endif -# endif -#endif - -/* -** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit -** SEH support if the -DSQLITE_OMIT_SEH option is given. -*/ -#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH) -# define SQLITE_USE_SEH 1 -#else -# undef SQLITE_USE_SEH -#endif - -/* -** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly -** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0 -*/ -#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1 - /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */ -# undef SQLITE_DIRECT_OVERFLOW_READ -#else - /* In all other cases, enable */ -# define SQLITE_DIRECT_OVERFLOW_READ 1 -#endif - - -/* -** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. -** 0 means mutexes are permanently disable and the library is never -** threadsafe. 1 means the library is serialized which is the highest -** level of threadsafety. 2 means the library is multithreaded - multiple -** threads can use SQLite as long as no two threads try to use the same -** database connection at the same time. -** -** Older versions of SQLite used an optional THREADSAFE macro. -** We support that for legacy. -** -** To ensure that the correct value of "THREADSAFE" is reported when querying -** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this -** logic is partially replicated in ctime.c. If it is updated here, it should -** also be updated there. -*/ -#if !defined(SQLITE_THREADSAFE) -# if defined(THREADSAFE) -# define SQLITE_THREADSAFE THREADSAFE -# else -# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ -# endif -#endif - -/* -** Powersafe overwrite is on by default. But can be turned off using -** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. -*/ -#ifndef SQLITE_POWERSAFE_OVERWRITE -# define SQLITE_POWERSAFE_OVERWRITE 1 -#endif - -/* -** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by -** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in -** which case memory allocation statistics are disabled by default. -*/ -#if !defined(SQLITE_DEFAULT_MEMSTATUS) -# define SQLITE_DEFAULT_MEMSTATUS 1 -#endif - -/* -** Exactly one of the following macros must be defined in order to -** specify which memory allocation subsystem to use. -** -** SQLITE_SYSTEM_MALLOC // Use normal system malloc() -** SQLITE_WIN32_MALLOC // Use Win32 native heap API -** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails -** SQLITE_MEMDEBUG // Debugging version of system malloc() -** -** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the -** assert() macro is enabled, each call into the Win32 native heap subsystem -** will cause HeapValidate to be called. If heap validation should fail, an -** assertion will be triggered. -** -** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as -** the default. -*/ -#if defined(SQLITE_SYSTEM_MALLOC) \ - + defined(SQLITE_WIN32_MALLOC) \ - + defined(SQLITE_ZERO_MALLOC) \ - + defined(SQLITE_MEMDEBUG)>1 -# error "Two or more of the following compile-time configuration options\ - are defined but at most one is allowed:\ - SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ - SQLITE_ZERO_MALLOC" -#endif -#if defined(SQLITE_SYSTEM_MALLOC) \ - + defined(SQLITE_WIN32_MALLOC) \ - + defined(SQLITE_ZERO_MALLOC) \ - + defined(SQLITE_MEMDEBUG)==0 -# define SQLITE_SYSTEM_MALLOC 1 -#endif - -/* -** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the -** sizes of memory allocations below this value where possible. -*/ -#if !defined(SQLITE_MALLOC_SOFT_LIMIT) -# define SQLITE_MALLOC_SOFT_LIMIT 1024 -#endif - -/* -** We need to define _XOPEN_SOURCE as follows in order to enable -** recursive mutexes on most Unix systems and fchmod() on OpenBSD. -** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit -** it. -*/ -#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) -# define _XOPEN_SOURCE 600 -#endif - -/* -** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that -** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, -** make it true by defining or undefining NDEBUG. -** -** Setting NDEBUG makes the code smaller and faster by disabling the -** assert() statements in the code. So we want the default action -** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG -** is set. Thus NDEBUG becomes an opt-in rather than an opt-out -** feature. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif -#if defined(NDEBUG) && defined(SQLITE_DEBUG) -# undef NDEBUG -#endif - -/* -** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on. -*/ -#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG) -# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1 -#endif - -/* -** The testcase() macro is used to aid in coverage testing. When -** doing coverage testing, the condition inside the argument to -** testcase() must be evaluated both true and false in order to -** get full branch coverage. The testcase() macro is inserted -** to help ensure adequate test coverage in places where simple -** condition/decision coverage is inadequate. For example, testcase() -** can be used to make sure boundary values are tested. For -** bitmask tests, testcase() can be used to make sure each bit -** is significant and used at least once. On switch statements -** where multiple cases go to the same block of code, testcase() -** can insure that all cases are evaluated. -*/ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) -# ifndef SQLITE_AMALGAMATION - extern unsigned int sqlite3CoverageCounter; -# endif -# define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; } -#else -# define testcase(X) -#endif - -/* -** The TESTONLY macro is used to enclose variable declarations or -** other bits of code that are needed to support the arguments -** within testcase() and assert() macros. -*/ -#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) -# define TESTONLY(X) X -#else -# define TESTONLY(X) -#endif - -/* -** Sometimes we need a small amount of code such as a variable initialization -** to setup for a later assert() statement. We do not want this code to -** appear when assert() is disabled. The following macro is therefore -** used to contain that setup code. The "VVA" acronym stands for -** "Verification, Validation, and Accreditation". In other words, the -** code within VVA_ONLY() will only run during verification processes. -*/ -#ifndef NDEBUG -# define VVA_ONLY(X) X -#else -# define VVA_ONLY(X) -#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 -** are included in a few cases in order to enhance the resilience -** of SQLite to unexpected behavior - to make the code "self-healing" -** or "ductile" rather than being "brittle" and crashing at the first -** hint of unplanned behavior. -** -** In other words, ALWAYS and NEVER are added for defensive code. -** -** When doing coverage testing ALWAYS and NEVER are hard-coded to -** be true and false so that the unreachable code they specify will -** not be counted as untested code. -*/ -#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 - -/* -** 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. -** -** The following macros mark these optimizations conditionals. -*/ -#if defined(SQLITE_MUTATION_TEST) -# define OK_IF_ALWAYS_TRUE(X) (1) -# define OK_IF_ALWAYS_FALSE(X) (0) -#else -# define OK_IF_ALWAYS_TRUE(X) (X) -# define OK_IF_ALWAYS_FALSE(X) (X) -#endif - -/* -** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is -** defined. We need to defend against those failures when testing with -** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches -** during a normal build. The following macro can be used to disable tests -** that are always false except when SQLITE_TEST_REALLOC_STRESS is set. -*/ -#if defined(SQLITE_TEST_REALLOC_STRESS) -# define ONLY_IF_REALLOC_STRESS(X) (X) -#elif !defined(NDEBUG) -# define ONLY_IF_REALLOC_STRESS(X) ((X)?(assert(0),1):0) -#else -# define ONLY_IF_REALLOC_STRESS(X) (0) -#endif - -/* -** Declarations used for tracing the operating system interfaces. -*/ -#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \ - (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) - extern int sqlite3OSTrace; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -# define SQLITE_HAVE_OS_TRACE -#else -# define OSTRACE(X) -# undef SQLITE_HAVE_OS_TRACE -#endif - -/* -** Is the sqlite3ErrName() function needed in the build? Currently, -** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when -** OSTRACE is enabled), and by several "test*.c" files (which are -** compiled using SQLITE_TEST). -*/ -#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \ - (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) -# define SQLITE_NEED_ERR_NAME -#else -# undef SQLITE_NEED_ERR_NAME -#endif - -/* -** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN -*/ -#ifdef SQLITE_OMIT_EXPLAIN -# undef SQLITE_ENABLE_EXPLAIN_COMMENTS -#endif - -/* -** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE -*/ -#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE) -# define SQLITE_OMIT_ALTERTABLE -#endif - -#define SQLITE_DIGIT_SEPARATOR '_' - -/* -** 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. -*/ -#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) - -/* -** The macro unlikely() is a hint that surrounds a boolean -** expression that is usually false. Macro likely() surrounds -** a boolean expression that is usually true. These hints could, -** in theory, be used by the compiler to generate better code, but -** currently they are just comments for human readers. -*/ -#define likely(X) (X) -#define unlikely(X) (X) - -/************** Include hash.h in the middle of sqliteInt.h ******************/ -/************** Begin file hash.h ********************************************/ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the header file for the generic hash-table implementation -** used in SQLite. -*/ -#ifndef SQLITE_HASH_H -#define SQLITE_HASH_H - -/* Forward declarations of structures. */ -typedef struct Hash Hash; -typedef struct HashElem HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, some of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -** -** All elements of the hash table are on a single doubly-linked list. -** Hash.first points to the head of this list. -** -** There are Hash.htsize buckets. Each bucket points to a spot in -** the global doubly-linked list. The contents of the bucket are the -** element pointed to plus the next _ht.count-1 elements in the list. -** -** Hash.htsize and Hash.ht may be zero. In that case lookup is done -** by a linear search of the global list. For small tables, the -** Hash.ht table is never allocated because if there are few elements -** in the table, it is faster to do a linear search than to manage -** the hash table. -*/ -struct Hash { - unsigned int htsize; /* Number of buckets in the hash table */ - unsigned int count; /* Number of entries in this table */ - HashElem *first; /* The first element of the array */ - struct _ht { /* the hash table */ - unsigned int count; /* Number of entries with this hash */ - HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct HashElem { - HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - const char *pKey; /* Key associated with this element */ - unsigned int h; /* hash for pKey */ -}; - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -SQLITE_PRIVATE void sqlite3HashInit(Hash*); -SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, void *pData); -SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey); -SQLITE_PRIVATE void sqlite3HashClear(Hash*); - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** Hash h; -** HashElem *p; -** ... -** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ -** SomeStructure *pData = sqliteHashData(p); -** // do something with pData -** } -*/ -#define sqliteHashFirst(H) ((H)->first) -#define sqliteHashNext(E) ((E)->next) -#define sqliteHashData(E) ((E)->data) -/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ -/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ - -/* -** Number of entries in a hash table -*/ -#define sqliteHashCount(H) ((H)->count) - -#endif /* SQLITE_HASH_H */ - -/************** End of hash.h ************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include parse.h in the middle of sqliteInt.h *****************/ -/************** Begin file parse.h *******************************************/ -#define TK_SEMI 1 -#define TK_EXPLAIN 2 -#define TK_QUERY 3 -#define TK_PLAN 4 -#define TK_BEGIN 5 -#define TK_TRANSACTION 6 -#define TK_DEFERRED 7 -#define TK_IMMEDIATE 8 -#define TK_EXCLUSIVE 9 -#define TK_COMMIT 10 -#define TK_END 11 -#define TK_ROLLBACK 12 -#define TK_SAVEPOINT 13 -#define TK_RELEASE 14 -#define TK_TO 15 -#define TK_TABLE 16 -#define TK_CREATE 17 -#define TK_IF 18 -#define TK_NOT 19 -#define TK_EXISTS 20 -#define TK_TEMP 21 -#define TK_LP 22 -#define TK_RP 23 -#define TK_AS 24 -#define TK_COMMA 25 -#define TK_WITHOUT 26 -#define TK_ABORT 27 -#define TK_ACTION 28 -#define TK_AFTER 29 -#define TK_ANALYZE 30 -#define TK_ASC 31 -#define TK_ATTACH 32 -#define TK_BEFORE 33 -#define TK_BY 34 -#define TK_CASCADE 35 -#define TK_CAST 36 -#define TK_CONFLICT 37 -#define TK_DATABASE 38 -#define TK_DESC 39 -#define TK_DETACH 40 -#define TK_EACH 41 -#define TK_FAIL 42 -#define TK_OR 43 -#define TK_AND 44 -#define TK_IS 45 -#define TK_ISNOT 46 -#define TK_MATCH 47 -#define TK_LIKE_KW 48 -#define TK_BETWEEN 49 -#define TK_IN 50 -#define TK_ISNULL 51 -#define TK_NOTNULL 52 -#define TK_NE 53 -#define TK_EQ 54 -#define TK_GT 55 -#define TK_LE 56 -#define TK_LT 57 -#define TK_GE 58 -#define TK_ESCAPE 59 -#define TK_ID 60 -#define TK_COLUMNKW 61 -#define TK_DO 62 -#define TK_FOR 63 -#define TK_IGNORE 64 -#define TK_INITIALLY 65 -#define TK_INSTEAD 66 -#define TK_NO 67 -#define TK_KEY 68 -#define TK_OF 69 -#define TK_OFFSET 70 -#define TK_PRAGMA 71 -#define TK_RAISE 72 -#define TK_RECURSIVE 73 -#define TK_REPLACE 74 -#define TK_RESTRICT 75 -#define TK_ROW 76 -#define TK_ROWS 77 -#define TK_TRIGGER 78 -#define TK_VACUUM 79 -#define TK_VIEW 80 -#define TK_VIRTUAL 81 -#define TK_WITH 82 -#define TK_NULLS 83 -#define TK_FIRST 84 -#define TK_LAST 85 -#define TK_CURRENT 86 -#define TK_FOLLOWING 87 -#define TK_PARTITION 88 -#define TK_PRECEDING 89 -#define TK_RANGE 90 -#define TK_UNBOUNDED 91 -#define TK_EXCLUDE 92 -#define TK_GROUPS 93 -#define TK_OTHERS 94 -#define TK_TIES 95 -#define TK_GENERATED 96 -#define TK_ALWAYS 97 -#define TK_MATERIALIZED 98 -#define TK_REINDEX 99 -#define TK_RENAME 100 -#define TK_CTIME_KW 101 -#define TK_ANY 102 -#define TK_BITAND 103 -#define TK_BITOR 104 -#define TK_LSHIFT 105 -#define TK_RSHIFT 106 -#define TK_PLUS 107 -#define TK_MINUS 108 -#define TK_STAR 109 -#define TK_SLASH 110 -#define TK_REM 111 -#define TK_CONCAT 112 -#define TK_PTR 113 -#define TK_COLLATE 114 -#define TK_BITNOT 115 -#define TK_ON 116 -#define TK_INDEXED 117 -#define TK_STRING 118 -#define TK_JOIN_KW 119 -#define TK_CONSTRAINT 120 -#define TK_DEFAULT 121 -#define TK_NULL 122 -#define TK_PRIMARY 123 -#define TK_UNIQUE 124 -#define TK_CHECK 125 -#define TK_REFERENCES 126 -#define TK_AUTOINCR 127 -#define TK_INSERT 128 -#define TK_DELETE 129 -#define TK_UPDATE 130 -#define TK_SET 131 -#define TK_DEFERRABLE 132 -#define TK_FOREIGN 133 -#define TK_DROP 134 -#define TK_UNION 135 -#define TK_ALL 136 -#define TK_EXCEPT 137 -#define TK_INTERSECT 138 -#define TK_SELECT 139 -#define TK_VALUES 140 -#define TK_DISTINCT 141 -#define TK_DOT 142 -#define TK_FROM 143 -#define TK_JOIN 144 -#define TK_USING 145 -#define TK_ORDER 146 -#define TK_GROUP 147 -#define TK_HAVING 148 -#define TK_LIMIT 149 -#define TK_WHERE 150 -#define TK_RETURNING 151 -#define TK_INTO 152 -#define TK_NOTHING 153 -#define TK_FLOAT 154 -#define TK_BLOB 155 -#define TK_INTEGER 156 -#define TK_VARIABLE 157 -#define TK_CASE 158 -#define TK_WHEN 159 -#define TK_THEN 160 -#define TK_ELSE 161 -#define TK_INDEX 162 -#define TK_ALTER 163 -#define TK_ADD 164 -#define TK_WINDOW 165 -#define TK_OVER 166 -#define TK_FILTER 167 -#define TK_COLUMN 168 -#define TK_AGG_FUNCTION 169 -#define TK_AGG_COLUMN 170 -#define TK_TRUEFALSE 171 -#define TK_FUNCTION 172 -#define TK_UPLUS 173 -#define TK_UMINUS 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_QNUMBER 183 -#define TK_SPACE 184 -#define TK_COMMENT 185 -#define TK_ILLEGAL 186 - -/************** End of parse.h ***********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -#include -#include -#include -#include -#include -#include - -/* -** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY. -** This allows better measurements of where memcpy() is used when running -** cachegrind. But this macro version of memcpy() is very slow so it -** should not be used in production. This is a performance measurement -** hack only. -*/ -#ifdef SQLITE_INLINE_MEMCPY -# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\ - int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);} -#endif - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite_int64 -# define float sqlite_int64 -# define fabs(X) ((X)<0?-(X):(X)) -# define sqlite3IsOverflow(X) 0 -# ifndef SQLITE_BIG_DBL -# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) -# endif -# define SQLITE_OMIT_DATETIME_FUNCS 1 -# define SQLITE_OMIT_TRACE 1 -# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -# undef SQLITE_HAVE_ISNAN -#endif -#ifndef SQLITE_BIG_DBL -# define SQLITE_BIG_DBL (1e99) -#endif - -/* -** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 -** afterward. Having this macro allows us to cause the C compiler -** to omit code used by TEMP tables without messy #ifndef statements. -*/ -#ifdef SQLITE_OMIT_TEMPDB -#define OMIT_TEMPDB 1 -#else -#define OMIT_TEMPDB 0 -#endif - -/* -** The "file format" number is an integer that is incremented whenever -** the VDBE-level file format changes. The following macros define the -** the default file format for new databases and the maximum file format -** that the library can read. -*/ -#define SQLITE_MAX_FILE_FORMAT 4 -#ifndef SQLITE_DEFAULT_FILE_FORMAT -# define SQLITE_DEFAULT_FILE_FORMAT 4 -#endif - -/* -** Determine whether triggers are recursive by default. This can be -** changed at run-time using a pragma. -*/ -#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS -# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 -#endif - -/* -** Provide a default value for SQLITE_TEMP_STORE in case it is not specified -** on the command-line -*/ -#ifndef SQLITE_TEMP_STORE -# define SQLITE_TEMP_STORE 1 -#endif - -/* -** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if -** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it -** to zero. -*/ -#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0 -# undef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS 0 -#endif -#ifndef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS 8 -#endif -#ifndef SQLITE_DEFAULT_WORKER_THREADS -# define SQLITE_DEFAULT_WORKER_THREADS 0 -#endif -#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS -# undef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS -#endif - -/* -** The default initial allocation for the pagecache when using separate -** pagecaches for each database connection. A positive number is the -** 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 chosen to minimize the run-time of the -** speedtest1 test program with options: --shrink-memory --reprepare -*/ -#ifndef SQLITE_DEFAULT_PCACHE_INITSZ -# define SQLITE_DEFAULT_PCACHE_INITSZ 20 -#endif - -/* -** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option. -*/ -#ifndef SQLITE_DEFAULT_SORTERREF_SIZE -# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff -#endif - -/* -** The compile-time options SQLITE_MMAP_READWRITE and -** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another. -** You must choose one or the other (or neither) but not both. -*/ -#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) -#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE -#endif - -/* -** GCC does not define the offsetof() macro so we'll have to do it -** ourselves. -*/ -#ifndef offsetof -#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) -#endif - -/* -** Work around C99 "flex-array" syntax for pre-C99 compilers, so as -** to avoid complaints from -fsanitize=strict-bounds. -*/ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define FLEXARRAY -#else -# define FLEXARRAY 1 -#endif - -/* -** Macros to compute minimum and maximum of two numbers. -*/ -#ifndef MIN -# define MIN(A,B) ((A)<(B)?(A):(B)) -#endif -#ifndef MAX -# define MAX(A,B) ((A)>(B)?(A):(B)) -#endif - -/* -** Swap two objects of type TYPE. -*/ -#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} - -/* -** Check to see if this machine uses EBCDIC. (Yes, believe it or -** not, there are still machines out there that use EBCDIC.) -*/ -#if 'A' == '\301' -# define SQLITE_EBCDIC 1 -#else -# define SQLITE_ASCII 1 -#endif - -/* -** Integers of known sizes. These typedefs might change for architectures -** where the sizes very. Preprocessor macros are available so that the -** types can be conveniently redefined at compile-type. Like this: -** -** cc '-DUINTPTR_TYPE=long long int' ... -*/ -#ifndef UINT32_TYPE -# ifdef HAVE_UINT32_T -# define UINT32_TYPE uint32_t -# else -# define UINT32_TYPE unsigned int -# endif -#endif -#ifndef UINT16_TYPE -# ifdef HAVE_UINT16_T -# define UINT16_TYPE uint16_t -# else -# define UINT16_TYPE unsigned short int -# endif -#endif -#ifndef INT16_TYPE -# ifdef HAVE_INT16_T -# define INT16_TYPE int16_t -# else -# define INT16_TYPE short int -# endif -#endif -#ifndef UINT8_TYPE -# ifdef HAVE_UINT8_T -# define UINT8_TYPE uint8_t -# else -# define UINT8_TYPE unsigned char -# endif -#endif -#ifndef INT8_TYPE -# ifdef HAVE_INT8_T -# define INT8_TYPE int8_t -# else -# define INT8_TYPE signed char -# endif -#endif -typedef sqlite_int64 i64; /* 8-byte signed integer */ -typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ -typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ -typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ -typedef INT16_TYPE i16; /* 2-byte signed integer */ -typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ -typedef INT8_TYPE i8; /* 1-byte signed integer */ - -/* A bitfield type for use inside of structures. Always follow with :N where -** N is the number of bits. -*/ -typedef unsigned bft; /* Bit Field Type */ - -/* -** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value -** that can be stored in a u32 without loss of data. The value -** is 0x00000000ffffffff. But because of quirks of some compilers, we -** have to specify the value in the less intuitive manner shown: -*/ -#define SQLITE_MAX_U32 ((((u64)1)<<32)-1) - -/* -** The datatype used to store estimates of the number of rows in a -** table or index. -*/ -typedef u64 tRowcnt; - -/* -** Estimated quantities used for query planning are stored as 16-bit -** logarithms. For quantity X, the value stored is 10*log2(X). This -** gives a possible range of values of approximately 1.0e986 to 1e-986. -** But the allowed values are "grainy". Not every value is representable. -** For example, quantities 16 and 17 are both represented by a LogEst -** of 40. However, since LogEst quantities are suppose to be estimates, -** not exact values, this imprecision is not a problem. -** -** "LogEst" is short for "Logarithmic Estimate". -** -** Examples: -** 1 -> 0 20 -> 43 10000 -> 132 -** 2 -> 10 25 -> 46 25000 -> 146 -** 3 -> 16 100 -> 66 1000000 -> 199 -** 4 -> 20 1000 -> 99 1048576 -> 200 -** 10 -> 33 1024 -> 100 4294967296 -> 320 -** -** The LogEst can be negative to indicate fractional values. -** Examples: -** -** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 -*/ -typedef INT16_TYPE LogEst; -#define LOGEST_MIN (-32768) -#define LOGEST_MAX (32767) - -/* -** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer -*/ -#ifndef SQLITE_PTRSIZE -# if defined(__SIZEOF_POINTER__) -# define SQLITE_PTRSIZE __SIZEOF_POINTER__ -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ - (defined(__APPLE__) && defined(__ppc__)) || \ - (defined(__TOS_AIX__) && !defined(__64BIT__)) -# define SQLITE_PTRSIZE 4 -# else -# define SQLITE_PTRSIZE 8 -# endif -#endif - -/* The uptr type is an unsigned integer large enough to hold a pointer -*/ -#if defined(HAVE_STDINT_H) - typedef uintptr_t uptr; -#elif SQLITE_PTRSIZE==4 - typedef u32 uptr; -#else - typedef u64 uptr; -#endif - -/* -** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to -** something between S (inclusive) and E (exclusive). -** -** In other words, S is a buffer and E is a pointer to the first byte after -** the end of buffer S. This macro returns true if P points to something -** contained within the buffer S. -*/ -#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) - -/* -** P is one byte past the end of a large buffer. Return true if a span of bytes -** between S..E crosses the end of that buffer. In other words, return true -** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. -** -** S is the start of the span. E is one byte past the end of end of span. -** -** P -** |-----------------| FALSE -** |-------| -** S E -** -** P -** |-----------------| -** |-------| TRUE -** S E -** -** P -** |-----------------| -** |-------| FALSE -** S E -*/ -#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P))) - -/* -** Macros to determine whether the machine is big or little endian, -** and whether or not that determination is run-time or compile-time. -** -** For best performance, an attempt is made to guess at the byte-order -** using C-preprocessor macros. If that is unsuccessful, or if -** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined -** at run-time. -** -** If you are building SQLite on some obscure platform for which the -** following ifdef magic does not work, you can always include either: -** -** -DSQLITE_BYTEORDER=1234 -** -** or -** -** -DSQLITE_BYTEORDER=4321 -** -** to cause the build to work for little-endian or big-endian processors, -** respectively. -*/ -#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ -# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ -# define SQLITE_BYTEORDER 4321 -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -# define SQLITE_BYTEORDER 1234 -# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 -# define SQLITE_BYTEORDER 4321 -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 -# else -# define SQLITE_BYTEORDER 0 -# endif -#endif -#if SQLITE_BYTEORDER==4321 -# define SQLITE_BIGENDIAN 1 -# define SQLITE_LITTLEENDIAN 0 -# define SQLITE_UTF16NATIVE SQLITE_UTF16BE -#elif SQLITE_BYTEORDER==1234 -# define SQLITE_BIGENDIAN 0 -# define SQLITE_LITTLEENDIAN 1 -# define SQLITE_UTF16NATIVE SQLITE_UTF16LE -#else -# ifdef SQLITE_AMALGAMATION - const int sqlite3one = 1; -# else - extern const int sqlite3one; -# endif -# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) -# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) -# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) -#endif - -/* -** Constants for the largest and smallest possible 64-bit signed integers. -** These macros are designed to work correctly on both 32-bit and 64-bit -** compilers. -*/ -#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) -#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32)) -#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) - -/* -** Macro SMXV(n) return the maximum value that can be held in variable n, -** assuming n is a signed integer type. UMXV(n) is similar for unsigned -** integer types. -*/ -#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1) -#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1) - -/* -** 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 -*/ -#define ROUNDDOWN8(x) ((x)&~7) - -/* -** Assert that the pointer X is aligned to an 8-byte boundary. This -** macro is used only within assert() to verify that the code gets -** all alignment restrictions correct. -** -** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the -** underlying malloc() implementation might return us 4-byte aligned -** pointers. In that case, only verify 4-byte alignment. -*/ -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) -#else -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) -#endif - -/* -** Disable MMAP on platforms where it is known to not work -*/ -#if defined(__OpenBSD__) || defined(__QNXNTO__) -# undef SQLITE_MAX_MMAP_SIZE -# define SQLITE_MAX_MMAP_SIZE 0 -#endif - -/* -** Default maximum size of memory used by memory-mapped I/O in the VFS -*/ -#ifdef __APPLE__ -# include -#endif -#ifndef SQLITE_MAX_MMAP_SIZE -# if defined(__linux__) \ - || defined(_WIN32) \ - || (defined(__APPLE__) && defined(__MACH__)) \ - || defined(__sun) \ - || defined(__FreeBSD__) \ - || defined(__DragonFly__) -# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ -# else -# define SQLITE_MAX_MMAP_SIZE 0 -# endif -#endif - -/* -** The default MMAP_SIZE is zero on all platforms. Or, even if a larger -** default MMAP_SIZE is specified at compile-time, make sure that it does -** not exceed the maximum mmap size. -*/ -#ifndef SQLITE_DEFAULT_MMAP_SIZE -# define SQLITE_DEFAULT_MMAP_SIZE 0 -#endif -#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE -# undef SQLITE_DEFAULT_MMAP_SIZE -# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE -#endif - -/* -** 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_AMALGAMATION) -SQLITE_PRIVATE u32 sqlite3TreeTrace; -#endif -#if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \ - || defined(SQLITE_ENABLE_TREETRACE)) -# define TREETRACE_ENABLED 1 -# define TREETRACE(K,P,S,X) \ - if(sqlite3TreeTrace&(K)) \ - sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ - sqlite3DebugPrintf X -#else -# define TREETRACE(K,P,S,X) -# define TREETRACE_ENABLED 0 -#endif - -/* TREETRACE flag meanings: -** -** 0x00000001 Beginning and end of SELECT processing -** 0x00000002 WHERE clause processing -** 0x00000004 Query flattener -** 0x00000008 Result-set wildcard expansion -** 0x00000010 Query name resolution -** 0x00000020 Aggregate analysis -** 0x00000040 Window functions -** 0x00000080 Generated column names -** 0x00000100 Move HAVING terms into WHERE -** 0x00000200 Count-of-view optimization -** 0x00000400 Compound SELECT processing -** 0x00000800 Drop superfluous ORDER BY -** 0x00001000 LEFT JOIN simplifies to JOIN -** 0x00002000 Constant propagation -** 0x00004000 Push-down optimization -** 0x00008000 After all FROM-clause analysis -** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing -** 0x00020000 Transform DISTINCT into GROUP BY -** 0x00040000 SELECT tree dump after all code has been generated -** 0x00080000 NOT NULL strength reduction -*/ - -/* -** Macros for "wheretrace" -*/ -SQLITE_PRIVATE u32 sqlite3WhereTrace; -#if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) -# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X -# define WHERETRACE_ENABLED 1 -#else -# define WHERETRACE(K,X) -#endif - -/* -** Bits for the sqlite3WhereTrace mask: -** -** (---any--) Top-level block structure -** 0x-------F High-level debug messages -** 0x----FFF- More detail -** 0xFFFF---- Low-level debug messages -** -** 0x00000001 Code generation -** 0x00000002 Solver (Use 0x40000 for less detail) -** 0x00000004 Solver costs -** 0x00000008 WhereLoop inserts -** -** 0x00000010 Display sqlite3_index_info xBestIndex calls -** 0x00000020 Range an equality scan metrics -** 0x00000040 IN operator decisions -** 0x00000080 WhereLoop cost adjustments -** 0x00000100 -** 0x00000200 Covering index decisions -** 0x00000400 OR optimization -** 0x00000800 Index scanner -** 0x00001000 More details associated with code generation -** 0x00002000 -** 0x00004000 Show all WHERE terms at key points -** 0x00008000 Show the full SELECT statement at key places -** -** 0x00010000 Show more detail when printing WHERE terms -** 0x00020000 Show WHERE terms returned from whereScanNext() -** 0x00040000 Solver overview messages -** 0x00080000 Star-query heuristic -*/ - - -/* -** An instance of the following structure is used to store the busy-handler -** callback for a given sqlite handle. -** -** The sqlite.busyHandler member of the sqlite struct contains the busy -** callback for the database handle. Each pager opened via the sqlite -** handle is passed a pointer to sqlite.busyHandler. The busy-handler -** callback is currently invoked only from within pager.c. -*/ -typedef struct BusyHandler BusyHandler; -struct BusyHandler { - int (*xBusyHandler)(void *,int); /* The busy callback */ - void *pBusyArg; /* First arg to busy callback */ - int nBusy; /* Incremented with each busy call */ -}; - -/* -** Name of table that holds the database schema. -** -** The PREFERRED names are used wherever possible. But LEGACY is also -** used for backwards compatibility. -** -** 1. Queries can use either the PREFERRED or the LEGACY names -** 2. The 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 sqlite3PreferredTableName() -** for (3). The sqlite3FindTable() function takes care of translating -** names for (1). -** -** Note that "sqlite_temp_schema" can also be called "temp.sqlite_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" - - -/* -** The root-page of the schema table. -*/ -#define SCHEMA_ROOT 1 - -/* -** The name of the schema table. The name is different for TEMP. -*/ -#define SCHEMA_TABLE(x) \ - ((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE) - -/* -** A convenience macro that returns the number of elements in -** an array. -*/ -#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) - -/* -** Determine if the argument is a power of two -*/ -#define IsPowerOfTwo(X) (((X)&((X)-1))==0) - -/* -** The following value as a destructor means to use sqlite3DbFree(). -** The sqlite3DbFree() routine requires two parameters instead of the -** one parameter that destructors normally want. So we have to introduce -** this magic value that the code knows to handle differently. Any -** pointer will work here as long as it is distinct from SQLITE_STATIC -** and SQLITE_TRANSIENT. -*/ -#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear) - -/* -** When SQLITE_OMIT_WSD is defined, it means that the target platform does -** not support Writable Static Data (WSD) such as global and static variables. -** All variables must either be on the stack or dynamically allocated from -** the heap. When WSD is unsupported, the variable declarations scattered -** throughout the SQLite code must become constants instead. The SQLITE_WSD -** macro is used for this purpose. And instead of referencing the variable -** directly, we use its constant as a key to lookup the run-time allocated -** buffer that holds real variable. The constant is also the initializer -** for the run-time allocated buffer. -** -** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL -** macros become no-ops and have zero performance impact. -*/ -#ifdef SQLITE_OMIT_WSD - #define SQLITE_WSD const - #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) - #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) -SQLITE_API int sqlite3_wsd_init(int N, int J); -SQLITE_API void *sqlite3_wsd_find(void *K, int L); -#else - #define SQLITE_WSD - #define GLOBAL(t,v) v - #define sqlite3GlobalConfig sqlite3Config -#endif - -/* -** The following macros are used to suppress compiler warnings and to -** make it clear to human readers when a function parameter is deliberately -** left unused within the body of a function. This usually happens when -** a function is called via a function pointer. For example the -** implementation of an SQL aggregate step callback may not use the -** parameter indicating the number of arguments passed to the aggregate, -** if it knows that this is enforced elsewhere. -** -** When a function parameter is not used at all within the body of a function, -** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. -** However, these macros may also be used to suppress warnings related to -** parameters that may or may not be used depending on compilation options. -** For example those parameters only used in assert() statements. In these -** cases the parameters are named as per the usual conventions. -*/ -#define UNUSED_PARAMETER(x) (void)(x) -#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) - -/* -** Forward references to structures -*/ -typedef struct AggInfo AggInfo; -typedef struct AuthContext AuthContext; -typedef struct AutoincInfo AutoincInfo; -typedef struct Bitvec Bitvec; -typedef struct CollSeq CollSeq; -typedef struct Column Column; -typedef struct Cte Cte; -typedef struct CteUse CteUse; -typedef struct Db Db; -typedef struct DbClientData DbClientData; -typedef struct DbFixer DbFixer; -typedef struct Schema Schema; -typedef struct Expr Expr; -typedef struct ExprList ExprList; -typedef struct FKey FKey; -typedef struct FpDecode FpDecode; -typedef struct FuncDestructor FuncDestructor; -typedef struct FuncDef FuncDef; -typedef struct FuncDefHash FuncDefHash; -typedef struct IdList IdList; -typedef struct Index Index; -typedef struct IndexedExpr IndexedExpr; -typedef struct IndexSample IndexSample; -typedef struct KeyClass KeyClass; -typedef struct KeyInfo KeyInfo; -typedef struct Lookaside Lookaside; -typedef struct LookasideSlot LookasideSlot; -typedef struct Module Module; -typedef struct NameContext NameContext; -typedef struct OnOrUsing OnOrUsing; -typedef struct Parse Parse; -typedef struct ParseCleanup ParseCleanup; -typedef struct PreUpdate PreUpdate; -typedef struct PrintfArguments PrintfArguments; -typedef struct RCStr RCStr; -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 Subquery Subquery; -typedef struct SrcItem SrcItem; -typedef struct SrcList SrcList; -typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */ -typedef struct Table Table; -typedef struct TableLock TableLock; -typedef struct Token Token; -typedef struct TreeView TreeView; -typedef struct Trigger Trigger; -typedef struct TriggerPrg TriggerPrg; -typedef struct TriggerStep TriggerStep; -typedef struct UnpackedRecord UnpackedRecord; -typedef struct Upsert Upsert; -typedef struct VTable VTable; -typedef struct VtabCtx VtabCtx; -typedef struct Walker Walker; -typedef struct WhereInfo WhereInfo; -typedef struct Window Window; -typedef struct With With; - - -/* -** The bitmask datatype defined below is used for various optimizations. -** -** Changing this from a 64-bit to a 32-bit type limits the number of -** tables in a join to 32 instead of 64. But it also reduces the size -** of the library by 738 bytes on ix86. -*/ -#ifdef SQLITE_BITMASK_TYPE - typedef SQLITE_BITMASK_TYPE Bitmask; -#else - typedef u64 Bitmask; -#endif - -/* -** The number of bits in a Bitmask. "BMS" means "BitMask Size". -*/ -#define BMS ((int)(sizeof(Bitmask)*8)) - -/* -** 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 SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0) -#define ALLBITS ((Bitmask)-1) -#define TOPBIT (((Bitmask)1)<<(BMS-1)) - -/* A VList object records a mapping between parameters/variables/wildcards -** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer -** variable number associated with that parameter. See the format description -** on the sqlite3VListAdd() routine for more information. A VList is really -** just an array of integers. -*/ -typedef int VList; - -/* -** Defer sourcing vdbe.h and btree.h until after the "u8" and -** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque -** pointer types (i.e. FuncDef) defined above. -*/ -/************** Include os.h in the middle of sqliteInt.h ********************/ -/************** Begin file os.h **********************************************/ -/* -** 2001 September 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file (together with is companion C source-code file -** "os.c") attempt to abstract the underlying operating system so that -** the SQLite library will work on both POSIX and windows systems. -** -** This header file is #include-ed by sqliteInt.h and thus ends up -** being included by every source file. -*/ -#ifndef _SQLITE_OS_H_ -#define _SQLITE_OS_H_ - -/* -** Attempt to automatically detect the operating system and setup the -** necessary pre-processor macros for it. -*/ -/************** Include os_setup.h in the middle of os.h *********************/ -/************** Begin file os_setup.h ****************************************/ -/* -** 2013 November 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains pre-processor directives related to operating system -** detection and/or setup. -*/ -#ifndef SQLITE_OS_SETUP_H -#define SQLITE_OS_SETUP_H - -/* -** Figure out if we are dealing with Unix, Windows, or some other operating -** system. -** -** After the following block of preprocess macros, all of -** -** SQLITE_OS_KV -** SQLITE_OS_OTHER -** SQLITE_OS_UNIX -** SQLITE_OS_WIN -** -** will defined to either 1 or 0. One of them will be 1. The others will be 0. -** If none of the macros are initially defined, then select either -** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform. -** -** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application -** must provide its own VFS implementation together with sqlite3_os_init() -** and sqlite3_os_end() routines. -*/ -#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \ - !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN) -# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ - defined(__MINGW32__) || defined(__BORLANDC__) -# define SQLITE_OS_WIN 1 -# define SQLITE_OS_UNIX 0 -# else -# define SQLITE_OS_WIN 0 -# define SQLITE_OS_UNIX 1 -# endif -#endif -#if SQLITE_OS_OTHER+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -#endif -#if SQLITE_OS_KV+1>1 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -# define SQLITE_OMIT_LOAD_EXTENSION 1 -# define SQLITE_OMIT_WAL 1 -# define SQLITE_OMIT_DEPRECATED 1 -# undef SQLITE_TEMP_STORE -# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */ -# define SQLITE_DQS 0 -# define SQLITE_OMIT_SHARED_CACHE 1 -# define SQLITE_OMIT_AUTOINIT 1 -#endif -#if SQLITE_OS_UNIX+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -#endif -#if SQLITE_OS_WIN+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -#endif - - -#endif /* SQLITE_OS_SETUP_H */ - -/************** End of os_setup.h ********************************************/ -/************** Continuing where we left off in os.h *************************/ - -/* If the SET_FULLSYNC macro is not defined above, then make it -** a no-op -*/ -#ifndef SET_FULLSYNC -# 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 -*/ -#ifndef SQLITE_DEFAULT_SECTOR_SIZE -# define SQLITE_DEFAULT_SECTOR_SIZE 4096 -#endif - -/* -** Temporary files are named starting with this prefix followed by 16 random -** alphanumeric characters, and no file extension. They are stored in the -** OS's standard temporary file directory, and are deleted prior to exit. -** If sqlite is being embedded in another program, you may wish to change the -** prefix to reflect your program's name, so that if your program exits -** prematurely, old temporary files can be easily identified. This can be done -** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. -** -** 2006-10-31: The default prefix used to be "sqlite_". But then -** Mcafee started using SQLite in their anti-virus product and it -** started putting files with the "sqlite" name in the c:/temp folder. -** This annoyed many windows users. Those users would then do a -** Google search for "sqlite", find the telephone numbers of the -** developers and call to wake them up at night and complain. -** For this reason, the default name prefix is changed to be "sqlite" -** spelled backwards. So the temp files are still identified, but -** anybody smart enough to figure out the code is also likely smart -** enough to know that calling the developer will not help get rid -** of the file. -*/ -#ifndef SQLITE_TEMP_FILE_PREFIX -# define SQLITE_TEMP_FILE_PREFIX "etilqs_" -#endif - -/* -** The following values may be passed as the second argument to -** sqlite3OsLock(). The various locks exhibit the following semantics: -** -** SHARED: Any number of processes may hold a SHARED lock simultaneously. -** RESERVED: A single process may hold a RESERVED lock on a file at -** any time. Other processes may hold and obtain new SHARED locks. -** PENDING: A single process may hold a PENDING lock on a file at -** any one time. Existing SHARED locks may persist, but no new -** SHARED locks may be obtained by other processes. -** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. -** -** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a -** process that requests an EXCLUSIVE lock may actually obtain a PENDING -** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to -** sqlite3OsLock(). -*/ -#define NO_LOCK 0 -#define SHARED_LOCK 1 -#define RESERVED_LOCK 2 -#define PENDING_LOCK 3 -#define EXCLUSIVE_LOCK 4 - -/* -** File Locking Notes: (Mostly about windows but also some info for Unix) -** -** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because -** those functions are not available. So we use only LockFile() and -** UnlockFile(). -** -** LockFile() prevents not just writing but also reading by other processes. -** A SHARED_LOCK is obtained by locking a single randomly-chosen -** byte out of a specific range of bytes. The lock byte is obtained at -** random so two separate readers can probably access the file at the -** same time, unless they are unlucky and choose the same lock byte. -** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. -** There can only be one writer. A RESERVED_LOCK is obtained by locking -** a single byte of the file that is designated as the reserved lock byte. -** A PENDING_LOCK is obtained by locking a designated byte different from -** the RESERVED_LOCK byte. -** -** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, -** which means we can use reader/writer locks. When reader/writer locks -** are used, the lock is placed on the same range of bytes that is used -** for probabilistic locking in Win95/98/ME. Hence, the locking scheme -** will support two or more Win95 readers or two or more WinNT readers. -** But a single Win95 reader will lock out all WinNT readers and a single -** WinNT reader will lock out all other Win95 readers. -** -** The following #defines specify the range of bytes used for locking. -** SHARED_SIZE is the number of bytes available in the pool from which -** a random byte is selected for a shared lock. The pool of bytes for -** shared locks begins at SHARED_FIRST. -** -** The same locking strategy and -** byte ranges are used for Unix. This leaves open the possibility of having -** clients on win95, winNT, and unix all talking to the same shared file -** and all locking correctly. To do so would require that samba (or whatever -** tool is being used for file sharing) implements locks correctly between -** windows and unix. I'm guessing that isn't likely to happen, but by -** using the same locking range we are at least open to the possibility. -** -** Locking in windows is manditory. For this reason, we cannot store -** actual data in the bytes used for locking. The pager never allocates -** the pages involved in locking therefore. SHARED_SIZE is selected so -** that all locks will fit on a single page even at the minimum page size. -** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE -** is set high so that we don't have to allocate an unused page except -** for very large databases. But one should test the page skipping logic -** by setting PENDING_BYTE low and running the entire regression suite. -** -** Changing the value of PENDING_BYTE results in a subtly incompatible -** file format. Depending on how it is changed, you might not notice -** the incompatibility right away, even running a full regression test. -** The default location of PENDING_BYTE is the first byte past the -** 1GB boundary. -** -*/ -#ifdef SQLITE_OMIT_WSD -# define PENDING_BYTE (0x40000000) -#else -# define PENDING_BYTE sqlite3PendingByte -#endif -#define RESERVED_BYTE (PENDING_BYTE+1) -#define SHARED_FIRST (PENDING_BYTE+2) -#define SHARED_SIZE 510 - -/* -** Wrapper around OS specific sqlite3_os_init() function. -*/ -SQLITE_PRIVATE int sqlite3OsInit(void); - -/* -** Functions for accessing sqlite3_file methods -*/ -SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*); -SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); -SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); -SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); -SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); -SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); -SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); -SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); -#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 -SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); -SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); -SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); -SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); -SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); -#endif /* SQLITE_OMIT_WAL */ -SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); -SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); - - -/* -** Functions for accessing sqlite3_vfs methods -*/ -SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); -SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); -SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); -SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); -#ifndef SQLITE_OMIT_LOAD_EXTENSION -SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); -SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); -SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); -SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ -SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); -SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); -SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*); -SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); - -/* -** Convenience functions for opening and closing files using -** sqlite3_malloc() to obtain space for the file-handle structure. -*/ -SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); -SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *); - -#endif /* _SQLITE_OS_H_ */ - -/************** End of os.h **************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include pager.h in the middle of sqliteInt.h *****************/ -/************** Begin file pager.h *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite page cache -** subsystem. The page cache subsystem reads and writes a file a page -** at a time and provides a journal for rollback. -*/ - -#ifndef SQLITE_PAGER_H -#define SQLITE_PAGER_H - -/* -** Default maximum size for persistent journal files. A negative -** value means no limit. This value may be overridden using the -** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". -*/ -#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT - #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 -#endif - -/* -** The type used to represent a page number. The first page in a file -** is called page 1. 0 is used to represent "not a page". -*/ -typedef u32 Pgno; - -/* -** Each open file is managed by a separate instance of the "Pager" structure. -*/ -typedef struct Pager Pager; - -/* -** Handle type for pages. -*/ -typedef struct PgHdr DbPage; - -/* -** 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_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) -#define PAGER_SJ_PGNO(x) ((x)->lckPgno) - -/* -** Allowed values for the flags parameter to sqlite3PagerOpen(). -** -** NOTE: These values must match the corresponding BTREE_ values in btree.h. -*/ -#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ -#define PAGER_MEMORY 0x0002 /* In-memory database */ - -/* -** Valid values for the second argument to sqlite3PagerLockingMode(). -*/ -#define PAGER_LOCKINGMODE_QUERY -1 -#define PAGER_LOCKINGMODE_NORMAL 0 -#define PAGER_LOCKINGMODE_EXCLUSIVE 1 - -/* -** Numeric constants that encode the journalmode. -** -** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY) -** are exposed in the API via the "PRAGMA journal_mode" command and -** therefore cannot be changed without a compatibility break. -*/ -#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ -#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ -#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ -#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ -#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ -#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ -#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ - -#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL) - -/* -** The argument to this macro is a file descriptor (type sqlite3_file*). -** Return 0 if it is not open, or non-zero (but not 1) if it is. -** -** This is so that expressions can be written as: -** -** if( isOpen(pPager->jfd) ){ ... -** -** instead of -** -** if( pPager->jfd->pMethods ){ ... -*/ -#define isOpen(pFd) ((pFd)->pMethods!=0) - -/* -** Flags that make up the mask passed to sqlite3PagerGet(). -*/ -#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ -#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ - -/* -** Flags for sqlite3PagerSetFlags() -** -** Value constraints (enforced via assert()): -** PAGER_FULLFSYNC == SQLITE_FullFSync -** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync -** PAGER_CACHE_SPILL == SQLITE_CacheSpill -*/ -#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ -#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ -#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ -#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ -#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ -#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ -#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ -#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ -#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ - -/* -** The remainder of this file contains the declarations of the functions -** that make up the Pager sub-system API. See source code comments for -** a detailed description of each routine. -*/ - -/* Open and close a Pager connection. */ -SQLITE_PRIVATE int sqlite3PagerOpen( - sqlite3_vfs*, - Pager **ppPager, - const char*, - int, - int, - int, - void(*)(DbPage*) -); -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); -SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); - -/* Functions used to configure a Pager object. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); -#endif -/* END SQLCIPHER */ -SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager*, Pgno); -SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); -SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int); -SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); -SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); -SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); -SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); -SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); -SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); -SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); -SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); -SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); -SQLITE_PRIVATE int sqlite3PagerFlush(Pager*); - -/* Functions used to obtain and release page references. */ -SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); -SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); -SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*); - -/* Operations on page references. */ -SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); -SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); -SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); -SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); -SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); -SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); - -/* Functions used to manage pager transactions and savepoints. */ -SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); -SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int); -SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper); -SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); -SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); -SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); -SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); -SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); - -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); -SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_ENABLE_SNAPSHOT -SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager); -# endif -#endif - -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT) -SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int); -SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*); -#else -# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK -# define sqlite3PagerWalDb(x,y) -#endif - -#ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); -#endif - -#ifdef SQLITE_ENABLE_ZIPVFS -SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); -#endif - -/* Functions used to query pager state and configuration. */ -SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); -SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); -#endif -SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); -SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int); -SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*); -SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); -SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); -SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); -SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); -SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*); -SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); -SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); - -/* Functions used to truncate the database file. */ -SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); - -SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); - -/* BEGIN SQLCIPHER */ -#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) -void *sqlcipherPagerCodec(DbPage *); -#endif -/* END SQLCIPHER */ - -/* Functions to support testing and debugging. */ -#if !defined(NDEBUG) || defined(SQLITE_TEST) -SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); -SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); -#endif -#ifdef SQLITE_TEST -SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); -SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); - void disable_simulated_io_errors(void); - void enable_simulated_io_errors(void); -#else -# define disable_simulated_io_errors() -# define enable_simulated_io_errors() -#endif - -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) -SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*); -#endif - -#endif /* SQLITE_PAGER_H */ - -/************** End of pager.h ***********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include btree.h in the middle of sqliteInt.h *****************/ -/************** Begin file btree.h *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite B-Tree file -** subsystem. See comments in the source code for a detailed description -** of what each interface routine does. -*/ -#ifndef SQLITE_BTREE_H -#define SQLITE_BTREE_H - -/* TODO: This definition is just included so other modules compile. It -** needs to be revisited. -*/ -#define SQLITE_N_BTREE_META 16 - -/* -** If defined as non-zero, auto-vacuum is enabled by default. Otherwise -** it must be turned on for each database using "PRAGMA auto_vacuum = 1". -*/ -#ifndef SQLITE_DEFAULT_AUTOVACUUM - #define SQLITE_DEFAULT_AUTOVACUUM 0 -#endif - -#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ -#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ -#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ - -/* -** Forward declarations of structure -*/ -typedef struct Btree Btree; -typedef struct BtCursor BtCursor; -typedef struct BtShared BtShared; -typedef struct BtreePayload BtreePayload; - - -SQLITE_PRIVATE int sqlite3BtreeOpen( - sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ - const char *zFilename, /* Name of database file to open */ - sqlite3 *db, /* Associated database connection */ - Btree **ppBtree, /* Return open Btree* here */ - int flags, /* Flags */ - int vfsFlags /* Flags passed through to VFS open */ -); - -/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the -** following values. -** -** NOTE: These values must match the corresponding PAGER_ values in -** pager.h. -*/ -#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ -#define BTREE_MEMORY 2 /* This is an in-memory DB */ -#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ -#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ - -SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); -SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeSetSpillSize(Btree*,int); -#if SQLITE_MAX_MMAP_SIZE>0 -SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); -#endif -SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned); -SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); -SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); -SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno); -SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree*); -SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree*); -SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); -SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); -SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*); -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char*); -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); -SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); -SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags); -SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*); -SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); - -SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); -SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); -#ifndef SQLITE_OMIT_SHARED_CACHE -SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); -#endif - -/* Savepoints are named, nestable SQL transactions mostly implemented */ -/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */ -SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); - -/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */ -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); -#endif - -SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); -SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); -SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); - -SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); - -/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR -** of the flags shown below. -** -** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. -** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data -** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With -** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored -** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL -** indices.) -*/ -#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ -#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ - -SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); -SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*); -SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); - -SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); -SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); - -SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); - -/* -** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta -** should be one of the following values. The integer values are assigned -** to constants so that the offset of the corresponding field in an -** SQLite database header may be found using the following formula: -** -** offset = 36 + (idx * 4) -** -** For example, the free-page-count field is located at byte offset 36 of -** the database file header. The incr-vacuum-flag field is located at -** byte offset 64 (== 36+4*7). -** -** The BTREE_DATA_VERSION value is not really a value stored in the header. -** It is a read-only number computed by the pager. But we merge it with -** the header value access routines since its access pattern is the same. -** Call it a "virtual meta value". -*/ -#define BTREE_FREE_PAGE_COUNT 0 -#define BTREE_SCHEMA_VERSION 1 -#define BTREE_FILE_FORMAT 2 -#define BTREE_DEFAULT_CACHE_SIZE 3 -#define BTREE_LARGEST_ROOT_PAGE 4 -#define BTREE_TEXT_ENCODING 5 -#define BTREE_USER_VERSION 6 -#define BTREE_INCR_VACUUM 7 -#define BTREE_APPLICATION_ID 8 -#define BTREE_DATA_VERSION 15 /* A virtual meta-value */ - -/* -** Kinds of hints that can be passed into the sqlite3BtreeCursorHint() -** interface. -** -** BTREE_HINT_RANGE (arguments: Expr*, Mem*) -** -** The first argument is an Expr* (which is guaranteed to be constant for -** the lifetime of the cursor) that defines constraints on which rows -** might be fetched with this cursor. The Expr* tree may contain -** TK_REGISTER nodes that refer to values stored in the array of registers -** passed as the second parameter. In other words, if Expr.op==TK_REGISTER -** then the value of the node is the value in Mem[pExpr.iTable]. Any -** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th -** column of the b-tree of the cursor. The Expr tree will not contain -** any function calls nor subqueries nor references to b-trees other than -** the cursor being hinted. -** -** The design of the _RANGE hint is aid b-tree implementations that try -** to prefetch content from remote machines - to provide those -** implementations with limits on what needs to be prefetched and thereby -** reduce network bandwidth. -** -** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by -** standard SQLite. The other hints are provided for extensions that use -** the SQLite parser and code generator but substitute their own storage -** engine. -*/ -#define BTREE_HINT_RANGE 0 /* Range constraints on queries */ - -/* -** Values that may be OR'd together to form the argument to the -** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint(): -** -** The BTREE_BULKLOAD flag is set on index cursors when the index is going -** to be filled with content that is already in sorted order. -** -** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or -** OP_SeekLE opcodes for a range search, but where the range of entries -** selected will all have the same key. In other words, the cursor will -** be used only for equality key searches. -** -*/ -#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ -#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ - -/* -** Flags passed as the third argument to sqlite3BtreeCursor(). -** -** For read-only cursors the wrFlag argument is always zero. For read-write -** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just -** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will -** only be used by SQLite for the following: -** -** * to seek to and then delete specific entries, and/or -** -** * to read values that will be used to create keys that other -** BTREE_FORDELETE cursors will seek to and delete. -** -** The BTREE_FORDELETE flag is an optimization hint. It is not used by -** by this, the native b-tree engine of SQLite, but it is available to -** alternative storage engines that might be substituted in place of this -** b-tree system. For alternative storage engines in which a delete of -** the main table row automatically deletes corresponding index rows, -** the FORDELETE flag hint allows those alternative storage engines to -** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK -** and DELETE operations as no-ops, and any READ operation against a -** FORDELETE cursor may return a null row: 0x01 0x00. -*/ -#define BTREE_WRCSR 0x00000004 /* read-write cursor */ -#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ - -SQLITE_PRIVATE int sqlite3BtreeCursor( - Btree*, /* BTree containing table to open */ - Pgno iTable, /* Index of root page */ - int wrFlag, /* 1 for writing. 0 for read-only */ - struct KeyInfo*, /* First argument to compare function */ - BtCursor *pCursor /* Space to write cursor structure */ -); -SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void); -SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*); -#endif -SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); -#ifdef SQLITE_ENABLE_CURSOR_HINTS -SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); -#endif - -SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeTableMoveto( - BtCursor*, - i64 intKey, - int bias, - int *pRes -); -SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( - BtCursor*, - UnpackedRecord *pUnKey, - int *pRes -); -SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); - -/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */ -#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. -** -** Index btrees (used for indexes and also WITHOUT ROWID tables) contain -** an arbitrary key and no data. These btrees have pKey,nKey set to the -** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem -** fields give an array of Mem objects that are a decomposition of the key. -** The nMem field might be zero, indicating that no decomposition is available. -** -** Table btrees (used for rowid tables) contain an integer rowid used as -** the key and passed in the nKey field. The pKey field is zero. -** pData,nData hold the content of the new entry. nZero extra zero bytes -** are appended to the end of the content when constructing the entry. -** The aMem,nMem fields are uninitialized for table btrees. -** -** Field usage summary: -** -** Table BTrees Index Btrees -** -** pKey always NULL encoded key -** nKey the ROWID length of pKey -** pData data not used -** aMem not used decomposed key value -** nMem not used entries in aMem -** nData length of pData not used -** nZero extra zeros after pData not used -** -** This object is used to pass information into sqlite3BtreeInsert(). The -** same information used to be passed as five separate parameters. But placing -** the information into this object helps to keep the interface more -** organized and understandable, and it also helps the resulting code to -** run a little faster by using fewer registers for parameter passing. -*/ -struct BtreePayload { - const void *pKey; /* Key content for indexes. NULL for tables */ - sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ - const void *pData; /* Data for tables. */ - sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */ - u16 nMem; /* Number of aMem[] value. Might be zero */ - int nData; /* Size of pData. 0 if none. */ - int nZero; /* Extra zero data appended after pData,nData */ -}; - -SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, - int flags, int seekResult); -SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); -SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); -SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); -SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*); -SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); -SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*); - -SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( - sqlite3 *db, /* Database connection that is running the check */ - Btree *p, /* The btree to be checked */ - Pgno *aRoot, /* An array of root pages numbers for individual trees */ - sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */ - int nRoot, /* Number of entries in aRoot[] */ - int mxErr, /* Stop reporting errors after this many */ - int *pnErr, /* OUT: Write number of errors seen to this variable */ - char **pzOut /* OUT: Write the error message string here */ -); -SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); -SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*); - -#ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); -#endif -SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); -SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); -SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); -SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*); -#else -# define sqlite3BtreeSeekCount(X) 0 -#endif - -#ifndef NDEBUG -SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); -#endif -SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*); - -SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*); - -#ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); -SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); -#endif - -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); -#endif - -SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64); - -SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree*); - -/* -** If we are not using shared cache, then there is no need to -** use mutexes to access the BtShared structures. So make the -** Enter and Leave procedures no-ops. -*/ -#ifndef SQLITE_OMIT_SHARED_CACHE -SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); -SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); -SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree*); -#else -# define sqlite3BtreeEnter(X) -# define sqlite3BtreeEnterAll(X) -# define sqlite3BtreeSharable(X) 0 -# define sqlite3BtreeEnterCursor(X) -# define sqlite3BtreeConnectionCount(X) 1 -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE -SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); -SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); -#ifndef NDEBUG - /* These routines are used inside assert() statements only. */ -SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); -SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); -SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); -#endif -#else - -# define sqlite3BtreeLeave(X) -# define sqlite3BtreeLeaveCursor(X) -# define sqlite3BtreeLeaveAll(X) - -# define sqlite3BtreeHoldsMutex(X) 1 -# define sqlite3BtreeHoldsAllMutexes(X) 1 -# define sqlite3SchemaMutexHeld(X,Y,Z) 1 -#endif - - -#endif /* SQLITE_BTREE_H */ - -/************** End of btree.h ***********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include vdbe.h in the middle of sqliteInt.h ******************/ -/************** Begin file vdbe.h ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Header file for the Virtual DataBase Engine (VDBE) -** -** This header defines the interface to the virtual database engine -** or VDBE. The VDBE implements an abstract machine that runs a -** simple program to access and modify the underlying database. -*/ -#ifndef SQLITE_VDBE_H -#define SQLITE_VDBE_H -/* #include */ - -/* -** A single VDBE is an opaque structure named "Vdbe". Only routines -** in the source file sqliteVdbe.c are allowed to see the insides -** of this structure. -*/ -typedef struct Vdbe Vdbe; - -/* -** The names of the following types declared in vdbeInt.h are required -** for the VdbeOp definition. -*/ -typedef struct sqlite3_value Mem; -typedef struct SubProgram SubProgram; -typedef struct SubrtnSig SubrtnSig; - -/* -** A signature for a reusable subroutine that materializes the RHS of -** an IN operator. -*/ -struct SubrtnSig { - int selId; /* SELECT-id for the SELECT statement on the RHS */ - u8 bComplete; /* True if fully coded and available for reusable */ - char *zAff; /* Affinity of the overall IN expression */ - int iTable; /* Ephemeral table generated by the subroutine */ - int iAddr; /* Subroutine entry address */ - int regReturn; /* Register used to hold return address */ -}; - -/* -** A single instruction of the virtual machine has an opcode -** and as many as three operands. The instruction is recorded -** as an instance of the following structure: -*/ -struct VdbeOp { - u8 opcode; /* What operation to perform */ - signed char p4type; /* One of the P4_xxx constants for p4 */ - u16 p5; /* Fifth parameter is an unsigned 16-bit integer */ - int p1; /* First operand */ - int p2; /* Second parameter (often the jump destination) */ - int p3; /* The third parameter */ - union p4union { /* fourth parameter */ - int i; /* Integer value if p4type==P4_INT32 */ - void *p; /* Generic pointer */ - char *z; /* Pointer to data for string (char array) types */ - i64 *pI64; /* Used when p4type is P4_INT64 */ - double *pReal; /* Used when p4type is P4_REAL */ - FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ - sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ - CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ - Mem *pMem; /* Used when p4type is P4_MEM */ - VTable *pVtab; /* Used when p4type is P4_VTAB */ - KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ - u32 *ai; /* Used when p4type is P4_INTARRAY */ - SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ - Table *pTab; /* Used when p4type is P4_TABLE */ - SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */ -#ifdef SQLITE_ENABLE_CURSOR_HINTS - Expr *pExpr; /* Used when p4type is P4_EXPR */ -#endif - } p4; -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - char *zComment; /* Comment to improve readability */ -#endif -#ifdef SQLITE_VDBE_COVERAGE - u32 iSrcLine; /* Source-code line that generated this opcode - ** with flags in the upper 8 bits */ -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - u64 nExec; - u64 nCycle; -#endif -}; -typedef struct VdbeOp VdbeOp; - - -/* -** A sub-routine used to implement a trigger program. -*/ -struct SubProgram { - VdbeOp *aOp; /* Array of opcodes for sub-program */ - int nOp; /* Elements in aOp[] */ - int nMem; /* Number of memory cells required */ - int nCsr; /* Number of cursors required */ - u8 *aOnce; /* Array of OP_Once flags */ - void *token; /* id that may be used to recursive triggers */ - SubProgram *pNext; /* Next sub-program already visited */ -}; - -/* -** A smaller version of VdbeOp used for the VdbeAddOpList() function because -** it takes up less space. -*/ -struct VdbeOpList { - u8 opcode; /* What operation to perform */ - signed char p1; /* First operand */ - signed char p2; /* Second parameter (often the jump destination) */ - signed char p3; /* Third parameter */ -}; -typedef struct VdbeOpList VdbeOpList; - -/* -** Allowed values of VdbeOp.p4type -*/ -#define P4_NOTUSED 0 /* The P4 parameter is not used */ -#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ -#define P4_STATIC (-1) /* Pointer to a static string */ -#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_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 (-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 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 sqlite3_context object */ -#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */ -#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */ - -/* Error message codes for OP_Halt */ -#define P5_ConstraintNotNull 1 -#define P5_ConstraintUnique 2 -#define P5_ConstraintCheck 3 -#define P5_ConstraintFK 4 - -/* -** The Vdbe.aColName array contains 5n Mem structures, where n is the -** number of columns of data returned by the statement. -*/ -#define COLNAME_NAME 0 -#define COLNAME_DECLTYPE 1 -#define COLNAME_DATABASE 2 -#define COLNAME_TABLE 3 -#define COLNAME_COLUMN 4 -#ifdef SQLITE_ENABLE_COLUMN_METADATA -# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ -#else -# ifdef SQLITE_OMIT_DECLTYPE -# define COLNAME_N 1 /* Store only the name */ -# else -# define COLNAME_N 2 /* Store the name and decltype */ -# endif -#endif - -/* -** The following macro converts a label returned by sqlite3VdbeMakeLabel() -** into an index into the Parse.aLabel[] array that contains the resolved -** address of that label. -*/ -#define ADDR(X) (~(X)) - -/* -** The makefile scans the vdbe.c source file and creates the "opcodes.h" -** header file that defines a number for each opcode used by the VDBE. -*/ -/************** Include opcodes.h in the middle of vdbe.h ********************/ -/************** Begin file opcodes.h *****************************************/ -/* Automatically generated. Do not edit */ -/* See the tool/mkopcodeh.tcl script for details */ -#define OP_Savepoint 0 -#define OP_AutoCommit 1 -#define OP_Transaction 2 -#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_Init 8 /* jump0, synopsis: Start at P2 */ -#define OP_Goto 9 /* jump */ -#define OP_Gosub 10 /* jump */ -#define OP_InitCoroutine 11 /* jump0 */ -#define OP_Yield 12 /* jump0 */ -#define OP_MustBeInt 13 /* jump0 */ -#define OP_Jump 14 /* jump */ -#define OP_Once 15 /* jump */ -#define OP_If 16 /* jump */ -#define OP_IfNot 17 /* jump */ -#define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */ -#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ -#define OP_SeekLT 21 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */ -#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */ -#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekRowid 30 /* jump0, synopsis: intkey=r[P3] */ -#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ -#define OP_Last 32 /* jump0 */ -#define OP_IfSizeBetween 33 /* jump */ -#define OP_SorterSort 34 /* jump */ -#define OP_Sort 35 /* jump */ -#define OP_Rewind 36 /* jump0 */ -#define OP_SorterNext 37 /* jump */ -#define OP_Prev 38 /* jump */ -#define OP_Next 39 /* jump */ -#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxLT 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_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */ -#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 48 /* jump0 */ -#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ -#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ -#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ -#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ -#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */ -#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */ -#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ -#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 62 /* jump */ -#define OP_VNext 63 /* jump */ -#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto 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) */ -#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_OpenRead 102 /* synopsis: root=P2 iDb=P3 */ -#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenDup 114 -#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ -#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */ -#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#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_DropTrigger 153 -#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#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_VCheck 174 -#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ -#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 177 -#define OP_Pagecount 178 -#define OP_MaxPgcnt 179 -#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ -#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */ -#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */ -#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */ -#define OP_Trace 184 -#define OP_CursorHint 185 -#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */ -#define OP_Noop 187 -#define OP_Explain 188 -#define OP_Abortable 189 - -/* Properties such as "out2" or "jump" that are specified in -** comments following the "case" for each opcode in the vdbe.c -** are encoded into bitvectors as follows: -*/ -#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */ -#define OPFLG_IN1 0x02 /* in1: P1 is an input */ -#define OPFLG_IN2 0x04 /* in2: P2 is an input */ -#define OPFLG_IN3 0x08 /* in3: P3 is an input */ -#define OPFLG_OUT2 0x10 /* out2: P2 is an output */ -#define OPFLG_OUT3 0x20 /* out3: P3 is an output */ -#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */ -#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */ -#define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\ -/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\ -/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\ -/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\ -/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\ -/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ -/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ -/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\ -/* 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, 0x40, 0x00,\ -/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\ -/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ -/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\ -/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ -/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ -/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ -/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\ -/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ -/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\ -/* 184 */ 0x00, 0x00, 0x00, 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 64 /* Maximum JUMP opcode */ - -/************** End of opcodes.h *********************************************/ -/************** Continuing where we left off in vdbe.h ***********************/ - -/* -** Additional non-public SQLITE_PREPARE_* flags -*/ -#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ -#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */ - -/* -** Prototypes for the VDBE interface. See comments on the implementation -** for a description of what each of these routines does. -*/ -SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*); -SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe*,int); -SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe*,int,const char*); -SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); -SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int); -SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); -#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) -SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); -SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); -#else -# define sqlite3VdbeVerifyNoMallocRequired(A,B) -# define sqlite3VdbeVerifyNoResultRow(A) -#endif -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); -SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int); -#else -# define sqlite3VdbeVerifyAbortable(A,B) -# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D) -#endif -SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); -#ifndef SQLITE_OMIT_EXPLAIN -SQLITE_PRIVATE int sqlite3VdbeExplain(Parse*,u8,const char*,...); -SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); -SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); -# define ExplainQueryPlan(P) sqlite3VdbeExplain P -# ifdef SQLITE_ENABLE_STMT_SCANSTATUS -# define ExplainQueryPlan2(V,P) (V = sqlite3VdbeExplain P) -# else -# define ExplainQueryPlan2(V,P) ExplainQueryPlan(P) -# endif -# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) -# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) -#else -# define ExplainQueryPlan(P) -# define ExplainQueryPlan2(V,P) -# define ExplainQueryPlanPop(P) -# define ExplainQueryPlanParent(P) 0 -# define sqlite3ExplainBreakpoint(A,B) /*no-op*/ -#endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) -SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*); -#else -# define sqlite3ExplainBreakpoint(A,B) /*no-op*/ -#endif -SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16); -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8); -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); -SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); -SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5); -SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe*, int); -SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); -SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); -SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr); -SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int); -#else -# define sqlite3VdbeReleaseRegisters(P,A,N,M,F) -#endif -SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); -SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type); -SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); -SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*); -SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); -SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); -SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); -#endif -SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); -SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); -SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); -SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); -SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*); -SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*); -#endif -SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); -SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); -SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); -SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); -#ifndef SQLITE_OMIT_TRACE -SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); -#endif -SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); -SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*); - -SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); -SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*); - -typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); -SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); - -SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); -SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*); - -SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); - -SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*); -#ifdef SQLITE_ENABLE_BYTECODE_VTAB -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*); -#endif - -/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra -** comments on each VDBE opcode. -** -** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op -** comments in VDBE programs that show key decision points in the code -** generator. -*/ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS -SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); -# define VdbeComment(X) sqlite3VdbeComment X -SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); -# define VdbeNoopComment(X) sqlite3VdbeNoopComment X -# ifdef SQLITE_ENABLE_MODULE_COMMENTS -# define VdbeModuleComment(X) sqlite3VdbeNoopComment X -# else -# define VdbeModuleComment(X) -# endif -#else -# define VdbeComment(X) -# define VdbeNoopComment(X) -# define VdbeModuleComment(X) -#endif - -/* -** The VdbeCoverage macros are used to set a coverage testing point -** for VDBE branch instructions. The coverage testing points are line -** numbers in the sqlite3.c source file. VDBE branch coverage testing -** only works with an amalgamation build. That's ok since a VDBE branch -** coverage build designed for testing the test suite only. No application -** should ever ship with VDBE branch coverage measuring turned on. -** -** VdbeCoverage(v) // Mark the previously coded instruction -** // as a branch -** -** VdbeCoverageIf(v, conditional) // Mark previous if conditional true -** -** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken -** -** VdbeCoverageNeverTaken(v) // Previous branch is never taken -** -** VdbeCoverageNeverNull(v) // Previous three-way branch is only -** // taken on the first two ways. The -** // NULL option is not possible -** -** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested -** // in distinguishing equal and not-equal. -** -** Every VDBE branch operation must be tagged with one of the macros above. -** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and -** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() -** routine in vdbe.c, alerting the developer to the missed tag. -** -** During testing, the test application will invoke -** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback -** routine that is invoked as each bytecode branch is taken. The callback -** contains the sqlite3.c source line number of the VdbeCoverage macro and -** flags to indicate whether or not the branch was taken. The test application -** is responsible for keeping track of this and reporting byte-code branches -** that are never taken. -** -** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the -** vdbe.c source file for additional information. -*/ -#ifdef SQLITE_VDBE_COVERAGE -SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); -# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) -# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) -# define VdbeCoverageAlwaysTaken(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); -# define VdbeCoverageNeverTaken(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); -# define VdbeCoverageNeverNull(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); -# define VdbeCoverageNeverNullIf(v,x) \ - if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); -# define VdbeCoverageEqNe(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); -# define VDBE_OFFSET_LINENO(x) (__LINE__+x) -#else -# define VdbeCoverage(v) -# define VdbeCoverageIf(v,x) -# define VdbeCoverageAlwaysTaken(v) -# define VdbeCoverageNeverTaken(v) -# define VdbeCoverageNeverNull(v) -# define VdbeCoverageNeverNullIf(v,x) -# define VdbeCoverageEqNe(v) -# define VDBE_OFFSET_LINENO(x) 0 -#endif - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); -SQLITE_PRIVATE void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int); -SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int); -#else -# define sqlite3VdbeScanStatus(a,b,c,d,e,f) -# define sqlite3VdbeScanStatusRange(a,b,c,d) -# define sqlite3VdbeScanStatusCounters(a,b,c,d) -#endif - -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) -SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); -#endif - -#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr); -#endif - -#endif /* SQLITE_VDBE_H */ - -/************** End of vdbe.h ************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include pcache.h in the middle of sqliteInt.h ****************/ -/************** Begin file pcache.h ******************************************/ -/* -** 2008 August 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite page cache -** subsystem. -*/ - -#ifndef _PCACHE_H_ - -typedef struct PgHdr PgHdr; -typedef struct PCache PCache; - -/* -** Every page in the cache is controlled by an instance of the following -** structure. -*/ -struct PgHdr { - sqlite3_pcache_page *pPage; /* Pcache object page handle */ - void *pData; /* Page data */ - void *pExtra; /* Extra content */ - PCache *pCache; /* PRIVATE: Cache that owns this page */ - PgHdr *pDirty; /* Transient list of dirty sorted by pgno */ - Pager *pPager; /* The pager this page is part of */ - Pgno pgno; /* Page number for this page */ -#ifdef SQLITE_CHECK_PAGES - u32 pageHash; /* Hash of page content */ -#endif - u16 flags; /* PGHDR flags defined below */ - - /********************************************************************** - ** Elements above, except pCache, are public. All that follow are - ** private to pcache.c and should not be accessed by other modules. - ** pCache is grouped with the public elements for efficiency. - */ - i64 nRef; /* Number of users of this page */ - PgHdr *pDirtyNext; /* Next element in list of dirty pages */ - PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ - /* NB: pDirtyNext and pDirtyPrev are undefined if the - ** PgHdr object is not dirty */ -}; - -/* Bit values for PgHdr.flags */ -#define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */ -#define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */ -#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */ -#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before - ** writing this page to the database */ -#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */ -#define PGHDR_MMAP 0x020 /* This is an mmap page object */ - -#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */ - -/* Initialize and shutdown the page cache subsystem */ -SQLITE_PRIVATE int sqlite3PcacheInitialize(void); -SQLITE_PRIVATE void sqlite3PcacheShutdown(void); - -/* Page cache buffer management: -** These routines implement SQLITE_CONFIG_PAGECACHE. -*/ -SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); - -/* Create a new pager cache. -** Under memory stress, invoke xStress to try to make pages clean. -** Only clean and unpinned pages can be reclaimed. -*/ -SQLITE_PRIVATE int sqlite3PcacheOpen( - int szPage, /* Size of every page */ - int szExtra, /* Extra space associated with each page */ - int bPurgeable, /* True if pages are on backing store */ - int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ - void *pStress, /* Argument to xStress */ - PCache *pToInit /* Preallocated space for the PCache */ -); - -/* Modify the page-size after the cache has been created. */ -SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *, int); - -/* Return the size in bytes of a PCache object. Used to preallocate -** storage space. -*/ -SQLITE_PRIVATE int sqlite3PcacheSize(void); - -/* One release per successful fetch. Page is pinned until released. -** Reference counted. -*/ -SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag); -SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**); -SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage); -SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); - -SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ -SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ -SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ -SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ -SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache*); - -/* Change a page number. Used by incr-vacuum. */ -SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); - -/* Remove all pages with pgno>x. Reset the cache if x==0 */ -SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); - -/* Get a list of all dirty pages in the cache, sorted by page number */ -SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); - -/* Reset and close the cache object */ -SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); - -/* Clear flags from pages of the page cache */ -SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); - -/* Discard the contents of the cache */ -SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); - -/* Return the total number of outstanding page references */ -SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*); - -/* Increment the reference count of an existing page */ -SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); - -SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*); - -/* Return the total number of pages stored in the cache */ -SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); - -#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) -/* Iterate through all dirty pages currently stored in the cache. This -** interface is only available if SQLITE_CHECK_PAGES is defined when the -** library is built. -*/ -SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); -#endif - -#if defined(SQLITE_DEBUG) -/* Check invariants on a PgHdr object */ -SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr*); -#endif - -/* Set and get the suggested cache-size for the specified pager-cache. -** -** If no global maximum is configured, then the system attempts to limit -** the total number of pages cached by purgeable pager-caches to the sum -** of the suggested cache-sizes. -*/ -SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); -#ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); -#endif - -/* Set or get the suggested spill-size for the specified pager-cache. -** -** The spill-size is the minimum number of pages in cache before the cache -** will attempt to spill dirty pages by calling xStress. -*/ -SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *, int); - -/* Free up as much memory as possible from the page cache */ -SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*); - -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -/* Try to return memory used by the pcache module to the main memory heap */ -SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); -#endif - -#ifdef SQLITE_TEST -SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); -#endif - -SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); - -/* Return the header size */ -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void); -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); - -/* Number of dirty pages as a percentage of the configured cache size */ -SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); - -#ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); -#endif - -#endif /* _PCACHE_H_ */ - -/************** End of pcache.h **********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include mutex.h in the middle of sqliteInt.h *****************/ -/************** Begin file mutex.h *******************************************/ -/* -** 2007 August 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the common header for all mutex implementations. -** The sqliteInt.h header #includes this file so that it is available -** to all source files. We break it out in an effort to keep the code -** better organized. -** -** NOTE: source files should *not* #include this header file directly. -** Source files should #include the sqliteInt.h file and let that file -** include this one indirectly. -*/ - - -/* -** Figure out what version of the code to use. The choices are -** -** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The -** mutexes implementation cannot be overridden -** at start-time. -** -** SQLITE_MUTEX_NOOP For single-threaded applications. No -** mutual exclusion is provided. But this -** implementation can be overridden at -** start-time. -** -** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. -** -** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. -*/ -#if !SQLITE_THREADSAFE -# define SQLITE_MUTEX_OMIT -#endif -#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) -# if SQLITE_OS_UNIX -# define SQLITE_MUTEX_PTHREADS -# elif SQLITE_OS_WIN -# define SQLITE_MUTEX_W32 -# else -# define SQLITE_MUTEX_NOOP -# endif -#endif - -#ifdef SQLITE_MUTEX_OMIT -/* -** If this is a no-op implementation, implement everything as macros. -*/ -#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) -#define sqlite3_mutex_free(X) -#define sqlite3_mutex_enter(X) -#define sqlite3_mutex_try(X) SQLITE_OK -#define sqlite3_mutex_leave(X) -#define sqlite3_mutex_held(X) ((void)(X),1) -#define sqlite3_mutex_notheld(X) ((void)(X),1) -#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) -#define sqlite3MutexInit() SQLITE_OK -#define sqlite3MutexEnd() -#define MUTEX_LOGIC(X) -#else -#define MUTEX_LOGIC(X) X -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); -#endif /* defined(SQLITE_MUTEX_OMIT) */ - -/************** End of mutex.h ***********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default -** synchronous setting to EXTRA. It is no longer supported. -*/ -#ifdef SQLITE_EXTRA_DURABLE -# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE -# define SQLITE_DEFAULT_SYNCHRONOUS 3 -#endif - -/* -** Default synchronous levels. -** -** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ -** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. -** -** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS -** OFF 1 0 -** NORMAL 2 1 -** FULL 3 2 -** EXTRA 4 3 -** -** The "PRAGMA synchronous" statement also uses the zero-based numbers. -** In other words, the zero-based numbers are used for all external interfaces -** and the one-based values are used internally. -*/ -#ifndef SQLITE_DEFAULT_SYNCHRONOUS -# define SQLITE_DEFAULT_SYNCHRONOUS 2 -#endif -#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS -# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS -#endif - -/* -** Each database file to be accessed by the system is an instance -** of the following structure. There are normally two of these structures -** in the sqlite.aDb[] array. aDb[0] is the main database file and -** aDb[1] is the database file used to hold temporary tables. Additional -** databases may be attached. -*/ -struct Db { - char *zDbSName; /* Name of this database. (schema name, not filename) */ - Btree *pBt; /* The B*Tree structure for this database file */ - u8 safety_level; /* How aggressive at syncing data to disk */ - u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ - Schema *pSchema; /* Pointer to database schema (possibly shared) */ -}; - -/* -** An instance of the following structure stores a database schema. -** -** Most Schema objects are associated with a Btree. The exception is -** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing. -** In shared cache mode, a single Schema object can be shared by multiple -** Btrees that refer to the same underlying BtShared object. -** -** Schema objects are automatically deallocated when the last Btree that -** references them is destroyed. The TEMP Schema is manually freed by -** sqlite3_close(). -* -** A thread must be holding a mutex on the corresponding Btree in order -** to access Schema content. This implies that the thread must also be -** holding a mutex on the sqlite3 connection pointer that owns the Btree. -** For a TEMP Schema, only the connection mutex is required. -*/ -struct Schema { - int schema_cookie; /* Database schema version number for this file */ - int iGeneration; /* Generation counter. Incremented with each change */ - Hash tblHash; /* All tables indexed by name */ - Hash idxHash; /* All (named) indices indexed by name */ - Hash trigHash; /* All triggers indexed by name */ - Hash fkeyHash; /* All foreign keys by referenced table name */ - Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ - u8 file_format; /* Schema format version for this file */ - u8 enc; /* Text encoding used by this database */ - u16 schemaFlags; /* Flags associated with this schema */ - int cache_size; /* Number of pages to use in the cache */ -}; - -/* -** These macros can be used to test, set, or clear bits in the -** Db.pSchema->flags field. -*/ -#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P)) -#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0) -#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P) -#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P) - -/* -** Allowed values for the DB.pSchema->flags field. -** -** The DB_SchemaLoaded flag is set after the database schema has been -** read into internal hash tables. -** -** DB_UnresetViews means that one or more views have column names that -** have been filled out. If the schema changes, these column names might -** changes and so the view will need to be reset. -*/ -#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ -#define DB_UnresetViews 0x0002 /* Some views have defined column names */ -#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */ - -/* -** The number of different kinds of things that can be limited -** using the sqlite3_limit() interface. -*/ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) - -/* -** Lookaside malloc is a set of fixed-size buffers that can be used -** to satisfy small transient memory allocation requests for objects -** associated with a particular database connection. The use of -** lookaside malloc provides a significant performance enhancement -** (approx 10%) by avoiding numerous malloc/free requests while parsing -** SQL statements. -** -** The Lookaside structure holds configuration information about the -** lookaside malloc subsystem. Each available memory allocation in -** the lookaside subsystem is stored on a linked list of LookasideSlot -** objects. -** -** Lookaside allocations are only allowed for objects that are associated -** with a particular database connection. Hence, schema information cannot -** be stored in lookaside because in shared cache mode the schema information -** is shared by multiple database connections. Therefore, while parsing -** schema information, the Lookaside.bEnabled flag is cleared so that -** lookaside allocations are not used to construct the schema objects. -** -** New lookaside allocations are only allowed if bDisable==0. When -** bDisable is greater than zero, sz is set to zero which effectively -** disables lookaside without adding a new test for the bDisable flag -** in a performance-critical path. sz should be set by to szTrue whenever -** bDisable changes back to zero. -** -** Lookaside buffers are initially held on the pInit list. As they are -** used and freed, they are added back to the pFree list. New allocations -** come off of pFree first, then pInit as a fallback. This dual-list -** allows use to compute a high-water mark - the maximum number of allocations -** outstanding at any point in the past - by subtracting the number of -** allocations on the pInit list from the total number of allocations. -** -** Enhancement on 2019-12-12: Two-size-lookaside -** The default lookaside configuration is 100 slots of 1200 bytes each. -** The larger slot sizes are important for performance, but they waste -** a lot of space, as most lookaside allocations are less than 128 bytes. -** The two-size-lookaside enhancement breaks up the lookaside allocation -** into two pools: One of 128-byte slots and the other of the default size -** (1200-byte) slots. Allocations are filled from the small-pool first, -** failing over to the full-size pool if that does not work. Thus more -** lookaside slots are available while also using less memory. -** This enhancement can be omitted by compiling with -** SQLITE_OMIT_TWOSIZE_LOOKASIDE. -*/ -struct Lookaside { - u32 bDisable; /* Only operate the lookaside when zero */ - u16 sz; /* Size of each buffer in bytes */ - u16 szTrue; /* True value of sz, even if disabled */ - u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ - u32 nSlot; /* Number of lookaside slots allocated */ - u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ - LookasideSlot *pInit; /* List of buffers not previously used */ - LookasideSlot *pFree; /* List of available buffers */ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - LookasideSlot *pSmallInit; /* List of small buffers not previously used */ - LookasideSlot *pSmallFree; /* List of available small buffers */ - void *pMiddle; /* First byte past end of full-size buffers and - ** the first byte of LOOKASIDE_SMALL buffers */ -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - void *pStart; /* First byte of available memory space */ - void *pEnd; /* First byte past end of available space */ - void *pTrueEnd; /* True value of pEnd, when db->pnBytesFreed!=0 */ -}; -struct LookasideSlot { - LookasideSlot *pNext; /* Next buffer in the list of free buffers */ -}; - -#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0 -#define EnableLookaside db->lookaside.bDisable--;\ - db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue - -/* Size of the smaller allocations in two-size lookaside */ -#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE -# define LOOKASIDE_SMALL 0 -#else -# define LOOKASIDE_SMALL 128 -#endif - -/* -** A hash table for built-in function definitions. (Application-defined -** functions use a regular table table from hash.h.) -** -** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. -** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() -** macro to compute a hash on the function name. -*/ -#define SQLITE_FUNC_HASH_SZ 23 -struct FuncDefHash { - FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ -}; -#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) - -/* -** typedef for the authorization callback function. -*/ -typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, - const char*); - -#ifndef SQLITE_OMIT_DEPRECATED -/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing -** in the style of sqlite3_trace() -*/ -#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */ -#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */ -#else -#define SQLITE_TRACE_LEGACY 0 -#define SQLITE_TRACE_XPROFILE 0 -#endif /* SQLITE_OMIT_DEPRECATED */ -#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */ - -/* -** Maximum number of 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. -*/ -struct sqlite3 { - sqlite3_vfs *pVfs; /* OS Interface */ - struct Vdbe *pVdbe; /* List of active virtual machines */ - CollSeq *pDfltColl; /* BINARY collseq for the database encoding */ - sqlite3_mutex *mutex; /* Connection mutex */ - Db *aDb; /* All backends */ - int nDb; /* Number of backends currently in use */ - u32 mDbFlags; /* flags recording internal state */ - u64 flags; /* flags settable by pragmas. See below */ - i64 lastRowid; /* ROWID of most recent insert (see above) */ - i64 szMmap; /* Default mmap_size setting */ - u32 nSchemaLock; /* Do not reset the schema when non-zero */ - unsigned int openFlags; /* Flags passed to 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 */ - 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 */ - u8 mallocFailed; /* True if we have seen a malloc failure */ - u8 bBenignMalloc; /* Do not require OOMs if true */ - u8 dfltLockMode; /* Default locking-mode for attached dbs */ - signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ - u8 suppressErr; /* Do not issue error messages if true */ - u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ - u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ - 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 */ - i64 nChange; /* Value returned by sqlite3_changes() */ - i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ - int aLimit[SQLITE_N_LIMIT]; /* Limits */ - int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ - struct sqlite3InitInfo { /* Information used during initialization */ - Pgno newTnum; /* Rootpage of table being initialized */ - u8 iDb; /* Which db file is being initialized */ - u8 busy; /* TRUE if currently initializing */ - 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 */ - 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 */ - int nVdbeWrite; /* Number of active VDBEs that read and write */ - int nVdbeExec; /* Number of nested calls to VdbeExec() */ - int nVDestroy; /* Number of active OP_VDestroy operations */ - int nExtension; /* Number of loaded extensions */ - void **aExtension; /* Array of shared library handles */ - union { - 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 */ -#ifndef SQLITE_OMIT_DEPRECATED - void (*xProfile)(void*,const char*,u64); /* Profiling function */ - void *pProfileArg; /* Argument to profile function */ -#endif - void *pCommitArg; /* Argument to xCommitCallback() */ - int (*xCommitCallback)(void*); /* Invoked at every commit. */ - void *pRollbackArg; /* Argument to xRollbackCallback() */ - 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 */ - void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ - void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 - ); - PreUpdate *pPreUpdate; /* Context for active pre-update callback */ -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ -#ifndef SQLITE_OMIT_WAL - int (*xWalCallback)(void *, sqlite3 *, const char *, int); - void *pWalArg; -#endif - void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); - void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); - void *pCollNeededArg; - sqlite3_value *pErr; /* Most recent error message */ - union { - volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ - double notUsed1; /* Spacer */ - } u1; - Lookaside lookaside; /* Lookaside malloc configuration */ -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth; /* Access authorization function */ - void *pAuthArg; /* 1st argument to the access auth function */ -#endif -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - int (*xProgress)(void *); /* The progress callback */ - void *pProgressArg; /* Argument to the progress callback */ - unsigned nProgressOps; /* Number of opcodes for progress callback */ -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - int nVTrans; /* Allocated size of aVTrans */ - Hash aModule; /* populated by sqlite3_create_module() */ - VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ - VTable **aVTrans; /* Virtual tables with open transactions */ - VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ -#endif - Hash aFunc; /* Hash table of connection functions */ - Hash aCollSeq; /* All collating sequences */ - BusyHandler busyHandler; /* Busy callback */ - Db aDbStatic[2]; /* Static space for the 2 default backends */ - Savepoint *pSavepoint; /* List of active savepoints */ - int nAnalysisLimit; /* Number of index rows to ANALYZE */ - int busyTimeout; /* Busy handler timeout, in msec */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */ - int setlkFlags; /* Flags passed to setlk_timeout() */ -#endif - int nSavepoint; /* Number of non-transaction savepoints */ - int nStatement; /* Number of nested statement-transactions */ - i64 nDeferredCons; /* Net deferred constraints this transaction. */ - i64 nDeferredImmCons; /* Net deferred immediate constraints */ - int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ - DbClientData *pDbData; /* sqlite3_set_clientdata() content */ -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - /* The following variables are all protected by the STATIC_MAIN - ** mutex, not by sqlite3.mutex. They are used by code in notify.c. - ** - ** When X.pUnlockConnection==Y, that means that X is waiting for Y to - ** unlock so that it can proceed. - ** - ** When X.pBlockingConnection==Y, that means that something that X tried - ** tried to do recently failed with an SQLITE_LOCKED error due to locks - ** held by Y. - */ - sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ - sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ - void *pUnlockArg; /* Argument to xUnlockNotify */ - void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ - sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ -#endif -}; - -/* -** A macro to discover the encoding of a database. -*/ -#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) -#define ENC(db) ((db)->enc) - -/* -** A u64 constant where the lower 32 bits are all zeros. Only the -** upper 32 bits are included in the argument. Necessary because some -** C-compilers still do not accept LL integer literals. -*/ -#define HI(X) ((u64)(X)<<32) - -/* -** Possible values for the sqlite3.flags. -** -** Value constraints (enforced via assert()): -** SQLITE_FullFSync == PAGER_FULLFSYNC -** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC -** SQLITE_CacheSpill == PAGER_CACHE_SPILL -*/ -#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_SCHEMA */ -#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */ -#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ -#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */ -#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */ -#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ -#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ -#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and - ** vtabs in the schema definition */ -#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ - /* result set is empty */ -#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ -#define SQLITE_StmtScanStatus 0x00000400 /* Enable stmt_scanstats() counters */ -#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */ -#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */ -#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */ -#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */ -#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */ -#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */ -#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */ -#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */ -#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */ -#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */ -#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */ -#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ -#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ -#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ -#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ -#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ -#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ -#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ -#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ -#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ -#define SQLITE_EnableView 0x80000000 /* Enable the use of views */ -#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 */ -#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */ -#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */ -#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */ -#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */ -#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */ - -/* Flags used only if debugging */ -#ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */ -#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */ -#endif - -/* -** Allowed values for sqlite3.mDbFlags -*/ -#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ -#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ -#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ -#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */ -#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */ -#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */ -#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */ - -/* -** Bits of the sqlite3.dbOptFlags field that are used by the -** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to -** selectively disable various 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 /* WHERE-clause push-down opt */ -#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_IndexedExpr 0x01000000 /* Pull exprs from index when able */ -#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ -#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */ -#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ -#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */ -#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */ -#define SQLITE_AllOpts 0xffffffff /* All optimizations */ - -/* -** Macros for testing whether or not optimizations are enabled or disabled. -*/ -#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) -#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) - -/* -** Return true if it OK to factor constant expressions into the initialization -** code. The argument is a Parse object for the code generator. -*/ -#define ConstFactorOk(P) ((P)->okConstFactor) - -/* Possible values for the 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_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 -** structure. For global built-in functions (ex: substr(), max(), count()) -** a pointer to this structure is held in the sqlite3BuiltinFunctions object. -** For per-connection application-defined functions, a pointer to this -** structure is held in the db->aHash hash table. -** -** The u.pHash field is used by the global built-ins. The u.pDestructor -** field is used by per-connection app-def functions. -*/ -struct FuncDef { - i16 nArg; /* Number of arguments. -1 means unlimited */ - u32 funcFlags; /* Some combination of SQLITE_FUNC_* */ - void *pUserData; /* User data parameter */ - FuncDef *pNext; /* Next function with same name */ - void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ - void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ - void (*xValue)(sqlite3_context*); /* Current agg value */ - void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */ - const char *zName; /* SQL name of the function. */ - union { - FuncDef *pHash; /* Next with a different name but the same hash */ - FuncDestructor *pDestructor; /* Reference counted destructor function */ - } u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */ -}; - -/* -** This structure encapsulates a user-function destructor callback (as -** configured using create_function_v2()) and a reference counter. When -** create_function_v2() is called to create a function with a destructor, -** a single object of this type is allocated. FuncDestructor.nRef is set to -** the number of FuncDef objects created (either 1 or 3, depending on whether -** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor -** member of each of the new FuncDef objects is set to point to the allocated -** FuncDestructor. -** -** Thereafter, when one of the FuncDef objects is deleted, the reference -** count on this object is decremented. When it reaches 0, the destructor -** is invoked and the FuncDestructor structure freed. -*/ -struct FuncDestructor { - int nRef; - void (*xDestroy)(void *); - void *pUserData; -}; - -/* -** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF -** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And -** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There -** are assert() statements in the code to verify this. -** -** Value constraints (enforced via assert()): -** 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_BYTELEN == OPFLAG_BYTELENARG -** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API -** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API -** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!! -** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API -** -** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the -** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is -** used internally and if set means that the function has side effects. -** SQLITE_INNOCUOUS is used by application code and means "not unsafe". -** See multiple instances of tag-20230109-1. -*/ -#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ -#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ -#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */ -#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */ -#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ -#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ -#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ -#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */ -#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ -/* 0x0200 -- available for reuse */ -#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ -#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ -#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ -#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_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */ -#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 */ -/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */ -#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 */ -/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */ -#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ - -/* Identifier numbers for each in-line function */ -#define INLINEFUNC_coalesce 0 -#define INLINEFUNC_implies_nonnull_row 1 -#define INLINEFUNC_expr_implies_expr 2 -#define INLINEFUNC_expr_compare 3 -#define INLINEFUNC_affinity 4 -#define INLINEFUNC_iif 5 -#define INLINEFUNC_sqlite_offset 6 -#define INLINEFUNC_unlikely 99 /* Default case */ - -/* -** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are -** used to create the initializers for the FuncDef structures. -** -** FUNCTION(zName, nArg, iArg, bNC, xFunc) -** Used to create a scalar function definition of a function zName -** implemented by C function xFunc that accepts nArg arguments. The -** value passed as iArg is cast to a (void*) and made available -** as the user-data (sqlite3_user_data()) for the function. If -** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. -** -** VFUNCTION(zName, nArg, iArg, bNC, xFunc) -** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag. -** -** SFUNCTION(zName, nArg, iArg, bNC, xFunc) -** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and -** adds the SQLITE_DIRECTONLY flag. -** -** INLINE_FUNC(zName, nArg, iFuncId, mFlags) -** zName is the name of a function that is implemented by in-line -** byte code rather than by the usual callbacks. The iFuncId -** parameter determines the function id. The mFlags parameter is -** optional SQLITE_FUNC_ flags for this function. -** -** TEST_FUNC(zName, nArg, iFuncId, mFlags) -** zName is the name of a test-only function implemented by in-line -** byte code rather than by the usual callbacks. The iFuncId -** parameter determines the function id. The mFlags parameter is -** optional SQLITE_FUNC_ flags for this function. -** -** DFUNCTION(zName, nArg, iArg, bNC, xFunc) -** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and -** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions -** and functions like sqlite_version() that can change, but not during -** 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 -** ignored and the user-data for these functions is set to an -** arbitrary non-NULL pointer. The bNC parameter is not used. -** -** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) -** Used to create an aggregate function definition implemented by -** the C functions xStep and xFinal. The first four parameters -** are interpreted in the same way as the first 4 parameters to -** FUNCTION(). -** -** 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 -** FUNCTION(). -** -** LIKEFUNC(zName, nArg, pArg, flags) -** Used to create a scalar function definition of a function zName -** that accepts nArg arguments and is implemented by a call to C -** function likeFunc. Argument pArg is cast to a (void *) and made -** available as the function user-data (sqlite3_user_data()). The -** FuncDef.flags variable is set to the value passed as the flags -** parameter. -*/ -#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_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_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_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, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\ - SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\ - ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \ - SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} } -#define INLINE_FUNC(zName, nArg, iArg, 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_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_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_BUILTIN|\ - SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ - (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} } -#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, 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_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_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_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_BUILTIN|\ - SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ - 0, 0, xFunc, 0, 0, 0, #zName, {0} } - - -/* -** All current savepoints are stored in a linked list starting at -** sqlite3.pSavepoint. The first element in the list is the most recently -** opened savepoint. Savepoints are added to the list by the vdbe -** OP_Savepoint instruction. -*/ -struct Savepoint { - char *zName; /* Savepoint name (nul-terminated) */ - i64 nDeferredCons; /* Number of deferred fk violations */ - i64 nDeferredImmCons; /* Number of deferred imm fk. */ - Savepoint *pNext; /* Parent savepoint (if any) */ -}; - -/* -** The following are used as the second parameter to sqlite3Savepoint(), -** and as the P1 argument to the OP_Savepoint instruction. -*/ -#define SAVEPOINT_BEGIN 0 -#define SAVEPOINT_RELEASE 1 -#define SAVEPOINT_ROLLBACK 2 - - -/* -** Each SQLite module (virtual table definition) is defined by an -** instance of the following structure, stored in the sqlite3.aModule -** hash table. -*/ -struct Module { - const sqlite3_module *pModule; /* Callback pointers */ - const char *zName; /* Name passed to create_module() */ - int nRefModule; /* Number of pointers to this object */ - void *pAux; /* pAux passed to create_module() */ - void (*xDestroy)(void *); /* Module destructor function */ - Table *pEpoTab; /* Eponymous table for this module */ -}; - -/* -** Information about each column of an SQL table is held in an instance -** of the Column structure, in the Table.aCol[] array. -** -** Definitions: -** -** "table column index" This is the index of the column in the -** Table.aCol[] array, and also the index of -** the column in the original CREATE TABLE stmt. -** -** "storage column index" This is the index of the column in the -** record BLOB generated by the OP_MakeRecord -** opcode. The storage column index is less than -** 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 *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.eCType. -** -** Values must match entries in the global constant arrays -** sqlite3StdTypeLen[] and 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 */ -#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ -#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ -#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ -#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ -#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 */ - -/* -** A "Collating Sequence" is defined by an instance of the following -** structure. Conceptually, a collating sequence consists of a name and -** a comparison routine that defines the order of that sequence. -** -** If CollSeq.xCmp is NULL, it means that the -** collating sequence is undefined. Indices built on an undefined -** collating sequence may not be read or written. -*/ -struct CollSeq { - char *zName; /* Name of the collating sequence, UTF-8 encoded */ - u8 enc; /* Text encoding handled by xCmp() */ - void *pUser; /* First argument to xCmp() */ - int (*xCmp)(void*,int, const void*, int, const void*); - void (*xDel)(void*); /* Destructor for pUser */ -}; - -/* -** A sort order can be either ASC or DESC. -*/ -#define SQLITE_SO_ASC 0 /* Sort in ascending order */ -#define SQLITE_SO_DESC 1 /* Sort in ascending order */ -#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */ - -/* -** Column affinity types. -** -** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and -** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve -** the speed a little by numbering the values consecutively. -** -** But rather than start with 0 or 1, we begin with 'A'. That way, -** when multiple affinity types are concatenated into a string and -** used as the P4 operand, they will be more readable. -** -** Note also that the numeric types are grouped together so that testing -** for a numeric type is a single comparison. And the BLOB type is first. -*/ -#define SQLITE_AFF_NONE 0x40 /* '@' */ -#define SQLITE_AFF_BLOB 0x41 /* 'A' */ -#define SQLITE_AFF_TEXT 0x42 /* 'B' */ -#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */ -#define SQLITE_AFF_INTEGER 0x44 /* 'D' */ -#define SQLITE_AFF_REAL 0x45 /* 'E' */ -#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */ -#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */ - -#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) - -/* -** The SQLITE_AFF_MASK values masks off the significant bits of an -** affinity value. -*/ -#define SQLITE_AFF_MASK 0x47 - -/* -** Additional bit values that can be ORed with an affinity without -** changing the affinity. -** -** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. -** It causes an assert() to fire if either operand to a comparison -** operator is NULL. It is added to certain comparison operators to -** prove that the operands are always NOT NULL. -*/ -#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ -#define SQLITE_NULLEQ 0x80 /* NULL=NULL */ -#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */ - -/* -** An object of this type is created for each virtual table present in -** the database schema. -** -** If the database schema is shared, then there is one instance of this -** structure for each database connection (sqlite3*) that uses the shared -** schema. This is because each database connection requires its own unique -** instance of the sqlite3_vtab* handle used to access the virtual table -** implementation. sqlite3_vtab* handles can not be shared between -** database connections, even when the rest of the in-memory database -** schema is shared, as the implementation often stores the database -** connection handle passed to it via the xConnect() or xCreate() method -** during initialization internally. This database connection handle may -** then be used by the virtual table implementation to access real tables -** within the database. So that they appear as part of the callers -** transaction, these accesses need to be made via the same database -** connection as that used to execute SQL operations on the virtual table. -** -** All VTable objects that correspond to a single table in a shared -** database schema are initially stored in a linked-list pointed to by -** the Table.pVTable member variable of the corresponding Table object. -** When an sqlite3_prepare() operation is required to access the virtual -** table, it searches the list for the VTable that corresponds to the -** database connection doing the preparing so as to use the correct -** sqlite3_vtab* handle in the compiled query. -** -** When an in-memory Table object is deleted (for example when the -** schema is being reloaded for some reason), the VTable objects are not -** deleted and the sqlite3_vtab* handles are not xDisconnect()ed -** immediately. Instead, they are moved from the Table.pVTable list to -** another linked list headed by the sqlite3.pDisconnect member of the -** corresponding sqlite3 structure. They are then deleted/xDisconnected -** next time a statement is prepared using said sqlite3*. This is done -** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. -** Refer to comments above function sqlite3VtabUnlockList() for an -** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect -** list without holding the corresponding sqlite3.mutex mutex. -** -** The memory for objects of this type is always allocated by -** sqlite3DbMalloc(), using the connection handle stored in VTable.db as -** the first argument. -*/ -struct VTable { - sqlite3 *db; /* Database connection associated with this table */ - Module *pMod; /* Pointer to module implementation */ - sqlite3_vtab *pVtab; /* Pointer to vtab instance */ - int nRef; /* Number of pointers to this structure */ - u8 bConstraint; /* True if constraints are supported */ - u8 bAllSchemas; /* True if might use any attached schema */ - u8 eVtabRisk; /* Riskiness of allowing hacker access */ - int iSavepoint; /* Depth of the SAVEPOINT stack */ - VTable *pNext; /* Next in linked list (see above) */ -}; - -/* Allowed values for VTable.eVtabRisk -*/ -#define SQLITE_VTABRISK_Low 0 -#define SQLITE_VTABRISK_Normal 1 -#define SQLITE_VTABRISK_High 2 - -/* -** 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. */ - char *zColAff; /* String defining the affinity of each column */ - ExprList *pCheck; /* All CHECK constraints */ - /* ... also used as column name list in a VIEW */ - Pgno tnum; /* Root BTree page for this table */ - u32 nTabRef; /* Number of pointers to this Table */ - u32 tabFlags; /* Mask of TF_* values */ - i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ - i16 nCol; /* Number of columns in this table */ - i16 nNVCol; /* Number of columns that are not VIRTUAL */ - LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ - LogEst szTabRow; /* Estimated size of each table row in bytes */ -#ifdef SQLITE_ENABLE_COSTMULT - LogEst costMult; /* Cost multiplier for using this table */ -#endif - u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ - 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 */ - u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */ -}; - -/* -** Allowed values for Table.tabFlags. -** -** TF_OOOHidden applies to tables or view that have hidden columns that are -** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING -** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, -** the TF_OOOHidden attribute would apply in this case. Such tables require -** special handling during INSERT processing. The "OOO" means "Out Of Order". -** -** Constraints: -** -** 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_MaybeReanalyze 0x00000100 /* Maybe run ANALYZE on 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 -** done as a macro so that it will be optimized out when virtual -** table support is omitted from the build. -*/ -#ifndef SQLITE_OMIT_VIRTUALTABLE -# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB) -# define ExprIsVtab(X) \ - ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB) -#else -# define IsVirtual(X) 0 -# define ExprIsVtab(X) 0 -#endif - -/* -** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() -** only works for non-virtual tables (ordinary tables and views) and is -** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The -** IsHiddenColumn() macro is general purpose. -*/ -#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS) -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -#elif !defined(SQLITE_OMIT_VIRTUALTABLE) -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -# define IsOrdinaryHiddenColumn(X) 0 -#else -# define IsHiddenColumn(X) 0 -# define IsOrdinaryHiddenColumn(X) 0 -#endif - - -/* Does the table have a rowid */ -#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) -#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) - -/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is -** available. By default, this macro is false -*/ -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW -# define ViewCanHaveRowid 0 -#else -# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0) -#endif - -/* -** Each foreign key constraint is an instance of the following structure. -** -** A foreign key is associated with two tables. The "from" table is -** the table that contains the REFERENCES clause that creates the foreign -** key. The "to" table is the table that is named in the REFERENCES clause. -** Consider this example: -** -** CREATE TABLE ex1( -** a INTEGER PRIMARY KEY, -** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) -** ); -** -** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". -** Equivalent names: -** -** from-table == child-table -** to-table == parent-table -** -** Each REFERENCES clause generates an instance of the following structure -** which is attached to the from-table. The to-table need not exist when -** the from-table is created. The existence of the to-table is not checked. -** -** The list of all parents for child Table X is held at X.pFKey. -** -** A list of all children for a table named Z (which might not even exist) -** is held in Schema.fkeyHash with a hash key of Z. -*/ -struct FKey { - Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ - FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */ - char *zTo; /* Name of table that the key points to (aka: Parent) */ - FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */ - FKey *pPrevTo; /* Previous with the same zTo */ - int nCol; /* Number of columns in this key */ - /* EV: R-30323-21917 */ - u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ - u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ - Trigger *apTrigger[2];/* Triggers for aAction[] actions */ - struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ - int iFrom; /* Index of column in pFrom */ - char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */ - } aCol[FLEXARRAY]; /* One entry for each of nCol columns */ -}; - -/* The size (in bytes) of an FKey object holding N columns. The answer -** does NOT include space to hold the zTo name. */ -#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap)) - -/* -** SQLite supports many different ways to resolve a constraint -** error. ROLLBACK processing means that a constraint violation -** causes the operation in process to fail and for the current transaction -** to be rolled back. ABORT processing means the operation in process -** fails and any prior changes from that one operation are backed out, -** but the transaction is not rolled back. FAIL processing means that -** the operation in progress stops and returns an error code. But prior -** changes due to the same operation are not backed out and no rollback -** occurs. IGNORE means that the particular row that caused the constraint -** error is not inserted or updated. Processing continues and no error -** 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, 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. 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 algorithm is required from context. -** -** The following symbolic values are used to record which type -** 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 */ -#define OE_Abort 2 /* Back out changes but do no rollback transaction */ -#define OE_Fail 3 /* Stop the operation but leave all prior changes */ -#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ -#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ -#define OE_Update 6 /* Process as a DO UPDATE in an upsert */ -#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ -#define OE_SetNull 8 /* Set the foreign key value to NULL */ -#define OE_SetDflt 9 /* Set the foreign key value to its default */ -#define OE_Cascade 10 /* Cascade the changes */ -#define OE_Default 11 /* Do whatever the default action is */ - - -/* -** An instance of the following structure is passed as the first -** argument to sqlite3VdbeKeyCompare and is used to control the -** comparison of the two index keys. -** -** Note that aSortOrder[] and aColl[] have nField+1 slots. There -** are nField slots for the columns of an index then one extra slot -** for the rowid at the end. -*/ -struct KeyInfo { - u32 nRef; /* Number of references to this KeyInfo object */ - u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ - u16 nKeyField; /* Number of key columns in the index */ - u16 nAllField; /* Total columns, including key plus others */ - sqlite3 *db; /* The database connection */ - u8 *aSortFlags; /* Sort order for each column. */ - CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */ -}; - -/* The size (in bytes) of a KeyInfo object with up to N fields */ -#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*)) - -/* -** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. -*/ -#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */ -#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */ - -/* -** This object holds a record which has been parsed out into individual -** fields, for the purposes of doing a comparison. -** -** A record is an object that contains one or more fields of data. -** Records are used to store the content of a table row and to store -** the key of an index. A blob encoding of a record is created by -** the OP_MakeRecord opcode of the VDBE and is disassembled by the -** OP_Column opcode. -** -** An instance of this object serves as a "key" for doing a search on -** an index b+tree. The goal of the search is to find the entry that -** is closed to the key described by this object. This object might hold -** just a prefix of the key. The number of fields is given by -** pKeyInfo->nField. -** -** The r1 and r2 fields are the values to return if this key is less than -** or greater than a key in the btree, respectively. These are normally -** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree -** is in DESC order. -** -** The key comparison functions actually return default_rc when they find -** an equals comparison. default_rc can be -1, 0, or +1. If there are -** multiple entries in the b-tree with the same key (when only looking -** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to -** cause the search to find the last match, or +1 to cause the search to -** find the first match. -** -** The key comparison functions will set eqSeen to true if they ever -** get and equal results when comparing this structure to a b-tree record. -** When default_rc!=0, the search might end up on the record immediately -** before the first match or immediately after the last match. The -** eqSeen field will indicate whether or not an exact match exists in the -** b-tree. -*/ -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) */ - i8 r1; /* Value to return if (lhs < rhs) */ - i8 r2; /* Value to return if (lhs > rhs) */ - u8 eqSeen; /* True if an equality comparison has been seen */ -}; - - -/* -** Each SQL index is represented in memory by an -** instance of the following structure. -** -** The columns of the table that are to be indexed are described -** by the aiColumn[] field of this structure. For example, suppose -** we have the following table and index: -** -** CREATE TABLE Ex1(c1 int, c2 int, c3 text); -** CREATE INDEX Ex2 ON Ex1(c3,c1); -** -** In the Table structure describing Ex1, nCol==3 because there are -** three columns in the table. In the Index structure describing -** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. -** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the -** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. -** The second column to be indexed (c1) has an index of 0 in -** Ex1.aCol[], hence Ex2.aiColumn[1]==0. -** -** The Index.onError field determines whether or not the indexed columns -** must be unique and what to do if they are not. When Index.onError=OE_None, -** it means this is not a unique index. Otherwise it is a unique index -** and the value of Index.onError indicates which conflict resolution -** algorithm to employ when an attempt is made to insert a non-unique -** element. -** -** The colNotIdxed bitmask is used in combination with SrcItem.colUsed -** for a fast test to see if an index can serve as a covering index. -** colNotIdxed has a 1 bit for every column of the original table that -** is *not* available in the index. Thus the expression -** "colUsed & colNotIdxed" will be non-zero if the index is not a -** covering index. The most significant bit of of colNotIdxed will always -** be true (note-20221022-a). If a column beyond the 63rd column of the -** table is used, the "colUsed & colNotIdxed" test will always be non-zero -** and we have to assume either that the index is not covering, or use -** an alternative (slower) algorithm to determine whether or not -** the index is covering. -** -** While parsing a CREATE TABLE or CREATE INDEX statement in order to -** generate VDBE code (as opposed to parsing one read from an sqlite_schema -** table as part of parsing an existing database schema), transient instances -** of this structure may be created. In this case the Index.tnum variable is -** used to store the address of a VDBE instruction, not a database page -** number (it cannot - the database page is not allocated until the VDBE -** program is executed). See convertToWithoutRowidTable() for details. -*/ -struct Index { - char *zName; /* Name of this index */ - i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */ - LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */ - Table *pTable; /* The SQL table being indexed */ - char *zColAff; /* String defining the affinity of each column */ - Index *pNext; /* The next index associated with the same table */ - Schema *pSchema; /* Schema containing this index */ - u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ - const char **azColl; /* Array of collation sequence names for index */ - Expr *pPartIdxWhere; /* WHERE clause for partial indices */ - ExprList *aColExpr; /* Column expressions */ - Pgno tnum; /* DB Page containing root of this index */ - LogEst szIdxRow; /* Estimated average row size in bytes */ - u16 nKeyCol; /* Number of columns forming the key */ - u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */ - u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */ - unsigned bUnordered:1; /* Use this index for == or IN queries only */ - unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ - unsigned isResized:1; /* True if resizeIndexObject() has been called */ - unsigned isCovering:1; /* True if this is a covering index */ - unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ - unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ - unsigned bNoQuery:1; /* Do not use this index to optimize queries */ - unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ - unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ - unsigned bHasExpr:1; /* Index contains an expression, either a literal - ** expression, or a reference to a VIRTUAL column */ -#ifdef SQLITE_ENABLE_STAT4 - int nSample; /* Number of elements in aSample[] */ - int mxSample; /* Number of slots allocated to aSample[] */ - int nSampleCol; /* Size of IndexSample.anEq[] and so on */ - tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ - IndexSample *aSample; /* Samples of the left-most key */ - tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ - tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ -#endif - Bitmask colNotIdxed; /* Unindexed columns in pTab */ -}; - -/* -** Allowed values for Index.idxType -*/ -#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ -#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */ -#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */ -#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */ - -/* Return true if index X is a PRIMARY KEY index */ -#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) - -/* Return true if index X is a UNIQUE index */ -#define IsUniqueIndex(X) ((X)->onError!=OE_None) - -/* The Index.aiColumn[] values are normally positive integer. But -** there are some negative values that have special meaning: -*/ -#define XN_ROWID (-1) /* Indexed column is the rowid */ -#define XN_EXPR (-2) /* Indexed column is an expression */ - -/* -** Each sample stored in the sqlite_stat4 table is represented in memory -** using a structure of this type. See documentation at the top of the -** analyze.c source file for additional information. -*/ -struct IndexSample { - void *p; /* Pointer to sampled record */ - int n; /* Size of record in bytes */ - tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ - tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ - tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ -}; - -/* -** Possible values to use within the flags argument to sqlite3GetToken(). -*/ -#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ -#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ - -/* -** Each token coming out of the lexer is an instance of -** this structure. Tokens are also used as part of an expression. -** -** The memory that "z" points to is owned by other objects. Take care -** that the owner of the "z" string does not deallocate the string before -** the Token goes out of scope! Very often, the "z" points to some place -** in the middle of the Parse.zSql text. But it might also point to a -** static string. -*/ -struct Token { - const char *z; /* Text of the token. Not NULL-terminated! */ - unsigned int n; /* Number of characters in this token */ -}; - -/* -** An instance of this structure contains information needed to generate -** code for a SELECT that contains aggregate functions. -** -** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a -** pointer to this structure. The Expr.iAgg field is the index in -** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate -** code for that node. -** -** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the -** original Select structure that describes the SELECT statement. These -** fields do not need to be freed when deallocating the AggInfo structure. -*/ -struct AggInfo { - u8 directMode; /* Direct rendering mode means take data directly - ** from source tables rather than from accumulators */ - u8 useSortingIdx; /* In direct mode, reference the sorting index rather - ** than the source table */ - u32 nSortingColumn; /* Number of columns in the sorting index */ - int sortingIdx; /* Cursor number of the sorting index */ - int sortingIdxPTab; /* Cursor number of pseudo-table */ - int iFirstReg; /* First register in range for aCol[] and aFunc[] */ - ExprList *pGroupBy; /* The group by clause */ - struct AggInfo_col { /* For each column used in source tables */ - Table *pTab; /* Source table */ - Expr *pCExpr; /* The original expression */ - int iTable; /* Cursor number of the source table */ - int iColumn; /* Column number within the source table */ - int iSorterColumn; /* Column number in the sorting index */ - } *aCol; - int nColumn; /* Number of used entries in aCol[] */ - int nAccumulator; /* Number of columns that show through to the output. - ** Additional columns are used only as parameters to - ** aggregate functions */ - struct AggInfo_func { /* For each aggregate function */ - Expr *pFExpr; /* Expression encoding the function */ - FuncDef *pFunc; /* The aggregate function implementation */ - int iDistinct; /* Ephemeral table used to enforce DISTINCT */ - int iDistAddr; /* Address of OP_OpenEphemeral */ - int iOBTab; /* Ephemeral table to implement ORDER BY */ - u8 bOBPayload; /* iOBTab has payload columns separate from key */ - u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */ - u8 bUseSubtype; /* Transfer subtype info through sorter */ - } *aFunc; - int nFunc; /* Number of entries in aFunc[] */ - u32 selId; /* Select to which this AggInfo belongs */ -#ifdef SQLITE_DEBUG - Select *pSelect; /* SELECT statement that this AggInfo supports */ -#endif -}; - -/* -** Macros to compute aCol[] and aFunc[] register numbers. -** -** These macros should not be used prior to the call to -** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg. -** The assert()s that are part of this macro verify that constraint. -*/ -#ifndef NDEBUG -#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I)) -#define AggInfoFuncReg(A,I) \ - (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I)) -#else -#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I)) -#define AggInfoFuncReg(A,I) \ - ((A)->iFirstReg+(A)->nColumn+(I)) -#endif - -/* -** The datatype ynVar is a signed integer, either 16-bit or 32-bit. -** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater -** than 32767 we have to make it 32-bit. 16-bit is preferred because -** it uses less memory in the Expr object, which is a big memory user -** in systems with lots of prepared statements. And few applications -** need more than about 10 or 20 variables. But some extreme users want -** to have prepared statements with over 32766 variables, and for them -** the option is available (at compile-time). -*/ -#if SQLITE_MAX_VARIABLE_NUMBER<32767 -typedef i16 ynVar; -#else -typedef int ynVar; -#endif - -/* -** Each node of an expression in the parse tree is an instance -** of this structure. -** -** Expr.op is the opcode. The integer parser token codes are reused -** as opcodes here. For example, the parser defines TK_GE to be an integer -** code representing the ">=" operator. This same integer code is reused -** to represent the greater-than-or-equal-to operator in the expression -** tree. -** -** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, -** 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.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. -** -** Expr.x.pList is a list of arguments if the expression is an SQL function, -** a CASE expression or an IN expression of the form " IN (, ...)". -** Expr.x.pSelect is used if the expression is a sub-select or an expression of -** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the -** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is -** valid. -** -** An expression of the form ID or ID.ID refers to a column in a table. -** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is -** the integer cursor number of a VDBE cursor pointing to that table and -** Expr.iColumn is the column number for the specific column. If the -** expression is used as a result in an aggregate SELECT, then the -** value is also stored in the Expr.iAgg column in the aggregate so that -** it can be accessed after all aggregates are computed. -** -** If the expression is an unbound variable marker (a question mark -** character '?' in the original SQL) then the Expr.iTable holds the index -** number for that variable. -** -** If the expression is a subquery then Expr.iColumn holds an integer -** register number containing the result of the subquery. If the -** subquery gives a constant result, then iTable is -1. If the subquery -** gives a different answer at different times during statement processing -** then iTable is the address of a subroutine that computes the subquery. -** -** If the Expr is of type OP_Column, and the table it is selecting from -** is a disk table or the "old.*" pseudo-table, then pTab points to the -** corresponding table definition. -** -** ALLOCATION NOTES: -** -** Expr objects can use a lot of memory space in database schema. To -** 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.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 -** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees -** are contained within the same memory allocation. Note, however, that -** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately -** allocated, regardless of whether or not EP_Reduced is set. -*/ -struct Expr { - u8 op; /* Operation performed by this node */ - char affExpr; /* affinity, or RAISE type */ - u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op - ** TK_COLUMN: the value of p5 for OP_Column - ** TK_AGG_FUNCTION: nesting depth - ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */ -#ifdef SQLITE_DEBUG - u8 vvaFlags; /* Verification flags. */ -#endif - u32 flags; /* Various flags. EP_* See below */ - union { - char *zToken; /* Token value. Zero terminated and dequoted */ - int iValue; /* Non-negative integer value if EP_IntValue */ - } u; - - /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no - ** space is allocated for the fields below this point. An attempt to - ** access them will result in a segfault or malfunction. - *********************************************************************/ - - Expr *pLeft; /* Left subnode */ - Expr *pRight; /* Right subnode */ - union { - ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */ - Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */ - } x; - - /* If the EP_Reduced flag is set in the Expr.flags mask, then no - ** space is allocated for the fields below this point. An attempt to - ** access them will result in a segfault or malfunction. - *********************************************************************/ - -#if SQLITE_MAX_EXPR_DEPTH>0 - int nHeight; /* Height of the tree headed by this node */ -#endif - int iTable; /* TK_COLUMN: cursor number of table holding column - ** TK_REGISTER: register number - ** TK_TRIGGER: 1 -> new, 0 -> old - ** EP_Unlikely: 134217728 times likelihood - ** TK_IN: ephemeral table holding RHS - ** TK_SELECT_COLUMN: Number of columns on the LHS - ** TK_SELECT: 1st register of result vector */ - ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. - ** TK_VARIABLE: variable number (always >= 1). - ** TK_SELECT_COLUMN: column of the result vector */ - i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - 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 - ** for a column of an index on an expression */ - Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */ - int nReg; /* TK_NULLS: Number of registers to NULL out */ - struct { /* TK_IN, TK_SELECT, and TK_EXISTS */ - int iAddr; /* Subroutine entry address */ - int regReturn; /* Register used to hold return address */ - } sub; - } y; -}; - -/* 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_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_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_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ -#define EP_FullSize 0x020000 /* Expr structure must remain full sized */ -#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 */ -#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ -#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ -#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ -#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ -#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */ -#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */ - -/* 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) - -/* Macros can be used to test, set, or clear bits in the -** Expr.flags field. -*/ -#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0) -#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P)) -#define ExprSetProperty(E,P) (E)->flags|=(u32)(P) -#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P) -#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) -#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) -#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0) - -/* 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 ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0) -#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=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 -*/ -#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */ -#define EP_Immutable 0x02 /* Do not change this Expr node */ - -/* The ExprSetVVAProperty() macro is used for Verification, Validation, -** and Accreditation only. It works like ExprSetProperty() during VVA -** processes but is a no-op for delivery. -*/ -#ifdef SQLITE_DEBUG -# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P) -# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0) -# define ExprClearVVAProperties(E) (E)->vvaFlags = 0 -#else -# define ExprSetVVAProperty(E,P) -# define ExprHasVVAProperty(E,P) 0 -# define ExprClearVVAProperties(E) -#endif - -/* -** Macros to determine the number of bytes required by a normal Expr -** struct, an Expr struct with the EP_Reduced flag set in Expr.flags -** and an Expr struct with the EP_TokenOnly flag set. -*/ -#define EXPR_FULLSIZE sizeof(Expr) /* Full size */ -#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */ -#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */ - -/* -** Flags passed to the sqlite3ExprDup() function. See the header comment -** above sqlite3ExprDup() for details. -*/ -#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ - -/* -** True if the expression passed as an argument was a function with -** an OVER() clause (a window function). -*/ -#ifdef SQLITE_OMIT_WINDOWFUNC -# define IsWindowFunc(p) 0 -#else -# define IsWindowFunc(p) ( \ - ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \ - ) -#endif - -/* -** A list of expressions. Each expression may optionally have a -** name. An expr/name combination can be used in several ways, such -** as the list of "expr AS ID" fields following a "SELECT" or in the -** list of "ID = expr" items in an UPDATE. A list of expressions can -** also be used as the argument to a function, in which case the a.zName -** field is not used. -** -** In order to try to keep memory usage down, the Expr.a.zEName field -** is used for multiple purposes: -** -** eEName Usage -** ---------- ------------------------- -** ENAME_NAME (1) the AS of result set column -** (2) COLUMN= of an UPDATE -** -** ENAME_TAB DB.TABLE.NAME used to resolve names -** of subqueries -** -** ENAME_SPAN Text of the original result set -** expression. -*/ -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 */ - 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 { /* 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. Used only - ** by Parse.pConstExpr */ - } u; - } a[FLEXARRAY]; /* One slot for each expression in the list */ -}; - -/* The size (in bytes) of an ExprList object that is big enough to hold -** as many as N expressions. */ -#define SZ_EXPRLIST(N) \ - (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item)) - -/* -** Allowed values for Expr.a.eEName -*/ -#define ENAME_NAME 0 /* The AS clause of a result set */ -#define ENAME_SPAN 1 /* Complete text of the result set expression */ -#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */ -#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */ - -/* -** An instance of this structure can hold a simple list of identifiers, -** such as the list "a,b,c" in the following statements: -** -** INSERT INTO t(a,b,c) VALUES ...; -** CREATE INDEX idx ON t(a,b,c); -** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...; -** -** The IdList.a.idx field is used when the IdList represents the list of -** column names after a table name in an INSERT statement. In the statement -** -** INSERT INTO t(a,b,c) ... -** -** 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 */ - struct IdList_item { - char *zName; /* Name of the identifier */ - } a[FLEXARRAY]; -}; - -/* The size (in bytes) of an IdList object that can hold up to N IDs. */ -#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item)) - -/* -** 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 */ - -/* -** Details of the implementation of a subquery. -*/ -struct Subquery { - Select *pSelect; /* A SELECT statement used in place of a table name */ - int addrFillSub; /* Address of subroutine to initialize a subquery */ - int regReturn; /* Register holding return address of addrFillSub */ - int regResult; /* Registers holding results of a co-routine */ -}; - -/* -** The SrcItem object represents a single term in the FROM clause of a query. -** The SrcList object is mostly an array of SrcItems. -** -** The jointype starts out showing the join type between the current table -** and the next table on the list. The parser builds the list this way. -** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each -** jointype expresses the join between the table and the previous table. -** -** In the colUsed field, the high-order bit (bit 63) is set if the table -** contains more than 63 columns and the 64-th or later column is used. -** -** Aggressive use of "union" helps keep the size of the object small. This -** has been shown to boost performance, in addition to saving memory. -** Access to union elements is gated by the following rules which should -** always be checked, either by an if-statement or by an assert(). -** -** Field Only access if this is true -** --------------- ----------------------------------- -** u1.zIndexedBy fg.isIndexedBy -** u1.pFuncArg fg.isTabFunc -** u1.nRow !fg.isTabFunc && !fg.isIndexedBy -** -** u2.pIBIndex fg.isIndexedBy -** u2.pCteUse fg.isCte -** -** u3.pOn !fg.isUsing -** u3.pUsing fg.isUsing -** -** u4.zDatabase !fg.fixedSchema && !fg.isSubquery -** u4.pSchema fg.fixedSchema -** u4.pSubq fg.isSubquery -** -** See also the sqlite3SrcListDelete() routine for assert() statements that -** check invariants on the fields of this object, especially the flags -** inside the fg struct. -*/ -struct SrcItem { - char *zName; /* Name of the table */ - char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ - Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */ - 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 isSubquery :1; /* True if this term is a subquery */ - 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 synthesized from NATURAL */ - unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ - unsigned rowidUsed :1; /* The ROWID of this table is referenced */ - unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */ - unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */ - } fg; - int iCursor; /* The VDBE cursor number used to access this table */ - Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */ - union { - char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ - ExprList *pFuncArg; /* Arguments to table-valued-function */ - u32 nRow; /* Number of rows in a VALUES clause */ - } u1; - union { - Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ - CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */ - } u2; - union { - Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */ - IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */ - } u3; - union { - Schema *pSchema; /* Schema to which this item is fixed */ - char *zDatabase; /* Name of database holding this table */ - Subquery *pSubq; /* Description of a subquery */ - } u4; -}; - -/* -** 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 */ -}; - -/* -** This object represents one or more tables that are the source of -** content for an SQL statement. For example, a single SrcList object -** is used to hold the FROM clause of a SELECT statement. SrcList also -** represents the target tables for DELETE, INSERT, and UPDATE statements. -** -*/ -struct SrcList { - int nSrc; /* Number of tables or subqueries in the FROM clause */ - u32 nAlloc; /* Number of entries allocated in a[] below */ - SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */ -}; - -/* Size (in bytes) of a SrcList object that can hold as many as N -** SrcItem objects. */ -#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem)) - -/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a -** special case of SZ_SRCITEM(1) that comes up often. */ -#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem)) - -/* -** Permitted values of the SrcList.a.jointype field -*/ -#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 sqlite3WhereBegin() -** and the WhereInfo.wctrlFlags member. -** -** Value constraints (enforced via assert()): -** WHERE_USE_LIMIT == SF_FixedLimit -*/ -#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ -#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ -#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ -#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ -#define WHERE_ONEPASS_MULTIROW 0x0008 /* ONEPASS is ok with multiple rows */ -#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */ -#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of - ** the OR optimization */ -#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */ -#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 sqlite3WhereIsSorted() */ -#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */ -#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ -#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */ -#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */ -#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */ - /* 0x8000 not currently used */ - -/* Allowed return values from sqlite3WhereIsDistinct() -*/ -#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ -#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ -#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */ -#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */ - -/* -** A NameContext defines a context in which to resolve table and column -** names. The context consists of a list of tables (the pSrcList) field and -** a list of named expression (pEList). The named expression list may -** be NULL. The pSrc corresponds to the FROM clause of a SELECT or -** to the table being operated on by INSERT, UPDATE, or DELETE. The -** pEList corresponds to the result set of a SELECT and is NULL for -** other statements. -** -** NameContexts can be nested. When resolving names, the inner-most -** context is searched first. If no match is found, the next outer -** context is checked. If there is still no match, the next context -** is checked. This process continues until either a match is found -** or all contexts are check. When a match is found, the nRef member of -** the context containing the match is incremented. -** -** Each subquery gets a new NameContext. The pNext field points to the -** NameContext in the parent query. Thus the process of scanning the -** NameContext list corresponds to searching through successively outer -** subqueries looking for a match. -*/ -struct NameContext { - Parse *pParse; /* The parser */ - SrcList *pSrcList; /* One or more tables used to resolve names */ - union { - 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 nNcErr; /* Number of errors encountered while resolving names */ - int ncFlags; /* Zero or more NC_* flags defined below */ - u32 nNestedSelect; /* Number of nested selects using this NC */ - Select *pWinSelect; /* SELECT statement for any window functions */ -}; - -/* -** 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_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER -** NC_HasWin == EP_Win -** -*/ -#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_Subquery 0x000040 /* A 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 */ -/* 0x002000 // available for reuse */ -#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_Where 0x100000 /* Processing WHERE clause of a SELECT */ -#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */ - -/* -** An instance of the following object describes a single ON CONFLICT -** clause in an upsert. -** -** The pUpsertTarget field is only set if the ON CONFLICT clause includes -** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the -** conflict-target clause.) The pUpsertTargetWhere is the optional -** WHERE clause used to identify partial unique indexes. -** -** pUpsertSet is the list of column=expr terms of the UPDATE statement. -** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The -** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the -** WHERE clause is omitted. -*/ -struct Upsert { - 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 */ - Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ - u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ - u8 isDup; /* True if 2nd or later with same pUpsertIdx */ - /* 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 */ - int iIdxCur; /* Index of the first index cursor */ -}; - -/* -** An instance of the following structure contains all information -** needed to generate code for a single SELECT statement. -** -** See the header comment on the computeLimitRegisters() routine for a -** detailed description of the meaning of the iLimit and iOffset fields. -** -** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. -** These addresses must be stored so that we can go back and fill in -** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor -** the number of columns in P2 can be computed at the same time -** as the OP_OpenEphm instruction is coded because not -** enough information about the compound query is known at that point. -** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences -** for the result set. The KeyInfo for addrOpenEphm[2] contains collating -** sequences for the ORDER BY clause. -*/ -struct Select { - u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ - LogEst nSelectRow; /* Estimated number of result rows */ - u32 selFlags; /* Various SF_* values */ - int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ - u32 selId; /* Unique identifier number for this SELECT */ - int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ - ExprList *pEList; /* The fields of the result */ - SrcList *pSrc; /* The FROM clause */ - Expr *pWhere; /* The WHERE clause */ - ExprList *pGroupBy; /* The GROUP BY clause */ - Expr *pHaving; /* The HAVING clause */ - ExprList *pOrderBy; /* The ORDER BY clause */ - Select *pPrior; /* Prior select in a compound select statement */ - Select *pNext; /* Next select to the left in a compound */ - Expr *pLimit; /* LIMIT expression. NULL means not used. */ - With *pWith; /* WITH clause attached to this select. Or NULL. */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* List of window functions */ - Window *pWinDefn; /* List of named window definitions */ -#endif -}; - -/* -** Allowed values for Select.selFlags. The "SF" prefix stands for -** "Select Flag". -** -** Value constraints (all checked via assert()) -** 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 */ -#define SF_Resolved 0x0000004 /* Identifiers have been resolved */ -#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ -#define SF_HasAgg 0x0000010 /* Contains aggregate functions */ -#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ -#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */ -#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */ -#define SF_Compound 0x0000100 /* Part of a compound query */ -#define SF_Values 0x0000200 /* Synthesized from VALUES clause */ -#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */ -#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */ -#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */ -#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */ -#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */ -#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */ -#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ -#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ -#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ -#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ -#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_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ -#define SF_PushDown 0x1000000 /* Modified by WHERE-clause 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 */ -#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ -#define SF_Correlated 0x20000000 /* True if references the outer context */ - -/* True if SrcItem X is a subquery that has SF_NestedFrom */ -#define IsNestedFrom(X) \ - ((X)->fg.isSubquery && \ - ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0) - -/* -** The results of a SELECT can be distributed in several ways, as defined -** by one of the following macros. The "SRT" prefix means "SELECT Result -** Type". -** -** SRT_Union Store results as a key in a temporary index -** identified by pDest->iSDParm. -** -** SRT_Except Remove results from the temporary index pDest->iSDParm. -** -** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result -** set is not empty. -** -** SRT_Discard Throw the results away. This is used by SELECT -** statements within triggers whose only purpose is -** the side-effects of functions. -** -** SRT_Output Generate a row of output (using the OP_ResultRow -** opcode) for each row in the result set. -** -** SRT_Mem Only valid if the result is a single column. -** Store the first column of the first result row -** in register pDest->iSDParm then abandon the rest -** of the query. This destination implies "LIMIT 1". -** -** SRT_Set The result must be a single column. Store each -** row of result as the key in table pDest->iSDParm. -** Apply the affinity pDest->affSdst before storing -** results. if pDest->iSDParm2 is positive, then it is -** a register holding a Bloom filter for the IN operator -** that should be populated in addition to the -** pDest->iSDParm table. This SRT is used to -** implement "IN (SELECT ...)". -** -** SRT_EphemTab Create an temporary table pDest->iSDParm and store -** the result there. The cursor is left open after -** returning. This is like SRT_Table except that -** this destination uses OP_OpenEphemeral to create -** the table first. -** -** SRT_Coroutine Generate a co-routine that returns a new row of -** results each time it is invoked. The entry point -** of the co-routine is stored in register pDest->iSDParm -** and the result row is stored in pDest->nDest registers -** starting with pDest->iSdst. -** -** SRT_Table Store results in temporary table pDest->iSDParm. -** SRT_Fifo This is like SRT_EphemTab except that the table -** is assumed to already be open. SRT_Fifo has -** the additional property of being able to ignore -** the ORDER BY clause. -** -** SRT_DistFifo Store results in a temporary table pDest->iSDParm. -** But also use temporary table pDest->iSDParm+1 as -** a record of all prior results and ignore any duplicate -** rows. Name means: "Distinct Fifo". -** -** SRT_Queue Store results in priority queue pDest->iSDParm (really -** an index). Append a sequence number so that all entries -** are distinct. -** -** SRT_DistQueue Store results in priority queue pDest->iSDParm only if -** the same record has never been stored before. The -** index at pDest->iSDParm+1 hold all prior stores. -** -** SRT_Upfrom Store results in the temporary table already opened by -** pDest->iSDParm. If (pDest->iSDParm<0), then the temp -** table is an intkey table - in this case the first -** column returned by the SELECT is used as the integer -** key. If (pDest->iSDParm>0), then the table is an index -** table. (pDest->iSDParm) is the number of key columns in -** each index record in this case. -*/ -#define SRT_Union 1 /* Store result as keys in an index */ -#define SRT_Except 2 /* Remove result from a UNION index */ -#define SRT_Exists 3 /* Store 1 if the result is not empty */ -#define SRT_Discard 4 /* Do not save the results anywhere */ -#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */ -#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */ - -/* The DISTINCT clause is ignored for all of the above. Not that -** IgnorableDistinct() implies IgnorableOrderby() */ -#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue) - -#define SRT_Queue 7 /* Store result in an queue */ -#define SRT_Fifo 8 /* Store result as data with an automatic rowid */ - -/* The ORDER BY clause is ignored for all of the above */ -#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo) - -#define SRT_Output 9 /* Output each row of result */ -#define SRT_Mem 10 /* Store result in a memory cell */ -#define SRT_Set 11 /* Store results as keys in an index */ -#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ -#define SRT_Coroutine 13 /* Generate a single row of result */ -#define SRT_Table 14 /* Store result as data with an automatic rowid */ -#define SRT_Upfrom 15 /* Store result as data with rowid */ - -/* -** An instance of this object describes where to put of the results of -** a SELECT statement. -*/ -struct SelectDest { - u8 eDest; /* How to dispose of the results. One of SRT_* above. */ - int iSDParm; /* A parameter used by the eDest disposal method */ - int iSDParm2; /* A second parameter for the eDest disposal method */ - int iSdst; /* Base register where results are written */ - int nSdst; /* Number of registers allocated */ - char *zAffSdst; /* Affinity used for SRT_Set */ - ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ -}; - -/* -** During code generation of statements that do inserts into AUTOINCREMENT -** tables, the following information is attached to the Table.u.autoInc.p -** pointer of each autoincrement table to record some side information that -** the code generator needs. We have to keep per-table autoincrement -** information in case inserts are done within triggers. Triggers do not -** normally coordinate their activities, but we do need to coordinate the -** loading and saving of autoincrement information. -*/ -struct AutoincInfo { - AutoincInfo *pNext; /* Next info block in a list of them all */ - Table *pTab; /* Table this info block refers to */ - int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ - int regCtr; /* Memory register holding the rowid counter */ -}; - -/* -** At least one instance of the following structure is created for each -** trigger that may be fired while parsing an INSERT, UPDATE or DELETE -** statement. All such objects are stored in the linked list headed at -** Parse.pTriggerPrg and deleted once statement compilation has been -** completed. -** -** A Vdbe sub-program that implements the body and WHEN clause of trigger -** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of -** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. -** The Parse.pTriggerPrg list never contains two entries with the same -** values for both pTrigger and orconf. -** -** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns -** accessed (or set to 0 for triggers fired as a result of INSERT -** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to -** a mask of new.* columns used by the program. -*/ -struct TriggerPrg { - Trigger *pTrigger; /* Trigger this program was coded from */ - TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ - SubProgram *pProgram; /* Program implementing pTrigger/orconf */ - int orconf; /* Default ON CONFLICT policy */ - u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ -}; - -/* -** The yDbMask datatype for the bitmask of all attached databases. -*/ -#if SQLITE_MAX_ATTACHED>30 - typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8]; -# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0) -# define DbMaskZero(M) memset((M),0,sizeof(M)) -# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7)) -# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M) -# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0) -#else - typedef unsigned int yDbMask; -# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0) -# define DbMaskZero(M) ((M)=0) -# define DbMaskSet(M,I) ((M)|=(((yDbMask)1)<<(I))) -# define DbMaskAllZero(M) ((M)==0) -# define DbMaskNonZero(M) ((M)!=0) -#endif - -/* -** For each index X that has as one of its arguments either an expression -** or the name of a virtual generated column, and if X is in scope such that -** the value of the expression can simply be read from the index, then -** there is an instance of this object on the Parse.pIdxExpr list. -** -** During code generation, while generating code to evaluate expressions, -** this list is consulted and if a matching expression is found, the value -** is read from the index rather than being recomputed. -*/ -struct IndexedExpr { - Expr *pExpr; /* The expression contained in the index */ - int iDataCur; /* The data cursor associated with the index */ - int iIdxCur; /* The index cursor */ - int iIdxCol; /* The index column that contains value of pExpr */ - u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ - u8 aff; /* Affinity of the pExpr expression */ - IndexedExpr *pIENext; /* Next in a list of all indexed expressions */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - const char *zIdxName; /* Name of index, used only for bytecode comments */ -#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)(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. -** -** The structure is divided into two parts. When the parser and code -** generate call themselves recursively, the first part of the structure -** is constant but the second part is reset at the beginning and end of -** each recursion. -** -** The nTableLock and aTableLock variables are only used if the shared-cache -** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are -** used to store the set of table-locks required by the statement being -** compiled. Function sqlite3TableLock() is used to add entries to the -** list. -*/ -struct Parse { - sqlite3 *db; /* The main database structure */ - char *zErrMsg; /* An error message */ - Vdbe *pVdbe; /* An engine for executing database bytecode */ - int rc; /* Return code from execution */ - LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ - u8 nested; /* Number of nested calls to the parser/code generator */ - u8 nTempReg; /* Number of temporary registers in aTempReg[] */ - u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ - u8 mayAbort; /* True if statement may throw an ABORT exception */ - u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ - u8 disableLookaside; /* Number of times lookaside has been disabled */ - u8 prepFlags; /* SQLITE_PREPARE_* flags */ - u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ - u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ - 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 */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ -#endif -#ifdef SQLITE_DEBUG - u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */ - u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER) - ** and ALTER TABLE ADD COLUMN. */ -#endif - bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ - bft bHasWith :1; /* True if statement contains WITH */ - bft okConstFactor :1; /* OK to factor out constants */ - bft checkSchema :1; /* Causes schema cookie check after an error */ - int nRangeReg; /* Size of the temporary register block */ - int iRangeReg; /* First register in temporary register block */ - int nErr; /* Number of errors seen */ - int nTab; /* Number of previously allocated VDBE cursors */ - int nMem; /* Number of memory cells used so far */ - int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int iSelfTab; /* Table associated with an index on expr, or negative - ** of the base register during check-constraint eval */ - int nLabel; /* The *negative* of the number of labels used */ - int nLabelAlloc; /* Number of slots in aLabel */ - int *aLabel; /* Space to hold the labels */ - ExprList *pConstExpr;/* Constant expressions */ - IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */ - IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */ - yDbMask writeMask; /* Start a write transaction on these databases */ - yDbMask cookieMask; /* Bitmask of schema verified databases */ - int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */ - int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ -#endif -#ifndef SQLITE_OMIT_SHARED_CACHE - int nTableLock; /* Number of locks in aTableLock */ - TableLock *aTableLock; /* Required table locks for shared-cache mode */ -#endif - AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ - Parse *pToplevel; /* Parse structure for main program (or NULL) */ - Table *pTriggerTab; /* Table triggers are being coded for */ - TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ - ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ - - /************************************************************************** - ** Fields above must be initialized to zero. The fields that follow, - ** down to the beginning of the recursive section, do not need to be - ** initialized as they will be set before being used. The boundary is - ** determined by offsetof(Parse,aTempReg). - **************************************************************************/ - - int aTempReg[8]; /* Holding area for temporary registers */ - Parse *pOuterParse; /* Outer Parse object when nested */ - Token sNameToken; /* Token with unqualified schema object name */ - u32 oldmask; /* Mask of old.* columns referenced */ - u32 newmask; /* Mask of new.* columns referenced */ - union { - struct { /* These fields available when isCreate is true */ - int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ - int regRowid; /* Register holding rowid of CREATE TABLE entry */ - int regRoot; /* Register holding root page for new objects */ - Token constraintName; /* Name of the constraint currently being parsed */ - } cr; - struct { /* These fields available to all other statements */ - Returning *pReturning; /* The RETURNING clause */ - } d; - } u1; - - /************************************************************************ - ** Above is constant between recursions. Below is reset before and after - ** each recursion. The boundary between these two regions is determined - ** using offsetof(Parse,sLastToken) so the sLastToken field must be the - ** first field in the recursive region. - ************************************************************************/ - - Token sLastToken; /* The last token parsed */ - ynVar nVar; /* Number of '?' variables seen in the SQL so far */ - u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ - u8 explain; /* True if the EXPLAIN flag is found on the query */ - u8 eParseMode; /* PARSE_MODE_XXX constant */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - int nVtabLock; /* Number of virtual tables to lock */ -#endif - int nHeight; /* Expression tree height of current sub-select */ - int addrExplain; /* Address of current OP_Explain opcode */ - VList *pVList; /* Mapping between variable names and numbers */ - Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ - const char *zTail; /* All SQL text past the last semicolon parsed */ - Table *pNewTable; /* A table being constructed by CREATE TABLE */ - Index *pNewIndex; /* An index being constructed by CREATE INDEX. - ** Also used to hold redundant UNIQUE constraints - ** during a RENAME COLUMN */ - Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ - const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - Token sArg; /* Complete text of a module argument */ - Table **apVtabLock; /* Pointer to virtual tables needing locking */ -#endif - With *pWith; /* Current WITH clause, or NULL */ -#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 -#define PARSE_MODE_UNMAP 3 - -/* -** Sizes and pointers of various parts of the Parse object. -*/ -#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 */ - -/* -** Return true if currently inside an sqlite3_declare_vtab() call. -*/ -#ifdef SQLITE_OMIT_VIRTUALTABLE - #define IN_DECLARE_VTAB 0 -#else - #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB) -#endif - -#if defined(SQLITE_OMIT_ALTERTABLE) - #define IN_RENAME_OBJECT 0 -#else - #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME) -#endif - -#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE) - #define IN_SPECIAL_PARSE 0 -#else - #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL) -#endif - -/* -** An instance of the following structure can be declared on a stack and used -** to save the Parse.zAuthContext value so that it can be restored later. -*/ -struct AuthContext { - const char *zAuthContext; /* Put saved Parse.zAuthContext here */ - Parse *pParse; /* The Parse structure */ -}; - -/* -** Bitfield flags for P5 value in various opcodes. -** -** Value constraints (enforced via assert()): -** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH -** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF -** OPFLAG_BULKCSR == BTREE_BULKLOAD -** OPFLAG_SEEKEQ == BTREE_SEEK_EQ -** OPFLAG_FORDELETE == BTREE_FORDELETE -** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION -** OPFLAG_AUXDELETE == BTREE_AUXDELETE -*/ -#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ - /* Also used in P2 (not P5) of OP_Delete */ -#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */ -#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ -#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ -#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ -#define OPFLAG_APPEND 0x08 /* This is likely to be an append */ -#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ -#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ -#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ -#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ -#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */ -#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ -#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ -#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ -#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ -#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ -#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 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 trigger, - the is stored here */ - Schema *pSchema; /* Schema containing the trigger */ - Schema *pTabSchema; /* Schema containing the table */ - TriggerStep *step_list; /* Link list of trigger program steps */ - Trigger *pNext; /* Next trigger associated with the table */ -}; - -/* -** A trigger is either a BEFORE or an AFTER trigger. The following constants -** determine which. -** -** If there are multiple triggers, you might of some BEFORE and some AFTER. -** In that cases, the constants below can be ORed together. -*/ -#define TRIGGER_BEFORE 1 -#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 -> 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 ... () 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 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, - ** 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, or RETURNING clause */ - IdList *pIdList; /* Column names for INSERT */ - Upsert *pUpsert; /* Upsert clauses on an INSERT */ - char *zSpan; /* Original SQL text of this command */ - TriggerStep *pNext; /* Next in the link-list */ - TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ -}; - -/* -** Information about a RETURNING clause -*/ -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 */ - char zName[40]; /* Name of trigger: "sqlite_returning_%p" */ -}; - -/* -** An object used to accumulate the text of a string where we -** do not necessarily know how big the string will be in the end. -*/ -struct sqlite3_str { - sqlite3 *db; /* Optional database for lookaside. Can be NULL */ - char *zText; /* The string collected so far */ - u32 nAlloc; /* Amount of space allocated in zText */ - u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ - u32 nChar; /* Length of the string so far */ - u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */ - u8 printfFlags; /* SQLITE_PRINTF flags below */ -}; -#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ -#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ -#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */ - -#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) - -/* -** The following object is the header for an "RCStr" or "reference-counted -** string". An RCStr is passed around and used like any other char* -** that has been dynamically allocated. The important interface -** differences: -** -** 1. RCStr strings are reference counted. They are deallocated -** when the reference count reaches zero. -** -** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than -** sqlite3_free() -** -** 3. Make a (read-only) copy of a read-only RCStr string using -** sqlite3RCStrRef(). -** -** "String" is in the name, but an RCStr object can also be used to hold -** binary data. -*/ -struct RCStr { - u64 nRCRef; /* Number of references */ - /* Total structure size should be a multiple of 8 bytes for alignment */ -}; - -/* -** A pointer to this structure is used to communicate information -** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. -*/ -typedef struct { - sqlite3 *db; /* The database being initialized */ - char **pzErrMsg; /* Error message stored here */ - int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ - int rc; /* Result code stored here */ - u32 mInitFlags; /* Flags controlling error messages */ - u32 nInitRow; /* Number of rows processed */ - Pgno mxPage; /* Maximum page number. 0 for no limit. */ -} InitData; - -/* -** Allowed values for mInitFlags -*/ -#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 -** optimal 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) (sqlite3Config.aTune[(X)-1]) -#else -# define Tuning(X) 0 -#endif - -/* -** Structure containing global configuration data for the SQLite library. -** -** This structure also contains some state information. -*/ -struct Sqlite3Config { - int bMemstat; /* True to enable memory status */ - u8 bCoreMutex; /* True to enable core mutexing */ - u8 bFullMutex; /* True to enable full mutexing */ - u8 bOpenUri; /* True to interpret filenames as URIs */ - u8 bUseCis; /* Use covering indices for full-scans */ - u8 bSmallMalloc; /* Avoid large memory allocations if true */ - u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ -#ifdef SQLITE_DEBUG - u8 bJsonSelfcheck; /* Double-check JSON parsing */ -#endif - int mxStrlen; /* Maximum string length */ - int neverCorrupt; /* Database is always well-formed */ - int szLookaside; /* Default lookaside buffer size */ - int nLookaside; /* Default lookaside buffer count */ - int nStmtSpill; /* Stmt-journal spill-to-disk threshold */ - sqlite3_mem_methods m; /* Low-level memory allocation interface */ - sqlite3_mutex_methods mutex; /* Low-level mutex interface */ - sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ - void *pHeap; /* Heap storage space */ - int nHeap; /* Size of pHeap[] */ - int mnReq, mxReq; /* Min and max heap requests sizes */ - sqlite3_int64 szMmap; /* mmap() space per open file */ - sqlite3_int64 mxMmap; /* Maximum value for szMmap */ - void *pPage; /* Page cache memory */ - int szPage; /* Size of each page in pPage[] */ - int nPage; /* Number of pages in pPage[] */ - int mxParserStack; /* maximum depth of the parser stack */ - int sharedCacheEnabled; /* true if shared-cache mode enabled */ - u32 szPma; /* Maximum Sorter PMA size */ - /* The above might be initialized to non-zero. The following need to always - ** initially be zero, however. */ - int isInit; /* True after initialization has finished */ - int inProgress; /* True while initialization in progress */ - int isMutexInit; /* True after mutexes are initialized */ - int isMallocInit; /* True after malloc is initialized */ - int isPCacheInit; /* True after malloc is initialized */ - int nRefInitMutex; /* Number of users of pInitMutex */ - sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ - void (*xLog)(void*,int,const char*); /* Function for logging */ - void *pLogArg; /* First argument to xLog() */ -#ifdef SQLITE_ENABLE_SQLLOG - void(*xSqllog)(void*,sqlite3*,const char*, int); - void *pSqllogArg; -#endif -#ifdef SQLITE_VDBE_COVERAGE - /* The following callback (if not NULL) is invoked on every VDBE branch - ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. - */ - void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ - void *pVdbeBranchArg; /* 1st argument */ -#endif -#ifndef SQLITE_OMIT_DESERIALIZE - sqlite3_int64 mxMemdbSize; /* Default max memdb size */ -#endif -#ifndef SQLITE_UNTESTABLE - int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ -#endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW - ** feature is disabled. 0 if rowids can - ** occur in views. */ -#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 - sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ -#endif -}; - -/* -** This macro is used inside of assert() statements to indicate that -** the assert is only valid on a well-formed database. Instead of: -** -** assert( X ); -** -** One writes: -** -** assert( X || CORRUPT_DB ); -** -** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate -** that the database is definitely corrupt, only that it might be corrupt. -** For most test cases, CORRUPT_DB is set to false using a special -** sqlite3_test_control(). This enables assert() statements to prove -** things that are always true for well-formed databases. -*/ -#define CORRUPT_DB (sqlite3Config.neverCorrupt==0) - -/* -** Context pointer passed down through the tree-walk. -*/ -struct Walker { - Parse *pParse; /* Parser context. */ - int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ - int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ - void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ - int walkerDepth; /* Number of subqueries */ - u16 eCode; /* A small processing code */ - u16 mWFlags; /* Use-dependent flags */ - union { /* Extra data for callback */ - NameContext *pNC; /* Naming context */ - int n; /* A counter */ - int iCur; /* A cursor number */ - SrcList *pSrcList; /* FROM clause */ - struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ - struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ - int *aiCol; /* array of column indexes */ - struct IdxCover *pIdxCover; /* Check for index coverage */ - ExprList *pGroupBy; /* GROUP BY clause */ - Select *pSelect; /* HAVING to WHERE clause ctx */ - struct WindowRewrite *pRewrite; /* Window rewrite context */ - struct WhereConst *pConst; /* WHERE clause constants */ - struct RenameCtx *pRename; /* RENAME COLUMN context */ - struct Table *pTab; /* Table of generated column */ - struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ - SrcItem *pSrcItem; /* A single FROM clause item */ - DbFixer *pFix; /* See sqlite3FixSelect() */ - Mem *aMem; /* See sqlite3BtreeCursorHint() */ - } 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 sqlite3WalkExpr(Walker*, Expr*); -SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*); -SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); -SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); -SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); -SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); -SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); -SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); -SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); -SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*); -SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*); -SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*); - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); -#endif - -#ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*); -#else -# define sqlite3SelectPopWith 0 -#endif - -/* -** Return code from the parse-tree walking primitives and their -** callbacks. -*/ -#define WRC_Continue 0 /* Continue down into children */ -#define WRC_Prune 1 /* Omit children but continue walking siblings */ -#define WRC_Abort 2 /* Abandon the tree walk */ - -/* -** 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 */ - int bView; /* Belongs to the outermost Select of a view */ - With *pOuter; /* Containing WITH clause, or NULL */ - Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */ -}; - -/* The size (in bytes) of a With object that can hold as many -** as N different CTEs. */ -#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte)) - -/* -** 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 sqlite3ParserAddCleanup() rather -** than 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 */ -}; - - -/* Client data associated with sqlite3_set_clientdata() and -** sqlite3_get_clientdata(). -*/ -struct DbClientData { - DbClientData *pNext; /* Next in a linked list */ - void *pData; /* The data */ - void (*xDestructor)(void*); /* Destructor. Might be NULL */ - char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */ -}; - -/* The size (in bytes) of a DbClientData object that can has a name -** that is N bytes long, including the zero-terminator. */ -#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N)) - -#ifdef SQLITE_DEBUG -/* -** An instance of the TreeView object is used for printing the content of -** data structures on sqlite3DebugPrintf() using a tree-like view. -*/ -struct TreeView { - int iLevel; /* Which level of the tree we are on */ - u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ -}; -#endif /* SQLITE_DEBUG */ - -/* -** This object is used in various ways, most (but not all) related to window -** functions. -** -** (1) A single instance of this structure is attached to the -** the Expr.y.pWin field for each window function in an expression tree. -** This object holds the information contained in the OVER clause, -** plus additional fields used during code generation. -** -** (2) All window functions in a single SELECT form a linked-list -** attached to Select.pWin. The Window.pFunc and Window.pExpr -** fields point back to the expression that is the window function. -** -** (3) The terms of the WINDOW clause of a SELECT are instances of this -** object on a linked list attached to Select.pWinDefn. -** -** (4) For an aggregate function with a FILTER clause, an instance -** of this object is stored in Expr.y.pWin with eFrmType set to -** TK_FILTER. In this case the only field used is Window.pFilter. -** -** The uses (1) and (2) are really the same Window object that just happens -** to be accessible in two different ways. Use case (3) are separate objects. -*/ -struct Window { - char *zName; /* Name of window (may be NULL) */ - char *zBase; /* Name of base window for chaining (may be NULL) */ - ExprList *pPartition; /* PARTITION BY clause */ - ExprList *pOrderBy; /* ORDER BY clause */ - u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */ - u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ - u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ - u8 bImplicitFrame; /* True if frame was implicitly specified */ - u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ - Expr *pStart; /* Expression for " PRECEDING" */ - Expr *pEnd; /* Expression for " FOLLOWING" */ - 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 *pWFunc; /* The function */ - int iEphCsr; /* Partition buffer or Peer buffer */ - int regAccum; /* Accumulator */ - int regResult; /* Interim result */ - int csrApp; /* Function cursor (used by min/max) */ - int regApp; /* Function register (also used by min/max) */ - int regPart; /* Array of registers for PARTITION BY values */ - Expr *pOwner; /* Expression object this window is attached to */ - int nBufferCol; /* Number of columns in buffer table */ - int iArgCol; /* Offset of first argument for this function */ - int regOne; /* Register containing constant value 1 */ - int regStartRowid; - int regEndRowid; - u8 bExprArgs; /* Defer evaluation of window function arguments - ** due to the SQLITE_SUBTYPE flag */ -}; - -SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow); -SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal); - -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); -SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*); -SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p); -SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); -SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*); -SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin); -SQLITE_PRIVATE int sqlite3WindowCompare(const Parse*, const Window*, const Window*, int); -SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*); -SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); -SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*); -SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); -SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); -SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p); -SQLITE_PRIVATE void sqlite3WindowFunctions(void); -SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*); -SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*); -#else -# define sqlite3WindowDelete(a,b) -# define sqlite3WindowFunctions() -# define sqlite3WindowAttach(a,b,c) -#endif - -/* -** Assuming zIn points to the first byte of a UTF-8 character, -** advance zIn to point to the first byte of the next UTF-8 character. -*/ -#define SQLITE_SKIP_UTF8(zIn) { \ - if( (*(zIn++))>=0xc0 ){ \ - while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ - } \ -} - -/* -** The SQLITE_*_BKPT macros are substitutes for the error codes with -** the same name but without the _BKPT suffix. These macros invoke -** routines that report the line-number on which the error originated -** using sqlite3_log(). The routines also provide a convenient place -** to set a debugger breakpoint. -*/ -SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType); -SQLITE_PRIVATE int sqlite3CorruptError(int); -SQLITE_PRIVATE int sqlite3MisuseError(int); -SQLITE_PRIVATE int sqlite3CantopenError(int); -#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) -#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) -#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3NomemError(int); -SQLITE_PRIVATE int sqlite3IoerrnomemError(int); -# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__) -# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__) -#else -# define SQLITE_NOMEM_BKPT SQLITE_NOMEM -# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM -#endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) -SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); -# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) -#else -# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) -#endif - -/* -** FTS3 and FTS4 both require virtual table support -*/ -#if defined(SQLITE_OMIT_VIRTUALTABLE) -# undef SQLITE_ENABLE_FTS3 -# undef SQLITE_ENABLE_FTS4 -#endif - -/* -** FTS4 is really an extension for FTS3. It is enabled using the -** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call -** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3. -*/ -#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) -# define SQLITE_ENABLE_FTS3 1 -#endif - -/* -** The following macros mimic the standard library functions toupper(), -** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The -** sqlite versions only work for ASCII characters, regardless of locale. -*/ -#ifdef SQLITE_ASCII -# define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20)) -# define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01) -# define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06) -# define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) -# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) -# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) -# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) -# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) -# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42) -# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46) -#else -# define sqlite3Toupper(x) toupper((unsigned char)(x)) -# define sqlite3Isspace(x) isspace((unsigned char)(x)) -# define sqlite3Isalnum(x) isalnum((unsigned char)(x)) -# define sqlite3Isalpha(x) isalpha((unsigned char)(x)) -# define sqlite3Isdigit(x) isdigit((unsigned char)(x)) -# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) -# define sqlite3Tolower(x) tolower((unsigned char)(x)) -# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') -# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0') -# define sqlite3JsonId2(x) sqlite3IsIdChar(x) -#endif -SQLITE_PRIVATE int sqlite3IsIdChar(u8); - -/* -** Internal function prototypes -*/ -SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*); -SQLITE_PRIVATE int sqlite3Strlen30(const char*); -#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) -SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*); -#define sqlite3StrNICmp sqlite3_strnicmp - -SQLITE_PRIVATE int sqlite3MallocInit(void); -SQLITE_PRIVATE void sqlite3MallocEnd(void); -SQLITE_PRIVATE void *sqlite3Malloc(u64); -SQLITE_PRIVATE void *sqlite3MallocZero(u64); -SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); -SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); -SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); -SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); -SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); -SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3*,const char*,const char*); -SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); -SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); -SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); -SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*); -SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*); -SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3*, void*); -SQLITE_PRIVATE int sqlite3MallocSize(const void*); -SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, const void*); -SQLITE_PRIVATE void *sqlite3PageMalloc(int); -SQLITE_PRIVATE void sqlite3PageFree(void*); -SQLITE_PRIVATE void sqlite3MemSetDefault(void); -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); -#endif -SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); - -/* -** On systems with ample stack space and that support alloca(), make -** use of alloca() to obtain space for large automatic objects. By default, -** obtain space from malloc(). -** -** The alloca() routine never returns NULL. This will cause code paths -** that deal with sqlite3StackAlloc() failures to be unreachable. -*/ -#ifdef SQLITE_USE_ALLOCA -# define sqlite3StackAllocRaw(D,N) alloca(N) -# define sqlite3StackAllocRawNN(D,N) alloca(N) -# define sqlite3StackFree(D,P) -# define sqlite3StackFreeNN(D,P) -#else -# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) -# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N) -# define sqlite3StackFree(D,P) sqlite3DbFree(D,P) -# define sqlite3StackFreeNN(D,P) sqlite3DbFreeNN(D,P) -#endif - -/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they -** are, disable MEMSYS3 -*/ -#ifdef SQLITE_ENABLE_MEMSYS5 -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); -#undef SQLITE_ENABLE_MEMSYS3 -#endif -#ifdef SQLITE_ENABLE_MEMSYS3 -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); -#endif - - -#ifndef SQLITE_MUTEX_OMIT -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void); -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void); -SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int); -SQLITE_PRIVATE int sqlite3MutexInit(void); -SQLITE_PRIVATE int sqlite3MutexEnd(void); -#endif -#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP) -SQLITE_PRIVATE void sqlite3MemoryBarrier(void); -#else -# define sqlite3MemoryBarrier() -#endif - -SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int); -SQLITE_PRIVATE void sqlite3StatusUp(int, int); -SQLITE_PRIVATE void sqlite3StatusDown(int, int); -SQLITE_PRIVATE void sqlite3StatusHighwater(int, int); -SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); - -/* Access to mutexes used by sqlite3_status() */ -SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); -SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); - -#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT) -SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); -#else -# define sqlite3MutexWarnOnContention(x) -#endif - -#ifndef SQLITE_OMIT_FLOATING_POINT -# define EXP754 (((u64)0x7ff)<<52) -# define MAN754 ((((u64)1)<<52)-1) -# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) -# define IsOvfl(X) (((X)&EXP754)==EXP754) -SQLITE_PRIVATE int sqlite3IsNaN(double); -SQLITE_PRIVATE int sqlite3IsOverflow(double); -#else -# define IsNaN(X) 0 -# define sqlite3IsNaN(X) 0 -# define sqlite3IsOVerflow(X) 0 -#endif - -/* -** An instance of the following structure holds information about SQL -** functions arguments that are the parameters to the printf() function. -*/ -struct PrintfArguments { - int nArg; /* Total number of arguments */ - int nUsed; /* Number of arguments used so far */ - sqlite3_value **apArg; /* The argument values */ -}; - -/* -** An instance of this object receives the decoding of a floating point -** value into an approximate decimal representation. -*/ -struct FpDecode { - char sign; /* '+' or '-' */ - char isSpecial; /* 1: Infinity 2: NaN */ - int n; /* Significant digits in the decode */ - int iDP; /* Location of the decimal point */ - char *z; /* Start of significant digits */ - char zBuf[24]; /* Storage for significant digits */ -}; - -SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int); -SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); -SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) -SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); -#endif -#if defined(SQLITE_TEST) -SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); -#endif - -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...); -SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); -SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); -SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); -SQLITE_PRIVATE void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*); -SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*); -SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8); -SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); -SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); -SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); -SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8); -#if TREETRACE_ENABLED -SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*, - const ExprList*,const Expr*, const Trigger*); -SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*, - const IdList*, const Select*, const ExprList*, - int, const Upsert*, const Trigger*); -SQLITE_PRIVATE void 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 sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8); -SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); -SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); -#endif -SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*); -SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*); -SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*); -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*); -SQLITE_PRIVATE void sqlite3ShowSelect(const Select*); -SQLITE_PRIVATE void sqlite3ShowWith(const With*); -SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*); -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*); -SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*); -SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*); -SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3ShowWindow(const Window*); -SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*); -#endif -#endif - -SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); -SQLITE_PRIVATE void sqlite3ProgressCheck(Parse*); -SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); -SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); -SQLITE_PRIVATE void sqlite3Dequote(char*); -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); -SQLITE_PRIVATE void sqlite3DequoteToken(Token*); -SQLITE_PRIVATE void sqlite3DequoteNumber(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); -SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); -SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*); -SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); -SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); -SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); -SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); -SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int); -SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*); -SQLITE_PRIVATE void sqlite3TouchRegister(Parse*,int); -#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse*,int); -#endif -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); -#endif -SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); -SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); -SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); -SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); -SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); -SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); -SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*); -SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); -SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); -SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); -SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); -SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); -SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*); -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); -SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); -SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); -SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); -SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); -SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); -SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); -SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); -SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); -SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); -#ifndef SQLITE_OMIT_VIRTUALTABLE -SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); -#endif -SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); -SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); -SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); -SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); -SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*); -SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*); -SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl); -SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*); -SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); -SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); -SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); -SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char); -SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); -SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); -SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); -SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index*, int); -#ifdef SQLITE_OMIT_GENERATED_COLUMNS -# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */ -# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */ -#else -SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16); -SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16); -#endif -SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); -#if SQLITE_ENABLE_HIDDEN_COLUMNS -SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*); -#else -# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ -#endif -SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token); -SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); -SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); -SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*); -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); -SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); -SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*); -SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u32,Select*); -SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*); -SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, - sqlite3_vfs**,char**,char **); -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -SQLITE_PRIVATE int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*); -#else -# define sqlite3CodecQueryParameters(A,B,C) 0 -#endif -/* END SQLCIPHER */ -SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); - -#ifdef SQLITE_UNTESTABLE -# define sqlite3FaultSim(X) SQLITE_OK -#else -SQLITE_PRIVATE int sqlite3FaultSim(int); -#endif - -SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); -SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); -SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec*, u32); -SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); -SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); -SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); -SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); -#endif - -SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*); -SQLITE_PRIVATE void sqlite3RowSetDelete(void*); -SQLITE_PRIVATE void sqlite3RowSetClear(void*); -SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); -SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); -SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); - -SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); - -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*); -#else -# define sqlite3ViewGetColumnNames(A,B) 0 -#endif - -#if SQLITE_MAX_ATTACHED>30 -SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); -#endif -SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); -SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); -SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); -SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*); -SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); -#ifndef SQLITE_OMIT_AUTOINCREMENT -SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); -SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); -#else -# define sqlite3AutoincrementBegin(X) -# define sqlite3AutoincrementEnd(X) -#endif -SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*); -#endif -SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); -SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*); -SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); -SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int); -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2); -SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*); -SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*); -SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int); -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, - Token*, Select*, OnOrUsing*); -SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); -SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*); -SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *); -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*); -SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); -SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); -SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*); -SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); -SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**); -SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, - Expr*, int, int, u8); -SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); -SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); -SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, - Expr*,ExprList*,u32,Expr*); -SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); -SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*); -SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) -SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); -#endif -SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*); -SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); -SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, - Upsert*); -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*, - ExprList*,Select*,u16,int); -SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); -SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); -SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*); -#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ -#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ -#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ -SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*); -SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); -SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); -SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); -SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); -SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg); -SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int); -#endif -SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); -SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int); -SQLITE_PRIVATE void sqlite3ExprNullRegisterRange(Parse*, int, int); -SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); -SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); -#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ -#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ -#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ -#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */ -SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); -SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); -SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); -SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); -#define LOCATE_VIEW 0x01 -#define LOCATE_NOERR 0x02 -SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); -SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char*); -SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *); -SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*); -SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*); -SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, const Token*); -SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int); -SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int); -SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); -SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); -SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*); -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE void sqlite3PrngSaveState(void); -SQLITE_PRIVATE void sqlite3PrngRestoreState(void); -#endif -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); -SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); -SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); -SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); -SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int); -SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); -SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); -SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); -SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*); -SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); -SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); -SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); -SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int); -#ifdef SQLITE_ENABLE_CURSOR_HINTS -SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); -#endif -SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*); -SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); -SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); -SQLITE_PRIVATE int sqlite3IsRowid(const char*); -SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); -SQLITE_PRIVATE void sqlite3GenerateRowDelete( - Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); -SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); -SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); -SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); -SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); -SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, - u8,u8,int,int*,int*,Upsert*); -#ifdef SQLITE_ENABLE_NULL_TRIM -SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); -#else -# define sqlite3SetMakeRecordP5(A,B) -#endif -SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); -SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); -SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); -SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); -SQLITE_PRIVATE void sqlite3MayAbort(Parse*); -SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8); -SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*); -SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*); -SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,const Expr*,int); -SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,const ExprList*,int); -SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,const SrcList*,int); -SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,const IdList*); -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int); -SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*); -SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); -SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int); -SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32); -SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); -SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); -SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); -SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) -SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*); -#endif -SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); -SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); -SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); -SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p); - -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); -#endif - -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, - Expr*,int, int); -SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); -SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int); -SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*); -SQLITE_PRIVATE Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); -SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *, Table *); -SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, - int, int, int); -SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); - void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); -SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, - const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, - Select*,u8,Upsert*, - const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*, - Expr*, u8, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, - const char*,const char*); -SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); -SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); -SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*); -# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) -# define sqlite3IsToplevel(p) ((p)->pToplevel==0) -#else -# define sqlite3TriggersExist(B,C,D,E,F) 0 -# define sqlite3DeleteTrigger(A,B) -# define sqlite3DropTriggerPtr(A,B) -# define sqlite3UnlinkAndDeleteTrigger(A,B,C) -# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) -# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) -# define sqlite3TriggerList(X, Y) 0 -# define sqlite3ParseToplevel(p) p -# define sqlite3IsToplevel(p) 1 -# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 -# define sqlite3TriggerStepSrc(A,B) 0 -#endif - -SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); -SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol); -SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int); -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32); -SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); -SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); -#ifndef SQLITE_OMIT_AUTHORIZATION -SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); -SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); -SQLITE_PRIVATE void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); -SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext*); -SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int); -#else -# define sqlite3AuthRead(a,b,c,d) -# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK -# define sqlite3AuthContextPush(a,b,c) -# define sqlite3AuthContextPop(a) ((void)(a)) -#endif -SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName); -SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); -SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); -SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); -SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); -SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); -SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); - -SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); -SQLITE_PRIVATE i64 sqlite3RealToI64(double); -SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); -SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); -SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); -SQLITE_PRIVATE int sqlite3Atoi(const char*); -#ifndef SQLITE_OMIT_UTF16 -SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar); -#endif -SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); -SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); -SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*); -SQLITE_PRIVATE LogEst sqlite3LogEst(u64); -SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); -SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); -SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); -SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); -SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); -SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); - -/* -** Routines to read and write variable-length integers. These used to -** be defined locally, but now we use the varint routines in the util.c -** file. -*/ -SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64); -SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *); -SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *); -SQLITE_PRIVATE int sqlite3VarintLen(u64 v); - -/* -** The common case is for a varint to be a single byte. They following -** macros handle the common case without a procedure call, but then call -** the procedure for larger varints. -*/ -#define getVarint32(A,B) \ - (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) -#define getVarint32NR(A,B) \ - B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B)) -#define putVarint32(A,B) \ - (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ - sqlite3PutVarint((A),(B))) -#define getVarint sqlite3GetVarint -#define putVarint sqlite3PutVarint - - -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*); -SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*); -SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); -SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2); -SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity); -SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table*,int); -SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr); -SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); -SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); -SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); -SQLITE_PRIVATE void sqlite3Error(sqlite3*,int); -SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*); -SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int); -#if !defined(SQLITE_OMIT_BLOB_LITERAL) -SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); -#endif -SQLITE_PRIVATE u8 sqlite3HexToInt(int h); -SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); - -#if defined(SQLITE_NEED_ERR_NAME) -SQLITE_PRIVATE const char *sqlite3ErrName(int); -#endif - -#ifndef SQLITE_OMIT_DESERIALIZE -SQLITE_PRIVATE int sqlite3MemdbInit(void); -SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs*); -#else -# define sqlite3IsMemdb(X) 0 -#endif - -SQLITE_PRIVATE const char *sqlite3ErrStr(int); -SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); -SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); -SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*); -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); -SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8); -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr); -SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*); -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*); -SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); -SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); -SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); -SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64); -SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); -SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); -SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64); -SQLITE_PRIVATE int sqlite3AbsInt32(int); -#ifdef SQLITE_ENABLE_8_3_NAMES -SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); -#else -# define sqlite3FileSuffix3(X,Y) -#endif -SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); - -SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); -SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*)); -SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); -SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, - void(*)(void*)); -SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*); -SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context*); -#endif -SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); -#ifndef SQLITE_OMIT_UTF16 -SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); -#endif -SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, const Expr *, u8, u8, sqlite3_value **); -SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); -#ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; -SQLITE_PRIVATE const char sqlite3StrBINARY[]; -SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[]; -SQLITE_PRIVATE const char sqlite3StdTypeAffinity[]; -SQLITE_PRIVATE const char *sqlite3StdType[]; -SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; -SQLITE_PRIVATE const unsigned char *sqlite3aLTb; -SQLITE_PRIVATE const unsigned char *sqlite3aEQb; -SQLITE_PRIVATE const unsigned char *sqlite3aGTb; -SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; -SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; -SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; -#ifndef SQLITE_OMIT_WSD -SQLITE_PRIVATE int sqlite3PendingByte; -#endif -#endif /* SQLITE_AMALGAMATION */ -#ifdef VDBE_PROFILE -SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt; -#endif -SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno); -SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); -SQLITE_PRIVATE void sqlite3AlterFunctions(void); -SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); -SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); -SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); -SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); -SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); -SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*); -SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); -SQLITE_PRIVATE int sqlite3MatchEName( - const struct ExprList_item*, - const char*, - const char*, - const char*, - int* -); -SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*); -SQLITE_PRIVATE u8 sqlite3StrIHash(const char*); -SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); -SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*); -SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); -SQLITE_PRIVATE int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); -SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); -SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); -SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); -SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); -SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, const Token*); -SQLITE_PRIVATE const void *sqlite3RenameTokenMap(Parse*, const void*, const Token*); -SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom); -SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*); -SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); -SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); -SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); -SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); -SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); -SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); -SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); -SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); -SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int); -SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); -SQLITE_PRIVATE void sqlite3SchemaClear(void *); -SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *); -SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *); -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); -SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*); -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); -SQLITE_PRIVATE const char *sqlite3SelectOpName(int); -SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*); - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*); -#endif -SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, - void (*)(sqlite3_context*,int,sqlite3_value **), - void (*)(sqlite3_context*,int,sqlite3_value **), - void (*)(sqlite3_context*), - void (*)(sqlite3_context*), - void (*)(sqlite3_context*,int,sqlite3_value **), - FuncDestructor *pDestructor -); -SQLITE_PRIVATE void sqlite3NoopDestructor(void*); -SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*); -SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); -SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); -SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); - -SQLITE_PRIVATE char *sqlite3RCStrRef(char*); -SQLITE_PRIVATE void sqlite3RCStrUnref(void*); -SQLITE_PRIVATE char *sqlite3RCStrNew(u64); -SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64); - -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); -SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64); -SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); -SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8); -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); -SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); -SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); -SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*); -SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*); - -SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); -SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); - -#ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*); -#else -# define sqlite3ExprCheckIN(x,y) SQLITE_OK -#endif - -#ifdef SQLITE_ENABLE_STAT4 -SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( - Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*); -SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); -SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); -SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); -SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); -#endif - -/* -** The interface to the LEMON-generated parser -*/ -#ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*); -SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); -#endif -SQLITE_PRIVATE void sqlite3Parser(void*, int, Token); -SQLITE_PRIVATE int sqlite3ParserFallback(int); -#ifdef YYTRACKMAXSTACKDEPTH -SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); -#endif - -SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*); -#ifndef SQLITE_OMIT_LOAD_EXTENSION -SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*); -#else -# define sqlite3CloseExtensions(X) -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE -SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, Pgno, u8, const char *); -#else - #define sqlite3TableLock(v,w,x,y,z) -#endif - -#ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*); -#endif - -#ifdef SQLITE_OMIT_VIRTUALTABLE -# define sqlite3VtabClear(D,T) -# define sqlite3VtabSync(X,Y) SQLITE_OK -# define sqlite3VtabRollback(X) -# define sqlite3VtabCommit(X) -# define sqlite3VtabInSync(db) 0 -# define sqlite3VtabLock(X) -# define sqlite3VtabUnlock(X) -# define sqlite3VtabModuleUnref(D,X) -# define sqlite3VtabUnlockList(X) -# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK -# define sqlite3GetVTable(X,Y) ((VTable*)0) -#else -SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*); -SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p); -SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*); -SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); -SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); -SQLITE_PRIVATE void sqlite3VtabLock(VTable *); -SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *); -SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3*,Module*); -SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); -SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int); -SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); -SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); -SQLITE_PRIVATE Module *sqlite3VtabCreateModule( - sqlite3*, - const char*, - const sqlite3_module*, - void*, - void(*)(void*) - ); -# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) -#endif -SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db); -#ifndef SQLITE_OMIT_VIRTUALTABLE -SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName); -SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); -SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*); -#else -# define sqlite3ShadowTableName(A,B) 0 -# define sqlite3IsShadowTableOf(A,B,C) 0 -# define sqlite3MarkAllShadowTablesOf(A,B) -#endif -SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); -SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); -SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); -SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); -SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); -SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); -SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*); -SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); -SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); -SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); -SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); - -SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); -SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse*); -SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); -SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); -SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); -SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*); -SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*); -SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*); -#endif -SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); -SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); -SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*); -SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*); -SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); -SQLITE_PRIVATE const char *sqlite3JournalModename(int); -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); -SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); -#endif -#ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); -SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); -SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); -SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); -SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); -#else -# define sqlite3CteNew(P,T,E,S) ((void*)0) -# define sqlite3CteDelete(D,C) -# define sqlite3CteWithAdd(P,W,C) ((void*)0) -# define sqlite3WithDelete(x,y) -# define sqlite3WithPush(x,y,z) ((void*)0) -#endif -#ifndef SQLITE_OMIT_UPSERT -SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); -SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); -SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); -SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*); -SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); -SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); -SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*); -#else -#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0) -#define sqlite3UpsertDelete(x,y) -#define sqlite3UpsertDup(x,y) ((Upsert*)0) -#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0) -#define sqlite3UpsertNextIsIPK(x) 0 -#endif - - -/* Declarations for functions in fkey.c. All of these are replaced by -** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign -** key functionality is available. If OMIT_TRIGGER is defined but -** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In -** this case foreign keys are parsed, but no other functionality is -** provided (enforcement of FK constraints requires the triggers sub-system). -*/ -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int, int*, int); -SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*); -SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); -SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); -SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); -SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); -SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3*,int); -#else - #define sqlite3FkActions(a,b,c,d,e,f) - #define sqlite3FkCheck(a,b,c,d,e,f) - #define sqlite3FkDropTable(a,b,c) - #define sqlite3FkOldmask(a,b) 0 - #define sqlite3FkRequired(a,b,c,d) 0 - #define sqlite3FkReferences(a) 0 - #define sqlite3FkClearTriggerCache(a,b) -#endif -#ifndef SQLITE_OMIT_FOREIGN_KEY -SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); -SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); -#else - #define sqlite3FkDelete(a,b) - #define sqlite3FkLocateIndex(a,b,c,d,e) -#endif - - -/* -** Available fault injectors. Should be numbered beginning with 0. -*/ -#define SQLITE_FAULTINJECTOR_MALLOC 0 -#define SQLITE_FAULTINJECTOR_COUNT 1 - -/* -** The interface to the code in fault.c used for identifying "benign" -** malloc failures. This is only present if SQLITE_UNTESTABLE -** is not defined. -*/ -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void); -SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); -#else - #define sqlite3BeginBenignMalloc() - #define sqlite3EndBenignMalloc() -#endif - -/* -** Allowed return values from sqlite3FindInIndex() -*/ -#define IN_INDEX_ROWID 1 /* Search the rowid of the table */ -#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */ -#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */ -#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */ -#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */ -/* -** Allowed flags for the 3rd parameter to sqlite3FindInIndex(). -*/ -#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ -#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ -#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*); - -SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); -SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) -SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); -#endif - -SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p); -SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); - -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); -#if SQLITE_MAX_EXPR_DEPTH>0 -SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *); -SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); -#else - #define sqlite3SelectExprHeight(x) 0 - #define sqlite3ExprCheckHeight(x,y) -#endif -SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int); - -SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*); -SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32); - -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY -SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *); -SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db); -SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db); -#else - #define sqlite3ConnectionBlocked(x,y) - #define sqlite3ConnectionUnlocked(x) - #define sqlite3ConnectionClosed(x) -#endif - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); -#endif -#if defined(YYCOVERAGE) -SQLITE_PRIVATE int sqlite3ParserCoverage(FILE*); -#endif - -/* -** If the SQLITE_ENABLE IOTRACE exists then the global variable -** sqlite3IoTrace is a pointer to a printf-like routine used to -** print I/O tracing messages. -*/ -#ifdef SQLITE_ENABLE_IOTRACE -# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } -SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); -SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); -#else -# define IOTRACE(A) -# define sqlite3VdbeIOTraceSql(X) -#endif - -/* -** These routines are available for the mem2.c debugging memory allocator -** only. They are used to verify that different "types" of memory -** allocations are properly tracked by the system. -** -** sqlite3MemdebugSetType() sets the "type" of an allocation to one of -** the MEMTYPE_* macros defined below. The type must be a bitmask with -** a single bit set. -** -** sqlite3MemdebugHasType() returns true if any of the bits in its second -** argument match the type set by the previous sqlite3MemdebugSetType(). -** sqlite3MemdebugHasType() is intended for use inside assert() statements. -** -** sqlite3MemdebugNoType() returns true if none of the bits in its second -** argument match the type set by the previous sqlite3MemdebugSetType(). -** -** Perhaps the most important point is the difference between MEMTYPE_HEAP -** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means -** it might have been allocated by lookaside, except the allocation was -** too large or lookaside was already full. It is important to verify -** that allocations that might have been satisfied by lookaside are not -** passed back to non-lookaside free() routines. Asserts such as the -** example above are placed on the non-lookaside free() routines to verify -** this constraint. -** -** All of this is no-op for a production build. It only comes into -** play when the SQLITE_MEMDEBUG compile-time option is used. -*/ -#ifdef SQLITE_MEMDEBUG -SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8); -SQLITE_PRIVATE int sqlite3MemdebugHasType(const void*,u8); -SQLITE_PRIVATE int sqlite3MemdebugNoType(const void*,u8); -#else -# define sqlite3MemdebugSetType(X,Y) /* no-op */ -# define sqlite3MemdebugHasType(X,Y) 1 -# define sqlite3MemdebugNoType(X,Y) 1 -#endif -#define MEMTYPE_HEAP 0x01 /* General heap allocations */ -#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ -#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ - -/* -** Threading interface -*/ -#if SQLITE_MAX_WORKER_THREADS>0 -SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); -#endif - -#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST) -SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*); -#endif -#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) -SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); -#endif - -SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr); -SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); -SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int); -SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt); -#endif - -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) -SQLITE_PRIVATE int sqlite3KvvfsInit(void); -#endif - -#if defined(VDBE_PROFILE) \ - || defined(SQLITE_PERFORMANCE_TRACE) \ - || defined(SQLITE_ENABLE_STMT_SCANSTATUS) -SQLITE_PRIVATE sqlite3_uint64 sqlite3Hwtime(void); -#endif - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStatus) -#else -# define IS_STMT_SCANSTATUS(db) 0 -#endif - -#endif /* SQLITEINT_H */ - -/************** End of sqliteInt.h *******************************************/ -/************** 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 - -static sqlite_uint64 g_start; -static sqlite_uint64 g_elapsed; -#define TIMER_START g_start=sqlite3Hwtime() -#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start -#define TIMER_ELAPSED g_elapsed -#else -#define TIMER_START -#define TIMER_END -#define TIMER_ELAPSED ((sqlite_uint64)0) -#endif - -/* -** If we compile with the SQLITE_TEST macro set, then the following block -** of code will give us the ability to simulate a disk I/O error. This -** is used for testing the I/O recovery logic. -*/ -#if defined(SQLITE_TEST) -SQLITE_API extern int sqlite3_io_error_hit; -SQLITE_API extern int sqlite3_io_error_hardhit; -SQLITE_API extern int sqlite3_io_error_pending; -SQLITE_API extern int sqlite3_io_error_persist; -SQLITE_API extern int sqlite3_io_error_benign; -SQLITE_API extern int sqlite3_diskfull_pending; -SQLITE_API extern int sqlite3_diskfull; -#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) -#define SimulateIOError(CODE) \ - if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ - || sqlite3_io_error_pending-- == 1 ) \ - { local_ioerr(); CODE; } -static void local_ioerr(){ - IOTRACE(("IOERR\n")); - sqlite3_io_error_hit++; - if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; -} -#define SimulateDiskfullError(CODE) \ - if( sqlite3_diskfull_pending ){ \ - if( sqlite3_diskfull_pending == 1 ){ \ - local_ioerr(); \ - sqlite3_diskfull = 1; \ - sqlite3_io_error_hit = 1; \ - CODE; \ - }else{ \ - sqlite3_diskfull_pending--; \ - } \ - } -#else -#define SimulateIOErrorBenign(X) -#define SimulateIOError(A) -#define SimulateDiskfullError(A) -#endif /* defined(SQLITE_TEST) */ - -/* -** When testing, keep a count of the number of open files. -*/ -#if defined(SQLITE_TEST) -SQLITE_API extern int sqlite3_open_file_count; -#define OpenCounter(X) sqlite3_open_file_count+=(X) -#else -#define OpenCounter(X) -#endif /* defined(SQLITE_TEST) */ - -#endif /* !defined(_OS_COMMON_H_) */ - -/************** 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. -** -** To modify this header, edit any of the various lists in that script -** which specify categories of generated conditionals in this file. -*/ - -/* -** 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 "sqlite_cfg.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) -/* #include "sqliteInt.h" */ - -/* -** 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 sqlite3azCompileOpt[] = { - -#ifdef SQLITE_32BIT_ROWID - "32BIT_ROWID", -#endif -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC - "4_BYTE_ALIGNED_MALLOC", -#endif -#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 -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - "ALLOW_ROWID_IN_VIEW", -#endif -#ifdef SQLITE_ALLOW_URI_AUTHORITY - "ALLOW_URI_AUTHORITY", -#endif -#ifdef SQLITE_ATOMIC_INTRINSICS - "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS), -#endif -#ifdef SQLITE_BITMASK_TYPE - "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), -#endif -#ifdef SQLITE_BUG_COMPATIBLE_20160819 - "BUG_COMPATIBLE_20160819", -#endif -#ifdef SQLITE_BUG_COMPATIBLE_20250510 - "BUG_COMPATIBLE_20250510", -#endif -#ifdef SQLITE_CASE_SENSITIVE_LIKE - "CASE_SENSITIVE_LIKE", -#endif -#ifdef 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 -#ifdef SQLITE_COVERAGE_TEST - "COVERAGE_TEST", -#endif -#ifdef SQLITE_DEBUG - "DEBUG", -#endif -#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX - "DEFAULT_AUTOMATIC_INDEX", -#endif -#ifdef SQLITE_DEFAULT_AUTOVACUUM - "DEFAULT_AUTOVACUUM", -#endif -#ifdef SQLITE_DEFAULT_CACHE_SIZE - "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE), -#endif -#ifdef 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 -#ifdef 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 -#ifdef SQLITE_DEFAULT_MEMSTATUS -# if SQLITE_DEFAULT_MEMSTATUS != 1 - "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS), -# endif -#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 -#ifdef 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 -#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 -#ifdef SQLITE_DISABLE_FTS4_DEFERRED - "DISABLE_FTS4_DEFERRED", -#endif -#ifdef SQLITE_DISABLE_INTRINSIC - "DISABLE_INTRINSIC", -#endif -#ifdef SQLITE_DISABLE_LFS - "DISABLE_LFS", -#endif -#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS - "DISABLE_PAGECACHE_OVERFLOW_STATS", -#endif -#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT - "DISABLE_SKIPAHEAD_DISTINCT", -#endif -#ifdef SQLITE_DQS - "DQS=" CTIMEOPT_VAL(SQLITE_DQS), -#endif -#ifdef SQLITE_ENABLE_8_3_NAMES - "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - "ENABLE_API_ARMOR", -#endif -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - "ENABLE_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - "ENABLE_BATCH_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - "ENABLE_BYTECODE_VTAB", -#endif -#ifdef SQLITE_ENABLE_CEROD - "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA - "ENABLE_COLUMN_METADATA", -#endif -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - "ENABLE_COLUMN_USED_MASK", -#endif -#ifdef SQLITE_ENABLE_COSTMULT - "ENABLE_COSTMULT", -#endif -#ifdef SQLITE_ENABLE_CURSOR_HINTS - "ENABLE_CURSOR_HINTS", -#endif -#ifdef SQLITE_ENABLE_DBPAGE_VTAB - "ENABLE_DBPAGE_VTAB", -#endif -#ifdef SQLITE_ENABLE_DBSTAT_VTAB - "ENABLE_DBSTAT_VTAB", -#endif -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - "ENABLE_EXPENSIVE_ASSERT", -#endif -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - "ENABLE_EXPLAIN_COMMENTS", -#endif -#ifdef SQLITE_ENABLE_FTS3 - "ENABLE_FTS3", -#endif -#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS - "ENABLE_FTS3_PARENTHESIS", -#endif -#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_ORDERED_SET_AGGREGATES - "ENABLE_ORDERED_SET_AGGREGATES", -#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_SETLK_TIMEOUT - "ENABLE_SETLK_TIMEOUT", -#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_AUTOEXT - "EXTRA_AUTOEXT=" CTIMEOPT_VAL(SQLITE_EXTRA_AUTOEXT), -#endif -#ifdef SQLITE_EXTRA_IFNULLROW - "EXTRA_IFNULLROW", -#endif -#ifdef SQLITE_EXTRA_INIT - "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT), -#endif -#ifdef SQLITE_EXTRA_INIT_MUTEXED - "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED), -#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 -#ifdef SQLITE_HAS_CODEC - "HAS_CODEC", -#endif -#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_LEGACY_JSON_VALID - "LEGACY_JSON_VALID", -#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_SEH - "OMIT_SEH", -#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_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 - "THREADSAFE=1", -#endif -#ifdef SQLITE_UNLINK_AFTER_CLOSE - "UNLINK_AFTER_CLOSE", -#endif -#ifdef SQLITE_UNTESTABLE - "UNTESTABLE", -#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 - -} ; - -SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ - *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); - return (const char**)sqlite3azCompileOpt; -} - -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/************** End of ctime.c ***********************************************/ -/************** Begin file global.c ******************************************/ -/* -** 2008 June 13 -** -** 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 definitions of global variables and constants. -*/ -/* #include "sqliteInt.h" */ - -/* An array to map all upper-case characters into their corresponding -** lower-case character. -** -** SQLite only considers US-ASCII (or EBCDIC) characters. We do not -** handle case conversions for the UTF character set since the tables -** involved are nearly as big or bigger than SQLite itself. -*/ -SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { -#ifdef SQLITE_ASCII - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, - 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, - 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, - 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, - 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, - 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, - 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, -#endif -#ifdef SQLITE_EBCDIC - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */ - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */ - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */ - 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ - 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ - 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ - 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 -** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is -** going on: -** -** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented -** by invoking 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 sqlite3aLTb[opcode], sqlite3aEQb[opcode], or -** 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 *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne]; -SQLITE_PRIVATE const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne]; -SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne]; - -/* -** The following 256 byte lookup table is used to support SQLites built-in -** equivalents to the following standard library functions: -** -** isspace() 0x01 -** isalpha() 0x02 -** isdigit() 0x04 -** isalnum() 0x06 -** isxdigit() 0x08 -** toupper() 0x20 -** SQLite identifier character 0x40 $, _, or non-ascii -** Quote character 0x80 -** -** Bit 0x20 is set if the mapped character requires translation to upper -** case. i.e. if the character is a lower-case ASCII character. -** If x is a lower-case ASCII character, then its upper-case equivalent -** is (x - 0x20). Therefore toupper() can be implemented as: -** -** (x & ~(map[x]&0x20)) -** -** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] -** array. tolower() is used more often than toupper() by SQLite. -** -** Bit 0x40 is set if the character is non-alphanumeric and can be used in an -** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any -** non-ASCII UTF character. Hence the test for whether or not a character is -** part of an identifier is 0x46. -*/ -SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */ - 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */ - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */ - 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */ - - 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */ - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */ - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */ - 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */ - 0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */ - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */ - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */ - 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */ - - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */ - - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ -}; - -/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards -** compatibility for legacy applications, the URI filename capability is -** disabled by default. -** -** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled -** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. -** -** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally -** disabled. The default value may be changed by compiling with the -** SQLITE_USE_URI symbol defined. -** -** URI filenames are enabled by default if SQLITE_HAS_CODEC is -** enabled. -*/ -#ifndef SQLITE_USE_URI -/* BEGIN SQLCIPHER */ -# ifdef SQLITE_HAS_CODEC -# define SQLITE_USE_URI 1 -# else -# define SQLITE_USE_URI 0 -# endif -/* END SQLCIPHER */ -#endif - -/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the -** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if -** that compile-time option is omitted. -*/ -#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN) -# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 -#else -# if !SQLITE_ALLOW_COVERING_INDEX_SCAN -# error "Compile-time disabling of covering index scan using the\ - -DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\ - Contact SQLite developers if this is a problem for you, and\ - delete this #error macro to continue with your build." -# endif -#endif - -/* The minimum PMA size is set to this value multiplied by the database -** page size in bytes. -*/ -#ifndef SQLITE_SORTER_PMASZ -# define SQLITE_SORTER_PMASZ 250 -#endif - -/* Statement journals spill to disk when their size exceeds the following -** threshold (in bytes). 0 means that statement journals are created and -** written to disk immediately (the default behavior for SQLite versions -** before 3.12.0). -1 means always keep the entire statement journal in -** memory. (The statement journal is also always held entirely in memory -** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this -** setting.) -*/ -#ifndef SQLITE_STMTJRNL_SPILL -# define SQLITE_STMTJRNL_SPILL (64*1024) -#endif - -/* -** The default lookaside-configuration, the format "SZ,N". SZ is the -** number of bytes in each lookaside slot (should be a multiple of 8) -** and N is the number of slots. The lookaside-configuration can be -** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE) -** or at run-time for an individual database connection using -** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE); -** -** With the two-size-lookaside enhancement, less lookaside is required. -** The default configuration of 1200,40 actually provides 30 1200-byte slots -** and 93 128-byte slots, which is more lookaside than is available -** using the older 1200,100 configuration without two-size-lookaside. -*/ -#ifndef SQLITE_DEFAULT_LOOKASIDE -# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE -# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */ -# else -# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */ -# endif -#endif - - -/* The default maximum size of an in-memory database created using -** sqlite3_deserialize() -*/ -#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE -# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824 -#endif - -/* -** The following singleton contains the global configuration for -** the SQLite library. -*/ -SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { - SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ - 1, /* bCoreMutex */ - SQLITE_THREADSAFE==1, /* bFullMutex */ - SQLITE_USE_URI, /* bOpenUri */ - SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ - 0, /* bSmallMalloc */ - 1, /* bExtraSchemaChecks */ -#ifdef SQLITE_DEBUG - 0, /* bJsonSelfcheck */ -#endif - 0x7ffffffe, /* mxStrlen */ - 0, /* neverCorrupt */ - SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ - SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ - {0,0,0,0,0,0,0,0}, /* m */ - {0,0,0,0,0,0,0,0,0}, /* mutex */ - {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ - (void*)0, /* pHeap */ - 0, /* nHeap */ - 0, 0, /* mnHeap, mxHeap */ - SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ - SQLITE_MAX_MMAP_SIZE, /* mxMmap */ - (void*)0, /* pPage */ - 0, /* szPage */ - SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */ - 0, /* mxParserStack */ - 0, /* sharedCacheEnabled */ - SQLITE_SORTER_PMASZ, /* szPma */ - /* All the rest should always be initialized to zero */ - 0, /* isInit */ - 0, /* inProgress */ - 0, /* isMutexInit */ - 0, /* isMallocInit */ - 0, /* isPCacheInit */ - 0, /* nRefInitMutex */ - 0, /* pInitMutex */ - 0, /* xLog */ - 0, /* pLogArg */ -#ifdef SQLITE_ENABLE_SQLLOG - 0, /* xSqllog */ - 0, /* pSqllogArg */ -#endif -#ifdef SQLITE_VDBE_COVERAGE - 0, /* xVdbeBranch */ - 0, /* pVbeBranchArg */ -#endif -#ifndef SQLITE_OMIT_DESERIALIZE - SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ -#endif -#ifndef SQLITE_UNTESTABLE - 0, /* xTestCallback */ -#endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */ -#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 -}; - -/* -** Hash table for global functions - functions common to all -** database connections. After initialization, this table is -** read-only. -*/ -SQLITE_PRIVATE FuncDefHash 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 sqlite3CoverageCounter; -#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */ - -#ifdef VDBE_PROFILE -/* -** The following performance counter can be used in place of -** sqlite3Hwtime() for profiling. This is a no-op on standard builds. -*/ -SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; -#endif - -/* -** The value of the "pending" byte must be 0x40000000 (1 byte past the -** 1-gibabyte boundary) in a compatible database. SQLite never uses -** the database page that contains the pending byte. It never attempts -** to read or write that page. The pending byte page is set aside -** for use by the VFS layers as space for managing file locks. -** -** During testing, it is often desirable to move the pending byte to -** a different position in the file. This allows code that has to -** deal with the pending byte to run on files that are much smaller -** than 1 GiB. The sqlite3_test_control() interface can be used to -** move the pending byte. -** -** IMPORTANT: Changing the pending byte to any value other than -** 0x40000000 results in an incompatible database file format! -** Changing the pending byte during operation will result in undefined -** and incorrect behavior. -*/ -#ifndef SQLITE_OMIT_WSD -SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; -#endif - -/* -** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS. -*/ -SQLITE_PRIVATE u32 sqlite3TreeTrace = 0; -SQLITE_PRIVATE u32 sqlite3WhereTrace = 0; - -/* #include "opcodes.h" */ -/* -** Properties of opcodes. The OPFLG_INITIALIZER macro is -** created by mkopcodeh.awk during compilation. Data is obtained -** from the comments following the "case OP_xxxx:" statements in -** the vdbe.c file. -*/ -SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; - -/* -** Name of the default collating sequence -*/ -SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; - -/* -** Standard typenames. These names must match the COLTYPE_* definitions. -** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. -** -** sqlite3StdType[] The actual names of the datatypes. -** -** sqlite3StdTypeLen[] The length (in bytes) of each entry -** in sqlite3StdType[]. -** -** sqlite3StdTypeAffinity[] The affinity associated with each entry -** in sqlite3StdType[]. -*/ -SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 }; -SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = { - SQLITE_AFF_NUMERIC, - SQLITE_AFF_BLOB, - SQLITE_AFF_INTEGER, - SQLITE_AFF_INTEGER, - SQLITE_AFF_REAL, - SQLITE_AFF_TEXT -}; -SQLITE_PRIVATE const char *sqlite3StdType[] = { - "ANY", - "BLOB", - "INT", - "INTEGER", - "REAL", - "TEXT" -}; - -/************** End of global.c **********************************************/ -/************** Begin file status.c ******************************************/ -/* -** 2008 June 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This module implements the sqlite3_status() interface and related -** functionality. -*/ -/* #include "sqliteInt.h" */ -/************** Include vdbeInt.h in the middle of status.c ******************/ -/************** Begin file vdbeInt.h *****************************************/ -/* -** 2003 September 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 is the header file for information that is private to the -** VDBE. This information used to all be at the top of the single -** source code file "vdbe.c". When that file became too big (over -** 6000 lines long) it was split up into several smaller files and -** this header information was factored out. -*/ -#ifndef SQLITE_VDBEINT_H -#define SQLITE_VDBEINT_H - -/* -** The maximum number of times that a statement will try to reparse -** itself before giving up and returning SQLITE_SCHEMA. -*/ -#ifndef SQLITE_MAX_SCHEMA_RETRY -# define SQLITE_MAX_SCHEMA_RETRY 50 -#endif - -/* -** VDBE_DISPLAY_P4 is true or false depending on whether or not the -** "explain" P4 display logic is enabled. -*/ -#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ - || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \ - || defined(SQLITE_ENABLE_BYTECODE_VTAB) -# define VDBE_DISPLAY_P4 1 -#else -# define VDBE_DISPLAY_P4 0 -#endif - -/* -** SQL is translated into a sequence of instructions to be -** executed by a virtual machine. Each instruction is an instance -** of the following structure. -*/ -typedef struct VdbeOp Op; - -/* -** Boolean values -*/ -typedef unsigned Bool; - -/* Opaque type used by code in vdbesort.c */ -typedef struct VdbeSorter VdbeSorter; - -/* Elements of the linked list at Vdbe.pAuxData */ -typedef struct AuxData AuxData; - -/* A cache of large TEXT or BLOB values in a VdbeCursor */ -typedef struct VdbeTxtBlbCache VdbeTxtBlbCache; - -/* Types of VDBE cursors */ -#define CURTYPE_BTREE 0 -#define CURTYPE_SORTER 1 -#define CURTYPE_VTAB 2 -#define CURTYPE_PSEUDO 3 - -/* -** A VdbeCursor is an superclass (a wrapper) for various cursor objects: -** -** * A b-tree cursor -** - In the main database or in an ephemeral database -** - On either an index or a table -** * A sorter -** * A virtual table -** * A one-row "pseudotable" stored in a single register -*/ -typedef struct VdbeCursor VdbeCursor; -struct VdbeCursor { - u8 eCurType; /* One of the CURTYPE_* values above */ - 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 sqlite3BtreeMoveto() is needed */ - u8 isTable; /* True for rowid tables. False for indexes */ -#ifdef SQLITE_DEBUG - u8 seekOp; /* Most recent seek operation on this cursor */ - u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ -#endif - 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 */ - Bool colCache:1; /* pCache pointer is initialized and non-NULL */ - u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */ - 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 */ - - /* Cached OP_Column parse information is only valid if cacheStatus matches - ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of - ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that - ** the cache is out of date. */ - u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ - int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 - ** if there have been no prior seeks on the cursor. */ - /* seekResult does not distinguish between "no seeks have ever occurred - ** on this cursor" and "the most recent seek was an exact match". - ** For CURTYPE_PSEUDO, seekResult is the register holding the record */ - - /* When a new VdbeCursor is allocated, only the fields above are zeroed. - ** The fields that follow are uninitialized, and must be individually - ** initialized prior to first use. */ - VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ - union { - BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */ - sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ - VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ - } uc; - KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ - u32 iHdrOffset; /* Offset to next unparsed byte of the header */ - Pgno pgnoRoot; /* Root page of the open btree cursor */ - i16 nField; /* Number of fields in the header */ - u16 nHdrParsed; /* Number of header fields parsed so far */ - i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ - u32 *aOffset; /* Pointer to aType[nField] */ - const u8 *aRow; /* Data for the current row, if all on one page */ - u32 payloadSize; /* Total number of bytes in the record */ - u32 szRow; /* Byte available in aRow */ -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - u64 maskUsed; /* Mask of columns used by this cursor */ -#endif - VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ - - /* Space is allocated for aType to hold at least 2*nField+1 entries: - ** nField slots for aType[] and nField+1 array slots for aOffset[] */ - u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */ -}; - -/* -** The size (in bytes) of a VdbeCursor object that has an nField value of N -** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple -** of 8. -*/ -#define SZ_VDBECURSOR(N) \ - (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64)) - -/* 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. -*/ -#define CACHE_STALE 0 - -/* -** Large TEXT or BLOB values can be slow to load, so we want to avoid -** loading them more than once. For that reason, large TEXT and BLOB values -** can be stored in a cache defined by this object, and attached to the -** VdbeCursor using the pCache field. -*/ -struct VdbeTxtBlbCache { - char *pCValue; /* A RCStr buffer to hold the value */ - i64 iOffset; /* File offset of the row being cached */ - int iCol; /* Column for which the cache is valid */ - u32 cacheStatus; /* Vdbe.cacheCtr value */ - u32 colCacheCtr; /* Column cache counter */ -}; - -/* -** When a sub-program is executed (OP_Program), a structure of this type -** is allocated to store the current value of the program counter, as -** well as the current memory cell array and various other frame specific -** values stored in the Vdbe struct. When the sub-program is finished, -** these values are copied back to the Vdbe from the VdbeFrame structure, -** restoring the state of the VM to as it was before the sub-program -** began executing. -** -** The memory for a VdbeFrame object is allocated and managed by a memory -** cell in the parent (calling) frame. When the memory cell is deleted or -** overwritten, the VdbeFrame object is not freed immediately. Instead, it -** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame -** list is deleted when the VM is reset in VdbeHalt(). The reason for doing -** this instead of deleting the VdbeFrame immediately is to avoid recursive -** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the -** child frame are released. -** -** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is -** set to NULL if the currently executing frame is the main program. -*/ -typedef struct VdbeFrame VdbeFrame; -struct VdbeFrame { - Vdbe *v; /* VM this frame belongs to */ - VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ - Op *aOp; /* Program instructions for parent frame */ - Mem *aMem; /* Array of memory cells for parent frame */ - VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ - u8 *aOnce; /* Bitmask used by OP_Once */ - void *token; /* Copy of SubProgram.token */ - i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ - AuxData *pAuxData; /* Linked list of auxdata allocations */ -#if SQLITE_DEBUG - u32 iFrameMagic; /* magic number for sanity checking */ -#endif - int nCursor; /* Number of entries in apCsr */ - int pc; /* Program Counter in parent (calling) frame */ - int nOp; /* Size of aOp array */ - int nMem; /* Number of entries in aMem */ - int nChildMem; /* Number of memory cells for child frame */ - int nChildCsr; /* Number of cursors for child frame */ - i64 nChange; /* Statement changes (Vdbe.nChange) */ - i64 nDbChange; /* Value of db->nChange */ -}; - -/* Magic number for sanity checking on VdbeFrame objects */ -#define SQLITE_FRAME_MAGIC 0x879fb71e - -/* -** Return a pointer to the array of registers allocated for use -** by a VdbeFrame. -*/ -#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) - -/* -** Internally, the vdbe manipulates nearly all SQL values as Mem -** structures. Each Mem struct may cache multiple representations (string, -** integer etc.) of the same value. -*/ -struct sqlite3_value { - union MemValue { - double r; /* Real value used when MEM_Real is set in flags */ - i64 i; /* Integer value used when MEM_Int is set in flags */ - int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ - 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 */ - /* ShallowCopy only needs to copy the information above */ - sqlite3 *db; /* The associated database connection */ - int szMalloc; /* Size of the zMalloc allocation */ - u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ - 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 */ - u16 mScopyFlags; /* flags value immediately after the shallow copy */ - u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */ -#endif -}; - -/* -** Size of struct Mem not including the Mem.zMalloc member or anything that -** follows. -*/ -#define MEMCELLSIZE offsetof(Mem,db) - -/* 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 -** 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 sqlite3_bind_pointer() or -** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. -** -** If the MEM_Str flag is set then Mem.z points at a string representation. -** Usually this is encoded in the same unicode encoding as the main -** database (see below for exceptions). If the MEM_Term flag is also -** 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 */ -#define MEM_Real 0x0008 /* Value is a real number */ -#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 sqlite3_bind() */ - /* 0x0080 // Available */ -#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#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 */ - -/* Bits that determine the storage for Mem.z for a string or blob or -** aggregate accumulator. -*/ -#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. -*/ -#define VdbeMemDynamic(X) \ - (((X)->flags&(MEM_Agg|MEM_Dyn))!=0) - -/* -** Clear any existing type flags from a Mem and replace them with f -*/ -#define MemSetTypeFlag(p, f) \ - ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) - -/* -** True if Mem X is a NULL-nochng type. -*/ -#define MemNullNochng(X) \ - (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \ - && (X)->n==0 && (X)->u.nZero==0) - -/* -** 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_AffMask)!=0 -#endif - -/* -** Each auxiliary data pointer stored by a user defined function -** implementation calling sqlite3_set_auxdata() is stored in an instance -** of this structure. All such structures associated with a single VM -** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed -** when the VM is halted (if not before). -*/ -struct AuxData { - int iAuxOp; /* Instruction number of OP_Function opcode */ - int iAuxArg; /* Index of function argument. */ - void *pAux; /* Aux data pointer */ - void (*xDeleteAux)(void*); /* Destructor for the aux data */ - AuxData *pNextAux; /* Next element in list */ -}; - -/* -** The "context" argument for an installable function. A pointer to an -** instance of this structure is the first argument to the routines used -** implement the SQL functions. -** -** There is a typedef for this structure in sqlite.h. So all routines, -** even the public interface to SQLite, can use a pointer to this structure. -** But this file is the only place where the internal details of this -** structure are known. -** -** This structure is defined inside of vdbeInt.h because it uses substructures -** (Mem) which are only defined there. -*/ -struct sqlite3_context { - Mem *pOut; /* The return value is stored here */ - FuncDef *pFunc; /* Pointer to function information */ - Mem *pMem; /* Memory cell used to store aggregate 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 */ - u16 argc; /* Number of arguments */ - sqlite3_value *argv[FLEXARRAY]; /* Argument set */ -}; - -/* -** The size (in bytes) of an sqlite3_context object that holds N -** argv[] arguments. -*/ -#define SZ_CONTEXT(N) \ - (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*)) - - -/* The ScanStatus object holds a single value for the -** sqlite3_stmt_scanstatus() interface. -** -** aAddrRange[]: -** This array is used by ScanStatus elements associated with EQP -** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is -** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[] -** values should be summed to calculate the NCYCLE value. Each pair of -** integer addresses is a start and end address (both inclusive) for a range -** instructions. A start value of 0 indicates an empty range. -*/ -typedef struct ScanStatus ScanStatus; -struct ScanStatus { - int addrExplain; /* OP_Explain for loop */ - int aAddrRange[6]; - int addrLoop; /* Address of "loops" counter */ - int addrVisit; /* Address of "rows visited" counter */ - int iSelectID; /* The "Select-ID" for this loop */ - LogEst nEst; /* Estimated output rows per loop */ - char *zName; /* Name of table or index */ -}; - -/* The DblquoteStr object holds the text of a double-quoted -** string for a prepared statement. A linked list of these objects -** is constructed during statement parsing and is held on Vdbe.pDblStr. -** When computing a normalized SQL statement for an SQL statement, that -** list is consulted for each double-quoted identifier to see if the -** identifier should really be a string literal. -*/ -typedef struct DblquoteStr DblquoteStr; -struct DblquoteStr { - DblquoteStr *pNextStr; /* Next string literal in the list */ - char z[8]; /* Dequoted value for the string */ -}; - -/* -** An instance of the virtual machine. This structure contains the complete -** state of the virtual machine. -** -** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() -** is really a pointer to an instance of this structure. -*/ -struct Vdbe { - sqlite3 *db; /* The database connection that owns this statement */ - Vdbe **ppVPrev,*pVNext; /* 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[] */ - 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 */ - 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 */ - i64 nStmtDefCons; /* Number of def. constraints when stmt started */ - i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ - Mem *aMem; /* The memory locations */ - Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */ - VdbeCursor **apCsr; /* One element of this array for each open cursor */ - Mem *aVar; /* Values for the OP_Variable opcode. */ - - /* When allocating a new Vdbe object, all of the fields below should be - ** initialized to zero or NULL */ - - Op *aOp; /* Space to hold the virtual machine's program */ - int nOp; /* Number of instructions in the program */ - int nOpAlloc; /* Slots allocated for aOp[] */ - Mem *aColName; /* Column names to return */ - Mem *pResultRow; /* Current output row */ - char *zErrMsg; /* Error message written here */ - VList *pVList; /* Name of variables */ -#ifndef SQLITE_OMIT_TRACE - i64 startTime; /* Time when query started - used for profiling */ -#endif -#ifdef SQLITE_DEBUG - int rcApp; /* errcode set by sqlite3_result_error_code() */ - u32 nWrite; /* Number of write operations that have occurred */ - int napArg; /* Size of the apArg[] array */ -#endif - u16 nResColumn; /* Number of columns in one row of the result set */ - u16 nResAlloc; /* Column slots allocated to aColName[] */ - 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 eVdbeState; /* On of the VDBE_*_STATE values */ - bft expired:2; /* 1: recompile VM immediately 2: when convenient */ - bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */ - bft changeCntOn:1; /* True to update the change-counter */ - 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 */ - bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */ - yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ - yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[9]; /* Counters used by 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 */ - DblquoteStr *pDblStr; /* List of double-quoted string literals */ -#endif - void *pFree; /* Free this when deleting the vdbe */ - VdbeFrame *pFrame; /* Parent frame */ - VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ - int nFrame; /* Number of frames in pFrame list */ - u32 expmask; /* Binding to these vars invalidates VM */ - SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ - AuxData *pAuxData; /* Linked list of auxdata allocations */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int nScan; /* Entries in aScan[] */ - ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ -#endif -}; - -/* -** The following are allowed values for Vdbe.eVdbeState -*/ -#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 -** sqlite3_preupdate_*() API functions. -*/ -struct PreUpdate { - Vdbe *v; - VdbeCursor *pCsr; /* Cursor to read old values from */ - int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ - u8 *aRecord; /* old.* database record */ - KeyInfo *pKeyinfo; /* Key information */ - 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 oldipk; /* Memory cell holding "old" IPK value */ - Mem *aNew; /* Array of new.* values */ - Table *pTab; /* Schema object being updated */ - Index *pPk; /* PK index if pTab is WITHOUT ROWID */ - sqlite3_value **apDflt; /* Array of default values, if required */ - u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */ -}; - -/* -** 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 sqlite3_value with a "pointer" -** type, such as is generated by sqlite3_result_pointer() and read by -** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null -** and a subtype of 'p'. The 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 */ - 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 sqlite3SmallTypeSizes[]; -#endif - -/* -** Function prototypes -*/ -SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); -SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); -SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*); -void sqliteVdbePopStack(Vdbe*,int); -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p); -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*); -SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); -SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); -SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in); -# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X) -#else -# define swapMixedEndianFloat(X) -#endif -SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); -SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); - -int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); -SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); -SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); -#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB) -SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**); -SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*); -#endif -#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) -SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*); -#endif -#if !defined(SQLITE_OMIT_EXPLAIN) -SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); -#endif -SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); -SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); -SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); -SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); -SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); -#ifdef SQLITE_OMIT_FLOATING_POINT -# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 -#else -SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); -#endif -SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); -SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); -SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); -#ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); -#else -SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); -#endif -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); -#endif -SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); -SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); -SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); -SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); -SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); -SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8); -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*); -SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); -SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem*p); -SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); -#endif -#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB) -SQLITE_PRIVATE const char *sqlite3OpcodeName(int); -#endif -SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); -SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); -SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*); -#endif -SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ -SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ -SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( - Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int); -#endif -SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); - -SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); -SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); -SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); -SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); -SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *); -SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); -SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); -SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); - -SQLITE_PRIVATE void sqlite3VdbeValueListFree(void*); - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); -SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); -#else -# define sqlite3VdbeIncrWriteCounter(V,C) -# define sqlite3VdbeAssertAbortable(V) -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) -SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); -#else -# define sqlite3VdbeEnter(X) -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 -SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*); -#else -# define sqlite3VdbeLeave(X) -#endif - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); -SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*); -#endif - -#ifndef SQLITE_OMIT_FOREIGN_KEY -SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int); -#else -# define sqlite3VdbeCheckFk(p,i) 0 -#endif - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr); -#endif -#ifndef SQLITE_OMIT_UTF16 -SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8); -SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem); -#endif - -#ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *); - #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) -#else - #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK - #define ExpandBlob(P) SQLITE_OK -#endif - -#endif /* !defined(SQLITE_VDBEINT_H) */ - -/************** End of vdbeInt.h *********************************************/ -/************** Continuing where we left off in status.c *********************/ - -/* -** Variables in which to record status information. -*/ -#if SQLITE_PTRSIZE>4 -typedef sqlite3_int64 sqlite3StatValueType; -#else -typedef u32 sqlite3StatValueType; -#endif -typedef struct sqlite3StatType sqlite3StatType; -static SQLITE_WSD struct sqlite3StatType { - sqlite3StatValueType nowValue[10]; /* Current value */ - sqlite3StatValueType mxValue[10]; /* Maximum value */ -} sqlite3Stat = { {0,}, {0,} }; - -/* -** Elements of sqlite3Stat[] are protected by either the memory allocator -** mutex, or by the pcache1 mutex. The following array determines which. -*/ -static const char statMutex[] = { - 0, /* SQLITE_STATUS_MEMORY_USED */ - 1, /* SQLITE_STATUS_PAGECACHE_USED */ - 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ - 0, /* SQLITE_STATUS_SCRATCH_USED */ - 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ - 0, /* SQLITE_STATUS_MALLOC_SIZE */ - 0, /* SQLITE_STATUS_PARSER_STACK */ - 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ - 0, /* SQLITE_STATUS_SCRATCH_SIZE */ - 0, /* SQLITE_STATUS_MALLOC_COUNT */ -}; - - -/* The "wsdStat" macro will resolve to the status information -** state vector. If writable static data is unsupported on the target, -** we have to locate the state vector at run-time. In the more common -** case where writable static data is supported, wsdStat can refer directly -** to the "sqlite3Stat" state vector declared above. -*/ -#ifdef SQLITE_OMIT_WSD -# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat) -# define wsdStat x[0] -#else -# define wsdStatInit -# define wsdStat sqlite3Stat -#endif - -/* -** Return the current value of a status parameter. The caller must -** be holding the appropriate mutex. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){ - wsdStatInit; - assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ - wsdStat.mxValue[op] = wsdStat.nowValue[op]; - } -} -SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){ - wsdStatInit; - assert( N>=0 ); - assert( op>=0 && op=0 && op=0 ); - newValue = (sqlite3StatValueType)X; - assert( op>=0 && op=0 && opwsdStat.mxValue[op] ){ - wsdStat.mxValue[op] = newValue; - } -} - -/* -** Query status information. -*/ -SQLITE_API int sqlite3_status64( - int op, - sqlite3_int64 *pCurrent, - sqlite3_int64 *pHighwater, - int resetFlag -){ - sqlite3_mutex *pMutex; - wsdStatInit; - if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ - return SQLITE_MISUSE_BKPT; - } -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; -#endif - pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); - sqlite3_mutex_enter(pMutex); - *pCurrent = wsdStat.nowValue[op]; - *pHighwater = wsdStat.mxValue[op]; - if( resetFlag ){ - wsdStat.mxValue[op] = wsdStat.nowValue[op]; - } - sqlite3_mutex_leave(pMutex); - (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ - return SQLITE_OK; -} -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ - sqlite3_int64 iCur = 0, iHwtr = 0; - int rc; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; -#endif - rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); - if( rc==0 ){ - *pCurrent = (int)iCur; - *pHighwater = (int)iHwtr; - } - return rc; -} - -/* -** Return the number of LookasideSlot elements on the linked list -*/ -static u32 countLookasideSlots(LookasideSlot *p){ - u32 cnt = 0; - while( p ){ - p = p->pNext; - cnt++; - } - return cnt; -} - -/* -** Count the number of slots of lookaside memory that are outstanding -*/ -SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ - u32 nInit = countLookasideSlots(db->lookaside.pInit); - u32 nFree = countLookasideSlots(db->lookaside.pFree); -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - nInit += countLookasideSlots(db->lookaside.pSmallInit); - nFree += countLookasideSlots(db->lookaside.pSmallFree); -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - assert( db->lookaside.nSlot >= nInit+nFree ); - if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit); - return (int)(db->lookaside.nSlot - (nInit+nFree)); -} - -/* -** Query status information for a single database connection -*/ -SQLITE_API int sqlite3_db_status( - sqlite3 *db, /* The database connection whose status is desired */ - int op, /* Status verb */ - int *pCurrent, /* Write current value here */ - int *pHighwater, /* Write high-water mark here */ - int resetFlag /* Reset high-water mark if true */ -){ - int rc = SQLITE_OK; /* Return code */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - switch( op ){ - case SQLITE_DBSTATUS_LOOKASIDE_USED: { - *pCurrent = sqlite3LookasideUsed(db, pHighwater); - if( resetFlag ){ - LookasideSlot *p = db->lookaside.pFree; - if( p ){ - while( p->pNext ) p = p->pNext; - p->pNext = db->lookaside.pInit; - db->lookaside.pInit = db->lookaside.pFree; - db->lookaside.pFree = 0; - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - p = db->lookaside.pSmallFree; - if( p ){ - while( p->pNext ) p = p->pNext; - p->pNext = db->lookaside.pSmallInit; - db->lookaside.pSmallInit = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = 0; - } -#endif - } - break; - } - - case SQLITE_DBSTATUS_LOOKASIDE_HIT: - case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE: - case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: { - testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT ); - testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ); - testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL ); - assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 ); - assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 ); - *pCurrent = 0; - *pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT]; - if( resetFlag ){ - db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; - } - break; - } - - /* - ** Return an approximation for the amount of memory currently used - ** by all pagers associated with the given database connection. The - ** highwater mark is meaningless and is returned as zero. - */ - case SQLITE_DBSTATUS_CACHE_USED_SHARED: - case SQLITE_DBSTATUS_CACHE_USED: { - int totalUsed = 0; - int i; - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - Pager *pPager = sqlite3BtreePager(pBt); - int nByte = sqlite3PagerMemUsed(pPager); - if( op==SQLITE_DBSTATUS_CACHE_USED_SHARED ){ - nByte = nByte / sqlite3BtreeConnectionCount(pBt); - } - totalUsed += nByte; - } - } - sqlite3BtreeLeaveAll(db); - *pCurrent = totalUsed; - *pHighwater = 0; - break; - } - - /* - ** *pCurrent gets an accurate estimate of the amount of memory used - ** to store the schema for all databases (main, temp, and any ATTACHed - ** databases. *pHighwater is set to zero. - */ - case SQLITE_DBSTATUS_SCHEMA_USED: { - int i; /* Used to iterate through schemas */ - int nByte = 0; /* Used to accumulate return value */ - - sqlite3BtreeEnterAll(db); - db->pnBytesFreed = &nByte; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; - for(i=0; inDb; i++){ - Schema *pSchema = db->aDb[i].pSchema; - if( ALWAYS(pSchema!=0) ){ - HashElem *p; - - nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( - pSchema->tblHash.count - + pSchema->trigHash.count - + pSchema->idxHash.count - + pSchema->fkeyHash.count - ); - nByte += sqlite3_msize(pSchema->tblHash.ht); - nByte += sqlite3_msize(pSchema->trigHash.ht); - nByte += sqlite3_msize(pSchema->idxHash.ht); - nByte += sqlite3_msize(pSchema->fkeyHash.ht); - - for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ - sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); - } - for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ - sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); - } - } - } - db->pnBytesFreed = 0; - db->lookaside.pEnd = db->lookaside.pTrueEnd; - sqlite3BtreeLeaveAll(db); - - *pHighwater = 0; - *pCurrent = nByte; - break; - } - - /* - ** *pCurrent gets an accurate estimate of the amount of memory used - ** to store all prepared statements. - ** *pHighwater is set to zero. - */ - case SQLITE_DBSTATUS_STMT_USED: { - struct Vdbe *pVdbe; /* Used to iterate through VMs */ - int nByte = 0; /* Used to accumulate return value */ - - db->pnBytesFreed = &nByte; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; - for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){ - sqlite3VdbeDelete(pVdbe); - } - db->lookaside.pEnd = db->lookaside.pTrueEnd; - db->pnBytesFreed = 0; - - *pHighwater = 0; /* IMP: R-64479-57858 */ - *pCurrent = nByte; - - break; - } - - /* - ** Set *pCurrent to the total cache hits or misses encountered by all - ** pagers the database handle is connected to. *pHighwater is always set - ** to zero. - */ - case SQLITE_DBSTATUS_CACHE_SPILL: - op = SQLITE_DBSTATUS_CACHE_WRITE+1; - /* no break */ deliberate_fall_through - case SQLITE_DBSTATUS_CACHE_HIT: - case SQLITE_DBSTATUS_CACHE_MISS: - case SQLITE_DBSTATUS_CACHE_WRITE:{ - int i; - u64 nRet = 0; - assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); - assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); - - for(i=0; inDb; i++){ - if( db->aDb[i].pBt ){ - Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt); - sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet); - } - } - *pHighwater = 0; /* IMP: R-42420-56072 */ - /* IMP: R-54100-20147 */ - /* IMP: R-29431-39229 */ - *pCurrent = (int)nRet & 0x7fffffff; - break; - } - - /* Set *pCurrent to non-zero if there are unresolved deferred foreign - ** key constraints. Set *pCurrent to zero if all foreign key constraints - ** have been satisfied. The *pHighwater is always set to zero. - */ - case SQLITE_DBSTATUS_DEFERRED_FKS: { - *pHighwater = 0; /* IMP: R-11967-56545 */ - *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; - break; - } - - default: { - rc = SQLITE_ERROR; - } - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/************** End of status.c **********************************************/ -/************** Begin file date.c ********************************************/ -/* -** 2003 October 31 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement date and time -** functions for SQLite. -** -** There is only one exported symbol in this file - the function -** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. -** All other code has file scope. -** -** SQLite processes all times and dates as julian day numbers. The -** dates and times are stored as the number of days since noon -** in Greenwich on November 24, 4714 B.C. according to the Gregorian -** calendar system. -** -** 1970-01-01 00:00:00 is JD 2440587.5 -** 2000-01-01 00:00:00 is JD 2451544.5 -** -** This implementation requires years to be expressed as a 4-digit number -** which means that only dates between 0000-01-01 and 9999-12-31 can -** be represented, even though julian day numbers allow a much wider -** range of dates. -** -** The Gregorian calendar system is used for all dates and times, -** even those that predate the Gregorian calendar. Historians usually -** use the julian calendar for dates prior to 1582-10-15 and for some -** dates afterwards, depending on locale. Beware of this difference. -** -** The conversion algorithms are implemented based on descriptions -** in the following text: -** -** Jean Meeus -** Astronomical Algorithms, 2nd Edition, 1998 -** ISBN 0-943396-61-1 -** Willmann-Bell, Inc -** Richmond, Virginia (USA) -*/ -/* #include "sqliteInt.h" */ -/* #include */ -/* #include */ -#include - -#ifndef SQLITE_OMIT_DATETIME_FUNCS - -/* -** The MSVC CRT on Windows CE may not have a localtime() function. -** So declare a substitute. The substitute function itself is -** defined in "os_win.c". -*/ -#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \ - (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API) -struct tm *__cdecl localtime(const time_t *); -#endif - -/* -** A structure for holding a single date and time. -*/ -typedef struct DateTime DateTime; -struct DateTime { - sqlite3_int64 iJD; /* The julian day number times 86400000 */ - int Y, M, D; /* Year, month, and day */ - int h, m; /* Hour and minutes */ - int tz; /* Timezone offset in minutes */ - double s; /* Seconds */ - char validJD; /* True (1) if iJD is valid */ - char validYMD; /* True (1) if Y,M,D are valid */ - char validHMS; /* True (1) if h,m,s are valid */ - char nFloor; /* Days to implement "floor" */ - unsigned rawS : 1; /* Raw numeric value stored in s */ - unsigned isError : 1; /* An overflow has occurred */ - unsigned useSubsec : 1; /* Display subsecond precision */ - unsigned isUtc : 1; /* Time is known to be UTC */ - unsigned isLocal : 1; /* Time is known to be localtime */ -}; - - -/* -** Convert zDate into one or more integers according to the conversion -** specifier zFormat. -** -** zFormat[] contains 4 characters for each integer converted, except for -** the last integer which is specified by three characters. The meaning -** of a four-character format specifiers ABCD is: -** -** A: number of digits to convert. Always "2" or "4". -** B: minimum value. Always "0" or "1". -** C: maximum value, decoded as: -** a: 12 -** b: 14 -** c: 24 -** d: 31 -** e: 59 -** f: 9999 -** D: the separator character, or \000 to indicate this is the -** last number to convert. -** -** Example: To translate an ISO-8601 date YYYY-MM-DD, the format would -** be "40f-21a-20c". The "40f-" indicates the 4-digit year followed by "-". -** The "21a-" indicates the 2-digit month followed by "-". The "20c" indicates -** the 2-digit day which is the last integer in the set. -** -** The function returns the number of successful conversions. -*/ -static int getDigits(const char *zDate, const char *zFormat, ...){ - /* The aMx[] array translates the 3rd character of each format - ** spec into a max size: a b c d e f */ - static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 }; - va_list ap; - int cnt = 0; - char nextC; - va_start(ap, zFormat); - do{ - char N = zFormat[0] - '0'; - char min = zFormat[1] - '0'; - int val = 0; - u16 max; - - assert( zFormat[2]>='a' && zFormat[2]<='f' ); - max = aMx[zFormat[2] - 'a']; - nextC = zFormat[3]; - val = 0; - while( N-- ){ - if( !sqlite3Isdigit(*zDate) ){ - goto end_getDigits; - } - val = val*10 + *zDate - '0'; - zDate++; - } - if( val<(int)min || val>(int)max || (nextC!=0 && nextC!=*zDate) ){ - goto end_getDigits; - } - *va_arg(ap,int*) = val; - zDate++; - cnt++; - zFormat += 4; - }while( nextC ); -end_getDigits: - va_end(ap); - return cnt; -} - -/* -** Parse a timezone extension on the end of a date-time. -** The extension is of the form: -** -** (+/-)HH:MM -** -** Or the "zulu" notation: -** -** Z -** -** If the parse is successful, write the number of minutes -** of change in p->tz and return 0. If a parser error occurs, -** return non-zero. -** -** A missing specifier is not considered an error. -*/ -static int parseTimezone(const char *zDate, DateTime *p){ - int sgn = 0; - int nHr, nMn; - int c; - while( sqlite3Isspace(*zDate) ){ zDate++; } - p->tz = 0; - c = *zDate; - if( c=='-' ){ - sgn = -1; - }else if( c=='+' ){ - sgn = +1; - }else if( c=='Z' || c=='z' ){ - zDate++; - p->isLocal = 0; - p->isUtc = 1; - goto zulu_time; - }else{ - return c!=0; - } - zDate++; - if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){ - return 1; - } - zDate += 5; - p->tz = sgn*(nMn + nHr*60); -zulu_time: - while( sqlite3Isspace(*zDate) ){ zDate++; } - return *zDate!=0; -} - -/* -** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. -** The HH, MM, and SS must each be exactly 2 digits. The -** fractional seconds FFFF can be one or more digits. -** -** Return 1 if there is a parsing error and 0 on success. -*/ -static int parseHhMmSs(const char *zDate, DateTime *p){ - int h, m, s; - double ms = 0.0; - if( getDigits(zDate, "20c:20e", &h, &m)!=2 ){ - return 1; - } - zDate += 5; - if( *zDate==':' ){ - zDate++; - if( getDigits(zDate, "20e", &s)!=1 ){ - return 1; - } - zDate += 2; - if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){ - double rScale = 1.0; - zDate++; - while( sqlite3Isdigit(*zDate) ){ - ms = ms*10.0 + *zDate - '0'; - rScale *= 10.0; - zDate++; - } - ms /= rScale; - /* Truncate to avoid problems with sub-milliseconds - ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */ - if( ms>0.999 ) ms = 0.999; - } - }else{ - s = 0; - } - p->validJD = 0; - p->rawS = 0; - p->validHMS = 1; - p->h = h; - p->m = m; - p->s = s + ms; - if( parseTimezone(zDate, p) ) return 1; - return 0; -} - -/* -** Put the DateTime object into its error state. -*/ -static void datetimeError(DateTime *p){ - memset(p, 0, sizeof(*p)); - p->isError = 1; -} - -/* -** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume -** that the YYYY-MM-DD is according to the Gregorian calendar. -** -** Reference: Meeus page 61 -*/ -static void computeJD(DateTime *p){ - int Y, M, D, A, B, X1, X2; - - if( p->validJD ) return; - if( p->validYMD ){ - Y = p->Y; - M = p->M; - D = p->D; - }else{ - Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ - M = 1; - D = 1; - } - if( Y<-4713 || Y>9999 || p->rawS ){ - datetimeError(p); - return; - } - if( M<=2 ){ - Y--; - M += 12; - } - A = (Y+4800)/100; - B = 38 - A + (A/4); - X1 = 36525*(Y+4716)/100; - X2 = 306001*(M+1)/10000; - p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000); - p->validJD = 1; - if( p->validHMS ){ - p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5); - if( p->tz ){ - p->iJD -= p->tz*60000; - p->validYMD = 0; - p->validHMS = 0; - p->tz = 0; - p->isUtc = 1; - p->isLocal = 0; - } - } -} - -/* -** Given the YYYY-MM-DD information current in p, determine if there -** is day-of-month overflow and set nFloor to the number of days that -** would need to be subtracted from the date in order to bring the -** date back to the end of the month. -*/ -static void computeFloor(DateTime *p){ - assert( p->validYMD || p->isError ); - assert( p->D>=0 && p->D<=31 ); - assert( p->M>=0 && p->M<=12 ); - if( p->D<=28 ){ - p->nFloor = 0; - }else if( (1<M) & 0x15aa ){ - p->nFloor = 0; - }else if( p->M!=2 ){ - p->nFloor = (p->D==31); - }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){ - p->nFloor = p->D - 28; - }else{ - p->nFloor = p->D - 29; - } -} - -/* -** Parse dates of the form -** -** YYYY-MM-DD HH:MM:SS.FFF -** YYYY-MM-DD HH:MM:SS -** YYYY-MM-DD HH:MM -** YYYY-MM-DD -** -** Write the result into the DateTime structure and return 0 -** on success and 1 if the input string is not a well-formed -** date. -*/ -static int parseYyyyMmDd(const char *zDate, DateTime *p){ - int Y, M, D, neg; - - if( zDate[0]=='-' ){ - zDate++; - neg = 1; - }else{ - neg = 0; - } - if( getDigits(zDate, "40f-21a-21d", &Y, &M, &D)!=3 ){ - return 1; - } - zDate += 10; - while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; } - if( parseHhMmSs(zDate, p)==0 ){ - /* We got the time */ - }else if( *zDate==0 ){ - p->validHMS = 0; - }else{ - return 1; - } - p->validJD = 0; - p->validYMD = 1; - p->Y = neg ? -Y : Y; - p->M = M; - p->D = D; - computeFloor(p); - if( p->tz ){ - computeJD(p); - } - return 0; -} - - -static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */ - -/* -** Set the time to the current time reported by the VFS. -** -** Return the number of errors. -*/ -static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ - p->iJD = sqlite3StmtCurrentTime(context); - if( p->iJD>0 ){ - p->validJD = 1; - p->isUtc = 1; - p->isLocal = 0; - clearYMD_HMS_TZ(p); - return 0; - }else{ - return 1; - } -} - -/* -** Input "r" is a numeric quantity which might be a julian day number, -** or the number of seconds since 1970. If the value if r is within -** range of a julian day number, install it as such and set validJD. -** If the value is a valid unix timestamp, put it in p->s and set p->rawS. -*/ -static void setRawDateNumber(DateTime *p, double r){ - p->s = r; - p->rawS = 1; - if( r>=0.0 && r<5373484.5 ){ - p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); - p->validJD = 1; - } -} - -/* -** Attempt to parse the given string into a julian day number. Return -** the number of errors. -** -** The following are acceptable forms for the input string: -** -** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM -** DDDD.DD -** now -** -** In the first form, the +/-HH:MM is always optional. The fractional -** seconds extension (the ".FFF") is optional. The seconds portion -** (":SS.FFF") is option. The year and date can be omitted as long -** as there is a time string. The time string can be omitted as long -** as there is a year and date. -*/ -static int parseDateOrTime( - sqlite3_context *context, - const char *zDate, - DateTime *p -){ - double r; - if( parseYyyyMmDd(zDate,p)==0 ){ - return 0; - }else if( parseHhMmSs(zDate, p)==0 ){ - return 0; - }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ - return setDateTimeToCurrent(context, p); - }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ - setRawDateNumber(p, r); - return 0; - }else if( (sqlite3StrICmp(zDate,"subsec")==0 - || sqlite3StrICmp(zDate,"subsecond")==0) - && sqlite3NotPureFunc(context) ){ - p->useSubsec = 1; - return setDateTimeToCurrent(context, p); - } - return 1; -} - -/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999. -** Multiplying this by 86400000 gives 464269060799999 as the maximum value -** for DateTime.iJD. -** -** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with -** such a large integer literal, so we have to encode it. -*/ -#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff) - -/* -** Return TRUE if the given julian day number is within range. -** -** The input is the JulianDay times 86400000. -*/ -static int validJulianDay(sqlite3_int64 iJD){ - return iJD>=0 && iJD<=INT_464269060799999; -} - -/* -** Compute the Year, Month, and Day from the julian day number. -*/ -static void computeYMD(DateTime *p){ - int Z, alpha, A, B, C, D, E, X1; - if( p->validYMD ) return; - if( !p->validJD ){ - p->Y = 2000; - p->M = 1; - p->D = 1; - }else if( !validJulianDay(p->iJD) ){ - datetimeError(p); - return; - }else{ - Z = (int)((p->iJD + 43200000)/86400000); - alpha = (int)((Z + 32044.75)/36524.25) - 52; - A = Z + 1 + alpha - ((alpha+100)/4) + 25; - B = A + 1524; - C = (int)((B - 122.1)/365.25); - D = (36525*(C&32767))/100; - E = (int)((B-D)/30.6001); - X1 = (int)(30.6001*E); - p->D = B - D - X1; - p->M = E<14 ? E-1 : E-13; - p->Y = p->M>2 ? C - 4716 : C - 4715; - } - p->validYMD = 1; -} - -/* -** Compute the Hour, Minute, and Seconds from the julian day number. -*/ -static void computeHMS(DateTime *p){ - int day_ms, day_min; /* milliseconds, minutes into the day */ - if( p->validHMS ) return; - computeJD(p); - day_ms = (int)((p->iJD + 43200000) % 86400000); - p->s = (day_ms % 60000)/1000.0; - day_min = day_ms/60000; - p->m = day_min % 60; - p->h = day_min / 60; - p->rawS = 0; - p->validHMS = 1; -} - -/* -** Compute both YMD and HMS -*/ -static void computeYMD_HMS(DateTime *p){ - computeYMD(p); - computeHMS(p); -} - -/* -** Clear the YMD and HMS and the TZ -*/ -static void clearYMD_HMS_TZ(DateTime *p){ - p->validYMD = 0; - p->validHMS = 0; - p->tz = 0; -} - -#ifndef SQLITE_OMIT_LOCALTIME -/* -** On recent Windows platforms, the localtime_s() function is available -** as part of the "Secure CRT". It is essentially equivalent to -** localtime_r() available under most POSIX platforms, except that the -** order of the parameters is reversed. -** -** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx. -** -** If the user has not indicated to use localtime_r() or localtime_s() -** already, check for an MSVC build environment that provides -** localtime_s(). -*/ -#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \ - && defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) -#undef HAVE_LOCALTIME_S -#define HAVE_LOCALTIME_S 1 -#endif - -/* -** The following routine implements the rough equivalent of localtime_r() -** using whatever operating-system specific localtime facility that -** is available. This routine returns 0 on success and -** non-zero on any kind of error. -** -** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this -** routine will always fail. If bLocaltimeFault is nonzero and -** 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 -** local time. -*/ -static int osLocaltime(time_t *t, struct tm *pTm){ - int rc; -#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S - struct tm *pX; -#if SQLITE_THREADSAFE>0 - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); -#endif - sqlite3_mutex_enter(mutex); - pX = localtime(t); -#ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ){ - if( sqlite3GlobalConfig.xAltLocaltime!=0 - && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm) - ){ - pX = pTm; - }else{ - pX = 0; - } - } -#endif - if( pX ) *pTm = *pX; -#if SQLITE_THREADSAFE>0 - sqlite3_mutex_leave(mutex); -#endif - rc = pX==0; -#else -#ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ){ - if( sqlite3GlobalConfig.xAltLocaltime!=0 ){ - return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm); - }else{ - return 1; - } - } -#endif -#if HAVE_LOCALTIME_R - rc = localtime_r(t, pTm)==0; -#else - rc = localtime_s(pTm, t); -#endif /* HAVE_LOCALTIME_R */ -#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */ - return rc; -} -#endif /* SQLITE_OMIT_LOCALTIME */ - - -#ifndef SQLITE_OMIT_LOCALTIME -/* -** Assuming the input DateTime is UTC, move it to its localtime equivalent. -*/ -static int toLocaltime( - DateTime *p, /* Date at which to calculate offset */ - sqlite3_context *pCtx /* Write error here if one occurs */ -){ - time_t t; - struct tm sLocal; - int iYearDiff; - - /* Initialize the contents of sLocal to avoid a compiler warning. */ - memset(&sLocal, 0, sizeof(sLocal)); - - 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. - */ - 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); - } - if( osLocaltime(&t, &sLocal) ){ - sqlite3_result_error(pCtx, "local time unavailable", -1); - return SQLITE_ERROR; - } - 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->tz = 0; - p->isError = 0; - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_LOCALTIME */ - -/* -** The following table defines various date transformations of the form -** -** 'NNN days' -** -** Where NNN is an arbitrary floating-point number and "days" can be one -** of several units of time. -*/ -static const struct { - 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", 4.6427e+14, 1.0 }, - /* 1 */ { 6, "minute", 7.7379e+12, 60.0 }, - /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 }, - /* 3 */ { 3, "day", 5373485.0, 86400.0 }, - /* 4 */ { 5, "month", 176546.0, 2592000.0 }, - /* 5 */ { 4, "year", 14713.0, 31536000.0 }, -}; - -/* -** If the DateTime p is raw number, try to figure out if it is -** a julian day number of a unix timestamp. Set the p value -** appropriately. -*/ -static void autoAdjustDate(DateTime *p){ - if( !p->rawS || p->validJD ){ - 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 */ - ){ - double r = p->s*1000.0 + 210866760000000.0; - clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)(r + 0.5); - p->validJD = 1; - p->rawS = 0; - } -} - -/* -** Process a modifier to a date-time stamp. The modifiers are -** as follows: -** -** NNN days -** NNN hours -** NNN minutes -** NNN.NNNN seconds -** NNN months -** NNN years -** +/-YYYY-MM-DD HH:MM:SS.SSS -** ceiling -** floor -** start of month -** start of year -** start of week -** start of day -** weekday N -** unixepoch -** auto -** localtime -** utc -** subsec -** subsecond -** -** Return 0 on success and 1 if there is any kind of error. If the error -** is in a system call (i.e. localtime()), then an error message is written -** to context pCtx. If the error is an unrecognized modifier, no error is -** written to pCtx. -*/ -static int parseModifier( - 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 */ - int idx /* Parameter index of the modifier */ -){ - int rc = 1; - double r; - switch(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( sqlite3_stricmp(z, "auto")==0 ){ - if( idx>1 ) return 1; /* IMP: R-33611-57934 */ - autoAdjustDate(p); - rc = 0; - } - break; - } - case 'c': { - /* - ** ceiling - ** - ** Resolve day-of-month overflow by rolling forward into the next - ** month. As this is the default action, this modifier is really - ** a no-op that is only included for symmetry. See "floor". - */ - if( sqlite3_stricmp(z, "ceiling")==0 ){ - computeJD(p); - clearYMD_HMS_TZ(p); - rc = 0; - p->nFloor = 0; - } - break; - } - case 'f': { - /* - ** floor - ** - ** Resolve day-of-month overflow by rolling back to the end of the - ** previous month. - */ - if( sqlite3_stricmp(z, "floor")==0 ){ - computeJD(p); - p->iJD -= p->nFloor*86400000; - clearYMD_HMS_TZ(p); - 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( 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 - ** - ** Assuming the current time value is UTC (a.k.a. GMT), shift it to - ** show local time. - */ - if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ - rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx); - p->isUtc = 0; - p->isLocal = 1; - } - break; - } -#endif - case 'u': { - /* - ** unixepoch - ** - ** Treat the current value of p->s as the number of - ** seconds since 1970. Convert to a real julian day number. - */ - if( 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); - p->iJD = (sqlite3_int64)(r + 0.5); - p->validJD = 1; - p->rawS = 0; - rc = 0; - } - } -#ifndef SQLITE_OMIT_LOCALTIME - else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ - if( p->isUtc==0 ){ - i64 iOrigJD; /* Original localtime */ - i64 iGuess; /* Guess at the corresponding utc time */ - int cnt = 0; /* Safety to prevent infinite loop */ - i64 iErr; /* Guess is off by this much */ - - computeJD(p); - 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->isUtc = 1; - p->isLocal = 0; - } - rc = SQLITE_OK; - } -#endif - break; - } - case 'w': { - /* - ** weekday N - ** - ** Move the date to the same time on the next occurrence of - ** weekday N where 0==Sunday, 1==Monday, and so forth. If the - ** date is already on the appropriate weekday, this is a no-op. - */ - if( sqlite3_strnicmp(z, "weekday ", 8)==0 - && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 - && r>=0.0 && r<7.0 && (n=(int)r)==r ){ - sqlite3_int64 Z; - computeYMD_HMS(p); - p->tz = 0; - p->validJD = 0; - computeJD(p); - Z = ((p->iJD + 129600000)/86400000) % 7; - if( Z>n ) Z -= 7; - p->iJD += (n - Z)*86400000; - clearYMD_HMS_TZ(p); - rc = 0; - } - break; - } - case 's': { - /* - ** start of TTTTT - ** - ** Move the date backwards to the beginning of the current day, - ** or month or year. - ** - ** subsecond - ** subsec - ** - ** Show subsecond precision in the output of datetime() and - ** unixepoch() and strftime('%s'). - */ - if( sqlite3_strnicmp(z, "start of ", 9)!=0 ){ - if( sqlite3_stricmp(z, "subsec")==0 - || sqlite3_stricmp(z, "subsecond")==0 - ){ - p->useSubsec = 1; - rc = 0; - } - break; - } - if( !p->validJD && !p->validYMD && !p->validHMS ) break; - z += 9; - computeYMD(p); - p->validHMS = 1; - p->h = p->m = 0; - p->s = 0.0; - p->rawS = 0; - p->tz = 0; - p->validJD = 0; - if( sqlite3_stricmp(z,"month")==0 ){ - p->D = 1; - rc = 0; - }else if( sqlite3_stricmp(z,"year")==0 ){ - p->M = 1; - p->D = 1; - rc = 0; - }else if( sqlite3_stricmp(z,"day")==0 ){ - rc = 0; - } - break; - } - case '+': - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - double rRounder; - int i; - int Y,M,D,h,m,x; - const char *z2 = z; - char z0 = z[0]; - for(n=1; z[n]; n++){ - if( z[n]==':' ) break; - if( sqlite3Isspace(z[n]) ) break; - if( z[n]=='-' ){ - if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break; - if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break; - } - } - if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ - assert( rc==1 ); - break; - } - if( z[n]=='-' ){ - /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the - ** specified number of years, months, and days. MM is limited to - ** the range 0-11 and DD is limited to 0-30. - */ - if( z0!='+' && z0!='-' ) break; /* Must start with +/- */ - if( n==5 ){ - if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break; - }else{ - assert( n==6 ); - if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break; - z++; - } - if( M>=12 ) break; /* M range 0..11 */ - if( D>=31 ) break; /* D range 0..30 */ - computeYMD_HMS(p); - p->validJD = 0; - if( z0=='-' ){ - p->Y -= Y; - p->M -= M; - D = -D; - }else{ - p->Y += Y; - p->M += M; - } - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - computeFloor(p); - computeJD(p); - p->validHMS = 0; - p->validYMD = 0; - p->iJD += (i64)D*86400000; - if( z[11]==0 ){ - rc = 0; - break; - } - if( sqlite3Isspace(z[11]) - && getDigits(&z[12], "20c:20e", &h, &m)==2 - ){ - z2 = &z[12]; - n = 2; - }else{ - break; - } - } - if( z2[n]==':' ){ - /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the - ** specified number of hours, minutes, seconds, and fractional seconds - ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be - ** omitted. - */ - - DateTime tx; - sqlite3_int64 day; - if( !sqlite3Isdigit(*z2) ) z2++; - memset(&tx, 0, sizeof(tx)); - if( parseHhMmSs(z2, &tx) ) break; - computeJD(&tx); - tx.iJD -= 43200000; - day = tx.iJD/86400000; - tx.iJD -= day*86400000; - if( z0=='-' ) tx.iJD = -tx.iJD; - computeJD(p); - clearYMD_HMS_TZ(p); - p->iJD += tx.iJD; - rc = 0; - break; - } - - /* If control reaches this point, it means the transformation is - ** one of the forms like "+NNN days". */ - z += n; - while( sqlite3Isspace(*z) ) z++; - n = sqlite3Strlen30(z); - if( n<3 || n>10 ) break; - if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; - computeJD(p); - assert( rc==1 ); - rRounder = r<0 ? -0.5 : +0.5; - p->nFloor = 0; - for(i=0; i-aXformType[i].rLimit && rM += (int)r; - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - computeFloor(p); - p->validJD = 0; - r -= (int)r; - break; - } - case 5: { /* Special processing to add years */ - int y = (int)r; - assert( strcmp(aXformType[5].zName,"year")==0 ); - computeYMD_HMS(p); - assert( p->M>=0 && p->M<=12 ); - p->Y += y; - computeFloor(p); - p->validJD = 0; - r -= (int)r; - break; - } - } - computeJD(p); - p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder); - rc = 0; - break; - } - } - clearYMD_HMS_TZ(p); - break; - } - default: { - break; - } - } - return rc; -} - -/* -** Process time function arguments. argv[0] is a date-time stamp. -** argv[1] and following are modifiers. Parse them all and write -** the resulting time into the DateTime structure p. Return 0 -** on success and 1 if there are any errors. -** -** If there are zero parameters (if even argv[0] is undefined) -** then assume a default value of "now" for argv[0]. -*/ -static int isDate( - sqlite3_context *context, - int argc, - sqlite3_value **argv, - DateTime *p -){ - int i, n; - const unsigned char *z; - int eType; - memset(p, 0, sizeof(*p)); - if( argc==0 ){ - if( !sqlite3NotPureFunc(context) ) return 1; - return setDateTimeToCurrent(context, p); - } - if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT - || eType==SQLITE_INTEGER ){ - setRawDateNumber(p, sqlite3_value_double(argv[0])); - }else{ - z = sqlite3_value_text(argv[0]); - if( !z || parseDateOrTime(context, (char*)z, p) ){ - return 1; - } - } - for(i=1; iisError || !validJulianDay(p->iJD) ) return 1; - if( argc==1 && p->validYMD && p->D>28 ){ - /* Make sure a YYYY-MM-DD is normalized. - ** Example: 2023-02-31 -> 2023-03-03 */ - assert( p->validJD ); - p->validYMD = 0; - } - return 0; -} - - -/* -** The following routines implement the various date and time functions -** of SQLite. -*/ - -/* -** julianday( TIMESTRING, MOD, MOD, ...) -** -** Return the julian day number of the date specified in the arguments -*/ -static void juliandayFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - computeJD(&x); - sqlite3_result_double(context, x.iJD/86400000.0); - } -} - -/* -** 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( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - computeJD(&x); - if( x.useSubsec ){ - sqlite3_result_double(context, (x.iJD - 21086676*(i64)10000000)/1000.0); - }else{ - sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); - } - } -} - -/* -** datetime( TIMESTRING, MOD, MOD, ...) -** -** Return YYYY-MM-DD HH:MM:SS -*/ -static void datetimeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - int Y, s, n; - char zBuf[32]; - computeYMD_HMS(&x); - 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] = ':'; - if( x.useSubsec ){ - s = (int)(1000.0*x.s + 0.5); - zBuf[18] = '0' + (s/10000)%10; - zBuf[19] = '0' + (s/1000)%10; - zBuf[20] = '.'; - zBuf[21] = '0' + (s/100)%10; - zBuf[22] = '0' + (s/10)%10; - zBuf[23] = '0' + (s)%10; - zBuf[24] = 0; - n = 24; - }else{ - s = (int)x.s; - zBuf[18] = '0' + (s/10)%10; - zBuf[19] = '0' + (s)%10; - zBuf[20] = 0; - n = 20; - } - if( x.Y<0 ){ - zBuf[0] = '-'; - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT); - } - } -} - -/* -** time( TIMESTRING, MOD, MOD, ...) -** -** Return HH:MM:SS -*/ -static void timeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - int s, n; - char zBuf[16]; - computeHMS(&x); - 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] = ':'; - if( x.useSubsec ){ - s = (int)(1000.0*x.s + 0.5); - zBuf[6] = '0' + (s/10000)%10; - zBuf[7] = '0' + (s/1000)%10; - zBuf[8] = '.'; - zBuf[9] = '0' + (s/100)%10; - zBuf[10] = '0' + (s/10)%10; - zBuf[11] = '0' + (s)%10; - zBuf[12] = 0; - n = 12; - }else{ - s = (int)x.s; - zBuf[6] = '0' + (s/10)%10; - zBuf[7] = '0' + (s)%10; - zBuf[8] = 0; - n = 8; - } - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); - } -} - -/* -** date( TIMESTRING, MOD, MOD, ...) -** -** Return YYYY-MM-DD -*/ -static void dateFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - int Y; - char zBuf[16]; - computeYMD(&x); - 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] = '-'; - sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT); - } - } -} - -/* -** Compute the number of days after the most recent January 1. -** -** In other words, compute the zero-based day number for the -** current year: -** -** Jan01 = 0, Jan02 = 1, ..., Jan31 = 30, Feb01 = 31, ... -** Dec31 = 364 or 365. -*/ -static int daysAfterJan01(DateTime *pDate){ - DateTime jan01 = *pDate; - assert( jan01.validYMD ); - assert( jan01.validHMS ); - assert( pDate->validJD ); - jan01.validJD = 0; - jan01.M = 1; - jan01.D = 1; - computeJD(&jan01); - return (int)((pDate->iJD-jan01.iJD+43200000)/86400000); -} - -/* -** Return the number of days after the most recent Monday. -** -** In other words, return the day of the week according -** to this code: -** -** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday. -*/ -static int daysAfterMonday(DateTime *pDate){ - assert( pDate->validJD ); - return (int)((pDate->iJD+43200000)/86400000) % 7; -} - -/* -** Return the number of days after the most recent Sunday. -** -** In other words, return the day of the week according -** to this code: -** -** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday -*/ -static int daysAfterSunday(DateTime *pDate){ - assert( pDate->validJD ); - return (int)((pDate->iJD+129600000)/86400000) % 7; -} - -/* -** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) -** -** Return a string described by FORMAT. Conversions as follows: -** -** %d day of month 01-31 -** %e day of month 1-31 -** %f ** fractional seconds SS.SSS -** %F ISO date. YYYY-MM-DD -** %G ISO year corresponding to %V 0000-9999. -** %g 2-digit ISO year corresponding to %V 00-99 -** %H hour 00-24 -** %k hour 0-24 (leading zero converted to space) -** %I hour 01-12 -** %j day of year 001-366 -** %J ** julian day number -** %l hour 1-12 (leading zero converted to space) -** %m month 01-12 -** %M minute 00-59 -** %p "am" or "pm" -** %P "AM" or "PM" -** %R time as HH:MM -** %s seconds since 1970-01-01 -** %S seconds 00-59 -** %T time as HH:MM:SS -** %u day of week 1-7 Monday==1, Sunday==7 -** %w day of week 0-6 Sunday==0, Monday==1 -** %U week of year 00-53 (First Sunday is start of week 01) -** %V week of year 01-53 (First week containing Thursday is week 01) -** %W week of year 00-53 (First Monday is start of week 01) -** %Y year 0000-9999 -** %% % -*/ -static void strftimeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - size_t i,j; - sqlite3 *db; - const char *zFmt; - sqlite3_str sRes; - - - if( argc==0 ) return; - zFmt = (const char*)sqlite3_value_text(argv[0]); - if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; - db = sqlite3_context_db_handle(context); - sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - - computeJD(&x); - computeYMD_HMS(&x); - for(i=j=0; zFmt[i]; i++){ - char cf; - if( zFmt[i]!='%' ) continue; - if( j59.999) ) s = 59.999; - sqlite3_str_appendf(&sRes, "%06.3f", s); - break; - } - case 'F': { - sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D); - break; - } - case 'G': /* Fall thru */ - case 'g': { - DateTime y = x; - assert( y.validJD ); - /* Move y so that it is the Thursday in the same week as x */ - y.iJD += (3 - daysAfterMonday(&x))*86400000; - y.validYMD = 0; - computeYMD(&y); - if( cf=='g' ){ - sqlite3_str_appendf(&sRes, "%02d", y.Y%100); - }else{ - sqlite3_str_appendf(&sRes, "%04d", y.Y); - } - break; - } - case 'H': - case 'k': { - sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h); - break; - } - case 'I': /* Fall thru */ - case 'l': { - int h = x.h; - if( h>12 ) h -= 12; - if( h==0 ) h = 12; - sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); - break; - } - case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */ - sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1); - break; - } - case 'J': { /* Julian day number. (Non-standard) */ - sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0); - break; - } - case 'm': { - sqlite3_str_appendf(&sRes,"%02d",x.M); - break; - } - case 'M': { - sqlite3_str_appendf(&sRes,"%02d",x.m); - break; - } - case 'p': /* Fall thru */ - case 'P': { - if( x.h>=12 ){ - sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2); - }else{ - sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2); - } - break; - } - case 'R': { - sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m); - break; - } - case 's': { - if( x.useSubsec ){ - sqlite3_str_appendf(&sRes,"%.3f", - (x.iJD - 21086676*(i64)10000000)/1000.0); - }else{ - i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000); - sqlite3_str_appendf(&sRes,"%lld",iS); - } - break; - } - case 'S': { - sqlite3_str_appendf(&sRes,"%02d",(int)x.s); - break; - } - case 'T': { - sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); - break; - } - case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */ - case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */ - char c = (char)daysAfterSunday(&x) + '0'; - if( c=='0' && cf=='u' ) c = '7'; - sqlite3_str_appendchar(&sRes, 1, c); - break; - } - case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */ - sqlite3_str_appendf(&sRes,"%02d", - (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7); - break; - } - case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */ - DateTime y = x; - /* Adjust y so that is the Thursday in the same week as x */ - assert( y.validJD ); - y.iJD += (3 - daysAfterMonday(&x))*86400000; - y.validYMD = 0; - computeYMD(&y); - sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1); - break; - } - case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */ - sqlite3_str_appendf(&sRes,"%02d", - (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7); - break; - } - case 'Y': { - sqlite3_str_appendf(&sRes,"%04d",x.Y); - break; - } - case '%': { - sqlite3_str_appendchar(&sRes, 1, '%'); - break; - } - default: { - sqlite3_str_reset(&sRes); - return; - } - } - } - if( j=d2.iJD ){ - sign = '+'; - Y = d1.Y - d2.Y; - if( Y ){ - d2.Y = d1.Y; - d2.validJD = 0; - computeJD(&d2); - } - M = d1.M - d2.M; - if( M<0 ){ - Y--; - M += 12; - } - if( M!=0 ){ - d2.M = d1.M; - d2.validJD = 0; - computeJD(&d2); - } - while( d1.iJDd2.iJD ){ - M--; - if( M<0 ){ - M = 11; - Y--; - } - d2.M++; - if( d2.M>12 ){ - d2.M = 1; - d2.Y++; - } - d2.validJD = 0; - computeJD(&d2); - } - d1.iJD = d2.iJD - d1.iJD; - d1.iJD += (u64)1486995408 * (u64)100000; - } - clearYMD_HMS_TZ(&d1); - computeYMD_HMS(&d1); - sqlite3StrAccumInit(&sRes, 0, 0, 0, 100); - sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f", - sign, Y, M, d1.D-1, d1.h, d1.m, d1.s); - sqlite3ResultStrAccum(context, &sRes); -} - - -/* -** current_timestamp() -** -** This function returns the same value as datetime('now'). -*/ -static void ctimestampFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **NotUsed2 -){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - datetimeFunc(context, 0, 0); -} -#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ - -#ifdef SQLITE_OMIT_DATETIME_FUNCS -/* -** If the library is compiled to omit the full-scale date and time -** handling (to get a smaller binary), the following minimal version -** of the functions current_time(), current_date() and current_timestamp() -** are included instead. This is to support column declarations that -** include "DEFAULT CURRENT_TIME" etc. -** -** This function uses the C-library functions time(), gmtime() -** and strftime(). The format string to pass to strftime() is supplied -** as the user-data for the function. -*/ -static void currentTimeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - time_t t; - char *zFormat = (char *)sqlite3_user_data(context); - sqlite3_int64 iT; - struct tm *pTm; - struct tm sNow; - char zBuf[20]; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - iT = sqlite3StmtCurrentTime(context); - if( iT<=0 ) return; - t = iT/1000 - 10000*(sqlite3_int64)21086676; -#if HAVE_GMTIME_R - pTm = gmtime_r(&t, &sNow); -#else - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); - pTm = gmtime(&t); - if( pTm ) memcpy(&sNow, pTm, sizeof(sNow)); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); -#endif - if( pTm ){ - strftime(zBuf, 20, zFormat, &sNow); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); - } -} -#endif - -#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG) -/* -** datedebug(...) -** -** This routine returns JSON that describes the internal DateTime object. -** Used for debugging and testing only. Subject to change. -*/ -static void datedebugFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - char *zJson; - zJson = sqlite3_mprintf( - "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d," - "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d," - "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d," - "isUtc:%d,isLocal:%d}", - x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz, - x.s, x.validJD, x.validYMD, x.validHMS, - x.nFloor, x.rawS, x.isError, x.useSubsec, - x.isUtc, x.isLocal); - sqlite3_result_text(context, zJson, -1, sqlite3_free); - } -} -#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */ - - -/* -** This function registered all of the above C functions as SQL -** functions. This should be the only routine in this file with -** external linkage. -*/ -SQLITE_PRIVATE void 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 ), - PURE_DATE(strftime, -1, 0, 0, strftimeFunc ), - PURE_DATE(timediff, 2, 0, 0, timediffFunc ), -#ifdef SQLITE_DEBUG - PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ), -#endif - DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), - DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), - DFUNCTION(current_date, 0, 0, 0, cdateFunc ), -#else - STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), - STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), - STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), -#endif - }; - sqlite3InsertBuiltinFuncs(aDateTimeFuncs, ArraySize(aDateTimeFuncs)); -} - -/************** End of date.c ************************************************/ -/************** Begin file os.c **********************************************/ -/* -** 2005 November 29 -** -** 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 OS interface code that is common to all -** architectures. -*/ -/* #include "sqliteInt.h" */ - -/* -** 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 int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ -SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ -SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ -SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ -SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ -SQLITE_API int sqlite3_diskfull_pending = 0; -SQLITE_API int sqlite3_diskfull = 0; -#endif /* defined(SQLITE_TEST) */ - -/* -** When testing, also keep a count of the number of open files. -*/ -#if defined(SQLITE_TEST) -SQLITE_API int sqlite3_open_file_count = 0; -#endif /* defined(SQLITE_TEST) */ - -/* -** The default SQLite sqlite3_vfs implementations do not allocate -** memory (actually, os_unix.c allocates a small amount of memory -** from within OsOpen()), but some third-party implementations may. -** So we test the effects of a malloc() failing and the sqlite3OsXXX() -** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. -** -** The following functions are instrumented for malloc() failure -** testing: -** -** sqlite3OsRead() -** sqlite3OsWrite() -** sqlite3OsSync() -** sqlite3OsFileSize() -** sqlite3OsLock() -** sqlite3OsCheckReservedLock() -** sqlite3OsFileControl() -** sqlite3OsShmMap() -** sqlite3OsOpen() -** sqlite3OsDelete() -** sqlite3OsAccess() -** sqlite3OsFullPathname() -** -*/ -#if defined(SQLITE_TEST) -SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1; - #define DO_OS_MALLOC_TEST(x) \ - if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \ - void *pTstAlloc = sqlite3Malloc(10); \ - if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \ - sqlite3_free(pTstAlloc); \ - } -#else - #define DO_OS_MALLOC_TEST(x) -#endif - -/* -** The following routines are convenience wrappers around methods -** of the sqlite3_file object. This is mostly just syntactic sugar. All -** of this would be completely automatic if SQLite were coded using -** C++ instead of plain old C. -*/ -SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file *pId){ - if( pId->pMethods ){ - pId->pMethods->xClose(pId); - pId->pMethods = 0; - } -} -SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xRead(id, pBuf, amt, offset); -} -SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xWrite(id, pBuf, amt, offset); -} -SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){ - return id->pMethods->xTruncate(id, size); -} -SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ - DO_OS_MALLOC_TEST(id); - return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xFileSize(id, pSize); -} -SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){ - DO_OS_MALLOC_TEST(id); - assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE ); - return id->pMethods->xLock(id, lockType); -} -SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){ - assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED ); - return id->pMethods->xUnlock(id, lockType); -} -SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xCheckReservedLock(id, pResOut); -} - -/* -** Use sqlite3OsFileControl() when we are doing something that might fail -** and we need to know about the failures. Use sqlite3OsFileControlHint() -** when simply tossing information over the wall to the VFS and we do not -** really care if the VFS receives and understands the information since it -** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() -** routine has no return value since the return value would be meaningless. -*/ -SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ - if( id->pMethods==0 ) return SQLITE_NOTFOUND; -#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 - ** transaction has been committed. Injecting a fault at this point - ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM - ** but the transaction is committed anyway. - ** - ** The core must call OsFileControl() though, not OsFileControlHint(), - ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably - ** means the commit really has failed and an error should be returned - ** to the user. - ** - ** 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 - return id->pMethods->xFileControl(id, op, pArg); -} -SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ - if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); -} - -SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ - int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; - return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); -} -SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ - if( NEVER(id->pMethods==0) ) return 0; - return id->pMethods->xDeviceCharacteristics(id); -} -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){ - return id->pMethods->xShmLock(id, offset, n, flags); -} -SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){ - id->pMethods->xShmBarrier(id); -} -SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){ - return id->pMethods->xShmUnmap(id, deleteFlag); -} -SQLITE_PRIVATE int sqlite3OsShmMap( - sqlite3_file *id, /* Database file handle */ - int iPage, - int pgsz, - int bExtend, /* True to extend file if necessary */ - void volatile **pp /* OUT: Pointer to mapping */ -){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); -} -#endif /* SQLITE_OMIT_WAL */ - -#if SQLITE_MAX_MMAP_SIZE>0 -/* The real implementation of xFetch and xUnfetch */ -SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ - DO_OS_MALLOC_TEST(id); - return id->pMethods->xFetch(id, iOff, iAmt, pp); -} -SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ - return id->pMethods->xUnfetch(id, iOff, p); -} -#else -/* No-op stubs to use when memory-mapped I/O is disabled */ -SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ - *pp = 0; - return SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ - return SQLITE_OK; -} -#endif - -/* -** The next group of routines are convenience wrappers around the -** VFS methods. -*/ -SQLITE_PRIVATE int sqlite3OsOpen( - sqlite3_vfs *pVfs, - const char *zPath, - sqlite3_file *pFile, - int flags, - int *pFlagsOut -){ - int rc; - DO_OS_MALLOC_TEST(0); - /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed - ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, - ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before - ** reaching the VFS. */ - assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) ); - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut); - assert( rc==SQLITE_OK || pFile->pMethods==0 ); - return rc; -} -SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - DO_OS_MALLOC_TEST(0); - assert( dirSync==0 || dirSync==1 ); - return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3OsAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - DO_OS_MALLOC_TEST(0); - return pVfs->xAccess(pVfs, zPath, flags, pResOut); -} -SQLITE_PRIVATE int sqlite3OsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nPathOut, - char *zPathOut -){ - DO_OS_MALLOC_TEST(0); - zPathOut[0] = 0; - return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); -} -#ifndef SQLITE_OMIT_LOAD_EXTENSION -SQLITE_PRIVATE void *sqlite3OsDlOpen(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 sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - pVfs->xDlError(pVfs, nByte, zBufOut); -} -SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ - return pVfs->xDlSym(pVfs, pHdle, zSym); -} -SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ - pVfs->xDlClose(pVfs, pHandle); -} -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ -SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - if( sqlite3Config.iPrngSeed ){ - memset(zBufOut, 0, nByte); - if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int); - memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte); - return SQLITE_OK; - }else{ - return pVfs->xRandomness(pVfs, nByte, zBufOut); - } - -} -SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ - return pVfs->xSleep(pVfs, nMicro); -} -SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs *pVfs){ - return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0; -} -SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ - int rc; - /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() - ** method to get the current date and time if that method is available - ** (if iVersion is 2 or greater and the function pointer is not NULL) and - ** will fall back to xCurrentTime() if xCurrentTimeInt64() is - ** unavailable. - */ - if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ - rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); - }else{ - double r; - rc = pVfs->xCurrentTime(pVfs, &r); - *pTimeOut = (sqlite3_int64)(r*86400000.0); - } - return rc; -} - -SQLITE_PRIVATE int sqlite3OsOpenMalloc( - sqlite3_vfs *pVfs, - const char *zFile, - sqlite3_file **ppFile, - int flags, - int *pOutFlags -){ - int rc; - sqlite3_file *pFile; - pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); - if( pFile ){ - rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); - if( rc!=SQLITE_OK ){ - 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 sqlite3OsCloseFree(sqlite3_file *pFile){ - assert( pFile ); - sqlite3OsClose(pFile); - sqlite3_free(pFile); -} - -/* -** This function is a wrapper around the OS specific implementation of -** sqlite3_os_init(). The purpose of the wrapper is to provide the -** ability to simulate a malloc failure, so that the handling of an -** error in sqlite3_os_init() by the upper layers can be tested. -*/ -SQLITE_PRIVATE int sqlite3OsInit(void){ - void *p = sqlite3_malloc(10); - if( p==0 ) return SQLITE_NOMEM_BKPT; - sqlite3_free(p); - return sqlite3_os_init(); -} - -/* -** The list of all registered VFS implementations. -*/ -static sqlite3_vfs * SQLITE_WSD vfsList = 0; -#define vfsList GLOBAL(sqlite3_vfs *, vfsList) - -/* -** Locate a VFS by name. If no name is given, simply return the -** first VFS on the list. -*/ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ - sqlite3_vfs *pVfs = 0; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex; -#endif -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return 0; -#endif -#if SQLITE_THREADSAFE - mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); -#endif - sqlite3_mutex_enter(mutex); - for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ - if( zVfs==0 ) break; - if( strcmp(zVfs, pVfs->zName)==0 ) break; - } - sqlite3_mutex_leave(mutex); - return pVfs; -} - -/* -** Unlink a VFS from the linked list -*/ -static void vfsUnlink(sqlite3_vfs *pVfs){ - assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) ); - if( pVfs==0 ){ - /* No-op */ - }else if( vfsList==pVfs ){ - vfsList = pVfs->pNext; - }else if( vfsList ){ - sqlite3_vfs *p = vfsList; - while( p->pNext && p->pNext!=pVfs ){ - p = p->pNext; - } - if( p->pNext==pVfs ){ - p->pNext = pVfs->pNext; - } - } -} - -/* -** Register a VFS with the system. It is harmless to register the same -** VFS multiple times. The new VFS becomes the default if makeDflt is -** true. -*/ -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ - MUTEX_LOGIC(sqlite3_mutex *mutex;) -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return rc; -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - if( pVfs==0 ) return SQLITE_MISUSE_BKPT; -#endif - - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(mutex); - vfsUnlink(pVfs); - if( makeDflt || vfsList==0 ){ - pVfs->pNext = vfsList; - vfsList = pVfs; - }else{ - pVfs->pNext = vfsList->pNext; - vfsList->pNext = pVfs; - } - assert(vfsList); - sqlite3_mutex_leave(mutex); - return SQLITE_OK; -} - -/* -** Unregister a VFS so that it is no longer accessible. -*/ -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ - MUTEX_LOGIC(sqlite3_mutex *mutex;) -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(mutex); - vfsUnlink(pVfs); - sqlite3_mutex_leave(mutex); - return SQLITE_OK; -} - -/************** End of os.c **************************************************/ -/************** Begin file fault.c *******************************************/ -/* -** 2008 Jan 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 code to support the concept of "benign" -** malloc failures (when the xMalloc() or xRealloc() method of the -** sqlite3_mem_methods structure fails to allocate a block of memory -** and returns 0). -** -** Most malloc failures are non-benign. After they occur, SQLite -** abandons the current operation and returns an error code (usually -** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily -** fatal. For example, if a malloc fails while resizing a hash table, this -** is completely recoverable simply by not carrying out the resize. The -** hash table will continue to function normally. So a malloc failure -** during a hash table resize is a benign fault. -*/ - -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_UNTESTABLE - -/* -** Global variables. -*/ -typedef struct BenignMallocHooks BenignMallocHooks; -static SQLITE_WSD struct BenignMallocHooks { - void (*xBenignBegin)(void); - void (*xBenignEnd)(void); -} sqlite3Hooks = { 0, 0 }; - -/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks -** structure. If writable static data is unsupported on the target, -** we have to locate the state vector at run-time. In the more common -** case where writable static data is supported, wsdHooks can refer directly -** to the "sqlite3Hooks" state vector declared above. -*/ -#ifdef SQLITE_OMIT_WSD -# define wsdHooksInit \ - BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks) -# define wsdHooks x[0] -#else -# define wsdHooksInit -# define wsdHooks sqlite3Hooks -#endif - - -/* -** Register hooks to call when sqlite3BeginBenignMalloc() and -** sqlite3EndBenignMalloc() are called, respectively. -*/ -SQLITE_PRIVATE void sqlite3BenignMallocHooks( - void (*xBenignBegin)(void), - void (*xBenignEnd)(void) -){ - wsdHooksInit; - wsdHooks.xBenignBegin = xBenignBegin; - wsdHooks.xBenignEnd = xBenignEnd; -} - -/* -** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that -** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc() -** indicates that subsequent malloc failures are non-benign. -*/ -SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){ - wsdHooksInit; - if( wsdHooks.xBenignBegin ){ - wsdHooks.xBenignBegin(); - } -} -SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ - wsdHooksInit; - if( wsdHooks.xBenignEnd ){ - wsdHooks.xBenignEnd(); - } -} - -#endif /* #ifndef SQLITE_UNTESTABLE */ - -/************** End of fault.c ***********************************************/ -/************** Begin file mem0.c ********************************************/ -/* -** 2008 October 28 -** -** 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 a no-op memory allocation drivers for use when -** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented -** here always fail. SQLite will not operate with these drivers. These -** are merely placeholders. Real drivers must be substituted using -** sqlite3_config() before SQLite will operate. -*/ -/* #include "sqliteInt.h" */ - -/* -** This version of the memory allocator is the default. It is -** used when no other memory allocator is specified using compile-time -** macros. -*/ -#ifdef SQLITE_ZERO_MALLOC - -/* -** No-op versions of all memory allocation routines -*/ -static void *sqlite3MemMalloc(int nByte){ return 0; } -static void sqlite3MemFree(void *pPrior){ return; } -static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; } -static int sqlite3MemSize(void *pPrior){ return 0; } -static int sqlite3MemRoundup(int n){ return n; } -static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; } -static void sqlite3MemShutdown(void *NotUsed){ return; } - -/* -** This routine is the only routine in this file with external linkage. -** -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -SQLITE_PRIVATE void sqlite3MemSetDefault(void){ - static const sqlite3_mem_methods defaultMethods = { - sqlite3MemMalloc, - sqlite3MemFree, - sqlite3MemRealloc, - sqlite3MemSize, - sqlite3MemRoundup, - sqlite3MemInit, - sqlite3MemShutdown, - 0 - }; - sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); -} - -#endif /* SQLITE_ZERO_MALLOC */ - -/************** End of mem0.c ************************************************/ -/************** Begin file mem1.c ********************************************/ -/* -** 2007 August 14 -** -** 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 low-level memory allocation drivers for when -** SQLite will use the standard C-library malloc/realloc/free interface -** to obtain the memory it needs. -** -** This file contains implementations of the low-level memory allocation -** routines specified in the sqlite3_mem_methods object. The content of -** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The -** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the -** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The -** default configuration is to use memory allocation routines in this -** file. -** -** C-preprocessor macro summary: -** -** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if -** the malloc_usable_size() interface exists -** on the target platform. Or, this symbol -** can be set manually, if desired. -** If an equivalent interface exists by -** a different name, using a separate -D -** option to rename it. -** -** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone -** memory allocator. Set this symbol to enable -** building on older macs. -** -** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of -** _msize() on windows systems. This might -** be necessary when compiling for Delphi, -** for example. -*/ -/* #include "sqliteInt.h" */ - -/* -** This version of the memory allocator is the default. It is -** used when no other memory allocator is specified using compile-time -** macros. -*/ -#ifdef SQLITE_SYSTEM_MALLOC -#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) - -/* -** Use the zone allocator available on apple products unless the -** SQLITE_WITHOUT_ZONEMALLOC symbol is defined. -*/ -#include -#include -#ifdef SQLITE_MIGHT_BE_SINGLE_CORE -#include -#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */ -static malloc_zone_t* _sqliteZone_; -#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x)) -#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x)); -#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y)) -#define SQLITE_MALLOCSIZE(x) \ - (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x)) - -#else /* if not __APPLE__ */ - -/* -** Use standard C library malloc and free on non-Apple systems. -** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined. -*/ -#define SQLITE_MALLOC(x) malloc(x) -#define SQLITE_FREE(x) free(x) -#define SQLITE_REALLOC(x,y) realloc((x),(y)) - -/* -** The malloc.h header file is needed for malloc_usable_size() function -** on some systems (e.g. Linux). -*/ -#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE -# define SQLITE_USE_MALLOC_H 1 -# define SQLITE_USE_MALLOC_USABLE_SIZE 1 -/* -** The MSVCRT has malloc_usable_size(), but it is called _msize(). The -** use of _msize() is automatic, but can be disabled by compiling with -** -DSQLITE_WITHOUT_MSIZE. Using the _msize() function also requires -** the malloc.h header file. -*/ -#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE) -# define SQLITE_USE_MALLOC_H -# define SQLITE_USE_MSIZE -#endif - -/* -** Include the malloc.h header file, if necessary. Also set define macro -** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize() -** for MSVC and malloc_usable_size() for most other systems (e.g. Linux). -** The memory size function can always be overridden manually by defining -** the macro SQLITE_MALLOCSIZE to the desired function name. -*/ -#if defined(SQLITE_USE_MALLOC_H) -# include -# if defined(SQLITE_USE_MALLOC_USABLE_SIZE) -# if !defined(SQLITE_MALLOCSIZE) -# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x) -# endif -# elif defined(SQLITE_USE_MSIZE) -# if !defined(SQLITE_MALLOCSIZE) -# define SQLITE_MALLOCSIZE _msize -# endif -# endif -#endif /* defined(SQLITE_USE_MALLOC_H) */ - -#endif /* __APPLE__ or not __APPLE__ */ - -/* -** Like malloc(), but remember the size of the allocation -** so that we can find it later using sqlite3MemSize(). -** -** For this low-level routine, we are guaranteed that nByte>0 because -** cases of nByte<=0 will be intercepted and dealt with by higher level -** routines. -*/ -static void *sqlite3MemMalloc(int nByte){ -#ifdef SQLITE_MALLOCSIZE - void *p; - testcase( ROUND8(nByte)==nByte ); - p = SQLITE_MALLOC( nByte ); - if( p==0 ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); - } - return p; -#else - sqlite3_int64 *p; - assert( nByte>0 ); - testcase( ROUND8(nByte)!=nByte ); - p = SQLITE_MALLOC( nByte+8 ); - if( p ){ - p[0] = nByte; - p++; - }else{ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); - } - return (void *)p; -#endif -} - -/* -** Like free() but works for allocations obtained from sqlite3MemMalloc() -** or sqlite3MemRealloc(). -** -** For this low-level routine, we already know that pPrior!=0 since -** cases where pPrior==0 will have been intercepted and dealt with -** by higher-level routines. -*/ -static void sqlite3MemFree(void *pPrior){ -#ifdef SQLITE_MALLOCSIZE - SQLITE_FREE(pPrior); -#else - sqlite3_int64 *p = (sqlite3_int64*)pPrior; - assert( pPrior!=0 ); - p--; - SQLITE_FREE(p); -#endif -} - -/* -** Report the allocated size of a prior return from xMalloc() -** or xRealloc(). -*/ -static int sqlite3MemSize(void *pPrior){ -#ifdef SQLITE_MALLOCSIZE - assert( pPrior!=0 ); - return (int)SQLITE_MALLOCSIZE(pPrior); -#else - sqlite3_int64 *p; - assert( pPrior!=0 ); - p = (sqlite3_int64*)pPrior; - p--; - return (int)p[0]; -#endif -} - -/* -** Like realloc(). Resize an allocation previously obtained from -** sqlite3MemMalloc(). -** -** For this low-level interface, we know that pPrior!=0. Cases where -** pPrior==0 while have been intercepted by higher-level routine and -** redirected to xMalloc. Similarly, we know that nByte>0 because -** cases where nByte<=0 will have been intercepted by higher-level -** routines and redirected to xFree. -*/ -static void *sqlite3MemRealloc(void *pPrior, int nByte){ -#ifdef SQLITE_MALLOCSIZE - void *p = SQLITE_REALLOC(pPrior, nByte); - if( p==0 ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, - "failed memory resize %u to %u bytes", - SQLITE_MALLOCSIZE(pPrior), nByte); - } - return p; -#else - sqlite3_int64 *p = (sqlite3_int64*)pPrior; - assert( pPrior!=0 && nByte>0 ); - assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */ - p--; - p = SQLITE_REALLOC(p, nByte+8 ); - if( p ){ - p[0] = nByte; - p++; - }else{ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, - "failed memory resize %u to %u bytes", - sqlite3MemSize(pPrior), nByte); - } - return (void*)p; -#endif -} - -/* -** Round up a request size to the next valid allocation size. -*/ -static int sqlite3MemRoundup(int n){ - return ROUND8(n); -} - -/* -** Initialize this module. -*/ -static int sqlite3MemInit(void *NotUsed){ -#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) - int cpuCount; - size_t len; - if( _sqliteZone_ ){ - return SQLITE_OK; - } - len = sizeof(cpuCount); - /* One usually wants to use hw.activecpu for MT decisions, but not here */ - sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); - if( cpuCount>1 ){ - /* defer MT decisions to system malloc */ - _sqliteZone_ = malloc_default_zone(); - }else{ - /* only 1 core, use our own zone to contention over global locks, - ** e.g. we have our own dedicated locks */ - _sqliteZone_ = malloc_create_zone(4096, 0); - malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap"); - } -#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */ - UNUSED_PARAMETER(NotUsed); - return SQLITE_OK; -} - -/* -** Deinitialize this module. -*/ -static void sqlite3MemShutdown(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - return; -} - -/* -** This routine is the only routine in this file with external linkage. -** -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -SQLITE_PRIVATE void sqlite3MemSetDefault(void){ - static const sqlite3_mem_methods defaultMethods = { - sqlite3MemMalloc, - sqlite3MemFree, - sqlite3MemRealloc, - sqlite3MemSize, - sqlite3MemRoundup, - sqlite3MemInit, - sqlite3MemShutdown, - 0 - }; - sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); -} - -#endif /* SQLITE_SYSTEM_MALLOC */ - -/************** End of mem1.c ************************************************/ -/************** Begin file mem2.c ********************************************/ -/* -** 2007 August 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains low-level memory allocation drivers for when -** SQLite will use the standard C-library malloc/realloc/free interface -** to obtain the memory it needs while adding lots of additional debugging -** information to each allocation in order to help detect and fix memory -** leaks and memory usage errors. -** -** This file contains implementations of the low-level memory allocation -** routines specified in the sqlite3_mem_methods object. -*/ -/* #include "sqliteInt.h" */ - -/* -** This version of the memory allocator is used only if the -** SQLITE_MEMDEBUG macro is defined -*/ -#ifdef SQLITE_MEMDEBUG - -/* -** The backtrace functionality is only available with GLIBC -*/ -#ifdef __GLIBC__ - extern int backtrace(void**,int); - extern void backtrace_symbols_fd(void*const*,int,int); -#else -# define backtrace(A,B) 1 -# define backtrace_symbols_fd(A,B,C) -#endif -/* #include */ - -/* -** Each memory allocation looks like this: -** -** ------------------------------------------------------------------------ -** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard | -** ------------------------------------------------------------------------ -** -** The application code sees only a pointer to the allocation. We have -** to back up from the allocation pointer to find the MemBlockHdr. The -** MemBlockHdr tells us the size of the allocation and the number of -** backtrace pointers. There is also a guard word at the end of the -** MemBlockHdr. -*/ -struct MemBlockHdr { - i64 iSize; /* Size of this allocation */ - struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ - char nBacktrace; /* Number of backtraces on this alloc */ - char nBacktraceSlots; /* Available backtrace slots */ - u8 nTitle; /* Bytes of title; includes '\0' */ - u8 eType; /* Allocation type code */ - int iForeGuard; /* Guard word for sanity */ -}; - -/* -** Guard words -*/ -#define FOREGUARD 0x80F5E153 -#define REARGUARD 0xE4676B53 - -/* -** Number of malloc size increments to track. -*/ -#define NCSIZE 1000 - -/* -** All of the static variables used by this module are collected -** into a single structure named "mem". This is to keep the -** static variables organized and to reduce namespace pollution -** when this module is combined with other in the amalgamation. -*/ -static struct { - - /* - ** Mutex to control access to the memory allocation subsystem. - */ - sqlite3_mutex *mutex; - - /* - ** Head and tail of a linked list of all outstanding allocations - */ - struct MemBlockHdr *pFirst; - struct MemBlockHdr *pLast; - - /* - ** The number of levels of backtrace to save in new allocations. - */ - int nBacktrace; - void (*xBacktrace)(int, int, void **); - - /* - ** Title text to insert in front of each block - */ - int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ - char zTitle[100]; /* The title text */ - - /* - ** sqlite3MallocDisallow() increments the following counter. - ** sqlite3MallocAllow() decrements it. - */ - int disallow; /* Do not allow memory allocation */ - - /* - ** Gather statistics on the sizes of memory allocations. - ** nAlloc[i] is the number of allocation attempts of i*8 - ** bytes. i==NCSIZE is the number of allocation attempts for - ** sizes more than NCSIZE*8 bytes. - */ - int nAlloc[NCSIZE]; /* Total number of allocations */ - int nCurrent[NCSIZE]; /* Current number of allocations */ - int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */ - -} mem; - - -/* -** Adjust memory usage statistics -*/ -static void adjustStats(int iSize, int increment){ - int i = ROUND8(iSize)/8; - if( i>NCSIZE-1 ){ - i = NCSIZE - 1; - } - if( increment>0 ){ - mem.nAlloc[i]++; - mem.nCurrent[i]++; - if( mem.nCurrent[i]>mem.mxCurrent[i] ){ - mem.mxCurrent[i] = mem.nCurrent[i]; - } - }else{ - mem.nCurrent[i]--; - assert( mem.nCurrent[i]>=0 ); - } -} - -/* -** Given an allocation, find the MemBlockHdr for that allocation. -** -** This routine checks the guards at either end of the allocation and -** if they are incorrect it asserts. -*/ -static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){ - struct MemBlockHdr *p; - int *pInt; - u8 *pU8; - int nReserve; - - p = (struct MemBlockHdr*)pAllocation; - p--; - assert( p->iForeGuard==(int)FOREGUARD ); - nReserve = ROUND8(p->iSize); - pInt = (int*)pAllocation; - pU8 = (u8*)pAllocation; - assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD ); - /* This checks any of the "extra" bytes allocated due - ** to rounding up to an 8 byte boundary to ensure - ** they haven't been overwritten. - */ - while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 ); - return p; -} - -/* -** Return the number of bytes currently allocated at address p. -*/ -static int sqlite3MemSize(void *p){ - struct MemBlockHdr *pHdr; - if( !p ){ - return 0; - } - pHdr = sqlite3MemsysGetHeader(p); - return (int)pHdr->iSize; -} - -/* -** Initialize the memory allocation subsystem. -*/ -static int sqlite3MemInit(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - assert( (sizeof(struct MemBlockHdr)&7) == 0 ); - if( !sqlite3GlobalConfig.bMemstat ){ - /* If memory status is enabled, then the malloc.c wrapper will already - ** hold the STATIC_MEM mutex when the routines here are invoked. */ - mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - } - return SQLITE_OK; -} - -/* -** Deinitialize the memory allocation subsystem. -*/ -static void sqlite3MemShutdown(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - mem.mutex = 0; -} - -/* -** Round up a request size to the next valid allocation size. -*/ -static int sqlite3MemRoundup(int n){ - return ROUND8(n); -} - -/* -** Fill a buffer with pseudo-random bytes. This is used to preset -** the content of a new memory allocation to unpredictable values and -** to clear the content of a freed allocation to unpredictable values. -*/ -static void randomFill(char *pBuf, int nByte){ - unsigned int x, y, r; - x = SQLITE_PTR_TO_INT(pBuf); - y = nByte | 1; - while( nByte >= 4 ){ - x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); - y = y*1103515245 + 12345; - r = x ^ y; - *(int*)pBuf = r; - pBuf += 4; - nByte -= 4; - } - while( nByte-- > 0 ){ - x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); - y = y*1103515245 + 12345; - r = x ^ y; - *(pBuf++) = r & 0xff; - } -} - -/* -** Allocate nByte bytes of memory. -*/ -static void *sqlite3MemMalloc(int nByte){ - struct MemBlockHdr *pHdr; - void **pBt; - char *z; - int *pInt; - void *p = 0; - int totalSize; - int nReserve; - sqlite3_mutex_enter(mem.mutex); - assert( mem.disallow==0 ); - nReserve = ROUND8(nByte); - totalSize = nReserve + sizeof(*pHdr) + sizeof(int) + - mem.nBacktrace*sizeof(void*) + mem.nTitle; - p = malloc(totalSize); - if( p ){ - z = p; - pBt = (void**)&z[mem.nTitle]; - pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; - pHdr->pNext = 0; - pHdr->pPrev = mem.pLast; - if( mem.pLast ){ - mem.pLast->pNext = pHdr; - }else{ - mem.pFirst = pHdr; - } - mem.pLast = pHdr; - pHdr->iForeGuard = FOREGUARD; - pHdr->eType = MEMTYPE_HEAP; - pHdr->nBacktraceSlots = mem.nBacktrace; - pHdr->nTitle = mem.nTitle; - if( mem.nBacktrace ){ - void *aAddr[40]; - pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; - memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); - assert(pBt[0]); - if( mem.xBacktrace ){ - mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); - } - }else{ - pHdr->nBacktrace = 0; - } - if( mem.nTitle ){ - memcpy(z, mem.zTitle, mem.nTitle); - } - pHdr->iSize = nByte; - adjustStats(nByte, +1); - pInt = (int*)&pHdr[1]; - pInt[nReserve/sizeof(int)] = REARGUARD; - randomFill((char*)pInt, nByte); - memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); - p = (void*)pInt; - } - sqlite3_mutex_leave(mem.mutex); - return p; -} - -/* -** Free memory. -*/ -static void sqlite3MemFree(void *pPrior){ - struct MemBlockHdr *pHdr; - void **pBt; - char *z; - assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 - || mem.mutex!=0 ); - pHdr = sqlite3MemsysGetHeader(pPrior); - pBt = (void**)pHdr; - pBt -= pHdr->nBacktraceSlots; - sqlite3_mutex_enter(mem.mutex); - if( pHdr->pPrev ){ - assert( pHdr->pPrev->pNext==pHdr ); - pHdr->pPrev->pNext = pHdr->pNext; - }else{ - assert( mem.pFirst==pHdr ); - mem.pFirst = pHdr->pNext; - } - if( pHdr->pNext ){ - assert( pHdr->pNext->pPrev==pHdr ); - pHdr->pNext->pPrev = pHdr->pPrev; - }else{ - assert( mem.pLast==pHdr ); - mem.pLast = pHdr->pPrev; - } - z = (char*)pBt; - z -= pHdr->nTitle; - adjustStats((int)pHdr->iSize, -1); - randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + - (int)pHdr->iSize + sizeof(int) + pHdr->nTitle); - free(z); - sqlite3_mutex_leave(mem.mutex); -} - -/* -** Change the size of an existing memory allocation. -** -** For this debugging implementation, we *always* make a copy of the -** allocation into a new place in memory. In this way, if the -** higher level code is using pointer to the old allocation, it is -** much more likely to break and we are much more liking to find -** the error. -*/ -static void *sqlite3MemRealloc(void *pPrior, int nByte){ - struct MemBlockHdr *pOldHdr; - void *pNew; - assert( mem.disallow==0 ); - assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */ - pOldHdr = sqlite3MemsysGetHeader(pPrior); - pNew = sqlite3MemMalloc(nByte); - if( pNew ){ - memcpy(pNew, pPrior, (int)(nByteiSize ? nByte : pOldHdr->iSize)); - if( nByte>pOldHdr->iSize ){ - randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize); - } - sqlite3MemFree(pPrior); - } - return pNew; -} - -/* -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -SQLITE_PRIVATE void sqlite3MemSetDefault(void){ - static const sqlite3_mem_methods defaultMethods = { - sqlite3MemMalloc, - sqlite3MemFree, - sqlite3MemRealloc, - sqlite3MemSize, - sqlite3MemRoundup, - sqlite3MemInit, - sqlite3MemShutdown, - 0 - }; - sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); -} - -/* -** Set the "type" of an allocation. -*/ -SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){ - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ - struct MemBlockHdr *pHdr; - pHdr = sqlite3MemsysGetHeader(p); - assert( pHdr->iForeGuard==FOREGUARD ); - pHdr->eType = eType; - } -} - -/* -** Return TRUE if the mask of type in eType matches the type of the -** allocation p. Also return true if p==NULL. -** -** This routine is designed for use within an assert() statement, to -** verify the type of an allocation. For example: -** -** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); -*/ -SQLITE_PRIVATE int sqlite3MemdebugHasType(const void *p, u8 eType){ - int rc = 1; - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ - struct MemBlockHdr *pHdr; - pHdr = sqlite3MemsysGetHeader(p); - assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ - if( (pHdr->eType&eType)==0 ){ - rc = 0; - } - } - return rc; -} - -/* -** Return TRUE if the mask of type in eType matches no bits of the type of the -** allocation p. Also return true if p==NULL. -** -** This routine is designed for use within an assert() statement, to -** verify the type of an allocation. For example: -** -** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); -*/ -SQLITE_PRIVATE int sqlite3MemdebugNoType(const void *p, u8 eType){ - int rc = 1; - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ - struct MemBlockHdr *pHdr; - pHdr = sqlite3MemsysGetHeader(p); - assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ - if( (pHdr->eType&eType)!=0 ){ - rc = 0; - } - } - return rc; -} - -/* -** Set the number of backtrace levels kept for each allocation. -** A value of zero turns off backtracing. The number is always rounded -** up to a multiple of 2. -*/ -SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){ - if( depth<0 ){ depth = 0; } - if( depth>20 ){ depth = 20; } - depth = (depth+1)&0xfe; - mem.nBacktrace = depth; -} - -SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ - mem.xBacktrace = xBacktrace; -} - -/* -** Set the title string for subsequent allocations. -*/ -SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){ - unsigned int n = sqlite3Strlen30(zTitle) + 1; - sqlite3_mutex_enter(mem.mutex); - if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; - memcpy(mem.zTitle, zTitle, n); - mem.zTitle[n] = 0; - mem.nTitle = ROUND8(n); - sqlite3_mutex_leave(mem.mutex); -} - -SQLITE_PRIVATE void sqlite3MemdebugSync(){ - struct MemBlockHdr *pHdr; - for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ - void **pBt = (void**)pHdr; - pBt -= pHdr->nBacktraceSlots; - mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); - } -} - -/* -** Open the file indicated and write a log of all unfreed memory -** allocations into that log. -*/ -SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){ - FILE *out; - struct MemBlockHdr *pHdr; - void **pBt; - int i; - out = fopen(zFilename, "w"); - if( out==0 ){ - fprintf(stderr, "** Unable to output memory debug output log: %s **\n", - zFilename); - return; - } - for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ - char *z = (char*)pHdr; - z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; - fprintf(out, "**** %lld bytes at %p from %s ****\n", - pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); - if( pHdr->nBacktrace ){ - fflush(out); - pBt = (void**)pHdr; - pBt -= pHdr->nBacktraceSlots; - backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); - fprintf(out, "\n"); - } - } - fprintf(out, "COUNTS:\n"); - for(i=0; i=1 ); - size = mem3.aPool[i-1].u.hdr.size4x/4; - assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); - assert( size>=2 ); - if( size <= MX_SMALL ){ - memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]); - }else{ - hash = size % N_HASH; - memsys3UnlinkFromList(i, &mem3.aiHash[hash]); - } -} - -/* -** Link the chunk at mem3.aPool[i] so that is on the list rooted -** at *pRoot. -*/ -static void memsys3LinkIntoList(u32 i, u32 *pRoot){ - assert( sqlite3_mutex_held(mem3.mutex) ); - mem3.aPool[i].u.list.next = *pRoot; - mem3.aPool[i].u.list.prev = 0; - if( *pRoot ){ - mem3.aPool[*pRoot].u.list.prev = i; - } - *pRoot = i; -} - -/* -** Link the chunk at index i into either the appropriate -** small chunk list, or into the large chunk hash table. -*/ -static void memsys3Link(u32 i){ - u32 size, hash; - assert( sqlite3_mutex_held(mem3.mutex) ); - assert( i>=1 ); - assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 ); - size = mem3.aPool[i-1].u.hdr.size4x/4; - assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); - assert( size>=2 ); - if( size <= MX_SMALL ){ - memsys3LinkIntoList(i, &mem3.aiSmall[size-2]); - }else{ - hash = size % N_HASH; - memsys3LinkIntoList(i, &mem3.aiHash[hash]); - } -} - -/* -** If the STATIC_MEM mutex is not already held, obtain it now. The mutex -** will already be held (obtained by code in malloc.c) if -** sqlite3GlobalConfig.bMemStat is true. -*/ -static void memsys3Enter(void){ - if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){ - mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem3.mutex); -} -static void memsys3Leave(void){ - sqlite3_mutex_leave(mem3.mutex); -} - -/* -** Called when we are unable to satisfy an allocation of nBytes. -*/ -static void memsys3OutOfMemory(int nByte){ - if( !mem3.alarmBusy ){ - mem3.alarmBusy = 1; - assert( sqlite3_mutex_held(mem3.mutex) ); - sqlite3_mutex_leave(mem3.mutex); - sqlite3_release_memory(nByte); - sqlite3_mutex_enter(mem3.mutex); - mem3.alarmBusy = 0; - } -} - - -/* -** Chunk i is a free chunk that has been unlinked. Adjust its -** size parameters for check-out and return a pointer to the -** user portion of the chunk. -*/ -static void *memsys3Checkout(u32 i, u32 nBlock){ - u32 x; - assert( sqlite3_mutex_held(mem3.mutex) ); - assert( i>=1 ); - assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ); - assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); - x = mem3.aPool[i-1].u.hdr.size4x; - mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); - mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; - mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2; - return &mem3.aPool[i]; -} - -/* -** Carve a piece off of the end of the mem3.iKeyBlk free chunk. -** Return a pointer to the new allocation. Or, if the key chunk -** is not large enough, return 0. -*/ -static void *memsys3FromKeyBlk(u32 nBlock){ - assert( sqlite3_mutex_held(mem3.mutex) ); - assert( mem3.szKeyBlk>=nBlock ); - if( nBlock>=mem3.szKeyBlk-1 ){ - /* Use the entire key chunk */ - void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk); - mem3.iKeyBlk = 0; - mem3.szKeyBlk = 0; - mem3.mnKeyBlk = 0; - return p; - }else{ - /* Split the key block. Return the tail. */ - u32 newi, x; - newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock; - assert( newi > mem3.iKeyBlk+1 ); - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2; - mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; - mem3.szKeyBlk -= nBlock; - mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk; - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - if( mem3.szKeyBlk < mem3.mnKeyBlk ){ - mem3.mnKeyBlk = mem3.szKeyBlk; - } - return (void*)&mem3.aPool[newi]; - } -} - -/* -** *pRoot is the head of a list of free chunks of the same size -** or same size hash. In other words, *pRoot is an entry in either -** mem3.aiSmall[] or mem3.aiHash[]. -** -** This routine examines all entries on the given list and tries -** to coalesce each entries with adjacent free chunks. -** -** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces -** the current mem3.iKeyBlk with the new larger chunk. In order for -** this mem3.iKeyBlk replacement to work, the key chunk must be -** linked into the hash tables. That is not the normal state of -** affairs, of course. The calling routine must link the key -** chunk before invoking this routine, then must unlink the (possibly -** changed) key chunk once this routine has finished. -*/ -static void memsys3Merge(u32 *pRoot){ - u32 iNext, prev, size, i, x; - - assert( sqlite3_mutex_held(mem3.mutex) ); - for(i=*pRoot; i>0; i=iNext){ - iNext = mem3.aPool[i].u.list.next; - size = mem3.aPool[i-1].u.hdr.size4x; - assert( (size&1)==0 ); - if( (size&2)==0 ){ - memsys3UnlinkFromList(i, pRoot); - assert( i > mem3.aPool[i-1].u.hdr.prevSize ); - prev = i - mem3.aPool[i-1].u.hdr.prevSize; - if( prev==iNext ){ - iNext = mem3.aPool[prev].u.list.next; - } - memsys3Unlink(prev); - size = i + size/4 - prev; - x = mem3.aPool[prev-1].u.hdr.size4x & 2; - mem3.aPool[prev-1].u.hdr.size4x = size*4 | x; - mem3.aPool[prev+size-1].u.hdr.prevSize = size; - memsys3Link(prev); - i = prev; - }else{ - size /= 4; - } - if( size>mem3.szKeyBlk ){ - mem3.iKeyBlk = i; - mem3.szKeyBlk = size; - } - } -} - -/* -** Return a block of memory of at least nBytes in size. -** Return NULL if unable. -** -** This function assumes that the necessary mutexes, if any, are -** already held by the caller. Hence "Unsafe". -*/ -static void *memsys3MallocUnsafe(int nByte){ - u32 i; - u32 nBlock; - u32 toFree; - - assert( sqlite3_mutex_held(mem3.mutex) ); - assert( sizeof(Mem3Block)==8 ); - if( nByte<=12 ){ - nBlock = 2; - }else{ - nBlock = (nByte + 11)/8; - } - assert( nBlock>=2 ); - - /* STEP 1: - ** Look for an entry of the correct size in either the small - ** chunk table or in the large chunk hash table. This is - ** successful most of the time (about 9 times out of 10). - */ - if( nBlock <= MX_SMALL ){ - i = mem3.aiSmall[nBlock-2]; - if( i>0 ){ - memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]); - return memsys3Checkout(i, nBlock); - } - }else{ - int hash = nBlock % N_HASH; - for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){ - if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){ - memsys3UnlinkFromList(i, &mem3.aiHash[hash]); - return memsys3Checkout(i, nBlock); - } - } - } - - /* STEP 2: - ** Try to satisfy the allocation by carving a piece off of the end - ** of the key chunk. This step usually works if step 1 fails. - */ - if( mem3.szKeyBlk>=nBlock ){ - return memsys3FromKeyBlk(nBlock); - } - - - /* STEP 3: - ** Loop through the entire memory pool. Coalesce adjacent free - ** chunks. Recompute the key chunk as the largest free chunk. - ** Then try again to satisfy the allocation by carving a piece off - ** of the end of the key chunk. This step happens very - ** rarely (we hope!) - */ - for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){ - memsys3OutOfMemory(toFree); - if( mem3.iKeyBlk ){ - memsys3Link(mem3.iKeyBlk); - mem3.iKeyBlk = 0; - mem3.szKeyBlk = 0; - } - for(i=0; i=nBlock ){ - return memsys3FromKeyBlk(nBlock); - } - } - } - - /* If none of the above worked, then we fail. */ - return 0; -} - -/* -** Free an outstanding memory allocation. -** -** This function assumes that the necessary mutexes, if any, are -** already held by the caller. Hence "Unsafe". -*/ -static void memsys3FreeUnsafe(void *pOld){ - Mem3Block *p = (Mem3Block*)pOld; - int i; - u32 size, x; - assert( sqlite3_mutex_held(mem3.mutex) ); - assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] ); - i = p - mem3.aPool; - assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 ); - size = mem3.aPool[i-1].u.hdr.size4x/4; - assert( i+size<=mem3.nPool+1 ); - mem3.aPool[i-1].u.hdr.size4x &= ~1; - mem3.aPool[i+size-1].u.hdr.prevSize = size; - mem3.aPool[i+size-1].u.hdr.size4x &= ~2; - memsys3Link(i); - - /* Try to expand the key using the newly freed chunk */ - if( mem3.iKeyBlk ){ - while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){ - size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize; - mem3.iKeyBlk -= size; - mem3.szKeyBlk += size; - memsys3Unlink(mem3.iKeyBlk); - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk; - } - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){ - memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk); - mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk; - } - } -} - -/* -** Return the size of an outstanding allocation, in bytes. The -** size returned omits the 8-byte header overhead. This only -** works for chunks that are currently checked out. -*/ -static int memsys3Size(void *p){ - Mem3Block *pBlock; - assert( p!=0 ); - pBlock = (Mem3Block*)p; - assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); - return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; -} - -/* -** Round up a request size to the next valid allocation size. -*/ -static int memsys3Roundup(int n){ - if( n<=12 ){ - return 12; - }else{ - return ((n+11)&~7) - 4; - } -} - -/* -** Allocate nBytes of memory. -*/ -static void *memsys3Malloc(int nBytes){ - sqlite3_int64 *p; - assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */ - memsys3Enter(); - p = memsys3MallocUnsafe(nBytes); - memsys3Leave(); - return (void*)p; -} - -/* -** Free memory. -*/ -static void memsys3Free(void *pPrior){ - assert( pPrior ); - memsys3Enter(); - memsys3FreeUnsafe(pPrior); - memsys3Leave(); -} - -/* -** Change the size of an existing memory allocation -*/ -static void *memsys3Realloc(void *pPrior, int nBytes){ - int nOld; - void *p; - if( pPrior==0 ){ - return sqlite3_malloc(nBytes); - } - if( nBytes<=0 ){ - sqlite3_free(pPrior); - return 0; - } - nOld = memsys3Size(pPrior); - if( nBytes<=nOld && nBytes>=nOld-128 ){ - return pPrior; - } - memsys3Enter(); - p = memsys3MallocUnsafe(nBytes); - if( p ){ - if( nOld>1)!=(size&1) ){ - fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]); - assert( 0 ); - break; - } - if( size&1 ){ - fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8); - }else{ - fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8, - i==mem3.iKeyBlk ? " **key**" : ""); - } - } - for(i=0; i0; j=mem3.aPool[j].u.list.next){ - fprintf(out, " %p(%d)", &mem3.aPool[j], - (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); - } - fprintf(out, "\n"); - } - for(i=0; i0; j=mem3.aPool[j].u.list.next){ - fprintf(out, " %p(%d)", &mem3.aPool[j], - (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); - } - fprintf(out, "\n"); - } - fprintf(out, "key=%d\n", mem3.iKeyBlk); - fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szKeyBlk*8); - fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnKeyBlk*8); - sqlite3_mutex_leave(mem3.mutex); - if( out==stdout ){ - fflush(stdout); - }else{ - fclose(out); - } -#else - UNUSED_PARAMETER(zFilename); -#endif -} - -/* -** This routine is the only routine in this file with external -** linkage. -** -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. The -** arguments specify the block of memory to manage. -** -** This routine is only called by sqlite3_config(), and therefore -** is not required to be threadsafe (it is not). -*/ -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ - static const sqlite3_mem_methods mempoolMethods = { - memsys3Malloc, - memsys3Free, - memsys3Realloc, - memsys3Size, - memsys3Roundup, - memsys3Init, - memsys3Shutdown, - 0 - }; - return &mempoolMethods; -} - -#endif /* SQLITE_ENABLE_MEMSYS3 */ - -/************** End of mem3.c ************************************************/ -/************** Begin file mem5.c ********************************************/ -/* -** 2007 October 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement a memory -** allocation subsystem for use by SQLite. -** -** This version of the memory allocation subsystem omits all -** use of malloc(). The application gives SQLite a block of memory -** before calling sqlite3_initialize() from which allocations -** are made and returned by the xMalloc() and xRealloc() -** implementations. Once sqlite3_initialize() has been called, -** the amount of memory available to SQLite is fixed and cannot -** be changed. -** -** This version of the memory allocation subsystem is included -** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. -** -** This memory allocator uses the following algorithm: -** -** 1. All memory allocation sizes are rounded up to a power of 2. -** -** 2. If two adjacent free blocks are the halves of a larger block, -** then the two blocks are coalesced into the single larger block. -** -** 3. New memory is allocated from the first available free block. -** -** This algorithm is described in: J. M. Robson. "Bounds for Some Functions -** Concerning Dynamic Storage Allocation". Journal of the Association for -** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. -** -** Let n be the size of the largest allocation divided by the minimum -** allocation size (after rounding all sizes up to a power of 2.) Let M -** be the maximum amount of memory ever outstanding at one time. Let -** N be the total amount of memory available for allocation. Robson -** proved that this memory allocator will never breakdown due to -** fragmentation as long as the following constraint holds: -** -** N >= M*(1 + log2(n)/2) - n + 1 -** -** The sqlite3_status() logic tracks the maximum values of n and M so -** that an application can, at any time, verify this constraint. -*/ -/* #include "sqliteInt.h" */ - -/* -** This version of the memory allocator is used only when -** SQLITE_ENABLE_MEMSYS5 is defined. -*/ -#ifdef SQLITE_ENABLE_MEMSYS5 - -/* -** A minimum allocation is an instance of the following structure. -** Larger allocations are an array of these structures where the -** size of the array is a power of 2. -** -** The size of this object must be a power of two. That fact is -** verified in memsys5Init(). -*/ -typedef struct Mem5Link Mem5Link; -struct Mem5Link { - int next; /* Index of next free chunk */ - int prev; /* Index of previous free chunk */ -}; - -/* -** Maximum size of any allocation is ((1<=0 && i=0 && iLogsize<=LOGMAX ); - assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); - - next = MEM5LINK(i)->next; - prev = MEM5LINK(i)->prev; - if( prev<0 ){ - mem5.aiFreelist[iLogsize] = next; - }else{ - MEM5LINK(prev)->next = next; - } - if( next>=0 ){ - MEM5LINK(next)->prev = prev; - } -} - -/* -** Link the chunk at mem5.aPool[i] so that is on the iLogsize -** free list. -*/ -static void memsys5Link(int i, int iLogsize){ - int x; - assert( sqlite3_mutex_held(mem5.mutex) ); - assert( i>=0 && i=0 && iLogsize<=LOGMAX ); - assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); - - x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize]; - MEM5LINK(i)->prev = -1; - if( x>=0 ){ - assert( xprev = i; - } - mem5.aiFreelist[iLogsize] = i; -} - -/* -** Obtain or release the mutex needed to access global data structures. -*/ -static void memsys5Enter(void){ - sqlite3_mutex_enter(mem5.mutex); -} -static void memsys5Leave(void){ - sqlite3_mutex_leave(mem5.mutex); -} - -/* -** Return the size of an outstanding allocation, in bytes. -** This only works for chunks that are currently checked out. -*/ -static int memsys5Size(void *p){ - int iSize, i; - assert( p!=0 ); - i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom); - assert( i>=0 && i0 ); - - /* No more than 1GiB per allocation */ - if( nByte > 0x40000000 ) return 0; - -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* Keep track of the maximum allocation request. Even unfulfilled - ** requests are counted */ - if( (u32)nByte>mem5.maxRequest ){ - mem5.maxRequest = nByte; - } -#endif - - - /* Round nByte up to the next valid power of two */ - for(iFullSz=mem5.szAtom,iLogsize=0; iFullSzLOGMAX ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); - return 0; - } - i = mem5.aiFreelist[iBin]; - memsys5Unlink(i, iBin); - while( iBin>iLogsize ){ - int newSize; - - iBin--; - newSize = 1 << iBin; - mem5.aCtrl[i+newSize] = CTRL_FREE | iBin; - memsys5Link(i+newSize, iBin); - } - mem5.aCtrl[i] = iLogsize; - -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* Update allocator performance statistics. */ - mem5.nAlloc++; - mem5.totalAlloc += iFullSz; - mem5.totalExcess += iFullSz - nByte; - mem5.currentCount++; - mem5.currentOut += iFullSz; - if( mem5.maxCount=0 && iBlock0 ); - assert( mem5.currentOut>=(size*mem5.szAtom) ); - mem5.currentCount--; - mem5.currentOut -= size*mem5.szAtom; - assert( mem5.currentOut>0 || mem5.currentCount==0 ); - assert( mem5.currentCount>0 || mem5.currentOut==0 ); -#endif - - mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; - while( ALWAYS(iLogsize>iLogsize) & 1 ){ - iBuddy = iBlock - size; - assert( iBuddy>=0 ); - }else{ - iBuddy = iBlock + size; - if( iBuddy>=mem5.nBlock ) break; - } - if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; - memsys5Unlink(iBuddy, iLogsize); - iLogsize++; - if( iBuddy0 ){ - memsys5Enter(); - p = memsys5MallocUnsafe(nBytes); - memsys5Leave(); - } - return (void*)p; -} - -/* -** Free memory. -** -** The outer layer memory allocator prevents this routine from -** being called with pPrior==0. -*/ -static void memsys5Free(void *pPrior){ - assert( pPrior!=0 ); - memsys5Enter(); - memsys5FreeUnsafe(pPrior); - memsys5Leave(); -} - -/* -** Change the size of an existing memory allocation. -** -** The outer layer memory allocator prevents this routine from -** being called with pPrior==0. -** -** nBytes is always a value obtained from a prior call to -** memsys5Round(). Hence nBytes is always a non-negative power -** of two. If nBytes==0 that means that an oversize allocation -** (an allocation larger than 0x40000000) was requested and this -** routine should return 0 without freeing pPrior. -*/ -static void *memsys5Realloc(void *pPrior, int nBytes){ - int nOld; - void *p; - assert( pPrior!=0 ); - assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */ - assert( nBytes>=0 ); - if( nBytes==0 ){ - return 0; - } - nOld = memsys5Size(pPrior); - if( nBytes<=nOld ){ - return pPrior; - } - p = memsys5Malloc(nBytes); - if( p ){ - memcpy(p, pPrior, nOld); - memsys5Free(pPrior); - } - return p; -} - -/* -** Round up a request size to the next valid allocation size. If -** the allocation is too large to be handled by this allocation system, -** return 0. -** -** All allocations must be a power of two and must be expressed by a -** 32-bit signed integer. Hence the largest allocation is 0x40000000 -** or 1073741824 bytes. -*/ -static int memsys5Roundup(int n){ - int iFullSz; - if( n<=mem5.szAtom*2 ){ - if( n<=mem5.szAtom ) return mem5.szAtom; - return mem5.szAtom*2; - } - if( n>0x10000000 ){ - if( n>0x40000000 ) return 0; - if( n>0x20000000 ) return 0x40000000; - return 0x20000000; - } - for(iFullSz=mem5.szAtom*8; iFullSz=(i64)n ) return iFullSz/2; - return iFullSz; -} - -/* -** Return the ceiling of the logarithm base 2 of iValue. -** -** Examples: memsys5Log(1) -> 0 -** memsys5Log(2) -> 1 -** memsys5Log(4) -> 2 -** memsys5Log(5) -> 3 -** memsys5Log(8) -> 3 -** memsys5Log(9) -> 4 -*/ -static int memsys5Log(int iValue){ - int iLog; - for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<mem5.szAtom ){ - mem5.szAtom = mem5.szAtom << 1; - } - - mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8))); - mem5.zPool = zByte; - mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom]; - - for(ii=0; ii<=LOGMAX; ii++){ - mem5.aiFreelist[ii] = -1; - } - - iOffset = 0; - for(ii=LOGMAX; ii>=0; ii--){ - int nAlloc = (1<mem5.nBlock); - } - - /* If a mutex is required for normal operation, allocate one */ - if( sqlite3GlobalConfig.bMemstat==0 ){ - mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - } - - return SQLITE_OK; -} - -/* -** Deinitialize this module. -*/ -static void memsys5Shutdown(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - mem5.mutex = 0; - return; -} - -#ifdef SQLITE_TEST -/* -** Open the file indicated and write a log of all unfreed memory -** allocations into that log. -*/ -SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){ - FILE *out; - int i, j, n; - int nMinLog; - - if( zFilename==0 || zFilename[0]==0 ){ - out = stdout; - }else{ - out = fopen(zFilename, "w"); - if( out==0 ){ - fprintf(stderr, "** Unable to output memory debug output log: %s **\n", - zFilename); - return; - } - } - memsys5Enter(); - nMinLog = memsys5Log(mem5.szAtom); - for(i=0; i<=LOGMAX && i+nMinLog<32; i++){ - for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){} - fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n); - } - fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc); - fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc); - fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess); - fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut); - fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount); - fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut); - fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount); - fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest); - memsys5Leave(); - if( out==stdout ){ - fflush(stdout); - }else{ - fclose(out); - } -} -#endif - -/* -** This routine is the only routine in this file with external -** linkage. It returns a pointer to a static sqlite3_mem_methods -** struct populated with the memsys5 methods. -*/ -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){ - static const sqlite3_mem_methods memsys5Methods = { - memsys5Malloc, - memsys5Free, - memsys5Realloc, - memsys5Size, - memsys5Roundup, - memsys5Init, - memsys5Shutdown, - 0 - }; - return &memsys5Methods; -} - -#endif /* SQLITE_ENABLE_MEMSYS5 */ - -/************** End of mem5.c ************************************************/ -/************** Begin file mutex.c *******************************************/ -/* -** 2007 August 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement mutexes. -** -** This file contains code that is common across all mutex implementations. -*/ -/* #include "sqliteInt.h" */ - -#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) -/* -** For debugging purposes, record when the mutex subsystem is initialized -** and uninitialized so that we can assert() if there is an attempt to -** allocate a mutex while the system is uninitialized. -*/ -static SQLITE_WSD int mutexIsInit = 0; -#endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */ - - -#ifndef SQLITE_MUTEX_OMIT - -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS -/* -** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains -** the implementation of a wrapper around the system default mutex -** implementation (sqlite3DefaultMutex()). -** -** Most calls are passed directly through to the underlying default -** mutex implementation. Except, if a mutex is configured by calling -** sqlite3MutexWarnOnContention() on it, then if contention is ever -** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). -** -** This type of mutex is used as the database handle mutex when testing -** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. -*/ - -/* -** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS -** is defined. Variable CheckMutex.mutex is a pointer to the real mutex -** allocated by the system mutex implementation. Variable iType is usually set -** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST -** or one of the static mutex identifiers. Or, if this is a recursive mutex -** that has been configured using sqlite3MutexWarnOnContention(), it is -** set to SQLITE_MUTEX_WARNONCONTENTION. -*/ -typedef struct CheckMutex CheckMutex; -struct CheckMutex { - int iType; - sqlite3_mutex *mutex; -}; - -#define SQLITE_MUTEX_WARNONCONTENTION (-1) - -/* -** Pointer to real mutex methods object used by the CheckMutex -** implementation. Set by checkMutexInit(). -*/ -static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods; - -#ifdef SQLITE_DEBUG -static int checkMutexHeld(sqlite3_mutex *p){ - return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex); -} -static int checkMutexNotheld(sqlite3_mutex *p){ - return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex); -} -#endif - -/* -** Initialize and deinitialize the mutex subsystem. -*/ -static int checkMutexInit(void){ - pGlobalMutexMethods = sqlite3DefaultMutex(); - return SQLITE_OK; -} -static int checkMutexEnd(void){ - pGlobalMutexMethods = 0; - return SQLITE_OK; -} - -/* -** Allocate a mutex. -*/ -static sqlite3_mutex *checkMutexAlloc(int iType){ - static CheckMutex staticMutexes[] = { - {2, 0}, {3, 0}, {4, 0}, {5, 0}, - {6, 0}, {7, 0}, {8, 0}, {9, 0}, - {10, 0}, {11, 0}, {12, 0}, {13, 0} - }; - CheckMutex *p = 0; - - assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 ); - if( iType<2 ){ - p = sqlite3MallocZero(sizeof(CheckMutex)); - if( p==0 ) return 0; - p->iType = iType; - }else{ -#ifdef SQLITE_ENABLE_API_ARMOR - if( iType-2>=ArraySize(staticMutexes) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - p = &staticMutexes[iType-2]; - } - - if( p->mutex==0 ){ - p->mutex = pGlobalMutexMethods->xMutexAlloc(iType); - if( p->mutex==0 ){ - if( iType<2 ){ - sqlite3_free(p); - } - p = 0; - } - } - - return (sqlite3_mutex*)p; -} - -/* -** Free a mutex. -*/ -static void checkMutexFree(sqlite3_mutex *p){ - assert( SQLITE_MUTEX_RECURSIVE<2 ); - assert( SQLITE_MUTEX_FAST<2 ); - assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ((CheckMutex*)p)->iType<2 ) -#endif - { - CheckMutex *pCheck = (CheckMutex*)p; - pGlobalMutexMethods->xMutexFree(pCheck->mutex); - sqlite3_free(pCheck); - } -#ifdef SQLITE_ENABLE_API_ARMOR - else{ - (void)SQLITE_MISUSE_BKPT; - } -#endif -} - -/* -** Enter the mutex. -*/ -static void checkMutexEnter(sqlite3_mutex *p){ - CheckMutex *pCheck = (CheckMutex*)p; - if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){ - if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){ - return; - } - sqlite3_log(SQLITE_MISUSE, - "illegal multi-threaded access to database connection" - ); - } - pGlobalMutexMethods->xMutexEnter(pCheck->mutex); -} - -/* -** Enter the mutex (do not block). -*/ -static int checkMutexTry(sqlite3_mutex *p){ - CheckMutex *pCheck = (CheckMutex*)p; - return pGlobalMutexMethods->xMutexTry(pCheck->mutex); -} - -/* -** Leave the mutex. -*/ -static void checkMutexLeave(sqlite3_mutex *p){ - CheckMutex *pCheck = (CheckMutex*)p; - pGlobalMutexMethods->xMutexLeave(pCheck->mutex); -} - -sqlite3_mutex_methods const *multiThreadedCheckMutex(void){ - static const sqlite3_mutex_methods sMutex = { - checkMutexInit, - checkMutexEnd, - checkMutexAlloc, - checkMutexFree, - checkMutexEnter, - checkMutexTry, - checkMutexLeave, -#ifdef SQLITE_DEBUG - checkMutexHeld, - checkMutexNotheld -#else - 0, - 0 -#endif - }; - return &sMutex; -} - -/* -** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as -** one on which there should be no contention. -*/ -SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ - if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){ - CheckMutex *pCheck = (CheckMutex*)p; - assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE ); - pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; - } -} -#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ - -/* -** Initialize the mutex system. -*/ -SQLITE_PRIVATE int sqlite3MutexInit(void){ - int rc = SQLITE_OK; - if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ - /* If the xMutexAlloc method has not been set, then the user did not - ** install a mutex implementation via sqlite3_config() prior to - ** sqlite3_initialize() being called. This block copies pointers to - ** the default implementation into the sqlite3GlobalConfig structure. - */ - sqlite3_mutex_methods const *pFrom; - sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; - - if( sqlite3GlobalConfig.bCoreMutex ){ -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS - pFrom = multiThreadedCheckMutex(); -#else - pFrom = sqlite3DefaultMutex(); -#endif - }else{ - pFrom = sqlite3NoopMutex(); - } - pTo->xMutexInit = pFrom->xMutexInit; - pTo->xMutexEnd = pFrom->xMutexEnd; - pTo->xMutexFree = pFrom->xMutexFree; - pTo->xMutexEnter = pFrom->xMutexEnter; - pTo->xMutexTry = pFrom->xMutexTry; - pTo->xMutexLeave = pFrom->xMutexLeave; - pTo->xMutexHeld = pFrom->xMutexHeld; - pTo->xMutexNotheld = pFrom->xMutexNotheld; - sqlite3MemoryBarrier(); - pTo->xMutexAlloc = pFrom->xMutexAlloc; - } - assert( sqlite3GlobalConfig.mutex.xMutexInit ); - rc = sqlite3GlobalConfig.mutex.xMutexInit(); - -#ifdef SQLITE_DEBUG - GLOBAL(int, mutexIsInit) = 1; -#endif - - sqlite3MemoryBarrier(); - return rc; -} - -/* -** Shutdown the mutex system. This call frees resources allocated by -** sqlite3MutexInit(). -*/ -SQLITE_PRIVATE int sqlite3MutexEnd(void){ - int rc = SQLITE_OK; - if( sqlite3GlobalConfig.mutex.xMutexEnd ){ - rc = sqlite3GlobalConfig.mutex.xMutexEnd(); - } - -#ifdef SQLITE_DEBUG - GLOBAL(int, mutexIsInit) = 0; -#endif - - return rc; -} - -/* -** Retrieve a pointer to a static mutex or allocate a new dynamic one. -*/ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ -#ifndef SQLITE_OMIT_AUTOINIT - if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; - if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; -#endif - assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); - return sqlite3GlobalConfig.mutex.xMutexAlloc(id); -} - -SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ - if( !sqlite3GlobalConfig.bCoreMutex ){ - return 0; - } - assert( GLOBAL(int, mutexIsInit) ); - assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); - return sqlite3GlobalConfig.mutex.xMutexAlloc(id); -} - -/* -** Free a dynamic mutex. -*/ -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ - if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexFree ); - sqlite3GlobalConfig.mutex.xMutexFree(p); - } -} - -/* -** Obtain the mutex p. If some other thread already has the mutex, block -** until it can be obtained. -*/ -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ - if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexEnter ); - sqlite3GlobalConfig.mutex.xMutexEnter(p); - } -} - -/* -** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another -** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. -*/ -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ - int rc = SQLITE_OK; - if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexTry ); - return sqlite3GlobalConfig.mutex.xMutexTry(p); - } - return rc; -} - -/* -** The sqlite3_mutex_leave() routine exits a mutex that was previously -** entered by the same thread. The behavior is undefined if the mutex -** is not currently entered. If a NULL pointer is passed as an argument -** this function is a no-op. -*/ -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ - if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexLeave ); - sqlite3GlobalConfig.mutex.xMutexLeave(p); - } -} - -#ifndef NDEBUG -/* -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are -** intended for use inside assert() statements. -** -** Because these routines raise false-positive alerts in TSAN, disable -** them (make them always return 1) when compiling with TSAN. -*/ -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ -# if defined(__has_feature) -# if __has_feature(thread_sanitizer) - p = 0; -# endif -# endif - assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); - return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); -} -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ -# if defined(__has_feature) -# if __has_feature(thread_sanitizer) - p = 0; -# endif -# endif - assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); - return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); -} -#endif /* NDEBUG */ - -#endif /* !defined(SQLITE_MUTEX_OMIT) */ - -/************** End of mutex.c ***********************************************/ -/************** Begin file mutex_noop.c **************************************/ -/* -** 2008 October 07 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement mutexes. -** -** This implementation in this file does not provide any mutual -** exclusion and is thus suitable for use only in applications -** that use SQLite in a single thread. The routines defined -** here are place-holders. Applications can substitute working -** mutex routines at start-time using the -** -** sqlite3_config(SQLITE_CONFIG_MUTEX,...) -** -** interface. -** -** If compiled with SQLITE_DEBUG, then additional logic is inserted -** that does error checking on mutexes to make sure they are being -** called correctly. -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_MUTEX_OMIT - -#ifndef SQLITE_DEBUG -/* -** Stub routines for all mutex methods. -** -** This routines provide no mutual exclusion or error checking. -*/ -static int noopMutexInit(void){ return SQLITE_OK; } -static int noopMutexEnd(void){ return SQLITE_OK; } -static sqlite3_mutex *noopMutexAlloc(int id){ - UNUSED_PARAMETER(id); - return (sqlite3_mutex*)8; -} -static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } -static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } -static int noopMutexTry(sqlite3_mutex *p){ - UNUSED_PARAMETER(p); - return SQLITE_OK; -} -static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } - -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ - static const sqlite3_mutex_methods sMutex = { - noopMutexInit, - noopMutexEnd, - noopMutexAlloc, - noopMutexFree, - noopMutexEnter, - noopMutexTry, - noopMutexLeave, - - 0, - 0, - }; - - return &sMutex; -} -#endif /* !SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -** In this implementation, error checking is provided for testing -** and debugging purposes. The mutexes still do not provide any -** mutual exclusion. -*/ - -/* -** The mutex object -*/ -typedef struct sqlite3_debug_mutex { - int id; /* The mutex type */ - int cnt; /* Number of entries without a matching leave */ -} sqlite3_debug_mutex; - -/* -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are -** intended for use inside assert() statements. -*/ -static int debugMutexHeld(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - return p==0 || p->cnt>0; -} -static int debugMutexNotheld(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - return p==0 || p->cnt==0; -} - -/* -** Initialize and deinitialize the mutex subsystem. -*/ -static int debugMutexInit(void){ return SQLITE_OK; } -static int debugMutexEnd(void){ return SQLITE_OK; } - -/* -** The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. If it returns NULL -** that means that a mutex could not be allocated. -*/ -static sqlite3_mutex *debugMutexAlloc(int id){ - static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; - sqlite3_debug_mutex *pNew = 0; - switch( id ){ - case SQLITE_MUTEX_FAST: - case SQLITE_MUTEX_RECURSIVE: { - pNew = sqlite3Malloc(sizeof(*pNew)); - if( pNew ){ - pNew->id = id; - pNew->cnt = 0; - } - break; - } - default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( id-2<0 || id-2>=ArraySize(aStatic) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - pNew = &aStatic[id-2]; - pNew->id = id; - break; - } - } - return (sqlite3_mutex*)pNew; -} - -/* -** This routine deallocates a previously allocated mutex. -*/ -static void debugMutexFree(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - assert( p->cnt==0 ); - if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ - sqlite3_free(p); - }else{ -#ifdef SQLITE_ENABLE_API_ARMOR - (void)SQLITE_MISUSE_BKPT; -#endif - } -} - -/* -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can -** be entered multiple times by the same thread. In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. If the same thread tries to enter any other kind of mutex -** more than once, the behavior is undefined. -*/ -static void debugMutexEnter(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); - p->cnt++; -} -static int debugMutexTry(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); - p->cnt++; - return SQLITE_OK; -} - -/* -** The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. The behavior -** is undefined if the mutex is not currently entered or -** is not currently allocated. SQLite will never do either. -*/ -static void debugMutexLeave(sqlite3_mutex *pX){ - sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; - assert( debugMutexHeld(pX) ); - p->cnt--; - assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); -} - -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ - static const sqlite3_mutex_methods sMutex = { - debugMutexInit, - debugMutexEnd, - debugMutexAlloc, - debugMutexFree, - debugMutexEnter, - debugMutexTry, - debugMutexLeave, - - debugMutexHeld, - debugMutexNotheld - }; - - return &sMutex; -} -#endif /* SQLITE_DEBUG */ - -/* -** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation -** is used regardless of the run-time threadsafety setting. -*/ -#ifdef SQLITE_MUTEX_NOOP -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ - return sqlite3NoopMutex(); -} -#endif /* defined(SQLITE_MUTEX_NOOP) */ -#endif /* !defined(SQLITE_MUTEX_OMIT) */ - -/************** End of mutex_noop.c ******************************************/ -/************** Begin file mutex_unix.c **************************************/ -/* -** 2007 August 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement mutexes for pthreads -*/ -/* #include "sqliteInt.h" */ - -/* -** The code in this file is only used if we are compiling threadsafe -** under unix with pthreads. -** -** Note that this implementation requires a version of pthreads that -** supports recursive mutexes. -*/ -#ifdef SQLITE_MUTEX_PTHREADS - -#include - -/* -** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields -** are necessary under two conditions: (1) Debug builds and (2) using -** home-grown mutexes. Encapsulate these conditions into a single #define. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX) -# define SQLITE_MUTEX_NREF 1 -#else -# define SQLITE_MUTEX_NREF 0 -#endif - -/* -** Each recursive mutex is an instance of the following structure. -*/ -struct sqlite3_mutex { - pthread_mutex_t mutex; /* Mutex controlling the lock */ -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - int id; /* Mutex type */ -#endif -#if SQLITE_MUTEX_NREF - volatile int nRef; /* Number of entrances */ - volatile pthread_t owner; /* Thread that is within this mutex */ - int trace; /* True to trace changes */ -#endif -}; -#if SQLITE_MUTEX_NREF -# define SQLITE3_MUTEX_INITIALIZER(id) \ - {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0} -#elif defined(SQLITE_ENABLE_API_ARMOR) -# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id } -#else -#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER } -#endif - -/* -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are -** intended for use only inside assert() statements. On some platforms, -** there might be race conditions that can cause these routines to -** deliver incorrect results. In particular, if pthread_equal() is -** not an atomic operation, then these routines might delivery -** incorrect results. On most platforms, pthread_equal() is a -** comparison of two integers and is therefore atomic. But we are -** told that HPUX is not such a platform. If so, then these routines -** will not always work correctly on HPUX. -** -** On those platforms where pthread_equal() is not atomic, SQLite -** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to -** make sure no assert() statements are evaluated and hence these -** routines are never called. -*/ -#if !defined(NDEBUG) || defined(SQLITE_DEBUG) -static int pthreadMutexHeld(sqlite3_mutex *p){ - return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); -} -static int pthreadMutexNotheld(sqlite3_mutex *p){ - return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; -} -#endif - -/* -** Try to provide a memory barrier operation, needed for initialization -** and also for the implementation of xShmBarrier in the VFS in cases -** where SQLite is compiled without mutexes. -*/ -SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ -#if defined(SQLITE_MEMORY_BARRIER) - SQLITE_MEMORY_BARRIER; -#elif defined(__GNUC__) && GCC_VERSION>=4001000 - __sync_synchronize(); -#endif -} - -/* -** Initialize and deinitialize the mutex subsystem. -*/ -static int pthreadMutexInit(void){ return SQLITE_OK; } -static int pthreadMutexEnd(void){ return SQLITE_OK; } - -/* -** The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. If it returns NULL -** that means that a mutex could not be allocated. SQLite -** will unwind its stack and return an error. The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MAIN -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 -**
-** -** The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. But SQLite will only request a recursive mutex in -** cases where it really needs one. If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. Six static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. -*/ -static sqlite3_mutex *pthreadMutexAlloc(int iType){ - static sqlite3_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER(2), - SQLITE3_MUTEX_INITIALIZER(3), - SQLITE3_MUTEX_INITIALIZER(4), - SQLITE3_MUTEX_INITIALIZER(5), - SQLITE3_MUTEX_INITIALIZER(6), - SQLITE3_MUTEX_INITIALIZER(7), - SQLITE3_MUTEX_INITIALIZER(8), - SQLITE3_MUTEX_INITIALIZER(9), - SQLITE3_MUTEX_INITIALIZER(10), - SQLITE3_MUTEX_INITIALIZER(11), - SQLITE3_MUTEX_INITIALIZER(12), - SQLITE3_MUTEX_INITIALIZER(13) - }; - sqlite3_mutex *p; - switch( iType ){ - case SQLITE_MUTEX_RECURSIVE: { - p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - /* If recursive mutexes are not available, we will have to - ** build our own. See below. */ - pthread_mutex_init(&p->mutex, 0); -#else - /* Use a recursive mutex if it is available */ - pthread_mutexattr_t recursiveAttr; - pthread_mutexattr_init(&recursiveAttr); - pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&p->mutex, &recursiveAttr); - pthread_mutexattr_destroy(&recursiveAttr); -#endif -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - p->id = SQLITE_MUTEX_RECURSIVE; -#endif - } - break; - } - case SQLITE_MUTEX_FAST: { - p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ - pthread_mutex_init(&p->mutex, 0); -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - p->id = SQLITE_MUTEX_FAST; -#endif - } - break; - } - default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - p = &staticMutexes[iType-2]; - break; - } - } -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - assert( p==0 || p->id==iType ); -#endif - return p; -} - - -/* -** This routine deallocates a previously -** allocated mutex. SQLite is careful to deallocate every -** mutex that it allocates. -*/ -static void pthreadMutexFree(sqlite3_mutex *p){ - assert( p->nRef==0 ); -#ifdef SQLITE_ENABLE_API_ARMOR - if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) -#endif - { - pthread_mutex_destroy(&p->mutex); - sqlite3_free(p); - } -#ifdef SQLITE_ENABLE_API_ARMOR - else{ - (void)SQLITE_MISUSE_BKPT; - } -#endif -} - -/* -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can -** be entered multiple times by the same thread. In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. If the same thread tries to enter any other kind of mutex -** more than once, the behavior is undefined. -*/ -static void pthreadMutexEnter(sqlite3_mutex *p){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); - -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - /* If recursive mutexes are not available, then we have to grow - ** our own. This implementation assumes that pthread_equal() - ** is atomic - that it cannot be deceived into thinking self - ** and p->owner are equal if p->owner changes between two values - ** that are not equal to self while the comparison is taking place. - ** This implementation also assumes a coherent cache - that - ** separate processes cannot read different values from the same - ** address at the same time. If either of these two conditions - ** are not met, then the mutexes will fail and problems will result. - */ - { - pthread_t self = pthread_self(); - if( p->nRef>0 && pthread_equal(p->owner, self) ){ - p->nRef++; - }else{ - pthread_mutex_lock(&p->mutex); - assert( p->nRef==0 ); - p->owner = self; - p->nRef = 1; - } - } -#else - /* Use the built-in recursive mutexes if they are available. - */ - pthread_mutex_lock(&p->mutex); -#if SQLITE_MUTEX_NREF - assert( p->nRef>0 || p->owner==0 ); - p->owner = pthread_self(); - p->nRef++; -#endif -#endif - -#ifdef SQLITE_DEBUG - if( p->trace ){ - printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); - } -#endif -} -static int pthreadMutexTry(sqlite3_mutex *p){ - int rc; - assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); - -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - /* If recursive mutexes are not available, then we have to grow - ** our own. This implementation assumes that pthread_equal() - ** is atomic - that it cannot be deceived into thinking self - ** and p->owner are equal if p->owner changes between two values - ** that are not equal to self while the comparison is taking place. - ** This implementation also assumes a coherent cache - that - ** separate processes cannot read different values from the same - ** address at the same time. If either of these two conditions - ** are not met, then the mutexes will fail and problems will result. - */ - { - pthread_t self = pthread_self(); - if( p->nRef>0 && pthread_equal(p->owner, self) ){ - p->nRef++; - rc = SQLITE_OK; - }else if( pthread_mutex_trylock(&p->mutex)==0 ){ - assert( p->nRef==0 ); - p->owner = self; - p->nRef = 1; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } -#else - /* Use the built-in recursive mutexes if they are available. - */ - if( pthread_mutex_trylock(&p->mutex)==0 ){ -#if SQLITE_MUTEX_NREF - p->owner = pthread_self(); - p->nRef++; -#endif - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } -#endif - -#ifdef SQLITE_DEBUG - if( rc==SQLITE_OK && p->trace ){ - printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); - } -#endif - return rc; -} - -/* -** The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. The behavior -** is undefined if the mutex is not currently entered or -** is not currently allocated. SQLite will never do either. -*/ -static void pthreadMutexLeave(sqlite3_mutex *p){ - assert( pthreadMutexHeld(p) ); -#if SQLITE_MUTEX_NREF - p->nRef--; - if( p->nRef==0 ) p->owner = 0; -#endif - assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); - -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - if( p->nRef==0 ){ - pthread_mutex_unlock(&p->mutex); - } -#else - pthread_mutex_unlock(&p->mutex); -#endif - -#ifdef SQLITE_DEBUG - if( p->trace ){ - printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); - } -#endif -} - -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ - static const sqlite3_mutex_methods sMutex = { - pthreadMutexInit, - pthreadMutexEnd, - pthreadMutexAlloc, - pthreadMutexFree, - pthreadMutexEnter, - pthreadMutexTry, - pthreadMutexLeave, -#ifdef SQLITE_DEBUG - pthreadMutexHeld, - pthreadMutexNotheld -#else - 0, - 0 -#endif - }; - - return &sMutex; -} - -#endif /* SQLITE_MUTEX_PTHREADS */ - -/************** End of mutex_unix.c ******************************************/ -/************** Begin file mutex_w32.c ***************************************/ -/* -** 2007 August 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement mutexes for Win32. -*/ -/* #include "sqliteInt.h" */ - -#if SQLITE_OS_WIN -/* -** Include code that is common to all os_*.c files -*/ -/* #include "os_common.h" */ - -/* -** Include the header file for the Windows VFS. -*/ -/************** Include os_win.h in the middle of mutex_w32.c ****************/ -/************** Begin file os_win.h ******************************************/ -/* -** 2013 November 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that is specific to Windows. -*/ -#ifndef SQLITE_OS_WIN_H -#define SQLITE_OS_WIN_H - -/* -** Include the primary Windows SDK header file. -*/ -#include "windows.h" - -#ifdef __CYGWIN__ -# include -# include /* amalgamator: dontcache */ -# include /* amalgamator: dontcache */ -# include /* amalgamator: dontcache */ -#endif - -/* -** Determine if we are dealing with Windows NT. -** -** We ought to be able to determine if we are compiling for Windows 9x or -** Windows NT using the _WIN32_WINNT macro as follows: -** -** #if defined(_WIN32_WINNT) -** # define SQLITE_OS_WINNT 1 -** #else -** # define SQLITE_OS_WINNT 0 -** #endif -** -** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as -** it ought to, so the above test does not work. We'll just assume that -** everything is Windows NT unless the programmer explicitly says otherwise -** by setting SQLITE_OS_WINNT to 0. -*/ -#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) -# define SQLITE_OS_WINNT 1 -#endif - -/* -** Determine if we are dealing with Windows CE - which has a much reduced -** API. -*/ -#if defined(_WIN32_WCE) -# define SQLITE_OS_WINCE 1 -#else -# define SQLITE_OS_WINCE 0 -#endif - -/* -** Determine if we are dealing with WinRT, which provides only a subset of -** the full Win32 API. -*/ -#if !defined(SQLITE_OS_WINRT) -# define SQLITE_OS_WINRT 0 -#endif - -/* -** For WinCE, some API function parameters do not appear to be declared as -** volatile. -*/ -#if SQLITE_OS_WINCE -# define SQLITE_WIN32_VOLATILE -#else -# define SQLITE_WIN32_VOLATILE volatile -#endif - -/* -** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() -** functions are not available (e.g. those not using MSVC, Cygwin, etc). -*/ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ - SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) -# define SQLITE_OS_WIN_THREADS 1 -#else -# define SQLITE_OS_WIN_THREADS 0 -#endif - -#endif /* SQLITE_OS_WIN_H */ - -/************** End of os_win.h **********************************************/ -/************** Continuing where we left off in mutex_w32.c ******************/ -#endif - -/* -** The code in this file is only used if we are compiling multithreaded -** on a Win32 system. -*/ -#ifdef SQLITE_MUTEX_W32 - -/* -** Each recursive mutex is an instance of the following structure. -*/ -struct sqlite3_mutex { - CRITICAL_SECTION mutex; /* Mutex controlling the lock */ - int id; /* Mutex type */ -#ifdef SQLITE_DEBUG - volatile int nRef; /* Number of entrances */ - volatile DWORD owner; /* Thread holding this mutex */ - volatile LONG trace; /* True to trace changes */ -#endif -}; - -/* -** These are the initializer values used when declaring a "static" mutex -** on Win32. It should be noted that all mutexes require initialization -** on the Win32 platform. -*/ -#define SQLITE_W32_MUTEX_INITIALIZER { 0 } - -#ifdef SQLITE_DEBUG -#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ - 0L, (DWORD)0, 0 } -#else -#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } -#endif - -#ifdef SQLITE_DEBUG -/* -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are -** intended for use only inside assert() statements. -*/ -static int winMutexHeld(sqlite3_mutex *p){ - return p->nRef!=0 && p->owner==GetCurrentThreadId(); -} - -static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ - return p->nRef==0 || p->owner!=tid; -} - -static int winMutexNotheld(sqlite3_mutex *p){ - DWORD tid = GetCurrentThreadId(); - return winMutexNotheld2(p, tid); -} -#endif - -/* -** Try to provide a memory barrier operation, needed for initialization -** and also for the xShmBarrier method of the VFS in cases when SQLite is -** compiled without mutexes (SQLITE_THREADSAFE=0). -*/ -SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ -#if defined(SQLITE_MEMORY_BARRIER) - SQLITE_MEMORY_BARRIER; -#elif defined(__GNUC__) - __sync_synchronize(); -#elif MSVC_VERSION>=1400 - _ReadWriteBarrier(); -#elif defined(MemoryBarrier) - MemoryBarrier(); -#endif -} - -/* -** Initialize and deinitialize the mutex subsystem. -*/ -static sqlite3_mutex winMutex_staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER(2), - SQLITE3_MUTEX_INITIALIZER(3), - SQLITE3_MUTEX_INITIALIZER(4), - SQLITE3_MUTEX_INITIALIZER(5), - SQLITE3_MUTEX_INITIALIZER(6), - SQLITE3_MUTEX_INITIALIZER(7), - SQLITE3_MUTEX_INITIALIZER(8), - SQLITE3_MUTEX_INITIALIZER(9), - SQLITE3_MUTEX_INITIALIZER(10), - SQLITE3_MUTEX_INITIALIZER(11), - SQLITE3_MUTEX_INITIALIZER(12), - SQLITE3_MUTEX_INITIALIZER(13) -}; - -static int winMutex_isInit = 0; -static int winMutex_isNt = -1; /* <0 means "need to query" */ - -/* As the winMutexInit() and winMutexEnd() functions are called as part -** of the sqlite3_initialize() and sqlite3_shutdown() processing, the -** "interlocked" magic used here is probably not strictly necessary. -*/ -static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; - -SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */ -SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ - -static int winMutexInit(void){ - /* The first to increment to 1 does actual initialization */ - if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ - int i; - for(i=0; i -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MAIN -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 -** -** -** The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. But SQLite will only request a recursive mutex in -** cases where it really needs one. If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. Six static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. -*/ -static sqlite3_mutex *winMutexAlloc(int iType){ - sqlite3_mutex *p; - - switch( iType ){ - case SQLITE_MUTEX_FAST: - case SQLITE_MUTEX_RECURSIVE: { - p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ - p->id = iType; -#ifdef SQLITE_DEBUG -#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC - p->trace = 1; -#endif -#endif -#if SQLITE_OS_WINRT - InitializeCriticalSectionEx(&p->mutex, 0, 0); -#else - InitializeCriticalSection(&p->mutex); -#endif - } - break; - } - default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - p = &winMutex_staticMutexes[iType-2]; -#ifdef SQLITE_DEBUG -#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC - InterlockedCompareExchange(&p->trace, 1, 0); -#endif -#endif - break; - } - } - assert( p==0 || p->id==iType ); - return p; -} - - -/* -** This routine deallocates a previously -** allocated mutex. SQLite is careful to deallocate every -** mutex that it allocates. -*/ -static void winMutexFree(sqlite3_mutex *p){ - assert( p ); - assert( p->nRef==0 && p->owner==0 ); - if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ - DeleteCriticalSection(&p->mutex); - sqlite3_free(p); - }else{ -#ifdef SQLITE_ENABLE_API_ARMOR - (void)SQLITE_MISUSE_BKPT; -#endif - } -} - -/* -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can -** be entered multiple times by the same thread. In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. If the same thread tries to enter any other kind of mutex -** more than once, the behavior is undefined. -*/ -static void winMutexEnter(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - DWORD tid = GetCurrentThreadId(); -#endif -#ifdef SQLITE_DEBUG - assert( p ); - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); -#else - assert( p ); -#endif - assert( winMutex_isInit==1 ); - EnterCriticalSection(&p->mutex); -#ifdef SQLITE_DEBUG - assert( p->nRef>0 || p->owner==0 ); - p->owner = tid; - p->nRef++; - if( p->trace ){ - OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", - tid, p->id, p, p->trace, p->nRef)); - } -#endif -} - -static int winMutexTry(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - DWORD tid = GetCurrentThreadId(); -#endif - int rc = SQLITE_BUSY; - assert( p ); - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); - /* - ** The sqlite3_mutex_try() routine is very rarely used, and when it - ** is used it is merely an optimization. So it is OK for it to always - ** fail. - ** - ** The TryEnterCriticalSection() interface is only available on WinNT. - ** And some windows compilers complain if you try to use it without - ** first doing some #defines that prevent SQLite from building on Win98. - ** For that reason, we will omit this optimization for now. See - ** ticket #2685. - */ -#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 - assert( winMutex_isInit==1 ); - assert( winMutex_isNt>=-1 && winMutex_isNt<=1 ); - if( winMutex_isNt<0 ){ - winMutex_isNt = sqlite3_win32_is_nt(); - } - assert( winMutex_isNt==0 || winMutex_isNt==1 ); - if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){ -#ifdef SQLITE_DEBUG - p->owner = tid; - p->nRef++; -#endif - rc = SQLITE_OK; - } -#else - UNUSED_PARAMETER(p); -#endif -#ifdef SQLITE_DEBUG - if( p->trace ){ - OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n", - tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); - } -#endif - return rc; -} - -/* -** The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. The behavior -** is undefined if the mutex is not currently entered or -** is not currently allocated. SQLite will never do either. -*/ -static void winMutexLeave(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - DWORD tid = GetCurrentThreadId(); -#endif - assert( p ); -#ifdef SQLITE_DEBUG - assert( p->nRef>0 ); - assert( p->owner==tid ); - p->nRef--; - if( p->nRef==0 ) p->owner = 0; - assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); -#endif - assert( winMutex_isInit==1 ); - LeaveCriticalSection(&p->mutex); -#ifdef SQLITE_DEBUG - if( p->trace ){ - OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", - tid, p->id, p, p->trace, p->nRef)); - } -#endif -} - -SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ - static const sqlite3_mutex_methods sMutex = { - winMutexInit, - winMutexEnd, - winMutexAlloc, - winMutexFree, - winMutexEnter, - winMutexTry, - winMutexLeave, -#ifdef SQLITE_DEBUG - winMutexHeld, - winMutexNotheld -#else - 0, - 0 -#endif - }; - return &sMutex; -} - -#endif /* SQLITE_MUTEX_W32 */ - -/************** End of mutex_w32.c *******************************************/ -/************** Begin file malloc.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** Memory allocation functions used throughout sqlite. -*/ -/* #include "sqliteInt.h" */ -/* #include */ - -/* -** Attempt to release up to n bytes of non-essential memory currently -** held by SQLite. An example of non-essential memory is memory used to -** cache database pages that are not currently in use. -*/ -SQLITE_API int sqlite3_release_memory(int n){ -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - return sqlite3PcacheReleaseMemory(n); -#else - /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine - ** is a no-op returning zero if SQLite is not compiled with - ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */ - UNUSED_PARAMETER(n); - return 0; -#endif -} - -/* -** Default value of the hard heap limit. 0 means "no limit". -*/ -#ifndef SQLITE_MAX_MEMORY -# define SQLITE_MAX_MEMORY 0 -#endif - -/* -** State information local to the memory allocation subsystem. -*/ -static SQLITE_WSD struct Mem0Global { - sqlite3_mutex *mutex; /* Mutex to serialize access */ - sqlite3_int64 alarmThreshold; /* The soft heap limit */ - sqlite3_int64 hardLimit; /* The hard upper bound on memory */ - - /* - ** True if heap is nearly "full" where "full" is defined by the - ** sqlite3_soft_heap_limit() setting. - */ - int nearlyFull; -} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 }; - -#define mem0 GLOBAL(struct Mem0Global, mem0) - -/* -** Return the memory allocator mutex. sqlite3_status() needs it. -*/ -SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ - return mem0.mutex; -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Deprecated external interface. It used to set an alarm callback -** that was invoked when memory usage grew too large. Now it is a -** no-op. -*/ -SQLITE_API int sqlite3_memory_alarm( - void(*xCallback)(void *pArg, sqlite3_int64 used,int N), - void *pArg, - sqlite3_int64 iThreshold -){ - (void)xCallback; - (void)pArg; - (void)iThreshold; - return SQLITE_OK; -} -#endif - -/* -** Set the soft heap-size limit for the library. An argument of -** zero disables the limit. A negative argument is a no-op used to -** obtain the return value. -** -** The return value is the value of the heap limit just before this -** interface was called. -** -** If the hard heap limit is enabled, then the soft heap limit cannot -** be disabled nor raised above the hard heap limit. -*/ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ - sqlite3_int64 priorLimit; - sqlite3_int64 excess; - sqlite3_int64 nUsed; -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return -1; -#endif - sqlite3_mutex_enter(mem0.mutex); - priorLimit = mem0.alarmThreshold; - if( n<0 ){ - sqlite3_mutex_leave(mem0.mutex); - return priorLimit; - } - if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){ - n = mem0.hardLimit; - } - mem0.alarmThreshold = n; - nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed); - sqlite3_mutex_leave(mem0.mutex); - excess = sqlite3_memory_used() - n; - if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); - return priorLimit; -} -SQLITE_API void sqlite3_soft_heap_limit(int n){ - if( n<0 ) n = 0; - sqlite3_soft_heap_limit64(n); -} - -/* -** Set the hard heap-size limit for the library. An argument of zero -** disables the hard heap limit. A negative argument is a no-op used -** to obtain the return value without affecting the hard heap limit. -** -** The return value is the value of the hard heap limit just prior to -** calling this interface. -** -** Setting the hard heap limit will also activate the soft heap limit -** and constrain the soft heap limit to be no more than the hard heap -** limit. -*/ -SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){ - sqlite3_int64 priorLimit; -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return -1; -#endif - sqlite3_mutex_enter(mem0.mutex); - priorLimit = mem0.hardLimit; - if( n>=0 ){ - mem0.hardLimit = n; - if( n>32) < 0xffffffff ); -} -#else -# define test_oom_breakpoint(X) /* No-op for production builds */ -#endif - -/* -** Do a memory allocation with statistics and alarms. Assume the -** lock is already held. -*/ -static void mallocWithAlarm(int n, void **pp){ - void *p; - int nFull; - assert( sqlite3_mutex_held(mem0.mutex) ); - assert( n>0 ); - - /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal - ** implementation of malloc_good_size(), which must be called in debug - ** mode and specifically when the DMD "Dark Matter Detector" is enabled - ** or else a crash results. Hence, do not attempt to optimize out the - ** following xRoundup() call. */ - nFull = sqlite3GlobalConfig.m.xRoundup(n); - - sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); - if( mem0.alarmThreshold>0 ){ - sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - if( nUsed >= mem0.alarmThreshold - nFull ){ - AtomicStore(&mem0.nearlyFull, 1); - sqlite3MallocAlarm(nFull); - if( mem0.hardLimit ){ - nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - if( nUsed >= mem0.hardLimit - nFull ){ - test_oom_breakpoint(1); - *pp = 0; - return; - } - } - }else{ - AtomicStore(&mem0.nearlyFull, 0); - } - } - p = sqlite3GlobalConfig.m.xMalloc(nFull); -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - if( p==0 && mem0.alarmThreshold>0 ){ - sqlite3MallocAlarm(nFull); - p = sqlite3GlobalConfig.m.xMalloc(nFull); - } -#endif - if( p ){ - nFull = sqlite3MallocSize(p); - sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); - sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); - } - *pp = p; -} - -/* -** Maximum size of any single memory allocation. -** -** This is not a limit on the total amount of memory used. This is -** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). -** -** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 -** This provides a 256-byte safety margin for defense against 32-bit -** signed integer overflow bugs when computing memory allocation sizes. -** Paranoid applications might want to reduce the maximum allocation size -** further for an even larger safety margin. 0x3fffffff or 0x0fffffff -** or even smaller would be reasonable upper bounds on the size of a memory -** allocations for most applications. -*/ -#ifndef SQLITE_MAX_ALLOCATION_SIZE -# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 -#endif -#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 -# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 -#endif - -/* -** Allocate memory. This routine is like sqlite3_malloc() except that it -** assumes the memory subsystem has already been initialized. -*/ -SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ - void *p; - if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){ - p = 0; - }else if( sqlite3GlobalConfig.bMemstat ){ - sqlite3_mutex_enter(mem0.mutex); - mallocWithAlarm((int)n, &p); - sqlite3_mutex_leave(mem0.mutex); - }else{ - p = sqlite3GlobalConfig.m.xMalloc((int)n); - } - assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */ - return p; -} - -/* -** This version of the memory allocation is for use by the application. -** First make sure the memory subsystem is initialized, then do the -** allocation. -*/ -SQLITE_API void *sqlite3_malloc(int n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return n<=0 ? 0 : sqlite3Malloc(n); -} -SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return sqlite3Malloc(n); -} - -/* -** TRUE if p is a lookaside memory allocation from db -*/ -#ifndef SQLITE_OMIT_LOOKASIDE -static int isLookaside(sqlite3 *db, const void *p){ - return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd); -} -#else -#define isLookaside(A,B) 0 -#endif - -/* -** Return the size of a memory allocation previously obtained from -** sqlite3Malloc() or sqlite3_malloc(). -*/ -SQLITE_PRIVATE int sqlite3MallocSize(const void *p){ - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - return sqlite3GlobalConfig.m.xSize((void*)p); -} -static int lookasideMallocSize(sqlite3 *db, const void *p){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - return plookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL; -#else - return db->lookaside.szTrue; -#endif -} -SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, const void *p){ - assert( p!=0 ); -#ifdef SQLITE_DEBUG - if( db==0 ){ - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - }else if( !isLookaside(db,p) ){ - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - } -#endif - if( db ){ - if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - assert( sqlite3_mutex_held(db->mutex) ); - return LOOKASIDE_SMALL; - } -#endif - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - assert( sqlite3_mutex_held(db->mutex) ); - return db->lookaside.szTrue; - } - } - } - return sqlite3GlobalConfig.m.xSize((void*)p); -} -SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - return p ? sqlite3GlobalConfig.m.xSize(p) : 0; -} - -/* -** Free memory previously obtained from sqlite3Malloc(). -*/ -SQLITE_API void sqlite3_free(void *p){ - if( p==0 ) return; /* IMP: R-49053-54554 */ - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - if( sqlite3GlobalConfig.bMemstat ){ - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); - sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); - sqlite3GlobalConfig.m.xFree(p); - sqlite3_mutex_leave(mem0.mutex); - }else{ - sqlite3GlobalConfig.m.xFree(p); - } -} - -/* -** Add the size of memory allocation "p" to the count in -** *db->pnBytesFreed. -*/ -static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){ - *db->pnBytesFreed += sqlite3DbMallocSize(db,p); -} - -/* -** Free memory that might be associated with a particular database -** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op. -** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL. -*/ -SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - assert( p!=0 ); - if( db ){ - if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = pBuf; - return; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; - return; - } - } - if( db->pnBytesFreed ){ - measureAllocationSize(db, p); - return; - } - } - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - sqlite3_free(p); -} -SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3 *db, void *p){ - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( p!=0 ); - if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = pBuf; - return; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; - return; - } - } - if( db->pnBytesFreed ){ - measureAllocationSize(db, p); - return; - } - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - sqlite3_free(p); -} -SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - if( p ) sqlite3DbFreeNN(db, p); -} - -/* -** Change the size of an existing memory allocation -*/ -SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ - int nOld, nNew, nDiff; - void *pNew; - assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) ); - if( pOld==0 ){ - return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */ - } - if( nBytes==0 ){ - sqlite3_free(pOld); /* IMP: R-26507-47431 */ - return 0; - } - if( nBytes>=0x7fffff00 ){ - /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ - return 0; - } - nOld = sqlite3MallocSize(pOld); - /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second - ** argument to xRealloc is always a value returned by a prior call to - ** xRoundup. */ - nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); - if( nOld==nNew ){ - pNew = pOld; - }else if( sqlite3GlobalConfig.bMemstat ){ - sqlite3_int64 nUsed; - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); - nDiff = nNew - nOld; - if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >= - mem0.alarmThreshold-nDiff ){ - sqlite3MallocAlarm(nDiff); - if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){ - sqlite3_mutex_leave(mem0.mutex); - test_oom_breakpoint(1); - return 0; - } - } - pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - if( pNew==0 && mem0.alarmThreshold>0 ){ - sqlite3MallocAlarm((int)nBytes); - pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); - } -#endif - if( pNew ){ - nNew = sqlite3MallocSize(pNew); - sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); - } - sqlite3_mutex_leave(mem0.mutex); - }else{ - pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); - } - assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */ - return pNew; -} - -/* -** The public interface to sqlite3Realloc. Make sure that the memory -** subsystem is initialized prior to invoking sqliteRealloc. -*/ -SQLITE_API void *sqlite3_realloc(void *pOld, int n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - if( n<0 ) n = 0; /* IMP: R-26507-47431 */ - return sqlite3Realloc(pOld, n); -} -SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return sqlite3Realloc(pOld, n); -} - - -/* -** Allocate and zero memory. -*/ -SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){ - void *p = sqlite3Malloc(n); - if( p ){ - memset(p, 0, (size_t)n); - } - return p; -} - -/* -** Allocate and zero memory. If the allocation fails, make -** the mallocFailed flag in the connection pointer. -*/ -SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ - void *p; - testcase( db==0 ); - p = sqlite3DbMallocRaw(db, n); - if( p ) memset(p, 0, (size_t)n); - return p; -} - - -/* Finish the work of sqlite3DbMallocRawNN for the unusual and -** slower case when the allocation cannot be fulfilled using lookaside. -*/ -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ - void *p; - assert( db!=0 ); - p = sqlite3Malloc(n); - if( !p ) sqlite3OomFault(db); - sqlite3MemdebugSetType(p, - (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); - return p; -} - -/* -** Allocate memory, either lookaside (if possible) or heap. -** If the allocation fails, set the mallocFailed flag in -** the connection pointer. -** -** If db!=0 and db->mallocFailed is true (indicating a prior malloc -** failure on the same database connection) then always return 0. -** Hence for a particular database connection, once malloc starts -** failing, it fails consistently until mallocFailed is reset. -** This is an important assumption. There are many places in the -** code that do things like this: -** -** int *a = (int*)sqlite3DbMallocRaw(db, 100); -** int *b = (int*)sqlite3DbMallocRaw(db, 200); -** if( b ) a[10] = 9; -** -** In other words, if a subsequent malloc (ex: "b") worked, it is assumed -** that all prior mallocs (ex: "a") worked too. -** -** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is -** not a NULL pointer. -*/ -SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ - void *p; - if( db ) return sqlite3DbMallocRawNN(db, n); - p = sqlite3Malloc(n); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - return p; -} -SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ -#ifndef SQLITE_OMIT_LOOKASIDE - LookasideSlot *pBuf; - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( db->pnBytesFreed==0 ); - if( n>db->lookaside.sz ){ - if( !db->lookaside.bDisable ){ - db->lookaside.anStat[1]++; - }else if( db->mallocFailed ){ - return 0; - } - return dbMallocRawFinish(db, n); - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( n<=LOOKASIDE_SMALL ){ - if( (pBuf = db->lookaside.pSmallFree)!=0 ){ - db->lookaside.pSmallFree = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){ - db->lookaside.pSmallInit = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - } - } -#endif - if( (pBuf = db->lookaside.pFree)!=0 ){ - db->lookaside.pFree = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else if( (pBuf = db->lookaside.pInit)!=0 ){ - db->lookaside.pInit = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else{ - db->lookaside.anStat[2]++; - } -#else - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( db->pnBytesFreed==0 ); - if( db->mallocFailed ){ - return 0; - } -#endif - return dbMallocRawFinish(db, n); -} - -/* Forward declaration */ -static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); - -/* -** Resize the block of memory pointed to by p to n bytes. If the -** resize fails, set the mallocFailed flag in the connection object. -*/ -SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ - assert( db!=0 ); - if( p==0 ) return sqlite3DbMallocRawNN(db, n); - assert( sqlite3_mutex_held(db->mutex) ); - if( ((uptr)p)<(uptr)db->lookaside.pEnd ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){ - if( n<=LOOKASIDE_SMALL ) return p; - }else -#endif - if( ((uptr)p)>=(uptr)db->lookaside.pStart ){ - if( n<=db->lookaside.szTrue ) return p; - } - } - return dbReallocFinish(db, p, n); -} -static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ - void *pNew = 0; - assert( db!=0 ); - assert( p!=0 ); - if( db->mallocFailed==0 ){ - if( isLookaside(db, p) ){ - pNew = sqlite3DbMallocRawNN(db, n); - if( pNew ){ - memcpy(pNew, p, lookasideMallocSize(db, p)); - sqlite3DbFree(db, p); - } - }else{ - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - pNew = sqlite3Realloc(p, n); - if( !pNew ){ - sqlite3OomFault(db); - } - sqlite3MemdebugSetType(pNew, - (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); - } - } - return pNew; -} - -/* -** Attempt to reallocate p. If the reallocation fails, then free p -** and set the mallocFailed flag in the database connection. -*/ -SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){ - void *pNew; - pNew = sqlite3DbRealloc(db, p, n); - if( !pNew ){ - sqlite3DbFree(db, p); - } - return pNew; -} - -/* -** Make a copy of a string in memory obtained from sqliteMalloc(). These -** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This -** is because when memory debugging is turned on, these two functions are -** called via macros that record the current file and line number in the -** ThreadData structure. -*/ -SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){ - char *zNew; - size_t n; - if( z==0 ){ - return 0; - } - n = strlen(z) + 1; - zNew = sqlite3DbMallocRaw(db, n); - if( zNew ){ - memcpy(zNew, z, n); - } - return zNew; -} -SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ - char *zNew; - assert( db!=0 ); - assert( z!=0 || n==0 ); - assert( (n&0x7fffffff)==n ); - zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0; - if( zNew ){ - memcpy(zNew, z, (size_t)n); - zNew[n] = 0; - } - return zNew; -} - -/* -** The text between zStart and zEnd represents a phrase within a larger -** SQL statement. Make a copy of this phrase in space obtained form -** sqlite3DbMalloc(). Omit leading and trailing whitespace. -*/ -SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ - int n; -#ifdef SQLITE_DEBUG - /* Because of the way the parser works, the span is guaranteed to contain - ** at least one non-space character */ - for(n=0; sqlite3Isspace(zStart[n]); n++){ assert( &zStart[n]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 sqlite3OomFault(db); -** -** and thereby avoid unnecessary stack frame allocations for the overwhelmingly -** common case where no OOM occurs. -*/ -SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ - if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ - db->mallocFailed = 1; - if( db->nVdbeExec>0 ){ - AtomicStore(&db->u1.isInterrupted, 1); - } - DisableLookaside; - if( db->pParse ){ - Parse *pParse; - 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; -} - -/* -** This routine reactivates the memory allocator and clears the -** db->mallocFailed flag as necessary. -** -** The memory allocator is not restarted if there are running -** VDBEs. -*/ -SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){ - if( db->mallocFailed && db->nVdbeExec==0 ){ - db->mallocFailed = 0; - AtomicStore(&db->u1.isInterrupted, 0); - assert( db->lookaside.bDisable>0 ); - EnableLookaside; - } -} - -/* -** Take actions at the end of an API call to deal with error codes. -*/ -static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){ - if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomClear(db); - sqlite3Error(db, SQLITE_NOMEM); - return SQLITE_NOMEM_BKPT; - } - return rc & db->errMask; -} - -/* -** This function must be called before exiting any API function (i.e. -** returning control to the user) that has called sqlite3_malloc or -** sqlite3_realloc. -** -** The returned value is normally a copy of the second argument to this -** function. However, if a malloc() failure has occurred since the previous -** invocation SQLITE_NOMEM is returned instead. -** -** If an OOM as occurred, then the connection error-code (the value -** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. -*/ -SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ - /* If the db handle must hold the connection handle mutex here. - ** Otherwise the read (and possible write) of db->mallocFailed - ** is unsafe, as is the call to sqlite3Error(). - */ - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - if( db->mallocFailed || rc ){ - return apiHandleError(db, rc); - } - return 0; -} - -/************** End of malloc.c **********************************************/ -/************** Begin file printf.c ******************************************/ -/* -** The "printf" code that follows dates from the 1980's. It is in -** the public domain. -** -************************************************************************** -** -** This file contains code for a set of "printf"-like routines. These -** routines format strings much like the printf() from the standard C -** library, though the implementation here has enhancements to support -** SQLite. -*/ -/* #include "sqliteInt.h" */ - -/* -** Conversion types fall into various categories as defined by the -** following enumeration. -*/ -#define etRADIX 0 /* non-decimal integer types. %x %o */ -#define etFLOAT 1 /* Floating point. %f */ -#define etEXP 2 /* Exponentional notation. %e and %E */ -#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ -#define etSIZE 4 /* Return number of characters processed so far. %n */ -#define etSTRING 5 /* Strings. %s */ -#define etDYNSTRING 6 /* Dynamically allocated strings. %z */ -#define etPERCENT 7 /* Percent symbol. %% */ -#define etCHARX 8 /* Characters. %c */ -/* The rest are extensions, not normally found in printf() */ -#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */ -#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '', - NULL pointers replaced by SQL NULL. %Q */ -#define etTOKEN 11 /* a pointer to a Token structure */ -#define etSRCITEM 12 /* a pointer to a SrcItem */ -#define etPOINTER 13 /* The %p conversion */ -#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */ -#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ -#define etDECIMAL 16 /* %d or %u, but not %x, %o */ - -#define etINVALID 17 /* Any unrecognized conversion type */ - - -/* -** An "etByte" is an 8-bit unsigned value. -*/ -typedef unsigned char etByte; - -/* -** Each builtin conversion character (ex: the 'd' in "%d") is described -** by an instance of the following structure -*/ -typedef struct et_info { /* Information about each format field */ - char fmttype; /* The format field code letter */ - etByte base; /* The base for radix conversion */ - etByte flags; /* One or more of FLAG_ constants below */ - etByte type; /* Conversion paradigm */ - etByte charset; /* Offset into aDigits[] of the digits string */ - etByte prefix; /* Offset into aPrefix[] of the prefix string */ -} et_info; - -/* -** Allowed values for et_info.flags -*/ -#define FLAG_SIGNED 1 /* True if the value to convert is signed */ -#define FLAG_STRING 4 /* Allow infinite precision */ - - -/* -** The following table is searched linearly, so it is good to put the -** most frequently used conversion types first. -*/ -static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; -static const char aPrefix[] = "-x0\000X0"; -static const et_info fmtinfo[] = { - { 'd', 10, 1, etDECIMAL, 0, 0 }, - { 's', 0, 4, etSTRING, 0, 0 }, - { 'g', 0, 1, etGENERIC, 30, 0 }, - { 'z', 0, 4, etDYNSTRING, 0, 0 }, - { 'q', 0, 4, etESCAPE_q, 0, 0 }, - { 'Q', 0, 4, etESCAPE_Q, 0, 0 }, - { 'w', 0, 4, etESCAPE_w, 0, 0 }, - { 'c', 0, 0, etCHARX, 0, 0 }, - { 'o', 8, 0, etRADIX, 0, 2 }, - { 'u', 10, 0, etDECIMAL, 0, 0 }, - { 'x', 16, 0, etRADIX, 16, 1 }, - { 'X', 16, 0, etRADIX, 0, 4 }, -#ifndef SQLITE_OMIT_FLOATING_POINT - { 'f', 0, 1, etFLOAT, 0, 0 }, - { 'e', 0, 1, etEXP, 30, 0 }, - { 'E', 0, 1, etEXP, 14, 0 }, - { 'G', 0, 1, etGENERIC, 14, 0 }, -#endif - { 'i', 10, 1, etDECIMAL, 0, 0 }, - { 'n', 0, 0, etSIZE, 0, 0 }, - { '%', 0, 0, etPERCENT, 0, 0 }, - { 'p', 16, 0, etPOINTER, 0, 1 }, - - /* All the rest are undocumented and are for internal use only */ - { 'T', 0, 0, etTOKEN, 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 -*/ - -/* -** Set the StrAccum object to an error mode. -*/ -SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum *p, u8 eError){ - assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); - p->accError = eError; - if( p->mxAlloc ) sqlite3_str_reset(p); - if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError); -} - -/* -** Extra argument values from a PrintfArguments object -*/ -static sqlite3_int64 getIntArg(PrintfArguments *p){ - if( p->nArg<=p->nUsed ) return 0; - return sqlite3_value_int64(p->apArg[p->nUsed++]); -} -static double getDoubleArg(PrintfArguments *p){ - if( p->nArg<=p->nUsed ) return 0.0; - return sqlite3_value_double(p->apArg[p->nUsed++]); -} -static char *getTextArg(PrintfArguments *p){ - if( p->nArg<=p->nUsed ) return 0; - return (char*)sqlite3_value_text(p->apArg[p->nUsed++]); -} - -/* -** Allocate memory for a temporary buffer needed for printf rendering. -** -** If the requested size of the temp buffer is larger than the size -** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error. -** Do the size check before the memory allocation to prevent rogue -** SQL from requesting large allocations using the precision or width -** field of the printf() function. -*/ -static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ - char *z; - if( pAccum->accError ) return 0; - if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){ - sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG); - return 0; - } - z = sqlite3DbMallocRaw(pAccum->db, n); - if( z==0 ){ - sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM); - } - return z; -} - -/* -** On machines with a small stack size, you can redefine the -** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. -*/ -#ifndef SQLITE_PRINT_BUF_SIZE -# define SQLITE_PRINT_BUF_SIZE 70 -#endif -#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ - -/* -** Hard limit on the precision of floating-point conversions. -*/ -#ifndef SQLITE_PRINTF_PRECISION_LIMIT -# define SQLITE_FP_PRECISION_LIMIT 100000000 -#endif - -/* -** Render a string given by "fmt" into the StrAccum object. -*/ -SQLITE_API void sqlite3_str_vappendf( - sqlite3_str *pAccum, /* Accumulate results here */ - const char *fmt, /* Format string */ - va_list ap /* arguments */ -){ - int c; /* Next character in the format string */ - char *bufpt; /* Pointer to the conversion buffer */ - int precision; /* Precision of the current field */ - int length; /* Length of the field */ - int idx; /* A general purpose loop counter */ - int width; /* Width of the current field */ - etByte flag_leftjustify; /* True if "-" flag is present */ - etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ - etByte flag_alternateform; /* True if "#" flag is present */ - etByte flag_altform2; /* True if "!" flag is present */ - etByte flag_zeropad; /* True if field width constant starts with zero */ - etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */ - etByte done; /* Loop termination flag */ - etByte cThousand; /* Thousands separator for %d and %u */ - etByte xtype = etINVALID; /* Conversion paradigm */ - u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ - char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ - sqlite_uint64 longvalue; /* Value for integer types */ - double realvalue; /* Value for real types */ - const et_info *infop; /* Pointer to the appropriate info structure */ - char *zOut; /* Rendering buffer */ - int nOut; /* Size of the rendering buffer */ - char *zExtra = 0; /* Malloced memory used by some conversion */ - int exp, e2; /* exponent of real numbers */ - etByte flag_dp; /* True if decimal point should be shown */ - etByte flag_rtz; /* True if trailing zeros should be removed */ - - PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ - char buf[etBUFSIZE]; /* Conversion buffer */ - - /* pAccum never starts out with an empty buffer that was obtained from - ** malloc(). This precondition is required by the mprintf("%z...") - ** optimization. */ - assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); - - bufpt = 0; - if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ - pArgList = va_arg(ap, PrintfArguments*); - bArgList = 1; - }else{ - bArgList = 0; - } - for(; (c=(*fmt))!=0; ++fmt){ - if( c!='%' ){ - bufpt = (char *)fmt; -#if HAVE_STRCHRNUL - fmt = strchrnul(fmt, '%'); -#else - do{ fmt++; }while( *fmt && *fmt != '%' ); -#endif - sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); - if( *fmt==0 ) break; - } - if( (c=(*++fmt))==0 ){ - sqlite3_str_append(pAccum, "%", 1); - break; - } - /* Find out what flags are present */ - flag_leftjustify = flag_prefix = cThousand = - flag_alternateform = flag_altform2 = flag_zeropad = 0; - done = 0; - width = 0; - flag_long = 0; - precision = -1; - do{ - switch( c ){ - case '-': flag_leftjustify = 1; break; - case '+': flag_prefix = '+'; break; - case ' ': flag_prefix = ' '; break; - case '#': flag_alternateform = 1; break; - case '!': flag_altform2 = 1; break; - case '0': flag_zeropad = 1; break; - case ',': cThousand = ','; break; - default: done = 1; break; - case 'l': { - flag_long = 1; - c = *++fmt; - if( c=='l' ){ - c = *++fmt; - flag_long = 2; - } - done = 1; - break; - } - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': { - unsigned wx = c - '0'; - while( (c = *++fmt)>='0' && c<='9' ){ - wx = wx*10 + c - '0'; - } - testcase( wx>0x7fffffff ); - width = wx & 0x7fffffff; -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ - width = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( c!='.' && c!='l' ){ - done = 1; - }else{ - fmt--; - } - break; - } - case '*': { - if( bArgList ){ - width = (int)getIntArg(pArgList); - }else{ - width = va_arg(ap,int); - } - if( width<0 ){ - flag_leftjustify = 1; - width = width >= -2147483647 ? -width : 0; - } -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ - width = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( (c = fmt[1])!='.' && c!='l' ){ - c = *++fmt; - done = 1; - } - break; - } - case '.': { - c = *++fmt; - if( c=='*' ){ - if( bArgList ){ - precision = (int)getIntArg(pArgList); - }else{ - precision = va_arg(ap,int); - } - if( precision<0 ){ - precision = precision >= -2147483647 ? -precision : -1; - } - c = *++fmt; - }else{ - unsigned px = 0; - while( c>='0' && c<='9' ){ - px = px*10 + c - '0'; - c = *++fmt; - } - testcase( px>0x7fffffff ); - precision = px & 0x7fffffff; - } -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){ - precision = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( c=='l' ){ - --fmt; - }else{ - done = 1; - } - break; - } - } - }while( !done && (c=(*++fmt))!=0 ); - - /* Fetch the info entry for the field */ - infop = &fmtinfo[0]; - xtype = etINVALID; - for(idx=0; idxtype; - break; - } - } - - /* - ** At this point, variables are initialized as follows: - ** - ** flag_alternateform TRUE if a '#' is present. - ** flag_altform2 TRUE if a '!' is present. - ** flag_prefix '+' or ' ' or zero - ** flag_leftjustify TRUE if a '-' is present or if the - ** field width was negative. - ** flag_zeropad TRUE if the width began with 0. - ** flag_long 1 for "l", 2 for "ll" - ** width The specified field width. This is - ** always non-negative. Zero is the default. - ** precision The specified precision. The default - ** is -1. - ** xtype The class of the conversion. - ** infop Pointer to the appropriate info struct. - */ - assert( width>=0 ); - assert( precision>=(-1) ); - switch( xtype ){ - case etPOINTER: - flag_long = sizeof(char*)==sizeof(i64) ? 2 : - sizeof(char*)==sizeof(long int) ? 1 : 0; - /* no break */ deliberate_fall_through - case etORDINAL: - case etRADIX: - cThousand = 0; - /* no break */ deliberate_fall_through - case etDECIMAL: - if( infop->flags & FLAG_SIGNED ){ - i64 v; - if( bArgList ){ - v = getIntArg(pArgList); - }else if( flag_long ){ - if( flag_long==2 ){ - v = va_arg(ap,i64) ; - }else{ - v = va_arg(ap,long int); - } - }else{ - v = va_arg(ap,int); - } - if( v<0 ){ - testcase( v==SMALLEST_INT64 ); - testcase( v==(-1) ); - longvalue = ~v; - longvalue++; - prefix = '-'; - }else{ - longvalue = v; - prefix = flag_prefix; - } - }else{ - if( bArgList ){ - longvalue = (u64)getIntArg(pArgList); - }else if( flag_long ){ - if( flag_long==2 ){ - longvalue = va_arg(ap,u64); - }else{ - longvalue = va_arg(ap,unsigned long int); - } - }else{ - longvalue = va_arg(ap,unsigned int); - } - prefix = 0; - } - if( longvalue==0 ) flag_alternateform = 0; - if( flag_zeropad && precision=4 || (longvalue/10)%10==1 ){ - x = 0; - } - *(--bufpt) = zOrd[x*2+1]; - *(--bufpt) = zOrd[x*2]; - } - { - const char *cset = &aDigits[infop->charset]; - u8 base = infop->base; - do{ /* Convert to ascii */ - *(--bufpt) = cset[longvalue%base]; - longvalue = longvalue/base; - }while( longvalue>0 ); - } - length = (int)(&zOut[nOut-1]-bufpt); - while( precision>length ){ - *(--bufpt) = '0'; /* Zero pad */ - length++; - } - if( cThousand ){ - int nn = (length - 1)/3; /* Number of "," to insert */ - int ix = (length - 1)%3 + 1; - bufpt -= nn; - for(idx=0; nn>0; idx++){ - bufpt[idx] = bufpt[idx+nn]; - ix--; - if( ix==0 ){ - bufpt[++idx] = cThousand; - nn--; - ix = 3; - } - } - } - if( prefix ) *(--bufpt) = prefix; /* Add sign */ - if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ - const char *pre; - char x; - pre = &aPrefix[infop->prefix]; - for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; - } - length = (int)(&zOut[nOut-1]-bufpt); - break; - case etFLOAT: - case etEXP: - case etGENERIC: { - FpDecode s; - int iRound; - int j; - - if( bArgList ){ - realvalue = getDoubleArg(pArgList); - }else{ - realvalue = va_arg(ap,double); - } - if( precision<0 ) precision = 6; /* Set default precision */ -#ifdef SQLITE_FP_PRECISION_LIMIT - if( precision>SQLITE_FP_PRECISION_LIMIT ){ - precision = SQLITE_FP_PRECISION_LIMIT; - } -#endif - if( xtype==etFLOAT ){ - iRound = -precision; - }else if( xtype==etGENERIC ){ - if( precision==0 ) precision = 1; - iRound = precision; - }else{ - iRound = precision+1; - } - sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); - if( s.isSpecial ){ - if( s.isSpecial==2 ){ - bufpt = flag_zeropad ? "null" : "NaN"; - length = sqlite3Strlen30(bufpt); - break; - }else if( flag_zeropad ){ - s.z[0] = '9'; - s.iDP = 1000; - s.n = 1; - }else{ - memcpy(buf, "-Inf", 5); - bufpt = buf; - if( s.sign=='-' ){ - /* no-op */ - }else if( flag_prefix ){ - buf[0] = flag_prefix; - }else{ - bufpt++; - } - length = sqlite3Strlen30(bufpt); - break; - } - } - if( s.sign=='-' ){ - prefix = '-'; - }else{ - prefix = flag_prefix; - } - - exp = s.iDP-1; - - /* - ** If the field type is etGENERIC, then convert to either etEXP - ** or etFLOAT, as appropriate. - */ - if( xtype==etGENERIC ){ - assert( precision>0 ); - precision--; - flag_rtz = !flag_alternateform; - if( exp<-4 || exp>precision ){ - xtype = etEXP; - }else{ - precision = precision - exp; - xtype = etFLOAT; - } - }else{ - flag_rtz = flag_altform2; - } - if( xtype==etEXP ){ - e2 = 0; - }else{ - e2 = s.iDP - 1; - } - bufpt = buf; - { - i64 szBufNeeded; /* Size of a temporary buffer needed */ - szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15; - if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3; - if( szBufNeeded > etBUFSIZE ){ - bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded); - if( bufpt==0 ) return; - } - } - zOut = bufpt; - flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; - /* The sign in front of the number */ - if( prefix ){ - *(bufpt++) = prefix; - } - /* Digits prior to the decimal point */ - j = 0; - if( e2<0 ){ - *(bufpt++) = '0'; - }else{ - for(; e2>=0; e2--){ - *(bufpt++) = j1 ) *(bufpt++) = ','; - } - } - /* The decimal point */ - if( flag_dp ){ - *(bufpt++) = '.'; - } - /* "0" digits after the decimal point but before the first - ** significant digit of the number */ - for(e2++; e2<0 && precision>0; precision--, e2++){ - *(bufpt++) = '0'; - } - /* Significant digits after the decimal point */ - while( (precision--)>0 ){ - *(bufpt++) = jzOut ); - if( bufpt[-1]=='.' ){ - if( flag_altform2 ){ - *(bufpt++) = '0'; - }else{ - *(--bufpt) = 0; - } - } - } - /* Add the "eNNN" suffix */ - if( xtype==etEXP ){ - exp = s.iDP - 1; - *(bufpt++) = aDigits[infop->charset]; - if( exp<0 ){ - *(bufpt++) = '-'; exp = -exp; - }else{ - *(bufpt++) = '+'; - } - if( exp>=100 ){ - *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */ - exp %= 100; - } - *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */ - *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */ - } - *bufpt = 0; - - /* The converted number is in buf[] and zero terminated. Output it. - ** Note that the number is in the usual order, not reversed as with - ** integer conversions. */ - length = (int)(bufpt-zOut); - bufpt = zOut; - - /* Special case: Add leading zeros if the flag_zeropad flag is - ** set and we are not left justified */ - if( flag_zeropad && !flag_leftjustify && length < width){ - int i; - int nPad = width - length; - for(i=width; i>=nPad; i--){ - bufpt[i] = bufpt[i-nPad]; - } - i = prefix!=0; - while( nPad-- ) bufpt[i++] = '0'; - length = width; - } - break; - } - case etSIZE: - if( !bArgList ){ - *(va_arg(ap,int*)) = pAccum->nChar; - } - length = width = 0; - break; - case etPERCENT: - buf[0] = '%'; - bufpt = buf; - length = 1; - break; - case etCHARX: - if( bArgList ){ - bufpt = getTextArg(pArgList); - length = 1; - if( bufpt ){ - buf[0] = c = *(bufpt++); - if( (c&0xc0)==0xc0 ){ - while( length<4 && (bufpt[0]&0xc0)==0x80 ){ - buf[length++] = *(bufpt++); - } - } - }else{ - buf[0] = 0; - } - }else{ - unsigned int ch = va_arg(ap,unsigned int); - length = sqlite3AppendOneUtf8Character(buf, ch); - } - if( precision>1 ){ - i64 nPrior = 1; - width -= precision-1; - if( width>1 && !flag_leftjustify ){ - sqlite3_str_appendchar(pAccum, width-1, ' '); - width = 0; - } - sqlite3_str_append(pAccum, buf, length); - precision--; - while( precision > 1 ){ - i64 nCopyBytes; - if( nPrior > precision-1 ) nPrior = precision - 1; - nCopyBytes = length*nPrior; - if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){ - sqlite3StrAccumEnlarge(pAccum, nCopyBytes); - } - if( pAccum->accError ) break; - sqlite3_str_append(pAccum, - &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes); - precision -= nPrior; - nPrior *= 2; - } - } - bufpt = buf; - flag_altform2 = 1; - goto adjust_width_for_utf8; - case etSTRING: - case etDYNSTRING: - if( bArgList ){ - bufpt = getTextArg(pArgList); - xtype = etSTRING; - }else{ - bufpt = va_arg(ap,char*); - } - if( bufpt==0 ){ - bufpt = ""; - }else if( xtype==etDYNSTRING ){ - if( pAccum->nChar==0 - && pAccum->mxAlloc - && width==0 - && precision<0 - && pAccum->accError==0 - ){ - /* Special optimization for sqlite3_mprintf("%z..."): - ** Extend an existing memory allocation rather than creating - ** a new one. */ - assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); - pAccum->zText = bufpt; - pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); - pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); - pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED; - length = 0; - break; - } - zExtra = bufpt; - } - if( precision>=0 ){ - if( flag_altform2 ){ - /* Set length to the number of bytes needed in order to display - ** precision characters */ - unsigned char *z = (unsigned char*)bufpt; - while( precision-- > 0 && z[0] ){ - SQLITE_SKIP_UTF8(z); - } - length = (int)(z - (unsigned char*)bufpt); - }else{ - for(length=0; length0 ){ - /* Adjust width to account for extra bytes in UTF-8 characters */ - int ii = length - 1; - while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; - } - break; - case etESCAPE_q: /* %q: Escape ' characters */ - case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */ - case etESCAPE_w: { /* %w: Escape " characters */ - i64 i, j, k, n; - int needQuote = 0; - char ch; - char *escarg; - char q; - - if( bArgList ){ - escarg = getTextArg(pArgList); - }else{ - escarg = va_arg(ap,char*); - } - if( escarg==0 ){ - escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)"); - }else if( xtype==etESCAPE_Q ){ - needQuote = 1; - } - if( xtype==etESCAPE_w ){ - q = '"'; - flag_alternateform = 0; - }else{ - q = '\''; - } - /* For %q, %Q, and %w, the precision is the number of bytes (or - ** characters if the ! flags is present) to use from the input. - ** Because of the extra quoting characters inserted, the number - ** of output characters may be larger than the precision. - */ - k = precision; - for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ - if( ch==q ) n++; - if( flag_altform2 && (ch&0xc0)==0xc0 ){ - while( (escarg[i+1]&0xc0)==0x80 ){ i++; } - } - } - if( flag_alternateform ){ - /* For %#q, do unistr()-style backslash escapes for - ** all control characters, and for backslash itself. - ** For %#Q, do the same but only if there is at least - ** one control character. */ - u32 nBack = 0; - u32 nCtrl = 0; - for(k=0; ketBUFSIZE ){ - bufpt = zExtra = printfTempBuf(pAccum, n); - if( bufpt==0 ) return; - }else{ - bufpt = buf; - } - j = 0; - if( needQuote ){ - if( needQuote==2 ){ - memcpy(&bufpt[j], "unistr('", 8); - j += 8; - }else{ - bufpt[j++] = '\''; - } - } - k = i; - if( flag_alternateform ){ - for(i=0; i=0x10 ? '1' : '0'; - bufpt[j++] = "0123456789abcdef"[ch&0xf]; - } - } - }else{ - for(i=0; iprintfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - 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)) ){ - sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken); - sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr); - } - }else{ - /* %T means a Token pointer */ - Token *pToken = va_arg(ap, Token*); - assert( bArgList==0 ); - if( pToken && pToken->n ){ - sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); - sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); - } - } - length = width = 0; - break; - } - case etSRCITEM: { - SrcItem *pItem; - if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pItem = va_arg(ap, SrcItem*); - assert( bArgList==0 ); - if( pItem->zAlias && !flag_altform2 ){ - sqlite3_str_appendall(pAccum, pItem->zAlias); - }else if( pItem->zName ){ - if( pItem->fg.fixedSchema==0 - && pItem->fg.isSubquery==0 - && pItem->u4.zDatabase!=0 - ){ - sqlite3_str_appendall(pAccum, pItem->u4.zDatabase); - sqlite3_str_append(pAccum, ".", 1); - } - sqlite3_str_appendall(pAccum, pItem->zName); - }else if( pItem->zAlias ){ - sqlite3_str_appendall(pAccum, pItem->zAlias); - }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */ - Select *pSel = pItem->u4.pSubq->pSelect; - assert( pSel!=0 ); - if( pSel->selFlags & SF_NestedFrom ){ - sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); - }else if( pSel->selFlags & SF_MultiValue ){ - assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy ); - sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", - pItem->u1.nRow); - }else{ - sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); - } - } - length = width = 0; - break; - } - default: { - assert( xtype==etINVALID ); - return; - } - }/* End switch over the format type */ - /* - ** The text of the conversion is pointed to by "bufpt" and is - ** "length" characters long. The field width is "width". Do - ** the output. Both length and width are in bytes, not characters, - ** at this point. If the "!" flag was present on string conversions - ** indicating that width and precision should be expressed in characters, - ** then the values have been translated prior to reaching this point. - */ - width -= length; - if( width>0 ){ - if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); - sqlite3_str_append(pAccum, bufpt, length); - if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); - }else{ - sqlite3_str_append(pAccum, bufpt, length); - } - - if( zExtra ){ - sqlite3DbFree(pAccum->db, zExtra); - zExtra = 0; - } - }/* 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 sqlite3RecordErrorByteOffset(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 sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){ - while( pExpr - && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0) - ){ - pExpr = pExpr->pLeft; - } - if( pExpr==0 ) return; - if( ExprHasProperty(pExpr, EP_FromDDL) ) 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. -** -** Return the number of bytes of text that StrAccum is able to accept -** after the attempted enlargement. The value returned might be zero. -*/ -SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){ - char *zNew; - assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ - if( p->accError ){ - testcase(p->accError==SQLITE_TOOBIG); - testcase(p->accError==SQLITE_NOMEM); - return 0; - } - if( p->mxAlloc==0 ){ - sqlite3StrAccumSetError(p, SQLITE_TOOBIG); - return p->nAlloc - p->nChar - 1; - }else{ - char *zOld = isMalloced(p) ? p->zText : 0; - i64 szNew = p->nChar + 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 */ - szNew += p->nChar; - } - if( szNew > p->mxAlloc ){ - sqlite3_str_reset(p); - sqlite3StrAccumSetError(p, SQLITE_TOOBIG); - return 0; - }else{ - p->nAlloc = (int)szNew; - } - if( p->db ){ - zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); - }else{ - zNew = sqlite3Realloc(zOld, p->nAlloc); - } - if( zNew ){ - assert( p->zText!=0 || p->nChar==0 ); - if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); - p->zText = zNew; - p->nAlloc = sqlite3DbMallocSize(p->db, zNew); - p->printfFlags |= SQLITE_PRINTF_MALLOCED; - }else{ - sqlite3_str_reset(p); - sqlite3StrAccumSetError(p, SQLITE_NOMEM); - return 0; - } - } - assert( N>=0 && N<=0x7fffffff ); - return (int)N; -} - -/* -** Append N copies of character c to the given string buffer. -*/ -SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ - testcase( p->nChar + (i64)N > 0x7fffffff ); - if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ - return; - } - while( (N--)>0 ) p->zText[p->nChar++] = c; -} - -/* -** The StrAccum "p" is not large enough to accept N new bytes of z[]. -** So enlarge if first, then do the append. -** -** This is a helper routine to sqlite3_str_append() that does special-case -** work (enlarging the buffer) using tail recursion, so that the -** sqlite3_str_append() routine can use fast calling semantics. -*/ -static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ - N = sqlite3StrAccumEnlarge(p, N); - if( N>0 ){ - memcpy(&p->zText[p->nChar], z, N); - p->nChar += N; - } -} - -/* -** Append N bytes of text from z to the StrAccum object. Increase the -** size of the memory allocation for StrAccum if necessary. -*/ -SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ - assert( z!=0 || N==0 ); - assert( p->zText!=0 || p->nChar==0 || p->accError ); - assert( N>=0 ); - assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 ); - if( p->nChar+N >= p->nAlloc ){ - enlargeAndAppend(p,z,N); - }else if( N ){ - assert( p->zText ); - p->nChar += N; - memcpy(&p->zText[p->nChar-N], z, N); - } -} - -/* -** Append the complete text of zero-terminated string z[] to the p string. -*/ -SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ - sqlite3_str_append(p, z, sqlite3Strlen30(z)); -} - - -/* -** Finish off a string by making sure it is zero-terminated. -** Return a pointer to the resulting string. Return a NULL -** pointer if any kind of error was encountered. -*/ -static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ - char *zText; - assert( p->mxAlloc>0 && !isMalloced(p) ); - zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar ); - if( zText ){ - memcpy(zText, p->zText, p->nChar+1); - p->printfFlags |= SQLITE_PRINTF_MALLOCED; - }else{ - sqlite3StrAccumSetError(p, SQLITE_NOMEM); - } - p->zText = zText; - return zText; -} -SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ - if( p->zText ){ - p->zText[p->nChar] = 0; - if( p->mxAlloc>0 && !isMalloced(p) ){ - return strAccumFinishRealloc(p); - } - } - return p->zText; -} - -/* -** Use the content of the StrAccum passed as the second argument -** as the result of an SQL function. -*/ -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){ - if( p->accError ){ - sqlite3_result_error_code(pCtx, p->accError); - sqlite3_str_reset(p); - }else if( isMalloced(p) ){ - sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC); - }else{ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - sqlite3_str_reset(p); - } -} - -/* -** This singleton is an sqlite3_str object that is returned if -** sqlite3_malloc() fails to provide space for a real one. This -** sqlite3_str object accepts no new text and always returns -** an SQLITE_NOMEM error. -*/ -static sqlite3_str sqlite3OomStr = { - 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 -}; - -/* Finalize a string created using sqlite3_str_new(). -*/ -SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ - char *z; - if( p!=0 && p!=&sqlite3OomStr ){ - z = sqlite3StrAccumFinish(p); - sqlite3_free(p); - }else{ - z = 0; - } - return z; -} - -/* Return any error code associated with p */ -SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){ - return p ? p->accError : SQLITE_NOMEM; -} - -/* Return the current length of p in bytes */ -SQLITE_API int sqlite3_str_length(sqlite3_str *p){ - return p ? p->nChar : 0; -} - -/* Return the current value for p */ -SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ - if( p==0 || p->nChar==0 ) return 0; - p->zText[p->nChar] = 0; - return p->zText; -} - -/* -** Reset an StrAccum string. Reclaim all malloced memory. -*/ -SQLITE_API void sqlite3_str_reset(StrAccum *p){ - if( isMalloced(p) ){ - sqlite3DbFree(p->db, p->zText); - p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; - } - p->nAlloc = 0; - p->nChar = 0; - p->zText = 0; -} - -/* -** Initialize a string accumulator. -** -** p: The accumulator to be initialized. -** db: Pointer to a database connection. May be NULL. Lookaside -** memory is used if not NULL. db->mallocFailed is set appropriately -** when not NULL. -** zBase: An initial buffer. May be NULL in which case the initial buffer -** is malloced. -** n: Size of zBase in bytes. If total space requirements never exceed -** n then no memory allocations ever occur. -** mx: Maximum number of bytes to accumulate. If mx==0 then no memory -** allocations will ever occur. -*/ -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ - p->zText = zBase; - p->db = db; - p->nAlloc = n; - p->mxAlloc = mx; - p->nChar = 0; - p->accError = 0; - p->printfFlags = 0; -} - -/* Allocate and initialize a new dynamic string object */ -SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){ - sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); - if( p ){ - sqlite3StrAccumInit(p, 0, 0, 0, - db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); - }else{ - p = &sqlite3OomStr; - } - return p; -} - -/* -** Print into memory obtained from sqliteMalloc(). Use the internal -** %-conversion extensions. -*/ -SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ - char *z; - char zBase[SQLITE_PRINT_BUF_SIZE]; - StrAccum acc; - assert( db!=0 ); - sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), - db->aLimit[SQLITE_LIMIT_LENGTH]); - acc.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_vappendf(&acc, zFormat, ap); - z = sqlite3StrAccumFinish(&acc); - if( acc.accError==SQLITE_NOMEM ){ - sqlite3OomFault(db); - } - return z; -} - -/* -** Print into memory obtained from sqliteMalloc(). Use the internal -** %-conversion extensions. -*/ -SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ - va_list ap; - char *z; - va_start(ap, zFormat); - z = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - return z; -} - -/* -** Print into memory obtained from sqlite3_malloc(). Omit the internal -** %-conversion extensions. -*/ -SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ - char *z; - char zBase[SQLITE_PRINT_BUF_SIZE]; - StrAccum acc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zFormat==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - sqlite3_str_vappendf(&acc, zFormat, ap); - z = sqlite3StrAccumFinish(&acc); - return z; -} - -/* -** Print into memory obtained from sqlite3_malloc()(). Omit the internal -** %-conversion extensions. -*/ -SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ - va_list ap; - char *z; -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - return z; -} - -/* -** sqlite3_snprintf() works like snprintf() except that it ignores the -** current locale settings. This is important for SQLite because we -** are not able to use a "," as the decimal point in place of "." as -** specified by some locales. -** -** Oops: The first two arguments of sqlite3_snprintf() are backwards -** from the snprintf() standard. Unfortunately, it is too late to change -** this without breaking compatibility, so we just have to live with the -** mistake. -** -** sqlite3_vsnprintf() is the varargs version. -*/ -SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ - StrAccum acc; - if( n<=0 ) return zBuf; -#ifdef SQLITE_ENABLE_API_ARMOR - if( zBuf==0 || zFormat==0 ) { - (void)SQLITE_MISUSE_BKPT; - if( zBuf ) zBuf[0] = 0; - return zBuf; - } -#endif - sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); - sqlite3_str_vappendf(&acc, zFormat, ap); - zBuf[acc.nChar] = 0; - return zBuf; -} -SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ - StrAccum acc; - va_list ap; - if( n<=0 ) return zBuf; -#ifdef SQLITE_ENABLE_API_ARMOR - if( zBuf==0 || zFormat==0 ) { - (void)SQLITE_MISUSE_BKPT; - if( zBuf ) zBuf[0] = 0; - return zBuf; - } -#endif - sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); - va_start(ap,zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); - va_end(ap); - zBuf[acc.nChar] = 0; - return zBuf; -} - -/* Maximum size of an sqlite3_log() message. */ -#if defined(SQLITE_MAX_LOG_MESSAGE) - /* Leave the definition as supplied */ -#elif SQLITE_PRINT_BUF_SIZE*10>10000 -# define SQLITE_MAX_LOG_MESSAGE 10000 -#else -# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10) -#endif - -/* -** This is the routine that actually formats the sqlite3_log() message. -** We house it in a separate routine from sqlite3_log() to avoid using -** stack space on small-stack systems when logging is disabled. -** -** sqlite3_log() must render into a static buffer. It cannot dynamically -** allocate memory because it might be called while the memory allocator -** mutex is held. -** -** sqlite3_str_vappendf() might ask for *temporary* memory allocations for -** certain format characters (%q) or for very large precisions or widths. -** Care must be taken that any sqlite3_log() calls that occur while the -** memory mutex is held do not use these mechanisms. -*/ -static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ - StrAccum acc; /* String accumulator */ - char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */ - - sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); - sqlite3_str_vappendf(&acc, zFormat, ap); - sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, - sqlite3StrAccumFinish(&acc)); -} - -/* -** Format and write a message to the log if logging is enabled. -*/ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ - va_list ap; /* Vararg list */ - if( sqlite3GlobalConfig.xLog ){ - va_start(ap, zFormat); - renderLogMsg(iErrCode, zFormat, ap); - va_end(ap); - } -} - -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) -/* -** A version of printf() that understands %lld. Used for debugging. -** The printf() built into some versions of windows does not understand %lld -** and segfaults if you give it a long long int. -*/ -SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ - va_list ap; - StrAccum acc; - char zBuf[SQLITE_PRINT_BUF_SIZE*10]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - va_start(ap,zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); - va_end(ap); - sqlite3StrAccumFinish(&acc); -#ifdef SQLITE_OS_TRACE_PROC - { - extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf); - SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf)); - } -#else - fprintf(stdout,"%s", zBuf); - fflush(stdout); -#endif -} -#endif - - -/* -** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument -** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. -*/ -SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ - va_list ap; - va_start(ap,zFormat); - sqlite3_str_vappendf(p, zFormat, ap); - va_end(ap); -} - - -/***************************************************************************** -** Reference counted string/blob storage -*****************************************************************************/ - -/* -** Increase the reference count of the string by one. -** -** The input parameter is returned. -*/ -SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){ - RCStr *p = (RCStr*)z; - assert( p!=0 ); - p--; - p->nRCRef++; - return z; -} - -/* -** Decrease the reference count by one. Free the string when the -** reference count reaches zero. -*/ -SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){ - RCStr *p = (RCStr*)z; - assert( p!=0 ); - p--; - assert( p->nRCRef>0 ); - if( p->nRCRef>=2 ){ - p->nRCRef--; - }else{ - sqlite3_free(p); - } -} - -/* -** Create a new string that is capable of holding N bytes of text, not counting -** the zero byte at the end. The string is uninitialized. -** -** The reference count is initially 1. Call sqlite3RCStrUnref() to free the -** newly allocated string. -** -** This routine returns 0 on an OOM. -*/ -SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){ - RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 ); - if( p==0 ) return 0; - p->nRCRef = 1; - return (char*)&p[1]; -} - -/* -** Change the size of the string so that it is able to hold N bytes. -** The string might be reallocated, so return the new allocation. -*/ -SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){ - RCStr *p = (RCStr*)z; - RCStr *pNew; - assert( p!=0 ); - p--; - assert( p->nRCRef==1 ); - pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1); - if( pNew==0 ){ - sqlite3_free(p); - return 0; - }else{ - return (char*)&pNew[1]; - } -} - -/************** End of printf.c **********************************************/ -/************** Begin file treeview.c ****************************************/ -/* -** 2015-06-08 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains C code to implement the TreeView debugging routines. -** These routines print a parse tree to standard output for debugging and -** analysis. -** -** The interfaces in this file is only available when compiling -** with SQLITE_DEBUG. -*/ -/* #include "sqliteInt.h" */ -#ifdef SQLITE_DEBUG - -/* -** Add a new subitem to the tree. The moreToFollow flag indicates that this -** is not the last item in the tree. -*/ -static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){ - TreeView *p = *pp; - if( p==0 ){ - *pp = p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return; - memset(p, 0, sizeof(*p)); - }else{ - p->iLevel++; - } - assert( moreToFollow==0 || moreToFollow==1 ); - if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow; -} - -/* -** Finished with one layer of the tree -*/ -static void sqlite3TreeViewPop(TreeView **pp){ - TreeView *p = *pp; - if( p==0 ) return; - p->iLevel--; - if( p->iLevel<0 ){ - sqlite3_free(p); - *pp = 0; - } -} - -/* -** Generate a single line of output for the tree, with a prefix that contains -** all the appropriate tree lines -*/ -SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ - va_list ap; - int i; - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - if( p ){ - for(i=0; iiLevel && i<(int)sizeof(p->bLine)-1; i++){ - sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); - } - sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); - } - if( zFormat!=0 ){ - va_start(ap, zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); - va_end(ap); - assert( acc.nChar>0 || acc.accError ); - sqlite3_str_append(&acc, "\n", 1); - } - sqlite3StrAccumFinish(&acc); - fprintf(stdout,"%s", zBuf); - fflush(stdout); -} - -/* -** Shorthand for starting a new tree item that consists of a single label -*/ -static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ - sqlite3TreeViewPush(&p, moreFollows); - sqlite3TreeViewLine(p, "%s", zLabel); -} - -/* -** Show a list of Column objects in tree format. -*/ -SQLITE_PRIVATE void sqlite3TreeViewColumnList( - TreeView *pView, - const Column *aCol, - int nCol, - u8 moreToFollow -){ - int i; - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewLine(pView, "COLUMNS"); - for(i=0; inCte==0 ) return; - if( pWith->pOuter ){ - sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter); - }else{ - sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith); - } - if( pWith->nCte>0 ){ - sqlite3TreeViewPush(&pView, moreToFollow); - for(i=0; inCte; i++){ - StrAccum x; - char zLine[1000]; - const struct Cte *pCte = &pWith->a[i]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3_str_appendf(&x, "%s", pCte->zName); - if( pCte->pCols && pCte->pCols->nExpr>0 ){ - char cSep = '('; - int j; - for(j=0; jpCols->nExpr; j++){ - sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName); - cSep = ','; - } - sqlite3_str_appendf(&x, ")"); - } - if( pCte->eM10d!=M10d_Any ){ - sqlite3_str_appendf(&x, " %sMATERIALIZED", - pCte->eM10d==M10d_No ? "NOT " : ""); - } - if( pCte->pUse ){ - sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse, - pCte->pUse->nUse); - } - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, inCte-1); - sqlite3TreeViewSelect(pView, pCte->pSelect, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); - } -} - -/* -** Generate a human-readable description of a SrcList object. -*/ -SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ - int i; - if( pSrc==0 ) return; - for(i=0; inSrc; i++){ - const SrcItem *pItem = &pSrc->a[i]; - StrAccum x; - int n = 0; - char zLine[1000]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - x.printfFlags |= SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); - if( pItem->pSTab ){ - sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s", - pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab, - pItem->colUsed, - pItem->fg.rowidUsed ? "+rowid" : ""); - } - if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ - sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); - }else if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&x, " LEFT-JOIN"); - }else if( pItem->fg.jointype & JT_RIGHT ){ - sqlite3_str_appendf(&x, " RIGHT-JOIN"); - }else if( pItem->fg.jointype & JT_CROSS ){ - sqlite3_str_appendf(&x, " CROSS-JOIN"); - } - if( pItem->fg.jointype & JT_LTORJ ){ - sqlite3_str_appendf(&x, " LTORJ"); - } - if( pItem->fg.fromDDL ){ - sqlite3_str_appendf(&x, " DDL"); - } - if( pItem->fg.isCte ){ - static const char *aMat[] = {",MAT", "", ",NO-MAT"}; - sqlite3_str_appendf(&x, " CteUse=%d%s", - pItem->u2.pCteUse->nUse, - aMat[pItem->u2.pCteUse->eM10d]); - } - if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){ - sqlite3_str_appendf(&x, " isOn"); - } - if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc"); - if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated"); - if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized"); - if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine"); - if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte"); - if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom"); - if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema"); - if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema"); - if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery"); - - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, inSrc-1); - n = 0; - if( pItem->fg.isSubquery ) n++; - if( pItem->fg.isTabFunc ) n++; - if( pItem->fg.isUsing ) n++; - if( pItem->fg.isUsing ){ - sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); - } - if( pItem->fg.isSubquery ){ - assert( n==1 ); - if( pItem->pSTab ){ - Table *pTab = pItem->pSTab; - sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); - } - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) ); - sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0); - } - if( pItem->fg.isTabFunc ){ - sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); - } - sqlite3TreeViewPop(&pView); - } -} - -/* -** Generate a human-readable description of a Select object. -*/ -SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ - int n = 0; - int cnt = 0; - if( p==0 ){ - sqlite3TreeViewLine(pView, "nil-SELECT"); - return; - } - sqlite3TreeViewPush(&pView, moreToFollow); - if( p->pWith ){ - sqlite3TreeViewWith(pView, p->pWith, 1); - cnt = 1; - sqlite3TreeViewPush(&pView, 1); - } - do{ - if( p->selFlags & SF_WhereBegin ){ - sqlite3TreeViewLine(pView, "sqlite3WhereBegin()"); - }else{ - sqlite3TreeViewLine(pView, - "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d", - ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), - p->selId, p, p->selFlags, - (int)p->nSelectRow - ); - } - if( cnt++ ) sqlite3TreeViewPop(&pView); - if( p->pPrior ){ - n = 1000; - }else{ - n = 0; - if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++; - if( p->pWhere ) n++; - if( p->pGroupBy ) n++; - if( p->pHaving ) n++; - if( p->pOrderBy ) n++; - if( p->pLimit ) n++; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ) n++; - if( p->pWinDefn ) n++; -#endif - } - if( p->pEList ){ - sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set"); - } - n--; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ){ - Window *pX; - sqlite3TreeViewPush(&pView, (n--)>0); - sqlite3TreeViewLine(pView, "window-functions"); - for(pX=p->pWin; pX; pX=pX->pNextWin){ - sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0); - } - sqlite3TreeViewPop(&pView); - } -#endif - if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){ - sqlite3TreeViewPush(&pView, (n--)>0); - sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, p->pSrc); - sqlite3TreeViewPop(&pView); - } - if( p->pWhere ){ - sqlite3TreeViewItem(pView, "WHERE", (n--)>0); - sqlite3TreeViewExpr(pView, p->pWhere, 0); - sqlite3TreeViewPop(&pView); - } - if( p->pGroupBy ){ - sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); - } - if( p->pHaving ){ - sqlite3TreeViewItem(pView, "HAVING", (n--)>0); - sqlite3TreeViewExpr(pView, p->pHaving, 0); - sqlite3TreeViewPop(&pView); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWinDefn ){ - Window *pX; - sqlite3TreeViewItem(pView, "WINDOW", (n--)>0); - for(pX=p->pWinDefn; pX; pX=pX->pNextWin){ - sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0); - } - sqlite3TreeViewPop(&pView); - } -#endif - if( p->pOrderBy ){ - sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); - } - if( p->pLimit ){ - sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); - sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); - if( p->pLimit->pRight ){ - sqlite3TreeViewItem(pView, "OFFSET", 0); - sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); - } - if( p->pPrior ){ - const char *zOp = "UNION"; - switch( p->op ){ - case TK_ALL: zOp = "UNION ALL"; break; - case TK_INTERSECT: zOp = "INTERSECT"; break; - case TK_EXCEPT: zOp = "EXCEPT"; break; - } - sqlite3TreeViewItem(pView, zOp, 1); - } - p = p->pPrior; - }while( p!=0 ); - sqlite3TreeViewPop(&pView); -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a description of starting or stopping bounds -*/ -SQLITE_PRIVATE void sqlite3TreeViewBound( - TreeView *pView, /* View context */ - u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */ - Expr *pExpr, /* Value for PRECEDING or FOLLOWING */ - u8 moreToFollow /* True if more to follow */ -){ - switch( eBound ){ - case TK_UNBOUNDED: { - sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow); - sqlite3TreeViewPop(&pView); - break; - } - case TK_CURRENT: { - sqlite3TreeViewItem(pView, "CURRENT", moreToFollow); - sqlite3TreeViewPop(&pView); - break; - } - case TK_PRECEDING: { - sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow); - sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(&pView); - break; - } - case TK_FOLLOWING: { - sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow); - sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(&pView); - break; - } - } -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a human-readable explanation for a Window object -*/ -SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ - int nElement = 0; - if( pWin==0 ) return; - if( pWin->pFilter ){ - sqlite3TreeViewItem(pView, "FILTER", 1); - sqlite3TreeViewExpr(pView, pWin->pFilter, 0); - sqlite3TreeViewPop(&pView); - if( pWin->eFrmType==TK_FILTER ) return; - } - sqlite3TreeViewPush(&pView, more); - if( pWin->zName ){ - sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin); - }else{ - sqlite3TreeViewLine(pView, "OVER (%p)", pWin); - } - if( pWin->zBase ) nElement++; - if( pWin->pOrderBy ) nElement++; - if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++; - if( pWin->eExclude ) nElement++; - if( pWin->zBase ){ - sqlite3TreeViewPush(&pView, (--nElement)>0); - sqlite3TreeViewLine(pView, "window: %s", pWin->zBase); - sqlite3TreeViewPop(&pView); - } - if( pWin->pPartition ){ - sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY"); - } - if( pWin->pOrderBy ){ - sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); - } - if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){ - char zBuf[30]; - const char *zFrmType = "ROWS"; - if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; - if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS"; - sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType, - pWin->bImplicitFrame ? " (implied)" : ""); - sqlite3TreeViewItem(pView, zBuf, (--nElement)>0); - sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); - sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); - sqlite3TreeViewPop(&pView); - } - if( pWin->eExclude ){ - char zBuf[30]; - const char *zExclude; - switch( pWin->eExclude ){ - case TK_NO: zExclude = "NO OTHERS"; break; - case TK_CURRENT: zExclude = "CURRENT ROW"; break; - case TK_GROUP: zExclude = "GROUP"; break; - case TK_TIES: zExclude = "TIES"; break; - default: - sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude); - zExclude = zBuf; - break; - } - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a human-readable explanation for a Window Function object -*/ -SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){ - if( pWin==0 ) return; - sqlite3TreeViewPush(&pView, more); - sqlite3TreeViewLine(pView, "WINFUNC %s(%d)", - pWin->pWFunc->zName, pWin->pWFunc->nArg); - sqlite3TreeViewWindow(pView, pWin, 0); - sqlite3TreeViewPop(&pView); -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** Generate a human-readable explanation of an expression tree. -*/ -SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ - const char *zBinOp = 0; /* Binary operator */ - const char *zUniOp = 0; /* Unary operator */ - char zFlgs[200]; - sqlite3TreeViewPush(&pView, moreToFollow); - if( pExpr==0 ){ - sqlite3TreeViewLine(pView, "nil"); - sqlite3TreeViewPop(&pView); - return; - } - if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){ - StrAccum x; - sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0); - sqlite3_str_appendf(&x, " fg.af=%x.%c", - pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n'); - if( ExprHasProperty(pExpr, EP_OuterON) ){ - sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin); - } - if( ExprHasProperty(pExpr, EP_InnerON) ){ - sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin); - } - if( ExprHasProperty(pExpr, EP_FromDDL) ){ - sqlite3_str_appendf(&x, " DDL"); - } - if( ExprHasVVAProperty(pExpr, EP_Immutable) ){ - sqlite3_str_appendf(&x, " IMMUTABLE"); - } - if( pExpr->pAggInfo!=0 ){ - sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg); - } - sqlite3StrAccumFinish(&x); - }else{ - zFlgs[0] = 0; - } - switch( pExpr->op ){ - case TK_AGG_COLUMN: { - sqlite3TreeViewLine(pView, "AGG{%d:%d}%s", - pExpr->iTable, pExpr->iColumn, zFlgs); - break; - } - case TK_COLUMN: { - if( pExpr->iTable<0 ){ - /* This only happens when coding check constraints */ - char zOp2[16]; - if( pExpr->op2 ){ - sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2); - }else{ - zOp2[0] = 0; - } - sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s", - pExpr->iColumn, zFlgs, zOp2); - }else{ - assert( ExprUseYTab(pExpr) ); - sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s", - pExpr->iTable, pExpr->iColumn, - pExpr->y.pTab, zFlgs); - } - if( ExprHasProperty(pExpr, EP_FixedCol) ){ - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - } - break; - } - case TK_INTEGER: { - if( pExpr->flags & EP_IntValue ){ - sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue); - }else{ - sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken); - } - break; - } -#ifndef SQLITE_OMIT_FLOATING_POINT - case TK_FLOAT: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_STRING: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken); - break; - } - case TK_NULL: { - sqlite3TreeViewLine(pView,"NULL"); - break; - } - case TK_TRUEFALSE: { - sqlite3TreeViewLine(pView,"%s%s", - sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs); - break; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_VARIABLE: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)", - pExpr->u.zToken, pExpr->iColumn); - break; - } - case TK_REGISTER: { - sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable); - break; - } - case TK_ID: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - 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) ); - sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } -#endif /* SQLITE_OMIT_CAST */ - case TK_LT: zBinOp = "LT"; break; - case TK_LE: zBinOp = "LE"; break; - case TK_GT: zBinOp = "GT"; break; - case TK_GE: zBinOp = "GE"; break; - case TK_NE: zBinOp = "NE"; break; - case TK_EQ: zBinOp = "EQ"; break; - case TK_IS: zBinOp = "IS"; break; - case TK_ISNOT: zBinOp = "ISNOT"; break; - case TK_AND: zBinOp = "AND"; break; - case TK_OR: zBinOp = "OR"; break; - case TK_PLUS: zBinOp = "ADD"; break; - case TK_STAR: zBinOp = "MUL"; break; - case TK_MINUS: zBinOp = "SUB"; break; - case TK_REM: zBinOp = "REM"; break; - case TK_BITAND: zBinOp = "BITAND"; break; - case TK_BITOR: zBinOp = "BITOR"; break; - case TK_SLASH: zBinOp = "DIV"; break; - case TK_LSHIFT: zBinOp = "LSHIFT"; break; - case TK_RSHIFT: zBinOp = "RSHIFT"; break; - case TK_CONCAT: zBinOp = "CONCAT"; break; - case TK_DOT: zBinOp = "DOT"; break; - case TK_LIMIT: zBinOp = "LIMIT"; break; - - case TK_UMINUS: zUniOp = "UMINUS"; break; - case TK_UPLUS: zUniOp = "UPLUS"; break; - case TK_BITNOT: zUniOp = "BITNOT"; break; - case TK_NOT: zUniOp = "NOT"; break; - case TK_ISNULL: zUniOp = "ISNULL"; break; - case TK_NOTNULL: zUniOp = "NOTNULL"; break; - - case TK_TRUTH: { - int x; - const char *azOp[] = { - "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" - }; - assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); - assert( pExpr->pRight ); - assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op - == TK_TRUEFALSE ); - x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); - zUniOp = azOp[x]; - break; - } - - case TK_SPAN: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } - - case TK_COLLATE: { - /* COLLATE operators without the EP_Collate flag are intended to - ** emulate collation associated with a table column. These show - ** 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) ); - sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s", - !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "", - pExpr->u.zToken, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } - - case TK_AGG_FUNCTION: - case TK_FUNCTION: { - ExprList *pFarg; /* List of function arguments */ - Window *pWin; - if( ExprHasProperty(pExpr, EP_TokenOnly) ){ - pFarg = 0; - pWin = 0; - }else{ - assert( ExprUseXList(pExpr) ); - pFarg = pExpr->x.pList; -#ifndef SQLITE_OMIT_WINDOWFUNC - pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0; -#else - pWin = 0; -#endif - } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - if( pExpr->op==TK_AGG_FUNCTION ){ - sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p", - pExpr->op2, pExpr->u.zToken, zFlgs, - pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0, - pExpr->iAgg, pExpr->pAggInfo); - }else if( pExpr->op2!=0 ){ - const char *zOp2; - char zBuf[8]; - sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2); - zOp2 = zBuf; - if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck"; - if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr"; - if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx"; - if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol"; - sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s", - pExpr->u.zToken, zFlgs, zOp2); - }else{ - sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); - } - if( pFarg ){ - sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0); - if( pExpr->pLeft ){ - Expr *pOB = pExpr->pLeft; - assert( pOB->op==TK_ORDER ); - assert( ExprUseXList(pOB) ); - sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY"); - } - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ - sqlite3TreeViewWindow(pView, pWin, 0); - } -#endif - break; - } - case TK_ORDER: { - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY"); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: { - assert( ExprUseXSelect(pExpr) ); - sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags); - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - break; - } - case TK_SELECT: { - assert( ExprUseXSelect(pExpr) ); - sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags); - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - break; - } - case TK_IN: { - sqlite3_str *pStr = sqlite3_str_new(0); - char *z; - sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags); - if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable); - if( ExprHasProperty(pExpr, EP_Subrtn) ){ - sqlite3_str_appendf(pStr, " subrtn(%d,%d)", - pExpr->y.sub.regReturn, pExpr->y.sub.iAddr); - } - z = sqlite3_str_finish(pStr); - sqlite3TreeViewLine(pView, z); - sqlite3_free(z); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - if( ExprUseXSelect(pExpr) ){ - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - }else{ - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); - } - break; - } -#endif /* SQLITE_OMIT_SUBQUERY */ - - /* - ** x BETWEEN y AND z - ** - ** This is equivalent to - ** - ** x>=y AND x<=z - ** - ** X is stored in pExpr->pLeft. - ** Y is stored in pExpr->pList->a[0].pExpr. - ** Z is stored in pExpr->pList->a[1].pExpr. - */ - case TK_BETWEEN: { - 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; - sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs); - sqlite3TreeViewExpr(pView, pX, 1); - sqlite3TreeViewExpr(pView, pY, 1); - sqlite3TreeViewExpr(pView, pZ, 0); - break; - } - case TK_TRIGGER: { - /* If the opcode is TK_TRIGGER, then the expression is a reference - ** to a column in the new.* or old.* pseudo-tables available to - ** trigger programs. In this case Expr.iTable is set to 1 for the - ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn - ** is set to the column of the pseudo-table to read, or to -1 to - ** read the rowid field. - */ - sqlite3TreeViewLine(pView, "%s(%d)", - pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); - break; - } - case TK_CASE: { - sqlite3TreeViewLine(pView, "CASE"); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - assert( ExprUseXList(pExpr) ); - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); - break; - } -#ifndef SQLITE_OMIT_TRIGGER - case TK_RAISE: { - const char *zType = "unk"; - switch( pExpr->affExpr ){ - case OE_Rollback: zType = "rollback"; break; - case OE_Abort: zType = "abort"; break; - case OE_Fail: zType = "fail"; break; - case OE_Ignore: zType = "ignore"; break; - } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView, "RAISE %s", zType); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } -#endif - case TK_MATCH: { - sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s", - pExpr->iTable, pExpr->iColumn, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pRight, 0); - break; - } - case TK_VECTOR: { - char *z = sqlite3_mprintf("VECTOR%s",zFlgs); - assert( ExprUseXList(pExpr) ); - sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z); - sqlite3_free(z); - break; - } - case TK_SELECT_COLUMN: { - sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s", - pExpr->iColumn, pExpr->iTable-1, - pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : ""); - assert( ExprUseXSelect(pExpr->pLeft) ); - sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); - break; - } - case TK_IF_NULL_ROW: { - sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } - case TK_ERROR: { - Expr tmp; - sqlite3TreeViewLine(pView, "ERROR"); - tmp = *pExpr; - tmp.op = pExpr->op2; - sqlite3TreeViewExpr(pView, &tmp, 0); - break; - } - case TK_ROW: { - if( pExpr->iColumn<=0 ){ - sqlite3TreeViewLine(pView, "First FROM table rowid"); - }else{ - sqlite3TreeViewLine(pView, "First FROM table column %d", - pExpr->iColumn-1); - } - break; - } - default: { - sqlite3TreeViewLine(pView, "op=%d", pExpr->op); - break; - } - } - if( zBinOp ){ - sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - sqlite3TreeViewExpr(pView, pExpr->pRight, 0); - }else if( zUniOp ){ - sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - } - sqlite3TreeViewPop(&pView); -} - - -/* -** Generate a human-readable explanation of an expression list. -*/ -SQLITE_PRIVATE void sqlite3TreeViewBareExprList( - TreeView *pView, - const ExprList *pList, - const char *zLabel -){ - if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; - if( pList==0 ){ - sqlite3TreeViewLine(pView, "%s (empty)", zLabel); - }else{ - int i; - sqlite3TreeViewLine(pView, "%s", zLabel); - for(i=0; inExpr; i++){ - int j = pList->a[i].u.x.iOrderByCol; - u8 sortFlags = pList->a[i].fg.sortFlags; - char *zName = pList->a[i].zEName; - int moreToFollow = inExpr - 1; - if( j || zName || sortFlags ){ - sqlite3TreeViewPush(&pView, moreToFollow); - moreToFollow = 0; - sqlite3TreeViewLine(pView, 0); - if( 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); - } - if( sortFlags & KEYINFO_ORDER_DESC ){ - fprintf(stdout, "DESC "); - }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){ - fprintf(stdout, "NULLS-LAST"); - } - fprintf(stdout, "\n"); - fflush(stdout); - } - sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); - if( j || zName || sortFlags ){ - sqlite3TreeViewPop(&pView); - } - } - } -} -SQLITE_PRIVATE void sqlite3TreeViewExprList( - TreeView *pView, - const ExprList *pList, - u8 moreToFollow, - const char *zLabel -){ - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewBareExprList(pView, pList, zLabel); - sqlite3TreeViewPop(&pView); -} - -/* -** Generate a human-readable explanation of an id-list. -*/ -SQLITE_PRIVATE void sqlite3TreeViewBareIdList( - TreeView *pView, - const IdList *pList, - const char *zLabel -){ - if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; - if( pList==0 ){ - sqlite3TreeViewLine(pView, "%s (empty)", zLabel); - }else{ - int i; - sqlite3TreeViewLine(pView, "%s", zLabel); - for(i=0; inId; i++){ - char *zName = pList->a[i].zName; - int moreToFollow = inId - 1; - if( zName==0 ) zName = "(null)"; - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewLine(pView, 0); - fprintf(stdout, "%s\n", zName); - sqlite3TreeViewPop(&pView); - } - } -} -SQLITE_PRIVATE void sqlite3TreeViewIdList( - TreeView *pView, - const IdList *pList, - u8 moreToFollow, - const char *zLabel -){ - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewBareIdList(pView, pList, zLabel); - sqlite3TreeViewPop(&pView); -} - -/* -** Generate a human-readable explanation of a list of Upsert objects -*/ -SQLITE_PRIVATE void sqlite3TreeViewUpsert( - TreeView *pView, - const Upsert *pUpsert, - u8 moreToFollow -){ - if( pUpsert==0 ) return; - sqlite3TreeViewPush(&pView, moreToFollow); - while( pUpsert ){ - int n; - sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow); - sqlite3TreeViewLine(pView, "ON CONFLICT DO %s", - pUpsert->isDoUpdate ? "UPDATE" : "NOTHING"); - n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0); - sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET"); - sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET"); - if( pUpsert->pUpsertWhere ){ - sqlite3TreeViewItem(pView, "WHERE", (n--)>0); - sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); - pUpsert = pUpsert->pNextUpsert; - } - sqlite3TreeViewPop(&pView); -} - -#if TREETRACE_ENABLED -/* -** Generate a human-readable diagram of the data structure that go -** into generating an DELETE statement. -*/ -SQLITE_PRIVATE void 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; - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "DELETE"); - if( pWith ) n++; - if( pTabList ) n++; - if( pWhere ) n++; - if( pOrderBy ) n++; - if( pLimit ) n++; - if( pTrigger ) n++; - if( pWith ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pWhere ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "WHERE"); - sqlite3TreeViewExpr(pView, pWhere, 0); - sqlite3TreeViewPop(&pView); - } - if( pOrderBy ){ - sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); - } - if( pLimit ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "LIMIT"); - sqlite3TreeViewExpr(pView, pLimit, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - 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 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; - } - sqlite3TreeViewPush(&pView, 0); - 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 ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "INTO"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pColumnList ){ - sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS"); - } - if( pSelect ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "DATA-SOURCE"); - sqlite3TreeViewSelect(pView, pSelect, 0); - sqlite3TreeViewPop(&pView); - } - if( pExprList ){ - sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES"); - } - if( pUpsert ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "UPSERT"); - sqlite3TreeViewUpsert(pView, pUpsert, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - 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 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; - } - sqlite3TreeViewPush(&pView, 0); - 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 ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pChanges ){ - sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET"); - } - if( pWhere ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "WHERE"); - sqlite3TreeViewExpr(pView, pWhere, 0); - sqlite3TreeViewPop(&pView); - } - if( pOrderBy ){ - sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); - } - if( pLimit ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "LIMIT"); - sqlite3TreeViewExpr(pView, pLimit, 0); - sqlite3TreeViewPop(&pView); - } - if( pUpsert ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "UPSERT"); - sqlite3TreeViewUpsert(pView, pUpsert, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - sqlite3TreeViewPop(&pView); -} -#endif /* TREETRACE_ENABLED */ - -#ifndef SQLITE_OMIT_TRIGGER -/* -** Show a human-readable graph of a TriggerStep -*/ -SQLITE_PRIVATE void sqlite3TreeViewTriggerStep( - TreeView *pView, - const TriggerStep *pStep, - u8 moreToFollow, - u8 showFullList -){ - int cnt = 0; - if( pStep==0 ) return; - sqlite3TreeViewPush(&pView, - moreToFollow || (showFullList && pStep->pNext!=0)); - do{ - if( cnt++ && pStep->pNext==0 ){ - sqlite3TreeViewPop(&pView); - sqlite3TreeViewPush(&pView, 0); - } - sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING"); - }while( showFullList && (pStep = pStep->pNext)!=0 ); - sqlite3TreeViewPop(&pView); -} - -/* -** Show a human-readable graph of a Trigger -*/ -SQLITE_PRIVATE void sqlite3TreeViewTrigger( - TreeView *pView, - const Trigger *pTrigger, - u8 moreToFollow, - u8 showFullList -){ - int cnt = 0; - if( pTrigger==0 ) return; - sqlite3TreeViewPush(&pView, - moreToFollow || (showFullList && pTrigger->pNext!=0)); - do{ - if( cnt++ && pTrigger->pNext==0 ){ - sqlite3TreeViewPop(&pView); - sqlite3TreeViewPush(&pView, 0); - } - sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName); - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1); - sqlite3TreeViewPop(&pView); - }while( showFullList && (pTrigger = pTrigger->pNext)!=0 ); - 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. -** -** See Also: -** -** sqlite3ShowWhereTerm() in where.c -*/ -SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);} -SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); } -SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); } -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){ - sqlite3TreeViewTriggerStep(0,p,0,0); -} -SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){ - sqlite3TreeViewTriggerStep(0,p,0,1); -} -SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);} -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); } -#endif - -#endif /* SQLITE_DEBUG */ - -/************** End of treeview.c ********************************************/ -/************** Begin file random.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code to implement a pseudo-random number -** generator (PRNG) for SQLite. -** -** Random numbers are used by some of the database backends in order -** to generate random integer keys for tables or random filenames. -*/ -/* #include "sqliteInt.h" */ - - -/* All threads share a single random number generator. -** This structure is the current state of the generator. -*/ -static SQLITE_WSD struct sqlite3PrngType { - u32 s[16]; /* 64 bytes of chacha20 state */ - u8 out[64]; /* Output bytes */ - u8 n; /* Output bytes remaining */ -} sqlite3Prng; - - -/* The RFC-7539 ChaCha20 block function -*/ -#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) -#define QR(a, b, c, d) ( \ - a += b, d ^= a, d = ROTL(d,16), \ - c += d, b ^= c, b = ROTL(b,12), \ - a += b, d ^= a, d = ROTL(d, 8), \ - c += d, b ^= c, b = ROTL(b, 7)) -static void chacha_block(u32 *out, const u32 *in){ - int i; - u32 x[16]; - memcpy(x, in, 64); - for(i=0; i<10; i++){ - QR(x[0], x[4], x[ 8], x[12]); - QR(x[1], x[5], x[ 9], x[13]); - QR(x[2], x[6], x[10], x[14]); - QR(x[3], x[7], x[11], x[15]); - QR(x[0], x[5], x[10], x[15]); - QR(x[1], x[6], x[11], x[12]); - QR(x[2], x[7], x[ 8], x[13]); - QR(x[3], x[4], x[ 9], x[14]); - } - for(i=0; i<16; i++) out[i] = x[i]+in[i]; -} - -/* -** Return N random bytes. -*/ -SQLITE_API void sqlite3_randomness(int N, void *pBuf){ - unsigned char *zBuf = pBuf; - - /* The "wsdPrng" macro will resolve to the pseudo-random number generator - ** state vector. If writable static data is unsupported on the target, - ** we have to locate the state vector at run-time. In the more common - ** case where writable static data is supported, wsdPrng can refer directly - ** to the "sqlite3Prng" state vector declared above. - */ -#ifdef SQLITE_OMIT_WSD - struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng); -# define wsdPrng p[0] -#else -# define wsdPrng sqlite3Prng -#endif - -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex; -#endif - -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return; -#endif - -#if SQLITE_THREADSAFE - mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); -#endif - - sqlite3_mutex_enter(mutex); - if( N<=0 || pBuf==0 ){ - wsdPrng.s[0] = 0; - sqlite3_mutex_leave(mutex); - return; - } - - /* Initialize the state of the random number generator once, - ** the first time this routine is called. - */ - if( wsdPrng.s[0]==0 ){ - sqlite3_vfs *pVfs = sqlite3_vfs_find(0); - static const u32 chacha20_init[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - memcpy(&wsdPrng.s[0], chacha20_init, 16); - if( NEVER(pVfs==0) ){ - memset(&wsdPrng.s[4], 0, 44); - }else{ - sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]); - } - wsdPrng.s[15] = wsdPrng.s[12]; - wsdPrng.s[12] = 0; - wsdPrng.n = 0; - } - - assert( N>0 ); - while( 1 /* exit by break */ ){ - if( N<=wsdPrng.n ){ - memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N); - wsdPrng.n -= N; - break; - } - if( wsdPrng.n>0 ){ - memcpy(zBuf, wsdPrng.out, wsdPrng.n); - N -= wsdPrng.n; - zBuf += wsdPrng.n; - } - wsdPrng.s[12]++; - chacha_block((u32*)wsdPrng.out, wsdPrng.s); - wsdPrng.n = 64; - } - sqlite3_mutex_leave(mutex); -} - -#ifndef SQLITE_UNTESTABLE -/* -** For testing purposes, we sometimes want to preserve the state of -** PRNG and restore the PRNG to its saved state at a later time, or -** to reset the PRNG to its initial state. These routines accomplish -** those tasks. -** -** The sqlite3_test_control() interface calls these routines to -** control the PRNG. -*/ -static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng; -SQLITE_PRIVATE void sqlite3PrngSaveState(void){ - memcpy( - &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), - &GLOBAL(struct sqlite3PrngType, sqlite3Prng), - sizeof(sqlite3Prng) - ); -} -SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ - memcpy( - &GLOBAL(struct sqlite3PrngType, sqlite3Prng), - &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), - sizeof(sqlite3Prng) - ); -} -#endif /* SQLITE_UNTESTABLE */ - -/************** End of random.c **********************************************/ -/************** Begin file threads.c *****************************************/ -/* -** 2012 July 21 -** -** 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 presents a simple cross-platform threading interface for -** use internally by SQLite. -** -** A "thread" can be created using sqlite3ThreadCreate(). This thread -** runs independently of its creator until it is joined using -** sqlite3ThreadJoin(), at which point it terminates. -** -** Threads do not have to be real. It could be that the work of the -** "thread" is done by the main thread at either the sqlite3ThreadCreate() -** or sqlite3ThreadJoin() call. This is, in fact, what happens in -** single threaded systems. Nothing in SQLite requires multiple threads. -** This interface exists so that applications that want to take advantage -** of multiple cores can do so, while also allowing applications to stay -** single-threaded if desired. -*/ -/* #include "sqliteInt.h" */ -#if SQLITE_OS_WIN -/* # include "os_win.h" */ -#endif - -#if SQLITE_MAX_WORKER_THREADS>0 - -/********************************* Unix Pthreads ****************************/ -#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 - -#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ -/* #include */ - -/* A running thread */ -struct SQLiteThread { - pthread_t tid; /* Thread ID */ - int done; /* Set to true when thread finishes */ - void *pOut; /* Result returned by the thread */ - void *(*xTask)(void*); /* The thread routine */ - void *pIn; /* Argument to the thread */ -}; - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - int rc; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - /* This routine is never used in single-threaded mode */ - assert( sqlite3GlobalConfig.bCoreMutex!=0 ); - - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM_BKPT; - memset(p, 0, sizeof(*p)); - p->xTask = xTask; - p->pIn = pIn; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a - ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically - ** for testing purposes. */ - if( sqlite3FaultSim(200) ){ - rc = 1; - }else{ - rc = pthread_create(&p->tid, 0, xTask, pIn); - } - if( rc ){ - p->done = 1; - p->pOut = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - int rc; - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; - if( p->done ){ - *ppOut = p->pOut; - rc = SQLITE_OK; - }else{ - rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK; - } - sqlite3_free(p); - return rc; -} - -#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ -/******************************** End Unix Pthreads *************************/ - - -/********************************* Win32 Threads ****************************/ -#if SQLITE_OS_WIN_THREADS - -#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ -#include - -/* A running thread */ -struct SQLiteThread { - void *tid; /* The thread handle */ - unsigned id; /* The thread identifier */ - void *(*xTask)(void*); /* The routine to run as a thread */ - void *pIn; /* Argument to xTask */ - void *pResult; /* Result of xTask */ -}; - -/* Thread procedure Win32 compatibility shim */ -static unsigned __stdcall sqlite3ThreadProc( - void *pArg /* IN: Pointer to the SQLiteThread structure */ -){ - SQLiteThread *p = (SQLiteThread *)pArg; - - assert( p!=0 ); -#if 0 - /* - ** This assert appears to trigger spuriously on certain - ** versions of Windows, possibly due to _beginthreadex() - ** and/or CreateThread() not fully setting their thread - ** ID parameter before starting the thread. - */ - assert( p->id==GetCurrentThreadId() ); -#endif - assert( p->xTask!=0 ); - p->pResult = p->xTask(p->pIn); - - _endthreadex(0); - return 0; /* NOT REACHED */ -} - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM_BKPT; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a - ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically - ** (via the sqlite3FaultSim() term of the conditional) for testing - ** purposes. */ - if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){ - memset(p, 0, sizeof(*p)); - }else{ - p->xTask = xTask; - p->pIn = pIn; - p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); - if( p->tid==0 ){ - memset(p, 0, sizeof(*p)); - } - } - if( p->xTask==0 ){ - p->id = GetCurrentThreadId(); - p->pResult = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - DWORD rc; - BOOL bRc; - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; - if( p->xTask==0 ){ - /* assert( p->id==GetCurrentThreadId() ); */ - rc = WAIT_OBJECT_0; - assert( p->tid==0 ); - }else{ - assert( p->id!=0 && p->id!=GetCurrentThreadId() ); - rc = sqlite3Win32Wait((HANDLE)p->tid); - assert( rc!=WAIT_IO_COMPLETION ); - bRc = CloseHandle((HANDLE)p->tid); - assert( bRc ); - } - if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; - sqlite3_free(p); - return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; -} - -#endif /* SQLITE_OS_WIN_THREADS */ -/******************************** End Win32 Threads *************************/ - - -/********************************* Single-Threaded **************************/ -#ifndef SQLITE_THREADS_IMPLEMENTED -/* -** This implementation does not actually create a new thread. It does the -** work of the thread in the main thread, when either the thread is created -** or when it is joined -*/ - -/* A running thread */ -struct SQLiteThread { - void *(*xTask)(void*); /* The routine to run as a thread */ - void *pIn; /* Argument to xTask */ - void *pResult; /* Result of xTask */ -}; - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM_BKPT; - if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ - p->xTask = xTask; - p->pIn = pIn; - }else{ - p->xTask = 0; - p->pResult = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT; - if( p->xTask ){ - *ppOut = p->xTask(p->pIn); - }else{ - *ppOut = p->pResult; - } - sqlite3_free(p); - -#if defined(SQLITE_TEST) - { - void *pTstAlloc = sqlite3Malloc(10); - if (!pTstAlloc) return SQLITE_NOMEM_BKPT; - sqlite3_free(pTstAlloc); - } -#endif - - return SQLITE_OK; -} - -#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ -/****************************** End Single-Threaded *************************/ -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - -/************** End of threads.c *********************************************/ -/************** Begin file utf.c *********************************************/ -/* -** 2004 April 13 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains routines used to translate between UTF-8, -** UTF-16, UTF-16BE, and UTF-16LE. -** -** Notes on UTF-8: -** -** Byte-0 Byte-1 Byte-2 Byte-3 Value -** 0xxxxxxx 00000000 00000000 0xxxxxxx -** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx -** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx -** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx -** -** -** Notes on UTF-16: (with wwww+1==uuuuu) -** -** Word-0 Word-1 Value -** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx -** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx -** -** -** BOM or Byte Order Mark: -** 0xff 0xfe little-endian utf-16 follows -** 0xfe 0xff big-endian utf-16 follows -** -*/ -/* #include "sqliteInt.h" */ -/* #include */ -/* #include "vdbeInt.h" */ - -#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0 -/* -** The following constant value is used by the SQLITE_BIGENDIAN and -** SQLITE_LITTLEENDIAN macros. -*/ -SQLITE_PRIVATE const int sqlite3one = 1; -#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */ - -/* -** This lookup table is used to help decode the first byte of -** a multi-byte UTF8 character. -*/ -static const unsigned char sqlite3Utf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - - -#define WRITE_UTF8(zOut, c) { \ - if( c<0x00080 ){ \ - *zOut++ = (u8)(c&0xFF); \ - } \ - else if( c<0x00800 ){ \ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ - else if( c<0x10000 ){ \ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - }else{ \ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ -} - -#define WRITE_UTF16LE(zOut, c) { \ - if( c<=0xFFFF ){ \ - *zOut++ = (u8)(c&0x00FF); \ - *zOut++ = (u8)((c>>8)&0x00FF); \ - }else{ \ - *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ - *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \ - *zOut++ = (u8)(c&0x00FF); \ - *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ - } \ -} - -#define WRITE_UTF16BE(zOut, c) { \ - if( c<=0xFFFF ){ \ - *zOut++ = (u8)((c>>8)&0x00FF); \ - *zOut++ = (u8)(c&0x00FF); \ - }else{ \ - *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \ - *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ - *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ - *zOut++ = (u8)(c&0x00FF); \ - } \ -} - -/* -** Write a single UTF8 character whose value is v into the -** buffer starting at zOut. zOut must be sized to hold at -** least four bytes. Return the number of bytes needed -** to encode the new character. -*/ -SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){ - if( v<0x00080 ){ - zOut[0] = (u8)(v & 0xff); - return 1; - } - if( v<0x00800 ){ - zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f); - zOut[1] = 0x80 + (u8)(v & 0x3f); - return 2; - } - if( v<0x10000 ){ - zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f); - zOut[1] = 0x80 + (u8)((v>>6) & 0x3f); - zOut[2] = 0x80 + (u8)(v & 0x3f); - return 3; - } - zOut[0] = 0xf0 + (u8)((v>>18) & 0x07); - zOut[1] = 0x80 + (u8)((v>>12) & 0x3f); - zOut[2] = 0x80 + (u8)((v>>6) & 0x3f); - zOut[3] = 0x80 + (u8)(v & 0x3f); - return 4; -} - -/* -** Translate a single UTF-8 character. Return the unicode value. -** -** During translation, assume that the byte that zTerm points -** is a 0x00. -** -** Write a pointer to the next unread byte back into *pzNext. -** -** Notes On Invalid UTF-8: -** -** * This routine never allows a 7-bit character (0x00 through 0x7f) to -** be encoded as a multi-byte character. Any multi-byte character that -** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. -** -** * This routine never allows a UTF16 surrogate value to be encoded. -** If a multi-byte character attempts to encode a value between -** 0xd800 and 0xe000 then it is rendered as 0xfffd. -** -** * Bytes in the range of 0x80 through 0xbf which occur as the first -** byte of a character are interpreted as single-byte characters -** and rendered as themselves even though they are technically -** invalid characters. -** -** * This routine accepts over-length UTF8 encodings -** for unicode values 0x80 and greater. It does not change over-length -** encodings to 0xfffd as some systems recommend. -*/ -#define READ_UTF8(zIn, zTerm, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn=0xc0 ){ - c = sqlite3Utf8Trans1[c-0xc0]; - while( (*(*pz) & 0xc0)==0x80 ){ - c = (c<<6) + (0x3f & *((*pz)++)); - } - if( c<0x80 - || (c&0xFFFFF800)==0xD800 - || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } - } - return c; -} - -/* -** Read a single UTF8 character out of buffer z[], but reading no -** more than n characters from the buffer. z[] is not zero-terminated. -** -** Return the number of bytes used to construct the character. -** -** Invalid UTF8 might generate a strange result. No effort is made -** to detect invalid UTF8. -** -** At most 4 bytes will be read out of z[]. The return value will always -** be between 1 and 4. -*/ -SQLITE_PRIVATE int sqlite3Utf8ReadLimited( - const u8 *z, - int n, - u32 *piOut -){ - u32 c; - int i = 1; - assert( n>0 ); - c = z[0]; - if( c>=0xc0 ){ - c = sqlite3Utf8Trans1[c-0xc0]; - if( n>4 ) n = 4; - while( idb==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( pMem->flags&MEM_Str ); - assert( pMem->enc!=desiredEnc ); - assert( pMem->enc!=0 ); - assert( pMem->n>=0 ); - -#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) - { - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(pMem, &acc); - fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc)); - } -#endif - - /* If the translation is between UTF-16 little and big endian, then - ** all that is required is to swap the byte order. This case is handled - ** differently from the others. - */ - if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ - u8 temp; - int rc; - rc = sqlite3VdbeMemMakeWriteable(pMem); - if( rc!=SQLITE_OK ){ - assert( rc==SQLITE_NOMEM ); - return SQLITE_NOMEM_BKPT; - } - zIn = (u8*)pMem->z; - zTerm = &zIn[pMem->n&~1]; - while( zInenc = desiredEnc; - goto translate_out; - } - - /* Set len to the maximum number of bytes required in the output buffer. */ - if( desiredEnc==SQLITE_UTF8 ){ - /* When converting from UTF-16, the maximum growth results from - ** translating a 2-byte character to a 4-byte UTF-8 character. - ** A single byte is required for the output string - ** nul-terminator. - */ - pMem->n &= ~1; - len = 2 * (sqlite3_int64)pMem->n + 1; - }else{ - /* When converting from UTF-8 to UTF-16 the maximum growth is caused - ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 - ** character. Two bytes are required in the output buffer for the - ** nul-terminator. - */ - len = 2 * (sqlite3_int64)pMem->n + 2; - } - - /* Set zIn to point at the start of the input buffer and zTerm to point 1 - ** byte past the end. - ** - ** Variable zOut is set to point at the output buffer, space obtained - ** from sqlite3_malloc(). - */ - zIn = (u8*)pMem->z; - zTerm = &zIn[pMem->n]; - zOut = sqlite3DbMallocRaw(pMem->db, len); - if( !zOut ){ - return SQLITE_NOMEM_BKPT; - } - z = zOut; - - if( pMem->enc==SQLITE_UTF8 ){ - if( desiredEnc==SQLITE_UTF16LE ){ - /* UTF-8 -> UTF-16 Little-endian */ - while( zIn UTF-16 Big-endian */ - while( zInn = (int)(z - zOut); - *z++ = 0; - }else{ - assert( desiredEnc==SQLITE_UTF8 ); - if( pMem->enc==SQLITE_UTF16LE ){ - /* UTF-16 Little-endian -> UTF-8 */ - while( zIn=0xd800 && c<0xe000 ){ -#ifdef SQLITE_REPLACE_INVALID_UTF - if( c>=0xdc00 || zIn>=zTerm ){ - c = 0xfffd; - }else{ - int c2 = *(zIn++); - c2 += (*(zIn++))<<8; - if( c2<0xdc00 || c2>=0xe000 ){ - zIn -= 2; - c = 0xfffd; - }else{ - c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000; - } - } -#else - if( zIn UTF-8 */ - while( zIn=0xd800 && c<0xe000 ){ -#ifdef SQLITE_REPLACE_INVALID_UTF - if( c>=0xdc00 || zIn>=zTerm ){ - c = 0xfffd; - }else{ - int c2 = (*(zIn++))<<8; - c2 += *(zIn++); - if( c2<0xdc00 || c2>=0xe000 ){ - zIn -= 2; - c = 0xfffd; - }else{ - c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000; - } - } -#else - if( zInn = (int)(z - zOut); - } - *z = 0; - assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); - - c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype)); - sqlite3VdbeMemRelease(pMem); - pMem->flags = c; - pMem->enc = desiredEnc; - pMem->z = (char*)zOut; - pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); - -translate_out: -#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) - { - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(pMem, &acc); - fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc)); - } -#endif - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_UTF16 */ - -#ifndef SQLITE_OMIT_UTF16 -/* -** This routine checks for a byte-order mark at the beginning of the -** UTF-16 string stored in *pMem. If one is present, it is removed and -** the encoding of the Mem adjusted. This routine does not do any -** byte-swapping, it just sets Mem.enc appropriately. -** -** The allocation (static, dynamic etc.) and encoding of the Mem may be -** changed by this function. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){ - int rc = SQLITE_OK; - u8 bom = 0; - - assert( pMem->n>=0 ); - if( pMem->n>1 ){ - u8 b1 = *(u8 *)pMem->z; - u8 b2 = *(((u8 *)pMem->z) + 1); - if( b1==0xFE && b2==0xFF ){ - bom = SQLITE_UTF16BE; - } - if( b1==0xFF && b2==0xFE ){ - bom = SQLITE_UTF16LE; - } - } - - if( bom ){ - rc = sqlite3VdbeMemMakeWriteable(pMem); - if( rc==SQLITE_OK ){ - pMem->n -= 2; - memmove(pMem->z, &pMem->z[2], pMem->n); - pMem->z[pMem->n] = '\0'; - pMem->z[pMem->n+1] = '\0'; - pMem->flags |= MEM_Term; - pMem->enc = bom; - } - } - return rc; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, -** return the number of unicode characters in pZ up to (but not including) -** the first 0x00 byte. If nByte is not less than zero, return the -** number of unicode characters in the first nByte of pZ (or up to -** the first 0x00, whichever comes first). -*/ -SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){ - int r = 0; - const u8 *z = (const u8*)zIn; - const u8 *zTerm; - if( nByte>=0 ){ - zTerm = &z[nByte]; - }else{ - zTerm = (const u8*)(-1); - } - assert( z<=zTerm ); - while( *z!=0 && zmallocFailed ){ - sqlite3VdbeMemRelease(&m); - m.z = 0; - } - assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); - assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); - assert( m.z || db->mallocFailed ); - return m.z; -} - -/* -** zIn is a UTF-16 encoded unicode string at least nByte bytes long. -** Return the number of bytes in the first nChar unicode characters -** in pZ. nChar must be non-negative. Surrogate pairs count as a single -** character. -*/ -SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){ - int c; - unsigned char const *z = zIn; - unsigned char const *zEnd = &z[nByte-1]; - int n = 0; - - if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++; - while( n=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2; - n++; - } - return (int)(z-(unsigned char const *)zIn) - - (SQLITE_UTF16NATIVE==SQLITE_UTF16LE); -} - -#if defined(SQLITE_TEST) -/* -** This routine is called from the TCL test function "translate_selftest". -** It checks that the primitives for serializing and deserializing -** characters in each encoding are inverses of each other. -*/ -SQLITE_PRIVATE void sqlite3UtfSelfTest(void){ - unsigned int i, t; - unsigned char zBuf[20]; - unsigned char *z; - int n; - unsigned int c; - - for(i=0; i<0x00110000; i++){ - z = zBuf; - WRITE_UTF8(z, i); - n = (int)(z-zBuf); - assert( n>0 && n<=4 ); - z[0] = 0; - z = zBuf; - c = sqlite3Utf8Read((const u8**)&z); - t = i; - if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD; - if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD; - assert( c==t ); - assert( (z-zBuf)==n ); - } -} -#endif /* SQLITE_TEST */ -#endif /* SQLITE_OMIT_UTF16 */ - -/************** End of utf.c *************************************************/ -/************** Begin file util.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Utility functions used throughout sqlite. -** -** This file contains functions for allocating memory, comparing -** strings, and stuff like that. -** -*/ -/* #include "sqliteInt.h" */ -/* #include */ -#ifndef SQLITE_OMIT_FLOATING_POINT -#include -#endif - -/* -** Calls to sqlite3FaultSim() are used to simulate a failure during testing, -** or to bypass normal error detection during testing in order to let -** execute proceed further downstream. -** -** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The -** sqlite3FaultSim() function only returns non-zero during testing. -** -** During testing, if the test harness has set a fault-sim callback using -** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then -** each call to sqlite3FaultSim() is relayed to that application-supplied -** callback and the integer return value form the application-supplied -** callback is returned by sqlite3FaultSim(). -** -** The integer argument to sqlite3FaultSim() is a code to identify which -** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim() -** should have a unique code. To prevent legacy testing applications from -** breaking, the codes should not be changed or reused. -*/ -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ - int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; - return xCallback ? xCallback(iTest) : SQLITE_OK; -} -#endif - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Return true if the floating point value is Not a Number (NaN). -** -** 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 sqlite3IsNaN(double x){ - int rc; /* The value return */ -#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN - u64 y; - memcpy(&y,&x,sizeof(y)); - rc = IsNaN(y); -#else - rc = isnan(x); -#endif /* HAVE_ISNAN */ - testcase( rc ); - return rc; -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Return true if the floating point value is NaN or +Inf or -Inf. -*/ -SQLITE_PRIVATE int sqlite3IsOverflow(double x){ - int rc; /* The value return */ - u64 y; - memcpy(&y,&x,sizeof(y)); - rc = IsOvfl(y); - return rc; -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - -/* -** Compute a string length that is limited to what can be stored in -** lower 30 bits of a 32-bit signed integer. -** -** The value returned will never be negative. Nor will it ever be greater -** than the actual length of the string. For very long strings (greater -** than 1GiB) the value returned might be less than the true string length. -*/ -SQLITE_PRIVATE int sqlite3Strlen30(const char *z){ - if( z==0 ) return 0; - return 0x3fffffff & (int)strlen(z); -} - -/* -** Return the declared type of a column. Or return zDflt if the column -** has no declared type. -** -** The column type is an extra string stored after the zero-terminator on -** the column name if and only if the COLFLAG_HASTYPE flag is set. -*/ -SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){ - if( pCol->colFlags & COLFLAG_HASTYPE ){ - return pCol->zCnName + strlen(pCol->zCnName) + 1; - }else if( pCol->eCType ){ - assert( pCol->eCType<=SQLITE_N_STDTYPE ); - return (char*)sqlite3StdType[pCol->eCType-1]; - }else{ - return zDflt; - } -} - -/* -** Helper function for sqlite3Error() - called rarely. Broken out into -** a separate routine to avoid unnecessary register saves on entry to -** sqlite3Error(). -*/ -static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){ - if( db->pErr ) sqlite3ValueSetNull(db->pErr); - sqlite3SystemError(db, err_code); -} - -/* -** Set the current error code to err_code and clear any prior error message. -** Also set iSysErrno (by calling sqlite3System) if the err_code indicates -** that would be appropriate. -*/ -SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ - assert( db!=0 ); - db->errCode = err_code; - if( err_code || db->pErr ){ - sqlite3ErrorFinish(db, err_code); - }else{ - db->errByteOffset = -1; - } -} - -/* -** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state -** and error message. -*/ -SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){ - assert( db!=0 ); - db->errCode = SQLITE_OK; - db->errByteOffset = -1; - if( db->pErr ) sqlite3ValueSetNull(db->pErr); -} - -/* -** Load the sqlite3.iSysErrno field if that is an appropriate thing -** to do based on the SQLite error code in rc. -*/ -SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ - if( rc==SQLITE_IOERR_NOMEM ) return; -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) - if( rc==SQLITE_IOERR_IN_PAGE ){ - int ii; - int iErr; - sqlite3BtreeEnterAll(db); - for(ii=0; iinDb; ii++){ - if( db->aDb[ii].pBt ){ - iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); - if( iErr ){ - db->iSysErrno = iErr; - } - } - } - sqlite3BtreeLeaveAll(db); - return; - } -#endif - rc &= 0xff; - if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ - db->iSysErrno = sqlite3OsGetLastError(db->pVfs); - } -} - -/* -** Set the most recent error code and error string for the sqlite -** handle "db". The error code is set to "err_code". -** -** If it is not NULL, string zFormat specifies the format of the -** 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", sqlite3Error -** should be called with err_code set to SQLITE_OK and zFormat set -** to NULL. -*/ -SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ - assert( db!=0 ); - db->errCode = err_code; - sqlite3SystemError(db, err_code); - if( zFormat==0 ){ - sqlite3Error(db, err_code); - }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ - char *z; - va_list ap; - va_start(ap, zFormat); - z = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); - } -} - -/* -** Check for interrupts and invoke progress callback. -*/ -SQLITE_PRIVATE void sqlite3ProgressCheck(Parse *p){ - sqlite3 *db = p->db; - if( AtomicLoad(&db->u1.isInterrupted) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; - } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - if( p->rc==SQLITE_INTERRUPT ){ - p->nProgressSteps = 0; - }else if( (++p->nProgressSteps)>=db->nProgressOps ){ - if( db->xProgress(db->pProgressArg) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; - } - p->nProgressSteps = 0; - } - } -#endif -} - -/* -** Add an error message to pParse->zErrMsg and increment pParse->nErr. -** -** This function should be used to report any error that occurs while -** compiling an SQL statement (i.e. within sqlite3_prepare()). The -** last thing the sqlite3_prepare() function does is copy the error -** stored by this function into the database handle using sqlite3Error(). -** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used -** during statement execution (sqlite3_step() etc.). -*/ -SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ - char *zMsg; - va_list ap; - sqlite3 *db = pParse->db; - assert( db!=0 ); - assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); - db->errByteOffset = -2; - va_start(ap, zFormat); - zMsg = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - if( db->errByteOffset<-1 ) db->errByteOffset = -1; - if( db->suppressErr ){ - sqlite3DbFree(db, zMsg); - if( db->mallocFailed ){ - pParse->nErr++; - pParse->rc = SQLITE_NOMEM; - } - }else{ - pParse->nErr++; - sqlite3DbFree(db, pParse->zErrMsg); - pParse->zErrMsg = zMsg; - pParse->rc = SQLITE_ERROR; - pParse->pWith = 0; - } -} - -/* -** If database connection db is currently parsing SQL, then transfer -** error code errCode to that parser if the parser has not already -** encountered some other kind of error. -*/ -SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3 *db, int errCode){ - Parse *pParse; - if( db==0 || (pParse = db->pParse)==0 ) return errCode; - pParse->rc = errCode; - pParse->nErr++; - return errCode; -} - -/* -** Convert an SQL-style quoted string into a normal string by removing -** the quote characters. The conversion is done in-place. If the -** input does not begin with a quote character, then this routine -** is a no-op. -** -** The input string must be zero-terminated. A new zero-terminator -** is added to the dequoted string. -** -** The return value is -1 if no dequoting occurs or the length of the -** dequoted string, exclusive of the zero terminator, if dequoting does -** occur. -** -** 2002-02-14: This routine is extended to remove MS-Access style -** brackets from around identifiers. For example: "[a-b-c]" becomes -** "a-b-c". -*/ -SQLITE_PRIVATE void sqlite3Dequote(char *z){ - char quote; - int i, j; - if( z==0 ) return; - quote = z[0]; - if( !sqlite3Isquote(quote) ) return; - if( quote=='[' ) quote = ']'; - for(i=1, j=0;; i++){ - assert( z[i] ); - if( z[i]==quote ){ - if( z[i+1]==quote ){ - z[j++] = quote; - i++; - }else{ - break; - } - }else{ - z[j++] = z[i]; - } - } - z[j] = 0; -} -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ - assert( !ExprHasProperty(p, EP_IntValue) ); - assert( sqlite3Isquote(p->u.zToken[0]) ); - p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted; - sqlite3Dequote(p->u.zToken); -} - -/* -** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken -** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those -** that contain '_' characters that must be removed before further processing. -*/ -SQLITE_PRIVATE void sqlite3DequoteNumber(Parse *pParse, Expr *p){ - assert( p!=0 || pParse->db->mallocFailed ); - if( p ){ - const char *pIn = p->u.zToken; - char *pOut = p->u.zToken; - int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X')); - int iValue; - assert( p->op==TK_QNUMBER ); - p->op = TK_INTEGER; - do { - if( *pIn!=SQLITE_DIGIT_SEPARATOR ){ - *pOut++ = *pIn; - if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT; - }else{ - if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1]))) - || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1]))) - ){ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken); - } - } - }while( *pIn++ ); - if( bHex ) p->op = TK_INTEGER; - - /* tag-20240227-a: If after dequoting, the number is an integer that - ** fits in 32 bits, then it must be converted into EP_IntValue. Other - ** parts of the code expect this. See also tag-20240227-b. */ - if( p->op==TK_INTEGER && sqlite3GetInt32(p->u.zToken, &iValue) ){ - p->u.iValue = iValue; - p->flags |= EP_IntValue; - } - } -} - -/* -** 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 sqlite3DequoteToken(Token *p){ - unsigned int i; - if( p->n<2 ) return; - if( !sqlite3Isquote(p->z[0]) ) return; - for(i=1; in-1; i++){ - if( sqlite3Isquote(p->z[i]) ) return; - } - p->n -= 2; - p->z++; -} - -/* -** Generate a Token object from a string -*/ -SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ - p->z = z; - p->n = sqlite3Strlen30(z); -} - -/* Convenient short-hand */ -#define UpperToLower sqlite3UpperToLower - -/* -** Some systems have stricmp(). Others have strcasecmp(). Because -** there is no consistency, we will define our own. -** -** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and -** sqlite3_strnicmp() APIs allow applications and extensions to compare -** the contents of two buffers containing UTF-8 strings in a -** case-independent fashion, using the same definition of "case -** independence" that SQLite uses internally when comparing identifiers. -*/ -SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ - if( zLeft==0 ){ - return zRight ? -1 : 0; - }else if( zRight==0 ){ - return 1; - } - return sqlite3StrICmp(zLeft, zRight); -} -SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ - unsigned char *a, *b; - int c, x; - a = (unsigned char *)zLeft; - b = (unsigned char *)zRight; - for(;;){ - c = *a; - x = *b; - if( c==x ){ - if( c==0 ) break; - }else{ - c = (int)UpperToLower[c] - (int)UpperToLower[x]; - if( c ) break; - } - a++; - b++; - } - return c; -} -SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ - register unsigned char *a, *b; - if( zLeft==0 ){ - return zRight ? -1 : 0; - }else if( zRight==0 ){ - return 1; - } - a = (unsigned char *)zLeft; - b = (unsigned char *)zRight; - while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } - return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; -} - -/* -** Compute an 8-bit hash on a string that is insensitive to case differences -*/ -SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ - u8 h = 0; - if( z==0 ) return 0; - while( z[0] ){ - h += UpperToLower[(unsigned char)z[0]]; - z++; - } - return h; -} - -/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) -** -** Reference: -** T. J. Dekker, "A Floating-Point Technique for Extending the -** Available Precision". 1971-07-26. -*/ -static void dekkerMul2(volatile double *x, double y, double yy){ - /* - ** The "volatile" keywords on parameter x[] and on local variables - ** below are needed force intermediate results to be truncated to - ** binary64 rather than be carried around in an extended-precision - ** format. The truncation is necessary for the Dekker algorithm to - ** work. Intel x86 floating point might omit the truncation without - ** the use of volatile. - */ - volatile double tx, ty, p, q, c, cc; - double hx, hy; - u64 m; - memcpy(&m, (void*)&x[0], 8); - m &= 0xfffffffffc000000LL; - memcpy(&hx, &m, 8); - tx = x[0] - hx; - memcpy(&m, &y, 8); - m &= 0xfffffffffc000000LL; - memcpy(&hy, &m, 8); - ty = y - hy; - p = hx*hy; - q = hx*ty + tx*hy; - c = p+q; - cc = p - c + q + tx*ty; - cc = x[0]*yy + x[1]*y + cc; - x[0] = c + cc; - x[1] = c - x[0]; - x[1] += cc; -} - -/* -** The string z[] is an text representation of a real number. -** Convert this string to a double and write it into *pResult. -** -** The string z[] is length bytes in length (bytes, not characters) and -** uses the encoding enc. The string is not necessarily zero-terminated. -** -** Return TRUE if the result is a valid real number (or integer) and FALSE -** if the string is empty or contains extraneous text. More specifically -** return -** 1 => The input string is a pure integer -** 2 or more => The input has a decimal point or eNNN clause -** 0 or less => The input string is not a valid number -** -1 => Not a valid number, but has a valid prefix which -** includes a decimal point and/or an eNNN clause -** -** Valid numbers are in one of these formats: -** -** [+-]digits[E[+-]digits] -** [+-]digits.[digits][E[+-]digits] -** [+-].digits[E[+-]digits] -** -** Leading and trailing whitespace is ignored for the purpose of determining -** validity. -** -** If some prefix of the input string is a valid number, this routine -** returns FALSE but it still converts the prefix and writes the result -** into *pResult. -*/ -#if defined(_MSC_VER) -#pragma warning(disable : 4756) -#endif -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ -#ifndef SQLITE_OMIT_FLOATING_POINT - int incr; - const char *zEnd; - /* sign * significand * (10 ^ (esign * exponent)) */ - int sign = 1; /* sign of significand */ - u64 s = 0; /* significand */ - int d = 0; /* adjust exponent for shifting decimal point */ - int esign = 1; /* sign of exponent */ - int e = 0; /* exponent */ - int eValid = 1; /* True exponent is either not used or is well-formed */ - int nDigit = 0; /* Number of digits processed */ - int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ - u64 s2; /* round-tripped significand */ - double rr[2]; - - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - *pResult = 0.0; /* Default return value, in case of an error */ - if( length==0 ) return 0; - - if( enc==SQLITE_UTF8 ){ - incr = 1; - zEnd = z + length; - }else{ - int i; - incr = 2; - length &= ~1; - assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - testcase( enc==SQLITE_UTF16LE ); - testcase( enc==SQLITE_UTF16BE ); - for(i=3-enc; i=zEnd ) return 0; - - /* get sign of significand */ - if( *z=='-' ){ - sign = -1; - z+=incr; - }else if( *z=='+' ){ - z+=incr; - } - - /* copy max significant digits to significand */ - while( z=((LARGEST_UINT64-9)/10) ){ - /* skip non-significant significand digits - ** (increase exponent by d to shift decimal left) */ - while( z=zEnd ) goto do_atof_calc; - - /* if decimal point is present */ - if( *z=='.' ){ - z+=incr; - eType++; - /* copy digits from after decimal to significand - ** (decrease exponent by d to shift decimal right) */ - while( z=zEnd ) goto do_atof_calc; - - /* if exponent is present */ - if( *z=='e' || *z=='E' ){ - z+=incr; - eValid = 0; - eType++; - - /* This branch is needed to avoid a (harmless) buffer overread. The - ** special comment alerts the mutation tester that the correct answer - ** is obtained even if the branch is omitted */ - if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ - - /* get sign of exponent */ - if( *z=='-' ){ - esign = -1; - z+=incr; - }else if( *z=='+' ){ - z+=incr; - } - /* copy digits to exponent */ - while( z0 && s<((LARGEST_UINT64-0x7ff)/10) ){ - s *= 10; - e--; - } - while( e<0 && (s%10)==0 ){ - s /= 10; - e++; - } - - rr[0] = (double)s; - assert( sizeof(s2)==sizeof(rr[0]) ); -#ifdef SQLITE_DEBUG - rr[1] = 18446744073709549568.0; - memcpy(&s2, &rr[1], sizeof(s2)); - assert( s2==0x43efffffffffffffLL ); -#endif - /* Largest double that can be safely converted to u64 - ** vvvvvvvvvvvvvvvvvvvvvv */ - if( rr[0]<=18446744073709549568.0 ){ - s2 = (u64)rr[0]; - rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); - }else{ - rr[1] = 0.0; - } - assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */ - - if( e>0 ){ - while( e>=100 ){ - e -= 100; - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); - } - while( e>=10 ){ - e -= 10; - dekkerMul2(rr, 1.0e+10, 0.0); - } - while( e>=1 ){ - e -= 1; - dekkerMul2(rr, 1.0e+01, 0.0); - } - }else{ - while( e<=-100 ){ - e += 100; - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); - } - while( e<=-10 ){ - e += 10; - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); - } - while( e<=-1 ){ - e += 1; - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); - } - } - *pResult = rr[0]+rr[1]; - if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; - if( sign<0 ) *pResult = -*pResult; - assert( !sqlite3IsNaN(*pResult) ); - -atof_return: - /* return true if number and no extra non-whitespace characters after */ - if( z==zEnd && nDigit>0 && eValid && eType>0 ){ - return eType; - }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ - return -1; - }else{ - return 0; - } -#else - return !sqlite3Atoi64(z, pResult, length, enc); -#endif /* SQLITE_OMIT_FLOATING_POINT */ -} -#if defined(_MSC_VER) -#pragma warning(default : 4756) -#endif - -/* -** Render an signed 64-bit integer as text. Store the result in zOut[] and -** return the length of the string that was stored, in bytes. The value -** returned does not include the zero terminator at the end of the output -** string. -** -** The caller must ensure that zOut[] is at least 21 bytes in size. -*/ -SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ - int i; - u64 x; - char zTemp[22]; - if( v<0 ){ - x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; - }else{ - x = v; - } - i = sizeof(zTemp)-2; - zTemp[sizeof(zTemp)-1] = 0; - while( 1 /*exit-by-break*/ ){ - zTemp[i] = (x%10) + '0'; - x = x/10; - if( x==0 ) break; - i--; - }; - if( v<0 ) zTemp[--i] = '-'; - memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); - return sizeof(zTemp)-1-i; -} - -/* -** Compare the 19-character string zNum against the text representation -** value 2^63: 9223372036854775808. Return negative, zero, or positive -** if zNum is less than, equal to, or greater than the string. -** Note that zNum must contain exactly 19 characters. -** -** Unlike memcmp() this routine is guaranteed to return the difference -** in the values of the last digit if the only difference is in the -** last digit. So, for example, -** -** compare2pow63("9223372036854775800", 1) -** -** will return -8. -*/ -static int compare2pow63(const char *zNum, int incr){ - int c = 0; - int i; - /* 012345678901234567 */ - const char *pow63 = "922337203685477580"; - for(i=0; c==0 && i<18; i++){ - c = (zNum[i*incr]-pow63[i])*10; - } - if( c==0 ){ - c = zNum[18*incr] - '8'; - testcase( c==(-1) ); - testcase( c==0 ); - testcase( c==(+1) ); - } - return c; -} - -/* -** Convert zNum to a 64-bit signed integer. zNum must be decimal. This -** routine does *not* accept hexadecimal notation. -** -** Returns: -** -** -1 Not even a prefix of the input text looks like an integer -** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Excess non-space text after the integer value -** 2 Integer too large for a 64-bit signed integer or is malformed -** 3 Special case of 9223372036854775808 -** -** length is the number of bytes in the string (bytes, not characters). -** The string is not necessarily zero-terminated. The encoding is -** given by enc. -*/ -SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ - int incr; - u64 u = 0; - int neg = 0; /* assume positive */ - int i; - int c = 0; - int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ - int rc; /* Baseline return code */ - const char *zStart; - const char *zEnd = zNum + length; - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - if( enc==SQLITE_UTF8 ){ - incr = 1; - }else{ - incr = 2; - length &= ~1; - assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - for(i=3-enc; i='0' && c<='9'; i+=incr){ - u = u*10 + c - '0'; - } - testcase( i==18*incr ); - testcase( i==19*incr ); - testcase( i==20*incr ); - if( u>LARGEST_INT64 ){ - /* This test and assignment is needed only to suppress UB warnings - ** from clang and -fsanitize=undefined. This test and assignment make - ** the code a little larger and slower, and no harm comes from omitting - ** them, but we must appease the undefined-behavior pharisees. */ - *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; - }else if( neg ){ - *pNum = -(i64)u; - }else{ - *pNum = (i64)u; - } - rc = 0; - if( i==0 && zStart==zNum ){ /* No digits */ - rc = -1; - }else if( nonNum ){ /* UTF16 with high-order bytes non-zero */ - rc = 1; - }else if( &zNum[i]19*incr ? 1 : compare2pow63(zNum, incr); - if( c<0 ){ - /* zNum is less than 9223372036854775808 so it fits */ - assert( u<=LARGEST_INT64 ); - return rc; - }else{ - *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; - if( c>0 ){ - /* zNum is greater than 9223372036854775808 so it overflows */ - return 2; - }else{ - /* zNum is exactly 9223372036854775808. Fits if negative. The - ** special case 2 overflow if positive */ - assert( u-1==LARGEST_INT64 ); - return neg ? rc : 3; - } - } - } -} - -/* -** Transform a UTF-8 integer literal, in either decimal or hexadecimal, -** into a 64-bit signed integer. This routine accepts hexadecimal literals, -** whereas sqlite3Atoi64() does not. -** -** Returns: -** -** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Excess text after the integer value -** 2 Integer too large for a 64-bit signed integer or is malformed -** 3 Special case of 9223372036854775808 -*/ -SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ -#ifndef SQLITE_OMIT_HEX_INTEGER - if( z[0]=='0' - && (z[1]=='x' || z[1]=='X') - ){ - u64 u = 0; - int i, k; - for(i=2; z[i]=='0'; i++){} - for(k=i; sqlite3Isxdigit(z[k]); k++){ - u = u*16 + sqlite3HexToInt(z[k]); - } - memcpy(pOut, &u, 8); - if( k-i>16 ) return 2; - if( z[k]!=0 ) return 1; - return 0; - }else -#endif /* SQLITE_OMIT_HEX_INTEGER */ - { - int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789")); - if( z[n] ) n++; - return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8); - } -} - -/* -** If zNum represents an integer that will fit in 32-bits, then set -** *pValue to that integer and return true. Otherwise return false. -** -** This routine accepts both decimal and hexadecimal notation for integers. -** -** Any non-numeric characters that following zNum are ignored. -** This is different from sqlite3Atoi64() which requires the -** input number to be zero-terminated. -*/ -SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ - sqlite_int64 v = 0; - int i, c; - int neg = 0; - if( zNum[0]=='-' ){ - neg = 1; - zNum++; - }else if( zNum[0]=='+' ){ - zNum++; - } -#ifndef SQLITE_OMIT_HEX_INTEGER - else if( zNum[0]=='0' - && (zNum[1]=='x' || zNum[1]=='X') - && sqlite3Isxdigit(zNum[2]) - ){ - u32 u = 0; - zNum += 2; - while( zNum[0]=='0' ) zNum++; - for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){ - u = u*16 + sqlite3HexToInt(zNum[i]); - } - if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ - memcpy(pValue, &u, 4); - return 1; - }else{ - return 0; - } - } -#endif - if( !sqlite3Isdigit(zNum[0]) ) return 0; - while( zNum[0]=='0' ) zNum++; - for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ - v = v*10 + c; - } - - /* The longest decimal representation of a 32 bit integer is 10 digits: - ** - ** 1234567890 - ** 2^31 -> 2147483648 - */ - testcase( i==10 ); - if( i>10 ){ - return 0; - } - testcase( v-neg==2147483647 ); - if( v-neg>2147483647 ){ - return 0; - } - if( neg ){ - v = -v; - } - *pValue = (int)v; - return 1; -} - -/* -** Return a 32-bit integer value extracted from a string. If the -** string is not an integer, just return 0. -*/ -SQLITE_PRIVATE int sqlite3Atoi(const char *z){ - int x = 0; - sqlite3GetInt32(z, &x); - return x; -} - -/* -** Decode a floating-point value into an approximate decimal -** representation. -** -** If iRound<=0 then round to -iRound significant digits to the -** the left of the decimal point, or to a maximum of mxRound total -** significant digits. -** -** If iRound>0 round to min(iRound,mxRound) significant digits total. -** -** mxRound must be positive. -** -** The significant digits of the decimal representation are -** stored in p->z[] which is a often (but not always) a pointer -** into the middle of p->zBuf[]. There are p->n significant digits. -** The p->z[] array is *not* zero-terminated. -*/ -SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ - int i; - u64 v; - int e, exp = 0; - double rr[2]; - - p->isSpecial = 0; - p->z = p->zBuf; - assert( mxRound>0 ); - - /* Convert negative numbers to positive. Deal with Infinity, 0.0, and - ** NaN. */ - if( r<0.0 ){ - p->sign = '-'; - r = -r; - }else if( r==0.0 ){ - p->sign = '+'; - p->n = 1; - p->iDP = 1; - p->z = "0"; - return; - }else{ - p->sign = '+'; - } - memcpy(&v,&r,8); - e = v>>52; - if( (e&0x7ff)==0x7ff ){ - p->isSpecial = 1 + (v!=0x7ff0000000000000LL); - p->n = 0; - p->iDP = 0; - return; - } - - /* Multiply r by powers of ten until it lands somewhere in between - ** 1.0e+19 and 1.0e+17. - ** - ** Use Dekker-style double-double computation to increase the - ** precision. - ** - ** The error terms on constants like 1.0e+100 computed using the - ** decimal extension, for example as follows: - ** - ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); - */ - rr[0] = r; - rr[1] = 0.0; - if( rr[0]>9.223372036854774784e+18 ){ - while( rr[0]>9.223372036854774784e+118 ){ - exp += 100; - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); - } - while( rr[0]>9.223372036854774784e+28 ){ - exp += 10; - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); - } - while( rr[0]>9.223372036854774784e+18 ){ - exp += 1; - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); - } - }else{ - while( rr[0]<9.223372036854774784e-83 ){ - exp -= 100; - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); - } - while( rr[0]<9.223372036854774784e+07 ){ - exp -= 10; - dekkerMul2(rr, 1.0e+10, 0.0); - } - while( rr[0]<9.22337203685477478e+17 ){ - exp -= 1; - dekkerMul2(rr, 1.0e+01, 0.0); - } - } - v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; - - /* Extract significant digits. */ - i = sizeof(p->zBuf)-1; - assert( v>0 ); - while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } - assert( i>=0 && izBuf)-1 ); - p->n = sizeof(p->zBuf) - 1 - i; - assert( p->n>0 ); - assert( p->nzBuf) ); - p->iDP = p->n + exp; - if( iRound<=0 ){ - iRound = p->iDP - iRound; - if( iRound==0 && p->zBuf[i+1]>='5' ){ - iRound = 1; - p->zBuf[i--] = '0'; - p->n++; - p->iDP++; - } - } - if( iRound>0 && (iRoundn || p->n>mxRound) ){ - char *z = &p->zBuf[i+1]; - if( iRound>mxRound ) iRound = mxRound; - p->n = iRound; - if( z[iRound]>='5' ){ - int j = iRound-1; - while( 1 /*exit-by-break*/ ){ - z[j]++; - if( z[j]<='9' ) break; - z[j] = '0'; - if( j==0 ){ - p->z[i--] = '1'; - p->n++; - p->iDP++; - break; - }else{ - j--; - } - } - } - } - p->z = &p->zBuf[i+1]; - assert( i+p->n < sizeof(p->zBuf) ); - assert( p->n>0 ); - while( p->z[p->n-1]=='0' ){ - p->n--; - assert( p->n>0 ); - } -} - -/* -** Try to convert z into an unsigned 32-bit integer. Return true on -** success and false if there is an error. -** -** Only decimal notation is accepted. -*/ -SQLITE_PRIVATE int sqlite3GetUInt32(const char *z, u32 *pI){ - u64 v = 0; - int i; - for(i=0; sqlite3Isdigit(z[i]); i++){ - v = v*10 + z[i] - '0'; - if( v>4294967296LL ){ *pI = 0; return 0; } - } - if( i==0 || z[i]!=0 ){ *pI = 0; return 0; } - *pI = (u32)v; - return 1; -} - -/* -** The variable-length integer encoding is as follows: -** -** KEY: -** A = 0xxxxxxx 7 bits of data and one flag bit -** B = 1xxxxxxx 7 bits of data and one flag bit -** C = xxxxxxxx 8 bits of data -** -** 7 bits - A -** 14 bits - BA -** 21 bits - BBA -** 28 bits - BBBA -** 35 bits - BBBBA -** 42 bits - BBBBBA -** 49 bits - BBBBBBA -** 56 bits - BBBBBBBA -** 64 bits - BBBBBBBBC -*/ - -/* -** Write a 64-bit variable-length integer to memory starting at p[0]. -** The length of data write will be between 1 and 9 bytes. The number -** of bytes written is returned. -** -** A variable-length integer consists of the lower 7 bits of each byte -** for all bytes that have the 8th bit set and one byte with the 8th -** bit clear. Except, if we get to the 9th byte, it stores the full -** 8 bits and is the last byte. -*/ -static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ - int i, j, n; - u8 buf[10]; - if( v & (((u64)0xff000000)<<32) ){ - p[8] = (u8)v; - v >>= 8; - for(i=7; i>=0; i--){ - p[i] = (u8)((v & 0x7f) | 0x80); - v >>= 7; - } - return 9; - } - n = 0; - do{ - buf[n++] = (u8)((v & 0x7f) | 0x80); - v >>= 7; - }while( v!=0 ); - buf[0] &= 0x7f; - assert( n<=9 ); - for(i=0, j=n-1; j>=0; j--, i++){ - p[i] = buf[j]; - } - return n; -} -SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){ - if( v<=0x7f ){ - p[0] = v&0x7f; - return 1; - } - if( v<=0x3fff ){ - p[0] = ((v>>7)&0x7f)|0x80; - p[1] = v&0x7f; - return 2; - } - return putVarint64(p,v); -} - -/* -** Bitmasks used by sqlite3GetVarint(). These precomputed constants -** are defined here rather than simply putting the constant expressions -** inline in order to work around bugs in the RVT compiler. -** -** SLOT_2_0 A mask for (0x7f<<14) | 0x7f -** -** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 -*/ -#define SLOT_2_0 0x001fc07f -#define SLOT_4_2_0 0xf01fc07f - - -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read. The value is stored in *v. -*/ -SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ - u32 a,b,s; - - if( ((signed char*)p)[0]>=0 ){ - *v = *p; - return 1; - } - if( ((signed char*)p)[1]>=0 ){ - *v = ((u32)(p[0]&0x7f)<<7) | p[1]; - return 2; - } - - /* Verify that constants are precomputed correctly */ - assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); - assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); - - a = ((u32)p[0])<<14; - b = p[1]; - p += 2; - a |= *p; - /* a: p0<<14 | p2 (unmasked) */ - if (!(a&0x80)) - { - a &= SLOT_2_0; - b &= 0x7f; - b = b<<7; - a |= b; - *v = a; - return 3; - } - - /* CSE1 from below */ - a &= SLOT_2_0; - p++; - b = b<<14; - b |= *p; - /* b: p1<<14 | p3 (unmasked) */ - if (!(b&0x80)) - { - b &= SLOT_2_0; - /* moved CSE1 up */ - /* a &= (0x7f<<14)|(0x7f); */ - a = a<<7; - a |= b; - *v = a; - return 4; - } - - /* a: p0<<14 | p2 (masked) */ - /* b: p1<<14 | p3 (unmasked) */ - /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ - /* moved CSE1 up */ - /* a &= (0x7f<<14)|(0x7f); */ - b &= SLOT_2_0; - s = a; - /* s: p0<<14 | p2 (masked) */ - - p++; - a = a<<14; - a |= *p; - /* a: p0<<28 | p2<<14 | p4 (unmasked) */ - if (!(a&0x80)) - { - /* we can skip these cause they were (effectively) done above - ** while calculating s */ - /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ - /* b &= (0x7f<<14)|(0x7f); */ - b = b<<7; - a |= b; - s = s>>18; - *v = ((u64)s)<<32 | a; - return 5; - } - - /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ - s = s<<7; - s |= b; - /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ - - p++; - b = b<<14; - b |= *p; - /* b: p1<<28 | p3<<14 | p5 (unmasked) */ - if (!(b&0x80)) - { - /* we can skip this cause it was (effectively) done above in calc'ing s */ - /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ - a &= SLOT_2_0; - a = a<<7; - a |= b; - s = s>>18; - *v = ((u64)s)<<32 | a; - return 6; - } - - p++; - a = a<<14; - a |= *p; - /* a: p2<<28 | p4<<14 | p6 (unmasked) */ - if (!(a&0x80)) - { - a &= SLOT_4_2_0; - b &= SLOT_2_0; - b = b<<7; - a |= b; - s = s>>11; - *v = ((u64)s)<<32 | a; - return 7; - } - - /* CSE2 from below */ - a &= SLOT_2_0; - p++; - b = b<<14; - b |= *p; - /* b: p3<<28 | p5<<14 | p7 (unmasked) */ - if (!(b&0x80)) - { - b &= SLOT_4_2_0; - /* moved CSE2 up */ - /* a &= (0x7f<<14)|(0x7f); */ - a = a<<7; - a |= b; - s = s>>4; - *v = ((u64)s)<<32 | a; - return 8; - } - - p++; - a = a<<15; - a |= *p; - /* a: p4<<29 | p6<<15 | p8 (unmasked) */ - - /* moved CSE2 up */ - /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ - b &= SLOT_2_0; - b = b<<8; - a |= b; - - s = s<<4; - b = p[-4]; - b &= 0x7f; - b = b>>3; - s |= b; - - *v = ((u64)s)<<32 | a; - - return 9; -} - -/* -** Read a 32-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read. The value is stored in *v. -** -** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned -** integer, then set *v to 0xffffffff. -** -** A MACRO version, getVarint32, is provided which inlines the -** single-byte case. All code should use the MACRO version as -** this function assumes the single-byte case has already been handled. -*/ -SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ - u64 v64; - u8 n; - - /* Assume that the single-byte case has already been handled by - ** the getVarint32() macro */ - assert( (p[0] & 0x80)!=0 ); - - if( (p[1] & 0x80)==0 ){ - /* This is the two-byte case */ - *v = ((p[0]&0x7f)<<7) | p[1]; - return 2; - } - if( (p[2] & 0x80)==0 ){ - /* This is the three-byte case */ - *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2]; - return 3; - } - /* four or more bytes */ - n = sqlite3GetVarint(p, &v64); - assert( n>3 && n<=9 ); - if( (v64 & SQLITE_MAX_U32)!=v64 ){ - *v = 0xffffffff; - }else{ - *v = (u32)v64; - } - return n; -} - -/* -** Return the number of bytes that will be needed to store the given -** 64-bit integer. -*/ -SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ - int i; - for(i=1; (v >>= 7)!=0; i++){ assert( i<10 ); } - return i; -} - - -/* -** Read or write a four-byte big-endian integer value. -*/ -SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){ -#if SQLITE_BYTEORDER==4321 - u32 x; - memcpy(&x,p,4); - return x; -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - u32 x; - memcpy(&x,p,4); - return __builtin_bswap32(x); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - u32 x; - memcpy(&x,p,4); - return _byteswap_ulong(x); -#else - testcase( p[0]&0x80 ); - return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; -#endif -} -SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ -#if SQLITE_BYTEORDER==4321 - memcpy(p,&v,4); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - u32 x = __builtin_bswap32(v); - memcpy(p,&x,4); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - u32 x = _byteswap_ulong(v); - memcpy(p,&x,4); -#else - p[0] = (u8)(v>>24); - p[1] = (u8)(v>>16); - p[2] = (u8)(v>>8); - p[3] = (u8)v; -#endif -} - - - -/* -** Translate a single byte of Hex into an integer. -** This routine only works if h really is a valid hexadecimal -** character: 0..9a..fA..F -*/ -SQLITE_PRIVATE u8 sqlite3HexToInt(int h){ - assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); -#ifdef SQLITE_ASCII - h += 9*(1&(h>>6)); -#endif -#ifdef SQLITE_EBCDIC - h += 9*(1&~(h>>4)); -#endif - return (u8)(h & 0xf); -} - -/* BEGIN SQLCIPHER */ -#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) -/* -** Convert a BLOB literal of the form "x'hhhhhh'" into its binary -** value. Return a pointer to its binary value. Space to hold the -** binary value has been obtained from malloc and must be freed by -** the calling routine. -*/ -SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ - char *zBlob; - int i; - - zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1); - n--; - if( zBlob ){ - for(i=0; ieOpenState; - if( eOpenState!=SQLITE_STATE_OPEN ){ - if( sqlite3SafetyCheckSickOrOk(db) ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - logBadConnection("unopened"); - } - return 0; - }else{ - return 1; - } -} -SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ - u8 eOpenState; - eOpenState = db->eOpenState; - if( eOpenState!=SQLITE_STATE_SICK && - eOpenState!=SQLITE_STATE_OPEN && - eOpenState!=SQLITE_STATE_BUSY ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - logBadConnection("invalid"); - return 0; - }else{ - return 1; - } -} - -/* -** Attempt to add, subtract, or multiply the 64-bit signed value iB against -** the other 64-bit signed integer at *pA and store the result in *pA. -** Return 0 on success. Or if the operation would have resulted in an -** overflow, leave *pA unchanged and return 1. -*/ -SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) - return __builtin_add_overflow(*pA, iB, pA); -#else - i64 iA = *pA; - testcase( iA==0 ); testcase( iA==1 ); - testcase( iB==-1 ); testcase( iB==0 ); - if( iB>=0 ){ - testcase( iA>0 && LARGEST_INT64 - iA == iB ); - testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 ); - if( iA>0 && LARGEST_INT64 - iA < iB ) return 1; - }else{ - testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 ); - testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); - if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; - } - *pA += iB; - return 0; -#endif -} -SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) - return __builtin_sub_overflow(*pA, iB, pA); -#else - testcase( iB==SMALLEST_INT64+1 ); - if( iB==SMALLEST_INT64 ){ - testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); - if( (*pA)>=0 ) return 1; - *pA -= iB; - return 0; - }else{ - return sqlite3AddInt64(pA, -iB); - } -#endif -} -SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) - return __builtin_mul_overflow(*pA, iB, pA); -#else - i64 iA = *pA; - if( iB>0 ){ - if( iA>LARGEST_INT64/iB ) return 1; - if( iA0 ){ - if( iBLARGEST_INT64/-iB ) return 1; - } - } - *pA = iA*iB; - return 0; -#endif -} - -/* -** Compute the absolute value of a 32-bit signed integer, if possible. Or -** if the integer has a value of -2147483648, return +2147483647 -*/ -SQLITE_PRIVATE int sqlite3AbsInt32(int x){ - if( x>=0 ) return x; - if( x==(int)0x80000000 ) return 0x7fffffff; - return -x; -} - -#ifdef SQLITE_ENABLE_8_3_NAMES -/* -** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database -** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and -** if filename in z[] has a suffix (a.k.a. "extension") that is longer than -** three characters, then shorten the suffix on z[] to be the last three -** characters of the original suffix. -** -** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always -** do the suffix shortening regardless of URI parameter. -** -** Examples: -** -** test.db-journal => test.nal -** test.db-wal => test.wal -** test.db-shm => test.shm -** test.db-mj7f3319fa => test.9fa -*/ -SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ -#if SQLITE_ENABLE_8_3_NAMES<2 - if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) ) -#endif - { - int i, sz; - sz = sqlite3Strlen30(z); - for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} - if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); - } -} -#endif - -/* -** Find (an approximate) sum of two LogEst values. This computation is -** not a simple "+" operator because LogEst is stored as a logarithmic -** value. -** -*/ -SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ - static const unsigned char x[] = { - 10, 10, /* 0,1 */ - 9, 9, /* 2,3 */ - 8, 8, /* 4,5 */ - 7, 7, 7, /* 6,7,8 */ - 6, 6, 6, /* 9,10,11 */ - 5, 5, 5, /* 12-14 */ - 4, 4, 4, 4, /* 15-18 */ - 3, 3, 3, 3, 3, 3, /* 19-24 */ - 2, 2, 2, 2, 2, 2, 2, /* 25-31 */ - }; - if( a>=b ){ - if( a>b+49 ) return a; - if( a>b+31 ) return a+1; - return a+x[a-b]; - }else{ - if( b>a+49 ) return b; - if( b>a+31 ) return b+1; - return b+x[b-a]; - } -} - -/* -** Convert an integer into a LogEst. In other words, compute an -** approximation for 10*log2(x). -*/ -SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ - static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; - LogEst y = 40; - if( x<8 ){ - if( x<2 ) return 0; - while( x<8 ){ y -= 10; x <<= 1; } - }else{ -#if GCC_VERSION>=5004000 - int i = 60 - __builtin_clzll(x); - y += i*10; - x >>= i; -#else - while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/ - while( x>15 ){ y += 10; x >>= 1; } -#endif - } - return a[x&7] + y - 10; -} - -/* -** Convert a double into a LogEst -** In other words, compute an approximation for 10*log2(x). -*/ -SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ - u64 a; - LogEst e; - assert( sizeof(x)==8 && sizeof(a)==8 ); - if( x<=1 ) return 0; - if( x<=2000000000 ) return sqlite3LogEst((u64)x); - memcpy(&a, &x, 8); - e = (a>>52) - 1022; - return e*10; -} - -/* -** Convert a LogEst into an integer. -*/ -SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ - u64 n; - n = x%10; - x /= 10; - if( n>=5 ) n -= 2; - else if( n>=1 ) n -= 1; - if( x>60 ) return (u64)LARGEST_INT64; - return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); -} - -/* -** Add a new name/number pair to a VList. This might require that the -** VList object be reallocated, so return the new VList. If an OOM -** error occurs, the original VList returned and the -** db->mallocFailed flag is set. -** -** A VList is really just an array of integers. To destroy a VList, -** simply pass it to sqlite3DbFree(). -** -** The first integer is the number of integers allocated for the whole -** VList. The second integer is the number of integers actually used. -** Each name/number pair is encoded by subsequent groups of 3 or more -** integers. -** -** Each name/number pair starts with two integers which are the numeric -** value for the pair and the size of the name/number pair, respectively. -** The text name overlays one or more following integers. The text name -** is always zero-terminated. -** -** Conceptually: -** -** struct VList { -** int nAlloc; // Number of allocated slots -** int nUsed; // Number of used slots -** struct VListEntry { -** int iValue; // Value for this entry -** int nSlot; // Slots used by this entry -** // ... variable name goes here -** } a[0]; -** } -** -** During code generation, pointers to the variable names within the -** VList are taken. When that happens, nAlloc is set to zero as an -** indication that the VList may never again be enlarged, since the -** accompanying realloc() would invalidate the pointers. -*/ -SQLITE_PRIVATE VList *sqlite3VListAdd( - sqlite3 *db, /* The database connection used for malloc() */ - VList *pIn, /* The input VList. Might be NULL */ - const char *zName, /* Name of symbol to add */ - int nName, /* Bytes of text in zName */ - int iVal /* Value to associate with zName */ -){ - int nInt; /* number of sizeof(int) objects needed for zName */ - char *z; /* Pointer to where zName will be stored */ - int i; /* Index in pIn[] where zName is stored */ - - nInt = nName/4 + 3; - assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ - if( pIn==0 || pIn[1]+nInt > pIn[0] ){ - /* Enlarge the allocation */ - sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt; - VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); - if( pOut==0 ) return pIn; - if( pIn==0 ) pOut[1] = 2; - pIn = pOut; - pIn[0] = nAlloc; - } - i = pIn[1]; - pIn[i] = iVal; - pIn[i+1] = nInt; - z = (char*)&pIn[i+2]; - pIn[1] = i+nInt; - assert( pIn[1]<=pIn[0] ); - memcpy(z, zName, nName); - z[nName] = 0; - return pIn; -} - -/* -** Return a pointer to the name of a variable in the given VList that -** has the value iVal. Or return a NULL if there is no such variable in -** the list -*/ -SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){ - int i, mx; - if( pIn==0 ) return 0; - mx = pIn[1]; - i = 2; - do{ - if( pIn[i]==iVal ) return (char*)&pIn[i+2]; - i += pIn[i+1]; - }while( i */ - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "pNew" is a pointer to the hash table that is to be initialized. -*/ -SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){ - assert( pNew!=0 ); - pNew->first = 0; - pNew->count = 0; - pNew->htsize = 0; - pNew->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ - HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - sqlite3_free(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - HashElem *next_elem = elem->next; - sqlite3_free(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** The hashing function. -*/ -static unsigned int strHash(const char *z){ - unsigned int h = 0; - while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/ - /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). - ** 0x9e3779b1 is 2654435761 which is the closest prime number to - ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. - ** - ** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are - ** hashed since the omitted bits determine the upper/lower case difference. - */ -#ifdef SQLITE_EBCDIC - h += 0xbf & (unsigned char)*(z++); -#else - h += 0xdf & (unsigned char)*(z++); -#endif - h *= 0x9e3779b1; - } - return h; -} - - -/* Link pNew element into the hash table pH. If pEntry!=0 then also -** insert pNew into the pEntry hash bucket. -*/ -static void insertElement( - Hash *pH, /* The complete hash table */ - struct _ht *pEntry, /* The entry into which pNew is inserted */ - HashElem *pNew /* The element to be inserted */ -){ - HashElem *pHead; /* First element already in pEntry */ - if( pEntry ){ - pHead = pEntry->count ? pEntry->chain : 0; - pEntry->count++; - pEntry->chain = pNew; - }else{ - pHead = 0; - } - if( pHead ){ - pNew->next = pHead; - pNew->prev = pHead->prev; - if( pHead->prev ){ pHead->prev->next = pNew; } - else { pH->first = pNew; } - pHead->prev = pNew; - }else{ - pNew->next = pH->first; - if( pH->first ){ pH->first->prev = pNew; } - pNew->prev = 0; - pH->first = pNew; - } -} - - -/* Resize the hash table so that it contains "new_size" buckets. -** -** The hash table might fail to resize if sqlite3_malloc() fails or -** if the new size is the same as the prior size. -** Return TRUE if the resize occurs and false if not. -*/ -static int rehash(Hash *pH, unsigned int new_size){ - struct _ht *new_ht; /* The new hash table */ - HashElem *elem, *next_elem; /* For looping over existing elements */ - -#if SQLITE_MALLOC_SOFT_LIMIT>0 - if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){ - new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); - } - if( new_size==pH->htsize ) return 0; -#endif - - /* The inability to allocates space for a larger hash table is - ** a performance hit but it is not a fatal error. So mark the - ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of - ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero() - ** only zeroes the requested number of bytes whereas this module will - ** use the actual amount of space allocated for the hash table (which - ** may be larger than the requested amount). - */ - sqlite3BeginBenignMalloc(); - new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) ); - sqlite3EndBenignMalloc(); - - if( new_ht==0 ) return 0; - sqlite3_free(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); - memset(new_ht, 0, new_size*sizeof(struct _ht)); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - next_elem = elem->next; - insertElement(pH, &new_ht[elem->h % new_size], elem); - } - return 1; -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. If no element is found, -** a pointer to a static null element with HashElem.data==0 is returned. -** If pH is not NULL, then the hash for this key is written to *pH. -*/ -static HashElem *findElementWithHash( - const Hash *pH, /* The pH to be searched */ - const char *pKey, /* The key we are searching for */ - unsigned int *pHash /* Write the hash value here */ -){ - HashElem *elem; /* Used to loop thru the element list */ - unsigned int count; /* Number of elements left to test */ - unsigned int h; /* The computed hash */ - static HashElem nullElement = { 0, 0, 0, 0, 0 }; - - h = strHash(pKey); - if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ - struct _ht *pEntry; - pEntry = &pH->ht[h % pH->htsize]; - elem = pEntry->chain; - count = pEntry->count; - }else{ - elem = pH->first; - count = pH->count; - } - if( pHash ) *pHash = h; - while( count ){ - assert( elem!=0 ); - if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){ - return elem; - } - elem = elem->next; - count--; - } - return &nullElement; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void removeElement( - Hash *pH, /* The pH containing "elem" */ - HashElem *elem /* The element to be removed from the pH */ -){ - struct _ht *pEntry; - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - if( pH->ht ){ - pEntry = &pH->ht[elem->h % pH->htsize]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - assert( pEntry->count>0 ); - pEntry->count--; - } - sqlite3_free( elem ); - pH->count--; - if( pH->count==0 ){ - assert( pH->first==0 ); - assert( pH->count==0 ); - sqlite3HashClear(pH); - } -} - -/* Attempt to locate an element of the hash table pH with a key -** that matches pKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){ - assert( pH!=0 ); - assert( pKey!=0 ); - return findElementWithHash(pH, pKey, 0)->data; -} - -/* Insert an element into the hash table pH. The key is pKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created and NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ - unsigned int h; /* the hash of the key modulo hash table size */ - HashElem *elem; /* Used to loop thru the element list */ - HashElem *new_elem; /* New element added to the pH */ - - assert( pH!=0 ); - assert( pKey!=0 ); - elem = findElementWithHash(pH,pKey,&h); - if( elem->data ){ - void *old_data = elem->data; - if( data==0 ){ - removeElement(pH,elem); - }else{ - elem->data = data; - elem->pKey = pKey; - } - return old_data; - } - if( data==0 ) return 0; - new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); - if( new_elem==0 ) return data; - new_elem->pKey = pKey; - new_elem->h = h; - new_elem->data = data; - pH->count++; - if( pH->count>=5 && pH->count > 2*pH->htsize ){ - rehash(pH, pH->count*3); - } - insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem); - return 0; -} - -/************** End of hash.c ************************************************/ -/************** Begin file opcodes.c *****************************************/ -/* Automatically generated. Do not edit */ -/* See the tool/mkopcodec.tcl script for details. */ -#if !defined(SQLITE_OMIT_EXPLAIN) \ - || defined(VDBE_PROFILE) \ - || defined(SQLITE_DEBUG) -#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG) -# define OpHelp(X) "\0" X -#else -# define OpHelp(X) -#endif -SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ - static const char *const azName[] = { - /* 0 */ "Savepoint" OpHelp(""), - /* 1 */ "AutoCommit" OpHelp(""), - /* 2 */ "Transaction" 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 */ "Init" OpHelp("Start at P2"), - /* 9 */ "Goto" OpHelp(""), - /* 10 */ "Gosub" OpHelp(""), - /* 11 */ "InitCoroutine" OpHelp(""), - /* 12 */ "Yield" OpHelp(""), - /* 13 */ "MustBeInt" OpHelp(""), - /* 14 */ "Jump" OpHelp(""), - /* 15 */ "Once" OpHelp(""), - /* 16 */ "If" OpHelp(""), - /* 17 */ "IfNot" OpHelp(""), - /* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"), - /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), - /* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"), - /* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"), - /* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"), - /* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"), - /* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"), - /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"), - /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 29 */ "Found" OpHelp("key=r[P3@P4]"), - /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"), - /* 31 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 32 */ "Last" OpHelp(""), - /* 33 */ "IfSizeBetween" OpHelp(""), - /* 34 */ "SorterSort" OpHelp(""), - /* 35 */ "Sort" OpHelp(""), - /* 36 */ "Rewind" OpHelp(""), - /* 37 */ "SorterNext" OpHelp(""), - /* 38 */ "Prev" OpHelp(""), - /* 39 */ "Next" OpHelp(""), - /* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"), - /* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"), - /* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 48 */ "Program" OpHelp(""), - /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), - /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"), - /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"), - /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"), - /* 57 */ "Lt" OpHelp("IF r[P3]=r[P1]"), - /* 59 */ "ElseEq" OpHelp(""), - /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), - /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 62 */ "IncrVacuum" OpHelp(""), - /* 63 */ "VNext" OpHelp(""), - /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto 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)"), - /* 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 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 114 */ "OpenDup" OpHelp(""), - /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), - /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 118 */ "String8" OpHelp("r[P2]='P4'"), - /* 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 */ "DropTrigger" OpHelp(""), - /* 154 */ "Real" OpHelp("r[P2]=P4"), - /* 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 */ "VCheck" OpHelp(""), - /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), - /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 177 */ "VRename" OpHelp(""), - /* 178 */ "Pagecount" OpHelp(""), - /* 179 */ "MaxPgcnt" OpHelp(""), - /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), - /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"), - /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"), - /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), - /* 184 */ "Trace" OpHelp(""), - /* 185 */ "CursorHint" OpHelp(""), - /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), - /* 187 */ "Noop" OpHelp(""), - /* 188 */ "Explain" OpHelp(""), - /* 189 */ "Abortable" OpHelp(""), - }; - return azName[i]; -} -#endif - -/************** End of opcodes.c *********************************************/ -/************** Begin file os_kv.c *******************************************/ -/* -** 2022-09-06 -** -** 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 an experimental VFS layer that operates on a -** Key/Value storage engine where both keys and values must be pure -** text. -*/ -/* #include */ -#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)) - -/***************************************************************************** -** Debugging logic -*/ - -/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */ -#if 0 -#define SQLITE_KV_TRACE(X) printf X -#else -#define SQLITE_KV_TRACE(X) -#endif - -/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */ -#if 0 -#define SQLITE_KV_LOG(X) printf X -#else -#define SQLITE_KV_LOG(X) -#endif - - -/* -** Forward declaration of objects used by this VFS implementation -*/ -typedef struct KVVfsFile KVVfsFile; - -/* A single open file. There are only two files represented by this -** VFS - the database and the rollback journal. -*/ -struct KVVfsFile { - sqlite3_file base; /* IO methods */ - const char *zClass; /* Storage class */ - int isJournal; /* True if this is a journal file */ - unsigned int nJrnl; /* Space allocated for aJrnl[] */ - char *aJrnl; /* Journal content */ - int szPage; /* Last known page size */ - sqlite3_int64 szDb; /* Database file size. -1 means unknown */ - char *aData; /* Buffer to hold page data */ -}; -#define SQLITE_KVOS_SZ 133073 - -/* -** Methods for KVVfsFile -*/ -static int kvvfsClose(sqlite3_file*); -static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64); -static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64); -static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size); -static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size); -static int kvvfsSyncDb(sqlite3_file*, int flags); -static int kvvfsSyncJrnl(sqlite3_file*, int flags); -static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize); -static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize); -static int kvvfsLock(sqlite3_file*, int); -static int kvvfsUnlock(sqlite3_file*, int); -static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut); -static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg); -static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg); -static int kvvfsSectorSize(sqlite3_file*); -static int kvvfsDeviceCharacteristics(sqlite3_file*); - -/* -** Methods for sqlite3_vfs -*/ -static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename); -static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int kvvfsSleep(sqlite3_vfs*, int microseconds); -static int kvvfsCurrentTime(sqlite3_vfs*, double*); -static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs sqlite3OsKvvfsObject = { - 1, /* iVersion */ - sizeof(KVVfsFile), /* szOsFile */ - 1024, /* mxPathname */ - 0, /* pNext */ - "kvvfs", /* zName */ - 0, /* pAppData */ - kvvfsOpen, /* xOpen */ - kvvfsDelete, /* xDelete */ - kvvfsAccess, /* xAccess */ - kvvfsFullPathname, /* xFullPathname */ - kvvfsDlOpen, /* xDlOpen */ - 0, /* xDlError */ - 0, /* xDlSym */ - 0, /* xDlClose */ - kvvfsRandomness, /* xRandomness */ - kvvfsSleep, /* xSleep */ - kvvfsCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */ -}; - -/* Methods for sqlite3_file objects referencing a database file -*/ -static sqlite3_io_methods kvvfs_db_io_methods = { - 1, /* iVersion */ - kvvfsClose, /* xClose */ - kvvfsReadDb, /* xRead */ - kvvfsWriteDb, /* xWrite */ - kvvfsTruncateDb, /* xTruncate */ - kvvfsSyncDb, /* xSync */ - kvvfsFileSizeDb, /* xFileSize */ - kvvfsLock, /* xLock */ - kvvfsUnlock, /* xUnlock */ - kvvfsCheckReservedLock, /* xCheckReservedLock */ - kvvfsFileControlDb, /* xFileControl */ - kvvfsSectorSize, /* xSectorSize */ - kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/* Methods for sqlite3_file objects referencing a rollback journal -*/ -static sqlite3_io_methods kvvfs_jrnl_io_methods = { - 1, /* iVersion */ - kvvfsClose, /* xClose */ - kvvfsReadJrnl, /* xRead */ - kvvfsWriteJrnl, /* xWrite */ - kvvfsTruncateJrnl, /* xTruncate */ - kvvfsSyncJrnl, /* xSync */ - kvvfsFileSizeJrnl, /* xFileSize */ - kvvfsLock, /* xLock */ - kvvfsUnlock, /* xUnlock */ - kvvfsCheckReservedLock, /* xCheckReservedLock */ - kvvfsFileControlJrnl, /* xFileControl */ - kvvfsSectorSize, /* xSectorSize */ - kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/****** Storage subsystem **************************************************/ -#include -#include -#include - -/* Forward declarations for the low-level storage engine -*/ -static int kvstorageWrite(const char*, const char *zKey, const char *zData); -static int kvstorageDelete(const char*, const char *zKey); -static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); -#define KVSTORAGE_KEY_SZ 32 - -/* Expand the key name with an appropriate prefix and put the result -** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least -** KVSTORAGE_KEY_SZ bytes. -*/ -static void kvstorageMakeKey( - const char *zClass, - const char *zKeyIn, - char *zKeyOut -){ - sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); -} - -/* Write content into a key. zClass is the particular namespace of the -** underlying key/value store to use - either "local" or "session". -** -** Both zKey and zData are zero-terminated pure text strings. -** -** Return the number of errors. -*/ -static int kvstorageWrite( - const char *zClass, - const char *zKey, - const char *zData -){ - FILE *fd; - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - fd = fopen(zXKey, "wb"); - if( fd ){ - SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, - (int)strlen(zData), zData, - strlen(zData)>50 ? "..." : "")); - fputs(zData, fd); - fclose(fd); - return 0; - }else{ - return 1; - } -} - -/* Delete a key (with its corresponding data) from the key/value -** namespace given by zClass. If the key does not previously exist, -** this routine is a no-op. -*/ -static int kvstorageDelete(const char *zClass, const char *zKey){ - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - unlink(zXKey); - SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); - return 0; -} - -/* Read the value associated with a zKey from the key/value namespace given -** by zClass and put the text data associated with that key in the first -** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large -** enough to hold it all. The value put into zBuf must always be zero -** terminated, even if it gets truncated because nBuf is not large enough. -** -** Return the total number of bytes in the data, without truncation, and -** not counting the final zero terminator. Return -1 if the key does -** not exist. -** -** If nBuf<=0 then this routine simply returns the size of the data without -** actually reading it. -*/ -static int kvstorageRead( - const char *zClass, - const char *zKey, - char *zBuf, - int nBuf -){ - FILE *fd; - struct stat buf; - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - if( access(zXKey, R_OK)!=0 - || stat(zXKey, &buf)!=0 - || !S_ISREG(buf.st_mode) - ){ - SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); - return -1; - } - if( nBuf<=0 ){ - return (int)buf.st_size; - }else if( nBuf==1 ){ - zBuf[0] = 0; - SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey, - (int)buf.st_size)); - return (int)buf.st_size; - } - if( nBuf > buf.st_size + 1 ){ - nBuf = buf.st_size + 1; - } - fd = fopen(zXKey, "rb"); - if( fd==0 ){ - SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); - return -1; - }else{ - sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); - fclose(fd); - zBuf[n] = 0; - SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey, - n, zBuf, n>50 ? "..." : "")); - return (int)n; - } -} - -/* -** An internal level of indirection which enables us to replace the -** kvvfs i/o methods with JavaScript implementations in WASM builds. -** Maintenance reminder: if this struct changes in any way, the JSON -** rendering of its structure must be updated in -** sqlite3_wasm_enum_json(). There are no binary compatibility -** concerns, so it does not need an iVersion member. This file is -** necessarily always compiled together with sqlite3_wasm_enum_json(), -** and JS code dynamically creates the mapping of members based on -** that JSON description. -*/ -typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; -struct sqlite3_kvvfs_methods { - int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); - int (*xWrite)(const char *zClass, const char *zKey, const char *zData); - int (*xDelete)(const char *zClass, const char *zKey); - const int nKeySize; -}; - -/* -** This object holds the kvvfs I/O methods which may be swapped out -** for JavaScript-side implementations in WASM builds. In such builds -** it cannot be const, but in native builds it should be so that -** the compiler can hopefully optimize this level of indirection out. -** That said, kvvfs is intended primarily for use in WASM builds. -** -** Note that this is not explicitly flagged as static because the -** amalgamation build will tag it with SQLITE_PRIVATE. -*/ -#ifndef SQLITE_WASM -const -#endif -SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { -kvstorageRead, -kvstorageWrite, -kvstorageDelete, -KVSTORAGE_KEY_SZ -}; - -/****** Utility subroutines ************************************************/ - -/* -** Encode binary into the text encoded used to persist on disk. -** The output text is stored in aOut[], which must be at least -** nData+1 bytes in length. -** -** Return the actual length of the encoded text, not counting the -** zero terminator at the end. -** -** Encoding format -** --------------- -** -** * Non-zero bytes are encoded as upper-case hexadecimal -** -** * A sequence of one or more zero-bytes that are not at the -** beginning of the buffer are encoded as a little-endian -** base-26 number using a..z. "a" means 0. "b" means 1, -** "z" means 25. "ab" means 26. "ac" means 52. And so forth. -** -** * Because there is no overlap between the encoding characters -** of hexadecimal and base-26 numbers, it is always clear where -** one stops and the next begins. -*/ -static int kvvfsEncode(const char *aData, int nData, char *aOut){ - int i, j; - const unsigned char *a = (const unsigned char*)aData; - for(i=j=0; i>4]; - aOut[j++] = "0123456789ABCDEF"[c&0xf]; - }else{ - /* A sequence of 1 or more zeros is stored as a little-endian - ** base-26 number using a..z as the digits. So one zero is "b". - ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb", - ** and so forth. - */ - int k; - for(k=1; i+k0 ){ - aOut[j++] = 'a'+(k%26); - k /= 26; - } - } - } - aOut[j] = 0; - return j; -} - -static const signed char kvvfsHexValue[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* -** Decode the text encoding back to binary. The binary content is -** written into pOut, which must be at least nOut bytes in length. -** -** The return value is the number of bytes actually written into aOut[]. -*/ -static int kvvfsDecode(const char *a, char *aOut, int nOut){ - int i, j; - int c; - const unsigned char *aIn = (const unsigned char*)a; - i = 0; - j = 0; - while( 1 ){ - c = kvvfsHexValue[aIn[i]]; - if( c<0 ){ - int n = 0; - int mult = 1; - c = aIn[i]; - if( c==0 ) break; - while( c>='a' && c<='z' ){ - n += (c - 'a')*mult; - mult *= 26; - c = aIn[++i]; - } - if( j+n>nOut ) return -1; - memset(&aOut[j], 0, n); - j += n; - if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */ - }else{ - aOut[j] = c<<4; - c = kvvfsHexValue[aIn[++i]]; - if( c<0 ) break; - aOut[j++] += c; - i++; - } - } - return j; -} - -/* -** Decode a complete journal file. Allocate space in pFile->aJrnl -** and store the decoding there. Or leave pFile->aJrnl set to NULL -** if an error is encountered. -** -** The first few characters of the text encoding will be a little-endian -** base-26 number (digits a..z) that is the total number of bytes -** in the decoded journal file image. This base-26 number is followed -** by a single space, then the encoding of the journal. The space -** separator is required to act as a terminator for the base-26 number. -*/ -static void kvvfsDecodeJournal( - KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */ - const char *zTxt, /* Text encoding. Zero-terminated */ - int nTxt /* Bytes in zTxt, excluding zero terminator */ -){ - unsigned int n = 0; - int c, i, mult; - i = 0; - mult = 1; - while( (c = zTxt[i++])>='a' && c<='z' ){ - n += (zTxt[i] - 'a')*mult; - mult *= 26; - } - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = sqlite3_malloc64( n ); - if( pFile->aJrnl==0 ){ - pFile->nJrnl = 0; - return; - } - pFile->nJrnl = n; - n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl); - if( nnJrnl ){ - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = 0; - pFile->nJrnl = 0; - } -} - -/* -** Read or write the "sz" element, containing the database file size. -*/ -static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){ - char zData[50]; - zData[0] = 0; - sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1); - return strtoll(zData, 0, 0); -} -static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){ - char zData[50]; - sqlite3_snprintf(sizeof(zData), zData, "%lld", sz); - return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData); -} - -/****** sqlite3_io_methods methods ******************************************/ - -/* -** Close an kvvfs-file. -*/ -static int kvvfsClose(sqlite3_file *pProtoFile){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - - SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass, - pFile->isJournal ? "journal" : "db")); - sqlite3_free(pFile->aJrnl); - sqlite3_free(pFile->aData); - return SQLITE_OK; -} - -/* -** Read from the -journal file. -*/ -static int kvvfsReadJrnl( - sqlite3_file *pProtoFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - assert( pFile->isJournal ); - SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - if( pFile->aJrnl==0 ){ - int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0); - char *aTxt; - if( szTxt<=4 ){ - return SQLITE_IOERR; - } - aTxt = sqlite3_malloc64( szTxt+1 ); - if( aTxt==0 ) return SQLITE_NOMEM; - kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1); - kvvfsDecodeJournal(pFile, aTxt, szTxt); - sqlite3_free(aTxt); - if( pFile->aJrnl==0 ) return SQLITE_IOERR; - } - if( iOfst+iAmt>pFile->nJrnl ){ - return SQLITE_IOERR_SHORT_READ; - } - memcpy(zBuf, pFile->aJrnl+iOfst, iAmt); - return SQLITE_OK; -} - -/* -** Read from the database file. -*/ -static int kvvfsReadDb( - sqlite3_file *pProtoFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - unsigned int pgno; - int got, n; - char zKey[30]; - char *aData = pFile->aData; - assert( iOfst>=0 ); - assert( iAmt>=0 ); - SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - if( iOfst+iAmt>=512 ){ - if( (iOfst % iAmt)!=0 ){ - return SQLITE_IOERR_READ; - } - if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){ - return SQLITE_IOERR_READ; - } - pFile->szPage = iAmt; - pgno = 1 + iOfst/iAmt; - }else{ - pgno = 1; - } - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, - aData, SQLITE_KVOS_SZ-1); - if( got<0 ){ - n = 0; - }else{ - aData[got] = 0; - if( iOfst+iAmt<512 ){ - int k = iOfst+iAmt; - aData[k*2] = 0; - n = kvvfsDecode(aData, &aData[2000], SQLITE_KVOS_SZ-2000); - if( n>=iOfst+iAmt ){ - memcpy(zBuf, &aData[2000+iOfst], iAmt); - n = iAmt; - }else{ - n = 0; - } - }else{ - n = kvvfsDecode(aData, zBuf, iAmt); - } - } - if( nzClass, iAmt, iOfst)); - if( iEnd>=0x10000000 ) return SQLITE_FULL; - if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); - if( aNew==0 ){ - return SQLITE_IOERR_NOMEM; - } - pFile->aJrnl = aNew; - if( pFile->nJrnlaJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl); - } - pFile->nJrnl = iEnd; - } - memcpy(pFile->aJrnl+iOfst, zBuf, iAmt); - return SQLITE_OK; -} - -/* -** Write into the database file. -*/ -static int kvvfsWriteDb( - sqlite3_file *pProtoFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - unsigned int pgno; - char zKey[30]; - char *aData = pFile->aData; - SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - assert( iAmt>=512 && iAmt<=65536 ); - assert( (iAmt & (iAmt-1))==0 ); - assert( pFile->szPage<0 || pFile->szPage==iAmt ); - pFile->szPage = iAmt; - pgno = 1 + iOfst/iAmt; - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - kvvfsEncode(zBuf, iAmt, aData); - if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){ - return SQLITE_IOERR; - } - if( iOfst+iAmt > pFile->szDb ){ - pFile->szDb = iOfst + iAmt; - } - return SQLITE_OK; -} - -/* -** Truncate an kvvfs-file. -*/ -static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); - assert( size==0 ); - sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl"); - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = 0; - pFile->nJrnl = 0; - return SQLITE_OK; -} -static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - if( pFile->szDb>size - && pFile->szPage>0 - && (size % pFile->szPage)==0 - ){ - char zKey[50]; - unsigned int pgno, pgnoMax; - SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size)); - pgno = 1 + size/pFile->szPage; - pgnoMax = 2 + pFile->szDb/pFile->szPage; - while( pgno<=pgnoMax ){ - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey); - pgno++; - } - pFile->szDb = size; - return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK; - } - return SQLITE_IOERR; -} - -/* -** Sync an kvvfs-file. -*/ -static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ - int i, n; - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - char *zOut; - SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass)); - if( pFile->nJrnl<=0 ){ - return kvvfsTruncateJrnl(pProtoFile, 0); - } - zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 ); - if( zOut==0 ){ - return SQLITE_IOERR_NOMEM; - } - n = pFile->nJrnl; - i = 0; - do{ - zOut[i++] = 'a' + (n%26); - n /= 26; - }while( n>0 ); - zOut[i++] = ' '; - kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut); - sqlite3_free(zOut); - return i ? SQLITE_IOERR : SQLITE_OK; -} -static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ - return SQLITE_OK; -} - -/* -** Return the current file-size of an kvvfs-file. -*/ -static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass)); - *pSize = pFile->nJrnl; - return SQLITE_OK; -} -static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass)); - if( pFile->szDb>=0 ){ - *pSize = pFile->szDb; - }else{ - *pSize = kvvfsReadFileSize(pFile); - } - return SQLITE_OK; -} - -/* -** Lock an kvvfs-file. -*/ -static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - assert( !pFile->isJournal ); - SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock)); - - if( eLock!=SQLITE_LOCK_NONE ){ - pFile->szDb = kvvfsReadFileSize(pFile); - } - return SQLITE_OK; -} - -/* -** Unlock an kvvfs-file. -*/ -static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - assert( !pFile->isJournal ); - SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock)); - if( eLock==SQLITE_LOCK_NONE ){ - pFile->szDb = -1; - } - return SQLITE_OK; -} - -/* -** Check if another file-handle holds a RESERVED lock on an kvvfs-file. -*/ -static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){ - SQLITE_KV_LOG(("xCheckReservedLock\n")); - *pResOut = 0; - return SQLITE_OK; -} - -/* -** File control method. For custom operations on an kvvfs-file. -*/ -static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){ - SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op)); - return SQLITE_NOTFOUND; -} -static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){ - SQLITE_KV_LOG(("xFileControl(%d) on database\n", op)); - if( op==SQLITE_FCNTL_SYNC ){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - int rc = SQLITE_OK; - SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass)); - if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){ - rc = SQLITE_IOERR; - } - return rc; - } - return SQLITE_NOTFOUND; -} - -/* -** Return the sector-size in bytes for an kvvfs-file. -*/ -static int kvvfsSectorSize(sqlite3_file *pFile){ - return 512; -} - -/* -** Return the device characteristic flags supported by an kvvfs-file. -*/ -static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){ - return 0; -} - -/****** sqlite3_vfs methods *************************************************/ - -/* -** Open an kvvfs file handle. -*/ -static int kvvfsOpen( - sqlite3_vfs *pProtoVfs, - const char *zName, - sqlite3_file *pProtoFile, - int flags, - int *pOutFlags -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - if( zName==0 ) zName = ""; - SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); - if( strcmp(zName, "local")==0 - || strcmp(zName, "session")==0 - ){ - pFile->isJournal = 0; - pFile->base.pMethods = &kvvfs_db_io_methods; - }else - if( strcmp(zName, "local-journal")==0 - || strcmp(zName, "session-journal")==0 - ){ - pFile->isJournal = 1; - pFile->base.pMethods = &kvvfs_jrnl_io_methods; - }else{ - return SQLITE_CANTOPEN; - } - if( zName[0]=='s' ){ - pFile->zClass = "session"; - }else{ - pFile->zClass = "local"; - } - pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ); - if( pFile->aData==0 ){ - return SQLITE_NOMEM; - } - pFile->aJrnl = 0; - pFile->nJrnl = 0; - pFile->szPage = -1; - pFile->szDb = -1; - return SQLITE_OK; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - if( strcmp(zPath, "local-journal")==0 ){ - sqlite3KvvfsMethods.xDelete("local", "jrnl"); - }else - if( strcmp(zPath, "session-journal")==0 ){ - sqlite3KvvfsMethods.xDelete("session", "jrnl"); - } - return SQLITE_OK; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int kvvfsAccess( - sqlite3_vfs *pProtoVfs, - const char *zPath, - int flags, - int *pResOut -){ - SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); - if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0; - }else - if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0; - }else - if( strcmp(zPath, "local")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0; - }else - if( strcmp(zPath, "session")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0; - }else - { - *pResOut = 0; - } - SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut)); - return SQLITE_OK; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (INST_MAX_PATHNAME+1) bytes. -*/ -static int kvvfsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - size_t nPath; -#ifdef SQLITE_OS_KV_ALWAYS_LOCAL - zPath = "local"; -#endif - nPath = strlen(zPath); - SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath)); - if( nOut -static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ - static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; - struct timeval sNow; - (void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */ - *pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000; - return SQLITE_OK; -} -#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */ - -#if SQLITE_OS_KV -/* -** This routine is called initialize the KV-vfs as the default VFS. -*/ -SQLITE_API int sqlite3_os_init(void){ - return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1); -} -SQLITE_API int sqlite3_os_end(void){ - return SQLITE_OK; -} -#endif /* SQLITE_OS_KV */ - -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) -SQLITE_PRIVATE int sqlite3KvvfsInit(void){ - return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0); -} -#endif - -/************** End of os_kv.c ***********************************************/ -/************** Begin file os_unix.c *****************************************/ -/* -** 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 the VFS implementation for unix-like operating systems -** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others. -** -** There are actually several different VFS implementations in this file. -** The differences are in the way that file locking is done. The default -** implementation uses Posix Advisory Locks. Alternative implementations -** use flock(), dot-files, various proprietary locking schemas, or simply -** skip locking all together. -** -** This source file is organized into divisions where the logic for various -** subfunctions is contained within the appropriate division. PLEASE -** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed -** in the correct division and should be clearly labelled. -** -** The layout of divisions is as follows: -** -** * General-purpose declarations and utility functions. -** * Unique file ID logic used by VxWorks. -** * Various locking primitive implementations (all except proxy locking): -** + for Posix Advisory Locks -** + for no-op locks -** + for dot-file locks -** + for flock() locking -** + for named semaphore locks (VxWorks only) -** + for AFP filesystem locks (MacOSX only) -** * sqlite3_file methods not associated with locking. -** * Definitions of sqlite3_io_methods objects for all locking -** methods plus "finder" functions for each locking method. -** * sqlite3_vfs method implementations. -** * Locking primitives for the proxy uber-locking-method. (MacOSX only) -** * Definitions of sqlite3_vfs objects for all locking methods -** plus implementations of sqlite3_os_init() and sqlite3_os_end(). -*/ -/* #include "sqliteInt.h" */ -#if SQLITE_OS_UNIX /* This file is used on unix only */ - -/* -** There are various methods for file locking used for concurrency -** control: -** -** 1. POSIX locking (the default), -** 2. No locking, -** 3. Dot-file locking, -** 4. flock() locking, -** 5. AFP locking (OSX only), -** 6. Named POSIX semaphores (VXWorks only), -** 7. proxy locking. (OSX only) -** -** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE -** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic -** selection of the appropriate locking style based on the filesystem -** where the database is located. -*/ -#if !defined(SQLITE_ENABLE_LOCKING_STYLE) -# if defined(__APPLE__) -# define SQLITE_ENABLE_LOCKING_STYLE 1 -# else -# define SQLITE_ENABLE_LOCKING_STYLE 0 -# endif -#endif - -/* Use pread() and pwrite() if they are available */ -#if defined(__APPLE__) || defined(__linux__) -# define HAVE_PREAD 1 -# define HAVE_PWRITE 1 -#endif -#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) -# undef USE_PREAD -# define USE_PREAD64 1 -#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE) -# undef USE_PREAD64 -# define USE_PREAD 1 -#endif - -/* -** standard include files. -*/ -#include /* amalgamator: keep */ -#include /* amalgamator: keep */ -#include -#include -#include /* amalgamator: keep */ -/* #include */ -#include /* amalgamator: keep */ -#include -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) -# include -#endif - -#if SQLITE_ENABLE_LOCKING_STYLE -/* # include */ -# include -# include -#endif /* SQLITE_ENABLE_LOCKING_STYLE */ - -/* -** Try to determine if gethostuuid() is available based on standard -** macros. This might sometimes compute the wrong value for some -** obscure platforms. For those cases, simply compile with one of -** the following: -** -** -DHAVE_GETHOSTUUID=0 -** -DHAVE_GETHOSTUUID=1 -** -** None if this matters except when building on Apple products with -** -DSQLITE_ENABLE_LOCKING_STYLE. -*/ -#ifndef HAVE_GETHOSTUUID -# define HAVE_GETHOSTUUID 0 -# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ - (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) -# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ - && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\ - && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0)) -# undef HAVE_GETHOSTUUID -# define HAVE_GETHOSTUUID 1 -# else -# warning "gethostuuid() is disabled." -# endif -# endif -#endif - - -#if OS_VXWORKS -/* # include */ -# include -# include -#endif /* OS_VXWORKS */ - -#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE -# include -#endif - -#ifdef HAVE_UTIME -# include -#endif - -/* -** Allowed values of unixFile.fsFlags -*/ -#define SQLITE_FSFLAGS_IS_MSDOS 0x1 - -/* -** If we are to be thread-safe, include the pthreads header. -*/ -#if SQLITE_THREADSAFE -/* # include */ -#endif - -/* -** Default permissions when creating a new file -*/ -#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS -# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 -#endif - -/* -** Default permissions when creating auto proxy dir -*/ -#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS -# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 -#endif - -/* -** Maximum supported path-length. -*/ -#define MAX_PATHNAME 512 - -/* -** Maximum supported symbolic links -*/ -#define SQLITE_MAX_SYMLINKS 100 - -/* -** Remove and stub certain info for WASI (WebAssembly System -** Interface) builds. -*/ -#ifdef SQLITE_WASI -# undef HAVE_FCHMOD -# undef HAVE_FCHOWN -# undef HAVE_MREMAP -# define HAVE_MREMAP 0 -# ifndef SQLITE_DEFAULT_UNIX_VFS -# define SQLITE_DEFAULT_UNIX_VFS "unix-dotfile" - /* ^^^ should SQLITE_DEFAULT_UNIX_VFS be "unix-none"? */ -# endif -# ifndef F_RDLCK -# define F_RDLCK 0 -# define F_WRLCK 1 -# define F_UNLCK 2 -# if __LONG_MAX == 0x7fffffffL -# define F_GETLK 12 -# define F_SETLK 13 -# define F_SETLKW 14 -# else -# define F_GETLK 5 -# define F_SETLK 6 -# define F_SETLKW 7 -# endif -# endif -#else /* !SQLITE_WASI */ -# ifndef HAVE_FCHMOD -# define HAVE_FCHMOD 1 -# endif -#endif /* SQLITE_WASI */ - -#ifdef SQLITE_WASI -# define osGetpid(X) (pid_t)1 -#else -/* Always cast the getpid() return type for compatibility with -** kernel modules in VxWorks. */ -# define osGetpid(X) (pid_t)getpid() -#endif - -/* -** Only set the lastErrno if the error code is a real error and not -** a normal expected return code of SQLITE_BUSY or SQLITE_OK -*/ -#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) - -/* Forward references */ -typedef struct unixShm unixShm; /* Connection shared memory */ -typedef struct unixShmNode unixShmNode; /* Shared memory instance */ -typedef struct unixInodeInfo unixInodeInfo; /* An i-node */ -typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */ - -/* -** Sometimes, after a file handle is closed by SQLite, the file descriptor -** cannot be closed immediately. In these cases, instances of the following -** structure are used to store the file descriptor while waiting for an -** opportunity to either close or reuse it. -*/ -struct UnixUnusedFd { - int fd; /* File descriptor to close */ - int flags; /* Flags this file descriptor was opened with */ - UnixUnusedFd *pNext; /* Next unused file descriptor on same file */ -}; - -/* -** The unixFile structure is subclass of sqlite3_file specific to the unix -** VFS implementations. -*/ -typedef struct unixFile unixFile; -struct unixFile { - sqlite3_io_methods const *pMethod; /* Always the first entry */ - sqlite3_vfs *pVfs; /* The VFS that created this unixFile */ - unixInodeInfo *pInode; /* Info about locks on this inode */ - int h; /* The file descriptor */ - unsigned char eFileLock; /* The type of lock held on this fd */ - unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ - int lastErrno; /* The unix errno from last I/O error */ - void *lockingContext; /* Locking style specific state */ - UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ - const char *zPath; /* Name of the file */ - unixShm *pShm; /* Shared memory segment information */ - int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ -#if SQLITE_MAX_MMAP_SIZE>0 - int nFetchOut; /* Number of outstanding xFetch refs */ - sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ - sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ - sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ - void *pMapRegion; /* Memory mapped region */ -#endif - int sectorSize; /* Device sector size */ - int deviceCharacteristics; /* Precomputed device characteristics */ -#if SQLITE_ENABLE_LOCKING_STYLE - int openFlags; /* The flags specified at open() */ -#endif -#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) - unsigned fsFlags; /* cached details from statfs() */ -#endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - unsigned iBusyTimeout; /* Wait this many millisec on locks */ - int bBlockOnConnect; /* True to block for SHARED locks */ -#endif -#if OS_VXWORKS - struct vxworksFileId *pId; /* Unique file ID */ -#endif -#ifdef SQLITE_DEBUG - /* The next group of variables are used to track whether or not the - ** transaction counter in bytes 24-27 of database files are updated - ** whenever any part of the database changes. An assertion fault will - ** occur if a file is updated without also updating the transaction - ** counter. This test is made to avoid new problems similar to the - ** one described by ticket #3584. - */ - unsigned char transCntrChng; /* True if the transaction counter changed */ - unsigned char dbUpdate; /* True if any part of database file changed */ - unsigned char inNormalWrite; /* True if in a normal write operation */ - -#endif - -#ifdef SQLITE_TEST - /* In test mode, increase the size of this structure a bit so that - ** it is larger than the struct CrashFile defined in test6.c. - */ - char aPadding[32]; -#endif -}; - -/* This variable holds the process id (pid) from when the xRandomness() -** method was called. If xOpen() is called from a different process id, -** indicating that a fork() has occurred, the PRNG will be reset. -*/ -static pid_t randomnessPid = 0; - -/* -** Allowed values for the unixFile.ctrlFlags bitmask: -*/ -#define UNIXFILE_EXCL 0x01 /* Connections from one process only */ -#define UNIXFILE_RDONLY 0x02 /* Connection is read only */ -#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ -#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX) -# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */ -#else -# define UNIXFILE_DIRSYNC 0x00 -#endif -#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ -#define UNIXFILE_DELETE 0x20 /* Delete on close */ -#define UNIXFILE_URI 0x40 /* Filename might have query parameters */ -#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ - -/* -** Include code that is common to all os_*.c files -*/ -/* #include "os_common.h" */ - -/* -** Define various macros that are missing from some systems. -*/ -#ifndef O_LARGEFILE -# define O_LARGEFILE 0 -#endif -#ifdef SQLITE_DISABLE_LFS -# undef O_LARGEFILE -# define O_LARGEFILE 0 -#endif -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -/* -** The threadid macro resolves to the thread-id or to 0. Used for -** testing and debugging only. -*/ -#if SQLITE_THREADSAFE -#define threadid pthread_self() -#else -#define threadid 0 -#endif - -/* -** HAVE_MREMAP defaults to true on Linux and false everywhere else. -*/ -#if !defined(HAVE_MREMAP) -# if defined(__linux__) && defined(_GNU_SOURCE) -# define HAVE_MREMAP 1 -# else -# define HAVE_MREMAP 0 -# endif -#endif - -/* -** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek() -** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined. -*/ -#ifdef __ANDROID__ -# define lseek lseek64 -#endif - -#ifdef __linux__ -/* -** Linux-specific IOCTL magic numbers used for controlling F2FS -*/ -#define F2FS_IOCTL_MAGIC 0xf5 -#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) -#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) -#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) -#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) -#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32) -#define F2FS_FEATURE_ATOMIC_WRITE 0x0004 -#endif /* __linux__ */ - - -/* -** Different Unix systems declare open() in different ways. Same use -** open(const char*,int,mode_t). Others use open(const char*,int,...). -** The difference is important when using a pointer to the function. -** -** The safest way to deal with the problem is to always use this wrapper -** which always has the same well-defined interface. -*/ -static int posixOpen(const char *zFile, int flags, int mode){ - return open(zFile, flags, mode); -} - -/* Forward reference */ -static int openDirectory(const char*, int*); -static int unixGetpagesize(void); - -/* -** Many system calls are accessed through pointer-to-functions so that -** they may be overridden at runtime to facilitate fault injection during -** testing and sandboxing. The following array holds the names and pointers -** to all overrideable system calls. -*/ -static struct unix_syscall { - const char *zName; /* Name of the system call */ - sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ - sqlite3_syscall_ptr pDefault; /* Default value */ -} aSyscall[] = { - { "open", (sqlite3_syscall_ptr)posixOpen, 0 }, -#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent) - - { "close", (sqlite3_syscall_ptr)close, 0 }, -#define osClose ((int(*)(int))aSyscall[1].pCurrent) - - { "access", (sqlite3_syscall_ptr)access, 0 }, -#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent) - - { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 }, -#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent) - - { "stat", (sqlite3_syscall_ptr)stat, 0 }, -#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent) - -/* -** The DJGPP compiler environment looks mostly like Unix, but it -** lacks the fcntl() system call. So redefine fcntl() to be something -** that always succeeds. This means that locking does not occur under -** DJGPP. But it is DOS - what did you expect? -*/ -#ifdef __DJGPP__ - { "fstat", 0, 0 }, -#define osFstat(a,b,c) 0 -#else - { "fstat", (sqlite3_syscall_ptr)fstat, 0 }, -#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent) -#endif - - { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 }, -#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent) - - { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 }, -#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent) - - { "read", (sqlite3_syscall_ptr)read, 0 }, -#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent) - -#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE - { "pread", (sqlite3_syscall_ptr)pread, 0 }, -#else - { "pread", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent) - -#if defined(USE_PREAD64) - { "pread64", (sqlite3_syscall_ptr)pread64, 0 }, -#else - { "pread64", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent) - - { "write", (sqlite3_syscall_ptr)write, 0 }, -#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent) - -#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE - { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 }, -#else - { "pwrite", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\ - aSyscall[12].pCurrent) - -#if defined(USE_PREAD64) - { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, -#else - { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ - aSyscall[13].pCurrent) - -#if defined(HAVE_FCHMOD) - { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, -#else - { "fchmod", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) - -#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE - { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, -#else - { "fallocate", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) - - { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, -#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) - - { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, -#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) - - { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 }, -#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent) - - { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, -#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) - -#if defined(HAVE_FCHOWN) - { "fchown", (sqlite3_syscall_ptr)fchown, 0 }, -#else - { "fchown", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) - -#if defined(HAVE_FCHOWN) - { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, -#else - { "geteuid", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) - -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) - { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, -#else - { "mmap", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) - -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) - { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, -#else - { "munmap", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) - -#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) - { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, -#else - { "mremap", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent) - -#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 - { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, -#else - { "getpagesize", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent) - -#if defined(HAVE_READLINK) - { "readlink", (sqlite3_syscall_ptr)readlink, 0 }, -#else - { "readlink", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) - -#if defined(HAVE_LSTAT) - { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, -#else - { "lstat", (sqlite3_syscall_ptr)0, 0 }, -#endif -#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) - -#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) -# ifdef __ANDROID__ - { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, -#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) -# else - { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, -#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent) -# endif -#else - { "ioctl", (sqlite3_syscall_ptr)0, 0 }, -#endif - -}; /* End of the overrideable system calls */ - - -/* -** On some systems, calls to fchown() will trigger a message in a security -** log if they come from non-root processes. So avoid calling fchown() if -** we are not running as root. -*/ -static int robustFchown(int fd, uid_t uid, gid_t gid){ -#if defined(HAVE_FCHOWN) - return osGeteuid() ? 0 : osFchown(fd,uid,gid); -#else - return 0; -#endif -} - -/* -** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "unix" VFSes. Return SQLITE_OK upon successfully updating the -** system call pointer, or SQLITE_NOTFOUND if there is no configurable -** system call named zName. -*/ -static int unixSetSystemCall( - sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ - const char *zName, /* Name of system call to override */ - sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */ -){ - unsigned int i; - int rc = SQLITE_NOTFOUND; - - UNUSED_PARAMETER(pNotUsed); - if( zName==0 ){ - /* If no zName is given, restore all system calls to their default - ** settings and return NULL - */ - rc = SQLITE_OK; - for(i=0; i=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break; - if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){ - (void)osUnlink(z); - } - osClose(fd); - sqlite3_log(SQLITE_WARNING, - "attempt to open \"%s\" as file descriptor %d", z, fd); - fd = -1; - if( osOpen("/dev/null", O_RDONLY, m)<0 ) break; - } - if( fd>=0 ){ - if( m!=0 ){ - struct stat statbuf; - if( osFstat(fd, &statbuf)==0 - && statbuf.st_size==0 - && (statbuf.st_mode&0777)!=m - ){ - osFchmod(fd, m); - } - } -#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif - } - return fd; -} - -/* -** Helper functions to obtain and relinquish the global mutex. The -** global mutex is used to protect the unixInodeInfo and -** vxworksFileId objects used by this file, all of which may be -** shared by multiple threads. -** -** Function unixMutexHeld() is used to assert() that the global mutex -** is held when required. This function is only used as part of assert() -** statements. e.g. -** -** unixEnterMutex() -** assert( unixMutexHeld() ); -** unixEnterLeave() -** -** To prevent deadlock, the global unixBigLock must must be acquired -** before the unixInodeInfo.pLockMutex mutex, if both are held. It is -** OK to get the pLockMutex without holding unixBigLock first, but if -** that happens, the unixBigLock mutex must not be acquired until after -** pLockMutex is released. -** -** OK: enter(unixBigLock), enter(pLockInfo) -** OK: enter(unixBigLock) -** OK: enter(pLockInfo) -** ERROR: enter(pLockInfo), enter(unixBigLock) -*/ -static sqlite3_mutex *unixBigLock = 0; -static void unixEnterMutex(void){ - assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */ - sqlite3_mutex_enter(unixBigLock); -} -static void unixLeaveMutex(void){ - assert( sqlite3_mutex_held(unixBigLock) ); - sqlite3_mutex_leave(unixBigLock); -} -#ifdef SQLITE_DEBUG -static int unixMutexHeld(void) { - return sqlite3_mutex_held(unixBigLock); -} -#endif - - -#ifdef SQLITE_HAVE_OS_TRACE -/* -** Helper function for printing out trace information from debugging -** binaries. This returns the string representation of the supplied -** integer lock-type. -*/ -static const char *azFileLock(int eFileLock){ - switch( eFileLock ){ - case NO_LOCK: return "NONE"; - case SHARED_LOCK: return "SHARED"; - case RESERVED_LOCK: return "RESERVED"; - case PENDING_LOCK: return "PENDING"; - case EXCLUSIVE_LOCK: return "EXCLUSIVE"; - } - return "ERROR"; -} -#endif - -#ifdef SQLITE_LOCK_TRACE -/* -** Print out information about all locking operations. -** -** This routine is used for troubleshooting locks on multithreaded -** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE -** command-line option on the compiler. This code is normally -** turned off. -*/ -static int lockTrace(int fd, int op, struct flock *p){ - char *zOpName, *zType; - int s; - int savedErrno; - if( op==F_GETLK ){ - zOpName = "GETLK"; - }else if( op==F_SETLK ){ - zOpName = "SETLK"; - }else{ - s = osFcntl(fd, op, p); - sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); - return s; - } - if( p->l_type==F_RDLCK ){ - zType = "RDLCK"; - }else if( p->l_type==F_WRLCK ){ - zType = "WRLCK"; - }else if( p->l_type==F_UNLCK ){ - zType = "UNLCK"; - }else{ - assert( 0 ); - } - assert( p->l_whence==SEEK_SET ); - s = osFcntl(fd, op, p); - savedErrno = errno; - sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", - threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, - (int)p->l_pid, s); - if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ - struct flock l2; - l2 = *p; - osFcntl(fd, F_GETLK, &l2); - if( l2.l_type==F_RDLCK ){ - zType = "RDLCK"; - }else if( l2.l_type==F_WRLCK ){ - zType = "WRLCK"; - }else if( l2.l_type==F_UNLCK ){ - zType = "UNLCK"; - }else{ - assert( 0 ); - } - sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", - zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); - } - errno = savedErrno; - return s; -} -#undef osFcntl -#define osFcntl lockTrace -#endif /* SQLITE_LOCK_TRACE */ - -/* -** Retry ftruncate() calls that fail due to EINTR -** -** All calls to ftruncate() within this file should be made through -** this wrapper. On the Android platform, bypassing the logic below -** could lead to a corrupt database. -*/ -static int robust_ftruncate(int h, sqlite3_int64 sz){ - int rc; -#ifdef __ANDROID__ - /* On Android, ftruncate() always uses 32-bit offsets, even if - ** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to - ** truncate a file to any size larger than 2GiB. Silently ignore any - ** such attempts. */ - if( sz>(sqlite3_int64)0x7FFFFFFF ){ - rc = SQLITE_OK; - }else -#endif - do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR ); - return rc; -} - -/* -** This routine translates a standard POSIX errno code into something -** useful to the clients of the sqlite3 functions. Specifically, it is -** intended to translate a variety of "try again" errors into SQLITE_BUSY -** and a variety of "please close the file descriptor NOW" errors into -** SQLITE_IOERR -** -** Errors during initialization of locks, or file system support for locks, -** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately. -*/ -static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { - assert( (sqliteIOErr == SQLITE_IOERR_LOCK) || - (sqliteIOErr == SQLITE_IOERR_UNLOCK) || - (sqliteIOErr == SQLITE_IOERR_RDLOCK) || - (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ); - switch (posixError) { - case EACCES: - case EAGAIN: - case ETIMEDOUT: - case EBUSY: - case EINTR: - case ENOLCK: - /* random NFS retry error, unless during file system support - * introspection, in which it actually means what it says */ - return SQLITE_BUSY; - - case EPERM: - return SQLITE_PERM; - - default: - return sqliteIOErr; - } -} - - -/****************************************************************************** -****************** Begin Unique File ID Utility Used By VxWorks *************** -** -** On most versions of unix, we can get a unique ID for a file by concatenating -** the device number and the inode number. But this does not work on VxWorks. -** On VxWorks, a unique file id must be based on the canonical filename. -** -** A pointer to an instance of the following structure can be used as a -** unique file ID in VxWorks. Each instance of this structure contains -** a copy of the canonical filename. There is also a reference count. -** The structure is reclaimed when the number of pointers to it drops to -** zero. -** -** There are never very many files open at one time and lookups are not -** a performance-critical path, so it is sufficient to put these -** structures on a linked list. -*/ -struct vxworksFileId { - struct vxworksFileId *pNext; /* Next in a list of them all */ - int nRef; /* Number of references to this one */ - int nName; /* Length of the zCanonicalName[] string */ - char *zCanonicalName; /* Canonical filename */ -}; - -#if OS_VXWORKS -/* -** All unique filenames are held on a linked list headed by this -** variable: -*/ -static struct vxworksFileId *vxworksFileList = 0; - -/* -** Simplify a filename into its canonical form -** by making the following changes: -** -** * removing any trailing and duplicate / -** * convert /./ into just / -** * convert /A/../ where A is any simple name into just / -** -** Changes are made in-place. Return the new name length. -** -** The original filename is in z[0..n-1]. Return the number of -** characters in the simplified name. -*/ -static int vxworksSimplifyName(char *z, int n){ - int i, j; - while( n>1 && z[n-1]=='/' ){ n--; } - for(i=j=0; i0 && z[j-1]!='/' ){ j--; } - if( j>0 ){ j--; } - i += 2; - continue; - } - } - z[j++] = z[i]; - } - z[j] = 0; - return j; -} - -/* -** Find a unique file ID for the given absolute pathname. Return -** a pointer to the vxworksFileId object. This pointer is the unique -** file ID. -** -** The nRef field of the vxworksFileId object is incremented before -** the object is returned. A new vxworksFileId object is created -** and added to the global list if necessary. -** -** If a memory allocation error occurs, return NULL. -*/ -static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ - struct vxworksFileId *pNew; /* search key and new file ID */ - struct vxworksFileId *pCandidate; /* For looping over existing file IDs */ - int n; /* Length of zAbsoluteName string */ - - assert( zAbsoluteName[0]=='/' ); - n = (int)strlen(zAbsoluteName); - pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) ); - if( pNew==0 ) return 0; - pNew->zCanonicalName = (char*)&pNew[1]; - memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); - n = vxworksSimplifyName(pNew->zCanonicalName, n); - - /* Search for an existing entry that matching the canonical name. - ** If found, increment the reference count and return a pointer to - ** the existing file ID. - */ - unixEnterMutex(); - for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ - if( pCandidate->nName==n - && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 - ){ - sqlite3_free(pNew); - pCandidate->nRef++; - unixLeaveMutex(); - return pCandidate; - } - } - - /* No match was found. We will make a new file ID */ - pNew->nRef = 1; - pNew->nName = n; - pNew->pNext = vxworksFileList; - vxworksFileList = pNew; - unixLeaveMutex(); - return pNew; -} - -/* -** Decrement the reference count on a vxworksFileId object. Free -** the object when the reference count reaches zero. -*/ -static void vxworksReleaseFileId(struct vxworksFileId *pId){ - unixEnterMutex(); - assert( pId->nRef>0 ); - pId->nRef--; - if( pId->nRef==0 ){ - struct vxworksFileId **pp; - for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){} - assert( *pp==pId ); - *pp = pId->pNext; - sqlite3_free(pId); - } - unixLeaveMutex(); -} -#endif /* OS_VXWORKS */ -/*************** End of Unique File ID Utility Used By VxWorks **************** -******************************************************************************/ - - -/****************************************************************************** -*************************** Posix Advisory Locking **************************** -** -** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996) -** section 6.5.2.2 lines 483 through 490 specify that when a process -** sets or clears a lock, that operation overrides any prior locks set -** by the same process. It does not explicitly say so, but this implies -** that it overrides locks set by the same process using a different -** file descriptor. Consider this test case: -** -** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); -** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); -** -** Suppose ./file1 and ./file2 are really the same file (because -** one is a hard or symbolic link to the other) then if you set -** an exclusive lock on fd1, then try to get an exclusive lock -** on fd2, it works. I would have expected the second lock to -** fail since there was already a lock on the file due to fd1. -** But not so. Since both locks came from the same process, the -** second overrides the first, even though they were on different -** file descriptors opened on different file names. -** -** This means that we cannot use POSIX locks to synchronize file access -** among competing threads of the same process. POSIX locks will work fine -** to synchronize access for threads in separate processes, but not -** threads within the same process. -** -** To work around the problem, SQLite has to manage file locks internally -** on its own. Whenever a new database is opened, we have to find the -** specific inode of the database file (the inode is determined by the -** st_dev and st_ino fields of the stat structure that fstat() fills in) -** and check for locks already existing on that inode. When locks are -** created or removed, we have to look at our own internal record of the -** locks to see if another thread has previously set a lock on that same -** inode. -** -** (Aside: The use of inode numbers as unique IDs does not work on VxWorks. -** For VxWorks, we have to use the alternative unique ID system based on -** canonical filename and implemented in the previous division.) -** -** The sqlite3_file structure for POSIX is no longer just an integer file -** descriptor. It is now a structure that holds the integer file -** descriptor and a pointer to a structure that describes the internal -** locks on the corresponding inode. There is one locking structure -** per inode, so if the same inode is opened twice, both unixFile structures -** point to the same locking structure. The locking structure keeps -** a reference count (so we will know when to delete it) and a "cnt" -** field that tells us its internal lock status. cnt==0 means the -** file is unlocked. cnt==-1 means the file has an exclusive lock. -** cnt>0 means there are cnt shared locks on the file. -** -** Any attempt to lock or unlock a file first checks the locking -** structure. The fcntl() system call is only invoked to set a -** POSIX lock if the internal lock structure transitions between -** a locked and an unlocked state. -** -** But wait: there are yet more problems with POSIX advisory locks. -** -** If you close a file descriptor that points to a file that has locks, -** all locks on that file that are owned by the current process are -** released. To work around this problem, each unixInodeInfo object -** maintains a count of the number of pending locks on the inode. -** When an attempt is made to close an unixFile, if there are -** other unixFile open on the same inode that are holding locks, the call -** to close() the file descriptor is deferred until all of the locks clear. -** The unixInodeInfo structure keeps a list of file descriptors that need to -** be closed and that list is walked (and cleared) when the last lock -** clears. -** -** Yet another problem: LinuxThreads do not play well with posix locks. -** -** Many older versions of linux use the LinuxThreads library which is -** not posix compliant. Under LinuxThreads, a lock created by thread -** A cannot be modified or overridden by a different thread B. -** Only thread A can modify the lock. Locking behavior is correct -** if the application uses the newer Native Posix Thread Library (NPTL) -** on linux - with NPTL a lock created by thread A can override locks -** in thread B. But there is no way to know at compile-time which -** threading library is being used. So there is no way to know at -** compile-time whether or not thread A can override locks on thread B. -** One has to do a run-time check to discover the behavior of the -** current process. -** -** SQLite used to support LinuxThreads. But support for LinuxThreads -** was dropped beginning with version 3.7.0. SQLite will still work with -** LinuxThreads provided that (1) there is no more than one connection -** per database file in the same process and (2) database connections -** do not move across threads. -*/ - -/* -** An instance of the following structure serves as the key used -** to locate a particular unixInodeInfo object. -*/ -struct unixFileId { - dev_t dev; /* Device number */ -#if OS_VXWORKS - struct vxworksFileId *pId; /* Unique file ID for vxworks. */ -#else - /* We are told that some versions of Android contain a bug that - ** sizes ino_t at only 32-bits instead of 64-bits. (See - ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c) - ** To work around this, always allocate 64-bits for the inode number. - ** On small machines that only have 32-bit inodes, this wastes 4 bytes, - ** but that should not be a big deal. */ - /* WAS: ino_t ino; */ - u64 ino; /* Inode number */ -#endif -}; - -/* -** An instance of the following structure is allocated for each open -** inode. -** -** A single inode can have multiple file descriptors, so each unixFile -** structure contains a pointer to an instance of this object and this -** object keeps a count of the number of unixFile pointing to it. -** -** Mutex rules: -** -** (1) Only the pLockMutex mutex must be held in order to read or write -** any of the locking fields: -** nShared, nLock, eFileLock, bProcessLock, pUnused -** -** (2) When nRef>0, then the following fields are unchanging and can -** be read (but not written) without holding any mutex: -** fileId, pLockMutex -** -** (3) With the exceptions above, all the fields may only be read -** or written while holding the global unixBigLock mutex. -** -** Deadlock prevention: The global unixBigLock mutex may not -** be acquired while holding the pLockMutex mutex. If both unixBigLock -** and pLockMutex are needed, then unixBigLock must be acquired first. -*/ -struct unixInodeInfo { - struct unixFileId fileId; /* The lookup key */ - sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ - int nShared; /* Number of SHARED locks held */ - int nLock; /* Number of outstanding file locks */ - unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ - unsigned char bProcessLock; /* An exclusive process lock is held */ - UnixUnusedFd *pUnused; /* Unused file descriptors to close */ - int nRef; /* Number of pointers to this structure */ - unixShmNode *pShmNode; /* Shared memory associated with this inode */ - unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ - unixInodeInfo *pPrev; /* .... doubly linked */ -#if SQLITE_ENABLE_LOCKING_STYLE - unsigned long long sharedByte; /* for AFP simulated shared lock */ -#endif -#if OS_VXWORKS - sem_t *pSem; /* Named POSIX semaphore */ - char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */ -#endif -}; - -/* -** A lists of all unixInodeInfo objects. -** -** Must hold unixBigLock in order to read or write this variable. -*/ -static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ - -#ifdef SQLITE_DEBUG -/* -** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. -** This routine is used only within assert() to help verify correct mutex -** usage. -*/ -int unixFileMutexHeld(unixFile *pFile){ - assert( pFile->pInode ); - return sqlite3_mutex_held(pFile->pInode->pLockMutex); -} -int unixFileMutexNotheld(unixFile *pFile){ - assert( pFile->pInode ); - return sqlite3_mutex_notheld(pFile->pInode->pLockMutex); -} -#endif - -/* -** -** This function - unixLogErrorAtLine(), is only ever called via the macro -** unixLogError(). -** -** It is invoked after an error occurs in an OS function and errno has been -** set. It logs a message using sqlite3_log() containing the current value of -** errno and, if possible, the human-readable equivalent from strerror() or -** strerror_r(). -** -** The first argument passed to the macro should be the error code that -** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). -** The two subsequent arguments should be the name of the OS function that -** failed (e.g. "unlink", "open") and the associated file-system path, -** if any. -*/ -#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__) -static int unixLogErrorAtLine( - int errcode, /* SQLite error code */ - const char *zFunc, /* Name of OS function that failed */ - const char *zPath, /* File path associated with error */ - int iLine /* Source line number where error occurred */ -){ - char *zErr; /* Message from strerror() or equivalent */ - int iErrno = errno; /* Saved syscall error number */ - - /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use - ** the strerror() function to obtain the human-readable error message - ** equivalent to errno. Otherwise, use strerror_r(). - */ -#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R) - char aErr[80]; - memset(aErr, 0, sizeof(aErr)); - zErr = aErr; - - /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined, - ** assume that the system provides the GNU version of strerror_r() that - ** returns a pointer to a buffer containing the error message. That pointer - ** may point to aErr[], or it may point to some static storage somewhere. - ** Otherwise, assume that the system provides the POSIX version of - ** strerror_r(), which always writes an error message into aErr[]. - ** - ** If the code incorrectly assumes that it is the POSIX version that is - ** available, the error message will often be an empty string. Not a - ** huge problem. Incorrectly concluding that the GNU version is available - ** could lead to a segfault though. - ** - ** Forum post 3f13857fa4062301 reports that the Android SDK may use - ** int-type return, depending on its version. - */ -#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \ - && !defined(ANDROID) && !defined(__ANDROID__) - zErr = -# endif - strerror_r(iErrno, aErr, sizeof(aErr)-1); - -#elif SQLITE_THREADSAFE - /* This is a threadsafe build, but strerror_r() is not available. */ - zErr = ""; -#else - /* Non-threadsafe build, use strerror(). */ - zErr = strerror(iErrno); -#endif - - if( zPath==0 ) zPath = ""; - sqlite3_log(errcode, - "os_unix.c:%d: (%d) %s(%s) - %s", - iLine, iErrno, zFunc, zPath, zErr - ); - - return errcode; -} - -/* -** Close a file descriptor. -** -** We assume that close() almost always works, since it is only in a -** very sick application or on a very sick platform that it might fail. -** If it does fail, simply leak the file descriptor, but do log the -** error. -** -** Note that it is not safe to retry close() after EINTR since the -** file descriptor might have already been reused by another thread. -** So we don't even try to recover from an EINTR. Just log the error -** and move on. -*/ -static void robust_close(unixFile *pFile, int h, int lineno){ - if( osClose(h) ){ - unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close", - pFile ? pFile->zPath : 0, lineno); - } -} - -/* -** Set the pFile->lastErrno. Do this in a subroutine as that provides -** a convenient place to set a breakpoint. -*/ -static void storeLastErrno(unixFile *pFile, int error){ - pFile->lastErrno = error; -} - -/* -** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. -*/ -static void closePendingFds(unixFile *pFile){ - unixInodeInfo *pInode = pFile->pInode; - UnixUnusedFd *p; - UnixUnusedFd *pNext; - assert( unixFileMutexHeld(pFile) ); - for(p=pInode->pUnused; p; p=pNext){ - pNext = p->pNext; - robust_close(pFile, p->fd, __LINE__); - sqlite3_free(p); - } - pInode->pUnused = 0; -} - -/* -** Release a unixInodeInfo structure previously allocated by findInodeInfo(). -** -** The global mutex must be held when this routine is called, but the mutex -** on the inode being deleted must NOT be held. -*/ -static void releaseInodeInfo(unixFile *pFile){ - unixInodeInfo *pInode = pFile->pInode; - assert( unixMutexHeld() ); - assert( unixFileMutexNotheld(pFile) ); - if( ALWAYS(pInode) ){ - pInode->nRef--; - if( pInode->nRef==0 ){ - assert( pInode->pShmNode==0 ); - sqlite3_mutex_enter(pInode->pLockMutex); - closePendingFds(pFile); - sqlite3_mutex_leave(pInode->pLockMutex); - if( pInode->pPrev ){ - assert( pInode->pPrev->pNext==pInode ); - pInode->pPrev->pNext = pInode->pNext; - }else{ - assert( inodeList==pInode ); - inodeList = pInode->pNext; - } - if( pInode->pNext ){ - assert( pInode->pNext->pPrev==pInode ); - pInode->pNext->pPrev = pInode->pPrev; - } - sqlite3_mutex_free(pInode->pLockMutex); - sqlite3_free(pInode); - } - } -} - -/* -** Given a file descriptor, locate the unixInodeInfo object that -** describes that file descriptor. Create a new one if necessary. The -** return value might be uninitialized if an error occurs. -** -** The global mutex must held when calling this routine. -** -** Return an appropriate error code. -*/ -static int findInodeInfo( - unixFile *pFile, /* Unix file with file desc used in the key */ - unixInodeInfo **ppInode /* Return the unixInodeInfo object here */ -){ - int rc; /* System call return code */ - int fd; /* The file descriptor for pFile */ - struct unixFileId fileId; /* Lookup key for the unixInodeInfo */ - struct stat statbuf; /* Low-level file information */ - unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */ - - assert( unixMutexHeld() ); - - /* Get low-level information about the file that we can used to - ** create a unique name for the file. - */ - fd = pFile->h; - rc = osFstat(fd, &statbuf); - if( rc!=0 ){ - storeLastErrno(pFile, errno); -#if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS) - if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; -#endif - return SQLITE_IOERR; - } - -#ifdef __APPLE__ - /* On OS X on an msdos filesystem, the inode number is reported - ** incorrectly for zero-size files. See ticket #3260. To work - ** around this problem (we consider it a bug in OS X, not SQLite) - ** we always increase the file size to 1 by writing a single byte - ** prior to accessing the inode number. The one byte written is - ** an ASCII 'S' character which also happens to be the first byte - ** in the header of every SQLite database. In this way, if there - ** is a race condition such that another thread has already populated - ** the first page of the database, no damage is done. - */ - if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ - do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); - if( rc!=1 ){ - storeLastErrno(pFile, errno); - return SQLITE_IOERR; - } - rc = osFstat(fd, &statbuf); - if( rc!=0 ){ - storeLastErrno(pFile, errno); - return SQLITE_IOERR; - } - } -#endif - - memset(&fileId, 0, sizeof(fileId)); - fileId.dev = statbuf.st_dev; -#if OS_VXWORKS - fileId.pId = pFile->pId; -#else - fileId.ino = (u64)statbuf.st_ino; -#endif - assert( unixMutexHeld() ); - pInode = inodeList; - while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ - pInode = pInode->pNext; - } - if( pInode==0 ){ - pInode = sqlite3_malloc64( sizeof(*pInode) ); - if( pInode==0 ){ - return SQLITE_NOMEM_BKPT; - } - memset(pInode, 0, sizeof(*pInode)); - memcpy(&pInode->fileId, &fileId, sizeof(fileId)); - if( sqlite3GlobalConfig.bCoreMutex ){ - pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pInode->pLockMutex==0 ){ - sqlite3_free(pInode); - return SQLITE_NOMEM_BKPT; - } - } - pInode->nRef = 1; - assert( unixMutexHeld() ); - pInode->pNext = inodeList; - pInode->pPrev = 0; - if( inodeList ) inodeList->pPrev = pInode; - inodeList = pInode; - }else{ - pInode->nRef++; - } - *ppInode = pInode; - return SQLITE_OK; -} - -/* -** Return TRUE if pFile has been renamed or unlinked since it was first opened. -*/ -static int fileHasMoved(unixFile *pFile){ -#if OS_VXWORKS - return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; -#else - struct stat buf; - return pFile->pInode!=0 && - (osStat(pFile->zPath, &buf)!=0 - || (u64)buf.st_ino!=pFile->pInode->fileId.ino); -#endif -} - - -/* -** Check a unixFile that is a database. Verify the following: -** -** (1) There is exactly one hard link on the file -** (2) The file is not a symbolic link -** (3) The file has not been renamed or unlinked -** -** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right. -*/ -static void verifyDbFile(unixFile *pFile){ - struct stat buf; - int rc; - - /* These verifications occurs for the main database only */ - if( pFile->ctrlFlags & UNIXFILE_NOLOCK ) return; - - rc = osFstat(pFile->h, &buf); - if( rc!=0 ){ - sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); - return; - } - if( buf.st_nlink==0 ){ - sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath); - return; - } - if( buf.st_nlink>1 ){ - sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath); - return; - } - if( fileHasMoved(pFile) ){ - sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); - return; - } -} - - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, set *pResOut -** to a non-zero value otherwise *pResOut is set to zero. The return value -** is set to SQLITE_OK unless an I/O error occurs during lock checking. -*/ -static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ - int rc = SQLITE_OK; - int reserved = 0; - unixFile *pFile = (unixFile*)id; - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - assert( pFile ); - assert( pFile->eFileLock<=SHARED_LOCK ); - sqlite3_mutex_enter(pFile->pInode->pLockMutex); - - /* Check if a thread in this process holds such a lock */ - if( pFile->pInode->eFileLock>SHARED_LOCK ){ - reserved = 1; - } - - /* Otherwise see if some other process holds it. - */ -#ifndef __DJGPP__ - if( !reserved && !pFile->pInode->bProcessLock ){ - struct flock lock; - lock.l_whence = SEEK_SET; - lock.l_start = RESERVED_BYTE; - lock.l_len = 1; - lock.l_type = F_WRLCK; - if( osFcntl(pFile->h, F_GETLK, &lock) ){ - rc = SQLITE_IOERR_CHECKRESERVEDLOCK; - storeLastErrno(pFile, errno); - } else if( lock.l_type!=F_UNLCK ){ - reserved = 1; - } - } -#endif - - sqlite3_mutex_leave(pFile->pInode->pLockMutex); - OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); - - *pResOut = reserved; - return rc; -} - -/* Forward declaration*/ -static int unixSleep(sqlite3_vfs*,int); - -/* -** Set a posix-advisory-lock. -** -** There are two versions of this routine. If compiled with -** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter -** which is a pointer to a unixFile. If the unixFile->iBusyTimeout -** value is set, then it is the number of milliseconds to wait before -** failing the lock. The iBusyTimeout value is always reset back to -** zero on each call. -** -** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking -** attempt to set the lock. -*/ -#ifndef SQLITE_ENABLE_SETLK_TIMEOUT -# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) -#else -static int osSetPosixAdvisoryLock( - int h, /* The file descriptor on which to take the lock */ - struct flock *pLock, /* The description of the lock */ - unixFile *pFile /* Structure holding timeout value */ -){ - int tm = pFile->iBusyTimeout; - int rc = osFcntl(h,F_SETLK,pLock); - while( rc<0 && tm>0 ){ - /* On systems that support some kind of blocking file lock with a timeout, - ** make appropriate changes here to invoke that blocking file lock. On - ** generic posix, however, there is no such API. So we simply try the - ** lock once every millisecond until either the timeout expires, or until - ** the lock is obtained. */ - unixSleep(0,1000); - rc = osFcntl(h,F_SETLK,pLock); - tm--; - } - return rc; -} -#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ - - -/* -** Attempt to set a system-lock on the file pFile. The lock is -** described by pLock. -** -** If the pFile was opened read/write from unix-excl, then the only lock -** ever obtained is an exclusive lock, and it is obtained exactly once -** the first time any lock is attempted. All subsequent system locking -** operations become no-ops. Locking operations still happen internally, -** in order to coordinate access between separate database connections -** within this process, but all of that is handled in memory and the -** operating system does not participate. -** -** This function is a pass-through to fcntl(F_SETLK) if pFile is using -** any VFS other than "unix-excl" or if pFile is opened on "unix-excl" -** and is read-only. -** -** Zero is returned if the call completes successfully, or -1 if a call -** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). -*/ -static int unixFileLock(unixFile *pFile, struct flock *pLock){ - int rc; - unixInodeInfo *pInode = pFile->pInode; - assert( pInode!=0 ); - assert( sqlite3_mutex_held(pInode->pLockMutex) ); - if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ - if( pInode->bProcessLock==0 ){ - struct flock lock; - /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */ - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - lock.l_type = F_WRLCK; - rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); - if( rc<0 ) return rc; - pInode->bProcessLock = 1; - pInode->nLock++; - }else{ - rc = 0; - } - }else{ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK - && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE - ){ - rc = osFcntl(pFile->h, F_SETLKW, pLock); - }else -#endif - rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); - } - return rc; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -*/ -static int unixLock(sqlite3_file *id, int eFileLock){ - /* The following describes the implementation of the various locks and - ** lock transitions in terms of the POSIX advisory shared and exclusive - ** lock primitives (called read-locks and write-locks below, to avoid - ** confusion with SQLite lock names). The algorithms are complicated - ** slightly in order to be compatible with Windows95 systems simultaneously - ** accessing the same database file, in case that is ever required. - ** - ** Symbols defined in os.h identify the 'pending byte' and the 'reserved - ** byte', each single bytes at well known offsets, and the 'shared byte - ** range', a range of 510 bytes at a well known offset. - ** - ** To obtain a SHARED lock, a read-lock is obtained on the 'pending - ** byte'. If this is successful, 'shared byte range' is read-locked - ** and the lock on the 'pending byte' released. (Legacy note: When - ** SQLite was first developed, Windows95 systems were still very common, - ** and Windows95 lacks a shared-lock capability. So on Windows95, a - ** single randomly selected by from the 'shared byte range' is locked. - ** Windows95 is now pretty much extinct, but this work-around for the - ** lack of shared-locks on Windows95 lives on, for backwards - ** compatibility.) - ** - ** A process may only obtain a RESERVED lock after it has a SHARED lock. - ** A RESERVED lock is implemented by grabbing a write-lock on the - ** 'reserved byte'. - ** - ** An EXCLUSIVE lock may only be requested after either a SHARED or - ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining - ** a write-lock on the entire 'shared byte range'. Since all other locks - ** require a read-lock on one of the bytes within this range, this ensures - ** that no other locks are held on the database. - ** - ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then - ** a PENDING lock is obtained first. A PENDING lock is implemented by - ** obtaining a write-lock on the 'pending byte'. This ensures that no new - ** SHARED locks can be obtained, but existing SHARED locks are allowed to - ** persist. If the call to this function fails to obtain the EXCLUSIVE - ** lock in this case, it holds the PENDING lock instead. The client may - ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED - ** locks have cleared. - */ - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - unixInodeInfo *pInode; - struct flock lock; - int tErrno = 0; - - assert( pFile ); - OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, - azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared, - osGetpid(0))); - - /* If there is already a lock of this type or more restrictive on the - ** unixFile, do nothing. Don't use the end_lock: exit path, as - ** unixEnterMutex() hasn't been called yet. - */ - if( pFile->eFileLock>=eFileLock ){ - OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h, - azFileLock(eFileLock))); - return SQLITE_OK; - } - - /* Make sure the locking sequence is correct. - ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pending lock. - ** (3) A shared lock is always held when a reserve lock is requested. - */ - assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); - assert( eFileLock!=PENDING_LOCK ); - assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); - - /* This mutex is needed because pFile->pInode is shared across threads - */ - pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - - /* If some thread using this PID has a lock via a different unixFile* - ** handle that precludes the requested lock, return BUSY. - */ - if( (pFile->eFileLock!=pInode->eFileLock && - (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) - ){ - rc = SQLITE_BUSY; - goto end_lock; - } - - /* If a SHARED lock is requested, and some thread using this PID already - ** has a SHARED or RESERVED lock, then increment reference counts and - ** return SQLITE_OK. - */ - if( eFileLock==SHARED_LOCK && - (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ - assert( eFileLock==SHARED_LOCK ); - assert( pFile->eFileLock==0 ); - assert( pInode->nShared>0 ); - pFile->eFileLock = SHARED_LOCK; - pInode->nShared++; - pInode->nLock++; - goto end_lock; - } - - - /* A PENDING lock is needed before acquiring a SHARED lock and before - ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will - ** be released. - */ - lock.l_len = 1L; - lock.l_whence = SEEK_SET; - if( eFileLock==SHARED_LOCK - || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock==RESERVED_LOCK) - ){ - lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); - lock.l_start = PENDING_BYTE; - if( unixFileLock(pFile, &lock) ){ - tErrno = errno; - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); - } - goto end_lock; - }else if( eFileLock==EXCLUSIVE_LOCK ){ - pFile->eFileLock = PENDING_LOCK; - pInode->eFileLock = PENDING_LOCK; - } - } - - - /* If control gets to this point, then actually go ahead and make - ** operating system calls for the specified lock. - */ - if( eFileLock==SHARED_LOCK ){ - assert( pInode->nShared==0 ); - assert( pInode->eFileLock==0 ); - assert( rc==SQLITE_OK ); - - /* Now get the read-lock */ - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - if( unixFileLock(pFile, &lock) ){ - tErrno = errno; - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - } - - /* Drop the temporary PENDING lock */ - lock.l_start = PENDING_BYTE; - lock.l_len = 1L; - lock.l_type = F_UNLCK; - if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ - /* This could happen with a network mount */ - tErrno = errno; - rc = SQLITE_IOERR_UNLOCK; - } - - if( rc ){ - if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); - } - goto end_lock; - }else{ - pFile->eFileLock = SHARED_LOCK; - pInode->nLock++; - pInode->nShared = 1; - } - }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ - /* We are trying for an exclusive lock but another thread in this - ** same process is still holding a shared lock. */ - rc = SQLITE_BUSY; - }else{ - /* The request was for a RESERVED or EXCLUSIVE lock. It is - ** assumed that there is a SHARED or greater lock on the file - ** already. - */ - assert( 0!=pFile->eFileLock ); - lock.l_type = F_WRLCK; - - assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK ); - if( eFileLock==RESERVED_LOCK ){ - lock.l_start = RESERVED_BYTE; - lock.l_len = 1L; - }else{ - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - } - - if( unixFileLock(pFile, &lock) ){ - tErrno = errno; - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); - } - } - } - - -#ifdef SQLITE_DEBUG - /* Set up the transaction-counter change checking flags when - ** transitioning from a SHARED to a RESERVED lock. The change - ** from SHARED to RESERVED marks the beginning of a normal - ** write operation (not a hot journal rollback). - */ - if( rc==SQLITE_OK - && pFile->eFileLock<=SHARED_LOCK - && eFileLock==RESERVED_LOCK - ){ - pFile->transCntrChng = 0; - pFile->dbUpdate = 0; - pFile->inNormalWrite = 1; - } -#endif - - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - pInode->eFileLock = eFileLock; - } - -end_lock: - sqlite3_mutex_leave(pInode->pLockMutex); - OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), - rc==SQLITE_OK ? "ok" : "failed")); - return rc; -} - -/* -** Add the file descriptor used by file handle pFile to the corresponding -** pUnused list. -*/ -static void setPendingFd(unixFile *pFile){ - unixInodeInfo *pInode = pFile->pInode; - UnixUnusedFd *p = pFile->pPreallocatedUnused; - assert( unixFileMutexHeld(pFile) ); - p->pNext = pInode->pUnused; - pInode->pUnused = p; - pFile->h = -1; - pFile->pPreallocatedUnused = 0; -} - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -** -** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED -** the byte range is divided into 2 parts and the first part is unlocked then -** set to a read lock, then the other part is simply unlocked. This works -** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to -** remove the write lock on a region when a read lock is set. -*/ -static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ - unixFile *pFile = (unixFile*)id; - unixInodeInfo *pInode; - struct flock lock; - int rc = SQLITE_OK; - - assert( pFile ); - OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, - pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - osGetpid(0))); - - assert( eFileLock<=SHARED_LOCK ); - if( pFile->eFileLock<=eFileLock ){ - return SQLITE_OK; - } - pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - assert( pInode->nShared!=0 ); - if( pFile->eFileLock>SHARED_LOCK ){ - assert( pInode->eFileLock==pFile->eFileLock ); - -#ifdef SQLITE_DEBUG - /* When reducing a lock such that other processes can start - ** reading the database file again, make sure that the - ** transaction counter was updated if any part of the database - ** file changed. If the transaction counter is not updated, - ** other connections to the same file might not realize that - ** the file has changed and hence might not know to flush their - ** cache. The use of a stale cache can lead to database corruption. - */ - pFile->inNormalWrite = 0; -#endif - - /* downgrading to a shared lock on NFS involves clearing the write lock - ** before establishing the readlock - to avoid a race condition we downgrade - ** the lock in 2 blocks, so that part of the range will be covered by a - ** write lock until the rest is covered by a read lock: - ** 1: [WWWWW] - ** 2: [....W] - ** 3: [RRRRW] - ** 4: [RRRR.] - */ - if( eFileLock==SHARED_LOCK ){ -#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE - (void)handleNFSUnlock; - assert( handleNFSUnlock==0 ); -#endif -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - if( handleNFSUnlock ){ - int tErrno; /* Error code from system call errors */ - off_t divSize = SHARED_SIZE - 1; - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - tErrno = errno; - rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); - goto end_unlock; - } - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - tErrno = errno; - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); - if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); - } - goto end_unlock; - } - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST+divSize; - lock.l_len = SHARED_SIZE-divSize; - if( unixFileLock(pFile, &lock)==(-1) ){ - tErrno = errno; - rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); - goto end_unlock; - } - }else -#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ - { - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - if( unixFileLock(pFile, &lock) ){ - /* In theory, the call to unixFileLock() cannot fail because another - ** process is holding an incompatible lock. If it does, this - ** indicates that the other process is not following the locking - ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning - ** SQLITE_BUSY would confuse the upper layer (in practice it causes - ** an assert to fail). */ - rc = SQLITE_IOERR_RDLOCK; - storeLastErrno(pFile, errno); - goto end_unlock; - } - } - } - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = PENDING_BYTE; - lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( unixFileLock(pFile, &lock)==0 ){ - pInode->eFileLock = SHARED_LOCK; - }else{ - rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, errno); - goto end_unlock; - } - } - if( eFileLock==NO_LOCK ){ - /* Decrement the shared lock counter. Release the lock using an - ** OS call only when all threads in this same process have released - ** the lock. - */ - pInode->nShared--; - if( pInode->nShared==0 ){ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = lock.l_len = 0L; - if( unixFileLock(pFile, &lock)==0 ){ - pInode->eFileLock = NO_LOCK; - }else{ - rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, errno); - pInode->eFileLock = NO_LOCK; - pFile->eFileLock = NO_LOCK; - } - } - - /* Decrement the count of locks against this same file. When the - ** count reaches zero, close any other file descriptors whose close - ** was deferred because of outstanding locks. - */ - pInode->nLock--; - assert( pInode->nLock>=0 ); - if( pInode->nLock==0 ) closePendingFds(pFile); - } - -end_unlock: - sqlite3_mutex_leave(pInode->pLockMutex); - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - } - return rc; -} - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -*/ -static int unixUnlock(sqlite3_file *id, int eFileLock){ -#if SQLITE_MAX_MMAP_SIZE>0 - assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 ); -#endif - return posixUnlock(id, eFileLock, 0); -} - -#if SQLITE_MAX_MMAP_SIZE>0 -static int unixMapfile(unixFile *pFd, i64 nByte); -static void unixUnmapfile(unixFile *pFd); -#endif - -/* -** This function performs the parts of the "close file" operation -** common to all locking schemes. It closes the directory and file -** handles, if they are valid, and sets all fields of the unixFile -** structure to 0. -** -** It is *not* necessary to hold the mutex when this routine is called, -** even on VxWorks. A mutex will be acquired on VxWorks by the -** vxworksReleaseFileId() routine. -*/ -static int closeUnixFile(sqlite3_file *id){ - unixFile *pFile = (unixFile*)id; -#if SQLITE_MAX_MMAP_SIZE>0 - unixUnmapfile(pFile); -#endif - if( pFile->h>=0 ){ - robust_close(pFile, pFile->h, __LINE__); - pFile->h = -1; - } -#if OS_VXWORKS - if( pFile->pId ){ - if( pFile->ctrlFlags & UNIXFILE_DELETE ){ - osUnlink(pFile->pId->zCanonicalName); - } - vxworksReleaseFileId(pFile->pId); - pFile->pId = 0; - } -#endif -#ifdef SQLITE_UNLINK_AFTER_CLOSE - if( pFile->ctrlFlags & UNIXFILE_DELETE ){ - osUnlink(pFile->zPath); - sqlite3_free(*(char**)&pFile->zPath); - pFile->zPath = 0; - } -#endif - OSTRACE(("CLOSE %-3d\n", pFile->h)); - OpenCounter(-1); - sqlite3_free(pFile->pPreallocatedUnused); - memset(pFile, 0, sizeof(unixFile)); - return SQLITE_OK; -} - -/* -** Close a file. -*/ -static int unixClose(sqlite3_file *id){ - int rc = SQLITE_OK; - unixFile *pFile = (unixFile *)id; - unixInodeInfo *pInode = pFile->pInode; - - assert( pInode!=0 ); - verifyDbFile(pFile); - unixUnlock(id, NO_LOCK); - assert( unixFileMutexNotheld(pFile) ); - unixEnterMutex(); - - /* unixFile.pInode is always valid here. Otherwise, a different close - ** routine (e.g. nolockClose()) would be called instead. - */ - assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); - sqlite3_mutex_enter(pInode->pLockMutex); - if( pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->pUnused list. It will be automatically closed - ** when the last lock is cleared. - */ - setPendingFd(pFile); - } - sqlite3_mutex_leave(pInode->pLockMutex); - releaseInodeInfo(pFile); - assert( pFile->pShm==0 ); - rc = closeUnixFile(id); - unixLeaveMutex(); - return rc; -} - -/************** End of the posix advisory lock implementation ***************** -******************************************************************************/ - -/****************************************************************************** -****************************** No-op Locking ********************************** -** -** Of the various locking implementations available, this is by far the -** simplest: locking is ignored. No attempt is made to lock the database -** file for reading or writing. -** -** This locking mode is appropriate for use on read-only databases -** (ex: databases that are burned into CD-ROM, for example.) It can -** also be used if the application employs some external mechanism to -** prevent simultaneous access of the same database by two or more -** database connections. But there is a serious risk of database -** corruption if this locking mode is used in situations where multiple -** database connections are accessing the same database file at the same -** time and one or more of those connections are writing. -*/ - -static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){ - UNUSED_PARAMETER(NotUsed); - *pResOut = 0; - return SQLITE_OK; -} -static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return SQLITE_OK; -} -static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return SQLITE_OK; -} - -/* -** Close the file. -*/ -static int nolockClose(sqlite3_file *id) { - return closeUnixFile(id); -} - -/******************* End of the no-op lock implementation ********************* -******************************************************************************/ - -/****************************************************************************** -************************* Begin dot-file Locking ****************************** -** -** The dotfile locking implementation uses the existence of separate lock -** files (really a directory) to control access to the database. This works -** on just about every filesystem imaginable. But there are serious downsides: -** -** (1) There is zero concurrency. A single reader blocks all other -** connections from reading or writing the database. -** -** (2) An application crash or power loss can leave stale lock files -** sitting around that need to be cleared manually. -** -** Nevertheless, a dotlock is an appropriate locking mode for use if no -** other locking strategy is available. -** -** Dotfile locking works by creating a subdirectory in the same directory as -** the database and with the same name but with a ".lock" extension added. -** The existence of a lock directory implies an EXCLUSIVE lock. All other -** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE. -*/ - -/* -** The file suffix added to the data base filename in order to create the -** lock directory. -*/ -#define DOTLOCK_SUFFIX ".lock" - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If the caller holds a SHARED -** or greater lock when it is called, then it is assumed that no other -** client may hold RESERVED. Or, if the caller holds no lock, then it -** is assumed another client holds RESERVED if the lock-file exists. -*/ -static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { - unixFile *pFile = (unixFile*)id; - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - if( pFile->eFileLock>=SHARED_LOCK ){ - *pResOut = 0; - }else{ - *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0; - } - OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut)); - return SQLITE_OK; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -** -** With dotfile locking, we really only support state (4): EXCLUSIVE. -** But we track the other locking levels internally. -*/ -static int dotlockLock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - char *zLockFile = (char *)pFile->lockingContext; - int rc = SQLITE_OK; - - - /* If we have any lock, then the lock file already exists. All we have - ** to do is adjust our internal record of the lock level. - */ - if( pFile->eFileLock > NO_LOCK ){ - pFile->eFileLock = eFileLock; - /* Always update the timestamp on the old file */ -#ifdef HAVE_UTIME - utime(zLockFile, NULL); -#else - utimes(zLockFile, NULL); -#endif - return SQLITE_OK; - } - - /* grab an exclusive lock */ - rc = osMkdir(zLockFile, 0777); - if( rc<0 ){ - /* failed to open/create the lock directory */ - int tErrno = errno; - if( EEXIST == tErrno ){ - rc = SQLITE_BUSY; - } else { - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); - } - } - return rc; - } - - /* got it, set the type and return ok */ - pFile->eFileLock = eFileLock; - return rc; -} - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -** -** When the locking level reaches NO_LOCK, delete the lock file. -*/ -static int dotlockUnlock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - char *zLockFile = (char *)pFile->lockingContext; - int rc; - - assert( pFile ); - OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); - assert( eFileLock<=SHARED_LOCK ); - - /* no-op if possible */ - if( pFile->eFileLock==eFileLock ){ - return SQLITE_OK; - } - - /* To downgrade to shared, simply update our internal notion of the - ** lock state. No need to mess with the file on disk. - */ - if( eFileLock==SHARED_LOCK ){ - pFile->eFileLock = SHARED_LOCK; - return SQLITE_OK; - } - - /* To fully unlock the database, delete the lock file */ - assert( eFileLock==NO_LOCK ); - rc = osRmdir(zLockFile); - if( rc<0 ){ - int tErrno = errno; - if( tErrno==ENOENT ){ - rc = SQLITE_OK; - }else{ - rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); - } - return rc; - } - pFile->eFileLock = NO_LOCK; - return SQLITE_OK; -} - -/* -** Close a file. Make sure the lock has been released before closing. -*/ -static int dotlockClose(sqlite3_file *id) { - unixFile *pFile = (unixFile*)id; - assert( id!=0 ); - dotlockUnlock(id, NO_LOCK); - sqlite3_free(pFile->lockingContext); - return closeUnixFile(id); -} -/****************** End of the dot-file lock implementation ******************* -******************************************************************************/ - -/****************************************************************************** -************************** Begin flock Locking ******************************** -** -** Use the flock() system call to do file locking. -** -** flock() locking is like dot-file locking in that the various -** fine-grain locking levels supported by SQLite are collapsed into -** a single exclusive lock. In other words, SHARED, RESERVED, and -** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite -** still works when you do this, but concurrency is reduced since -** only a single process can be reading the database at a time. -** -** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off -*/ -#if SQLITE_ENABLE_LOCKING_STYLE - -/* -** Retry flock() calls that fail with EINTR -*/ -#ifdef EINTR -static int robust_flock(int fd, int op){ - int rc; - do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR ); - return rc; -} -#else -# define robust_flock(a,b) flock(a,b) -#endif - - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, set *pResOut -** to a non-zero value otherwise *pResOut is set to zero. The return value -** is set to SQLITE_OK unless an I/O error occurs during lock checking. -*/ -static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ -#ifdef SQLITE_DEBUG - unixFile *pFile = (unixFile*)id; -#else - UNUSED_PARAMETER(id); -#endif - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - assert( pFile ); - assert( pFile->eFileLock<=SHARED_LOCK ); - - /* The flock VFS only ever takes exclusive locks (see function flockLock). - ** Therefore, if this connection is holding any lock at all, no other - ** connection may be holding a RESERVED lock. So set *pResOut to 0 - ** in this case. - ** - ** Or, this connection may be holding no lock. In that case, set *pResOut to - ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the - ** db in order to roll the hot journal back. If there is another connection - ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to - ** the user. With other VFS, we try to avoid this, in order to allow a reader - ** to proceed while a writer is preparing its transaction. But that won't - ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is - ** not a problem in this case. */ - *pResOut = 0; - - return SQLITE_OK; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** flock() only really support EXCLUSIVE locks. We track intermediate -** lock states in the sqlite3_file structure, but all locks SHARED or -** above are really EXCLUSIVE locks and exclude all other processes from -** access the file. -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -*/ -static int flockLock(sqlite3_file *id, int eFileLock) { - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - - assert( pFile ); - - /* if we already have a lock, it is exclusive. - ** Just adjust level and punt on outta here. */ - if (pFile->eFileLock > NO_LOCK) { - pFile->eFileLock = eFileLock; - return SQLITE_OK; - } - - /* grab an exclusive lock */ - - if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) { - int tErrno = errno; - /* didn't get, must be busy */ - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); - } - } else { - /* got it, set the type and return ok */ - pFile->eFileLock = eFileLock; - } - OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), - rc==SQLITE_OK ? "ok" : "failed")); -#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - if( (rc & 0xff) == SQLITE_IOERR ){ - rc = SQLITE_BUSY; - } -#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ - return rc; -} - - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -*/ -static int flockUnlock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - - assert( pFile ); - OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); - assert( eFileLock<=SHARED_LOCK ); - - /* no-op if possible */ - if( pFile->eFileLock==eFileLock ){ - return SQLITE_OK; - } - - /* shared can just be set because we always have an exclusive */ - if (eFileLock==SHARED_LOCK) { - pFile->eFileLock = eFileLock; - return SQLITE_OK; - } - - /* no, really, unlock. */ - if( robust_flock(pFile->h, LOCK_UN) ){ -#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - return SQLITE_OK; -#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ - return SQLITE_IOERR_UNLOCK; - }else{ - pFile->eFileLock = NO_LOCK; - return SQLITE_OK; - } -} - -/* -** Close a file. -*/ -static int flockClose(sqlite3_file *id) { - assert( id!=0 ); - flockUnlock(id, NO_LOCK); - return closeUnixFile(id); -} - -#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */ - -/******************* End of the flock lock implementation ********************* -******************************************************************************/ - -/****************************************************************************** -************************ Begin Named Semaphore Locking ************************ -** -** Named semaphore locking is only supported on VxWorks. -** -** Semaphore locking is like dot-lock and flock in that it really only -** supports EXCLUSIVE locking. Only a single process can read or write -** the database file at a time. This reduces potential concurrency, but -** makes the lock implementation much easier. -*/ -#if OS_VXWORKS - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, set *pResOut -** to a non-zero value otherwise *pResOut is set to zero. The return value -** is set to SQLITE_OK unless an I/O error occurs during lock checking. -*/ -static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { - int rc = SQLITE_OK; - int reserved = 0; - unixFile *pFile = (unixFile*)id; - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - assert( pFile ); - - /* Check if a thread in this process holds such a lock */ - if( pFile->eFileLock>SHARED_LOCK ){ - reserved = 1; - } - - /* Otherwise see if some other process holds it. */ - if( !reserved ){ - sem_t *pSem = pFile->pInode->pSem; - - if( sem_trywait(pSem)==-1 ){ - int tErrno = errno; - if( EAGAIN != tErrno ){ - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); - storeLastErrno(pFile, tErrno); - } else { - /* someone else has the lock when we are in NO_LOCK */ - reserved = (pFile->eFileLock < SHARED_LOCK); - } - }else{ - /* we could have it if we want it */ - sem_post(pSem); - } - } - OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved)); - - *pResOut = reserved; - return rc; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** Semaphore locks only really support EXCLUSIVE locks. We track intermediate -** lock states in the sqlite3_file structure, but all locks SHARED or -** above are really EXCLUSIVE locks and exclude all other processes from -** access the file. -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -*/ -static int semXLock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - sem_t *pSem = pFile->pInode->pSem; - int rc = SQLITE_OK; - - /* if we already have a lock, it is exclusive. - ** Just adjust level and punt on outta here. */ - if (pFile->eFileLock > NO_LOCK) { - pFile->eFileLock = eFileLock; - rc = SQLITE_OK; - goto sem_end_lock; - } - - /* lock semaphore now but bail out when already locked. */ - if( sem_trywait(pSem)==-1 ){ - rc = SQLITE_BUSY; - goto sem_end_lock; - } - - /* got it, set the type and return ok */ - pFile->eFileLock = eFileLock; - - sem_end_lock: - return rc; -} - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -*/ -static int semXUnlock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - sem_t *pSem = pFile->pInode->pSem; - - assert( pFile ); - assert( pSem ); - OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); - assert( eFileLock<=SHARED_LOCK ); - - /* no-op if possible */ - if( pFile->eFileLock==eFileLock ){ - return SQLITE_OK; - } - - /* shared can just be set because we always have an exclusive */ - if (eFileLock==SHARED_LOCK) { - pFile->eFileLock = eFileLock; - return SQLITE_OK; - } - - /* no, really unlock. */ - if ( sem_post(pSem)==-1 ) { - int rc, tErrno = errno; - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); - if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); - } - return rc; - } - pFile->eFileLock = NO_LOCK; - return SQLITE_OK; -} - -/* - ** Close a file. - */ -static int semXClose(sqlite3_file *id) { - if( id ){ - unixFile *pFile = (unixFile*)id; - semXUnlock(id, NO_LOCK); - assert( pFile ); - assert( unixFileMutexNotheld(pFile) ); - unixEnterMutex(); - releaseInodeInfo(pFile); - unixLeaveMutex(); - closeUnixFile(id); - } - return SQLITE_OK; -} - -#endif /* OS_VXWORKS */ -/* -** Named semaphore locking is only available on VxWorks. -** -*************** End of the named semaphore lock implementation **************** -******************************************************************************/ - - -/****************************************************************************** -*************************** Begin AFP Locking ********************************* -** -** AFP is the Apple Filing Protocol. AFP is a network filesystem found -** on Apple Macintosh computers - both OS9 and OSX. -** -** Third-party implementations of AFP are available. But this code here -** only works on OSX. -*/ - -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -/* -** The afpLockingContext structure contains all afp lock specific state -*/ -typedef struct afpLockingContext afpLockingContext; -struct afpLockingContext { - int reserved; - const char *dbPath; /* Name of the open file */ -}; - -struct ByteRangeLockPB2 -{ - unsigned long long offset; /* offset to first byte to lock */ - unsigned long long length; /* nbr of bytes to lock */ - unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ - unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ - unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ - int fd; /* file desc to assoc this lock with */ -}; - -#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) - -/* -** This is a utility for setting or clearing a bit-range lock on an -** AFP filesystem. -** -** Return SQLITE_OK on success, SQLITE_BUSY on failure. -*/ -static int afpSetLock( - const char *path, /* Name of the file to be locked or unlocked */ - unixFile *pFile, /* Open file descriptor on path */ - unsigned long long offset, /* First byte to be locked */ - unsigned long long length, /* Number of bytes to lock */ - int setLockFlag /* True to set lock. False to clear lock */ -){ - struct ByteRangeLockPB2 pb; - int err; - - pb.unLockFlag = setLockFlag ? 0 : 1; - pb.startEndFlag = 0; - pb.offset = offset; - pb.length = length; - pb.fd = pFile->h; - - OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", - (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""), - offset, length)); - err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); - if ( err==-1 ) { - int rc; - int tErrno = errno; - OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n", - path, tErrno, strerror(tErrno))); -#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS - rc = SQLITE_BUSY; -#else - rc = sqliteErrorFromPosixError(tErrno, - setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); -#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */ - if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); - } - return rc; - } else { - return SQLITE_OK; - } -} - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, set *pResOut -** to a non-zero value otherwise *pResOut is set to zero. The return value -** is set to SQLITE_OK unless an I/O error occurs during lock checking. -*/ -static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ - int rc = SQLITE_OK; - int reserved = 0; - unixFile *pFile = (unixFile*)id; - afpLockingContext *context; - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - assert( pFile ); - context = (afpLockingContext *) pFile->lockingContext; - if( context->reserved ){ - *pResOut = 1; - return SQLITE_OK; - } - sqlite3_mutex_enter(pFile->pInode->pLockMutex); - /* Check if a thread in this process holds such a lock */ - if( pFile->pInode->eFileLock>SHARED_LOCK ){ - reserved = 1; - } - - /* Otherwise see if some other process holds it. - */ - if( !reserved ){ - /* lock the RESERVED byte */ - int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); - if( SQLITE_OK==lrc ){ - /* if we succeeded in taking the reserved lock, unlock it to restore - ** the original state */ - lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); - } else { - /* if we failed to get the lock then someone else must have it */ - reserved = 1; - } - if( IS_LOCK_ERROR(lrc) ){ - rc=lrc; - } - } - - sqlite3_mutex_leave(pFile->pInode->pLockMutex); - OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); - - *pResOut = reserved; - return rc; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -*/ -static int afpLock(sqlite3_file *id, int eFileLock){ - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - unixInodeInfo *pInode = pFile->pInode; - afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; - - assert( pFile ); - OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, - azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); - - /* If there is already a lock of this type or more restrictive on the - ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as - ** unixEnterMutex() hasn't been called yet. - */ - if( pFile->eFileLock>=eFileLock ){ - OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h, - azFileLock(eFileLock))); - return SQLITE_OK; - } - - /* Make sure the locking sequence is correct - ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pending lock. - ** (3) A shared lock is always held when a reserve lock is requested. - */ - assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); - assert( eFileLock!=PENDING_LOCK ); - assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); - - /* This mutex is needed because pFile->pInode is shared across threads - */ - pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - - /* If some thread using this PID has a lock via a different unixFile* - ** handle that precludes the requested lock, return BUSY. - */ - if( (pFile->eFileLock!=pInode->eFileLock && - (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) - ){ - rc = SQLITE_BUSY; - goto afp_end_lock; - } - - /* If a SHARED lock is requested, and some thread using this PID already - ** has a SHARED or RESERVED lock, then increment reference counts and - ** return SQLITE_OK. - */ - if( eFileLock==SHARED_LOCK && - (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ - assert( eFileLock==SHARED_LOCK ); - assert( pFile->eFileLock==0 ); - assert( pInode->nShared>0 ); - pFile->eFileLock = SHARED_LOCK; - pInode->nShared++; - pInode->nLock++; - goto afp_end_lock; - } - - /* A PENDING lock is needed before acquiring a SHARED lock and before - ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will - ** be released. - */ - if( eFileLock==SHARED_LOCK - || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockdbPath, pFile, PENDING_BYTE, 1, 1); - if (failed) { - rc = failed; - goto afp_end_lock; - } - } - - /* If control gets to this point, then actually go ahead and make - ** operating system calls for the specified lock. - */ - if( eFileLock==SHARED_LOCK ){ - int lrc1, lrc2, lrc1Errno = 0; - long lk, mask; - - assert( pInode->nShared==0 ); - assert( pInode->eFileLock==0 ); - - mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; - /* Now get the read-lock SHARED_LOCK */ - /* note that the quality of the randomness doesn't matter that much */ - lk = random(); - pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1); - lrc1 = afpSetLock(context->dbPath, pFile, - SHARED_FIRST+pInode->sharedByte, 1, 1); - if( IS_LOCK_ERROR(lrc1) ){ - lrc1Errno = pFile->lastErrno; - } - /* Drop the temporary PENDING lock */ - lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); - - if( IS_LOCK_ERROR(lrc1) ) { - storeLastErrno(pFile, lrc1Errno); - rc = lrc1; - goto afp_end_lock; - } else if( IS_LOCK_ERROR(lrc2) ){ - rc = lrc2; - goto afp_end_lock; - } else if( lrc1 != SQLITE_OK ) { - rc = lrc1; - } else { - pFile->eFileLock = SHARED_LOCK; - pInode->nLock++; - pInode->nShared = 1; - } - }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ - /* We are trying for an exclusive lock but another thread in this - ** same process is still holding a shared lock. */ - rc = SQLITE_BUSY; - }else{ - /* The request was for a RESERVED or EXCLUSIVE lock. It is - ** assumed that there is a SHARED or greater lock on the file - ** already. - */ - int failed = 0; - assert( 0!=pFile->eFileLock ); - if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) { - /* Acquire a RESERVED lock */ - failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); - if( !failed ){ - context->reserved = 1; - } - } - if (!failed && eFileLock == EXCLUSIVE_LOCK) { - /* Acquire an EXCLUSIVE lock */ - - /* Remove the shared lock before trying the range. we'll need to - ** reestablish the shared lock if we can't get the afpUnlock - */ - if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + - pInode->sharedByte, 1, 0)) ){ - int failed2 = SQLITE_OK; - /* now attempt to get the exclusive lock range */ - failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, - SHARED_SIZE, 1); - if( failed && (failed2 = afpSetLock(context->dbPath, pFile, - SHARED_FIRST + pInode->sharedByte, 1, 1)) ){ - /* Can't reestablish the shared lock. Sqlite can't deal, this is - ** a critical I/O error - */ - rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 : - SQLITE_IOERR_LOCK; - goto afp_end_lock; - } - }else{ - rc = failed; - } - } - if( failed ){ - rc = failed; - } - } - - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - pInode->eFileLock = eFileLock; - }else if( eFileLock==EXCLUSIVE_LOCK ){ - pFile->eFileLock = PENDING_LOCK; - pInode->eFileLock = PENDING_LOCK; - } - -afp_end_lock: - sqlite3_mutex_leave(pInode->pLockMutex); - OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), - rc==SQLITE_OK ? "ok" : "failed")); - return rc; -} - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -*/ -static int afpUnlock(sqlite3_file *id, int eFileLock) { - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - unixInodeInfo *pInode; - afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; - int skipShared = 0; - - assert( pFile ); - OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, - pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - osGetpid(0))); - - assert( eFileLock<=SHARED_LOCK ); - if( pFile->eFileLock<=eFileLock ){ - return SQLITE_OK; - } - pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - assert( pInode->nShared!=0 ); - if( pFile->eFileLock>SHARED_LOCK ){ - assert( pInode->eFileLock==pFile->eFileLock ); - -#ifdef SQLITE_DEBUG - /* When reducing a lock such that other processes can start - ** reading the database file again, make sure that the - ** transaction counter was updated if any part of the database - ** file changed. If the transaction counter is not updated, - ** other connections to the same file might not realize that - ** the file has changed and hence might not know to flush their - ** cache. The use of a stale cache can lead to database corruption. - */ - assert( pFile->inNormalWrite==0 - || pFile->dbUpdate==0 - || pFile->transCntrChng==1 ); - pFile->inNormalWrite = 0; -#endif - - if( pFile->eFileLock==EXCLUSIVE_LOCK ){ - rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); - if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){ - /* only re-establish the shared lock if necessary */ - int sharedLockByte = SHARED_FIRST+pInode->sharedByte; - rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); - } else { - skipShared = 1; - } - } - if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){ - rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); - } - if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){ - rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); - if( !rc ){ - context->reserved = 0; - } - } - if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){ - pInode->eFileLock = SHARED_LOCK; - } - } - if( rc==SQLITE_OK && eFileLock==NO_LOCK ){ - - /* Decrement the shared lock counter. Release the lock using an - ** OS call only when all threads in this same process have released - ** the lock. - */ - unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; - pInode->nShared--; - if( pInode->nShared==0 ){ - if( !skipShared ){ - rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); - } - if( !rc ){ - pInode->eFileLock = NO_LOCK; - pFile->eFileLock = NO_LOCK; - } - } - if( rc==SQLITE_OK ){ - pInode->nLock--; - assert( pInode->nLock>=0 ); - if( pInode->nLock==0 ) closePendingFds(pFile); - } - } - - sqlite3_mutex_leave(pInode->pLockMutex); - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - } - return rc; -} - -/* -** Close a file & cleanup AFP specific locking context -*/ -static int afpClose(sqlite3_file *id) { - int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - assert( id!=0 ); - afpUnlock(id, NO_LOCK); - assert( unixFileMutexNotheld(pFile) ); - unixEnterMutex(); - if( pFile->pInode ){ - unixInodeInfo *pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - if( pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - setPendingFd(pFile); - } - sqlite3_mutex_leave(pInode->pLockMutex); - } - releaseInodeInfo(pFile); - sqlite3_free(pFile->lockingContext); - rc = closeUnixFile(id); - unixLeaveMutex(); - return rc; -} - -#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -/* -** The code above is the AFP lock implementation. The code is specific -** to MacOSX and does not work on other unix platforms. No alternative -** is available. If you don't compile for a mac, then the "unix-afp" -** VFS is not available. -** -********************* End of the AFP lock implementation ********************** -******************************************************************************/ - -/****************************************************************************** -*************************** Begin NFS Locking ********************************/ - -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -/* - ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock - ** must be either NO_LOCK or SHARED_LOCK. - ** - ** If the locking level of the file descriptor is already at or below - ** the requested locking level, this routine is a no-op. - */ -static int nfsUnlock(sqlite3_file *id, int eFileLock){ - return posixUnlock(id, eFileLock, 1); -} - -#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -/* -** The code above is the NFS lock implementation. The code is specific -** to MacOSX and does not work on other unix platforms. No alternative -** is available. -** -********************* End of the NFS lock implementation ********************** -******************************************************************************/ - -/****************************************************************************** -**************** Non-locking sqlite3_file methods ***************************** -** -** The next division contains implementations for all methods of the -** sqlite3_file object other than the locking methods. The locking -** methods were defined in divisions above (one locking method per -** division). Those methods that are common to all locking modes -** are gather together into this division. -*/ - -/* -** Seek to the offset passed as the second argument, then read cnt -** bytes into pBuf. Return the number of bytes actually read. -** -** To avoid stomping the errno value on a failed read the lastErrno value -** is set before returning. -*/ -static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ - int got; - int prior = 0; -#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) - i64 newOffset; -#endif - TIMER_START; - assert( cnt==(cnt&0x1ffff) ); - assert( id->h>2 ); - do{ -#if defined(USE_PREAD) - got = osPread(id->h, pBuf, cnt, offset); - SimulateIOError( got = -1 ); -#elif defined(USE_PREAD64) - got = osPread64(id->h, pBuf, cnt, offset); - SimulateIOError( got = -1 ); -#else - newOffset = lseek(id->h, offset, SEEK_SET); - SimulateIOError( newOffset = -1 ); - if( newOffset<0 ){ - storeLastErrno((unixFile*)id, errno); - return -1; - } - got = osRead(id->h, pBuf, cnt); -#endif - if( got==cnt ) break; - if( got<0 ){ - if( errno==EINTR ){ got = 1; continue; } - prior = 0; - storeLastErrno((unixFile*)id, errno); - break; - }else if( got>0 ){ - cnt -= got; - offset += got; - prior += got; - pBuf = (void*)(got + (char*)pBuf); - } - }while( got>0 ); - TIMER_END; - OSTRACE(("READ %-3d %5d %7lld %llu\n", - id->h, got+prior, offset-prior, TIMER_ELAPSED)); - return got+prior; -} - -/* -** Read data from a file into a buffer. Return SQLITE_OK if all -** bytes were read successfully and SQLITE_IOERR if anything goes -** wrong. -*/ -static int unixRead( - sqlite3_file *id, - void *pBuf, - int amt, - sqlite3_int64 offset -){ - unixFile *pFile = (unixFile *)id; - int got; - assert( id ); - assert( offset>=0 ); - assert( amt>0 ); - - /* If this is a database file (not a journal, super-journal or temp - ** file), the bytes in the locking range should never be read or written. */ -#if 0 - assert( pFile->pPreallocatedUnused==0 - || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE - ); -#endif - -#if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transferring - ** data from the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - return SQLITE_OK; - }else{ - int nCopy = pFile->mmapSize - offset; - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } - } -#endif - - got = seekAndRead(pFile, offset, pBuf, amt); - if( got==amt ){ - return SQLITE_OK; - }else if( got<0 ){ - /* pFile->lastErrno has been set by seekAndRead(). - ** Usually we return SQLITE_IOERR_READ here, though for some - ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The - ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT - ** prior to returning to the application by the sqlite3ApiExit() - ** routine. - */ - switch( pFile->lastErrno ){ - case ERANGE: - case EIO: -#ifdef ENXIO - case ENXIO: -#endif -#ifdef EDEVERR - case EDEVERR: -#endif - return SQLITE_IOERR_CORRUPTFS; - } - return SQLITE_IOERR_READ; - }else{ - storeLastErrno(pFile, 0); /* not a system error */ - /* Unread parts of the buffer must be zero-filled */ - memset(&((char*)pBuf)[got], 0, amt-got); - return SQLITE_IOERR_SHORT_READ; - } -} - -/* -** Attempt to seek the file-descriptor passed as the first argument to -** absolute offset iOff, then attempt to write nBuf bytes of data from -** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, -** return the actual number of bytes written (which may be less than -** nBuf). -*/ -static int seekAndWriteFd( - int fd, /* File descriptor to write to */ - i64 iOff, /* File offset to begin writing at */ - const void *pBuf, /* Copy data from this buffer to the file */ - int nBuf, /* Size of buffer pBuf in bytes */ - int *piErrno /* OUT: Error number if error occurs */ -){ - int rc = 0; /* Value returned by system call */ - - assert( nBuf==(nBuf&0x1ffff) ); - assert( fd>2 ); - assert( piErrno!=0 ); - nBuf &= 0x1ffff; - TIMER_START; - -#if defined(USE_PREAD) - do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); -#elif defined(USE_PREAD64) - do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); -#else - do{ - i64 iSeek = lseek(fd, iOff, SEEK_SET); - SimulateIOError( iSeek = -1 ); - if( iSeek<0 ){ - rc = -1; - break; - } - rc = osWrite(fd, pBuf, nBuf); - }while( rc<0 && errno==EINTR ); -#endif - - TIMER_END; - OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED)); - - if( rc<0 ) *piErrno = errno; - return rc; -} - - -/* -** Seek to the offset in id->offset then read cnt bytes into pBuf. -** Return the number of bytes actually read. Update the offset. -** -** To avoid stomping the errno value on a failed write the lastErrno value -** is set before returning. -*/ -static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ - return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno); -} - - -/* -** Write data from a buffer into a file. Return SQLITE_OK on success -** or some other error code on failure. -*/ -static int unixWrite( - sqlite3_file *id, - const void *pBuf, - int amt, - sqlite3_int64 offset -){ - unixFile *pFile = (unixFile*)id; - int wrote = 0; - assert( id ); - assert( amt>0 ); - - /* If this is a database file (not a journal, super-journal or temp - ** file), the bytes in the locking range should never be read or written. */ -#if 0 - assert( pFile->pPreallocatedUnused==0 - || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE - ); -#endif - -#ifdef SQLITE_DEBUG - /* If we are doing a normal write to a database file (as opposed to - ** doing a hot-journal rollback or a write to some file other than a - ** normal database file) then record the fact that the database - ** has changed. If the transaction counter is modified, record that - ** fact too. - */ - if( pFile->inNormalWrite ){ - pFile->dbUpdate = 1; /* The database has been modified */ - if( offset<=24 && offset+amt>=27 ){ - int rc; - char oldCntr[4]; - SimulateIOErrorBenign(1); - rc = seekAndRead(pFile, 24, oldCntr, 4); - SimulateIOErrorBenign(0); - if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){ - pFile->transCntrChng = 1; /* The transaction counter has changed */ - } - } - } -#endif - -#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transferring - ** data from the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - return SQLITE_OK; - }else{ - int nCopy = pFile->mmapSize - offset; - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } - } -#endif - - while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))0 ){ - amt -= wrote; - offset += wrote; - pBuf = &((char*)pBuf)[wrote]; - } - SimulateIOError(( wrote=(-1), amt=1 )); - SimulateDiskfullError(( wrote=0, amt=1 )); - - if( amt>wrote ){ - if( wrote<0 && pFile->lastErrno!=ENOSPC ){ - /* lastErrno set by seekAndWrite */ - return SQLITE_IOERR_WRITE; - }else{ - storeLastErrno(pFile, 0); /* not a system error */ - return SQLITE_FULL; - } - } - - return SQLITE_OK; -} - -#ifdef SQLITE_TEST -/* -** Count the number of fullsyncs and normal syncs. This is used to test -** that syncs and fullsyncs are occurring at the right times. -*/ -SQLITE_API int sqlite3_sync_count = 0; -SQLITE_API int sqlite3_fullsync_count = 0; -#endif - -/* -** We do not trust systems to provide a working fdatasync(). Some do. -** Others do no. To be safe, we will stick with the (slightly slower) -** fsync(). If you know that your system does support fdatasync() correctly, -** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC -*/ -#if !defined(fdatasync) && !HAVE_FDATASYNC -# define fdatasync fsync -#endif - -/* -** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not -** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently -** only available on Mac OS X. But that could change. -*/ -#ifdef F_FULLFSYNC -# define HAVE_FULLFSYNC 1 -#else -# define HAVE_FULLFSYNC 0 -#endif - - -/* -** The fsync() system call does not work as advertised on many -** unix systems. The following procedure is an attempt to make -** it work better. -** -** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful -** for testing when we want to run through the test suite quickly. -** You are strongly advised *not* to deploy with SQLITE_NO_SYNC -** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash -** or power failure will likely corrupt the database file. -** -** SQLite sets the dataOnly flag if the size of the file is unchanged. -** The idea behind dataOnly is that it should only write the file content -** to disk, not the inode. We only set dataOnly if the file size is -** unchanged since the file size is part of the inode. However, -** Ted Ts'o tells us that fdatasync() will also write the inode if the -** file size has changed. The only real difference between fdatasync() -** and fsync(), Ted tells us, is that fdatasync() will not flush the -** inode if the mtime or owner or other inode attributes have changed. -** We only care about the file size, not the other file attributes, so -** as far as SQLite is concerned, an fdatasync() is always adequate. -** So, we always use fdatasync() if it is available, regardless of -** the value of the dataOnly flag. -*/ -static int full_fsync(int fd, int fullSync, int dataOnly){ - int rc; - - /* The following "ifdef/elif/else/" block has the same structure as - ** the one below. It is replicated here solely to avoid cluttering - ** up the real code with the UNUSED_PARAMETER() macros. - */ -#ifdef SQLITE_NO_SYNC - UNUSED_PARAMETER(fd); - UNUSED_PARAMETER(fullSync); - UNUSED_PARAMETER(dataOnly); -#elif HAVE_FULLFSYNC - UNUSED_PARAMETER(dataOnly); -#else - UNUSED_PARAMETER(fullSync); - UNUSED_PARAMETER(dataOnly); -#endif - - /* Record the number of times that we do a normal fsync() and - ** FULLSYNC. This is used during testing to verify that this procedure - ** gets called with the correct arguments. - */ -#ifdef SQLITE_TEST - if( fullSync ) sqlite3_fullsync_count++; - sqlite3_sync_count++; -#endif - - /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a - ** no-op. But go ahead and call fstat() to validate the file - ** descriptor as we need a method to provoke a failure during - ** coverage testing. - */ -#ifdef SQLITE_NO_SYNC - { - struct stat buf; - rc = osFstat(fd, &buf); - } -#elif HAVE_FULLFSYNC - if( fullSync ){ - rc = osFcntl(fd, F_FULLFSYNC, 0); - }else{ - rc = 1; - } - /* If the FULLFSYNC failed, fall back to attempting an fsync(). - ** It shouldn't be possible for fullfsync to fail on the local - ** file system (on OSX), so failure indicates that FULLFSYNC - ** isn't supported for this file system. So, attempt an fsync - ** and (for now) ignore the overhead of a superfluous fcntl call. - ** It'd be better to detect fullfsync support once and avoid - ** the fcntl call every time sync is called. - */ - if( rc ) rc = fsync(fd); - -#elif defined(__APPLE__) - /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly - ** so currently we default to the macro that redefines fdatasync to fsync - */ - rc = fsync(fd); -#else - rc = fdatasync(fd); -#if OS_VXWORKS - if( rc==-1 && errno==ENOTSUP ){ - rc = fsync(fd); - } -#endif /* OS_VXWORKS */ -#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ - - if( OS_VXWORKS && rc!= -1 ){ - rc = 0; - } - return rc; -} - -/* -** Open a file descriptor to the directory containing file zFilename. -** If successful, *pFd is set to the opened file descriptor and -** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM -** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined -** value. -** -** The directory file descriptor is used for only one thing - to -** fsync() a directory to make sure file creation and deletion events -** are flushed to disk. Such fsyncs are not needed on newer -** journaling filesystems, but are required on older filesystems. -** -** This routine can be overridden using the xSetSysCall interface. -** The ability to override this routine was added in support of the -** chromium sandbox. Opening a directory is a security risk (we are -** told) so making it overrideable allows the chromium sandbox to -** replace this routine with a harmless no-op. To make this routine -** a no-op, replace it with a stub that returns SQLITE_OK but leaves -** *pFd set to a negative number. -** -** If SQLITE_OK is returned, the caller is responsible for closing -** the file descriptor *pFd using close(). -*/ -static int openDirectory(const char *zFilename, int *pFd){ - int ii; - int fd = -1; - char zDirname[MAX_PATHNAME+1]; - - sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); - for(ii=(int)strlen(zDirname); ii>0 && zDirname[ii]!='/'; ii--); - if( ii>0 ){ - zDirname[ii] = '\0'; - }else{ - if( zDirname[0]!='/' ) zDirname[0] = '.'; - zDirname[1] = 0; - } - fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); - if( fd>=0 ){ - OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); - } - *pFd = fd; - if( fd>=0 ) return SQLITE_OK; - return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname); -} - -/* -** Make sure all writes to a particular file are committed to disk. -** -** If dataOnly==0 then both the file itself and its metadata (file -** size, access time, etc) are synced. If dataOnly!=0 then only the -** file data is synced. -** -** Under Unix, also make sure that the directory entry for the file -** has been created by fsync-ing the directory that contains the file. -** If we do not do this and we encounter a power failure, the directory -** entry for the journal might not exist after we reboot. The next -** SQLite to access the file will not know that the journal exists (because -** the directory entry for the journal was never created) and the transaction -** will not roll back - possibly leading to database corruption. -*/ -static int unixSync(sqlite3_file *id, int flags){ - int rc; - unixFile *pFile = (unixFile*)id; - - int isDataOnly = (flags&SQLITE_SYNC_DATAONLY); - int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL; - - /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ - assert((flags&0x0F)==SQLITE_SYNC_NORMAL - || (flags&0x0F)==SQLITE_SYNC_FULL - ); - - /* Unix cannot, but some systems may return SQLITE_FULL from here. This - ** line is to test that doing so does not cause any problems. - */ - SimulateDiskfullError( return SQLITE_FULL ); - - assert( pFile ); - OSTRACE(("SYNC %-3d\n", pFile->h)); - rc = full_fsync(pFile->h, isFullsync, isDataOnly); - SimulateIOError( rc=1 ); - if( rc ){ - storeLastErrno(pFile, errno); - return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); - } - - /* Also fsync the directory containing the file if the DIRSYNC flag - ** is set. This is a one-time occurrence. Many systems (examples: AIX) - ** are unable to fsync a directory, so ignore errors on the fsync. - */ - if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){ - int dirfd; - OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, - HAVE_FULLFSYNC, isFullsync)); - rc = osOpenDirectory(pFile->zPath, &dirfd); - if( rc==SQLITE_OK ){ - full_fsync(dirfd, 0, 0); - robust_close(pFile, dirfd, __LINE__); - }else{ - assert( rc==SQLITE_CANTOPEN ); - rc = SQLITE_OK; - } - pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; - } - return rc; -} - -/* -** Truncate an open file to a specified size -*/ -static int unixTruncate(sqlite3_file *id, i64 nByte){ - unixFile *pFile = (unixFile *)id; - int rc; - assert( pFile ); - SimulateIOError( return SQLITE_IOERR_TRUNCATE ); - - /* If the user has configured a chunk-size for this file, truncate the - ** file so that it consists of an integer number of chunks (i.e. the - ** actual file size after the operation may be larger than the requested - ** size). - */ - if( pFile->szChunk>0 ){ - nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; - } - - rc = robust_ftruncate(pFile->h, nByte); - if( rc ){ - storeLastErrno(pFile, errno); - return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); - }else{ -#ifdef SQLITE_DEBUG - /* If we are doing a normal write to a database file (as opposed to - ** doing a hot-journal rollback or a write to some file other than a - ** normal database file) and we truncate the file to zero length, - ** that effectively updates the change counter. This might happen - ** when restoring a database using the backup API from a zero-length - ** source. - */ - if( pFile->inNormalWrite && nByte==0 ){ - pFile->transCntrChng = 1; - } -#endif - -#if SQLITE_MAX_MMAP_SIZE>0 - /* If the file was just truncated to a size smaller than the currently - ** mapped region, reduce the effective mapping size as well. SQLite will - ** use read() and write() to access data beyond this point from now on. - */ - if( nBytemmapSize ){ - pFile->mmapSize = nByte; - } -#endif - - return SQLITE_OK; - } -} - -/* -** Determine the current size of a file in bytes -*/ -static int unixFileSize(sqlite3_file *id, i64 *pSize){ - int rc; - struct stat buf; - assert( id ); - rc = osFstat(((unixFile*)id)->h, &buf); - SimulateIOError( rc=1 ); - if( rc!=0 ){ - storeLastErrno((unixFile*)id, errno); - return SQLITE_IOERR_FSTAT; - } - *pSize = buf.st_size; - - /* When opening a zero-size database, the findInodeInfo() procedure - ** writes a single byte into that file in order to work around a bug - ** in the OS-X msdos filesystem. In order to avoid problems with upper - ** layers, we need to report this file size as zero even though it is - ** really 1. Ticket #3260. - */ - if( *pSize==1 ) *pSize = 0; - - - return SQLITE_OK; -} - -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) -/* -** Handler for proxy-locking file-control verbs. Defined below in the -** proxying locking division. -*/ -static int proxyFileControl(sqlite3_file*,int,void*); -#endif - -/* -** This function is called to handle the SQLITE_FCNTL_SIZE_HINT -** file-control operation. Enlarge the database to nBytes in size -** (rounded up to the next chunk-size). If the database is already -** nBytes or larger, this routine is a no-op. -*/ -static int fcntlSizeHint(unixFile *pFile, i64 nByte){ - if( pFile->szChunk>0 ){ - i64 nSize; /* Required file size */ - struct stat buf; /* Used to hold return values of fstat() */ - - if( osFstat(pFile->h, &buf) ){ - return SQLITE_IOERR_FSTAT; - } - - nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; - if( nSize>(i64)buf.st_size ){ - -#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE - /* The code below is handling the return value of osFallocate() - ** correctly. posix_fallocate() is defined to "returns zero on success, - ** or an error number on failure". See the manpage for details. */ - int err; - do{ - err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); - }while( err==EINTR ); - if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; -#else - /* If the OS does not have posix_fallocate(), fake it. Write a - ** single byte to the last byte in each block that falls entirely - ** within the extended region. Then, if required, a single byte - ** at offset (nSize-1), to set the size of the file correctly. - ** This is a similar technique to that used by glibc on systems - ** that do not have a real fallocate() call. - */ - int nBlk = buf.st_blksize; /* File-system block size */ - int nWrite = 0; /* Number of bytes written by seekAndWrite */ - i64 iWrite; /* Next offset to write to */ - - iWrite = (buf.st_size/nBlk)*nBlk + nBlk - 1; - assert( iWrite>=buf.st_size ); - assert( ((iWrite+1)%nBlk)==0 ); - for(/*no-op*/; iWrite=nSize ) iWrite = nSize - 1; - nWrite = seekAndWrite(pFile, iWrite, "", 1); - if( nWrite!=1 ) return SQLITE_IOERR_WRITE; - } -#endif - } - } - -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){ - int rc; - if( pFile->szChunk<=0 ){ - if( robust_ftruncate(pFile->h, nByte) ){ - storeLastErrno(pFile, errno); - return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); - } - } - - rc = unixMapfile(pFile, nByte); - return rc; - } -#endif - - return SQLITE_OK; -} - -/* -** If *pArg is initially negative then this is a query. Set *pArg to -** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. -** -** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. -*/ -static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){ - if( *pArg<0 ){ - *pArg = (pFile->ctrlFlags & mask)!=0; - }else if( (*pArg)==0 ){ - pFile->ctrlFlags &= ~mask; - }else{ - pFile->ctrlFlags |= mask; - } -} - -/* Forward declaration */ -static int unixGetTempname(int nBuf, char *zBuf); -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) - static int unixFcntlExternalReader(unixFile*, int*); -#endif - -/* -** Information and control of an open file handle. -*/ -static int unixFileControl(sqlite3_file *id, int op, void *pArg){ - unixFile *pFile = (unixFile*)id; - switch( op ){ -#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) - case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: { - int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE); - return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK; - } - case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: { - int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE); - return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK; - } - case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { - int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE); - return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK; - } -#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ - - case SQLITE_FCNTL_NULL_IO: { - osClose(pFile->h); - pFile->h = -1; - return SQLITE_OK; - } - case SQLITE_FCNTL_LOCKSTATE: { - *(int*)pArg = pFile->eFileLock; - return SQLITE_OK; - } - case SQLITE_FCNTL_LAST_ERRNO: { - *(int*)pArg = pFile->lastErrno; - return SQLITE_OK; - } - case SQLITE_FCNTL_CHUNK_SIZE: { - pFile->szChunk = *(int *)pArg; - return SQLITE_OK; - } - case SQLITE_FCNTL_SIZE_HINT: { - int rc; - SimulateIOErrorBenign(1); - rc = fcntlSizeHint(pFile, *(i64 *)pArg); - SimulateIOErrorBenign(0); - return rc; - } - case SQLITE_FCNTL_PERSIST_WAL: { - unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg); - return SQLITE_OK; - } - case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { - unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); - return SQLITE_OK; - } - case SQLITE_FCNTL_VFSNAME: { - *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); - return SQLITE_OK; - } - case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname ); - if( zTFile ){ - unixGetTempname(pFile->pVfs->mxPathname, zTFile); - *(char**)pArg = zTFile; - } - return SQLITE_OK; - } - case SQLITE_FCNTL_HAS_MOVED: { - *(int*)pArg = fileHasMoved(pFile); - return SQLITE_OK; - } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - case SQLITE_FCNTL_LOCK_TIMEOUT: { - int iOld = pFile->iBusyTimeout; - int iNew = *(int*)pArg; -#if SQLITE_ENABLE_SETLK_TIMEOUT==1 - pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew; -#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 - pFile->iBusyTimeout = !!(*(int*)pArg); -#else -# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" -#endif - *(int*)pArg = iOld; - return SQLITE_OK; - } - case SQLITE_FCNTL_BLOCK_ON_CONNECT: { - int iNew = *(int*)pArg; - pFile->bBlockOnConnect = iNew; - return SQLITE_OK; - } -#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ -#if SQLITE_MAX_MMAP_SIZE>0 - case SQLITE_FCNTL_MMAP_SIZE: { - i64 newLimit = *(i64*)pArg; - int rc = SQLITE_OK; - if( newLimit>sqlite3GlobalConfig.mxMmap ){ - newLimit = sqlite3GlobalConfig.mxMmap; - } - - /* The value of newLimit may be eventually cast to (size_t) and passed - ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a - ** 64-bit type. */ - if( newLimit>0 && sizeof(size_t)<8 ){ - newLimit = (newLimit & 0x7FFFFFFF); - } - - *(i64*)pArg = pFile->mmapSizeMax; - if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ - pFile->mmapSizeMax = newLimit; - if( pFile->mmapSize>0 ){ - unixUnmapfile(pFile); - rc = unixMapfile(pFile, -1); - } - } - return rc; - } -#endif -#ifdef SQLITE_DEBUG - /* The pager calls this method to signal that it has done - ** a rollback and that the database is therefore unchanged and - ** it hence it is OK for the transaction change counter to be - ** unchanged. - */ - case SQLITE_FCNTL_DB_UNCHANGED: { - ((unixFile*)id)->dbUpdate = 0; - return SQLITE_OK; - } -#endif -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_FCNTL_SET_LOCKPROXYFILE: - case SQLITE_FCNTL_GET_LOCKPROXYFILE: { - return proxyFileControl(id,op,pArg); - } -#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ - - case SQLITE_FCNTL_EXTERNAL_READER: { -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) - return unixFcntlExternalReader((unixFile*)id, (int*)pArg); -#else - *(int*)pArg = 0; - return SQLITE_OK; -#endif - } - } - return SQLITE_NOTFOUND; -} - -/* -** If pFd->sectorSize is non-zero when this function is called, it is a -** no-op. Otherwise, the values of pFd->sectorSize and -** pFd->deviceCharacteristics are set according to the file-system -** characteristics. -** -** There are two versions of this function. One for QNX and one for all -** other systems. -*/ -#ifndef __QNXNTO__ -static void setDeviceCharacteristics(unixFile *pFd){ - assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 ); - if( pFd->sectorSize==0 ){ -#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) - int res; - u32 f = 0; - - /* Check for support for F2FS atomic batch writes. */ - res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f); - if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){ - pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC; - } -#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ - - /* Set the POWERSAFE_OVERWRITE flag if requested. */ - if( pFd->ctrlFlags & UNIXFILE_PSOW ){ - pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; - } - pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ; - - pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; - } -} -#else -#include -#include -static void setDeviceCharacteristics(unixFile *pFile){ - if( pFile->sectorSize == 0 ){ - struct statvfs fsInfo; - - /* Set defaults for non-supported filesystems */ - pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; - pFile->deviceCharacteristics = 0; - if( fstatvfs(pFile->h, &fsInfo) == -1 ) { - return; - } - - if( !strcmp(fsInfo.f_basetype, "tmp") ) { - pFile->sectorSize = fsInfo.f_bsize; - pFile->deviceCharacteristics = - SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */ - SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until - ** the write succeeds */ - SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind - ** so it is ordered */ - 0; - }else if( strstr(fsInfo.f_basetype, "etfs") ){ - pFile->sectorSize = fsInfo.f_bsize; - pFile->deviceCharacteristics = - /* etfs cluster size writes are atomic */ - (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) | - SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until - ** the write succeeds */ - SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind - ** so it is ordered */ - 0; - }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){ - pFile->sectorSize = fsInfo.f_bsize; - pFile->deviceCharacteristics = - SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */ - SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until - ** the write succeeds */ - SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind - ** so it is ordered */ - 0; - }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){ - pFile->sectorSize = fsInfo.f_bsize; - pFile->deviceCharacteristics = - /* full bitset of atomics from max sector size and smaller */ - (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) | - SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind - ** so it is ordered */ - 0; - }else if( strstr(fsInfo.f_basetype, "dos") ){ - pFile->sectorSize = fsInfo.f_bsize; - pFile->deviceCharacteristics = - /* full bitset of atomics from max sector size and smaller */ - (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) | - SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind - ** so it is ordered */ - 0; - }else{ - pFile->deviceCharacteristics = - SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */ - SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until - ** the write succeeds */ - 0; - } - } - /* Last chance verification. If the sector size isn't a multiple of 512 - ** then it isn't valid.*/ - if( pFile->sectorSize % 512 != 0 ){ - pFile->deviceCharacteristics = 0; - pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; - } -} -#endif - -/* -** Return the sector size in bytes of the underlying block device for -** the specified file. This is almost always 512 bytes, but may be -** larger for some devices. -** -** SQLite code assumes this function cannot fail. It also assumes that -** if two files are created in the same file-system directory (i.e. -** a database and its journal file) that the sector size will be the -** same for both. -*/ -static int unixSectorSize(sqlite3_file *id){ - unixFile *pFd = (unixFile*)id; - setDeviceCharacteristics(pFd); - return pFd->sectorSize; -} - -/* -** Return the device characteristics for the file. -** -** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. -** However, that choice is controversial since technically the underlying -** file system does not always provide powersafe overwrites. (In other -** words, after a power-loss event, parts of the file that were never -** written might end up being altered.) However, non-PSOW behavior is very, -** very rare. And asserting PSOW makes a large reduction in the amount -** of required I/O for journaling, since a lot of padding is eliminated. -** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control -** available to turn it off and URI query parameter available to turn it off. -*/ -static int unixDeviceCharacteristics(sqlite3_file *id){ - unixFile *pFd = (unixFile*)id; - setDeviceCharacteristics(pFd); - return pFd->deviceCharacteristics; -} - -#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 - -/* -** Return the system page size. -** -** This function should not be called directly by other code in this file. -** Instead, it should be called via macro osGetpagesize(). -*/ -static int unixGetpagesize(void){ -#if OS_VXWORKS - return 1024; -#elif defined(_BSD_SOURCE) - return getpagesize(); -#else - return (int)sysconf(_SC_PAGESIZE); -#endif -} - -#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */ - -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) - -/* -** Object used to represent an shared memory buffer. -** -** When multiple threads all reference the same wal-index, each thread -** has its own unixShm object, but they all point to a single instance -** of this unixShmNode object. In other words, each wal-index is opened -** only once per process. -** -** Each unixShmNode object is connected to a single unixInodeInfo object. -** We could coalesce this object into unixInodeInfo, but that would mean -** every open file that does not use shared memory (in other words, most -** open files) would have to carry around this extra information. So -** the unixInodeInfo object contains a pointer to this unixShmNode object -** and the unixShmNode object is created only when needed. -** -** unixMutexHeld() must be true when creating or destroying -** this object or while reading or writing the following fields: -** -** nRef -** -** The following fields are read-only after the object is created: -** -** hShm -** zFilename -** -** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and -** unixMutexHeld() is true when reading or writing any other field -** in this structure. -** -** aLock[SQLITE_SHM_NLOCK]: -** This array records the various locks held by clients on each of the -** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no -** locks are held by the process on this slot. If it is set to -1, then -** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[] -** value is set to a positive value, then it is the number of shared -** locks currently held on the slot. -** -** aMutex[SQLITE_SHM_NLOCK]: -** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex -** pShmMutex is used to protect the aLock[] array and the right to -** call fcntl() on unixShmNode.hShm to obtain or release locks. -** -** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array -** of mutexes - one for each locking slot. To read or write locking -** slot aLock[iSlot], the caller must hold the corresponding mutex -** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a -** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held. -*/ -struct unixShmNode { - unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ - sqlite3_mutex *pShmMutex; /* Mutex to access this object */ - char *zFilename; /* Name of the mmapped file */ - int hShm; /* Open file descriptor */ - int szRegion; /* Size of shared-memory regions */ - u16 nRegion; /* Size of array apRegion */ - u8 isReadonly; /* True if read-only */ - u8 isUnlocked; /* True if no DMS lock held */ - char **apRegion; /* Array of mapped shared-memory regions */ - int nRef; /* Number of unixShm objects pointing to this */ - unixShm *pFirst; /* All unixShm objects pointing to this */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK]; -#endif - int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */ -#ifdef SQLITE_DEBUG - u8 nextShmId; /* Next available unixShm.id value */ -#endif -}; - -/* -** Structure used internally by this VFS to record the state of an -** open shared memory connection. -** -** The following fields are initialized when this object is created and -** are read-only thereafter: -** -** unixShm.pShmNode -** unixShm.id -** -** All other fields are read/write. The unixShm.pShmNode->pShmMutex must -** be held while accessing any read/write fields. -*/ -struct unixShm { - unixShmNode *pShmNode; /* The underlying unixShmNode object */ - unixShm *pNext; /* Next unixShm with the same unixShmNode */ - u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ - u8 id; /* Id of this connection within its unixShmNode */ - u16 sharedMask; /* Mask of shared locks held */ - u16 exclMask; /* Mask of exclusive locks held */ -}; - -/* -** Constants used for locking -*/ -#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ -#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; - - sqlite3_mutex_enter(pShmNode->pShmMutex); - if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){ - rc = SQLITE_IOERR_LOCK; - }else{ - *piOut = (f.l_type!=F_UNLCK); - } - 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 -** otherwise. -*/ -static int unixShmSystemLock( - unixFile *pFile, /* Open connection to the WAL file */ - int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ - int ofst, /* First byte of the locking range */ - int n /* Number of bytes to lock */ -){ - unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ - struct flock f; /* The posix advisory locking structure */ - int rc = SQLITE_OK; /* Result code form fcntl() */ - - pShmNode = pFile->pInode->pShmNode; - - /* Assert that the parameters are within expected range and that the - ** correct mutex or mutexes are held. */ - assert( pShmNode->nRef>=0 ); - assert( (ofst==UNIX_SHM_DMS && n==1) - || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK)) - ); - if( ofst==UNIX_SHM_DMS ){ - assert( pShmNode->nRef>0 || unixMutexHeld() ); - assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); - }else{ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int ii; - for(ii=ofst-UNIX_SHM_BASE; iiaMutex[ii]) ); - } -#else - assert( sqlite3_mutex_held(pShmNode->pShmMutex) ); - assert( pShmNode->nRef>0 ); -#endif - } - - /* Shared locks never span more than one byte */ - assert( n==1 || lockType!=F_RDLCK ); - - /* Locks are within range */ - assert( n>=1 && n<=SQLITE_SHM_NLOCK ); - assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); - - if( pShmNode->hShm>=0 ){ - int res; - /* Initialize the locking parameters */ - f.l_type = lockType; - f.l_whence = SEEK_SET; - f.l_start = ofst; - f.l_len = n; - res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); - if( res==-1 ){ -#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1 - rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); -#else - rc = SQLITE_BUSY; -#endif - } - } - - /* Do debug tracing */ -#ifdef SQLITE_DEBUG - OSTRACE(("SHM-LOCK ")); - if( rc==SQLITE_OK ){ - if( lockType==F_UNLCK ){ - OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1)); - }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1)); - }else{ - assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1)); - } - }else{ - if( lockType==F_UNLCK ){ - OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1)); - }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1)); - }else{ - assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1)); - } - } -#endif - - return rc; -} - -/* -** Return the minimum number of 32KB shm regions that should be mapped at -** a time, assuming that each mapping must be an integer multiple of the -** current system page-size. -** -** Usually, this is 1. The exception seems to be systems that are configured -** to use 64KB pages - in this case each mapping must cover at least two -** shm regions. -*/ -static int unixShmRegionPerMap(void){ - int shmsz = 32*1024; /* SHM region size */ - int pgsz = osGetpagesize(); /* System page size */ - assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */ - if( pgszpInode->pShmNode; - assert( unixMutexHeld() ); - if( p && ALWAYS(p->nRef==0) ){ - int nShmPerMap = unixShmRegionPerMap(); - int i; - assert( p->pInode==pFd->pInode ); - sqlite3_mutex_free(p->pShmMutex); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - for(i=0; iaMutex[i]); - } -#endif - for(i=0; inRegion; i+=nShmPerMap){ - if( p->hShm>=0 ){ - osMunmap(p->apRegion[i], p->szRegion); - }else{ - sqlite3_free(p->apRegion[i]); - } - } - sqlite3_free(p->apRegion); - if( p->hShm>=0 ){ - robust_close(pFd, p->hShm, __LINE__); - p->hShm = -1; - } - p->pInode->pShmNode = 0; - sqlite3_free(p); - } -} - -/* -** The DMS lock has not yet been taken on shm file pShmNode. Attempt to -** take it now. Return SQLITE_OK if successful, or an SQLite error -** code otherwise. -** -** If the DMS cannot be locked because this is a readonly_shm=1 -** connection and no other process already holds a lock, return -** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. -*/ -static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ - struct flock lock; - int rc = SQLITE_OK; - - /* Use F_GETLK to determine the locks other processes are holding - ** on the DMS byte. If it indicates that another process is holding - ** a SHARED lock, then this process may also take a SHARED lock - ** and proceed with opening the *-shm file. - ** - ** Or, if no other process is holding any lock, then this process - ** is the first to open it. In this case take an EXCLUSIVE lock on the - ** DMS byte and truncate the *-shm file to zero bytes in size. Then - ** downgrade to a SHARED lock on the DMS byte. - ** - ** If another process is holding an EXCLUSIVE lock on the DMS byte, - ** return SQLITE_BUSY to the caller (it will try again). An earlier - ** version of this code attempted the SHARED lock at this point. But - ** this introduced a subtle race condition: if the process holding - ** EXCLUSIVE failed just before truncating the *-shm file, then this - ** process might open and use the *-shm file without truncating it. - ** And if the *-shm file has been corrupted by a power failure or - ** system crash, the database itself may also become corrupt. */ - lock.l_whence = SEEK_SET; - lock.l_start = UNIX_SHM_DMS; - lock.l_len = 1; - lock.l_type = F_WRLCK; - if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) { - rc = SQLITE_IOERR_LOCK; - }else if( lock.l_type==F_UNLCK ){ - if( pShmNode->isReadonly ){ - pShmNode->isUnlocked = 1; - rc = SQLITE_READONLY_CANTINIT; - }else{ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* Do not use a blocking lock here. If the lock cannot be obtained - ** immediately, it means some other connection is truncating the - ** *-shm file. And after it has done so, it will not release its - ** lock, but only downgrade it to a shared lock. So no point in - ** blocking here. The call below to obtain the shared DMS lock may - ** use a blocking lock. */ - int iSaveTimeout = pDbFd->iBusyTimeout; - pDbFd->iBusyTimeout = 0; -#endif - rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - pDbFd->iBusyTimeout = iSaveTimeout; -#endif - /* The first connection to attach must truncate the -shm file. We - ** truncate to 3 bytes (an arbitrary small number, less than the - ** -shm header size) rather than 0 as a system debugging aid, to - ** help detect if a -shm file truncation is legitimate or is the work - ** or a rogue process. */ - if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ - rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); - } - } - }else if( lock.l_type==F_WRLCK ){ - rc = SQLITE_BUSY; - } - - if( rc==SQLITE_OK ){ - assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); - rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); - } - return rc; -} - -/* -** Open a shared-memory area associated with open database file pDbFd. -** This particular implementation uses mmapped files. -** -** The file used to implement shared-memory is in the same directory -** as the open database file and has the same name as the open database -** file with the "-shm" suffix added. For example, if the database file -** is "/home/user1/config.db" then the file that is created and mmapped -** for shared memory will be called "/home/user1/config.db-shm". -** -** Another approach to is to use files in /dev/shm or /dev/tmp or an -** some other tmpfs mount. But if a file in a different directory -** from the database file is used, then differing access permissions -** or a chroot() might cause two different processes on the same -** database to end up using different files for shared memory - -** meaning that their memory would not really be shared - resulting -** in database corruption. Nevertheless, this tmpfs file usage -** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm" -** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time -** option results in an incompatible build of SQLite; builds of SQLite -** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the -** same database file at the same time, database corruption will likely -** result. The SQLITE_SHM_DIRECTORY compile-time option is considered -** "unsupported" and may go away in a future SQLite release. -** -** When opening a new shared-memory file, if no other instances of that -** file are currently open, in this process or in other processes, then -** the file must be truncated to zero length or have its header cleared. -** -** If the original database file (pDbFd) is using the "unix-excl" VFS -** that means that an exclusive lock is held on the database file and -** that no other processes are able to read or write the database. In -** that case, we do not really need shared memory. No shared memory -** file is created. The shared memory will be simulated with heap memory. -*/ -static int unixOpenSharedMemory(unixFile *pDbFd){ - struct unixShm *p = 0; /* The connection to be opened */ - struct unixShmNode *pShmNode; /* The underlying mmapped file */ - int rc = SQLITE_OK; /* Result code */ - unixInodeInfo *pInode; /* The inode of fd */ - char *zShm; /* Name of the file used for SHM */ - int nShmFilename; /* Size of the SHM filename in bytes */ - - /* Allocate space for the new unixShm object. */ - p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return SQLITE_NOMEM_BKPT; - memset(p, 0, sizeof(*p)); - assert( pDbFd->pShm==0 ); - - /* Check to see if a unixShmNode object already exists. Reuse an existing - ** one if present. Create a new one if necessary. - */ - assert( unixFileMutexNotheld(pDbFd) ); - unixEnterMutex(); - pInode = pDbFd->pInode; - pShmNode = pInode->pShmNode; - if( pShmNode==0 ){ - struct stat sStat; /* fstat() info for database file */ -#ifndef SQLITE_SHM_DIRECTORY - const char *zBasePath = pDbFd->zPath; -#endif - - /* Call fstat() to figure out the permissions on the database file. If - ** a new *-shm file is created, an attempt will be made to create it - ** with the same permissions. - */ - if( osFstat(pDbFd->h, &sStat) ){ - rc = SQLITE_IOERR_FSTAT; - goto shm_open_err; - } - -#ifdef SQLITE_SHM_DIRECTORY - nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; -#else - nShmFilename = 6 + (int)strlen(zBasePath); -#endif - pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); - if( pShmNode==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; - } - memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); - zShm = pShmNode->zFilename = (char*)&pShmNode[1]; -#ifdef SQLITE_SHM_DIRECTORY - sqlite3_snprintf(nShmFilename, zShm, - SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", - (u32)sStat.st_ino, (u32)sStat.st_dev); -#else - sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); - sqlite3FileSuffix3(pDbFd->zPath, zShm); -#endif - pShmNode->hShm = -1; - pDbFd->pInode->pShmNode = pShmNode; - pShmNode->pInode = pDbFd->pInode; - if( sqlite3GlobalConfig.bCoreMutex ){ - pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->pShmMutex==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; - } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - { - int ii; - for(ii=0; iiaMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->aMutex[ii]==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; - } - } - } -#endif - } - - if( pInode->bProcessLock==0 ){ - if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW, - (sStat.st_mode&0777)); - } - if( pShmNode->hShm<0 ){ - pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW, - (sStat.st_mode&0777)); - if( pShmNode->hShm<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); - goto shm_open_err; - } - pShmNode->isReadonly = 1; - } - - /* If this process is running as root, make sure that the SHM file - ** is owned by the same user that owns the original database. Otherwise, - ** the original owner will not be able to connect. - */ - robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); - - rc = unixLockSharedMemory(pDbFd, pShmNode); - if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; - } - } - - /* Make the new connection a child of the unixShmNode */ - p->pShmNode = pShmNode; -#ifdef SQLITE_DEBUG - p->id = pShmNode->nextShmId++; -#endif - pShmNode->nRef++; - pDbFd->pShm = p; - unixLeaveMutex(); - - /* The reference count on pShmNode has already been incremented under - ** the cover of the unixEnterMutex() mutex and the pointer from the - ** new (struct unixShm) object to the pShmNode has been set. All that is - ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the - ** pShmNode->pShmMutex. - */ - sqlite3_mutex_enter(pShmNode->pShmMutex); - p->pNext = pShmNode->pFirst; - pShmNode->pFirst = p; - sqlite3_mutex_leave(pShmNode->pShmMutex); - return rc; - - /* Jump here on any error */ -shm_open_err: - unixShmPurge(pDbFd); /* This call frees pShmNode if required */ - sqlite3_free(p); - unixLeaveMutex(); - return rc; -} - -/* -** This function is called to obtain a pointer to region iRegion of the -** shared-memory associated with the database file fd. Shared-memory regions -** are numbered starting from zero. Each shared-memory region is szRegion -** bytes in size. -** -** If an error occurs, an error code is returned and *pp is set to NULL. -** -** Otherwise, if the bExtend parameter is 0 and the requested shared-memory -** region has not been allocated (by any client, including one running in a -** separate process), then *pp is set to NULL and SQLITE_OK returned. If -** bExtend is non-zero and the requested shared-memory region has not yet -** been allocated, it is allocated by this function. -** -** If the shared-memory region has already been allocated or is allocated by -** this call as described above, then it is mapped into this processes -** address space (if it is not already), *pp is set to point to the mapped -** memory and SQLITE_OK returned. -*/ -static int unixShmMap( - sqlite3_file *fd, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int szRegion, /* Size of regions */ - int bExtend, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - unixFile *pDbFd = (unixFile*)fd; - unixShm *p; - unixShmNode *pShmNode; - int rc = SQLITE_OK; - int nShmPerMap = unixShmRegionPerMap(); - int nReqRegion; - - /* If the shared-memory file has not yet been opened, open it now. */ - if( pDbFd->pShm==0 ){ - rc = unixOpenSharedMemory(pDbFd); - if( rc!=SQLITE_OK ) return rc; - } - - p = pDbFd->pShm; - pShmNode = p->pShmNode; - sqlite3_mutex_enter(pShmNode->pShmMutex); - if( pShmNode->isUnlocked ){ - rc = unixLockSharedMemory(pDbFd, pShmNode); - if( rc!=SQLITE_OK ) goto shmpage_out; - pShmNode->isUnlocked = 0; - } - assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); - assert( pShmNode->pInode==pDbFd->pInode ); - assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); - - /* Minimum number of regions required to be mapped. */ - nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; - - if( pShmNode->nRegionszRegion = szRegion; - - if( pShmNode->hShm>=0 ){ - /* The requested region is not mapped into this processes address space. - ** Check to see if it has been allocated (i.e. if the wal-index file is - ** large enough to contain the requested region). - */ - if( osFstat(pShmNode->hShm, &sStat) ){ - rc = SQLITE_IOERR_SHMSIZE; - goto shmpage_out; - } - - if( sStat.st_sizehShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ - const char *zFile = pShmNode->zFilename; - rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); - goto shmpage_out; - } - } - } - } - } - - /* Map the requested memory region into this processes address space. */ - apNew = (char **)sqlite3_realloc( - pShmNode->apRegion, nReqRegion*sizeof(char *) - ); - if( !apNew ){ - rc = SQLITE_IOERR_NOMEM_BKPT; - goto shmpage_out; - } - pShmNode->apRegion = apNew; - while( pShmNode->nRegionhShm>=0 ){ - pMem = osMmap(0, nMap, - pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, - MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion - ); - if( pMem==MAP_FAILED ){ - rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); - goto shmpage_out; - } - }else{ - pMem = sqlite3_malloc64(nMap); - if( pMem==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shmpage_out; - } - memset(pMem, 0, nMap); - } - - for(i=0; iapRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i]; - } - pShmNode->nRegion += nShmPerMap; - } - } - -shmpage_out: - if( pShmNode->nRegion>iRegion ){ - *pp = pShmNode->apRegion[iRegion]; - }else{ - *pp = 0; - } - if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; - sqlite3_mutex_leave(pShmNode->pShmMutex); - return rc; -} - -/* -** Check that the pShmNode->aLock[] array comports with the locking bitmasks -** held by each client. Return true if it does, or false otherwise. This -** is to be used in an assert(). e.g. -** -** assert( assertLockingArrayOk(pShmNode) ); -*/ -#ifdef SQLITE_DEBUG -static int assertLockingArrayOk(unixShmNode *pShmNode){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - return 1; -#else - unixShm *pX; - int aLock[SQLITE_SHM_NLOCK]; - - memset(aLock, 0, sizeof(aLock)); - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ - int i; - for(i=0; iexclMask & (1<sharedMask & (1<=0 ); - aLock[i]++; - } - } - } - - assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) ); - return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0); -#endif -} -#endif - -/* -** Change the lock state for a shared-memory segment. -** -** Note that the relationship between SHARED and EXCLUSIVE locks is a little -** different here than in posix. In xShmLock(), one can go from unlocked -** to shared and back or from unlocked to exclusive and back. But one may -** not go from shared to exclusive or from exclusive to shared. -*/ -static int unixShmLock( - sqlite3_file *fd, /* Database file holding the shared memory */ - int ofst, /* First lock to acquire or release */ - int n, /* Number of locks to acquire or release */ - int flags /* What to do with the lock */ -){ - unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */ - unixShm *p; /* The shared memory being locked */ - unixShmNode *pShmNode; /* The underlying file iNode */ - int rc = SQLITE_OK; /* Result code */ - u16 mask = (1<<(ofst+n)) - (1<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 ); - assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); - assert( n>=1 ); - assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) - || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); - assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); - - /* Check that, if this to be a blocking lock, no locks that occur later - ** in the following list than the lock being obtained are already held: - ** - ** 1. Recovery lock (ofst==2). - ** 2. Checkpointer lock (ofst==1). - ** 3. Write lock (ofst==0). - ** 4. Read locks (ofst>=3 && ofstexclMask|p->sharedMask); - assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( - (ofst!=2 || lockMask==0) - && (ofst!=1 || lockMask==0 || lockMask==2) - && (ofst!=0 || lockMask<3) - && (ofst<3 || lockMask<(1<exclMask & mask) - ); - if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) - || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) - || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) - ){ - - /* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if - ** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any - ** other thread is holding this mutex, then it is either holding or about - ** to hold a lock exclusive to the one being requested, and we may - ** therefore return SQLITE_BUSY to the caller. - ** - ** Doing this prevents some deadlock scenarios. For example, thread 1 may - ** be a checkpointer blocked waiting on the WRITER lock. And thread 2 - ** may be a normal SQL client upgrading to a write transaction. In this - ** case thread 2 does a non-blocking request for the WRITER lock. But - - ** if it were to use sqlite3_mutex_enter() then it would effectively - ** become a (doomed) blocking request, as thread 2 would block until thread - ** 1 obtained WRITER and released the mutex. Since thread 2 already holds - ** a lock on a read-locking slot at this point, this breaks the - ** anti-deadlock rules (see above). */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int iMutex; - for(iMutex=ofst; iMutexaMutex[iMutex]); - if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes; - }else{ - sqlite3_mutex_enter(pShmNode->aMutex[iMutex]); - } - } -#else - sqlite3_mutex_enter(pShmNode->pShmMutex); -#endif - - if( ALWAYS(rc==SQLITE_OK) ){ - if( flags & SQLITE_SHM_UNLOCK ){ - /* Case (a) - unlock. */ - int bUnlock = 1; - assert( (p->exclMask & p->sharedMask)==0 ); - assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); - assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); - - /* If this is a SHARED lock being unlocked, it is possible that other - ** clients within this process are holding the same SHARED lock. In - ** this case, set bUnlock to 0 so that the posix lock is not removed - ** from the file-descriptor below. */ - if( flags & SQLITE_SHM_SHARED ){ - assert( n==1 ); - assert( aLock[ofst]>=1 ); - if( aLock[ofst]>1 ){ - bUnlock = 0; - aLock[ofst]--; - p->sharedMask &= ~mask; - } - } - - if( bUnlock ){ - rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); - if( rc==SQLITE_OK ){ - memset(&aLock[ofst], 0, sizeof(int)*n); - p->sharedMask &= ~mask; - p->exclMask &= ~mask; - } - } - }else if( flags & SQLITE_SHM_SHARED ){ - /* Case (b) - a shared lock. */ - - if( aLock[ofst]<0 ){ - /* An exclusive lock is held by some other connection. BUSY. */ - rc = SQLITE_BUSY; - }else if( aLock[ofst]==0 ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); - } - - /* Get the local shared locks */ - if( rc==SQLITE_OK ){ - p->sharedMask |= mask; - aLock[ofst]++; - } - }else{ - /* Case (c) - an exclusive lock. */ - int ii; - - assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ); - assert( (p->sharedMask & mask)==0 ); - assert( (p->exclMask & mask)==0 ); - - /* Make sure no sibling connections hold locks that will block this - ** lock. If any do, return SQLITE_BUSY right away. */ - for(ii=ofst; iiexclMask |= mask; - for(ii=ofst; ii=ofst; iMutex--){ - sqlite3_mutex_leave(pShmNode->aMutex[iMutex]); - } -#else - sqlite3_mutex_leave(pShmNode->pShmMutex); -#endif - } - - OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", - p->id, osGetpid(0), p->sharedMask, p->exclMask)); - return rc; -} - -/* -** Implement a memory barrier or memory fence on shared memory. -** -** All loads and stores begun before the barrier must complete before -** any load or store begun after the barrier. -*/ -static void unixShmBarrier( - sqlite3_file *fd /* Database file holding the shared memory */ -){ - UNUSED_PARAMETER(fd); - sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - assert( fd->pMethods->xLock==nolockLock - || unixFileMutexNotheld((unixFile*)fd) - ); - unixEnterMutex(); /* Also mutex, for redundancy */ - unixLeaveMutex(); -} - -/* -** Close a connection to shared-memory. Delete the underlying -** storage if deleteFlag is true. -** -** If there is no shared memory associated with the connection then this -** routine is a harmless no-op. -*/ -static int unixShmUnmap( - sqlite3_file *fd, /* The underlying database file */ - int deleteFlag /* Delete shared-memory if true */ -){ - unixShm *p; /* The connection to be closed */ - unixShmNode *pShmNode; /* The underlying shared-memory file */ - unixShm **pp; /* For looping over sibling connections */ - unixFile *pDbFd; /* The underlying database file */ - - pDbFd = (unixFile*)fd; - p = pDbFd->pShm; - if( p==0 ) return SQLITE_OK; - pShmNode = p->pShmNode; - - assert( pShmNode==pDbFd->pInode->pShmNode ); - assert( pShmNode->pInode==pDbFd->pInode ); - - /* Remove connection p from the set of connections associated - ** with pShmNode */ - sqlite3_mutex_enter(pShmNode->pShmMutex); - for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} - *pp = p->pNext; - - /* Free the connection p */ - sqlite3_free(p); - pDbFd->pShm = 0; - sqlite3_mutex_leave(pShmNode->pShmMutex); - - /* If pShmNode->nRef has reached 0, then close the underlying - ** shared-memory file, too */ - assert( unixFileMutexNotheld(pDbFd) ); - unixEnterMutex(); - assert( pShmNode->nRef>0 ); - pShmNode->nRef--; - if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->hShm>=0 ){ - osUnlink(pShmNode->zFilename); - } - unixShmPurge(pDbFd); - } - unixLeaveMutex(); - - return SQLITE_OK; -} - - -#else -# define unixShmMap 0 -# define unixShmLock 0 -# define unixShmBarrier 0 -# define unixShmUnmap 0 -#endif /* #ifndef SQLITE_OMIT_WAL */ - -#if SQLITE_MAX_MMAP_SIZE>0 -/* -** If it is currently memory mapped, unmap file pFd. -*/ -static void unixUnmapfile(unixFile *pFd){ - assert( pFd->nFetchOut==0 ); - if( pFd->pMapRegion ){ - osMunmap(pFd->pMapRegion, pFd->mmapSizeActual); - pFd->pMapRegion = 0; - pFd->mmapSize = 0; - pFd->mmapSizeActual = 0; - } -} - -/* -** Attempt to set the size of the memory mapping maintained by file -** descriptor pFd to nNew bytes. Any existing mapping is discarded. -** -** If successful, this function sets the following variables: -** -** unixFile.pMapRegion -** unixFile.mmapSize -** unixFile.mmapSizeActual -** -** If unsuccessful, an error message is logged via sqlite3_log() and -** the three variables above are zeroed. In this case SQLite should -** continue accessing the database using the xRead() and xWrite() -** methods. -*/ -static void unixRemapfile( - unixFile *pFd, /* File descriptor object */ - i64 nNew /* Required mapping size */ -){ - const char *zErr = "mmap"; - int h = pFd->h; /* File descriptor open on db file */ - u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */ - i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */ - u8 *pNew = 0; /* Location of new mapping */ - int flags = PROT_READ; /* Flags to pass to mmap() */ - - assert( pFd->nFetchOut==0 ); - assert( nNew>pFd->mmapSize ); - assert( nNew<=pFd->mmapSizeMax ); - assert( nNew>0 ); - assert( pFd->mmapSizeActual>=pFd->mmapSize ); - assert( MAP_FAILED!=0 ); - -#ifdef SQLITE_MMAP_READWRITE - if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; -#endif - - if( pOrig ){ -#if HAVE_MREMAP - i64 nReuse = pFd->mmapSize; -#else - const int szSyspage = osGetpagesize(); - i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); -#endif - u8 *pReq = &pOrig[nReuse]; - - /* Unmap any pages of the existing mapping that cannot be reused. */ - if( nReuse!=nOrig ){ - osMunmap(pReq, nOrig-nReuse); - } - -#if HAVE_MREMAP - pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); - zErr = "mremap"; -#else - pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); - if( pNew!=MAP_FAILED ){ - if( pNew!=pReq ){ - osMunmap(pNew, nNew - nReuse); - pNew = 0; - }else{ - pNew = pOrig; - } - } -#endif - - /* The attempt to extend the existing mapping failed. Free it. */ - if( pNew==MAP_FAILED || pNew==0 ){ - osMunmap(pOrig, nReuse); - } - } - - /* If pNew is still NULL, try to create an entirely new mapping. */ - if( pNew==0 ){ - pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0); - } - - if( pNew==MAP_FAILED ){ - pNew = 0; - nNew = 0; - unixLogError(SQLITE_OK, zErr, pFd->zPath); - - /* If the mmap() above failed, assume that all subsequent mmap() calls - ** will probably fail too. Fall back to using xRead/xWrite exclusively - ** in this case. */ - pFd->mmapSizeMax = 0; - } - pFd->pMapRegion = (void *)pNew; - pFd->mmapSize = pFd->mmapSizeActual = nNew; -} - -/* -** Memory map or remap the file opened by file-descriptor pFd (if the file -** is already mapped, the existing mapping is replaced by the new). Or, if -** there already exists a mapping for this file, and there are still -** outstanding xFetch() references to it, this function is a no-op. -** -** If parameter nByte is non-negative, then it is the requested size of -** the mapping to create. Otherwise, if nByte is less than zero, then the -** requested size is the size of the file on disk. The actual size of the -** created mapping is either the requested size or the value configured -** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller. -** -** SQLITE_OK is returned if no error occurs (even if the mapping is not -** recreated as a result of outstanding references) or an SQLite error -** code otherwise. -*/ -static int unixMapfile(unixFile *pFd, i64 nMap){ - assert( nMap>=0 || pFd->nFetchOut==0 ); - assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) ); - if( pFd->nFetchOut>0 ) return SQLITE_OK; - - if( nMap<0 ){ - struct stat statbuf; /* Low-level file information */ - if( osFstat(pFd->h, &statbuf) ){ - return SQLITE_IOERR_FSTAT; - } - nMap = statbuf.st_size; - } - if( nMap>pFd->mmapSizeMax ){ - nMap = pFd->mmapSizeMax; - } - - assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) ); - if( nMap!=pFd->mmapSize ){ - unixRemapfile(pFd, nMap); - } - - return SQLITE_OK; -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* -** If possible, return a pointer to a mapping of file fd starting at offset -** iOff. The mapping must be valid for at least nAmt bytes. -** -** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. -** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. -** Finally, if an error does occur, return an SQLite error code. The final -** value of *pp is undefined in this case. -** -** If this function does return a pointer, the caller must eventually -** release the reference by calling unixUnfetch(). -*/ -static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ -#if SQLITE_MAX_MMAP_SIZE>0 - unixFile *pFd = (unixFile *)fd; /* The underlying database file */ -#endif - *pp = 0; - -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; - if( pFd->pMapRegion==0 ){ - int rc = unixMapfile(pFd, -1); - if( rc!=SQLITE_OK ) return rc; - } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ - *pp = &((u8 *)pFd->pMapRegion)[iOff]; - pFd->nFetchOut++; - } - } -#endif - return SQLITE_OK; -} - -/* -** If the third argument is non-NULL, then this function releases a -** reference obtained by an earlier call to unixFetch(). The second -** argument passed to this function must be the same as the corresponding -** argument that was passed to the unixFetch() invocation. -** -** Or, if the third argument is NULL, then this function is being called -** to inform the VFS layer that, according to POSIX, any existing mapping -** may now be invalid and should be unmapped. -*/ -static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ -#if SQLITE_MAX_MMAP_SIZE>0 - unixFile *pFd = (unixFile *)fd; /* The underlying database file */ - UNUSED_PARAMETER(iOff); - - /* If p==0 (unmap the entire file) then there must be no outstanding - ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), - ** then there must be at least one outstanding. */ - assert( (p==0)==(pFd->nFetchOut==0) ); - - /* If p!=0, it must match the iOff value. */ - assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); - - if( p ){ - pFd->nFetchOut--; - }else{ - unixUnmapfile(pFd); - } - - assert( pFd->nFetchOut>=0 ); -#else - UNUSED_PARAMETER(fd); - UNUSED_PARAMETER(p); - UNUSED_PARAMETER(iOff); -#endif - return SQLITE_OK; -} - -/* -** Here ends the implementation of all sqlite3_file methods. -** -********************** End sqlite3_file Methods ******************************* -******************************************************************************/ - -/* -** This division contains definitions of sqlite3_io_methods objects that -** implement various file locking strategies. It also contains definitions -** of "finder" functions. A finder-function is used to locate the appropriate -** sqlite3_io_methods object for a particular database file. The pAppData -** field of the sqlite3_vfs VFS objects are initialized to be pointers to -** the correct finder-function for that VFS. -** -** Most finder functions return a pointer to a fixed sqlite3_io_methods -** object. The only interesting finder-function is autolockIoFinder, which -** looks at the filesystem type and tries to guess the best locking -** strategy from that. -** -** For finder-function F, two objects are created: -** -** (1) The real finder-function named "FImpt()". -** -** (2) A constant pointer to this function named just "F". -** -** -** A pointer to the F pointer is used as the pAppData value for VFS -** objects. We have to do this instead of letting pAppData point -** directly at the finder-function since C90 rules prevent a void* -** from be cast into a function pointer. -** -** -** Each instance of this macro generates two objects: -** -** * A constant sqlite3_io_methods object call METHOD that has locking -** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. -** -** * An I/O method finder function called FINDER that returns a pointer -** to the METHOD object in the previous bullet. -*/ -#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \ -static const sqlite3_io_methods METHOD = { \ - VERSION, /* iVersion */ \ - CLOSE, /* xClose */ \ - unixRead, /* xRead */ \ - unixWrite, /* xWrite */ \ - unixTruncate, /* xTruncate */ \ - unixSync, /* xSync */ \ - unixFileSize, /* xFileSize */ \ - LOCK, /* xLock */ \ - UNLOCK, /* xUnlock */ \ - CKLOCK, /* xCheckReservedLock */ \ - unixFileControl, /* xFileControl */ \ - unixSectorSize, /* xSectorSize */ \ - unixDeviceCharacteristics, /* xDeviceCapabilities */ \ - SHMMAP, /* xShmMap */ \ - unixShmLock, /* xShmLock */ \ - unixShmBarrier, /* xShmBarrier */ \ - unixShmUnmap, /* xShmUnmap */ \ - unixFetch, /* xFetch */ \ - unixUnfetch, /* xUnfetch */ \ -}; \ -static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ - UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ - return &METHOD; \ -} \ -static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \ - = FINDER##Impl; - -/* -** Here are all of the sqlite3_io_methods objects for each of the -** locking strategies. Functions that return pointers to these methods -** are also created. -*/ -IOMETHODS( - posixIoFinder, /* Finder function name */ - posixIoMethods, /* sqlite3_io_methods object name */ - 3, /* shared memory and mmap are enabled */ - unixClose, /* xClose method */ - unixLock, /* xLock method */ - unixUnlock, /* xUnlock method */ - unixCheckReservedLock, /* xCheckReservedLock method */ - unixShmMap /* xShmMap method */ -) -IOMETHODS( - nolockIoFinder, /* Finder function name */ - nolockIoMethods, /* sqlite3_io_methods object name */ - 3, /* shared memory and mmap are enabled */ - nolockClose, /* xClose method */ - nolockLock, /* xLock method */ - nolockUnlock, /* xUnlock method */ - nolockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -IOMETHODS( - dotlockIoFinder, /* Finder function name */ - dotlockIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - dotlockClose, /* xClose method */ - dotlockLock, /* xLock method */ - dotlockUnlock, /* xUnlock method */ - dotlockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) - -#if SQLITE_ENABLE_LOCKING_STYLE -IOMETHODS( - flockIoFinder, /* Finder function name */ - flockIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - flockClose, /* xClose method */ - flockLock, /* xLock method */ - flockUnlock, /* xUnlock method */ - flockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -#endif - -#if OS_VXWORKS -IOMETHODS( - semIoFinder, /* Finder function name */ - semIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - semXClose, /* xClose method */ - semXLock, /* xLock method */ - semXUnlock, /* xUnlock method */ - semXCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -#endif - -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -IOMETHODS( - afpIoFinder, /* Finder function name */ - afpIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - afpClose, /* xClose method */ - afpLock, /* xLock method */ - afpUnlock, /* xUnlock method */ - afpCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -#endif - -/* -** The proxy locking method is a "super-method" in the sense that it -** opens secondary file descriptors for the conch and lock files and -** it uses proxy, dot-file, AFP, and flock() locking methods on those -** secondary files. For this reason, the division that implements -** proxy locking is located much further down in the file. But we need -** to go ahead and define the sqlite3_io_methods and finder function -** for proxy locking here. So we forward declare the I/O methods. -*/ -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -static int proxyClose(sqlite3_file*); -static int proxyLock(sqlite3_file*, int); -static int proxyUnlock(sqlite3_file*, int); -static int proxyCheckReservedLock(sqlite3_file*, int*); -IOMETHODS( - proxyIoFinder, /* Finder function name */ - proxyIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - proxyClose, /* xClose method */ - proxyLock, /* xLock method */ - proxyUnlock, /* xUnlock method */ - proxyCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -#endif - -/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -IOMETHODS( - nfsIoFinder, /* Finder function name */ - nfsIoMethods, /* sqlite3_io_methods object name */ - 1, /* shared memory is disabled */ - unixClose, /* xClose method */ - unixLock, /* xLock method */ - nfsUnlock, /* xUnlock method */ - unixCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ -) -#endif - -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -/* -** This "finder" function attempts to determine the best locking strategy -** for the database file "filePath". It then returns the sqlite3_io_methods -** object that implements that strategy. -** -** This is for MacOSX only. -*/ -static const sqlite3_io_methods *autolockIoFinderImpl( - const char *filePath, /* name of the database file */ - unixFile *pNew /* open file object for the database file */ -){ - static const struct Mapping { - const char *zFilesystem; /* Filesystem type name */ - const sqlite3_io_methods *pMethods; /* Appropriate locking method */ - } aMap[] = { - { "hfs", &posixIoMethods }, - { "ufs", &posixIoMethods }, - { "afpfs", &afpIoMethods }, - { "smbfs", &afpIoMethods }, - { "webdav", &nolockIoMethods }, - { 0, 0 } - }; - int i; - struct statfs fsInfo; - struct flock lockInfo; - - if( !filePath ){ - /* If filePath==NULL that means we are dealing with a transient file - ** that does not need to be locked. */ - return &nolockIoMethods; - } - if( statfs(filePath, &fsInfo) != -1 ){ - if( fsInfo.f_flags & MNT_RDONLY ){ - return &nolockIoMethods; - } - for(i=0; aMap[i].zFilesystem; i++){ - if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){ - return aMap[i].pMethods; - } - } - } - - /* Default case. Handles, amongst others, "nfs". - ** Test byte-range lock using fcntl(). If the call succeeds, - ** assume that the file-system supports POSIX style locks. - */ - lockInfo.l_len = 1; - lockInfo.l_start = 0; - lockInfo.l_whence = SEEK_SET; - lockInfo.l_type = F_RDLCK; - if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { - if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ - return &nfsIoMethods; - } else { - return &posixIoMethods; - } - }else{ - return &dotlockIoMethods; - } -} -static const sqlite3_io_methods - *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; - -#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ - -#if OS_VXWORKS -/* -** This "finder" function for VxWorks checks to see if posix advisory -** locking works. If it does, then that is what is used. If it does not -** work, then fallback to named semaphore locking. -*/ -static const sqlite3_io_methods *vxworksIoFinderImpl( - const char *filePath, /* name of the database file */ - unixFile *pNew /* the open file object */ -){ - struct flock lockInfo; - - if( !filePath ){ - /* If filePath==NULL that means we are dealing with a transient file - ** that does not need to be locked. */ - return &nolockIoMethods; - } - - /* Test if fcntl() is supported and use POSIX style locks. - ** Otherwise fall back to the named semaphore method. - */ - lockInfo.l_len = 1; - lockInfo.l_start = 0; - lockInfo.l_whence = SEEK_SET; - lockInfo.l_type = F_RDLCK; - if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { - return &posixIoMethods; - }else{ - return &semIoMethods; - } -} -static const sqlite3_io_methods - *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; - -#endif /* OS_VXWORKS */ - -/* -** An abstract type for a pointer to an IO method finder function: -*/ -typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*); - - -/**************************************************************************** -**************************** sqlite3_vfs methods **************************** -** -** This division contains the implementation of methods on the -** sqlite3_vfs object. -*/ - -/* -** Initialize the contents of the unixFile structure pointed to by pId. -*/ -static int fillInUnixFile( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - int h, /* Open file descriptor of file being opened */ - sqlite3_file *pId, /* Write to the unixFile structure here */ - const char *zFilename, /* Name of the file being opened */ - int ctrlFlags /* Zero or more UNIXFILE_* values */ -){ - const sqlite3_io_methods *pLockingStyle; - unixFile *pNew = (unixFile *)pId; - int rc = SQLITE_OK; - - assert( pNew->pInode==NULL ); - - /* No locking occurs in temporary files */ - assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); - - OSTRACE(("OPEN %-3d %s\n", h, zFilename)); - pNew->h = h; - pNew->pVfs = pVfs; - pNew->zPath = zFilename; - pNew->ctrlFlags = (u8)ctrlFlags; -#if SQLITE_MAX_MMAP_SIZE>0 - pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap; -#endif - if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0), - "psow", SQLITE_POWERSAFE_OVERWRITE) ){ - pNew->ctrlFlags |= UNIXFILE_PSOW; - } - if( strcmp(pVfs->zName,"unix-excl")==0 ){ - pNew->ctrlFlags |= UNIXFILE_EXCL; - } - -#if OS_VXWORKS - pNew->pId = vxworksFindFileId(zFilename); - if( pNew->pId==0 ){ - ctrlFlags |= UNIXFILE_NOLOCK; - rc = SQLITE_NOMEM_BKPT; - } -#endif - - if( ctrlFlags & UNIXFILE_NOLOCK ){ - pLockingStyle = &nolockIoMethods; - }else{ - pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew); -#if SQLITE_ENABLE_LOCKING_STYLE - /* Cache zFilename in the locking context (AFP and dotlock override) for - ** proxyLock activation is possible (remote proxy is based on db name) - ** zFilename remains valid until file is closed, to support */ - pNew->lockingContext = (void*)zFilename; -#endif - } - - if( pLockingStyle == &posixIoMethods -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - || pLockingStyle == &nfsIoMethods -#endif - ){ - unixEnterMutex(); - rc = findInodeInfo(pNew, &pNew->pInode); - if( rc!=SQLITE_OK ){ - /* If an error occurred in findInodeInfo(), close the file descriptor - ** immediately, before releasing the mutex. findInodeInfo() may fail - ** in two scenarios: - ** - ** (a) A call to fstat() failed. - ** (b) A malloc failed. - ** - ** Scenario (b) may only occur if the process is holding no other - ** file descriptors open on the same file. If there were other file - ** descriptors on this file, then no malloc would be required by - ** findInodeInfo(). If this is the case, it is quite safe to close - ** handle h - as it is guaranteed that no posix locks will be released - ** by doing so. - ** - ** If scenario (a) caused the error then things are not so safe. The - ** implicit assumption here is that if fstat() fails, things are in - ** such bad shape that dropping a lock or two doesn't matter much. - */ - robust_close(pNew, h, __LINE__); - h = -1; - } - unixLeaveMutex(); - } - -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - else if( pLockingStyle == &afpIoMethods ){ - /* AFP locking uses the file path so it needs to be included in - ** the afpLockingContext. - */ - afpLockingContext *pCtx; - pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); - if( pCtx==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - /* NB: zFilename exists and remains valid until the file is closed - ** according to requirement F11141. So we do not need to make a - ** copy of the filename. */ - pCtx->dbPath = zFilename; - pCtx->reserved = 0; - srandomdev(); - unixEnterMutex(); - rc = findInodeInfo(pNew, &pNew->pInode); - if( rc!=SQLITE_OK ){ - sqlite3_free(pNew->lockingContext); - robust_close(pNew, h, __LINE__); - h = -1; - } - unixLeaveMutex(); - } - } -#endif - - else if( pLockingStyle == &dotlockIoMethods ){ - /* Dotfile locking uses the file path so it needs to be included in - ** the dotlockLockingContext - */ - char *zLockFile; - int nFilename; - assert( zFilename!=0 ); - nFilename = (int)strlen(zFilename) + 6; - zLockFile = (char *)sqlite3_malloc64(nFilename); - if( zLockFile==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename); - } - pNew->lockingContext = zLockFile; - } - -#if OS_VXWORKS - else if( pLockingStyle == &semIoMethods ){ - /* Named semaphore locking uses the file path so it needs to be - ** included in the semLockingContext - */ - unixEnterMutex(); - rc = findInodeInfo(pNew, &pNew->pInode); - if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){ - char *zSemName = pNew->pInode->aSemName; - int n; - sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem", - pNew->pId->zCanonicalName); - for( n=1; zSemName[n]; n++ ) - if( zSemName[n]=='/' ) zSemName[n] = '_'; - pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1); - if( pNew->pInode->pSem == SEM_FAILED ){ - rc = SQLITE_NOMEM_BKPT; - pNew->pInode->aSemName[0] = '\0'; - } - } - unixLeaveMutex(); - } -#endif - - storeLastErrno(pNew, 0); -#if OS_VXWORKS - if( rc!=SQLITE_OK ){ - if( h>=0 ) robust_close(pNew, h, __LINE__); - h = -1; - osUnlink(zFilename); - pNew->ctrlFlags |= UNIXFILE_DELETE; - } -#endif - if( rc!=SQLITE_OK ){ - if( h>=0 ) robust_close(pNew, h, __LINE__); - }else{ - pId->pMethods = pLockingStyle; - OpenCounter(+1); - verifyDbFile(pNew); - } - return rc; -} - -/* -** 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){ - unsigned int i = 0; - struct stat buf; - const char *zDir = sqlite3_temp_directory; - - while(1){ - if( zDir!=0 - && osStat(zDir, &buf)==0 - && S_ISDIR(buf.st_mode) - && osAccess(zDir, 03)==0 - ){ - return zDir; - } - if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break; - zDir = azTempDirs[i++]; - } - return 0; -} - -/* -** Create a temporary file name in zBuf. zBuf must be allocated -** by the calling process and must be big enough to hold at least -** pVfs->mxPathname bytes. -*/ -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 - ** function failing. - */ - zBuf[0] = 0; - SimulateIOError( return SQLITE_IOERR ); - - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - zDir = unixTempFileDir(); - if( zDir==0 ){ - rc = SQLITE_IOERR_GETTEMPPATH; - }else{ - do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - 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 ); - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - return rc; -} - -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) -/* -** Routine to transform a unixFile into a proxy-locking unixFile. -** Implementation in the proxy-lock division, but used by unixOpen() -** if SQLITE_PREFER_PROXY_LOCKING is defined. -*/ -static int proxyTransformUnixFile(unixFile*, const char*); -#endif - -/* -** Search for an unused file descriptor that was opened on the database -** file (not a journal or super-journal file) identified by pathname -** zPath with SQLITE_OPEN_XXX flags matching those passed as the second -** argument to this function. -** -** Such a file descriptor may exist if a database connection was closed -** but the associated file descriptor could not be closed because some -** other file descriptor open on the same file is holding a file-lock. -** Refer to comments in the unixClose() function and the lengthy comment -** describing "Posix Advisory Locking" at the start of this file for -** further details. Also, ticket #4018. -** -** If a suitable file descriptor is found, then it is returned. If no -** such file descriptor is located, -1 is returned. -*/ -static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ - UnixUnusedFd *pUnused = 0; - - /* Do not search for an unused file descriptor on vxworks. Not because - ** vxworks would not benefit from the change (it might, we're not sure), - ** but because no way to test it is currently available. It is better - ** not to risk breaking vxworks support for the sake of such an obscure - ** feature. */ -#if !OS_VXWORKS - struct stat sStat; /* Results of stat() call */ - - unixEnterMutex(); - - /* A stat() call may fail for various reasons. If this happens, it is - ** almost certain that an open() call on the same path will also fail. - ** For this reason, if an error occurs in the stat() call here, it is - ** ignored and -1 is returned. The caller will try to open a new file - ** descriptor on the same path, fail, and return an error to SQLite. - ** - ** Even if a subsequent open() call does succeed, the consequences of - ** not searching for a reusable file descriptor are not dire. */ - if( inodeList!=0 && 0==osStat(zPath, &sStat) ){ - unixInodeInfo *pInode; - - pInode = inodeList; - while( pInode && (pInode->fileId.dev!=sStat.st_dev - || pInode->fileId.ino!=(u64)sStat.st_ino) ){ - pInode = pInode->pNext; - } - if( pInode ){ - UnixUnusedFd **pp; - assert( sqlite3_mutex_notheld(pInode->pLockMutex) ); - sqlite3_mutex_enter(pInode->pLockMutex); - flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); - for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); - pUnused = *pp; - if( pUnused ){ - *pp = pUnused->pNext; - } - sqlite3_mutex_leave(pInode->pLockMutex); - } - } - unixLeaveMutex(); -#endif /* if !OS_VXWORKS */ - return pUnused; -} - -/* -** Find the mode, uid and gid of file zFile. -*/ -static int getFileMode( - const char *zFile, /* File name */ - mode_t *pMode, /* OUT: Permissions of zFile */ - uid_t *pUid, /* OUT: uid of zFile. */ - gid_t *pGid /* OUT: gid of zFile. */ -){ - struct stat sStat; /* Output of stat() on database file */ - int rc = SQLITE_OK; - if( 0==osStat(zFile, &sStat) ){ - *pMode = sStat.st_mode & 0777; - *pUid = sStat.st_uid; - *pGid = sStat.st_gid; - }else{ - rc = SQLITE_IOERR_FSTAT; - } - return rc; -} - -/* -** This function is called by unixOpen() to determine the unix permissions -** to create new files with. If no error occurs, then SQLITE_OK is returned -** and a value suitable for passing as the third argument to open(2) is -** written to *pMode. If an IO error occurs, an SQLite error code is -** returned and the value of *pMode is not modified. -** -** In most cases, this routine sets *pMode to 0, which will become -** an indication to robust_open() to create the file using -** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask. -** But if the file being opened is a WAL or regular journal file, then -** this function queries the file-system for the permissions on the -** corresponding database file and sets *pMode to this value. Whenever -** possible, WAL and journal files are created using the same permissions -** as the associated database file. -** -** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the -** original filename is unavailable. But 8_3_NAMES is only used for -** FAT filesystems and permissions do not matter there, so just use -** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero. -*/ -static int findCreateFileMode( - const char *zPath, /* Path of file (possibly) being created */ - int flags, /* Flags passed as 4th argument to xOpen() */ - mode_t *pMode, /* OUT: Permissions to open file with */ - uid_t *pUid, /* OUT: uid to set on the file */ - gid_t *pGid /* OUT: gid to set on the file */ -){ - int rc = SQLITE_OK; /* Return Code */ - *pMode = 0; - *pUid = 0; - *pGid = 0; - if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ - char zDb[MAX_PATHNAME+1]; /* Database file path */ - int nDb; /* Number of valid bytes in zDb */ - - /* zPath is a path to a WAL or journal file. The following block derives - ** the path to the associated database file from zPath. This block handles - ** the following naming conventions: - ** - ** "-journal" - ** "-wal" - ** "-journalNN" - ** "-walNN" - ** - ** 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 = sqlite3Strlen30(zPath) - 1; - while( nDb>0 && zPath[nDb]!='.' ){ - if( zPath[nDb]=='-' ){ - memcpy(zDb, zPath, nDb); - zDb[nDb] = '\0'; - rc = getFileMode(zDb, pMode, pUid, pGid); - break; - } - nDb--; - } - }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ - *pMode = 0600; - }else if( flags & SQLITE_OPEN_URI ){ - /* If this is a main database file and the file was opened using a URI - ** filename, check for the "modeof" parameter. If present, interpret - ** its value as a filename and try to copy the mode, uid and gid from - ** that file. */ - const char *z = sqlite3_uri_parameter(zPath, "modeof"); - if( z ){ - rc = getFileMode(z, pMode, pUid, pGid); - } - } - return rc; -} - -/* -** Open the file zPath. -** -** Previously, the SQLite OS layer used three functions in place of this -** one: -** -** sqlite3OsOpenReadWrite(); -** sqlite3OsOpenReadOnly(); -** sqlite3OsOpenExclusive(); -** -** These calls correspond to the following combinations of flags: -** -** ReadWrite() -> (READWRITE | CREATE) -** ReadOnly() -> (READONLY) -** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) -** -** The old OpenExclusive() accepted a boolean argument - "delFlag". If -** true, the file was configured to be automatically deleted when the -** file handle closed. To achieve the same effect using this new -** interface, add the DELETEONCLOSE flag to those specified above for -** OpenExclusive(). -*/ -static int unixOpen( - sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ - const char *zPath, /* Pathname of file to be opened */ - sqlite3_file *pFile, /* The file descriptor to be filled in */ - int flags, /* Input flags to control the opening */ - int *pOutFlags /* Output flags returned to SQLite core */ -){ - unixFile *p = (unixFile *)pFile; - int fd = -1; /* File descriptor returned by open() */ - int openFlags = 0; /* Flags to pass to open() */ - int eType = flags&0x0FFF00; /* Type of file to open */ - int noLock; /* True to omit locking primitives */ - int rc = SQLITE_OK; /* Function Return Code */ - int ctrlFlags = 0; /* UNIXFILE_* flags */ - - int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); - int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); - int isCreate = (flags & SQLITE_OPEN_CREATE); - int isReadonly = (flags & SQLITE_OPEN_READONLY); - int isReadWrite = (flags & SQLITE_OPEN_READWRITE); -#if SQLITE_ENABLE_LOCKING_STYLE - int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); -#endif -#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE - struct statfs fsInfo; -#endif - - /* If creating a super- or main-file journal, this function will open - ** a file-descriptor on the directory too. The first time unixSync() - ** is called the directory file descriptor will be fsync()ed and close()d. - */ - int isNewJrnl = (isCreate && ( - eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL - || eType==SQLITE_OPEN_WAL - )); - - /* If argument zPath is a NULL pointer, this function is required to open - ** a temporary file. Use this buffer to store the file name in. - */ - char zTmpname[MAX_PATHNAME+2]; - const char *zName = zPath; - - /* Check the following statements are true: - ** - ** (a) Exactly one of the READWRITE and READONLY flags must be set, and - ** (b) if CREATE is set, then READWRITE must also be set, and - ** (c) if EXCLUSIVE is set, then CREATE must also be set. - ** (d) if DELETEONCLOSE is set, then CREATE must also be set. - */ - assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); - assert(isCreate==0 || isReadWrite); - assert(isExclusive==0 || isCreate); - assert(isDelete==0 || isCreate); - - /* The main DB, main journal, WAL file and super-journal are never - ** automatically deleted. Nor are they ever temporary files. */ - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); - - /* Assert that the upper layer has set one of the "file-type" flags. */ - assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB - || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL - ); - - /* Detect a pid change and reset the PRNG. There is a race condition - ** here such that two or more threads all trying to open databases at - ** the same instant might all reset the PRNG. But multiple resets - ** are harmless. - */ - if( randomnessPid!=osGetpid(0) ){ - randomnessPid = osGetpid(0); - sqlite3_randomness(0,0); - } - 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); - if( pUnused ){ - fd = pUnused->fd; - }else{ - pUnused = sqlite3_malloc64(sizeof(*pUnused)); - if( !pUnused ){ - return SQLITE_NOMEM_BKPT; - } - } - p->pPreallocatedUnused = pUnused; - - /* Database filenames are double-zero terminated if they are not - ** URIs with parameters. Hence, they can always be passed into - ** sqlite3_uri_parameter(). */ - assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 ); - - }else if( !zName ){ - /* If zName is NULL, the upper layer is requesting a temp file. */ - assert(isDelete && !isNewJrnl); - rc = unixGetTempname(pVfs->mxPathname, zTmpname); - if( rc!=SQLITE_OK ){ - return rc; - } - zName = zTmpname; - - /* Generated temporary filenames are always double-zero terminated - ** for use by sqlite3_uri_parameter(). */ - assert( zName[strlen(zName)+1]==0 ); - } - - /* Determine the value of the flags parameter passed to POSIX function - ** open(). These must be calculated even if open() is not called, as - ** they may be stored as part of the file handle and used by the - ** 'conch file' locking functions later on. */ - if( isReadonly ) openFlags |= O_RDONLY; - if( isReadWrite ) openFlags |= O_RDWR; - if( isCreate ) openFlags |= O_CREAT; - if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); - openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW); - - if( fd<0 ){ - mode_t openMode; /* Permissions to create file with */ - uid_t uid; /* Userid for the file */ - gid_t gid; /* Groupid for the file */ - rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); - if( rc!=SQLITE_OK ){ - assert( !p->pPreallocatedUnused ); - assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); - return rc; - } - fd = robust_open(zName, openFlags, openMode); - OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); - assert( !isExclusive || (openFlags & O_CREAT)!=0 ); - if( fd<0 ){ - if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ - /* If unable to create a journal because the directory is not - ** writable, change the error code to indicate that. */ - rc = SQLITE_READONLY_DIRECTORY; - }else if( errno!=EISDIR && isReadWrite ){ - /* Failed to open the file for read/write access. Try read-only. */ - UnixUnusedFd *pReadonly = 0; - flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); - openFlags &= ~(O_RDWR|O_CREAT); - flags |= SQLITE_OPEN_READONLY; - openFlags |= O_RDONLY; - isReadonly = 1; - pReadonly = findReusableFd(zName, flags); - if( pReadonly ){ - fd = pReadonly->fd; - sqlite3_free(pReadonly); - }else{ - fd = robust_open(zName, openFlags, openMode); - } - } - } - if( fd<0 ){ - int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); - if( rc==SQLITE_OK ) rc = rc2; - goto open_finished; - } - - /* The owner of the rollback journal or WAL file should always be the - ** same as the owner of the database file. Try to ensure that this is - ** the case. The chown() system call will be a no-op if the current - ** process lacks root privileges, be we should at least try. Without - ** this step, if a root process opens a database file, it can leave - ** behinds a journal/WAL that is owned by root and hence make the - ** database inaccessible to unprivileged processes. - ** - ** If openMode==0, then that means uid and gid are not set correctly - ** (probably because SQLite is configured to use 8+3 filename mode) and - ** in that case we do not want to attempt the chown(). - */ - if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){ - robustFchown(fd, uid, gid); - } - } - assert( fd>=0 ); - if( pOutFlags ){ - *pOutFlags = flags; - } - - if( p->pPreallocatedUnused ){ - p->pPreallocatedUnused->fd = fd; - p->pPreallocatedUnused->flags = - flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); - } - - if( isDelete ){ -#if OS_VXWORKS - zPath = zName; -#elif defined(SQLITE_UNLINK_AFTER_CLOSE) - zPath = sqlite3_mprintf("%s", zName); - if( zPath==0 ){ - robust_close(p, fd, __LINE__); - return SQLITE_NOMEM_BKPT; - } -#else - osUnlink(zName); -#endif - } -#if SQLITE_ENABLE_LOCKING_STYLE - else{ - p->openFlags = openFlags; - } -#endif - -#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE - if( fstatfs(fd, &fsInfo) == -1 ){ - storeLastErrno(p, errno); - robust_close(p, fd, __LINE__); - return SQLITE_IOERR_ACCESS; - } - if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { - ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; - } - if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { - ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; - } -#endif - - /* Set up appropriate ctrlFlags */ - if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; - if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; - noLock = eType!=SQLITE_OPEN_MAIN_DB; - if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; - if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; - if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; - -#if SQLITE_ENABLE_LOCKING_STYLE -#if SQLITE_PREFER_PROXY_LOCKING - isAutoProxy = 1; -#endif - if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ - char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); - int useProxy = 0; - - /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means - ** never use proxy, NULL means use proxy for non-local files only. */ - if( envforce!=NULL ){ - useProxy = atoi(envforce)>0; - }else{ - useProxy = !(fsInfo.f_flags&MNT_LOCAL); - } - if( useProxy ){ - rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); - if( rc==SQLITE_OK ){ - rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); - if( rc!=SQLITE_OK ){ - /* Use unixClose to clean up the resources added in fillInUnixFile - ** and clear all the structure's references. Specifically, - ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op - */ - unixClose(pFile); - return rc; - } - } - goto open_finished; - } - } -#endif - - assert( zPath==0 || zPath[0]=='/' - || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL - ); - rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); - -open_finished: - if( rc!=SQLITE_OK ){ - sqlite3_free(p->pPreallocatedUnused); - } - return rc; -} - - -/* -** Delete the file at zPath. If the dirSync argument is true, fsync() -** the directory after deleting the file. -*/ -static int unixDelete( - sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ - const char *zPath, /* Name of file to be deleted */ - int dirSync /* If true, fsync() directory after deleting file */ -){ - int rc = SQLITE_OK; - UNUSED_PARAMETER(NotUsed); - SimulateIOError(return SQLITE_IOERR_DELETE); - if( osUnlink(zPath)==(-1) ){ - if( errno==ENOENT -#if OS_VXWORKS - || osAccess(zPath,0)!=0 -#endif - ){ - rc = SQLITE_IOERR_DELETE_NOENT; - }else{ - rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); - } - return rc; - } -#ifndef SQLITE_DISABLE_DIRSYNC - if( (dirSync & 1)!=0 ){ - int fd; - rc = osOpenDirectory(zPath, &fd); - if( rc==SQLITE_OK ){ - if( full_fsync(fd,0,0) ){ - rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); - } - robust_close(0, fd, __LINE__); - }else{ - assert( rc==SQLITE_CANTOPEN ); - rc = SQLITE_OK; - } - } -#endif - return rc; -} - -/* -** Test the existence of or access permissions of file zPath. The -** test performed depends on the value of flags: -** -** SQLITE_ACCESS_EXISTS: Return 1 if the file exists -** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. -** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. -** -** Otherwise return 0. -*/ -static int unixAccess( - sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */ - const char *zPath, /* Path of the file to examine */ - int flags, /* What do we want to learn about the zPath file? */ - int *pResOut /* Write result boolean here */ -){ - UNUSED_PARAMETER(NotUsed); - SimulateIOError( return SQLITE_IOERR_ACCESS; ); - assert( pResOut!=0 ); - - /* The spec says there are three possible values for flags. But only - ** two of them are actually used */ - assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); - - if( flags==SQLITE_ACCESS_EXISTS ){ - struct stat buf; - *pResOut = 0==osStat(zPath, &buf) && - (!S_ISREG(buf.st_mode) || buf.st_size>0); - }else{ - *pResOut = osAccess(zPath, W_OK|R_OK)==0; - } - return SQLITE_OK; -} - -/* -** A pathname under construction -*/ -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*); - -/* -** Append a single path element to the DbPath under construction -*/ -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 */ -){ - assert( nName>0 ); - assert( zName!=0 ); - if( zName[0]=='.' ){ - if( nName==1 ) return; - if( zName[1]=='.' && nName==2 ){ - if( pPath->nUsed>1 ){ - assert( pPath->zOut[0]=='/' ); - while( pPath->zOut[--pPath->nUsed]!='/' ){} - } - return; - } - } - if( pPath->nUsed + nName + 2 >= pPath->nOut ){ - pPath->rc = SQLITE_ERROR; - return; - } - 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); - } - }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); - } - } -#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++] ); -} - -/* -** Turn a relative pathname into a full pathname. The relative path -** is stored as a nul-terminated string in the buffer pointed to by -** zPath. -** -** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes -** (in this case, MAX_PATHNAME bytes). The full-path is written to -** this buffer before returning. -*/ -static int unixFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zPath, /* Possibly relative input path */ - int nOut, /* Size of output buffer in bytes */ - char *zOut /* Output buffer */ -){ - DbPath path; - UNUSED_PARAMETER(pVfs); - 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); - } - 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 -** within the shared library, and closing the shared library. -*/ -#include -static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){ - UNUSED_PARAMETER(NotUsed); - return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); -} - -/* -** SQLite calls this function immediately after a call to unixDlSym() or -** unixDlOpen() fails (returns a null pointer). If a more detailed error -** message is available, it is written to zBufOut. If no error message -** is available, zBufOut is left unmodified and SQLite uses a default -** error message. -*/ -static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){ - const char *zErr; - UNUSED_PARAMETER(NotUsed); - unixEnterMutex(); - zErr = dlerror(); - if( zErr ){ - sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); - } - unixLeaveMutex(); -} -static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){ - /* - ** GCC with -pedantic-errors says that C90 does not allow a void* to be - ** cast into a pointer to a function. And yet the library dlsym() routine - ** returns a void* which is really a pointer to a function. So how do we - ** use dlsym() with -pedantic-errors? - ** - ** Variable x below is defined to be a pointer to a function taking - ** parameters void* and const char* and returning a pointer to a function. - ** We initialize x by assigning it a pointer to the dlsym() function. - ** (That assignment requires a cast.) Then we call the function that - ** x points to. - ** - ** This work-around is unlikely to work correctly on any system where - ** you really cannot cast a function pointer into void*. But then, on the - ** other hand, dlsym() will not work on such a system either, so we have - ** not really lost anything. - */ - void (*(*x)(void*,const char*))(void); - UNUSED_PARAMETER(NotUsed); - x = (void(*(*)(void*,const char*))(void))dlsym; - return (*x)(p, zSym); -} -static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){ - UNUSED_PARAMETER(NotUsed); - dlclose(pHandle); -} -#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ - #define unixDlOpen 0 - #define unixDlError 0 - #define unixDlSym 0 - #define unixDlClose 0 -#endif - -/* -** Write nBuf bytes of random data to the supplied buffer zBuf. -*/ -static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ - UNUSED_PARAMETER(NotUsed); - assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int))); - - /* We have to initialize zBuf to prevent valgrind from reporting - ** errors. The reports issued by valgrind are incorrect - we would - ** prefer that the randomness be increased by making use of the - ** uninitialized space in zBuf - but valgrind errors tend to worry - ** some users. Rather than argue, it seems easier just to initialize - ** the whole array and silence valgrind, even if that means less randomness - ** in the random seed. - ** - ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence. This makes the - ** tests repeatable. - */ - memset(zBuf, 0, nBuf); - randomnessPid = osGetpid(0); -#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) - { - int fd, got; - fd = robust_open("/dev/urandom", O_RDONLY, 0); - if( fd<0 ){ - time_t t; - time(&t); - memcpy(zBuf, &t, sizeof(t)); - memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid)); - assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf ); - nBuf = sizeof(t) + sizeof(randomnessPid); - }else{ - do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR ); - robust_close(0, fd, __LINE__); - } - } -#endif - return nBuf; -} - - -/* -** Sleep for a little while. Return the amount of time slept. -** The argument is the number of microseconds we want to sleep. -** The return value is the number of microseconds of sleep actually -** requested from the underlying operating system, a number which -** might be greater than or equal to the argument, but not less -** than the argument. -*/ -static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0 - struct timespec sp; - sp.tv_sec = microseconds / 1000000; - sp.tv_nsec = (microseconds % 1000000) * 1000; - - /* Almost all modern unix systems support nanosleep(). But if you are - ** compiling for one of the rare exceptions, you can use - ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if - ** usleep() is available) in order to bypass the use of nanosleep() */ - nanosleep(&sp, NULL); - - UNUSED_PARAMETER(NotUsed); - return microseconds; -#elif defined(HAVE_USLEEP) && HAVE_USLEEP - if( microseconds>=1000000 ) sleep(microseconds/1000000); - if( microseconds%1000000 ) usleep(microseconds%1000000); - UNUSED_PARAMETER(NotUsed); - return microseconds; -#else - int seconds = (microseconds+999999)/1000000; - sleep(seconds); - UNUSED_PARAMETER(NotUsed); - return seconds*1000000; -#endif -} - -/* -** The following variable, if set to a non-zero value, is interpreted as -** the number of seconds since 1970 and is used to set the result of -** sqlite3OsCurrentTime() during testing. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ -#endif - -/* -** Find the current time (in Universal Coordinated Time). Write into *piNow -** the current time and date as a Julian Day number times 86_400_000. In -** other words, write into *piNow the number of milliseconds since the Julian -** epoch of noon in Greenwich on November 24, 4714 B.C according to the -** proleptic Gregorian calendar. -** -** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date -** cannot be found. -*/ -static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ - static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; - int rc = SQLITE_OK; -#if defined(NO_GETTOD) - time_t t; - time(&t); - *piNow = ((sqlite3_int64)t)*1000 + unixEpoch; -#elif OS_VXWORKS - struct timespec sNow; - clock_gettime(CLOCK_REALTIME, &sNow); - *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000; -#else - struct timeval sNow; - (void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */ - *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000; -#endif - -#ifdef SQLITE_TEST - if( sqlite3_current_time ){ - *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; - } -#endif - UNUSED_PARAMETER(NotUsed); - return rc; -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Find the current time (in Universal Coordinated Time). Write the -** current time and date as a Julian Day number into *prNow and -** return 0. Return 1 if the time and date cannot be found. -*/ -static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ - sqlite3_int64 i = 0; - int rc; - UNUSED_PARAMETER(NotUsed); - rc = unixCurrentTimeInt64(0, &i); - *prNow = i/86400000.0; - return rc; -} -#else -# define unixCurrentTime 0 -#endif - -/* -** The xGetLastError() method is designed to return a better -** low-level error message when operating-system problems come up -** during SQLite operation. Only the integer return code is currently -** used. -*/ -static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ - UNUSED_PARAMETER(NotUsed); - UNUSED_PARAMETER(NotUsed2); - UNUSED_PARAMETER(NotUsed3); - return errno; -} - - -/* -************************ End of sqlite3_vfs methods *************************** -******************************************************************************/ - -/****************************************************************************** -************************** Begin Proxy Locking ******************************** -** -** Proxy locking is a "uber-locking-method" in this sense: It uses the -** other locking methods on secondary lock files. Proxy locking is a -** meta-layer over top of the primitive locking implemented above. For -** this reason, the division that implements of proxy locking is deferred -** until late in the file (here) after all of the other I/O methods have -** been defined - so that the primitive locking methods are available -** as services to help with the implementation of proxy locking. -** -**** -** -** The default locking schemes in SQLite use byte-range locks on the -** database file to coordinate safe, concurrent access by multiple readers -** and writers [http://sqlite.org/lockingv3.html]. The five file locking -** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented -** as POSIX read & write locks over fixed set of locations (via fsctl), -** on AFP and SMB only exclusive byte-range locks are available via fsctl -** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states. -** To simulate a F_RDLCK on the shared range, on AFP a randomly selected -** address in the shared range is taken for a SHARED lock, the entire -** shared range is taken for an EXCLUSIVE lock): -** -** PENDING_BYTE 0x40000000 -** RESERVED_BYTE 0x40000001 -** SHARED_RANGE 0x40000002 -> 0x40000200 -** -** This works well on the local file system, but shows a nearly 100x -** slowdown in read performance on AFP because the AFP client disables -** the read cache when byte-range locks are present. Enabling the read -** cache exposes a cache coherency problem that is present on all OS X -** supported network file systems. NFS and AFP both observe the -** close-to-open semantics for ensuring cache coherency -** [http://nfs.sourceforge.net/#faq_a8], which does not effectively -** address the requirements for concurrent database access by multiple -** readers and writers -** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html]. -** -** To address the performance and cache coherency issues, proxy file locking -** changes the way database access is controlled by limiting access to a -** single host at a time and moving file locks off of the database file -** and onto a proxy file on the local file system. -** -** -** Using proxy locks -** ----------------- -** -** C APIs -** -** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE, -** | ":auto:"); -** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE, -** &); -** -** -** SQL pragmas -** -** PRAGMA [database.]lock_proxy_file= | :auto: -** PRAGMA [database.]lock_proxy_file -** -** Specifying ":auto:" means that if there is a conch file with a matching -** host ID in it, the proxy path in the conch file will be used, otherwise -** a proxy path based on the user's temp dir -** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the -** actual proxy file name is generated from the name and path of the -** database file. For example: -** -** For database path "/Users/me/foo.db" -** The lock path will be "/sqliteplocks/_Users_me_foo.db:auto:") -** -** Once a lock proxy is configured for a database connection, it can not -** be removed, however it may be switched to a different proxy path via -** the above APIs (assuming the conch file is not being held by another -** connection or process). -** -** -** How proxy locking works -** ----------------------- -** -** Proxy file locking relies primarily on two new supporting files: -** -** * conch file to limit access to the database file to a single host -** at a time -** -** * proxy file to act as a proxy for the advisory locks normally -** taken on the database -** -** The conch file - to use a proxy file, sqlite must first "hold the conch" -** by taking an sqlite-style shared lock on the conch file, reading the -** contents and comparing the host's unique host ID (see below) and lock -** proxy path against the values stored in the conch. The conch file is -** stored in the same directory as the database file and the file name -** is patterned after the database file name as ".-conch". -** If the conch file does not exist, or its contents do not match the -** host ID and/or proxy path, then the lock is escalated to an exclusive -** lock and the conch file contents is updated with the host ID and proxy -** path and the lock is downgraded to a shared lock again. If the conch -** is held by another process (with a shared lock), the exclusive lock -** will fail and SQLITE_BUSY is returned. -** -** The proxy file - a single-byte file used for all advisory file locks -** normally taken on the database file. This allows for safe sharing -** of the database file for multiple readers and writers on the same -** host (the conch ensures that they all use the same local lock file). -** -** Requesting the lock proxy does not immediately take the conch, it is -** only taken when the first request to lock database file is made. -** This matches the semantics of the traditional locking behavior, where -** opening a connection to a database file does not take a lock on it. -** The shared lock and an open file descriptor are maintained until -** the connection to the database is closed. -** -** The proxy file and the lock file are never deleted so they only need -** to be created the first time they are used. -** -** Configuration options -** --------------------- -** -** SQLITE_PREFER_PROXY_LOCKING -** -** Database files accessed on non-local file systems are -** automatically configured for proxy locking, lock files are -** named automatically using the same logic as -** PRAGMA lock_proxy_file=":auto:" -** -** SQLITE_PROXY_DEBUG -** -** Enables the logging of error messages during host id file -** retrieval and creation -** -** LOCKPROXYDIR -** -** Overrides the default directory used for lock proxy files that -** are named automatically via the ":auto:" setting -** -** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS -** -** Permissions to use when creating a directory for storing the -** lock proxy files, only used when LOCKPROXYDIR is not set. -** -** -** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING, -** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will -** force proxy locking to be used for every database file opened, and 0 -** will force automatic proxy locking to be disabled for all database -** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or -** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). -*/ - -/* -** Proxy locking is only available on MacOSX -*/ -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - -/* -** The proxyLockingContext has the path and file structures for the remote -** and local proxy files in it -*/ -typedef struct proxyLockingContext proxyLockingContext; -struct proxyLockingContext { - unixFile *conchFile; /* Open conch file */ - char *conchFilePath; /* Name of the conch file */ - unixFile *lockProxy; /* Open proxy lock file */ - char *lockProxyPath; /* Name of the proxy lock file */ - char *dbPath; /* Name of the open file */ - int conchHeld; /* 1 if the conch is held, -1 if lockless */ - int nFails; /* Number of conch taking failures */ - void *oldLockingContext; /* Original lockingcontext to restore on close */ - sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ -}; - -/* -** The proxy lock file path for the database at dbPath is written into lPath, -** which must point to valid, writable memory large enough for a maxLen length -** file path. -*/ -static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ - int len; - int dbLen; - int i; - -#ifdef LOCKPROXYDIR - len = strlcpy(lPath, LOCKPROXYDIR, maxLen); -#else -# ifdef _CS_DARWIN_USER_TEMP_DIR - { - if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ - OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", - lPath, errno, osGetpid(0))); - return SQLITE_IOERR_LOCK; - } - len = strlcat(lPath, "sqliteplocks", maxLen); - } -# else - len = strlcpy(lPath, "/tmp/", maxLen); -# endif -#endif - - if( lPath[len-1]!='/' ){ - len = strlcat(lPath, "/", maxLen); - } - - /* transform the db path to a unique cache name */ - dbLen = (int)strlen(dbPath); - for( i=0; i 0) ){ - /* only mkdir if leaf dir != "." or "/" or ".." */ - if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') - || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ - buf[i]='\0'; - if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ - int err=errno; - if( err!=EEXIST ) { - OSTRACE(("CREATELOCKPATH FAILED creating %s, " - "'%s' proxy lock path=%s pid=%d\n", - buf, strerror(err), lockPath, osGetpid(0))); - return err; - } - } - } - start=i+1; - } - buf[i] = lockPath[i]; - } - OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0))); - return 0; -} - -/* -** Create a new VFS file descriptor (stored in memory obtained from -** sqlite3_malloc) and open the file named "path" in the file descriptor. -** -** The caller is responsible not only for closing the file descriptor -** but also for freeing the memory associated with the file descriptor. -*/ -static int proxyCreateUnixFile( - const char *path, /* path for the new unixFile */ - unixFile **ppFile, /* unixFile created and returned by ref */ - int islockfile /* if non zero missing dirs will be created */ -) { - int fd = -1; - unixFile *pNew; - int rc = SQLITE_OK; - int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW; - sqlite3_vfs dummyVfs; - int terrno = 0; - UnixUnusedFd *pUnused = NULL; - - /* 1. first try to open/create the file - ** 2. if that fails, and this is a lock file (not-conch), try creating - ** the parent directories and then try again. - ** 3. if that fails, try to open the file read-only - ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file - */ - pUnused = findReusableFd(path, openFlags); - if( pUnused ){ - fd = pUnused->fd; - }else{ - pUnused = sqlite3_malloc64(sizeof(*pUnused)); - if( !pUnused ){ - return SQLITE_NOMEM_BKPT; - } - } - if( fd<0 ){ - fd = robust_open(path, openFlags, 0); - terrno = errno; - if( fd<0 && errno==ENOENT && islockfile ){ - if( proxyCreateLockPath(path) == SQLITE_OK ){ - fd = robust_open(path, openFlags, 0); - } - } - } - if( fd<0 ){ - openFlags = O_RDONLY | O_NOFOLLOW; - fd = robust_open(path, openFlags, 0); - terrno = errno; - } - if( fd<0 ){ - if( islockfile ){ - return SQLITE_BUSY; - } - switch (terrno) { - case EACCES: - return SQLITE_PERM; - case EIO: - return SQLITE_IOERR_LOCK; /* even though it is the conch */ - default: - return SQLITE_CANTOPEN_BKPT; - } - } - - pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); - if( pNew==NULL ){ - rc = SQLITE_NOMEM_BKPT; - goto end_create_proxy; - } - memset(pNew, 0, sizeof(unixFile)); - pNew->openFlags = openFlags; - memset(&dummyVfs, 0, sizeof(dummyVfs)); - dummyVfs.pAppData = (void*)&autolockIoFinder; - dummyVfs.zName = "dummy"; - pUnused->fd = fd; - pUnused->flags = openFlags; - pNew->pPreallocatedUnused = pUnused; - - rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); - if( rc==SQLITE_OK ){ - *ppFile = pNew; - return SQLITE_OK; - } -end_create_proxy: - robust_close(pNew, fd, __LINE__); - sqlite3_free(pNew); - sqlite3_free(pUnused); - return rc; -} - -#ifdef SQLITE_TEST -/* simulate multiple hosts by creating unique hostid file paths */ -SQLITE_API int sqlite3_hostid_num = 0; -#endif - -#define PROXY_HOSTIDLEN 16 /* conch file host id length */ - -#if HAVE_GETHOSTUUID -/* Not always defined in the headers as it ought to be */ -extern int gethostuuid(uuid_t id, const struct timespec *wait); -#endif - -/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN -** bytes of writable memory. -*/ -static int proxyGetHostID(unsigned char *pHostID, int *pError){ - assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); - memset(pHostID, 0, PROXY_HOSTIDLEN); -#if HAVE_GETHOSTUUID - { - struct timespec timeout = {1, 0}; /* 1 sec timeout */ - if( gethostuuid(pHostID, &timeout) ){ - int err = errno; - if( pError ){ - *pError = err; - } - return SQLITE_IOERR; - } - } -#else - UNUSED_PARAMETER(pError); -#endif -#ifdef SQLITE_TEST - /* simulate multiple hosts by creating unique hostid file paths */ - if( sqlite3_hostid_num != 0){ - pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); - } -#endif - - return SQLITE_OK; -} - -/* The conch file contains the header, host id and lock file path - */ -#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ -#define PROXY_HEADERLEN 1 /* conch file header length */ -#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) -#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) - -/* -** Takes an open conch file, copies the contents to a new path and then moves -** it back. The newly created file's file descriptor is assigned to the -** conch file structure and finally the original conch file descriptor is -** closed. Returns zero if successful. -*/ -static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - unixFile *conchFile = pCtx->conchFile; - char tPath[MAXPATHLEN]; - char buf[PROXY_MAXCONCHLEN]; - char *cPath = pCtx->conchFilePath; - size_t readLen = 0; - size_t pathLen = 0; - char errmsg[64] = ""; - int fd = -1; - int rc = -1; - UNUSED_PARAMETER(myHostID); - - /* create a new path by replace the trailing '-conch' with '-break' */ - pathLen = strlcpy(tPath, cPath, MAXPATHLEN); - if( pathLen>MAXPATHLEN || pathLen<6 || - (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ - sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen); - goto end_breaklock; - } - /* read the conch content */ - readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0); - if( readLenh, __LINE__); - conchFile->h = fd; - conchFile->openFlags = O_RDWR | O_CREAT; - -end_breaklock: - if( rc ){ - if( fd>=0 ){ - osUnlink(tPath); - robust_close(pFile, fd, __LINE__); - } - fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); - } - return rc; -} - -/* Take the requested lock on the conch file and break a stale lock if the -** host id matches. -*/ -static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - unixFile *conchFile = pCtx->conchFile; - int rc = SQLITE_OK; - int nTries = 0; - struct timespec conchModTime; - - memset(&conchModTime, 0, sizeof(conchModTime)); - do { - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); - nTries ++; - if( rc==SQLITE_BUSY ){ - /* If the lock failed (busy): - * 1st try: get the mod time of the conch, wait 0.5s and try again. - * 2nd try: fail if the mod time changed or host id is different, wait - * 10 sec and try again - * 3rd try: break the lock unless the mod time has changed. - */ - struct stat buf; - if( osFstat(conchFile->h, &buf) ){ - storeLastErrno(pFile, errno); - return SQLITE_IOERR_LOCK; - } - - if( nTries==1 ){ - conchModTime = buf.st_mtimespec; - unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/ - continue; - } - - assert( nTries>1 ); - if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || - conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ - return SQLITE_BUSY; - } - - if( nTries==2 ){ - char tBuf[PROXY_MAXCONCHLEN]; - int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); - if( len<0 ){ - storeLastErrno(pFile, errno); - return SQLITE_IOERR_LOCK; - } - if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ - /* don't break the lock if the host id doesn't match */ - if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ - return SQLITE_BUSY; - } - }else{ - /* don't break the lock on short read or a version mismatch */ - return SQLITE_BUSY; - } - unixSleep(0,10000000); /* wait 10 sec and try the lock again */ - continue; - } - - assert( nTries==3 ); - if( 0==proxyBreakConchLock(pFile, myHostID) ){ - rc = SQLITE_OK; - if( lockType==EXCLUSIVE_LOCK ){ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); - } - if( !rc ){ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); - } - } - } - } while( rc==SQLITE_BUSY && nTries<3 ); - - return rc; -} - -/* Takes the conch by taking a shared lock and read the contents conch, if -** lockPath is non-NULL, the host ID and lock file path must match. A NULL -** lockPath means that the lockPath in the conch file will be used if the -** host IDs match, or a new lock path will be generated automatically -** and written to the conch file. -*/ -static int proxyTakeConch(unixFile *pFile){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - - if( pCtx->conchHeld!=0 ){ - return SQLITE_OK; - }else{ - unixFile *conchFile = pCtx->conchFile; - uuid_t myHostID; - int pError = 0; - char readBuf[PROXY_MAXCONCHLEN]; - char lockPath[MAXPATHLEN]; - char *tempLockPath = NULL; - int rc = SQLITE_OK; - int createConch = 0; - int hostIdMatch = 0; - int readLen = 0; - int tryOldLockPath = 0; - int forceNewLockPath = 0; - - OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - osGetpid(0))); - - rc = proxyGetHostID(myHostID, &pError); - if( (rc&0xff)==SQLITE_IOERR ){ - storeLastErrno(pFile, pError); - goto end_takeconch; - } - rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); - if( rc!=SQLITE_OK ){ - goto end_takeconch; - } - /* read the existing conch file */ - readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); - if( readLen<0 ){ - /* I/O error: lastErrno set by seekAndRead */ - storeLastErrno(pFile, conchFile->lastErrno); - rc = SQLITE_IOERR_READ; - goto end_takeconch; - }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || - readBuf[0]!=(char)PROXY_CONCHVERSION ){ - /* a short read or version format mismatch means we need to create a new - ** conch file. - */ - createConch = 1; - } - /* if the host id matches and the lock path already exists in the conch - ** we'll try to use the path there, if we can't open that path, we'll - ** retry with a new auto-generated path - */ - do { /* in case we need to try again for an :auto: named lock file */ - - if( !createConch && !forceNewLockPath ){ - hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, - PROXY_HOSTIDLEN); - /* if the conch has data compare the contents */ - if( !pCtx->lockProxyPath ){ - /* for auto-named local lock file, just check the host ID and we'll - ** use the local lock file path that's already in there - */ - if( hostIdMatch ){ - size_t pathLen = (readLen - PROXY_PATHINDEX); - - if( pathLen>=MAXPATHLEN ){ - pathLen=MAXPATHLEN-1; - } - memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); - lockPath[pathLen] = 0; - tempLockPath = lockPath; - tryOldLockPath = 1; - /* create a copy of the lock path if the conch is taken */ - goto end_takeconch; - } - }else if( hostIdMatch - && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], - readLen-PROXY_PATHINDEX) - ){ - /* conch host and lock path match */ - goto end_takeconch; - } - } - - /* if the conch isn't writable and doesn't match, we can't take it */ - if( (conchFile->openFlags&O_RDWR) == 0 ){ - rc = SQLITE_BUSY; - goto end_takeconch; - } - - /* either the conch didn't match or we need to create a new one */ - if( !pCtx->lockProxyPath ){ - proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); - tempLockPath = lockPath; - /* create a copy of the lock path _only_ if the conch is taken */ - } - - /* update conch with host and path (this will fail if other process - ** has a shared lock already), if the host id matches, use the big - ** stick. - */ - futimes(conchFile->h, NULL); - if( hostIdMatch && !createConch ){ - if( conchFile->pInode && conchFile->pInode->nShared>1 ){ - /* We are trying for an exclusive lock but another thread in this - ** same process is still holding a shared lock. */ - rc = SQLITE_BUSY; - } else { - rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); - } - }else{ - rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); - } - if( rc==SQLITE_OK ){ - char writeBuffer[PROXY_MAXCONCHLEN]; - int writeSize = 0; - - writeBuffer[0] = (char)PROXY_CONCHVERSION; - memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); - if( pCtx->lockProxyPath!=NULL ){ - strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, - MAXPATHLEN); - }else{ - strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); - } - writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); - robust_ftruncate(conchFile->h, writeSize); - rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); - full_fsync(conchFile->h,0,0); - /* If we created a new conch file (not just updated the contents of a - ** valid conch file), try to match the permissions of the database - */ - if( rc==SQLITE_OK && createConch ){ - struct stat buf; - int err = osFstat(pFile->h, &buf); - if( err==0 ){ - mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | - S_IROTH|S_IWOTH); - /* try to match the database file R/W permissions, ignore failure */ -#ifndef SQLITE_PROXY_DEBUG - osFchmod(conchFile->h, cmode); -#else - do{ - rc = osFchmod(conchFile->h, cmode); - }while( rc==(-1) && errno==EINTR ); - if( rc!=0 ){ - int code = errno; - fprintf(stderr, "fchmod %o FAILED with %d %s\n", - cmode, code, strerror(code)); - } else { - fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); - } - }else{ - int code = errno; - fprintf(stderr, "STAT FAILED[%d] with %d %s\n", - err, code, strerror(code)); -#endif - } - } - } - conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); - - end_takeconch: - OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h)); - if( rc==SQLITE_OK && pFile->openFlags ){ - int fd; - if( pFile->h>=0 ){ - robust_close(pFile, pFile->h, __LINE__); - } - pFile->h = -1; - fd = robust_open(pCtx->dbPath, pFile->openFlags, 0); - OSTRACE(("TRANSPROXY: OPEN %d\n", fd)); - if( fd>=0 ){ - pFile->h = fd; - }else{ - rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called - during locking */ - } - } - if( rc==SQLITE_OK && !pCtx->lockProxy ){ - char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; - rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); - if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ - /* we couldn't create the proxy lock file with the old lock file path - ** so try again via auto-naming - */ - forceNewLockPath = 1; - tryOldLockPath = 0; - continue; /* go back to the do {} while start point, try again */ - } - } - if( rc==SQLITE_OK ){ - /* Need to make a copy of path if we extracted the value - ** from the conch file or the path was allocated on the stack - */ - if( tempLockPath ){ - pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); - if( !pCtx->lockProxyPath ){ - rc = SQLITE_NOMEM_BKPT; - } - } - } - if( rc==SQLITE_OK ){ - pCtx->conchHeld = 1; - - if( pCtx->lockProxy->pMethod == &afpIoMethods ){ - afpLockingContext *afpCtx; - afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; - afpCtx->dbPath = pCtx->lockProxyPath; - } - } else { - conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); - } - OSTRACE(("TAKECONCH %d %s\n", conchFile->h, - rc==SQLITE_OK?"ok":"failed")); - return rc; - } while (1); /* in case we need to retry the :auto: lock file - - ** we should never get here except via the 'continue' call. */ - } -} - -/* -** If pFile holds a lock on a conch file, then release that lock. -*/ -static int proxyReleaseConch(unixFile *pFile){ - int rc = SQLITE_OK; /* Subroutine return code */ - proxyLockingContext *pCtx; /* The locking context for the proxy lock */ - unixFile *conchFile; /* Name of the conch file */ - - pCtx = (proxyLockingContext *)pFile->lockingContext; - conchFile = pCtx->conchFile; - OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - osGetpid(0))); - if( pCtx->conchHeld>0 ){ - rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); - } - pCtx->conchHeld = 0; - OSTRACE(("RELEASECONCH %d %s\n", conchFile->h, - (rc==SQLITE_OK ? "ok" : "failed"))); - return rc; -} - -/* -** Given the name of a database file, compute the name of its conch file. -** Store the conch filename in memory obtained from sqlite3_malloc64(). -** Make *pConchPath point to the new name. Return SQLITE_OK on success -** or SQLITE_NOMEM if unable to obtain memory. -** -** The caller is responsible for ensuring that the allocated memory -** space is eventually freed. -** -** *pConchPath is set to NULL if a memory allocation error occurs. -*/ -static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ - int i; /* Loop counter */ - int len = (int)strlen(dbPath); /* Length of database filename - dbPath */ - char *conchPath; /* buffer in which to construct conch name */ - - /* Allocate space for the conch filename and initialize the name to - ** the name of the original database file. */ - *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); - if( conchPath==0 ){ - return SQLITE_NOMEM_BKPT; - } - memcpy(conchPath, dbPath, len+1); - - /* now insert a "." before the last / character */ - for( i=(len-1); i>=0; i-- ){ - if( conchPath[i]=='/' ){ - i++; - break; - } - } - conchPath[i]='.'; - while ( ilockingContext; - char *oldPath = pCtx->lockProxyPath; - int rc = SQLITE_OK; - - if( pFile->eFileLock!=NO_LOCK ){ - return SQLITE_BUSY; - } - - /* nothing to do if the path is NULL, :auto: or matches the existing path */ - if( !path || path[0]=='\0' || !strcmp(path, ":auto:") || - (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){ - return SQLITE_OK; - }else{ - unixFile *lockProxy = pCtx->lockProxy; - pCtx->lockProxy=NULL; - pCtx->conchHeld = 0; - if( lockProxy!=NULL ){ - rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy); - if( rc ) return rc; - sqlite3_free(lockProxy); - } - sqlite3_free(oldPath); - pCtx->lockProxyPath = sqlite3DbStrDup(0, path); - } - - return rc; -} - -/* -** pFile is a file that has been opened by a prior xOpen call. dbPath -** is a string buffer at least MAXPATHLEN+1 characters in size. -** -** This routine find the filename associated with pFile and writes it -** int dbPath. -*/ -static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ -#if defined(__APPLE__) - if( pFile->pMethod == &afpIoMethods ){ - /* afp style keeps a reference to the db path in the filePath field - ** of the struct */ - assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); - strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, - MAXPATHLEN); - } else -#endif - if( pFile->pMethod == &dotlockIoMethods ){ - /* dot lock style uses the locking context to store the dot lock - ** file path */ - int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); - memcpy(dbPath, (char *)pFile->lockingContext, len + 1); - }else{ - /* all other styles use the locking context to store the db file path */ - assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); - strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN); - } - return SQLITE_OK; -} - -/* -** Takes an already filled in unix file and alters it so all file locking -** will be performed on the local proxy lock file. The following fields -** are preserved in the locking context so that they can be restored and -** the unix structure properly cleaned up at close time: -** ->lockingContext -** ->pMethod -*/ -static int proxyTransformUnixFile(unixFile *pFile, const char *path) { - proxyLockingContext *pCtx; - char dbPath[MAXPATHLEN+1]; /* Name of the database file */ - char *lockPath=NULL; - int rc = SQLITE_OK; - - if( pFile->eFileLock!=NO_LOCK ){ - return SQLITE_BUSY; - } - proxyGetDbPathForUnixFile(pFile, dbPath); - if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){ - lockPath=NULL; - }else{ - lockPath=(char *)path; - } - - OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, - (lockPath ? lockPath : ":auto:"), osGetpid(0))); - - pCtx = sqlite3_malloc64( sizeof(*pCtx) ); - if( pCtx==0 ){ - return SQLITE_NOMEM_BKPT; - } - memset(pCtx, 0, sizeof(*pCtx)); - - rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); - if( rc==SQLITE_OK ){ - rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0); - if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){ - /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and - ** (c) the file system is read-only, then enable no-locking access. - ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts - ** that openFlags will have only one of O_RDONLY or O_RDWR. - */ - struct statfs fsInfo; - struct stat conchInfo; - int goLockless = 0; - - if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) { - int err = errno; - if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){ - goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY; - } - } - if( goLockless ){ - pCtx->conchHeld = -1; /* read only FS/ lockless */ - rc = SQLITE_OK; - } - } - } - if( rc==SQLITE_OK && lockPath ){ - pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); - } - - if( rc==SQLITE_OK ){ - pCtx->dbPath = sqlite3DbStrDup(0, dbPath); - if( pCtx->dbPath==NULL ){ - rc = SQLITE_NOMEM_BKPT; - } - } - if( rc==SQLITE_OK ){ - /* all memory is allocated, proxys are created and assigned, - ** switch the locking context and pMethod then return. - */ - pCtx->oldLockingContext = pFile->lockingContext; - pFile->lockingContext = pCtx; - pCtx->pOldMethod = pFile->pMethod; - pFile->pMethod = &proxyIoMethods; - }else{ - if( pCtx->conchFile ){ - pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); - sqlite3_free(pCtx->conchFile); - } - sqlite3DbFree(0, pCtx->lockProxyPath); - sqlite3_free(pCtx->conchFilePath); - sqlite3_free(pCtx); - } - OSTRACE(("TRANSPROXY %d %s\n", pFile->h, - (rc==SQLITE_OK ? "ok" : "failed"))); - return rc; -} - - -/* -** This routine handles sqlite3_file_control() calls that are specific -** to proxy locking. -*/ -static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ - switch( op ){ - case SQLITE_FCNTL_GET_LOCKPROXYFILE: { - unixFile *pFile = (unixFile*)id; - if( pFile->pMethod == &proxyIoMethods ){ - proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; - proxyTakeConch(pFile); - if( pCtx->lockProxyPath ){ - *(const char **)pArg = pCtx->lockProxyPath; - }else{ - *(const char **)pArg = ":auto: (not held)"; - } - } else { - *(const char **)pArg = NULL; - } - return SQLITE_OK; - } - case SQLITE_FCNTL_SET_LOCKPROXYFILE: { - unixFile *pFile = (unixFile*)id; - int rc = SQLITE_OK; - int isProxyStyle = (pFile->pMethod == &proxyIoMethods); - if( pArg==NULL || (const char *)pArg==0 ){ - if( isProxyStyle ){ - /* turn off proxy locking - not supported. If support is added for - ** switching proxy locking mode off then it will need to fail if - ** the journal mode is WAL mode. - */ - rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; - }else{ - /* turn off proxy locking - already off - NOOP */ - rc = SQLITE_OK; - } - }else{ - const char *proxyPath = (const char *)pArg; - if( isProxyStyle ){ - proxyLockingContext *pCtx = - (proxyLockingContext*)pFile->lockingContext; - if( !strcmp(pArg, ":auto:") - || (pCtx->lockProxyPath && - !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN)) - ){ - rc = SQLITE_OK; - }else{ - rc = switchLockProxyPath(pFile, proxyPath); - } - }else{ - /* turn on proxy file locking */ - rc = proxyTransformUnixFile(pFile, proxyPath); - } - } - return rc; - } - default: { - assert( 0 ); /* The call assures that only valid opcodes are sent */ - } - } - /*NOTREACHED*/ assert(0); - return SQLITE_ERROR; -} - -/* -** Within this division (the proxying locking implementation) the procedures -** above this point are all utilities. The lock-related methods of the -** proxy-locking sqlite3_io_method object follow. -*/ - - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, set *pResOut -** to a non-zero value otherwise *pResOut is set to zero. The return value -** is set to SQLITE_OK unless an I/O error occurs during lock checking. -*/ -static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { - unixFile *pFile = (unixFile*)id; - int rc = proxyTakeConch(pFile); - if( rc==SQLITE_OK ){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - if( pCtx->conchHeld>0 ){ - unixFile *proxy = pCtx->lockProxy; - return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); - }else{ /* conchHeld < 0 is lockless */ - pResOut=0; - } - } - return rc; -} - -/* -** Lock the file with the lock specified by parameter eFileLock - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** This routine will only increase a lock. Use the sqlite3OsUnlock() -** routine to lower a locking level. -*/ -static int proxyLock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - int rc = proxyTakeConch(pFile); - if( rc==SQLITE_OK ){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - if( pCtx->conchHeld>0 ){ - unixFile *proxy = pCtx->lockProxy; - rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock); - pFile->eFileLock = proxy->eFileLock; - }else{ - /* conchHeld < 0 is lockless */ - } - } - return rc; -} - - -/* -** Lower the locking level on file descriptor pFile to eFileLock. eFileLock -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -*/ -static int proxyUnlock(sqlite3_file *id, int eFileLock) { - unixFile *pFile = (unixFile*)id; - int rc = proxyTakeConch(pFile); - if( rc==SQLITE_OK ){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - if( pCtx->conchHeld>0 ){ - unixFile *proxy = pCtx->lockProxy; - rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock); - pFile->eFileLock = proxy->eFileLock; - }else{ - /* conchHeld < 0 is lockless */ - } - } - return rc; -} - -/* -** Close a file that uses proxy locks. -*/ -static int proxyClose(sqlite3_file *id) { - if( ALWAYS(id) ){ - unixFile *pFile = (unixFile*)id; - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - unixFile *lockProxy = pCtx->lockProxy; - unixFile *conchFile = pCtx->conchFile; - int rc = SQLITE_OK; - - if( lockProxy ){ - rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK); - if( rc ) return rc; - rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy); - if( rc ) return rc; - sqlite3_free(lockProxy); - pCtx->lockProxy = 0; - } - if( conchFile ){ - if( pCtx->conchHeld ){ - rc = proxyReleaseConch(pFile); - if( rc ) return rc; - } - rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile); - if( rc ) return rc; - sqlite3_free(conchFile); - } - sqlite3DbFree(0, pCtx->lockProxyPath); - sqlite3_free(pCtx->conchFilePath); - sqlite3DbFree(0, pCtx->dbPath); - /* restore the original locking context and pMethod then close it */ - pFile->lockingContext = pCtx->oldLockingContext; - pFile->pMethod = pCtx->pOldMethod; - sqlite3_free(pCtx); - return pFile->pMethod->xClose(id); - } - return SQLITE_OK; -} - - - -#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -/* -** The proxy locking style is intended for use with AFP filesystems. -** And since AFP is only supported on MacOSX, the proxy locking is also -** restricted to MacOSX. -** -** -******************* End of the proxy lock implementation ********************** -******************************************************************************/ - -/* -** Initialize the operating system interface. -** -** This routine registers all VFS implementations for unix-like operating -** systems. This routine, and the sqlite3_os_end() routine that follows, -** should be the only routines in this file that are visible from other -** files. -** -** This routine is called once during SQLite initialization and by a -** single thread. The memory allocation and mutex subsystems have not -** necessarily been initialized when this routine is called, and so they -** should not be used. -*/ -SQLITE_API int sqlite3_os_init(void){ - /* - ** The following macro defines an initializer for an sqlite3_vfs object. - ** The name of the VFS is NAME. The pAppData is a pointer to a pointer - ** to the "finder" function. (pAppData is a pointer to a pointer because - ** silly C90 rules prohibit a void* from being cast to a function pointer - ** and so we have to go through the intermediate pointer to avoid problems - ** when compiling with -pedantic-errors on GCC.) - ** - ** The FINDER parameter to this macro is the name of the pointer to the - ** finder-function. The finder-function returns a pointer to the - ** sqlite_io_methods object that implements the desired locking - ** behaviors. See the division above that contains the IOMETHODS - ** macro for addition information on finder-functions. - ** - ** Most finders simply return a pointer to a fixed sqlite3_io_methods - ** object. But the "autolockIoFinder" available on MacOSX does a little - ** more than that; it looks at the filesystem type that hosts the - ** database file and tries to choose an locking method appropriate for - ** that filesystem time. - */ - #define UNIXVFS(VFSNAME, FINDER) { \ - 3, /* iVersion */ \ - sizeof(unixFile), /* szOsFile */ \ - MAX_PATHNAME, /* mxPathname */ \ - 0, /* pNext */ \ - VFSNAME, /* zName */ \ - (void*)&FINDER, /* pAppData */ \ - unixOpen, /* xOpen */ \ - unixDelete, /* xDelete */ \ - unixAccess, /* xAccess */ \ - unixFullPathname, /* xFullPathname */ \ - unixDlOpen, /* xDlOpen */ \ - unixDlError, /* xDlError */ \ - unixDlSym, /* xDlSym */ \ - unixDlClose, /* xDlClose */ \ - unixRandomness, /* xRandomness */ \ - unixSleep, /* xSleep */ \ - unixCurrentTime, /* xCurrentTime */ \ - unixGetLastError, /* xGetLastError */ \ - unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \ - unixSetSystemCall, /* xSetSystemCall */ \ - unixGetSystemCall, /* xGetSystemCall */ \ - unixNextSystemCall, /* xNextSystemCall */ \ - } - - /* - ** All default VFSes for unix are contained in the following array. - ** - ** Note that the sqlite3_vfs.pNext field of the VFS object is modified - ** by the SQLite core when the VFS is registered. So the following - ** array cannot be const. - */ - static sqlite3_vfs aVfs[] = { -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - UNIXVFS("unix", autolockIoFinder ), -#elif OS_VXWORKS - UNIXVFS("unix", vxworksIoFinder ), -#else - UNIXVFS("unix", posixIoFinder ), -#endif - UNIXVFS("unix-none", nolockIoFinder ), - UNIXVFS("unix-dotfile", dotlockIoFinder ), - UNIXVFS("unix-excl", posixIoFinder ), -#if OS_VXWORKS - UNIXVFS("unix-namedsem", semIoFinder ), -#endif -#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS - UNIXVFS("unix-posix", posixIoFinder ), -#endif -#if SQLITE_ENABLE_LOCKING_STYLE - UNIXVFS("unix-flock", flockIoFinder ), -#endif -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - UNIXVFS("unix-afp", afpIoFinder ), - UNIXVFS("unix-nfs", nfsIoFinder ), - UNIXVFS("unix-proxy", proxyIoFinder ), -#endif - }; - unsigned int i; /* Loop counter */ - - /* Double-check that the aSyscall[] array has been constructed - ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==29 ); - - /* Register all VFSes defined in the aVfs[] array */ - for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ -#ifdef SQLITE_DEFAULT_UNIX_VFS - sqlite3_vfs_register(&aVfs[i], - 0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS)); -#else - sqlite3_vfs_register(&aVfs[i], i==0); -#endif - } -#ifdef SQLITE_OS_KV_OPTIONAL - sqlite3KvvfsInit(); -#endif - unixBigLock = 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; -} - -/* -** Shutdown the operating system interface. -** -** Some operating systems might need to do some cleanup in this routine, -** to release dynamically allocated objects. But not on unix. -** This routine is a no-op for unix. -*/ -SQLITE_API int sqlite3_os_end(void){ - unixBigLock = 0; - return SQLITE_OK; -} - -#endif /* SQLITE_OS_UNIX */ - -/************** End of os_unix.c *********************************************/ -/************** Begin file os_win.c ******************************************/ -/* -** 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 code that is specific to Windows. -*/ -/* #include "sqliteInt.h" */ -#if SQLITE_OS_WIN /* This file is used for Windows only */ - -/* -** Include code that is common to all os_*.c files -*/ -/* #include "os_common.h" */ - -/* -** Include the header file for the Windows VFS. -*/ -/* #include "os_win.h" */ - -/* -** Compiling and using WAL mode requires several APIs that are only -** available in Windows platforms based on the NT kernel. -*/ -#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) -# error "WAL mode requires support from the Windows NT kernel, compile\ - with SQLITE_OMIT_WAL." -#endif - -#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 -# error "Memory mapped files require support from the Windows NT kernel,\ - compile with SQLITE_MAX_MMAP_SIZE=0." -#endif - -/* -** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions -** based on the sub-platform)? -*/ -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) -# define SQLITE_WIN32_HAS_ANSI -#endif - -/* -** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions -** based on the sub-platform)? -*/ -#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ - !defined(SQLITE_WIN32_NO_WIDE) -# define SQLITE_WIN32_HAS_WIDE -#endif - -/* -** Make sure at least one set of Win32 APIs is available. -*/ -#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE) -# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\ - must be defined." -#endif - -/* -** Define the required Windows SDK version constants if they are not -** already available. -*/ -#ifndef NTDDI_WIN8 -# define NTDDI_WIN8 0x06020000 -#endif - -#ifndef NTDDI_WINBLUE -# define NTDDI_WINBLUE 0x06030000 -#endif - -#ifndef NTDDI_WINTHRESHOLD -# define NTDDI_WINTHRESHOLD 0x06040000 -#endif - -/* -** Check to see if the GetVersionEx[AW] functions are deprecated on the -** target system. GetVersionEx was first deprecated in Win8.1. -*/ -#ifndef SQLITE_WIN32_GETVERSIONEX -# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE -# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */ -# else -# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ -# endif -#endif - -/* -** Check to see if the CreateFileMappingA function is supported on the -** target system. It is unavailable when using "mincore.lib" on Win10. -** When compiling for Windows 10, always assume "mincore.lib" is in use. -*/ -#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA -# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD -# define SQLITE_WIN32_CREATEFILEMAPPINGA 0 -# else -# define SQLITE_WIN32_CREATEFILEMAPPINGA 1 -# endif -#endif - -/* -** This constant should already be defined (in the "WinDef.h" SDK file). -*/ -#ifndef MAX_PATH -# define MAX_PATH (260) -#endif - -/* -** Maximum pathname length (in chars) for Win32. This should normally be -** MAX_PATH. -*/ -#ifndef SQLITE_WIN32_MAX_PATH_CHARS -# define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH) -#endif - -/* -** This constant should already be defined (in the "WinNT.h" SDK file). -*/ -#ifndef UNICODE_STRING_MAX_CHARS -# define UNICODE_STRING_MAX_CHARS (32767) -#endif - -/* -** Maximum pathname length (in chars) for WinNT. This should normally be -** UNICODE_STRING_MAX_CHARS. -*/ -#ifndef SQLITE_WINNT_MAX_PATH_CHARS -# define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS) -#endif - -/* -** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in -** characters, so we allocate 4 bytes per character assuming worst-case of -** 4-bytes-per-character for UTF8. -*/ -#ifndef SQLITE_WIN32_MAX_PATH_BYTES -# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4) -#endif - -/* -** Maximum pathname length (in bytes) for WinNT. This should normally be -** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR). -*/ -#ifndef SQLITE_WINNT_MAX_PATH_BYTES -# define SQLITE_WINNT_MAX_PATH_BYTES \ - (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS) -#endif - -/* -** Maximum error message length (in chars) for WinRT. -*/ -#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS -# define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024) -#endif - -/* -** Returns non-zero if the character should be treated as a directory -** separator. -*/ -#ifndef winIsDirSep -# define winIsDirSep(a) (((a) == '/') || ((a) == '\\')) -#endif - -/* -** This macro is used when a local variable is set to a value that is -** [sometimes] not used by the code (e.g. via conditional compilation). -*/ -#ifndef UNUSED_VARIABLE_VALUE -# define UNUSED_VARIABLE_VALUE(x) (void)(x) -#endif - -/* -** Returns the character that should be used as the directory separator. -*/ -#ifndef winGetDirSep -# define winGetDirSep() '\\' -#endif - -/* -** Do we need to manually define the Win32 file mapping APIs for use with WAL -** mode or memory mapped files (e.g. these APIs are available in the Windows -** CE SDK; however, they are not present in the header file)? -*/ -#if SQLITE_WIN32_FILEMAPPING_API && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) -/* -** Two of the file mapping APIs are different under WinRT. Figure out which -** set we need. -*/ -#if SQLITE_OS_WINRT -WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ - LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); - -WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); -#else -#if defined(SQLITE_WIN32_HAS_ANSI) -WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ - DWORD, DWORD, DWORD, LPCSTR); -#endif /* defined(SQLITE_WIN32_HAS_ANSI) */ - -#if defined(SQLITE_WIN32_HAS_WIDE) -WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ - DWORD, DWORD, DWORD, LPCWSTR); -#endif /* defined(SQLITE_WIN32_HAS_WIDE) */ - -WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); -#endif /* SQLITE_OS_WINRT */ - -/* -** These file mapping APIs are common to both Win32 and WinRT. -*/ - -WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); -WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); -#endif /* SQLITE_WIN32_FILEMAPPING_API */ - -/* -** Some Microsoft compilers lack this definition. -*/ -#ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -#endif - -#ifndef FILE_FLAG_MASK -# define FILE_FLAG_MASK (0xFF3C0000) -#endif - -#ifndef FILE_ATTRIBUTE_MASK -# define FILE_ATTRIBUTE_MASK (0x0003FFF7) -#endif - -#ifndef SQLITE_OMIT_WAL -/* Forward references to structures used for WAL */ -typedef struct winShm winShm; /* A connection to shared-memory */ -typedef struct winShmNode winShmNode; /* A region of shared-memory */ -#endif - -/* -** WinCE lacks native support for file locking so we have to fake it -** with some code of our own. -*/ -#if SQLITE_OS_WINCE -typedef struct winceLock { - int nReaders; /* Number of reader locks obtained */ - BOOL bPending; /* Indicates a pending lock has been obtained */ - BOOL bReserved; /* Indicates a reserved lock has been obtained */ - BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ -} winceLock; -#endif - -/* -** The winFile structure is a subclass of sqlite3_file* specific to the win32 -** portability layer. -*/ -typedef struct winFile winFile; -struct winFile { - const sqlite3_io_methods *pMethod; /*** Must be first ***/ - sqlite3_vfs *pVfs; /* The VFS used to open this file */ - HANDLE h; /* Handle for accessing the file */ - u8 locktype; /* Type of lock currently held on this file */ - short sharedLockByte; /* Randomly chosen byte used as a shared lock */ - u8 ctrlFlags; /* Flags. See WINFILE_* below */ - DWORD lastErrno; /* The Windows errno from the last I/O error */ -#ifndef SQLITE_OMIT_WAL - winShm *pShm; /* Instance of shared memory on this file */ -#endif - const char *zPath; /* Full pathname of this file */ - int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ -#if SQLITE_OS_WINCE - LPWSTR zDeleteOnClose; /* Name of file to delete when closing */ - HANDLE hMutex; /* Mutex used to control access to shared lock */ - HANDLE hShared; /* Shared memory segment used for locking */ - winceLock local; /* Locks obtained by this instance of winFile */ - winceLock *shared; /* Global shared lock memory for the file */ -#endif -#if SQLITE_MAX_MMAP_SIZE>0 - int nFetchOut; /* Number of outstanding xFetch references */ - HANDLE hMap; /* Handle for accessing memory mapping */ - void *pMapRegion; /* Area memory mapped */ - sqlite3_int64 mmapSize; /* Size of mapped region */ - sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ -#endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - DWORD iBusyTimeout; /* Wait this many millisec on locks */ - int bBlockOnConnect; -#endif -}; - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout -#else -# define winFileBusyTimeout(pDbFd) 0 -#endif - -/* -** The winVfsAppData structure is used for the pAppData member for all of the -** Win32 VFS variants. -*/ -typedef struct winVfsAppData winVfsAppData; -struct winVfsAppData { - const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */ - void *pAppData; /* The extra pAppData, if any. */ - BOOL bNoLock; /* Non-zero if locking is disabled. */ -}; - -/* -** Allowed values for winFile.ctrlFlags -*/ -#define WINFILE_RDONLY 0x02 /* Connection is read only */ -#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ -#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ - -/* - * The size of the buffer used by sqlite3_win32_write_debug(). - */ -#ifndef SQLITE_WIN32_DBG_BUF_SIZE -# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) -#endif - -/* - * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the - * various Win32 API heap functions instead of our own. - */ -#ifdef SQLITE_WIN32_MALLOC - -/* - * If this is non-zero, an isolated heap will be created by the native Win32 - * allocator subsystem; otherwise, the default process heap will be used. This - * setting has no effect when compiling for WinRT. By default, this is enabled - * and an isolated heap will be created to store all allocated data. - * - ****************************************************************************** - * WARNING: It is important to note that when this setting is non-zero and the - * winMemShutdown function is called (e.g. by the sqlite3_shutdown - * function), all data that was allocated using the isolated heap will - * be freed immediately and any attempt to access any of that freed - * data will almost certainly result in an immediate access violation. - ****************************************************************************** - */ -#ifndef SQLITE_WIN32_HEAP_CREATE -# define SQLITE_WIN32_HEAP_CREATE (TRUE) -#endif - -/* - * This is the maximum possible initial size of the Win32-specific heap, in - * bytes. - */ -#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE -# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U) -#endif - -/* - * This is the extra space for the initial size of the Win32-specific heap, - * in bytes. This value may be zero. - */ -#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA -# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304) -#endif - -/* - * Calculate the maximum legal cache size, in pages, based on the maximum - * possible initial heap size and the default page size, setting aside the - * needed extra space. - */ -#ifndef SQLITE_WIN32_MAX_CACHE_SIZE -# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \ - (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \ - (SQLITE_DEFAULT_PAGE_SIZE)) -#endif - -/* - * This is cache size used in the calculation of the initial size of the - * Win32-specific heap. It cannot be negative. - */ -#ifndef SQLITE_WIN32_CACHE_SIZE -# if SQLITE_DEFAULT_CACHE_SIZE>=0 -# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) -# else -# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) -# endif -#endif - -/* - * Make sure that the calculated cache size, in pages, cannot cause the - * initial size of the Win32-specific heap to exceed the maximum amount - * of memory that can be specified in the call to HeapCreate. - */ -#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE -# undef SQLITE_WIN32_CACHE_SIZE -# define SQLITE_WIN32_CACHE_SIZE (2000) -#endif - -/* - * The initial size of the Win32-specific heap. This value may be zero. - */ -#ifndef SQLITE_WIN32_HEAP_INIT_SIZE -# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ - (SQLITE_DEFAULT_PAGE_SIZE) + \ - (SQLITE_WIN32_HEAP_INIT_EXTRA)) -#endif - -/* - * The maximum size of the Win32-specific heap. This value may be zero. - */ -#ifndef SQLITE_WIN32_HEAP_MAX_SIZE -# define SQLITE_WIN32_HEAP_MAX_SIZE (0) -#endif - -/* - * The extra flags to use in calls to the Win32 heap APIs. This value may be - * zero for the default behavior. - */ -#ifndef SQLITE_WIN32_HEAP_FLAGS -# define SQLITE_WIN32_HEAP_FLAGS (0) -#endif - - -/* -** The winMemData structure stores information required by the Win32-specific -** sqlite3_mem_methods implementation. -*/ -typedef struct winMemData winMemData; -struct winMemData { -#ifndef NDEBUG - u32 magic1; /* Magic number to detect structure corruption. */ -#endif - HANDLE hHeap; /* The handle to our heap. */ - BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */ -#ifndef NDEBUG - u32 magic2; /* Magic number to detect structure corruption. */ -#endif -}; - -#ifndef NDEBUG -#define WINMEM_MAGIC1 0x42b2830b -#define WINMEM_MAGIC2 0xbd4d7cf4 -#endif - -static struct winMemData win_mem_data = { -#ifndef NDEBUG - WINMEM_MAGIC1, -#endif - NULL, FALSE -#ifndef NDEBUG - ,WINMEM_MAGIC2 -#endif -}; - -#ifndef NDEBUG -#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 ) -#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 ) -#define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2(); -#else -#define winMemAssertMagic() -#endif - -#define winMemGetDataPtr() &win_mem_data -#define winMemGetHeap() win_mem_data.hHeap -#define winMemGetOwned() win_mem_data.bOwned - -static void *winMemMalloc(int nBytes); -static void winMemFree(void *pPrior); -static void *winMemRealloc(void *pPrior, int nBytes); -static int winMemSize(void *p); -static int winMemRoundup(int n); -static int winMemInit(void *pAppData); -static void winMemShutdown(void *pAppData); - -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void); -#endif /* SQLITE_WIN32_MALLOC */ - -/* -** The following variable is (normally) set once and never changes -** thereafter. It records whether the operating system is Win9x -** or WinNT. -** -** 0: Operating system unknown. -** 1: Operating system is Win9x. -** 2: Operating system is WinNT. -** -** In order to facilitate testing on a WinNT system, the test fixture -** can manually set this value to 1 to emulate Win98 behavior. -*/ -#ifdef SQLITE_TEST -SQLITE_API LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; -#else -static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; -#endif - -#ifndef SYSCALL -# define SYSCALL sqlite3_syscall_ptr -#endif - -/* -** This function is not available on Windows CE or WinRT. - */ - -#if SQLITE_OS_WINCE || SQLITE_OS_WINRT -# define osAreFileApisANSI() 1 -#endif - -/* -** Many system calls are accessed through pointer-to-functions so that -** they may be overridden at runtime to facilitate fault injection during -** testing and sandboxing. The following array holds the names and pointers -** to all overrideable system calls. -*/ -static struct win_syscall { - const char *zName; /* Name of the system call */ - sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ - sqlite3_syscall_ptr pDefault; /* Default value */ -} aSyscall[] = { -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, -#else - { "AreFileApisANSI", (SYSCALL)0, 0 }, -#endif - -#ifndef osAreFileApisANSI -#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent) -#endif - -#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) - { "CharLowerW", (SYSCALL)CharLowerW, 0 }, -#else - { "CharLowerW", (SYSCALL)0, 0 }, -#endif - -#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent) - -#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) - { "CharUpperW", (SYSCALL)CharUpperW, 0 }, -#else - { "CharUpperW", (SYSCALL)0, 0 }, -#endif - -#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent) - - { "CloseHandle", (SYSCALL)CloseHandle, 0 }, - -#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "CreateFileA", (SYSCALL)CreateFileA, 0 }, -#else - { "CreateFileA", (SYSCALL)0, 0 }, -#endif - -#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ - LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "CreateFileW", (SYSCALL)CreateFileW, 0 }, -#else - { "CreateFileW", (SYSCALL)0, 0 }, -#endif - -#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ - LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ - SQLITE_WIN32_CREATEFILEMAPPINGA - { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, -#else - { "CreateFileMappingA", (SYSCALL)0, 0 }, -#endif - -#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ - DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) - -#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) - { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, -#else - { "CreateFileMappingW", (SYSCALL)0, 0 }, -#endif - -#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ - DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, -#else - { "CreateMutexW", (SYSCALL)0, 0 }, -#endif - -#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \ - LPCWSTR))aSyscall[8].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "DeleteFileA", (SYSCALL)DeleteFileA, 0 }, -#else - { "DeleteFileA", (SYSCALL)0, 0 }, -#endif - -#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) - { "DeleteFileW", (SYSCALL)DeleteFileW, 0 }, -#else - { "DeleteFileW", (SYSCALL)0, 0 }, -#endif - -#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent) - -#if SQLITE_OS_WINCE - { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, -#else - { "FileTimeToLocalFileTime", (SYSCALL)0, 0 }, -#endif - -#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \ - LPFILETIME))aSyscall[11].pCurrent) - -#if SQLITE_OS_WINCE - { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, -#else - { "FileTimeToSystemTime", (SYSCALL)0, 0 }, -#endif - -#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \ - LPSYSTEMTIME))aSyscall[12].pCurrent) - - { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, - -#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "FormatMessageA", (SYSCALL)FormatMessageA, 0 }, -#else - { "FormatMessageA", (SYSCALL)0, 0 }, -#endif - -#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \ - DWORD,va_list*))aSyscall[14].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) - { "FormatMessageW", (SYSCALL)FormatMessageW, 0 }, -#else - { "FormatMessageW", (SYSCALL)0, 0 }, -#endif - -#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \ - DWORD,va_list*))aSyscall[15].pCurrent) - -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) - { "FreeLibrary", (SYSCALL)FreeLibrary, 0 }, -#else - { "FreeLibrary", (SYSCALL)0, 0 }, -#endif - -#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent) - - { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 }, - -#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent) - -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) - { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 }, -#else - { "GetDiskFreeSpaceA", (SYSCALL)0, 0 }, -#endif - -#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ - LPDWORD))aSyscall[18].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, -#else - { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, -#endif - -#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \ - LPDWORD))aSyscall[19].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 }, -#else - { "GetFileAttributesA", (SYSCALL)0, 0 }, -#endif - -#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, -#else - { "GetFileAttributesW", (SYSCALL)0, 0 }, -#endif - -#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) - { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 }, -#else - { "GetFileAttributesExW", (SYSCALL)0, 0 }, -#endif - -#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ - LPVOID))aSyscall[22].pCurrent) - -#if !SQLITE_OS_WINRT - { "GetFileSize", (SYSCALL)GetFileSize, 0 }, -#else - { "GetFileSize", (SYSCALL)0, 0 }, -#endif - -#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) - -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) - { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 }, -#else - { "GetFullPathNameA", (SYSCALL)0, 0 }, -#endif - -#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ - LPSTR*))aSyscall[24].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, -#else - { "GetFullPathNameW", (SYSCALL)0, 0 }, -#endif - -#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ - LPWSTR*))aSyscall[25].pCurrent) - -/* -** For GetLastError(), MSDN says: -** -** Minimum supported client: Windows XP [desktop apps | UWP apps] -** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] -*/ - { "GetLastError", (SYSCALL)GetLastError, 0 }, - -#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) - -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) -#if SQLITE_OS_WINCE - /* The GetProcAddressA() routine is only available on Windows CE. */ - { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 }, -#else - /* All other Windows platforms expect GetProcAddress() to take - ** an ANSI string regardless of the _UNICODE setting */ - { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 }, -#endif -#else - { "GetProcAddressA", (SYSCALL)0, 0 }, -#endif - -#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ - LPCSTR))aSyscall[27].pCurrent) - -#if !SQLITE_OS_WINRT - { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, -#else - { "GetSystemInfo", (SYSCALL)0, 0 }, -#endif - -#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) - - { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, - -#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) - -#if !SQLITE_OS_WINCE - { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 }, -#else - { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 }, -#endif - -#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \ - LPFILETIME))aSyscall[30].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "GetTempPathA", (SYSCALL)GetTempPathA, 0 }, -#else - { "GetTempPathA", (SYSCALL)0, 0 }, -#endif - -#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) - { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, -#else - { "GetTempPathW", (SYSCALL)0, 0 }, -#endif - -#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) - -#if !SQLITE_OS_WINRT - { "GetTickCount", (SYSCALL)GetTickCount, 0 }, -#else - { "GetTickCount", (SYSCALL)0, 0 }, -#endif - -#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX - { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, -#else - { "GetVersionExA", (SYSCALL)0, 0 }, -#endif - -#define osGetVersionExA ((BOOL(WINAPI*)( \ - LPOSVERSIONINFOA))aSyscall[34].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - SQLITE_WIN32_GETVERSIONEX - { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, -#else - { "GetVersionExW", (SYSCALL)0, 0 }, -#endif - -#define osGetVersionExW ((BOOL(WINAPI*)( \ - LPOSVERSIONINFOW))aSyscall[35].pCurrent) - - { "HeapAlloc", (SYSCALL)HeapAlloc, 0 }, - -#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ - SIZE_T))aSyscall[36].pCurrent) - -#if !SQLITE_OS_WINRT - { "HeapCreate", (SYSCALL)HeapCreate, 0 }, -#else - { "HeapCreate", (SYSCALL)0, 0 }, -#endif - -#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ - SIZE_T))aSyscall[37].pCurrent) - -#if !SQLITE_OS_WINRT - { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, -#else - { "HeapDestroy", (SYSCALL)0, 0 }, -#endif - -#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent) - - { "HeapFree", (SYSCALL)HeapFree, 0 }, - -#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent) - - { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 }, - -#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \ - SIZE_T))aSyscall[40].pCurrent) - - { "HeapSize", (SYSCALL)HeapSize, 0 }, - -#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ - LPCVOID))aSyscall[41].pCurrent) - -#if !SQLITE_OS_WINRT - { "HeapValidate", (SYSCALL)HeapValidate, 0 }, -#else - { "HeapValidate", (SYSCALL)0, 0 }, -#endif - -#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ - LPCVOID))aSyscall[42].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - { "HeapCompact", (SYSCALL)HeapCompact, 0 }, -#else - { "HeapCompact", (SYSCALL)0, 0 }, -#endif - -#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION) - { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 }, -#else - { "LoadLibraryA", (SYSCALL)0, 0 }, -#endif - -#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent) - -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - !defined(SQLITE_OMIT_LOAD_EXTENSION) - { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, -#else - { "LoadLibraryW", (SYSCALL)0, 0 }, -#endif - -#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent) - -#if !SQLITE_OS_WINRT - { "LocalFree", (SYSCALL)LocalFree, 0 }, -#else - { "LocalFree", (SYSCALL)0, 0 }, -#endif - -#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - { "LockFile", (SYSCALL)LockFile, 0 }, -#else - { "LockFile", (SYSCALL)0, 0 }, -#endif - -#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI) -#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - DWORD))aSyscall[47].pCurrent) -#endif - -#if !SQLITE_OS_WINCE - { "LockFileEx", (SYSCALL)LockFileEx, 0 }, -#else - { "LockFileEx", (SYSCALL)0, 0 }, -#endif - -#ifndef osLockFileEx -#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ - LPOVERLAPPED))aSyscall[48].pCurrent) -#endif - -#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) - { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, -#else - { "MapViewOfFile", (SYSCALL)0, 0 }, -#endif - -#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - SIZE_T))aSyscall[49].pCurrent) - - { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 }, - -#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \ - int))aSyscall[50].pCurrent) - - { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 }, - -#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \ - LARGE_INTEGER*))aSyscall[51].pCurrent) - - { "ReadFile", (SYSCALL)ReadFile, 0 }, - -#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \ - LPOVERLAPPED))aSyscall[52].pCurrent) - - { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 }, - -#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent) - -#if !SQLITE_OS_WINRT - { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, -#else - { "SetFilePointer", (SYSCALL)0, 0 }, -#endif - -#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ - DWORD))aSyscall[54].pCurrent) - -#if !SQLITE_OS_WINRT - { "Sleep", (SYSCALL)Sleep, 0 }, -#else - { "Sleep", (SYSCALL)0, 0 }, -#endif - -#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) - - { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, - -#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \ - LPFILETIME))aSyscall[56].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - { "UnlockFile", (SYSCALL)UnlockFile, 0 }, -#else - { "UnlockFile", (SYSCALL)0, 0 }, -#endif - -#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI) -#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - DWORD))aSyscall[57].pCurrent) -#endif - -#if !SQLITE_OS_WINCE - { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 }, -#else - { "UnlockFileEx", (SYSCALL)0, 0 }, -#endif - -#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - LPOVERLAPPED))aSyscall[58].pCurrent) - -#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 - { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, -#else - { "UnmapViewOfFile", (SYSCALL)0, 0 }, -#endif - -#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent) - - { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, - -#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ - LPCSTR,LPBOOL))aSyscall[60].pCurrent) - - { "WriteFile", (SYSCALL)WriteFile, 0 }, - -#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ - LPOVERLAPPED))aSyscall[61].pCurrent) - -#if SQLITE_OS_WINRT - { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, -#else - { "CreateEventExW", (SYSCALL)0, 0 }, -#endif - -#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ - DWORD,DWORD))aSyscall[62].pCurrent) - -/* -** For WaitForSingleObject(), MSDN says: -** -** Minimum supported client: Windows XP [desktop apps | UWP apps] -** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] -*/ - { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, - -#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ - DWORD))aSyscall[63].pCurrent) - -#if !SQLITE_OS_WINCE - { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, -#else - { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, -#endif - -#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ - BOOL))aSyscall[64].pCurrent) - -#if SQLITE_OS_WINRT - { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, -#else - { "SetFilePointerEx", (SYSCALL)0, 0 }, -#endif - -#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ - PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) - -#if SQLITE_OS_WINRT - { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, -#else - { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, -#endif - -#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ - FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) - -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) - { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, -#else - { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, -#endif - -#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ - SIZE_T))aSyscall[67].pCurrent) - -#if SQLITE_OS_WINRT - { "CreateFile2", (SYSCALL)CreateFile2, 0 }, -#else - { "CreateFile2", (SYSCALL)0, 0 }, -#endif - -#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ - LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) - -#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION) - { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, -#else - { "LoadPackagedLibrary", (SYSCALL)0, 0 }, -#endif - -#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ - DWORD))aSyscall[69].pCurrent) - -#if SQLITE_OS_WINRT - { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, -#else - { "GetTickCount64", (SYSCALL)0, 0 }, -#endif - -#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) - -#if SQLITE_OS_WINRT - { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, -#else - { "GetNativeSystemInfo", (SYSCALL)0, 0 }, -#endif - -#define osGetNativeSystemInfo ((VOID(WINAPI*)( \ - LPSYSTEM_INFO))aSyscall[71].pCurrent) - -#if defined(SQLITE_WIN32_HAS_ANSI) - { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, -#else - { "OutputDebugStringA", (SYSCALL)0, 0 }, -#endif - -#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) - { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, -#else - { "OutputDebugStringW", (SYSCALL)0, 0 }, -#endif - -#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) - - { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, - -#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) - -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) - { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, -#else - { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, -#endif - -#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ - LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) - -/* -** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" -** is really just a macro that uses a compiler intrinsic (e.g. x64). -** So do not try to make this is into a redefinable interface. -*/ -#if defined(InterlockedCompareExchange) - { "InterlockedCompareExchange", (SYSCALL)0, 0 }, - -#define osInterlockedCompareExchange InterlockedCompareExchange -#else - { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, - -#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ - SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) -#endif /* defined(InterlockedCompareExchange) */ - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - { "UuidCreate", (SYSCALL)UuidCreate, 0 }, -#else - { "UuidCreate", (SYSCALL)0, 0 }, -#endif - -#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, -#else - { "UuidCreateSequential", (SYSCALL)0, 0 }, -#endif - -#define osUuidCreateSequential \ - ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) - -#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 - { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, -#else - { "FlushViewOfFile", (SYSCALL)0, 0 }, -#endif - -#define osFlushViewOfFile \ - ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) - -/* -** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() -** to implement blocking locks with timeouts. MSDN says: -** -** Minimum supported client: Windows XP [desktop apps | UWP apps] -** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] -*/ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - { "CreateEvent", (SYSCALL)CreateEvent, 0 }, -#else - { "CreateEvent", (SYSCALL)0, 0 }, -#endif - -#define osCreateEvent ( \ - (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ - aSyscall[80].pCurrent \ -) - -/* -** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo() -** for the case where a timeout expires and a lock request must be -** cancelled. -** -** Minimum supported client: Windows XP [desktop apps | UWP apps] -** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] -*/ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - { "CancelIo", (SYSCALL)CancelIo, 0 }, -#else - { "CancelIo", (SYSCALL)0, 0 }, -#endif - -#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32) - { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 }, -#else - { "GetModuleHandleW", (SYSCALL)0, 0 }, -#endif - -#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent) - -#ifndef _WIN32 - { "getenv", (SYSCALL)getenv, 0 }, -#else - { "getenv", (SYSCALL)0, 0 }, -#endif - -#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent) - -#ifndef _WIN32 - { "getcwd", (SYSCALL)getcwd, 0 }, -#else - { "getcwd", (SYSCALL)0, 0 }, -#endif - -#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent) - -#ifndef _WIN32 - { "readlink", (SYSCALL)readlink, 0 }, -#else - { "readlink", (SYSCALL)0, 0 }, -#endif - -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent) - -#ifndef _WIN32 - { "lstat", (SYSCALL)lstat, 0 }, -#else - { "lstat", (SYSCALL)0, 0 }, -#endif - -#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent) - -#ifndef _WIN32 - { "__errno", (SYSCALL)__errno, 0 }, -#else - { "__errno", (SYSCALL)0, 0 }, -#endif - -#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)()) - -#ifndef _WIN32 - { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 }, -#else - { "cygwin_conv_path", (SYSCALL)0, 0 }, -#endif - -#define osCygwin_conv_path ((size_t(*)(unsigned int, \ - const void *, void *, size_t))aSyscall[88].pCurrent) - -}; /* End of the overrideable system calls */ - -/* -** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "win32" VFSes. Return SQLITE_OK upon successfully updating the -** system call pointer, or SQLITE_NOTFOUND if there is no configurable -** system call named zName. -*/ -static int winSetSystemCall( - sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ - const char *zName, /* Name of system call to override */ - sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */ -){ - unsigned int i; - int rc = SQLITE_NOTFOUND; - - UNUSED_PARAMETER(pNotUsed); - if( zName==0 ){ - /* If no zName is given, restore all system calls to their default - ** settings and return NULL - */ - rc = SQLITE_OK; - for(i=0; i0 ){ - memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); - memcpy(zDbgBuf, zBuf, nMin); - osOutputDebugStringA(zDbgBuf); - }else{ - osOutputDebugStringA(zBuf); - } -#elif defined(SQLITE_WIN32_HAS_WIDE) - memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); - if ( osMultiByteToWideChar( - osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf, - nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){ - return; - } - osOutputDebugStringW((LPCWSTR)zDbgBuf); -#else - if( nMin>0 ){ - memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); - memcpy(zDbgBuf, zBuf, nMin); - fprintf(stderr, "%s", zDbgBuf); - }else{ - fprintf(stderr, "%s", zBuf); - } -#endif -} -#endif /* _WIN32 */ - -/* -** The following routine suspends the current thread for at least ms -** milliseconds. This is equivalent to the Win32 Sleep() interface. -*/ -#if SQLITE_OS_WINRT -static HANDLE sleepObj = NULL; -#endif - -SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ -#if SQLITE_OS_WINRT - if ( sleepObj==NULL ){ - sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, - SYNCHRONIZE); - } - assert( sleepObj!=NULL ); - osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); -#else - osSleep(milliseconds); -#endif -} - -#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ - SQLITE_THREADSAFE>0 -SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ - DWORD rc; - while( (rc = osWaitForSingleObjectEx(hObject, INFINITE, - TRUE))==WAIT_IO_COMPLETION ){} - return rc; -} -#endif - -/* -** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, -** or WinCE. Return false (zero) for Win95, Win98, or WinME. -** -** Here is an interesting observation: Win95, Win98, and WinME lack -** the LockFileEx() API. But we can still statically link against that -** API as long as we don't call it when running Win95/98/ME. A call to -** this routine is used to determine if the host is Win95/98/ME or -** WinNT/2K/XP so that we will know whether or not we can safely call -** the LockFileEx() API. -*/ - -#if !SQLITE_WIN32_GETVERSIONEX -# define osIsNT() (1) -#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) -# define osIsNT() (1) -#elif !defined(SQLITE_WIN32_HAS_WIDE) -# define osIsNT() (0) -#else -# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt()) -#endif - -/* -** This function determines if the machine is running a version of Windows -** based on the NT kernel. -*/ -SQLITE_API int sqlite3_win32_is_nt(void){ -#if SQLITE_OS_WINRT - /* - ** NOTE: The WinRT sub-platform is always assumed to be based on the NT - ** kernel. - */ - return 1; -#elif SQLITE_WIN32_GETVERSIONEX - if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ -#if defined(SQLITE_WIN32_HAS_ANSI) - OSVERSIONINFOA sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - osGetVersionExA(&sInfo); - osInterlockedCompareExchange(&sqlite3_os_type, - (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); -#elif defined(SQLITE_WIN32_HAS_WIDE) - OSVERSIONINFOW sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - osGetVersionExW(&sInfo); - osInterlockedCompareExchange(&sqlite3_os_type, - (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); -#endif - } - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; -#elif SQLITE_TEST - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2 - || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 - ; -#else - /* - ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are - ** deprecated are always assumed to be based on the NT kernel. - */ - return 1; -#endif -} - -#ifdef SQLITE_WIN32_MALLOC -/* -** Allocate nBytes of memory. -*/ -static void *winMemMalloc(int nBytes){ - HANDLE hHeap; - void *p; - - winMemAssertMagic(); - hHeap = winMemGetHeap(); - assert( hHeap!=0 ); - assert( hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); -#endif - assert( nBytes>=0 ); - p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); - if( !p ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p", - nBytes, osGetLastError(), (void*)hHeap); - } - return p; -} - -/* -** Free memory. -*/ -static void winMemFree(void *pPrior){ - HANDLE hHeap; - - winMemAssertMagic(); - hHeap = winMemGetHeap(); - assert( hHeap!=0 ); - assert( hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); -#endif - if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ - if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p", - pPrior, osGetLastError(), (void*)hHeap); - } -} - -/* -** Change the size of an existing memory allocation -*/ -static void *winMemRealloc(void *pPrior, int nBytes){ - HANDLE hHeap; - void *p; - - winMemAssertMagic(); - hHeap = winMemGetHeap(); - assert( hHeap!=0 ); - assert( hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); -#endif - assert( nBytes>=0 ); - if( !pPrior ){ - p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); - }else{ - p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes); - } - if( !p ){ - sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p", - pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(), - (void*)hHeap); - } - return p; -} - -/* -** Return the size of an outstanding allocation, in bytes. -*/ -static int winMemSize(void *p){ - HANDLE hHeap; - SIZE_T n; - - winMemAssertMagic(); - hHeap = winMemGetHeap(); - assert( hHeap!=0 ); - assert( hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) ); -#endif - if( !p ) return 0; - n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p); - if( n==(SIZE_T)-1 ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p", - p, osGetLastError(), (void*)hHeap); - return 0; - } - return (int)n; -} - -/* -** Round up a request size to the next valid allocation size. -*/ -static int winMemRoundup(int n){ - return n; -} - -/* -** Initialize this module. -*/ -static int winMemInit(void *pAppData){ - winMemData *pWinMemData = (winMemData *)pAppData; - - if( !pWinMemData ) return SQLITE_ERROR; - assert( pWinMemData->magic1==WINMEM_MAGIC1 ); - assert( pWinMemData->magic2==WINMEM_MAGIC2 ); - -#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE - if( !pWinMemData->hHeap ){ - DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE; - DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap; - if( dwMaximumSize==0 ){ - dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE; - }else if( dwInitialSize>dwMaximumSize ){ - dwInitialSize = dwMaximumSize; - } - pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS, - dwInitialSize, dwMaximumSize); - if( !pWinMemData->hHeap ){ - sqlite3_log(SQLITE_NOMEM, - "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu", - osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize, - dwMaximumSize); - return SQLITE_NOMEM_BKPT; - } - pWinMemData->bOwned = TRUE; - assert( pWinMemData->bOwned ); - } -#else - pWinMemData->hHeap = osGetProcessHeap(); - if( !pWinMemData->hHeap ){ - sqlite3_log(SQLITE_NOMEM, - "failed to GetProcessHeap (%lu)", osGetLastError()); - return SQLITE_NOMEM_BKPT; - } - pWinMemData->bOwned = FALSE; - assert( !pWinMemData->bOwned ); -#endif - assert( pWinMemData->hHeap!=0 ); - assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); -#endif - return SQLITE_OK; -} - -/* -** Deinitialize this module. -*/ -static void winMemShutdown(void *pAppData){ - winMemData *pWinMemData = (winMemData *)pAppData; - - if( !pWinMemData ) return; - assert( pWinMemData->magic1==WINMEM_MAGIC1 ); - assert( pWinMemData->magic2==WINMEM_MAGIC2 ); - - if( pWinMemData->hHeap ){ - assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) - assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); -#endif - if( pWinMemData->bOwned ){ - if( !osHeapDestroy(pWinMemData->hHeap) ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p", - osGetLastError(), (void*)pWinMemData->hHeap); - } - pWinMemData->bOwned = FALSE; - } - pWinMemData->hHeap = NULL; - } -} - -/* -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. The -** arguments specify the block of memory to manage. -** -** This routine is only called by sqlite3_config(), and therefore -** is not required to be threadsafe (it is not). -*/ -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){ - static const sqlite3_mem_methods winMemMethods = { - winMemMalloc, - winMemFree, - winMemRealloc, - winMemSize, - winMemRoundup, - winMemInit, - winMemShutdown, - &win_mem_data - }; - return &winMemMethods; -} - -SQLITE_PRIVATE void sqlite3MemSetDefault(void){ - sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); -} -#endif /* SQLITE_WIN32_MALLOC */ - -#ifdef _WIN32 -/* -** Convert a UTF-8 string to Microsoft Unicode. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static LPWSTR winUtf8ToUnicode(const char *zText){ - int nChar; - LPWSTR zWideText; - - nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0); - if( nChar==0 ){ - return 0; - } - zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) ); - if( zWideText==0 ){ - return 0; - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, - nChar); - if( nChar==0 ){ - sqlite3_free(zWideText); - zWideText = 0; - } - return zWideText; -} -#endif /* _WIN32 */ - -/* -** Convert a Microsoft Unicode string to UTF-8. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static char *winUnicodeToUtf8(LPCWSTR zWideText){ - int nByte; - char *zText; - - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0); - if( nByte == 0 ){ - return 0; - } - zText = sqlite3MallocZero( nByte ); - if( zText==0 ){ - return 0; - } - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, - 0, 0); - if( nByte == 0 ){ - sqlite3_free(zText); - zText = 0; - } - return zText; -} - -/* -** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM -** code page. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ - int nWideChar; - LPWSTR zMbcsText; - int codepage = useAnsi ? CP_ACP : CP_OEMCP; - - nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, - 0); - if( nWideChar==0 ){ - return 0; - } - zMbcsText = sqlite3MallocZero( nWideChar*sizeof(WCHAR) ); - if( zMbcsText==0 ){ - return 0; - } - nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, - nWideChar); - if( nWideChar==0 ){ - sqlite3_free(zMbcsText); - zMbcsText = 0; - } - return zMbcsText; -} - -#ifdef _WIN32 -/* -** Convert a Microsoft Unicode string to a multi-byte character string, -** using the ANSI or OEM code page. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ - int nByte; - char *zText; - int codepage = useAnsi ? CP_ACP : CP_OEMCP; - - nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0); - if( nByte == 0 ){ - return 0; - } - zText = sqlite3MallocZero( nByte ); - if( zText==0 ){ - return 0; - } - nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText, - nByte, 0, 0); - if( nByte == 0 ){ - sqlite3_free(zText); - zText = 0; - } - return zText; -} -#endif /* _WIN32 */ - -/* -** Convert a multi-byte character string to UTF-8. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static char *winMbcsToUtf8(const char *zText, int useAnsi){ - char *zTextUtf8; - LPWSTR zTmpWide; - - zTmpWide = winMbcsToUnicode(zText, useAnsi); - if( zTmpWide==0 ){ - return 0; - } - zTextUtf8 = winUnicodeToUtf8(zTmpWide); - sqlite3_free(zTmpWide); - return zTextUtf8; -} - -#ifdef _WIN32 -/* -** Convert a UTF-8 string to a multi-byte character string. -** -** Space to hold the returned string is obtained from sqlite3_malloc(). -*/ -static char *winUtf8ToMbcs(const char *zText, int useAnsi){ - char *zTextMbcs; - LPWSTR zTmpWide; - - zTmpWide = winUtf8ToUnicode(zText); - if( zTmpWide==0 ){ - return 0; - } - zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi); - sqlite3_free(zTmpWide); - return zTextMbcs; -} - -/* -** This is a public wrapper for the winUtf8ToUnicode() function. -*/ -SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winUtf8ToUnicode(zText); -} - -/* -** This is a public wrapper for the winUnicodeToUtf8() function. -*/ -SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zWideText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winUnicodeToUtf8(zWideText); -} -#endif /* _WIN32 */ - -/* -** This is a public wrapper for the winMbcsToUtf8() function. -*/ -SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winMbcsToUtf8(zText, osAreFileApisANSI()); -} - -#ifdef _WIN32 -/* -** This is a public wrapper for the winMbcsToUtf8() function. -*/ -SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winMbcsToUtf8(zText, useAnsi); -} - -/* -** This is a public wrapper for the winUtf8ToMbcs() function. -*/ -SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zText){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winUtf8ToMbcs(zText, osAreFileApisANSI()); -} - -/* -** This is a public wrapper for the winUtf8ToMbcs() function. -*/ -SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zText ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return winUtf8ToMbcs(zText, useAnsi); -} - -/* -** This function is the same as sqlite3_win32_set_directory (below); however, -** it accepts a UTF-8 string. -*/ -SQLITE_API int sqlite3_win32_set_directory8( - unsigned long type, /* Identifier for directory being set or reset */ - const char *zValue /* New value for directory being set or reset */ -){ - char **ppDirectory = 0; - int rc; -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ - ppDirectory = &sqlite3_data_directory; - }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ - ppDirectory = &sqlite3_temp_directory; - } - assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE - || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE - ); - assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); - if( ppDirectory ){ - char *zCopy = 0; - if( zValue && zValue[0] ){ - zCopy = sqlite3_mprintf("%s", zValue); - if ( zCopy==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto set_directory8_done; - } - } - sqlite3_free(*ppDirectory); - *ppDirectory = zCopy; - rc = SQLITE_OK; - }else{ - rc = SQLITE_ERROR; - } -set_directory8_done: - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - return rc; -} - -/* -** This function is the same as sqlite3_win32_set_directory (below); however, -** it accepts a UTF-16 string. -*/ -SQLITE_API int sqlite3_win32_set_directory16( - unsigned long type, /* Identifier for directory being set or reset */ - const void *zValue /* New value for directory being set or reset */ -){ - int rc; - char *zUtf8 = 0; - if( zValue ){ - zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); - if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; - } - rc = sqlite3_win32_set_directory8(type, zUtf8); - if( zUtf8 ) sqlite3_free(zUtf8); - return rc; -} - -/* -** This function sets the data directory or the temporary directory based on -** the provided arguments. The type argument must be 1 in order to set the -** data directory or 2 in order to set the temporary directory. The zValue -** argument is the name of the directory to use. The return value will be -** SQLITE_OK if successful. -*/ -SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ -){ - return sqlite3_win32_set_directory16(type, zValue); -} -#endif /* _WIN32 */ - -/* -** The return value of winGetLastErrorMsg -** is zero if the error message fits in the buffer, or non-zero -** otherwise (if the message was truncated). -*/ -static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ - /* FormatMessage returns 0 on failure. Otherwise it - ** returns the number of TCHARs written to the output - ** buffer, excluding the terminating null char. - */ - DWORD dwLen = 0; - char *zOut = 0; - - if( osIsNT() ){ -#if SQLITE_OS_WINRT - WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1]; - dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - lastErrno, - 0, - zTempWide, - SQLITE_WIN32_MAX_ERRMSG_CHARS, - 0); -#else - LPWSTR zTempWide = NULL; - dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - lastErrno, - 0, - (LPWSTR) &zTempWide, - 0, - 0); -#endif - if( dwLen > 0 ){ - /* allocate a buffer and convert to UTF8 */ - sqlite3BeginBenignMalloc(); - zOut = winUnicodeToUtf8(zTempWide); - sqlite3EndBenignMalloc(); -#if !SQLITE_OS_WINRT - /* free the system buffer allocated by FormatMessage */ - osLocalFree(zTempWide); -#endif - } - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - char *zTemp = NULL; - dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - lastErrno, - 0, - (LPSTR) &zTemp, - 0, - 0); - if( dwLen > 0 ){ - /* allocate a buffer and convert to UTF8 */ - sqlite3BeginBenignMalloc(); - zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); - sqlite3EndBenignMalloc(); - /* free the system buffer allocated by FormatMessage */ - osLocalFree(zTemp); - } - } -#endif - if( 0 == dwLen ){ - sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno); - }else{ - /* copy a maximum of nBuf chars to output buffer */ - sqlite3_snprintf(nBuf, zBuf, "%s", zOut); - /* free the UTF8 buffer */ - sqlite3_free(zOut); - } - return 0; -} - -/* -** -** This function - winLogErrorAtLine() - is only ever called via the macro -** winLogError(). -** -** This routine is invoked after an error occurs in an OS function. -** It logs a message using sqlite3_log() containing the current value of -** error code and, if possible, the human-readable equivalent from -** FormatMessage. -** -** The first argument passed to the macro should be the error code that -** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). -** The two subsequent arguments should be the name of the OS function that -** failed and the associated file-system path, if any. -*/ -#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__) -static int winLogErrorAtLine( - int errcode, /* SQLite error code */ - DWORD lastErrno, /* Win32 last error */ - const char *zFunc, /* Name of OS function that failed */ - const char *zPath, /* File path associated with error */ - int iLine /* Source line number where error occurred */ -){ - char zMsg[500]; /* Human readable error text */ - int i; /* Loop counter */ - - zMsg[0] = 0; - winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg); - assert( errcode!=SQLITE_OK ); - if( zPath==0 ) zPath = ""; - for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} - zMsg[i] = 0; - sqlite3_log(errcode, - "os_win.c:%d: (%lu) %s(%s) - %s", - iLine, lastErrno, zFunc, zPath, zMsg - ); - - return errcode; -} - -/* -** The number of times that a ReadFile(), WriteFile(), and DeleteFile() -** will be retried following a locking error - probably caused by -** antivirus software. Also the initial delay before the first retry. -** The delay increases linearly with each retry. -*/ -#ifndef SQLITE_WIN32_IOERR_RETRY -# define SQLITE_WIN32_IOERR_RETRY 10 -#endif -#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY -# define SQLITE_WIN32_IOERR_RETRY_DELAY 25 -#endif -static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY; -static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY; - -/* -** The "winIoerrCanRetry1" macro is used to determine if a particular I/O -** error code obtained via GetLastError() is eligible to be retried. It -** must accept the error code DWORD as its only argument and should return -** non-zero if the error code is transient in nature and the operation -** responsible for generating the original error might succeed upon being -** retried. The argument to this macro should be a variable. -** -** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it -** is defined, it will be consulted only when the macro "winIoerrCanRetry1" -** returns zero. The "winIoerrCanRetry2" macro is completely optional and -** may be used to include additional error codes in the set that should -** result in the failing I/O operation being retried by the caller. If -** defined, the "winIoerrCanRetry2" macro must exhibit external semantics -** identical to those of the "winIoerrCanRetry1" macro. -*/ -#if !defined(winIoerrCanRetry1) -#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \ - ((a)==ERROR_SHARING_VIOLATION) || \ - ((a)==ERROR_LOCK_VIOLATION) || \ - ((a)==ERROR_DEV_NOT_EXIST) || \ - ((a)==ERROR_NETNAME_DELETED) || \ - ((a)==ERROR_SEM_TIMEOUT) || \ - ((a)==ERROR_NETWORK_UNREACHABLE)) -#endif - -/* -** If a ReadFile() or WriteFile() error occurs, invoke this routine -** to see if it should be retried. Return TRUE to retry. Return FALSE -** to give up with an error. -*/ -static int winRetryIoerr(int *pnRetry, DWORD *pError){ - DWORD e = osGetLastError(); - if( *pnRetry>=winIoerrRetry ){ - if( pError ){ - *pError = e; - } - return 0; - } - if( winIoerrCanRetry1(e) ){ - sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); - ++*pnRetry; - return 1; - } -#if defined(winIoerrCanRetry2) - else if( winIoerrCanRetry2(e) ){ - sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); - ++*pnRetry; - return 1; - } -#endif - if( pError ){ - *pError = e; - } - return 0; -} - -/* -** Log a I/O error retry episode. -*/ -static void winLogIoerr(int nRetry, int lineno){ - if( nRetry ){ - sqlite3_log(SQLITE_NOTICE, - "delayed %dms for lock/sharing conflict at line %d", - winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno - ); - } -} - -/* -** This #if does not rely on the SQLITE_OS_WINCE define because the -** corresponding section in "date.c" cannot use it. -*/ -#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \ - (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API) -/* -** The MSVC CRT on Windows CE may not have a localtime() function. -** So define a substitute. -*/ -/* # include */ -struct tm *__cdecl localtime(const time_t *t) -{ - static struct tm y; - FILETIME uTm, lTm; - SYSTEMTIME pTm; - sqlite3_int64 t64; - t64 = *t; - t64 = (t64 + 11644473600)*10000000; - uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); - uTm.dwHighDateTime= (DWORD)(t64 >> 32); - osFileTimeToLocalFileTime(&uTm,&lTm); - osFileTimeToSystemTime(&lTm,&pTm); - y.tm_year = pTm.wYear - 1900; - y.tm_mon = pTm.wMonth - 1; - y.tm_wday = pTm.wDayOfWeek; - y.tm_mday = pTm.wDay; - y.tm_hour = pTm.wHour; - y.tm_min = pTm.wMinute; - y.tm_sec = pTm.wSecond; - return &y; -} -#endif - -#if SQLITE_OS_WINCE -/************************************************************************* -** This section contains code for WinCE only. -*/ -#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] - -/* -** Acquire a lock on the handle h -*/ -static void winceMutexAcquire(HANDLE h){ - DWORD dwErr; - do { - dwErr = osWaitForSingleObject(h, INFINITE); - } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); -} -/* -** Release a lock acquired by winceMutexAcquire() -*/ -#define winceMutexRelease(h) ReleaseMutex(h) - -/* -** Create the mutex and shared memory used for locking in the file -** descriptor pFile -*/ -static int winceCreateLock(const char *zFilename, winFile *pFile){ - LPWSTR zTok; - LPWSTR zName; - DWORD lastErrno; - BOOL bLogged = FALSE; - BOOL bInit = TRUE; - - zName = winUtf8ToUnicode(zFilename); - if( zName==0 ){ - /* out of memory */ - return SQLITE_IOERR_NOMEM_BKPT; - } - - /* Initialize the local lockdata */ - memset(&pFile->local, 0, sizeof(pFile->local)); - - /* Replace the backslashes from the filename and lowercase it - ** to derive a mutex name. */ - zTok = osCharLowerW(zName); - for (;*zTok;zTok++){ - if (*zTok == '\\') *zTok = '_'; - } - - /* Create/open the named mutex */ - pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); - if (!pFile->hMutex){ - pFile->lastErrno = osGetLastError(); - sqlite3_free(zName); - return winLogError(SQLITE_IOERR, pFile->lastErrno, - "winceCreateLock1", zFilename); - } - - /* Acquire the mutex before continuing */ - winceMutexAcquire(pFile->hMutex); - - /* Since the names of named mutexes, semaphores, file mappings etc are - ** case-sensitive, take advantage of that by uppercasing the mutex name - ** and using that as the shared filemapping name. - */ - osCharUpperW(zName); - pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, - PAGE_READWRITE, 0, sizeof(winceLock), - zName); - - /* Set a flag that indicates we're the first to create the memory so it - ** must be zero-initialized */ - lastErrno = osGetLastError(); - if (lastErrno == ERROR_ALREADY_EXISTS){ - bInit = FALSE; - } - - sqlite3_free(zName); - - /* If we succeeded in making the shared memory handle, map it. */ - if( pFile->hShared ){ - pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, - FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); - /* If mapping failed, close the shared memory handle and erase it */ - if( !pFile->shared ){ - pFile->lastErrno = osGetLastError(); - winLogError(SQLITE_IOERR, pFile->lastErrno, - "winceCreateLock2", zFilename); - bLogged = TRUE; - osCloseHandle(pFile->hShared); - pFile->hShared = NULL; - } - } - - /* If shared memory could not be created, then close the mutex and fail */ - if( pFile->hShared==NULL ){ - if( !bLogged ){ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_IOERR, pFile->lastErrno, - "winceCreateLock3", zFilename); - bLogged = TRUE; - } - winceMutexRelease(pFile->hMutex); - osCloseHandle(pFile->hMutex); - pFile->hMutex = NULL; - return SQLITE_IOERR; - } - - /* Initialize the shared memory if we're supposed to */ - if( bInit ){ - memset(pFile->shared, 0, sizeof(winceLock)); - } - - winceMutexRelease(pFile->hMutex); - return SQLITE_OK; -} - -/* -** Destroy the part of winFile that deals with wince locks -*/ -static void winceDestroyLock(winFile *pFile){ - if (pFile->hMutex){ - /* Acquire the mutex */ - winceMutexAcquire(pFile->hMutex); - - /* The following blocks should probably assert in debug mode, but they - are to cleanup in case any locks remained open */ - if (pFile->local.nReaders){ - pFile->shared->nReaders --; - } - if (pFile->local.bReserved){ - pFile->shared->bReserved = FALSE; - } - if (pFile->local.bPending){ - pFile->shared->bPending = FALSE; - } - if (pFile->local.bExclusive){ - pFile->shared->bExclusive = FALSE; - } - - /* De-reference and close our copy of the shared memory handle */ - osUnmapViewOfFile(pFile->shared); - osCloseHandle(pFile->hShared); - - /* Done with the mutex */ - winceMutexRelease(pFile->hMutex); - osCloseHandle(pFile->hMutex); - pFile->hMutex = NULL; - } -} - -/* -** An implementation of the LockFile() API of Windows for CE -*/ -static BOOL winceLockFile( - LPHANDLE phFile, - DWORD dwFileOffsetLow, - DWORD dwFileOffsetHigh, - DWORD nNumberOfBytesToLockLow, - DWORD nNumberOfBytesToLockHigh -){ - winFile *pFile = HANDLE_TO_WINFILE(phFile); - BOOL bReturn = FALSE; - - UNUSED_PARAMETER(dwFileOffsetHigh); - UNUSED_PARAMETER(nNumberOfBytesToLockHigh); - - if (!pFile->hMutex) return TRUE; - winceMutexAcquire(pFile->hMutex); - - /* Wanting an exclusive lock? */ - if (dwFileOffsetLow == (DWORD)SHARED_FIRST - && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ - if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ - pFile->shared->bExclusive = TRUE; - pFile->local.bExclusive = TRUE; - bReturn = TRUE; - } - } - - /* Want a read-only lock? */ - else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && - nNumberOfBytesToLockLow == 1){ - if (pFile->shared->bExclusive == 0){ - pFile->local.nReaders ++; - if (pFile->local.nReaders == 1){ - pFile->shared->nReaders ++; - } - bReturn = TRUE; - } - } - - /* Want a pending lock? */ - else if (dwFileOffsetLow == (DWORD)PENDING_BYTE - && nNumberOfBytesToLockLow == 1){ - /* If no pending lock has been acquired, then acquire it */ - if (pFile->shared->bPending == 0) { - pFile->shared->bPending = TRUE; - pFile->local.bPending = TRUE; - bReturn = TRUE; - } - } - - /* Want a reserved lock? */ - else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE - && nNumberOfBytesToLockLow == 1){ - if (pFile->shared->bReserved == 0) { - pFile->shared->bReserved = TRUE; - pFile->local.bReserved = TRUE; - bReturn = TRUE; - } - } - - winceMutexRelease(pFile->hMutex); - return bReturn; -} - -/* -** An implementation of the UnlockFile API of Windows for CE -*/ -static BOOL winceUnlockFile( - LPHANDLE phFile, - DWORD dwFileOffsetLow, - DWORD dwFileOffsetHigh, - DWORD nNumberOfBytesToUnlockLow, - DWORD nNumberOfBytesToUnlockHigh -){ - winFile *pFile = HANDLE_TO_WINFILE(phFile); - BOOL bReturn = FALSE; - - UNUSED_PARAMETER(dwFileOffsetHigh); - UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); - - if (!pFile->hMutex) return TRUE; - winceMutexAcquire(pFile->hMutex); - - /* Releasing a reader lock or an exclusive lock */ - if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ - /* Did we have an exclusive lock? */ - if (pFile->local.bExclusive){ - assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); - pFile->local.bExclusive = FALSE; - pFile->shared->bExclusive = FALSE; - bReturn = TRUE; - } - - /* Did we just have a reader lock? */ - else if (pFile->local.nReaders){ - assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE - || nNumberOfBytesToUnlockLow == 1); - pFile->local.nReaders --; - if (pFile->local.nReaders == 0) - { - pFile->shared->nReaders --; - } - bReturn = TRUE; - } - } - - /* Releasing a pending lock */ - else if (dwFileOffsetLow == (DWORD)PENDING_BYTE - && nNumberOfBytesToUnlockLow == 1){ - if (pFile->local.bPending){ - pFile->local.bPending = FALSE; - pFile->shared->bPending = FALSE; - bReturn = TRUE; - } - } - /* Releasing a reserved lock */ - else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE - && nNumberOfBytesToUnlockLow == 1){ - if (pFile->local.bReserved) { - pFile->local.bReserved = FALSE; - pFile->shared->bReserved = FALSE; - bReturn = TRUE; - } - } - - winceMutexRelease(pFile->hMutex); - return bReturn; -} -/* -** End of the special code for wince -*****************************************************************************/ -#endif /* SQLITE_OS_WINCE */ - -/* -** Lock a file region. -*/ -static BOOL winLockFile( - LPHANDLE phFile, - DWORD flags, - DWORD offsetLow, - DWORD offsetHigh, - DWORD numBytesLow, - DWORD numBytesHigh -){ -#if SQLITE_OS_WINCE - /* - ** NOTE: Windows CE is handled differently here due its lack of the Win32 - ** API LockFile. - */ - return winceLockFile(phFile, offsetLow, offsetHigh, - numBytesLow, numBytesHigh); -#else - if( osIsNT() ){ - OVERLAPPED ovlp; - memset(&ovlp, 0, sizeof(OVERLAPPED)); - ovlp.Offset = offsetLow; - ovlp.OffsetHigh = offsetHigh; - return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp); -#ifdef SQLITE_WIN32_HAS_ANSI - }else{ - return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, - numBytesHigh); -#endif - } -#endif -} - -/* -** Lock a region of nByte bytes starting at offset offset of file hFile. -** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock -** otherwise. If nMs is greater than zero and the lock cannot be obtained -** immediately, block for that many ms before giving up. -** -** This function returns SQLITE_OK if the lock is obtained successfully. If -** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or -** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR. -*/ -static int winHandleLockTimeout( - HANDLE hFile, - DWORD offset, - DWORD nByte, - int bExcl, - DWORD nMs -){ - DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0); - int rc = SQLITE_OK; - BOOL ret; - - if( !osIsNT() ){ - ret = winLockFile(&hFile, flags, offset, 0, nByte, 0); - }else{ - OVERLAPPED ovlp; - memset(&ovlp, 0, sizeof(OVERLAPPED)); - ovlp.Offset = offset; - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( nMs!=0 ){ - flags &= ~LOCKFILE_FAIL_IMMEDIATELY; - } - ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL); - if( ovlp.hEvent==NULL ){ - return SQLITE_IOERR_LOCK; - } -#endif - - ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp); - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was - ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to - ** LockFileEx() may fail because the request is still pending. This can - ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified. - ** - ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags - ** passed to LockFileEx(). In this case, if the operation is pending, - ** block indefinitely until it is finished. - ** - ** Otherwise, wait for up to nMs ms for the operation to finish. nMs - ** may be set to INFINITE. - */ - if( !ret && GetLastError()==ERROR_IO_PENDING ){ - DWORD nDelay = (nMs==0 ? INFINITE : nMs); - DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay); - if( res==WAIT_OBJECT_0 ){ - ret = TRUE; - }else if( res==WAIT_TIMEOUT ){ -#if SQLITE_ENABLE_SETLK_TIMEOUT==1 - rc = SQLITE_BUSY_TIMEOUT; -#else - rc = SQLITE_BUSY; -#endif - }else{ - /* Some other error has occurred */ - rc = SQLITE_IOERR_LOCK; - } - - /* If it is still pending, cancel the LockFileEx() call. */ - osCancelIo(hFile); - } - - osCloseHandle(ovlp.hEvent); -#endif - } - - if( rc==SQLITE_OK && !ret ){ - rc = SQLITE_BUSY; - } - return rc; -} - -/* -** Unlock a file region. - */ -static BOOL winUnlockFile( - LPHANDLE phFile, - DWORD offsetLow, - DWORD offsetHigh, - DWORD numBytesLow, - DWORD numBytesHigh -){ -#if SQLITE_OS_WINCE - /* - ** NOTE: Windows CE is handled differently here due its lack of the Win32 - ** API UnlockFile. - */ - return winceUnlockFile(phFile, offsetLow, offsetHigh, - numBytesLow, numBytesHigh); -#else - if( osIsNT() ){ - OVERLAPPED ovlp; - memset(&ovlp, 0, sizeof(OVERLAPPED)); - ovlp.Offset = offsetLow; - ovlp.OffsetHigh = offsetHigh; - return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp); -#ifdef SQLITE_WIN32_HAS_ANSI - }else{ - return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, - numBytesHigh); -#endif - } -#endif -} - -/* -** Remove an nByte lock starting at offset iOff from HANDLE h. -*/ -static int winHandleUnlock(HANDLE h, int iOff, int nByte){ - BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0); - return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK); -} - -/***************************************************************************** -** The next group of routines implement the I/O methods specified -** by the sqlite3_io_methods object. -******************************************************************************/ - -/* -** Some Microsoft compilers lack this definition. -*/ -#ifndef INVALID_SET_FILE_POINTER -# define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - -/* -** Seek the file handle h to offset nByte of the file. -** -** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite -** error code. -*/ -static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ - int rc = SQLITE_OK; /* Return value */ - -#if !SQLITE_OS_WINRT - LONG upperBits; /* Most sig. 32 bits of new offset */ - LONG lowerBits; /* Least sig. 32 bits of new offset */ - DWORD dwRet; /* Value returned by SetFilePointer() */ - - upperBits = (LONG)((iOffset>>32) & 0x7fffffff); - lowerBits = (LONG)(iOffset & 0xffffffff); - - dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN); - - /* API oddity: If successful, SetFilePointer() returns a dword - ** containing the lower 32-bits of the new file-offset. Or, if it fails, - ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, - ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine - ** whether an error has actually occurred, it is also necessary to call - ** GetLastError(). */ - if( dwRet==INVALID_SET_FILE_POINTER ){ - DWORD lastErrno = osGetLastError(); - if( lastErrno!=NO_ERROR ){ - rc = SQLITE_IOERR_SEEK; - } - } -#else - /* This implementation works for WinRT. */ - LARGE_INTEGER x; /* The new offset */ - BOOL bRet; /* Value returned by SetFilePointerEx() */ - - x.QuadPart = iOffset; - bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN); - - if(!bRet){ - rc = SQLITE_IOERR_SEEK; - } -#endif - - OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc))); - return rc; -} - -/* -** Move the current position of the file handle passed as the first -** argument to offset iOffset within the file. If successful, return 0. -** Otherwise, set pFile->lastErrno and return non-zero. -*/ -static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ - int rc; - - rc = winHandleSeek(pFile->h, iOffset); - if( rc!=SQLITE_OK ){ - pFile->lastErrno = osGetLastError(); - winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath); - } - return rc; -} - - -#if SQLITE_MAX_MMAP_SIZE>0 -/* Forward references to VFS helper methods used for memory mapped files */ -static int winMapfile(winFile*, sqlite3_int64); -static int winUnmapfile(winFile*); -#endif - -/* -** Close a file. -** -** It is reported that an attempt to close a handle might sometimes -** fail. This is a very unreasonable result, but Windows is notorious -** for being unreasonable so I do not doubt that it might happen. If -** the close fails, we pause for 100 milliseconds and try again. As -** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before -** giving up and returning an error. -*/ -#define MX_CLOSE_ATTEMPT 3 -static int winClose(sqlite3_file *id){ - int rc, cnt = 0; - winFile *pFile = (winFile*)id; - - assert( id!=0 ); -#ifndef SQLITE_OMIT_WAL - assert( pFile->pShm==0 ); -#endif - assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); - OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", - osGetCurrentProcessId(), pFile, pFile->h)); - -#if SQLITE_MAX_MMAP_SIZE>0 - winUnmapfile(pFile); -#endif - - do{ - rc = osCloseHandle(pFile->h); - /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ - }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); -#if SQLITE_OS_WINCE -#define WINCE_DELETION_ATTEMPTS 3 - { - winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData; - if( pAppData==NULL || !pAppData->bNoLock ){ - winceDestroyLock(pFile); - } - } - if( pFile->zDeleteOnClose ){ - int cnt = 0; - while( - osDeleteFileW(pFile->zDeleteOnClose)==0 - && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff - && cnt++ < WINCE_DELETION_ATTEMPTS - ){ - sqlite3_win32_sleep(100); /* Wait a little before trying again */ - } - sqlite3_free(pFile->zDeleteOnClose); - } -#endif - if( rc ){ - pFile->h = NULL; - } - OpenCounter(-1); - OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", - osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); - return rc ? SQLITE_OK - : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), - "winClose", pFile->zPath); -} - -/* -** Read data from a file into a buffer. Return SQLITE_OK if all -** bytes were read successfully and SQLITE_IOERR if anything goes -** wrong. -*/ -static int winRead( - sqlite3_file *id, /* File to read from */ - void *pBuf, /* Write content into this buffer */ - int amt, /* Number of bytes to read */ - sqlite3_int64 offset /* Begin reading at this offset */ -){ -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) - OVERLAPPED overlapped; /* The offset for ReadFile. */ -#endif - winFile *pFile = (winFile*)id; /* file handle */ - DWORD nRead; /* Number of bytes actually read from file */ - int nRetry = 0; /* Number of retrys */ - - assert( id!=0 ); - assert( amt>0 ); - assert( offset>=0 ); - SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " - "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, - pFile->h, pBuf, amt, offset, pFile->locktype)); - -#if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transferring - ** data from the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; - }else{ - int nCopy = (int)(pFile->mmapSize - offset); - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } - } -#endif - -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) - if( winSeekFile(pFile, offset) ){ - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_FULL; - } - while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ -#else - memset(&overlapped, 0, sizeof(OVERLAPPED)); - overlapped.Offset = (LONG)(offset & 0xffffffff); - overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); - while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) && - osGetLastError()!=ERROR_HANDLE_EOF ){ -#endif - DWORD lastErrno; - if( winRetryIoerr(&nRetry, &lastErrno) ) continue; - pFile->lastErrno = lastErrno; - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, - "winRead", pFile->zPath); - } - winLogIoerr(nRetry, __LINE__); - if( nRead<(DWORD)amt ){ - /* Unread parts of the buffer must be zero-filled */ - memset(&((char*)pBuf)[nRead], 0, amt-nRead); - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_IOERR_SHORT_READ; - } - - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; -} - -/* -** Write data from a buffer into a file. Return SQLITE_OK on success -** or some other error code on failure. -*/ -static int winWrite( - sqlite3_file *id, /* File to write into */ - const void *pBuf, /* The bytes to be written */ - int amt, /* Number of bytes to write */ - sqlite3_int64 offset /* Offset into the file to begin writing at */ -){ - int rc = 0; /* True if error has occurred, else false */ - winFile *pFile = (winFile*)id; /* File handle */ - int nRetry = 0; /* Number of retries */ - - assert( amt>0 ); - assert( pFile ); - SimulateIOError(return SQLITE_IOERR_WRITE); - SimulateDiskfullError(return SQLITE_FULL); - - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " - "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, - pFile->h, pBuf, amt, offset, pFile->locktype)); - -#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transferring - ** data from the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; - }else{ - int nCopy = (int)(pFile->mmapSize - offset); - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } - } -#endif - -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) - rc = winSeekFile(pFile, offset); - if( rc==0 ){ -#else - { -#endif -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) - OVERLAPPED overlapped; /* The offset for WriteFile. */ -#endif - u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ - int nRem = amt; /* Number of bytes yet to be written */ - DWORD nWrite; /* Bytes written by each WriteFile() call */ - DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ - -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) - memset(&overlapped, 0, sizeof(OVERLAPPED)); - overlapped.Offset = (LONG)(offset & 0xffffffff); - overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); -#endif - - while( nRem>0 ){ -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) - if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ -#else - if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ -#endif - if( winRetryIoerr(&nRetry, &lastErrno) ) continue; - break; - } - assert( nWrite==0 || nWrite<=(DWORD)nRem ); - if( nWrite==0 || nWrite>(DWORD)nRem ){ - lastErrno = osGetLastError(); - break; - } -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) - offset += nWrite; - overlapped.Offset = (LONG)(offset & 0xffffffff); - overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); -#endif - aRem += nWrite; - nRem -= nWrite; - } - if( nRem>0 ){ - pFile->lastErrno = lastErrno; - rc = 1; - } - } - - if( rc ){ - if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) - || ( pFile->lastErrno==ERROR_DISK_FULL )){ - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return winLogError(SQLITE_FULL, pFile->lastErrno, - "winWrite1", pFile->zPath); - } - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, - "winWrite2", pFile->zPath); - }else{ - winLogIoerr(nRetry, __LINE__); - } - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; -} - -/* -** Truncate the file opened by handle h to nByte bytes in size. -*/ -static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){ - int rc = SQLITE_OK; /* Return code */ - rc = winHandleSeek(h, nByte); - if( rc==SQLITE_OK ){ - if( 0==osSetEndOfFile(h) ){ - rc = SQLITE_IOERR_TRUNCATE; - } - } - return rc; -} - -/* -** Determine the size in bytes of the file opened by the handle passed as -** the first argument. -*/ -static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ - int rc = SQLITE_OK; - -#if SQLITE_OS_WINRT - FILE_STANDARD_INFO info; - BOOL b; - b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info)); - if( b ){ - *pnByte = info.EndOfFile.QuadPart; - }else{ - rc = SQLITE_IOERR_FSTAT; - } -#else - DWORD upperBits = 0; - DWORD lowerBits = 0; - - assert( pnByte ); - lowerBits = osGetFileSize(h, &upperBits); - *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits; - if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){ - rc = SQLITE_IOERR_FSTAT; - } -#endif - - return rc; -} - -/* -** Close the handle passed as the only argument. -*/ -static void winHandleClose(HANDLE h){ - if( h!=INVALID_HANDLE_VALUE ){ - osCloseHandle(h); - } -} - -/* -** Truncate an open file to a specified size -*/ -static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ - winFile *pFile = (winFile*)id; /* File handle object */ - int rc = SQLITE_OK; /* Return code for this function */ - DWORD lastErrno; -#if SQLITE_MAX_MMAP_SIZE>0 - sqlite3_int64 oldMmapSize; - if( pFile->nFetchOut>0 ){ - /* File truncation is a no-op if there are outstanding memory mapped - ** pages. This is because truncating the file means temporarily unmapping - ** the file, and that might delete memory out from under existing cursors. - ** - ** This can result in incremental vacuum not truncating the file, - ** if there is an active read cursor when the incremental vacuum occurs. - ** No real harm comes of this - the database file is not corrupted, - ** though some folks might complain that the file is bigger than it - ** needs to be. - ** - ** The only feasible work-around is to defer the truncation until after - ** all references to memory-mapped content are closed. That is doable, - ** but involves adding a few branches in the common write code path which - ** could slow down normal operations slightly. Hence, we have decided for - ** now to simply make transactions a no-op if there are pending reads. We - ** can maybe revisit this decision in the future. - */ - return SQLITE_OK; - } -#endif - - assert( pFile ); - SimulateIOError(return SQLITE_IOERR_TRUNCATE); - OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", - osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); - - /* If the user has configured a chunk-size for this file, truncate the - ** file so that it consists of an integer number of chunks (i.e. the - ** actual file size after the operation may be larger than the requested - ** size). - */ - if( pFile->szChunk>0 ){ - nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; - } - -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->pMapRegion ){ - oldMmapSize = pFile->mmapSize; - }else{ - oldMmapSize = 0; - } - winUnmapfile(pFile); -#endif - - /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ - if( winSeekFile(pFile, nByte) ){ - rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, - "winTruncate1", pFile->zPath); - }else if( 0==osSetEndOfFile(pFile->h) && - ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){ - pFile->lastErrno = lastErrno; - rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, - "winTruncate2", pFile->zPath); - } - -#if SQLITE_MAX_MMAP_SIZE>0 - if( rc==SQLITE_OK && oldMmapSize>0 ){ - if( oldMmapSize>nByte ){ - winMapfile(pFile, -1); - }else{ - winMapfile(pFile, oldMmapSize); - } - } -#endif - - OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", - osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); - return rc; -} - -#ifdef SQLITE_TEST -/* -** Count the number of fullsyncs and normal syncs. This is used to test -** that syncs and fullsyncs are occurring at the right times. -*/ -SQLITE_API int sqlite3_sync_count = 0; -SQLITE_API int sqlite3_fullsync_count = 0; -#endif - -/* -** Make sure all writes to a particular file are committed to disk. -*/ -static int winSync(sqlite3_file *id, int flags){ -#ifndef SQLITE_NO_SYNC - /* - ** Used only when SQLITE_NO_SYNC is not defined. - */ - BOOL rc; -#endif -#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ - defined(SQLITE_HAVE_OS_TRACE) - /* - ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or - ** OSTRACE() macros. - */ - winFile *pFile = (winFile*)id; -#else - UNUSED_PARAMETER(id); -#endif - - assert( pFile ); - /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ - assert((flags&0x0F)==SQLITE_SYNC_NORMAL - || (flags&0x0F)==SQLITE_SYNC_FULL - ); - - /* Unix cannot, but some systems may return SQLITE_FULL from here. This - ** line is to test that doing so does not cause any problems. - */ - SimulateDiskfullError( return SQLITE_FULL ); - - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", - osGetCurrentProcessId(), pFile, pFile->h, flags, - pFile->locktype)); - -#ifndef SQLITE_TEST - UNUSED_PARAMETER(flags); -#else - if( (flags&0x0F)==SQLITE_SYNC_FULL ){ - sqlite3_fullsync_count++; - } - sqlite3_sync_count++; -#endif - - /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a - ** no-op - */ -#ifdef SQLITE_NO_SYNC - OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; -#else -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->pMapRegion ){ - if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ - OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_OK\n", osGetCurrentProcessId(), - pFile, pFile->pMapRegion)); - }else{ - pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), - pFile, pFile->pMapRegion)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winSync1", pFile->zPath); - } - } -#endif - rc = osFlushFileBuffers(pFile->h); - SimulateIOError( rc=FALSE ); - if( rc ){ - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return SQLITE_OK; - }else{ - pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", - osGetCurrentProcessId(), pFile, pFile->h)); - return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, - "winSync2", pFile->zPath); - } -#endif -} - -/* -** Determine the current size of a file in bytes -*/ -static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ - winFile *pFile = (winFile*)id; - int rc = SQLITE_OK; - - assert( id!=0 ); - assert( pSize!=0 ); - SimulateIOError(return SQLITE_IOERR_FSTAT); - OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize)); - -#if SQLITE_OS_WINRT - { - FILE_STANDARD_INFO info; - if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, - &info, sizeof(info)) ){ - *pSize = info.EndOfFile.QuadPart; - }else{ - pFile->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, - "winFileSize", pFile->zPath); - } - } -#else - { - DWORD upperBits; - DWORD lowerBits; - DWORD lastErrno; - - lowerBits = osGetFileSize(pFile->h, &upperBits); - *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; - if( (lowerBits == INVALID_FILE_SIZE) - && ((lastErrno = osGetLastError())!=NO_ERROR) ){ - pFile->lastErrno = lastErrno; - rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, - "winFileSize", pFile->zPath); - } - } -#endif - OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", - pFile->h, pSize, *pSize, sqlite3ErrName(rc))); - return rc; -} - -/* -** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. -*/ -#ifndef LOCKFILE_FAIL_IMMEDIATELY -# define LOCKFILE_FAIL_IMMEDIATELY 1 -#endif - -#ifndef LOCKFILE_EXCLUSIVE_LOCK -# define LOCKFILE_EXCLUSIVE_LOCK 2 -#endif - -/* -** Historically, SQLite has used both the LockFile and LockFileEx functions. -** When the LockFile function was used, it was always expected to fail -** immediately if the lock could not be obtained. Also, it always expected to -** obtain an exclusive lock. These flags are used with the LockFileEx function -** and reflect those expectations; therefore, they should not be changed. -*/ -#ifndef SQLITE_LOCKFILE_FLAGS -# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \ - LOCKFILE_EXCLUSIVE_LOCK) -#endif - -/* -** Currently, SQLite never calls the LockFileEx function without wanting the -** call to fail immediately if the lock cannot be obtained. -*/ -#ifndef SQLITE_LOCKFILEEX_FLAGS -# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY) -#endif - -/* -** Acquire a reader lock. -** Different API routines are called depending on whether or not this -** is Win9x or WinNT. -*/ -static int winGetReadLock(winFile *pFile, int bBlock){ - int res; - DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0); - OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); - if( osIsNT() ){ -#if SQLITE_OS_WINCE - /* - ** NOTE: Windows CE is handled differently here due its lack of the Win32 - ** API LockFileEx. - */ - res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); -#else - res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0, - SHARED_SIZE, 0); -#endif - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - int lk; - sqlite3_randomness(sizeof(lk), &lk); - pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask, - SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); - } -#endif - if( res == 0 ){ - pFile->lastErrno = osGetLastError(); - /* No need to log a failure to lock */ - } - OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res)); - return res; -} - -/* -** Undo a readlock -*/ -static int winUnlockReadLock(winFile *pFile){ - int res; - DWORD lastErrno; - OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); - if( osIsNT() ){ - res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); - } -#endif - if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, - "winUnlockReadLock", pFile->zPath); - } - OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res)); - return res; -} - -/* -** Lock the file with the lock specified by parameter locktype - one -** of the following: -** -** (1) SHARED_LOCK -** (2) RESERVED_LOCK -** (3) PENDING_LOCK -** (4) EXCLUSIVE_LOCK -** -** Sometimes when requesting one lock state, additional lock states -** are inserted in between. The locking might fail on one of the later -** transitions leaving the lock state different from what it started but -** still short of its goal. The following chart shows the allowed -** transitions and the inserted intermediate states: -** -** UNLOCKED -> SHARED -** SHARED -> RESERVED -** SHARED -> (PENDING) -> EXCLUSIVE -** RESERVED -> (PENDING) -> EXCLUSIVE -** PENDING -> EXCLUSIVE -** -** This routine will only increase a lock. The winUnlock() routine -** erases all locks at once and returns us immediately to locking level 0. -** It is not possible to lower the locking level one step at a time. You -** must go straight to locking level 0. -*/ -static int winLock(sqlite3_file *id, int locktype){ - int rc = SQLITE_OK; /* Return code from subroutines */ - int res = 1; /* Result of a Windows lock call */ - int newLocktype; /* Set pFile->locktype to this value before exiting */ - int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ - winFile *pFile = (winFile*)id; - DWORD lastErrno = NO_ERROR; - - assert( id!=0 ); - OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n", - pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); - - /* If there is already a lock of this type or more restrictive on the - ** OsFile, do nothing. Don't use the end_lock: exit path, as - ** sqlite3OsEnterMutex() hasn't been called yet. - */ - if( pFile->locktype>=locktype ){ - OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - - /* Do not allow any kind of write-lock on a read-only database - */ - if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){ - return SQLITE_IOERR_LOCK; - } - - /* Make sure the locking sequence is correct - */ - assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); - assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); - - /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or - ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of - ** the PENDING_LOCK byte is temporary. - */ - newLocktype = pFile->locktype; - if( locktype==SHARED_LOCK - || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) - ){ - int cnt = 3; - - /* Flags for the LockFileEx() call. This should be an exclusive lock if - ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to - ** obtain SHARED. */ - int flags = LOCKFILE_FAIL_IMMEDIATELY; - if( locktype==EXCLUSIVE_LOCK ){ - flags |= LOCKFILE_EXCLUSIVE_LOCK; - } - while( cnt>0 ){ - /* Try 3 times to get the pending lock. This is needed to work - ** around problems caused by indexing and/or anti-virus software on - ** Windows systems. - ** - ** If you are using this code as a model for alternative VFSes, do not - ** copy this retry logic. It is a hack intended for Windows only. */ - res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0); - if( res ) break; - - lastErrno = osGetLastError(); - OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n", - pFile->h, cnt, res - )); - - if( lastErrno==ERROR_INVALID_HANDLE ){ - pFile->lastErrno = lastErrno; - rc = SQLITE_IOERR_LOCK; - OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n", - pFile->h, cnt, sqlite3ErrName(rc) - )); - return rc; - } - - cnt--; - if( cnt>0 ) sqlite3_win32_sleep(1); - } - gotPendingLock = res; - } - - /* Acquire a shared lock - */ - if( locktype==SHARED_LOCK && res ){ - assert( pFile->locktype==NO_LOCK ); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - res = winGetReadLock(pFile, pFile->bBlockOnConnect); -#else - res = winGetReadLock(pFile, 0); -#endif - if( res ){ - newLocktype = SHARED_LOCK; - }else{ - lastErrno = osGetLastError(); - } - } - - /* Acquire a RESERVED lock - */ - if( locktype==RESERVED_LOCK && res ){ - assert( pFile->locktype==SHARED_LOCK ); - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); - if( res ){ - newLocktype = RESERVED_LOCK; - }else{ - lastErrno = osGetLastError(); - } - } - - /* Acquire a PENDING lock - */ - if( locktype==EXCLUSIVE_LOCK && res ){ - newLocktype = PENDING_LOCK; - gotPendingLock = 0; - } - - /* Acquire an EXCLUSIVE lock - */ - if( locktype==EXCLUSIVE_LOCK && res ){ - assert( pFile->locktype>=SHARED_LOCK ); - (void)winUnlockReadLock(pFile); - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, - SHARED_SIZE, 0); - if( res ){ - newLocktype = EXCLUSIVE_LOCK; - }else{ - lastErrno = osGetLastError(); - winGetReadLock(pFile, 0); - } - } - - /* If we are holding a PENDING lock that ought to be released, then - ** release it now. - */ - if( gotPendingLock && locktype==SHARED_LOCK ){ - winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); - } - - /* Update the state of the lock has held in the file descriptor then - ** return the appropriate result code. - */ - if( res ){ - rc = SQLITE_OK; - }else{ - pFile->lastErrno = lastErrno; - rc = SQLITE_BUSY; - OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n", - pFile->h, locktype, newLocktype)); - } - pFile->locktype = (u8)newLocktype; - OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n", - pFile->h, pFile->locktype, sqlite3ErrName(rc))); - return rc; -} - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, return -** non-zero, otherwise zero. -*/ -static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ - int res; - winFile *pFile = (winFile*)id; - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut)); - - assert( id!=0 ); - if( pFile->locktype>=RESERVED_LOCK ){ - res = 1; - OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res)); - }else{ - res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE,0,1,0); - if( res ){ - winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); - } - res = !res; - OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res)); - } - *pResOut = res; - OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - pFile->h, pResOut, *pResOut)); - return SQLITE_OK; -} - -/* -** Lower the locking level on file descriptor id to locktype. locktype -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -** -** It is not possible for this routine to fail if the second argument -** is NO_LOCK. If the second argument is SHARED_LOCK then this routine -** might return SQLITE_IOERR; -*/ -static int winUnlock(sqlite3_file *id, int locktype){ - int type; - winFile *pFile = (winFile*)id; - int rc = SQLITE_OK; - assert( pFile!=0 ); - assert( locktype<=SHARED_LOCK ); - OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n", - pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); - type = pFile->locktype; - if( type>=EXCLUSIVE_LOCK ){ - winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){ - /* This should never happen. We should always be able to - ** reacquire the read lock */ - rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), - "winUnlock", pFile->zPath); - } - } - if( type>=RESERVED_LOCK ){ - winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); - } - if( locktype==NO_LOCK && type>=SHARED_LOCK ){ - winUnlockReadLock(pFile); - } - if( type>=PENDING_LOCK ){ - winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); - } - pFile->locktype = (u8)locktype; - OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n", - pFile->h, pFile->locktype, sqlite3ErrName(rc))); - return rc; -} - -/****************************************************************************** -****************************** No-op Locking ********************************** -** -** Of the various locking implementations available, this is by far the -** simplest: locking is ignored. No attempt is made to lock the database -** file for reading or writing. -** -** This locking mode is appropriate for use on read-only databases -** (ex: databases that are burned into CD-ROM, for example.) It can -** also be used if the application employs some external mechanism to -** prevent simultaneous access of the same database by two or more -** database connections. But there is a serious risk of database -** corruption if this locking mode is used in situations where multiple -** database connections are accessing the same database file at the same -** time and one or more of those connections are writing. -*/ - -static int winNolockLock(sqlite3_file *id, int locktype){ - UNUSED_PARAMETER(id); - UNUSED_PARAMETER(locktype); - return SQLITE_OK; -} - -static int winNolockCheckReservedLock(sqlite3_file *id, int *pResOut){ - UNUSED_PARAMETER(id); - UNUSED_PARAMETER(pResOut); - return SQLITE_OK; -} - -static int winNolockUnlock(sqlite3_file *id, int locktype){ - UNUSED_PARAMETER(id); - UNUSED_PARAMETER(locktype); - return SQLITE_OK; -} - -/******************* End of the no-op lock implementation ********************* -******************************************************************************/ - -/* -** If *pArg is initially negative then this is a query. Set *pArg to -** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. -** -** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. -*/ -static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){ - if( *pArg<0 ){ - *pArg = (pFile->ctrlFlags & mask)!=0; - }else if( (*pArg)==0 ){ - pFile->ctrlFlags &= ~mask; - }else{ - pFile->ctrlFlags |= mask; - } -} - -/* Forward references to VFS helper methods used for temporary files */ -static int winGetTempname(sqlite3_vfs *, char **); -static int winIsDir(const void *); -static BOOL winIsLongPathPrefix(const char *); -static BOOL winIsDriveLetterAndColon(const char *); - -/* -** Control and query of the open file handle. -*/ -static int winFileControl(sqlite3_file *id, int op, void *pArg){ - winFile *pFile = (winFile*)id; - OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg)); - switch( op ){ - case SQLITE_FCNTL_LOCKSTATE: { - *(int*)pArg = pFile->locktype; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_LAST_ERRNO: { - *(int*)pArg = (int)pFile->lastErrno; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_CHUNK_SIZE: { - pFile->szChunk = *(int *)pArg; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_SIZE_HINT: { - if( pFile->szChunk>0 ){ - sqlite3_int64 oldSz; - int rc = winFileSize(id, &oldSz); - if( rc==SQLITE_OK ){ - sqlite3_int64 newSz = *(sqlite3_int64*)pArg; - if( newSz>oldSz ){ - SimulateIOErrorBenign(1); - rc = winTruncate(id, newSz); - SimulateIOErrorBenign(0); - } - } - OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); - return rc; - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_PERSIST_WAL: { - winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { - winModeBit(pFile, WINFILE_PSOW, (int*)pArg); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_VFSNAME: { - *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_WIN32_AV_RETRY: { - int *a = (int*)pArg; - if( a[0]>0 ){ - winIoerrRetry = a[0]; - }else{ - a[0] = winIoerrRetry; - } - if( a[1]>0 ){ - winIoerrRetryDelay = a[1]; - }else{ - a[1] = winIoerrRetryDelay; - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_WIN32_GET_HANDLE: { - LPHANDLE phFile = (LPHANDLE)pArg; - *phFile = pFile->h; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } -#ifdef SQLITE_TEST - case SQLITE_FCNTL_WIN32_SET_HANDLE: { - LPHANDLE phFile = (LPHANDLE)pArg; - HANDLE hOldFile = pFile->h; - pFile->h = *phFile; - *phFile = hOldFile; - OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n", - hOldFile, pFile->h)); - return SQLITE_OK; - } -#endif - case SQLITE_FCNTL_NULL_IO: { - (void)osCloseHandle(pFile->h); - pFile->h = NULL; - return SQLITE_OK; - } - case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = 0; - int rc = winGetTempname(pFile->pVfs, &zTFile); - if( rc==SQLITE_OK ){ - *(char**)pArg = zTFile; - } - OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); - return rc; - } -#if SQLITE_MAX_MMAP_SIZE>0 - case SQLITE_FCNTL_MMAP_SIZE: { - i64 newLimit = *(i64*)pArg; - int rc = SQLITE_OK; - if( newLimit>sqlite3GlobalConfig.mxMmap ){ - newLimit = sqlite3GlobalConfig.mxMmap; - } - - /* The value of newLimit may be eventually cast to (SIZE_T) and passed - ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at - ** least a 64-bit type. */ - if( newLimit>0 && sizeof(SIZE_T)<8 ){ - newLimit = (newLimit & 0x7FFFFFFF); - } - - *(i64*)pArg = pFile->mmapSizeMax; - if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ - pFile->mmapSizeMax = newLimit; - if( pFile->mmapSize>0 ){ - winUnmapfile(pFile); - rc = winMapfile(pFile, -1); - } - } - OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); - return rc; - } -#endif - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - case SQLITE_FCNTL_LOCK_TIMEOUT: { - int iOld = pFile->iBusyTimeout; - int iNew = *(int*)pArg; -#if SQLITE_ENABLE_SETLK_TIMEOUT==1 - pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew; -#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 - pFile->iBusyTimeout = (DWORD)(!!iNew); -#else -# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" -#endif - *(int*)pArg = iOld; - return SQLITE_OK; - } - case SQLITE_FCNTL_BLOCK_ON_CONNECT: { - int iNew = *(int*)pArg; - pFile->bBlockOnConnect = iNew; - return SQLITE_OK; - } -#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ - - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); - return SQLITE_NOTFOUND; -} - -/* -** Return the sector size in bytes of the underlying block device for -** the specified file. This is almost always 512 bytes, but may be -** larger for some devices. -** -** SQLite code assumes this function cannot fail. It also assumes that -** if two files are created in the same file-system directory (i.e. -** a database and its journal file) that the sector size will be the -** same for both. -*/ -static int winSectorSize(sqlite3_file *id){ - (void)id; - return SQLITE_DEFAULT_SECTOR_SIZE; -} - -/* -** Return a vector of device characteristics. -*/ -static int winDeviceCharacteristics(sqlite3_file *id){ - winFile *p = (winFile*)id; - return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ | - ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); -} - -/* -** Windows will only let you create file view mappings -** on allocation size granularity boundaries. -** During sqlite3_os_init() we do a GetSystemInfo() -** to get the granularity size. -*/ -static SYSTEM_INFO winSysInfo; - -#ifndef SQLITE_OMIT_WAL - -/* -** Helper functions to obtain and relinquish the global mutex. The -** global mutex is used to protect the winLockInfo objects used by -** this file, all of which may be shared by multiple threads. -** -** Function winShmMutexHeld() is used to assert() that the global mutex -** is held when required. This function is only used as part of assert() -** statements. e.g. -** -** winShmEnterMutex() -** assert( winShmMutexHeld() ); -** winShmLeaveMutex() -*/ -static sqlite3_mutex *winBigLock = 0; -static void winShmEnterMutex(void){ - sqlite3_mutex_enter(winBigLock); -} -static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(winBigLock); -} -#ifndef NDEBUG -static int winShmMutexHeld(void) { - return sqlite3_mutex_held(winBigLock); -} -#endif - -/* -** Object used to represent a single file opened and mmapped to provide -** shared memory. When multiple threads all reference the same -** log-summary, each thread has its own winFile object, but they all -** point to a single instance of this object. In other words, each -** log-summary is opened only once per process. -** -** winShmMutexHeld() must be true when creating or destroying -** this object or while reading or writing the following fields: -** -** nRef -** pNext -** -** The following fields are read-only after the object is created: -** -** zFilename -** -** Either winShmNode.mutex must be held or winShmNode.nRef==0 and -** winShmMutexHeld() is true when reading or writing any other field -** in this structure. -** -** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate -** the *-shm file if the DMS-locking protocol demands it, and (c) map -** regions of the *-shm file into memory using MapViewOfFile() or -** similar. Other locks are taken by individual clients using the -** winShm.hShm handles. -*/ -struct winShmNode { - sqlite3_mutex *mutex; /* Mutex to access this object */ - char *zFilename; /* Name of the file */ - HANDLE hSharedShm; /* File handle open on zFilename */ - - int isUnlocked; /* DMS lock has not yet been obtained */ - int isReadonly; /* True if read-only */ - int szRegion; /* Size of shared-memory regions */ - int nRegion; /* Size of array apRegion */ - - struct ShmRegion { - HANDLE hMap; /* File handle from CreateFileMapping */ - void *pMap; - } *aRegion; - DWORD lastErrno; /* The Windows errno from the last I/O error */ - - int nRef; /* Number of winShm objects pointing to this */ - winShmNode *pNext; /* Next in list of all winShmNode objects */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) - u8 nextShmId; /* Next available winShm.id value */ -#endif -}; - -/* -** A global array of all winShmNode objects. -** -** The winShmMutexHeld() must be true while reading or writing this list. -*/ -static winShmNode *winShmNodeList = 0; - -/* -** Structure used internally by this VFS to record the state of an -** open shared memory connection. There is one such structure for each -** winFile open on a wal mode database. -*/ -struct winShm { - winShmNode *pShmNode; /* The underlying winShmNode object */ - u16 sharedMask; /* Mask of shared locks held */ - u16 exclMask; /* Mask of exclusive locks held */ - HANDLE hShm; /* File-handle on *-shm file. For locking. */ - int bReadonly; /* True if hShm is opened read-only */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) - u8 id; /* Id of this connection with its winShmNode */ -#endif -}; - -/* -** Constants used for locking -*/ -#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ -#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ - -/* Forward references to VFS methods */ -static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); -static int winDelete(sqlite3_vfs *,const char*,int); - -/* -** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. -** -** This is not a VFS shared-memory method; it is a utility function called -** by VFS shared-memory methods. -*/ -static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ - winShmNode **pp; - winShmNode *p; - assert( winShmMutexHeld() ); - OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", - osGetCurrentProcessId(), deleteFlag)); - pp = &winShmNodeList; - while( (p = *pp)!=0 ){ - if( p->nRef==0 ){ - int i; - if( p->mutex ){ sqlite3_mutex_free(p->mutex); } - for(i=0; inRegion; i++){ - BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); - OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", - osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); - UNUSED_VARIABLE_VALUE(bRc); - bRc = osCloseHandle(p->aRegion[i].hMap); - OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", - osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); - UNUSED_VARIABLE_VALUE(bRc); - } - winHandleClose(p->hSharedShm); - if( deleteFlag ){ - SimulateIOErrorBenign(1); - sqlite3BeginBenignMalloc(); - winDelete(pVfs, p->zFilename, 0); - sqlite3EndBenignMalloc(); - SimulateIOErrorBenign(0); - } - *pp = p->pNext; - sqlite3_free(p->aRegion); - sqlite3_free(p); - }else{ - pp = &p->pNext; - } - } -} - -/* -** The DMS lock has not yet been taken on the shm file associated with -** pShmNode. Take the lock. Truncate the *-shm file if required. -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){ - HANDLE h = pShmNode->hSharedShm; - int rc = SQLITE_OK; - - assert( sqlite3_mutex_held(pShmNode->mutex) ); - rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0); - if( rc==SQLITE_OK ){ - /* We have an EXCLUSIVE lock on the DMS byte. This means that this - ** is the first process to open the file. Truncate it to zero bytes - ** in this case. */ - if( pShmNode->isReadonly ){ - rc = SQLITE_READONLY_CANTINIT; - }else{ - rc = winHandleTruncate(h, 0); - } - - /* Release the EXCLUSIVE lock acquired above. */ - winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0); - }else if( (rc & 0xFF)==SQLITE_BUSY ){ - rc = SQLITE_OK; - } - - if( rc==SQLITE_OK ){ - /* Take a SHARED lock on the DMS byte. */ - rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs); - if( rc==SQLITE_OK ){ - pShmNode->isUnlocked = 0; - } - } - - return rc; -} - - -/* -** Convert a UTF-8 filename into whatever form the underlying -** operating system wants filenames in. Space to hold the result -** is obtained from malloc and must be freed by the calling -** function -** -** On Cygwin, 3 possible input forms are accepted: -** - If the filename starts with ":/" or ":\", -** it is converted to UTF-16 as-is. -** - If the filename contains '/', it is assumed to be a -** Cygwin absolute path, it is converted to a win32 -** absolute path in UTF-16. -** - Otherwise it must be a filename only, the win32 filename -** is returned in UTF-16. -** Note: If the function cygwin_conv_path() fails, only -** UTF-8 -> UTF-16 conversion will be done. This can only -** happen when the file path >32k, in which case winUtf8ToUnicode() -** will fail too. -*/ -static void *winConvertFromUtf8Filename(const char *zFilename){ - void *zConverted = 0; - if( osIsNT() ){ -#ifdef __CYGWIN__ - int nChar; - LPWSTR zWideFilename; - - if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2])) ){ - i64 nByte; - int convertflag = CCP_POSIX_TO_WIN_W; - if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; - nByte = (i64)osCygwin_conv_path(convertflag, - zFilename, 0, 0); - if( nByte>0 ){ - zConverted = sqlite3MallocZero(12+(u64)nByte); - if ( zConverted==0 ){ - return zConverted; - } - zWideFilename = zConverted; - /* Filenames should be prefixed, except when converted - * full path already starts with "\\?\". */ - if( osCygwin_conv_path(convertflag, zFilename, - zWideFilename+4, nByte)==0 ){ - if( (convertflag&CCP_RELATIVE) ){ - memmove(zWideFilename, zWideFilename+4, nByte); - }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( zWideFilename[6]!='?' ){ - memmove(zWideFilename+6, zWideFilename+4, nByte); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - }else{ - memmove(zWideFilename, zWideFilename+4, nByte); - } - return zConverted; - } - sqlite3_free(zConverted); - } - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); - if( nChar==0 ){ - return 0; - } - zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); - if( zWideFilename==0 ){ - return 0; - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, - zWideFilename, nChar); - if( nChar==0 ){ - sqlite3_free(zWideFilename); - zWideFilename = 0; - }else if( nChar>MAX_PATH - && winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2]) ){ - memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); - zWideFilename[2] = '\\'; - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( nChar>MAX_PATH - && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) - && zFilename[2] != '?' ){ - memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - } - zConverted = zWideFilename; -#else - zConverted = winUtf8ToUnicode(zFilename); -#endif /* __CYGWIN__ */ - } -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) - else{ - zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); - } -#endif - /* caller will handle out of memory */ - return zConverted; -} - -/* -** This function is used to open a handle on a *-shm file. -** -** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file -** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not. -*/ -static int winHandleOpen( - const char *zUtf8, /* File to open */ - int *pbReadonly, /* IN/OUT: True for readonly handle */ - HANDLE *ph /* OUT: New HANDLE for file */ -){ - int rc = SQLITE_OK; - void *zConverted = 0; - int bReadonly = *pbReadonly; - HANDLE h = INVALID_HANDLE_VALUE; - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED; -#else - const DWORD flag_overlapped = 0; -#endif - - /* Convert the filename to the system encoding. */ - zConverted = winConvertFromUtf8Filename(zUtf8); - if( zConverted==0 ){ - OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8)); - rc = SQLITE_IOERR_NOMEM_BKPT; - goto winopenfile_out; - } - - /* Ensure the file we are trying to open is not actually a directory. */ - if( winIsDir(zConverted) ){ - OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8)); - rc = SQLITE_CANTOPEN_ISDIR; - goto winopenfile_out; - } - - /* TODO: platforms. - ** TODO: retry-on-ioerr. - */ - if( osIsNT() ){ -#if SQLITE_OS_WINRT - CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; - memset(&extendedParameters, 0, sizeof(extendedParameters)); - extendedParameters.dwSize = sizeof(extendedParameters); - extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; - extendedParameters.dwFileFlags = flag_overlapped; - extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; - h = osCreateFile2((LPCWSTR)zConverted, - (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */ - FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ - OPEN_ALWAYS, /* dwCreationDisposition */ - &extendedParameters - ); -#else - h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */ - (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ - FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ - NULL, /* lpSecurityAttributes */ - OPEN_ALWAYS, /* dwCreationDisposition */ - FILE_ATTRIBUTE_NORMAL|flag_overlapped, - NULL - ); -#endif - }else{ - /* Due to pre-processor directives earlier in this file, - ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */ -#ifdef SQLITE_WIN32_HAS_ANSI - h = osCreateFileA((LPCSTR)zConverted, - (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ - FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ - NULL, /* lpSecurityAttributes */ - OPEN_ALWAYS, /* dwCreationDisposition */ - FILE_ATTRIBUTE_NORMAL|flag_overlapped, - NULL - ); -#endif - } - - if( h==INVALID_HANDLE_VALUE ){ - if( bReadonly==0 ){ - bReadonly = 1; - rc = winHandleOpen(zUtf8, &bReadonly, &h); - }else{ - rc = SQLITE_CANTOPEN_BKPT; - } - } - - winopenfile_out: - sqlite3_free(zConverted); - *pbReadonly = bReadonly; - *ph = h; - return rc; -} - - -/* -** Open the shared-memory area associated with database file pDbFd. -*/ -static int winOpenSharedMemory(winFile *pDbFd){ - struct winShm *p; /* The connection to be opened */ - winShmNode *pShmNode = 0; /* The underlying mmapped file */ - int rc = SQLITE_OK; /* Result code */ - winShmNode *pNew; /* Newly allocated winShmNode */ - int nName; /* Size of zName in bytes */ - - assert( pDbFd->pShm==0 ); /* Not previously opened */ - - /* Allocate space for the new sqlite3_shm object. Also speculatively - ** allocate space for a new winShmNode and filename. */ - p = sqlite3MallocZero( sizeof(*p) ); - if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT; - nName = sqlite3Strlen30(pDbFd->zPath); - pNew = sqlite3MallocZero( sizeof(*pShmNode) + (i64)nName + 17 ); - if( pNew==0 ){ - sqlite3_free(p); - return SQLITE_IOERR_NOMEM_BKPT; - } - pNew->zFilename = (char*)&pNew[1]; - pNew->hSharedShm = INVALID_HANDLE_VALUE; - pNew->isUnlocked = 1; - sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); - sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); - - /* Open a file-handle on the *-shm file for this connection. This file-handle - ** is only used for locking. The mapping of the *-shm file is created using - ** the shared file handle in winShmNode.hSharedShm. */ - p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); - rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm); - - /* Look to see if there is an existing winShmNode that can be used. - ** If no matching winShmNode currently exists, then create a new one. */ - winShmEnterMutex(); - for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ - /* TBD need to come up with better match here. Perhaps - ** use FILE_ID_BOTH_DIR_INFO Structure. */ - if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; - } - if( pShmNode==0 ){ - pShmNode = pNew; - - /* Allocate a mutex for this winShmNode object, if one is required. */ - if( sqlite3GlobalConfig.bCoreMutex ){ - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT; - } - - /* Open a file-handle to use for mappings, and for the DMS lock. */ - if( rc==SQLITE_OK ){ - HANDLE h = INVALID_HANDLE_VALUE; - pShmNode->isReadonly = p->bReadonly; - rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h); - pShmNode->hSharedShm = h; - } - - /* If successful, link the new winShmNode into the global list. If an - ** error occurred, free the object. */ - if( rc==SQLITE_OK ){ - pShmNode->pNext = winShmNodeList; - winShmNodeList = pShmNode; - pNew = 0; - }else{ - sqlite3_mutex_free(pShmNode->mutex); - if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){ - osCloseHandle(pShmNode->hSharedShm); - } - } - } - - /* If no error has occurred, link the winShm object to the winShmNode and - ** the winShm to pDbFd. */ - if( rc==SQLITE_OK ){ - p->pShmNode = pShmNode; - pShmNode->nRef++; -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) - p->id = pShmNode->nextShmId++; -#endif - pDbFd->pShm = p; - }else if( p ){ - winHandleClose(p->hShm); - sqlite3_free(p); - } - - assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 ); - winShmLeaveMutex(); - sqlite3_free(pNew); - return rc; -} - -/* -** Close a connection to shared-memory. Delete the underlying -** storage if deleteFlag is true. -*/ -static int winShmUnmap( - sqlite3_file *fd, /* Database holding shared memory */ - int deleteFlag /* Delete after closing if true */ -){ - winFile *pDbFd; /* Database holding shared-memory */ - winShm *p; /* The connection to be closed */ - winShmNode *pShmNode; /* The underlying shared-memory file */ - - pDbFd = (winFile*)fd; - p = pDbFd->pShm; - if( p==0 ) return SQLITE_OK; - if( p->hShm!=INVALID_HANDLE_VALUE ){ - osCloseHandle(p->hShm); - } - - pShmNode = p->pShmNode; - winShmEnterMutex(); - - /* If pShmNode->nRef has reached 0, then close the underlying - ** shared-memory file, too. */ - assert( pShmNode->nRef>0 ); - pShmNode->nRef--; - if( pShmNode->nRef==0 ){ - winShmPurge(pDbFd->pVfs, deleteFlag); - } - winShmLeaveMutex(); - - /* Free the connection p */ - sqlite3_free(p); - pDbFd->pShm = 0; - return SQLITE_OK; -} - -/* -** Change the lock state for a shared-memory segment. -*/ -static int winShmLock( - sqlite3_file *fd, /* Database file holding the shared memory */ - int ofst, /* First lock to acquire or release */ - int n, /* Number of locks to acquire or release */ - int flags /* What to do with the lock */ -){ - winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ - winShm *p = pDbFd->pShm; /* The shared memory being locked */ - winShmNode *pShmNode; - int rc = SQLITE_OK; /* Result code */ - u16 mask = (u16)((1U<<(ofst+n)) - (1U<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) - || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); - assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - - /* Check that, if this to be a blocking lock, no locks that occur later - ** in the following list than the lock being obtained are already held: - ** - ** 1. Recovery lock (ofst==2). - ** 2. Checkpointer lock (ofst==1). - ** 3. Write lock (ofst==0). - ** 4. Read locks (ofst>=3 && ofstexclMask|p->sharedMask); - assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( - (ofst!=2 || lockMask==0) - && (ofst!=1 || lockMask==0 || lockMask==2) - && (ofst!=0 || lockMask<3) - && (ofst<3 || lockMask<(1<exclMask & mask) - ); - if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) - || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) - || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) - ){ - - if( flags & SQLITE_SHM_UNLOCK ){ - /* Case (a) - unlock. */ - - assert( (p->exclMask & p->sharedMask)==0 ); - assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); - assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); - - rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n); - - /* If successful, also clear the bits in sharedMask/exclMask */ - if( rc==SQLITE_OK ){ - p->exclMask = (p->exclMask & ~mask); - p->sharedMask = (p->sharedMask & ~mask); - } - }else{ - int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0); - DWORD nMs = winFileBusyTimeout(pDbFd); - rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs); - if( rc==SQLITE_OK ){ - if( bExcl ){ - p->exclMask = (p->exclMask | mask); - }else{ - p->sharedMask = (p->sharedMask | mask); - } - } - } - } - - OSTRACE(( - "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x," - " rc=%s\n", - ofst, n, flags, - osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, - sqlite3ErrName(rc)) - ); - return rc; -} - -/* -** Implement a memory barrier or memory fence on shared memory. -** -** All loads and stores begun before the barrier must complete before -** any load or store begun after the barrier. -*/ -static void winShmBarrier( - sqlite3_file *fd /* Database holding the shared memory */ -){ - UNUSED_PARAMETER(fd); - sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - winShmEnterMutex(); /* Also mutex, for redundancy */ - winShmLeaveMutex(); -} - -/* -** This function is called to obtain a pointer to region iRegion of the -** shared-memory associated with the database file fd. Shared-memory regions -** are numbered starting from zero. Each shared-memory region is szRegion -** bytes in size. -** -** If an error occurs, an error code is returned and *pp is set to NULL. -** -** Otherwise, if the isWrite parameter is 0 and the requested shared-memory -** region has not been allocated (by any client, including one running in a -** separate process), then *pp is set to NULL and SQLITE_OK returned. If -** isWrite is non-zero and the requested shared-memory region has not yet -** been allocated, it is allocated by this function. -** -** If the shared-memory region has already been allocated or is allocated by -** this call as described above, then it is mapped into this processes -** address space (if it is not already), *pp is set to point to the mapped -** memory and SQLITE_OK returned. -*/ -static int winShmMap( - sqlite3_file *fd, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int szRegion, /* Size of regions */ - int isWrite, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - winFile *pDbFd = (winFile*)fd; - winShm *pShm = pDbFd->pShm; - winShmNode *pShmNode; - DWORD protect = PAGE_READWRITE; - DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ; - int rc = SQLITE_OK; - - if( !pShm ){ - rc = winOpenSharedMemory(pDbFd); - if( rc!=SQLITE_OK ) return rc; - pShm = pDbFd->pShm; - assert( pShm!=0 ); - } - pShmNode = pShm->pShmNode; - - sqlite3_mutex_enter(pShmNode->mutex); - if( pShmNode->isUnlocked ){ - /* Take the DMS lock. */ - assert( pShmNode->nRegion==0 ); - rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd)); - if( rc!=SQLITE_OK ) goto shmpage_out; - } - - assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); - if( pShmNode->nRegion<=iRegion ){ - HANDLE hShared = pShmNode->hSharedShm; - struct ShmRegion *apNew; /* New aRegion[] array */ - int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ - sqlite3_int64 sz; /* Current size of wal-index file */ - - pShmNode->szRegion = szRegion; - - /* The requested region is not mapped into this processes address space. - ** Check to see if it has been allocated (i.e. if the wal-index file is - ** large enough to contain the requested region). - */ - rc = winHandleSize(hShared, &sz); - if( rc!=SQLITE_OK ){ - rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath); - goto shmpage_out; - } - - if( szzPath); - goto shmpage_out; - } - } - - /* Map the requested memory region into this processes address space. */ - apNew = (struct ShmRegion*)sqlite3_realloc64( - pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) - ); - if( !apNew ){ - rc = SQLITE_IOERR_NOMEM_BKPT; - goto shmpage_out; - } - pShmNode->aRegion = apNew; - - if( pShmNode->isReadonly ){ - protect = PAGE_READONLY; - flags = FILE_MAP_READ; - } - - while( pShmNode->nRegion<=iRegion ){ - HANDLE hMap = NULL; /* file-mapping handle */ - void *pMap = 0; /* Mapped memory region */ - -#if SQLITE_OS_WINRT - hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL); -#elif defined(SQLITE_WIN32_HAS_WIDE) - hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL); -#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA - hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); -#endif - - OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", - osGetCurrentProcessId(), pShmNode->nRegion, nByte, - hMap ? "ok" : "failed")); - if( hMap ){ - int iOffset = pShmNode->nRegion*szRegion; - int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; -#if SQLITE_OS_WINRT - pMap = osMapViewOfFileFromApp(hMap, flags, - iOffset - iOffsetShift, szRegion + iOffsetShift - ); -#else - pMap = osMapViewOfFile(hMap, flags, - 0, iOffset - iOffsetShift, szRegion + iOffsetShift - ); -#endif - OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", - osGetCurrentProcessId(), pShmNode->nRegion, iOffset, - szRegion, pMap ? "ok" : "failed")); - } - if( !pMap ){ - pShmNode->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, - "winShmMap3", pDbFd->zPath); - if( hMap ) osCloseHandle(hMap); - goto shmpage_out; - } - - pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; - pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; - pShmNode->nRegion++; - } - } - -shmpage_out: - if( pShmNode->nRegion>iRegion ){ - int iOffset = iRegion*szRegion; - int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; - char *p = (char *)pShmNode->aRegion[iRegion].pMap; - *pp = (void *)&p[iOffsetShift]; - }else{ - *pp = 0; - } - if( pShmNode->isReadonly && rc==SQLITE_OK ){ - rc = SQLITE_READONLY; - } - sqlite3_mutex_leave(pShmNode->mutex); - return rc; -} - -#else -# define winShmMap 0 -# define winShmLock 0 -# define winShmBarrier 0 -# define winShmUnmap 0 -#endif /* #ifndef SQLITE_OMIT_WAL */ - -/* -** Cleans up the mapped region of the specified file, if any. -*/ -#if SQLITE_MAX_MMAP_SIZE>0 -static int winUnmapfile(winFile *pFile){ - assert( pFile!=0 ); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " - "mmapSize=%lld, mmapSizeMax=%lld\n", - osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, - pFile->mmapSize, pFile->mmapSizeMax)); - if( pFile->pMapRegion ){ - if( !osUnmapViewOfFile(pFile->pMapRegion) ){ - pFile->lastErrno = osGetLastError(); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, - pFile->pMapRegion)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winUnmapfile1", pFile->zPath); - } - pFile->pMapRegion = 0; - pFile->mmapSize = 0; - } - if( pFile->hMap!=NULL ){ - if( !osCloseHandle(pFile->hMap) ){ - pFile->lastErrno = osGetLastError(); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", - osGetCurrentProcessId(), pFile, pFile->hMap)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winUnmapfile2", pFile->zPath); - } - pFile->hMap = NULL; - } - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile)); - return SQLITE_OK; -} - -/* -** Memory map or remap the file opened by file-descriptor pFd (if the file -** is already mapped, the existing mapping is replaced by the new). Or, if -** there already exists a mapping for this file, and there are still -** outstanding xFetch() references to it, this function is a no-op. -** -** If parameter nByte is non-negative, then it is the requested size of -** the mapping to create. Otherwise, if nByte is less than zero, then the -** requested size is the size of the file on disk. The actual size of the -** created mapping is either the requested size or the value configured -** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller. -** -** SQLITE_OK is returned if no error occurs (even if the mapping is not -** recreated as a result of outstanding references) or an SQLite error -** code otherwise. -*/ -static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ - sqlite3_int64 nMap = nByte; - int rc; - - assert( nMap>=0 || pFd->nFetchOut==0 ); - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n", - osGetCurrentProcessId(), pFd, nByte)); - - if( pFd->nFetchOut>0 ) return SQLITE_OK; - - if( nMap<0 ){ - rc = winFileSize((sqlite3_file*)pFd, &nMap); - if( rc ){ - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_IOERR_FSTAT; - } - } - if( nMap>pFd->mmapSizeMax ){ - nMap = pFd->mmapSizeMax; - } - nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1); - - if( nMap==0 && pFd->mmapSize>0 ){ - winUnmapfile(pFd); - } - if( nMap!=pFd->mmapSize ){ - void *pNew = 0; - DWORD protect = PAGE_READONLY; - DWORD flags = FILE_MAP_READ; - - winUnmapfile(pFd); -#ifdef SQLITE_MMAP_READWRITE - if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ - protect = PAGE_READWRITE; - flags |= FILE_MAP_WRITE; - } -#endif -#if SQLITE_OS_WINRT - pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); -#elif defined(SQLITE_WIN32_HAS_WIDE) - pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, - (DWORD)((nMap>>32) & 0xffffffff), - (DWORD)(nMap & 0xffffffff), NULL); -#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA - pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, - (DWORD)((nMap>>32) & 0xffffffff), - (DWORD)(nMap & 0xffffffff), NULL); -#endif - if( pFd->hMap==NULL ){ - pFd->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, - "winMapfile1", pFd->zPath); - /* Log the error, but continue normal operation using xRead/xWrite */ - OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n", - osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); - return SQLITE_OK; - } - assert( (nMap % winSysInfo.dwPageSize)==0 ); - assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); -#if SQLITE_OS_WINRT - pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap); -#else - pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); -#endif - if( pNew==NULL ){ - osCloseHandle(pFd->hMap); - pFd->hMap = NULL; - pFd->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, - "winMapfile2", pFd->zPath); - /* Log the error, but continue normal operation using xRead/xWrite */ - OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n", - osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); - return SQLITE_OK; - } - pFd->pMapRegion = pNew; - pFd->mmapSize = nMap; - } - - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_OK; -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* -** If possible, return a pointer to a mapping of file fd starting at offset -** iOff. The mapping must be valid for at least nAmt bytes. -** -** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. -** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. -** Finally, if an error does occur, return an SQLite error code. The final -** value of *pp is undefined in this case. -** -** If this function does return a pointer, the caller must eventually -** release the reference by calling winUnfetch(). -*/ -static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ -#if SQLITE_MAX_MMAP_SIZE>0 - winFile *pFd = (winFile*)fd; /* The underlying database file */ -#endif - *pp = 0; - - OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", - osGetCurrentProcessId(), fd, iOff, nAmt, pp)); - -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; - if( pFd->pMapRegion==0 ){ - int rc = winMapfile(pFd, -1); - if( rc!=SQLITE_OK ){ - OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", - osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); - return rc; - } - } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ - assert( pFd->pMapRegion!=0 ); - *pp = &((u8 *)pFd->pMapRegion)[iOff]; - pFd->nFetchOut++; - } - } -#endif - - OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), fd, pp, *pp)); - return SQLITE_OK; -} - -/* -** If the third argument is non-NULL, then this function releases a -** reference obtained by an earlier call to winFetch(). The second -** argument passed to this function must be the same as the corresponding -** argument that was passed to the winFetch() invocation. -** -** Or, if the third argument is NULL, then this function is being called -** to inform the VFS layer that, according to POSIX, any existing mapping -** may now be invalid and should be unmapped. -*/ -static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ -#if SQLITE_MAX_MMAP_SIZE>0 - winFile *pFd = (winFile*)fd; /* The underlying database file */ - - /* If p==0 (unmap the entire file) then there must be no outstanding - ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), - ** then there must be at least one outstanding. */ - assert( (p==0)==(pFd->nFetchOut==0) ); - - /* If p!=0, it must match the iOff value. */ - assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); - - OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n", - osGetCurrentProcessId(), pFd, iOff, p)); - - if( p ){ - pFd->nFetchOut--; - }else{ - /* FIXME: If Windows truly always prevents truncating or deleting a - ** file while a mapping is held, then the following winUnmapfile() call - ** is unnecessary can be omitted - potentially improving - ** performance. */ - winUnmapfile(pFd); - } - - assert( pFd->nFetchOut>=0 ); -#endif - - OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), fd)); - return SQLITE_OK; -} - -/* -** Here ends the implementation of all sqlite3_file methods. -** -********************** End sqlite3_file Methods ******************************* -******************************************************************************/ - -/* -** This vector defines all the methods that can operate on an -** sqlite3_file for win32. -*/ -static const sqlite3_io_methods winIoMethod = { - 3, /* iVersion */ - winClose, /* xClose */ - winRead, /* xRead */ - winWrite, /* xWrite */ - winTruncate, /* xTruncate */ - winSync, /* xSync */ - winFileSize, /* xFileSize */ - winLock, /* xLock */ - winUnlock, /* xUnlock */ - winCheckReservedLock, /* xCheckReservedLock */ - winFileControl, /* xFileControl */ - winSectorSize, /* xSectorSize */ - winDeviceCharacteristics, /* xDeviceCharacteristics */ - winShmMap, /* xShmMap */ - winShmLock, /* xShmLock */ - winShmBarrier, /* xShmBarrier */ - winShmUnmap, /* xShmUnmap */ - winFetch, /* xFetch */ - winUnfetch /* xUnfetch */ -}; - -/* -** This vector defines all the methods that can operate on an -** sqlite3_file for win32 without performing any locking. -*/ -static const sqlite3_io_methods winIoNolockMethod = { - 3, /* iVersion */ - winClose, /* xClose */ - winRead, /* xRead */ - winWrite, /* xWrite */ - winTruncate, /* xTruncate */ - winSync, /* xSync */ - winFileSize, /* xFileSize */ - winNolockLock, /* xLock */ - winNolockUnlock, /* xUnlock */ - winNolockCheckReservedLock, /* xCheckReservedLock */ - winFileControl, /* xFileControl */ - winSectorSize, /* xSectorSize */ - winDeviceCharacteristics, /* xDeviceCharacteristics */ - winShmMap, /* xShmMap */ - winShmLock, /* xShmLock */ - winShmBarrier, /* xShmBarrier */ - winShmUnmap, /* xShmUnmap */ - winFetch, /* xFetch */ - winUnfetch /* xUnfetch */ -}; - -static winVfsAppData winAppData = { - &winIoMethod, /* pMethod */ - 0, /* pAppData */ - 0 /* bNoLock */ -}; - -static winVfsAppData winNolockAppData = { - &winIoNolockMethod, /* pMethod */ - 0, /* pAppData */ - 1 /* bNoLock */ -}; - -/**************************************************************************** -**************************** sqlite3_vfs methods **************************** -** -** This division contains the implementation of methods on the -** sqlite3_vfs object. -*/ - -/* -** This function returns non-zero if the specified UTF-8 string buffer -** ends with a directory separator character or one was successfully -** added to it. -*/ -static int winMakeEndInDirSep(int nBuf, char *zBuf){ - if( zBuf ){ - int nLen = sqlite3Strlen30(zBuf); - if( nLen>0 ){ - if( winIsDirSep(zBuf[nLen-1]) ){ - return 1; - }else if( nLen+1mxPathname; - nBuf = 2 + (i64)nMax; - zBuf = sqlite3MallocZero( nBuf ); - if( !zBuf ){ - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM_BKPT; - } - - /* Figure out the effective temporary directory. First, check if one - ** has been explicitly set by the application; otherwise, use the one - ** configured by the operating system. - */ - nDir = nMax - (nPre + 15); - assert( nDir>0 ); - if( winTempDirDefined() ){ - int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); - if( nDirLen>0 ){ - if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ - nDirLen++; - } - if( nDirLen>nDir ){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - sqlite3_free(zBuf); - OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); - return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); - } - sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - } - -#if defined(__CYGWIN__) - else if( osGetenv!=NULL ){ - static const char *azDirs[] = { - 0, /* getenv("SQLITE_TMPDIR") */ - 0, /* getenv("TMPDIR") */ - 0, /* getenv("TMP") */ - 0, /* getenv("TEMP") */ - 0, /* getenv("USERPROFILE") */ - "/var/tmp", - "/usr/tmp", - "/tmp", - ".", - 0 /* List terminator */ - }; - unsigned int i; - const char *zDir = 0; - - if( !azDirs[0] ) azDirs[0] = osGetenv("SQLITE_TMPDIR"); - if( !azDirs[1] ) azDirs[1] = osGetenv("TMPDIR"); - if( !azDirs[2] ) azDirs[2] = osGetenv("TMP"); - if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP"); - if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE"); - for(i=0; i/etilqs_XXXXXXXXXXXXXXX\0\0" - ** - ** If not, return SQLITE_ERROR. The number 17 is used here in order to - ** account for the space used by the 15 character random suffix and the - ** two trailing NUL characters. The final directory separator character - ** has already added if it was not already present. - */ - nLen = sqlite3Strlen30(zBuf); - if( (nLen + nPre + 17) > nBuf ){ - sqlite3_free(zBuf); - OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); - return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0); - } - - sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX); - - j = sqlite3Strlen30(zBuf); - sqlite3_randomness(15, &zBuf[j]); - pid = osGetCurrentProcessId(); - for(i=0; i<15; i++, j++){ - zBuf[j] += pid & 0xff; - pid >>= 8; - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - zBuf[j+1] = 0; - *pzBuf = zBuf; - - OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf)); - return SQLITE_OK; -} - -/* -** Return TRUE if the named file is really a directory. Return false if -** it is something other than a directory, or if there is any kind of memory -** allocation failure. -*/ -static int winIsDir(const void *zConverted){ - DWORD attr; - int rc = 0; - DWORD lastErrno; - - if( osIsNT() ){ - int cnt = 0; - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, - GetFileExInfoStandard, - &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} - if( !rc ){ - return 0; /* Invalid name? */ - } - attr = sAttrData.dwFileAttributes; -#if SQLITE_OS_WINCE==0 && defined(SQLITE_WIN32_HAS_ANSI) - }else{ - attr = osGetFileAttributesA((char*)zConverted); -#endif - } - return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); -} - -/* forward reference */ -static int winAccess( - sqlite3_vfs *pVfs, /* Not used on win32 */ - const char *zFilename, /* Name of file to check */ - int flags, /* Type of test to make on this file */ - int *pResOut /* OUT: Result */ -); - -/* -** The Windows version of xAccess() accepts an extra bit in the flags -** parameter that prevents an anti-virus retry loop. -*/ -#define NORETRY 0x4000 - -/* -** Open a file. -*/ -static int winOpen( - sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */ - const char *zName, /* Name of the file (UTF-8) */ - sqlite3_file *id, /* Write the SQLite file handle here */ - int flags, /* Open mode flags */ - int *pOutFlags /* Status return flags */ -){ - HANDLE h; - DWORD lastErrno = 0; - DWORD dwDesiredAccess; - DWORD dwShareMode; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes = 0; -#if SQLITE_OS_WINCE - int isTemp = 0; -#endif - winVfsAppData *pAppData; - winFile *pFile = (winFile*)id; - void *zConverted; /* Filename in OS encoding */ - const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ - int cnt = 0; - int isRO = 0; /* file is known to be accessible readonly */ - - /* If argument zPath is a NULL pointer, this function is required to open - ** a temporary file. Use this buffer to store the file name in. - */ - char *zTmpname = 0; /* For temporary filename, if necessary. */ - - int rc = SQLITE_OK; /* Function Return Code */ -#if !defined(NDEBUG) || SQLITE_OS_WINCE - int eType = flags&0x0FFF00; /* Type of file to open */ -#endif - - int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); - int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); - int isCreate = (flags & SQLITE_OPEN_CREATE); - int isReadonly = (flags & SQLITE_OPEN_READONLY); - int isReadWrite = (flags & SQLITE_OPEN_READWRITE); - -#ifndef NDEBUG - int isOpenJournal = (isCreate && ( - eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL - || eType==SQLITE_OPEN_WAL - )); -#endif - - OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n", - zUtf8Name, id, flags, pOutFlags)); - - /* Check the following statements are true: - ** - ** (a) Exactly one of the READWRITE and READONLY flags must be set, and - ** (b) if CREATE is set, then READWRITE must also be set, and - ** (c) if EXCLUSIVE is set, then CREATE must also be set. - ** (d) if DELETEONCLOSE is set, then CREATE must also be set. - */ - assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); - assert(isCreate==0 || isReadWrite); - assert(isExclusive==0 || isCreate); - assert(isDelete==0 || isCreate); - - /* The main DB, main journal, WAL file and super-journal are never - ** automatically deleted. Nor are they ever temporary files. */ - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); - - /* Assert that the upper layer has set one of the "file-type" flags. */ - assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB - || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL - ); - - assert( pFile!=0 ); - memset(pFile, 0, sizeof(winFile)); - pFile->h = INVALID_HANDLE_VALUE; - -#if SQLITE_OS_WINRT - if( !zUtf8Name && !sqlite3_temp_directory ){ - sqlite3_log(SQLITE_ERROR, - "sqlite3_temp_directory variable should be set for WinRT"); - } -#endif - - /* If the second argument to this function is NULL, generate a - ** temporary file name to use - */ - if( !zUtf8Name ){ - assert( isDelete && !isOpenJournal ); - rc = winGetTempname(pVfs, &zTmpname); - if( rc!=SQLITE_OK ){ - OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc))); - return rc; - } - zUtf8Name = zTmpname; - } - - /* Database filenames are double-zero terminated if they are not - ** URIs with parameters. Hence, they can always be passed into - ** sqlite3_uri_parameter(). - */ - assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || - zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 ); - - /* Convert the filename to the system encoding. */ - zConverted = winConvertFromUtf8Filename(zUtf8Name); - if( zConverted==0 ){ - sqlite3_free(zTmpname); - OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); - return SQLITE_IOERR_NOMEM_BKPT; - } - - if( winIsDir(zConverted) ){ - sqlite3_free(zConverted); - sqlite3_free(zTmpname); - OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name)); - return SQLITE_CANTOPEN_ISDIR; - } - - if( isReadWrite ){ - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - }else{ - dwDesiredAccess = GENERIC_READ; - } - - /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is - ** created. SQLite doesn't use it to indicate "exclusive access" - ** as it is usually understood. - */ - if( isExclusive ){ - /* Creates a new file, only if it does not already exist. */ - /* If the file exists, it fails. */ - dwCreationDisposition = CREATE_NEW; - }else if( isCreate ){ - /* Open existing file, or create if it doesn't exist */ - dwCreationDisposition = OPEN_ALWAYS; - }else{ - /* Opens a file, only if it exists. */ - dwCreationDisposition = OPEN_EXISTING; - } - - if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){ - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - }else{ - dwShareMode = 0; - } - - if( isDelete ){ -#if SQLITE_OS_WINCE - dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; - isTemp = 1; -#else - dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY - | FILE_ATTRIBUTE_HIDDEN - | FILE_FLAG_DELETE_ON_CLOSE; -#endif - }else{ - dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; - } - /* Reports from the internet are that performance is always - ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ -#if SQLITE_OS_WINCE - dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; -#endif - - if( osIsNT() ){ -#if SQLITE_OS_WINRT - CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; - extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); - extendedParameters.dwFileAttributes = - dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; - extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; - extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; - extendedParameters.lpSecurityAttributes = NULL; - extendedParameters.hTemplateFile = NULL; - do{ - h = osCreateFile2((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, - dwCreationDisposition, - &extendedParameters); - if( h!=INVALID_HANDLE_VALUE ) break; - if( isReadWrite ){ - int rc2; - sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); -#else - do{ - h = osCreateFileW((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL); - if( h!=INVALID_HANDLE_VALUE ) break; - if( isReadWrite ){ - int rc2; - sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); -#endif - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - do{ - h = osCreateFileA((LPCSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL); - if( h!=INVALID_HANDLE_VALUE ) break; - if( isReadWrite ){ - int rc2; - sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); - } -#endif - winLogIoerr(cnt, __LINE__); - - OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, - dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); - - if( h==INVALID_HANDLE_VALUE ){ - sqlite3_free(zConverted); - sqlite3_free(zTmpname); - if( isReadWrite && isRO && !isExclusive ){ - return winOpen(pVfs, zName, id, - ((flags|SQLITE_OPEN_READONLY) & - ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), - pOutFlags); - }else{ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); - return SQLITE_CANTOPEN_BKPT; - } - } - - if( pOutFlags ){ - if( isReadWrite ){ - *pOutFlags = SQLITE_OPEN_READWRITE; - }else{ - *pOutFlags = SQLITE_OPEN_READONLY; - } - } - - OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, " - "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ? - *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); - - pAppData = (winVfsAppData*)pVfs->pAppData; - -#if SQLITE_OS_WINCE - { - if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB - && ((pAppData==NULL) || !pAppData->bNoLock) - && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK - ){ - osCloseHandle(h); - sqlite3_free(zConverted); - sqlite3_free(zTmpname); - OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); - return rc; - } - } - if( isTemp ){ - pFile->zDeleteOnClose = zConverted; - }else -#endif - { - sqlite3_free(zConverted); - } - - sqlite3_free(zTmpname); - id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod; - pFile->pVfs = pVfs; - pFile->h = h; - if( isReadonly ){ - pFile->ctrlFlags |= WINFILE_RDONLY; - } - if( (flags & SQLITE_OPEN_MAIN_DB) - && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) - ){ - pFile->ctrlFlags |= WINFILE_PSOW; - } - pFile->lastErrno = NO_ERROR; - pFile->zPath = zName; -#if SQLITE_MAX_MMAP_SIZE>0 - pFile->hMap = NULL; - pFile->pMapRegion = 0; - pFile->mmapSize = 0; - pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; -#endif - - OpenCounter(+1); - return rc; -} - -/* -** Delete the named file. -** -** Note that Windows does not allow a file to be deleted if some other -** process has it open. Sometimes a virus scanner or indexing program -** will open a journal file shortly after it is created in order to do -** whatever it does. While this other process is holding the -** file open, we will be unable to delete it. To work around this -** problem, we delay 100 milliseconds and try to delete again. Up -** to MX_DELETION_ATTEMPTs deletion attempts are run before giving -** up and returning an error. -*/ -static int winDelete( - sqlite3_vfs *pVfs, /* Not used on win32 */ - const char *zFilename, /* Name of file to delete */ - int syncDir /* Not used on win32 */ -){ - int cnt = 0; - int rc; - DWORD attr; - DWORD lastErrno = 0; - void *zConverted; - UNUSED_PARAMETER(pVfs); - UNUSED_PARAMETER(syncDir); - - SimulateIOError(return SQLITE_IOERR_DELETE); - OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir)); - - zConverted = winConvertFromUtf8Filename(zFilename); - if( zConverted==0 ){ - OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); - return SQLITE_IOERR_NOMEM_BKPT; - } - if( osIsNT() ){ - do { -#if SQLITE_OS_WINRT - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, - &sAttrData) ){ - attr = sAttrData.dwFileAttributes; - }else{ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } -#else - attr = osGetFileAttributesW(zConverted); -#endif - if ( attr==INVALID_FILE_ATTRIBUTES ){ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } - if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ - rc = SQLITE_ERROR; /* Files only. */ - break; - } - if ( osDeleteFileW(zConverted) ){ - rc = SQLITE_OK; /* Deleted OK. */ - break; - } - if ( !winRetryIoerr(&cnt, &lastErrno) ){ - rc = SQLITE_ERROR; /* No more retries. */ - break; - } - } while(1); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - do { - attr = osGetFileAttributesA(zConverted); - if ( attr==INVALID_FILE_ATTRIBUTES ){ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } - if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ - rc = SQLITE_ERROR; /* Files only. */ - break; - } - if ( osDeleteFileA(zConverted) ){ - rc = SQLITE_OK; /* Deleted OK. */ - break; - } - if ( !winRetryIoerr(&cnt, &lastErrno) ){ - rc = SQLITE_ERROR; /* No more retries. */ - break; - } - } while(1); - } -#endif - if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ - rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); - }else{ - winLogIoerr(cnt, __LINE__); - } - sqlite3_free(zConverted); - OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); - return rc; -} - -/* -** Check the existence and status of a file. -*/ -static int winAccess( - sqlite3_vfs *pVfs, /* Not used on win32 */ - const char *zFilename, /* Name of file to check */ - int flags, /* Type of test to make on this file */ - int *pResOut /* OUT: Result */ -){ - DWORD attr; - int rc = 0; - DWORD lastErrno = 0; - void *zConverted; - int noRetry = 0; /* Do not use winRetryIoerr() */ - UNUSED_PARAMETER(pVfs); - - if( (flags & NORETRY)!=0 ){ - noRetry = 1; - flags &= ~NORETRY; - } - - SimulateIOError( return SQLITE_IOERR_ACCESS; ); - OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", - zFilename, flags, pResOut)); - - if( zFilename==0 ){ - *pResOut = 0; - OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - zFilename, pResOut, *pResOut)); - return SQLITE_OK; - } - - zConverted = winConvertFromUtf8Filename(zFilename); - if( zConverted==0 ){ - OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); - return SQLITE_IOERR_NOMEM_BKPT; - } - if( osIsNT() ){ - int cnt = 0; - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, - GetFileExInfoStandard, - &sAttrData)) - && !noRetry - && winRetryIoerr(&cnt, &lastErrno) - ){ /* Loop until true */} - if( rc ){ - /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file - ** as if it does not exist. - */ - if( flags==SQLITE_ACCESS_EXISTS - && sAttrData.nFileSizeHigh==0 - && sAttrData.nFileSizeLow==0 ){ - attr = INVALID_FILE_ATTRIBUTES; - }else{ - attr = sAttrData.dwFileAttributes; - } - }else{ - winLogIoerr(cnt, __LINE__); - if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ - sqlite3_free(zConverted); - return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", - zFilename); - }else{ - attr = INVALID_FILE_ATTRIBUTES; - } - } - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - attr = osGetFileAttributesA((char*)zConverted); - } -#endif - sqlite3_free(zConverted); - switch( flags ){ - case SQLITE_ACCESS_READ: - case SQLITE_ACCESS_EXISTS: - rc = attr!=INVALID_FILE_ATTRIBUTES; - break; - case SQLITE_ACCESS_READWRITE: - rc = attr!=INVALID_FILE_ATTRIBUTES && - (attr & FILE_ATTRIBUTE_READONLY)==0; - break; - default: - assert(!"Invalid flags argument"); - } - *pResOut = rc; - OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - zFilename, pResOut, *pResOut)); - return SQLITE_OK; -} - -/* -** Returns non-zero if the specified path name starts with the "long path" -** prefix. -*/ -static BOOL winIsLongPathPrefix( - const char *zPathname -){ - return ( zPathname[0]=='\\' && zPathname[1]=='\\' - && zPathname[2]=='?' && zPathname[3]=='\\' ); -} - -/* -** Returns non-zero if the specified path name starts with a drive letter -** followed by a colon character. -*/ -static BOOL winIsDriveLetterAndColon( - const char *zPathname -){ - return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ); -} - -#ifdef _WIN32 -/* -** Returns non-zero if the specified path name should be used verbatim. If -** non-zero is returned from this function, the calling function must simply -** use the provided path name verbatim -OR- resolve it into a full path name -** using the GetFullPathName Win32 API function (if available). -*/ -static BOOL winIsVerbatimPathname( - const char *zPathname -){ - /* - ** If the path name starts with a forward slash or a backslash, it is either - ** a legal UNC name, a volume relative path, or an absolute path name in the - ** "Unix" format on Windows. There is no easy way to differentiate between - ** the final two cases; therefore, we return the safer return value of TRUE - ** so that callers of this function will simply use it verbatim. - */ - if ( winIsDirSep(zPathname[0]) ){ - return TRUE; - } - - /* - ** If the path name starts with a letter and a colon it is either a volume - ** relative path or an absolute path. Callers of this function must not - ** attempt to treat it as a relative path name (i.e. they should simply use - ** it verbatim). - */ - if ( winIsDriveLetterAndColon(zPathname) ){ - return TRUE; - } - - /* - ** If we get to this point, the path name should almost certainly be a purely - ** relative one (i.e. not a UNC name, not absolute, and not volume relative). - */ - return FALSE; -} -#endif /* _WIN32 */ - -#ifdef __CYGWIN__ -/* -** Simplify a filename into its canonical form -** by making the following changes: -** -** * convert any '/' to '\' (win32) or reverse (Cygwin) -** * removing any trailing and duplicate / (except for UNC paths) -** * convert /./ into just / -** -** Changes are made in-place. Return the new name length. -** -** The original filename is in z[0..]. If the path is shortened, -** no-longer used bytes will be written by '\0'. -*/ -static void winSimplifyName(char *z){ - int i, j; - for(i=j=0; z[i]; ++i){ - if( winIsDirSep(z[i]) ){ -#if !defined(SQLITE_TEST) - /* Some test-cases assume that "./foo" and "foo" are different */ - if( z[i+1]=='.' && winIsDirSep(z[i+2]) ){ - ++i; - continue; - } -#endif - if( !z[i+1] || (winIsDirSep(z[i+1]) && (i!=0)) ){ - continue; - } - z[j++] = osGetenv?'/':'\\'; - }else{ - z[j++] = z[i]; - } - } - while(jnOut ){ - /* SQLite assumes that xFullPathname() nul-terminates the output buffer - ** even if it returns an error. */ - zOut[iOff] = '\0'; - return SQLITE_CANTOPEN_BKPT; - } - sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); - return SQLITE_OK; -} -#endif /* __CYGWIN__ */ - -/* -** Turn a relative pathname into a full pathname. Write the full -** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname -** bytes in size. -*/ -static int winFullPathnameNoMutex( - 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 */ -){ -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - int nByte; - void *zConverted; - char *zOut; -#endif - - /* If this path name begins with "/X:" or "\\?\", where "X" is any - ** alphabetic character, discard the initial "/" from the pathname. - */ - if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1) - || winIsLongPathPrefix(zRelative+1)) ){ - zRelative++; - } - - SimulateIOError( return SQLITE_ERROR ); - -#ifdef __CYGWIN__ - if( osGetcwd ){ - zFull[nFull-1] = '\0'; - if( !winIsDriveLetterAndColon(zRelative) || !winIsDirSep(zRelative[2]) ){ - int rc = SQLITE_OK; - int nLink = 1; /* Number of symbolic links followed so far */ - const char *zIn = zRelative; /* Input path for each iteration of loop */ - char *zDel = 0; - struct stat buf; - - UNUSED_PARAMETER(pVfs); - - do { - /* Call lstat() on path zIn. Set bLink to true if the path is a symbolic - ** link, or false otherwise. */ - int bLink = 0; - if( osLstat && osReadlink ) { - if( osLstat(zIn, &buf)!=0 ){ - int myErrno = osErrno; - if( myErrno!=ENOENT ){ - rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno, "lstat", zIn); - } - }else{ - bLink = ((buf.st_mode & 0170000) == 0120000); - } - - if( bLink ){ - if( zDel==0 ){ - zDel = sqlite3MallocZero(nFull); - if( zDel==0 ) rc = SQLITE_NOMEM; - }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ - rc = SQLITE_CANTOPEN_BKPT; - } - - if( rc==SQLITE_OK ){ - nByte = osReadlink(zIn, zDel, nFull-1); - if( nByte ==(DWORD)-1 ){ - rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn); - }else{ - if( zDel[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nFull ){ - 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!=zFull || zIn[0]=='/' ); - if( rc==SQLITE_OK && zIn!=zFull ){ - rc = mkFullPathname(zIn, zFull, nFull); - } - if( bLink==0 ) break; - zIn = zFull; - }while( rc==SQLITE_OK ); - - sqlite3_free(zDel); - winSimplifyName(zFull); - return rc; - } - } -#endif /* __CYGWIN__ */ - -#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) - SimulateIOError( return SQLITE_ERROR ); - /* WinCE has no concept of a relative pathname, or so I am told. */ - /* WinRT has no way to convert a relative path to an absolute one. */ - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ - /* - ** NOTE: We are dealing with a relative path name and the data - ** directory has been set. Therefore, use it as the basis - ** for converting the relative path name to an absolute - ** one by prepending the data directory and a backslash. - */ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", - sqlite3_data_directory, winGetDirSep(), zRelative); - }else{ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); - } - return SQLITE_OK; -#endif - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT -#if defined(_WIN32) - /* 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 ); - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ - /* - ** NOTE: We are dealing with a relative path name and the data - ** directory has been set. Therefore, use it as the basis - ** for converting the relative path name to an absolute - ** one by prepending the data directory and a backslash. - */ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", - sqlite3_data_directory, winGetDirSep(), zRelative); - return SQLITE_OK; - } -#endif - zConverted = winConvertFromUtf8Filename(zRelative); - if( zConverted==0 ){ - return SQLITE_IOERR_NOMEM_BKPT; - } - if( osIsNT() ){ - LPWSTR zTemp; - nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); - if( nByte==0 ){ - sqlite3_free(zConverted); - return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), - "winFullPathname1", zRelative); - } - nByte += 3; - zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM_BKPT; - } - nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); - if( nByte==0 ){ - sqlite3_free(zConverted); - sqlite3_free(zTemp); - return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), - "winFullPathname2", zRelative); - } - sqlite3_free(zConverted); - zOut = winUnicodeToUtf8(zTemp); - sqlite3_free(zTemp); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - char *zTemp; - nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); - if( nByte==0 ){ - sqlite3_free(zConverted); - return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), - "winFullPathname3", zRelative); - } - zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) + 3*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM_BKPT; - } - nByte = osGetFullPathNameA((char*)zConverted, nByte+3, zTemp, 0); - if( nByte==0 ){ - sqlite3_free(zConverted); - sqlite3_free(zTemp); - return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), - "winFullPathname4", zRelative); - } - sqlite3_free(zConverted); - zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); - sqlite3_free(zTemp); - } -#endif - if( zOut ){ -#ifdef __CYGWIN__ - if( memcmp(zOut, "\\\\?\\", 4) ){ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); - }else if( memcmp(zOut+4, "UNC\\", 4) ){ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+4); - }else{ - char *p = zOut+6; - *p = '\\'; - if( osGetcwd ){ - /* On Cygwin, UNC paths use forward slashes */ - while( *p ){ - if( *p=='\\' ) *p = '/'; - ++p; - } - } - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+6); - } -#else - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); -#endif /* __CYGWIN__ */ - sqlite3_free(zOut); - return SQLITE_OK; - }else{ - return SQLITE_IOERR_NOMEM_BKPT; - } -#endif -} -static int winFullPathname( - 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; - MUTEX_LOGIC( sqlite3_mutex *pMutex; ) - MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); ) - sqlite3_mutex_enter(pMutex); - rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); - sqlite3_mutex_leave(pMutex); - return rc; -} - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** Interfaces for opening a shared library, finding entry points -** within the shared library, and closing the shared library. -*/ -static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ - HANDLE h; - void *zConverted = winConvertFromUtf8Filename(zFilename); - UNUSED_PARAMETER(pVfs); - if( zConverted==0 ){ - OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); - return 0; - } - if( osIsNT() ){ -#if SQLITE_OS_WINRT - h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); -#else - h = osLoadLibraryW((LPCWSTR)zConverted); -#endif - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - h = osLoadLibraryA((char*)zConverted); - } -#endif - OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h)); - sqlite3_free(zConverted); - return (void*)h; -} -static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ - UNUSED_PARAMETER(pVfs); - winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); -} -static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ - FARPROC proc; - UNUSED_PARAMETER(pVfs); - proc = osGetProcAddressA((HANDLE)pH, zSym); - OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n", - (void*)pH, zSym, (void*)proc)); - return (void(*)(void))proc; -} -static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ - UNUSED_PARAMETER(pVfs); - osFreeLibrary((HANDLE)pHandle); - OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle)); -} -#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ - #define winDlOpen 0 - #define winDlError 0 - #define winDlSym 0 - #define winDlClose 0 -#endif - -/* State information for the randomness gatherer. */ -typedef struct EntropyGatherer EntropyGatherer; -struct EntropyGatherer { - unsigned char *a; /* Gather entropy into this buffer */ - int na; /* Size of a[] in bytes */ - int i; /* XOR next input into a[i] */ - int nXor; /* Number of XOR operations done */ -}; - -#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) -/* Mix sz bytes of entropy into p. */ -static void xorMemory(EntropyGatherer *p, unsigned char *x, int sz){ - int j, k; - for(j=0, k=p->i; ja[k++] ^= x[j]; - if( k>=p->na ) k = 0; - } - p->i = k; - p->nXor += sz; -} -#endif /* !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) */ - -/* -** Write up to nBuf bytes of randomness into zBuf. -*/ -static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ -#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) - UNUSED_PARAMETER(pVfs); - memset(zBuf, 0, nBuf); - return nBuf; -#else - EntropyGatherer e; - UNUSED_PARAMETER(pVfs); - memset(zBuf, 0, nBuf); - e.a = (unsigned char*)zBuf; - e.na = nBuf; - e.nXor = 0; - e.i = 0; - { - SYSTEMTIME x; - osGetSystemTime(&x); - xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME)); - } - { - DWORD pid = osGetCurrentProcessId(); - xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD)); - } -#if SQLITE_OS_WINRT - { - ULONGLONG cnt = osGetTickCount64(); - xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG)); - } -#else - { - DWORD cnt = osGetTickCount(); - xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD)); - } -#endif /* SQLITE_OS_WINRT */ - { - LARGE_INTEGER i; - osQueryPerformanceCounter(&i); - xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER)); - } -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - { - UUID id; - memset(&id, 0, sizeof(UUID)); - osUuidCreate(&id); - xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); - memset(&id, 0, sizeof(UUID)); - osUuidCreateSequential(&id); - xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); - } -#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */ - return e.nXor>nBuf ? nBuf : e.nXor; -#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */ -} - - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -static int winSleep(sqlite3_vfs *pVfs, int microsec){ - sqlite3_win32_sleep((microsec+999)/1000); - UNUSED_PARAMETER(pVfs); - return ((microsec+999)/1000)*1000; -} - -/* -** The following variable, if set to a non-zero value, is interpreted as -** the number of seconds since 1970 and is used to set the result of -** sqlite3OsCurrentTime() during testing. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ -#endif - -/* -** Find the current time (in Universal Coordinated Time). Write into *piNow -** the current time and date as a Julian Day number times 86_400_000. In -** other words, write into *piNow the number of milliseconds since the Julian -** epoch of noon in Greenwich on November 24, 4714 B.C according to the -** proleptic Gregorian calendar. -** -** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date -** cannot be found. -*/ -static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ - /* FILETIME structure is a 64-bit value representing the number of - 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). - */ - FILETIME ft; - static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; -#ifdef SQLITE_TEST - static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; -#endif - /* 2^32 - to avoid use of LL and warnings in gcc */ - static const sqlite3_int64 max32BitValue = - (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + - (sqlite3_int64)294967296; - -#if SQLITE_OS_WINCE - SYSTEMTIME time; - osGetSystemTime(&time); - /* if SystemTimeToFileTime() fails, it returns zero. */ - if (!osSystemTimeToFileTime(&time,&ft)){ - return SQLITE_ERROR; - } -#else - osGetSystemTimeAsFileTime( &ft ); -#endif - - *piNow = winFiletimeEpoch + - ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + - (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; - -#ifdef SQLITE_TEST - if( sqlite3_current_time ){ - *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; - } -#endif - UNUSED_PARAMETER(pVfs); - return SQLITE_OK; -} - -/* -** Find the current time (in Universal Coordinated Time). Write the -** current time and date as a Julian Day number into *prNow and -** return 0. Return 1 if the time and date cannot be found. -*/ -static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ - int rc; - sqlite3_int64 i; - rc = winCurrentTimeInt64(pVfs, &i); - if( !rc ){ - *prNow = i/86400000.0; - } - return rc; -} - -/* -** The idea is that this function works like a combination of -** GetLastError() and FormatMessage() on Windows (or errno and -** strerror_r() on Unix). After an error is returned by an OS -** function, SQLite calls this function with zBuf pointing to -** a buffer of nBuf bytes. The OS layer should populate the -** buffer with a nul-terminated UTF-8 encoded error message -** describing the last IO error to have occurred within the calling -** thread. -** -** If the error message is too large for the supplied buffer, -** it should be truncated. The return value of xGetLastError -** is zero if the error message fits in the buffer, or non-zero -** otherwise (if the message was truncated). If non-zero is returned, -** then it is not necessary to include the nul-terminator character -** in the output buffer. -** -** Not supplying an error message will have no adverse effect -** on SQLite. It is fine to have an implementation that never -** returns an error message: -** -** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ -** assert(zBuf[0]=='\0'); -** return 0; -** } -** -** However if an error message is supplied, it will be incorporated -** by sqlite into the error message available to the user using -** sqlite3_errmsg(), possibly making IO errors easier to debug. -*/ -static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - DWORD e = osGetLastError(); - UNUSED_PARAMETER(pVfs); - if( nBuf>0 ) winGetLastErrorMsg(e, nBuf, zBuf); - return e; -} - -/* -** Initialize and deinitialize the operating system interface. -*/ -SQLITE_API int sqlite3_os_init(void){ - static sqlite3_vfs winVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ - SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32", /* zName */ - &winAppData, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ - }; -#if defined(SQLITE_WIN32_HAS_WIDE) - static sqlite3_vfs winLongPathVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ - SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32-longpath", /* zName */ - &winAppData, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ - }; -#endif - static sqlite3_vfs winNolockVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ - SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32-none", /* zName */ - &winNolockAppData, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ - }; -#if defined(SQLITE_WIN32_HAS_WIDE) - static sqlite3_vfs winLongPathNolockVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ - SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32-longpath-none", /* zName */ - &winNolockAppData, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ - }; -#endif - - /* Double-check that the aSyscall[] array has been constructed - ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==89 ); - - /* get memory map allocation granularity */ - memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); -#if SQLITE_OS_WINRT - osGetNativeSystemInfo(&winSysInfo); -#else - osGetSystemInfo(&winSysInfo); -#endif - assert( winSysInfo.dwAllocationGranularity>0 ); - assert( winSysInfo.dwPageSize>0 ); - - sqlite3_vfs_register(&winVfs, 1); - -#if defined(SQLITE_WIN32_HAS_WIDE) - sqlite3_vfs_register(&winLongPathVfs, 0); -#endif - - sqlite3_vfs_register(&winNolockVfs, 0); - -#if defined(SQLITE_WIN32_HAS_WIDE) - sqlite3_vfs_register(&winLongPathNolockVfs, 0); -#endif - -#ifndef SQLITE_OMIT_WAL - winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - - return SQLITE_OK; -} - -SQLITE_API int sqlite3_os_end(void){ -#if SQLITE_OS_WINRT - if( sleepObj!=NULL ){ - osCloseHandle(sleepObj); - sleepObj = NULL; - } -#endif - -#ifndef SQLITE_OMIT_WAL - winBigLock = 0; -#endif - - return SQLITE_OK; -} - -#endif /* SQLITE_OS_WIN */ - -/************** End of os_win.c **********************************************/ -/************** Begin file memdb.c *******************************************/ -/* -** 2016-09-07 -** -** 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 in-memory VFS. A database is held as a contiguous -** block of memory. -** -** This file also implements interface sqlite3_serialize() and -** sqlite3_deserialize(). -*/ -/* #include "sqliteInt.h" */ -#ifndef SQLITE_OMIT_DESERIALIZE - -/* -** Forward declaration of objects used by this utility -*/ -typedef struct 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) ((sqlite3_vfs*)((p)->pAppData)) - -/* 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 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 { - sqlite3_int64 sz; /* Size of the file */ - sqlite3_int64 szAlloc; /* Space allocated to aData */ - sqlite3_int64 szMax; /* Maximum allowed size of the file */ - unsigned char *aData; /* content of the file */ - 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 { - 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(sqlite3_file*); -static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); -static int memdbSync(sqlite3_file*, int flags); -static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int memdbLock(sqlite3_file*, int); -static int memdbUnlock(sqlite3_file*, int); -/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ -static int memdbFileControl(sqlite3_file*, int op, void *pArg); -/* static int memdbSectorSize(sqlite3_file*); // not used */ -static int memdbDeviceCharacteristics(sqlite3_file*); -static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); -static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); - -/* -** Methods for MemVfs -*/ -static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ -static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); -static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); -static void memdbDlClose(sqlite3_vfs*, void*); -static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int memdbSleep(sqlite3_vfs*, int microseconds); -/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ -static int memdbGetLastError(sqlite3_vfs*, int, char *); -static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs memdb_vfs = { - 2, /* iVersion */ - 0, /* szOsFile (set when registered) */ - 1024, /* mxPathname */ - 0, /* pNext */ - "memdb", /* zName */ - 0, /* pAppData (set when registered) */ - memdbOpen, /* xOpen */ - 0, /* memdbDelete, */ /* xDelete */ - memdbAccess, /* xAccess */ - memdbFullPathname, /* xFullPathname */ - memdbDlOpen, /* xDlOpen */ - memdbDlError, /* xDlError */ - memdbDlSym, /* xDlSym */ - memdbDlClose, /* xDlClose */ - memdbRandomness, /* xRandomness */ - memdbSleep, /* xSleep */ - 0, /* memdbCurrentTime, */ /* xCurrentTime */ - memdbGetLastError, /* xGetLastError */ - memdbCurrentTimeInt64, /* xCurrentTimeInt64 */ - 0, /* xSetSystemCall */ - 0, /* xGetSystemCall */ - 0, /* xNextSystemCall */ -}; - -static const sqlite3_io_methods memdb_io_methods = { - 3, /* iVersion */ - memdbClose, /* xClose */ - memdbRead, /* xRead */ - memdbWrite, /* xWrite */ - memdbTruncate, /* xTruncate */ - memdbSync, /* xSync */ - memdbFileSize, /* xFileSize */ - memdbLock, /* xLock */ - memdbUnlock, /* xUnlock */ - 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ - memdbFileControl, /* xFileControl */ - 0, /* memdbSectorSize,*/ /* xSectorSize */ - memdbDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - memdbFetch, /* xFetch */ - 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){ - sqlite3_mutex_enter(p->pMutex); -} -static void memdbLeave(MemStore *p){ - sqlite3_mutex_leave(p->pMutex); -} -#endif - - - -/* -** Close an memdb-file. -** Free the underlying MemStore object when its refcount drops to zero -** or less. -*/ -static int memdbClose(sqlite3_file *pFile){ - MemStore *p = ((MemFile*)pFile)->pStore; - if( p->zFName ){ - int i; -#ifndef SQLITE_MUTEX_OMIT - sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - sqlite3_mutex_enter(pVfsMutex); - for(i=0; ALWAYS(inRef==1 ){ - memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore]; - if( memdb_g.nMemStore==0 ){ - sqlite3_free(memdb_g.apMemStore); - memdb_g.apMemStore = 0; - } - } - break; - } - } - sqlite3_mutex_leave(pVfsMutex); - }else{ - memdbEnter(p); - } - p->nRef--; - if( p->nRef<=0 ){ - if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){ - sqlite3_free(p->aData); - } - memdbLeave(p); - sqlite3_mutex_free(p->pMutex); - sqlite3_free(p); - }else{ - memdbLeave(p); - } - return SQLITE_OK; -} - -/* -** Read data from an memdb-file. -*/ -static int memdbRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - if( iOfst+iAmt>p->sz ){ - memset(zBuf, 0, iAmt); - if( iOfstsz ) 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(MemStore *p, sqlite3_int64 newSz){ - unsigned char *pNew; - if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){ - return SQLITE_FULL; - } - if( newSz>p->szMax ){ - return SQLITE_FULL; - } - newSz *= 2; - if( newSz>p->szMax ) newSz = p->szMax; - pNew = sqlite3Realloc(p->aData, newSz); - if( pNew==0 ) return SQLITE_IOERR_NOMEM; - p->aData = pNew; - p->szAlloc = newSz; - return SQLITE_OK; -} - -/* -** Write data to an memdb-file. -*/ -static int memdbWrite( - sqlite3_file *pFile, - const void *z, - int iAmt, - sqlite_int64 iOfst -){ - 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; -} - -/* -** Truncate an memdb-file. -** -** In rollback mode (which is always the case for memdb, as it does not -** support WAL mode) the truncate() method is only used to reduce -** the size of a file, never to increase the size. -*/ -static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ - 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(sqlite3_file *pFile, int flags){ - UNUSED_PARAMETER(pFile); - UNUSED_PARAMETER(flags); - return SQLITE_OK; -} - -/* -** Return the current file-size of an memdb-file. -*/ -static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - *pSize = p->sz; - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Lock an memdb-file. -*/ -static int memdbLock(sqlite3_file *pFile, int eLock){ - MemFile *pThis = (MemFile*)pFile; - MemStore *p = pThis->pStore; - int rc = SQLITE_OK; - if( eLock<=pThis->eLock ) return SQLITE_OK; - memdbEnter(p); - - assert( p->nWrLock==0 || p->nWrLock==1 ); - assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 ); - assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 ); - - if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){ - rc = SQLITE_READONLY; - }else{ - switch( eLock ){ - case SQLITE_LOCK_SHARED: { - assert( pThis->eLock==SQLITE_LOCK_NONE ); - if( p->nWrLock>0 ){ - rc = SQLITE_BUSY; - }else{ - p->nRdLock++; - } - break; - }; - - case SQLITE_LOCK_RESERVED: - case SQLITE_LOCK_PENDING: { - assert( pThis->eLock>=SQLITE_LOCK_SHARED ); - if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){ - if( p->nWrLock>0 ){ - rc = SQLITE_BUSY; - }else{ - p->nWrLock = 1; - } - } - break; - } - - default: { - assert( eLock==SQLITE_LOCK_EXCLUSIVE ); - assert( pThis->eLock>=SQLITE_LOCK_SHARED ); - if( p->nRdLock>1 ){ - rc = SQLITE_BUSY; - }else if( pThis->eLock==SQLITE_LOCK_SHARED ){ - p->nWrLock = 1; - } - break; - } - } - } - if( rc==SQLITE_OK ) pThis->eLock = eLock; - memdbLeave(p); - return rc; -} - -/* -** Unlock an memdb-file. -*/ -static int memdbUnlock(sqlite3_file *pFile, int eLock){ - MemFile *pThis = (MemFile*)pFile; - MemStore *p = pThis->pStore; - if( eLock>=pThis->eLock ) return SQLITE_OK; - memdbEnter(p); - - assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE ); - if( eLock==SQLITE_LOCK_SHARED ){ - if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){ - p->nWrLock--; - } - }else{ - if( pThis->eLock>SQLITE_LOCK_SHARED ){ - p->nWrLock--; - } - p->nRdLock--; - } - - pThis->eLock = eLock; - memdbLeave(p); - return SQLITE_OK; -} - -#if 0 -/* -** This interface is only used for crash recovery, which does not -** occur on an in-memory database. -*/ -static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - *pResOut = 0; - return SQLITE_OK; -} -#endif - - -/* -** File control method. For custom operations on an memdb-file. -*/ -static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ - MemStore *p = ((MemFile*)pFile)->pStore; - int rc = SQLITE_NOTFOUND; - memdbEnter(p); - if( op==SQLITE_FCNTL_VFSNAME ){ - *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); - rc = SQLITE_OK; - } - if( op==SQLITE_FCNTL_SIZE_LIMIT ){ - sqlite3_int64 iLimit = *(sqlite3_int64*)pArg; - if( iLimitsz ){ - if( iLimit<0 ){ - iLimit = p->szMax; - }else{ - iLimit = p->sz; - } - } - p->szMax = iLimit; - *(sqlite3_int64*)pArg = iLimit; - rc = SQLITE_OK; - } - memdbLeave(p); - return rc; -} - -#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ -/* -** Return the sector-size in bytes for an memdb-file. -*/ -static int memdbSectorSize(sqlite3_file *pFile){ - return 1024; -} -#endif - -/* -** Return the device characteristic flags supported by an memdb-file. -*/ -static int memdbDeviceCharacteristics(sqlite3_file *pFile){ - UNUSED_PARAMETER(pFile); - return SQLITE_IOCAP_ATOMIC | - SQLITE_IOCAP_POWERSAFE_OVERWRITE | - SQLITE_IOCAP_SAFE_APPEND | - SQLITE_IOCAP_SEQUENTIAL; -} - -/* Fetch a page of a memory-mapped file */ -static int memdbFetch( - sqlite3_file *pFile, - sqlite3_int64 iOfst, - int iAmt, - void **pp -){ - 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(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ - MemStore *p = ((MemFile*)pFile)->pStore; - UNUSED_PARAMETER(iOfst); - UNUSED_PARAMETER(pPage); - memdbEnter(p); - p->nMmap--; - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Open an mem file handle. -*/ -static int memdbOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFd, - int flags, - int *pOutFlags -){ - MemFile *pFile = (MemFile*)pFd; - MemStore *p = 0; - int szName; - UNUSED_PARAMETER(pVfs); - - memset(pFile, 0, sizeof(*pFile)); - szName = sqlite3Strlen30(zName); - if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){ - int i; -#ifndef SQLITE_MUTEX_OMIT - sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - sqlite3_mutex_enter(pVfsMutex); - for(i=0; izFName,zName)==0 ){ - p = memdb_g.apMemStore[i]; - break; - } - } - if( p==0 ){ - MemStore **apNew; - p = sqlite3Malloc( sizeof(*p) + (i64)szName + 3 ); - if( p==0 ){ - sqlite3_mutex_leave(pVfsMutex); - return SQLITE_NOMEM; - } - apNew = sqlite3Realloc(memdb_g.apMemStore, - sizeof(apNew[0])*(1+(i64)memdb_g.nMemStore) ); - if( apNew==0 ){ - sqlite3_free(p); - 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 = sqlite3GlobalConfig.mxMemdbSize; - p->zFName = (char*)&p[1]; - memcpy(p->zFName, zName, szName+1); - p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( p->pMutex==0 ){ - memdb_g.nMemStore--; - sqlite3_free(p); - sqlite3_mutex_leave(pVfsMutex); - return SQLITE_NOMEM; - } - p->nRef = 1; - memdbEnter(p); - }else{ - memdbEnter(p); - p->nRef++; - } - sqlite3_mutex_leave(pVfsMutex); - }else{ - p = sqlite3Malloc( sizeof(*p) ); - if( p==0 ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(*p)); - p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; - p->szMax = sqlite3GlobalConfig.mxMemdbSize; - } - pFile->pStore = p; - if( pOutFlags!=0 ){ - *pOutFlags = flags | SQLITE_OPEN_MEMORY; - } - pFd->pMethods = &memdb_io_methods; - memdbLeave(p); - return SQLITE_OK; -} - -#if 0 /* Only used to delete rollback journals, super-journals, and WAL - ** files, none of which exist in memdb. So this routine is never used */ -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return SQLITE_IOERR_DELETE; -} -#endif - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -** -** With memdb, no files ever exist on disk. So always return false. -*/ -static int memdbAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - UNUSED_PARAMETER(pVfs); - UNUSED_PARAMETER(zPath); - UNUSED_PARAMETER(flags); - *pResOut = 0; - return SQLITE_OK; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (INST_MAX_PATHNAME+1) bytes. -*/ -static int memdbFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - UNUSED_PARAMETER(pVfs); - sqlite3_snprintf(nOut, zOut, "%s", zPath); - return SQLITE_OK; -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ - ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ - return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); -} - -#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); -} -#endif - -static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ - return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); -} -static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ - return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); -} - -/* -** Translate a database connection pointer and schema name into a -** MemFile pointer. -*/ -static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ - MemFile *p = 0; - MemStore *pStore; - int rc = 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; -} - -/* -** Return the serialization of a database -*/ -SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which database within the connection */ - sqlite3_int64 *piSize, /* Write size here, if not NULL */ - unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ -){ - MemFile *p; - int iDb; - Btree *pBt; - sqlite3_int64 sz; - int szPage = 0; - sqlite3_stmt *pStmt = 0; - unsigned char *pOut; - char *zSql; - int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - - if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; - p = memdbFromDbSchema(db, zSchema); - iDb = sqlite3FindDbName(db, zSchema); - if( piSize ) *piSize = -1; - if( iDb<0 ) return 0; - if( p ){ - MemStore *pStore = p->pStore; - assert( pStore->pMutex==0 ); - if( piSize ) *piSize = pStore->sz; - if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ - pOut = pStore->aData; - }else{ - pOut = sqlite3_malloc64( pStore->sz ); - if( pOut ) memcpy(pOut, pStore->aData, pStore->sz); - } - return pOut; - } - pBt = db->aDb[iDb].pBt; - if( pBt==0 ) return 0; - szPage = sqlite3BtreeGetPageSize(pBt); - zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); - rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; - sqlite3_free(zSql); - if( rc ) return 0; - rc = sqlite3_step(pStmt); - if( rc!=SQLITE_ROW ){ - pOut = 0; - }else{ - sz = sqlite3_column_int64(pStmt, 0)*szPage; - if( sz==0 ){ - sqlite3_reset(pStmt); - sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - sz = sqlite3_column_int64(pStmt, 0)*szPage; - } - } - if( piSize ) *piSize = sz; - if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ - pOut = 0; - }else{ - pOut = sqlite3_malloc64( sz ); - if( pOut ){ - int nPage = sqlite3_column_int(pStmt, 0); - Pager *pPager = sqlite3BtreePager(pBt); - int pgno; - for(pgno=1; pgno<=nPage; pgno++){ - DbPage *pPage = 0; - unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); - rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); - if( rc==SQLITE_OK ){ - memcpy(pTo, sqlite3PagerGetData(pPage), szPage); - }else{ - memset(pTo, 0, szPage); - } - sqlite3PagerUnref(pPage); - } - } - } - } - sqlite3_finalize(pStmt); - return pOut; -} - -/* Convert zSchema to a MemDB and initialize its content. -*/ -SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ -){ - MemFile *p; - char *zSql; - sqlite3_stmt *pStmt = 0; - int rc; - int iDb; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( szDb<0 ) return SQLITE_MISUSE_BKPT; - if( szBuf<0 ) return SQLITE_MISUSE_BKPT; -#endif - - sqlite3_mutex_enter(db->mutex); - if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; - iDb = sqlite3FindDbName(db, zSchema); - testcase( iDb==1 ); - if( iDb<2 && iDb!=0 ){ - rc = SQLITE_ERROR; - goto end_deserialize; - } - zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - if( rc ) goto end_deserialize; - db->init.iDb = (u8)iDb; - db->init.reopenMemdb = 1; - rc = sqlite3_step(pStmt); - db->init.reopenMemdb = 0; - if( rc!=SQLITE_DONE ){ - rc = SQLITE_ERROR; - goto end_deserialize; - } - p = memdbFromDbSchema(db, zSchema); - if( p==0 ){ - rc = SQLITE_ERROR; - }else{ - MemStore *pStore = p->pStore; - pStore->aData = pData; - pData = 0; - pStore->sz = szDb; - pStore->szAlloc = szBuf; - pStore->szMax = szBuf; - if( pStore->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize; - } - pStore->mFlags = mFlags; - rc = SQLITE_OK; - } - -end_deserialize: - sqlite3_finalize(pStmt); - if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){ - sqlite3_free(pData); - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Return true if the VFS is the memvfs. -*/ -SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs *pVfs){ - return pVfs==&memdb_vfs; -} - -/* -** This routine is called when the extension is loaded. -** Register the new VFS. -*/ -SQLITE_PRIVATE int sqlite3MemdbInit(void){ - sqlite3_vfs *pLower = sqlite3_vfs_find(0); - 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 - ** it in, to be safe, but it is marked as NO_TEST since there - ** is no way to reach it under most builds. */ - if( szBITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is -** a hash table that will hold up to BITVEC_MXHASH distinct values. -** -** Otherwise, the value i is redirected into one of BITVEC_NPTR -** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap -** handles up to iDivisor separate values of i. apSub[0] holds -** values between 1 and iDivisor. apSub[1] holds values between -** iDivisor+1 and 2*iDivisor. apSub[N] holds values between -** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized -** to hold deal with values between 1 and iDivisor. -*/ -struct Bitvec { - u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */ - u32 nSet; /* Number of bits that are set - only valid for aHash - ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512, - ** this would be 125. */ - u32 iDivisor; /* Number of bits handled by each apSub[] entry. */ - /* Should >=0 for apSub element. */ - /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */ - /* For a BITVEC_SZ of 512, this would be 34,359,739. */ - union { - BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ - u32 aHash[BITVEC_NINT]; /* Hash table representation */ - Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ - } u; -}; - -/* -** Create a new bitmap object able to handle bits between 0 and iSize, -** inclusive. Return a pointer to the new object. Return NULL if -** malloc fails. -*/ -SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){ - Bitvec *p; - assert( sizeof(*p)==BITVEC_SZ ); - p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ - p->iSize = iSize; - } - return p; -} - -/* -** Check to see if the i-th bit is set. Return true or false. -** If p is NULL (if the bitmap has not been created) or if -** i is out of range, then return false. -*/ -SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){ - assert( p!=0 ); - i--; - if( i>=p->iSize ) return 0; - while( p->iDivisor ){ - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - p = p->u.apSub[bin]; - if (!p) { - return 0; - } - } - if( p->iSize<=BITVEC_NBIT ){ - return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; - } else{ - u32 h = BITVEC_HASH(i++); - while( p->u.aHash[h] ){ - if( p->u.aHash[h]==i ) return 1; - h = (h+1) % BITVEC_NINT; - } - return 0; - } -} -SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ - return p!=0 && sqlite3BitvecTestNotNull(p,i); -} - -/* -** Set the i-th bit. Return 0 on success and an error code if -** anything goes wrong. -** -** This routine might cause sub-bitmaps to be allocated. Failing -** to get the memory needed to hold the sub-bitmap is the only -** that can go wrong with an insert, assuming p and i are valid. -** -** The calling function must ensure that p is a valid Bitvec object -** and that the value for "i" is within range of the Bitvec object. -** Otherwise the behavior is undefined. -*/ -SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ - u32 h; - if( p==0 ) return SQLITE_OK; - assert( i>0 ); - assert( i<=p->iSize ); - i--; - while((p->iSize > BITVEC_NBIT) && p->iDivisor) { - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - if( p->u.apSub[bin]==0 ){ - p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); - if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM_BKPT; - } - p = p->u.apSub[bin]; - } - if( p->iSize<=BITVEC_NBIT ){ - p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1)); - return SQLITE_OK; - } - h = BITVEC_HASH(i++); - /* if there wasn't a hash collision, and this doesn't */ - /* completely fill the hash, then just add it without */ - /* worrying about sub-dividing and re-hashing. */ - if( !p->u.aHash[h] ){ - if (p->nSet<(BITVEC_NINT-1)) { - goto bitvec_set_end; - } else { - goto bitvec_set_rehash; - } - } - /* there was a collision, check to see if it's already */ - /* in hash, if not, try to find a spot for it */ - do { - if( p->u.aHash[h]==i ) return SQLITE_OK; - h++; - if( h>=BITVEC_NINT ) h = 0; - } while( p->u.aHash[h] ); - /* we didn't find it in the hash. h points to the first */ - /* available free spot. check to see if this is going to */ - /* make our hash too "full". */ -bitvec_set_rehash: - if( p->nSet>=BITVEC_MXHASH ){ - unsigned int j; - int rc; - u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); - if( aiValues==0 ){ - return SQLITE_NOMEM_BKPT; - }else{ - memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); - memset(p->u.apSub, 0, sizeof(p->u.apSub)); - p->iDivisor = p->iSize/BITVEC_NPTR; - if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++; - if( p->iDivisoriDivisor = BITVEC_NBIT; - rc = sqlite3BitvecSet(p, i); - for(j=0; jnSet++; - p->u.aHash[h] = i; - return SQLITE_OK; -} - -/* -** Clear the i-th bit. -** -** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage -** that BitvecClear can use to rebuilt its hash table. -*/ -SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){ - if( p==0 ) return; - assert( i>0 ); - i--; - while( p->iDivisor ){ - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - p = p->u.apSub[bin]; - if (!p) { - return; - } - } - if( p->iSize<=BITVEC_NBIT ){ - p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1))); - }else{ - unsigned int j; - u32 *aiValues = pBuf; - memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); - memset(p->u.aHash, 0, sizeof(p->u.aHash)); - p->nSet = 0; - for(j=0; jnSet++; - while( p->u.aHash[h] ){ - h++; - if( h>=BITVEC_NINT ) h = 0; - } - p->u.aHash[h] = aiValues[j]; - } - } - } -} - -/* -** Destroy a bitmap object. Reclaim all memory used. -*/ -SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){ - if( p==0 ) return; - if( p->iDivisor ){ - unsigned int i; - for(i=0; iu.apSub[i]); - } - } - sqlite3_free(p); -} - -/* -** Return the value of the iSize parameter specified when Bitvec *p -** was created. -*/ -SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ - return p->iSize; -} - -#ifndef SQLITE_UNTESTABLE -/* -** Let V[] be an array of unsigned characters sufficient to hold -** up to N bits. Let I be an integer between 0 and N. 0<=I>3] |= (1<<(I&7)) -#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7)) -#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 - -/* -** This routine runs an extensive test of the Bitvec code. -** -** The input is an array of integers that acts as a program -** to test the Bitvec. The integers are opcodes followed -** by 0, 1, or 3 operands, depending on the opcode. Another -** opcode follows immediately after the last operand. -** -** There are 6 opcodes numbered from 0 through 5. 0 is the -** "halt" opcode and causes the test to end. -** -** 0 Halt and return the number of errors -** 1 N S X Set N bits beginning with S and incrementing by X -** 2 N S X Clear N bits beginning with S and incrementing by X -** 3 N Set N randomly chosen bits -** 4 N Clear N randomly chosen bits -** 5 N S X Set N bits from S increment X in array only, not in bitvec -** -** The opcodes 1 through 4 perform set and clear operations are performed -** on both a Bitvec object and on a linear array of bits obtained from malloc. -** Opcode 5 works on the linear array only, not on the Bitvec. -** Opcode 5 is used to deliberately induce a fault in order to -** confirm that error detection works. -** -** At the conclusion of the test the linear array is compared -** against the Bitvec object. If there are any differences, -** an error is returned. If they are the same, zero is returned. -** -** If a memory allocation error occurs, return -1. -*/ -SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ - Bitvec *pBitvec = 0; - unsigned char *pV = 0; - int rc = -1; - int i, nx, pc, op; - void *pTmpSpace; - - /* Allocate the Bitvec to be tested and a linear array of - ** bits to act as the reference */ - pBitvec = sqlite3BitvecCreate( sz ); - pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 ); - pTmpSpace = sqlite3_malloc64(BITVEC_SZ); - if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; - - /* NULL pBitvec tests */ - sqlite3BitvecSet(0, 1); - sqlite3BitvecClear(0, 1, pTmpSpace); - - /* Run the program */ - pc = i = 0; - while( (op = aOp[pc])!=0 ){ - switch( op ){ - case 1: - case 2: - case 5: { - nx = 4; - i = aOp[pc+2] - 1; - aOp[pc+2] += aOp[pc+3]; - break; - } - case 3: - case 4: - default: { - nx = 2; - sqlite3_randomness(sizeof(i), &i); - break; - } - } - if( (--aOp[pc+1]) > 0 ) nx = 0; - pc += nx; - i = (i & 0x7fffffff)%sz; - if( (op & 1)!=0 ){ - SETBIT(pV, (i+1)); - if( op!=5 ){ - if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; - } - }else{ - CLEARBIT(pV, (i+1)); - sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); - } - } - - /* Test to make sure the linear array exactly matches the - ** Bitvec object. Start with the assumption that they do - ** match (rc==0). Change rc to non-zero if a discrepancy - ** is found. - */ - rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) - + sqlite3BitvecTest(pBitvec, 0) - + (sqlite3BitvecSize(pBitvec) - sz); - for(i=1; i<=sz; i++){ - if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ - rc = i; - break; - } - } - - /* Free allocated structure */ -bitvec_end: - sqlite3_free(pTmpSpace); - sqlite3_free(pV); - sqlite3BitvecDestroy(pBitvec); - return rc; -} -#endif /* SQLITE_UNTESTABLE */ - -/************** End of bitvec.c **********************************************/ -/************** Begin file pcache.c ******************************************/ -/* -** 2008 August 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements that page cache. -*/ -/* #include "sqliteInt.h" */ - -/* -** A complete page cache is an instance of this structure. Every -** entry in the cache holds a single page of the database file. The -** btree layer only operates on the cached copy of the database pages. -** -** A page cache entry is "clean" if it exactly matches what is currently -** on disk. A page is "dirty" if it has been modified and needs to be -** persisted to disk. -** -** pDirty, pDirtyTail, pSynced: -** All dirty pages are linked into the doubly linked list using -** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order -** such that p was added to the list more recently than p->pDirtyNext. -** PCache.pDirty points to the first (newest) element in the list and -** pDirtyTail to the last (oldest). -** -** The PCache.pSynced variable is used to optimize searching for a dirty -** page to eject from the cache mid-transaction. It is better to eject -** a page that does not require a journal sync than one that does. -** Therefore, pSynced is maintained so that it *almost* always points -** to either the oldest page in the pDirty/pDirtyTail list that has a -** clear PGHDR_NEED_SYNC flag or to a page that is older than this one -** (so that the right page to eject can be found by following pDirtyPrev -** pointers). -*/ -struct PCache { - PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ - PgHdr *pSynced; /* Last synced page in dirty page list */ - i64 nRefSum; /* Sum of ref counts over all pages */ - int szCache; /* Configured cache size */ - int szSpill; /* Size before spilling occurs */ - int szPage; /* Size of every page in this cache */ - int szExtra; /* Size of extra space for each page */ - u8 bPurgeable; /* True if pages are on backing store */ - u8 eCreate; /* eCreate value for for xFetch() */ - int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ - void *pStress; /* Argument to xStress */ - sqlite3_pcache *pCache; /* Pluggable cache module */ -}; - -/********************************** Test and Debug Logic **********************/ -/* -** Debug tracing macros. Enable by by changing the "0" to "1" and -** recompiling. -** -** When sqlite3PcacheTrace is 1, single line trace messages are issued. -** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries -** is displayed for many operations, resulting in a lot of output. -*/ -#if defined(SQLITE_DEBUG) && 0 - int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ - int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ -# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} - static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){ - PgHdr *pPg; - unsigned char *a; - int j; - if( pLower==0 ){ - printf("%3d: NULL\n", i); - }else{ - pPg = (PgHdr*)pLower->pExtra; - printf("%3d: nRef %2lld flgs %02x data ", i, pPg->nRef, pPg->flags); - a = (unsigned char *)pLower->pBuf; - for(j=0; j<12; j++) printf("%02x", a[j]); - printf(" ptr %p\n", pPg); - } - } - static void pcacheDump(PCache *pCache){ - int N; - int i; - sqlite3_pcache_page *pLower; - - if( sqlite3PcacheTrace<2 ) return; - if( pCache->pCache==0 ) return; - N = sqlite3PcachePagecount(pCache); - if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; - for(i=1; i<=N; i++){ - pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); - pcachePageTrace(i, pLower); - if( pLower && ((PgHdr*)pLower)->pPage==0 ){ - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); - } - } - } -#else -# define pcacheTrace(X) -# define pcachePageTrace(PGNO, X) -# define pcacheDump(X) -#endif - -/* -** Return 1 if pPg is on the dirty list for pCache. Return 0 if not. -** This routine runs inside of assert() statements only. -*/ -#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) -static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - if( p==pPg ) return 1; - } - return 0; -} -static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - if( p==pPg ) return 0; - } - return 1; -} -#else -# define pageOnDirtyList(A,B) 1 -# define pageNotOnDirtyList(A,B) 1 -#endif - -/* -** Check invariants on a PgHdr entry. Return true if everything is OK. -** Return false if any invariant is violated. -** -** This routine is for use inside of assert() statements only. For -** example: -** -** assert( sqlite3PcachePageSanity(pPg) ); -*/ -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ - PCache *pCache; - assert( pPg!=0 ); - assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ - pCache = pPg->pCache; - assert( pCache!=0 ); /* Every page has an associated PCache */ - if( pPg->flags & PGHDR_CLEAN ){ - assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ - assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */ - }else{ - assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */ - assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg ); - assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg ); - assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg ); - assert( pageOnDirtyList(pCache, pPg) ); - } - /* WRITEABLE pages must also be DIRTY */ - if( pPg->flags & PGHDR_WRITEABLE ){ - assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */ - } - /* NEED_SYNC can be set independently of WRITEABLE. This can happen, - ** for example, when using the sqlite3PagerDontWrite() optimization: - ** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK. - ** (2) Page X moved to freelist, WRITEABLE is cleared - ** (3) Page X reused, WRITEABLE is set again - ** If NEED_SYNC had been cleared in step 2, then it would not be reset - ** in step 3, and page might be written into the database without first - ** syncing the rollback journal, which might cause corruption on a power - ** loss. - ** - ** Another example is when the database page size is smaller than the - ** disk sector size. When any page of a sector is journalled, all pages - ** in that sector are marked NEED_SYNC even if they are still CLEAN, just - ** in case they are later modified, since all pages in the same sector - ** must be journalled and synced before any of those pages can be safely - ** written. - */ - return 1; -} -#endif /* SQLITE_DEBUG */ - - -/********************************** Linked List Management ********************/ - -/* Allowed values for second argument to pcacheManageDirtyList() */ -#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ -#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */ -#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */ - -/* -** Manage pPage's participation on the dirty list. Bits of the addRemove -** argument determines what operation to do. The 0x01 bit means first -** remove pPage from the dirty list. The 0x02 means add pPage back to -** the dirty list. Doing both moves pPage to the front of the dirty list. -*/ -static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ - PCache *p = pPage->pCache; - - pcacheTrace(("%p.DIRTYLIST.%s %d\n", p, - addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT", - pPage->pgno)); - if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ - assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); - assert( pPage->pDirtyPrev || pPage==p->pDirty ); - - /* Update the PCache1.pSynced variable if necessary. */ - if( p->pSynced==pPage ){ - p->pSynced = pPage->pDirtyPrev; - } - - if( pPage->pDirtyNext ){ - pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; - }else{ - assert( pPage==p->pDirtyTail ); - p->pDirtyTail = pPage->pDirtyPrev; - } - if( pPage->pDirtyPrev ){ - pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; - }else{ - /* If there are now no dirty pages in the cache, set eCreate to 2. - ** This is an optimization that allows sqlite3PcacheFetch() to skip - ** searching for a dirty page to eject from the cache when it might - ** otherwise have to. */ - assert( pPage==p->pDirty ); - p->pDirty = pPage->pDirtyNext; - assert( p->bPurgeable || p->eCreate==2 ); - if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/ - assert( p->bPurgeable==0 || p->eCreate==1 ); - p->eCreate = 2; - } - } - } - if( addRemove & PCACHE_DIRTYLIST_ADD ){ - pPage->pDirtyPrev = 0; - pPage->pDirtyNext = p->pDirty; - if( pPage->pDirtyNext ){ - assert( pPage->pDirtyNext->pDirtyPrev==0 ); - pPage->pDirtyNext->pDirtyPrev = pPage; - }else{ - p->pDirtyTail = pPage; - if( p->bPurgeable ){ - assert( p->eCreate==2 ); - p->eCreate = 1; - } - } - p->pDirty = pPage; - - /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set - ** pSynced to point to it. Checking the NEED_SYNC flag is an - ** optimization, as if pSynced points to a page with the NEED_SYNC - ** flag set sqlite3PcacheFetchStress() searches through all newer - ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */ - if( !p->pSynced - && 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/ - ){ - p->pSynced = pPage; - } - } - pcacheDump(p); -} - -/* -** Wrapper around the pluggable caches xUnpin method. If the cache is -** being used for an in-memory database, this function is a no-op. -*/ -static void pcacheUnpin(PgHdr *p){ - if( p->pCache->bPurgeable ){ - pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno)); - sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); - pcacheDump(p->pCache); - } -} - -/* -** Compute the number of pages of cache requested. p->szCache is the -** cache size requested by the "PRAGMA cache_size" statement. -*/ -static int numberOfCachePages(PCache *p){ - if( p->szCache>=0 ){ - /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the - ** suggested cache size is set to N. */ - return p->szCache; - }else{ - i64 n; - /* IMPLEMENTATION-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. */ - n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); - if( n>1000000000 ) n = 1000000000; - return (int)n; - } -} - -/*************************************************** General Interfaces ****** -** -** Initialize and shutdown the page cache subsystem. Neither of these -** functions are threadsafe. -*/ -SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ - if( sqlite3GlobalConfig.pcache2.xInit==0 ){ - /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the - ** built-in default page cache is used instead of the application defined - ** page cache. */ - sqlite3PCacheSetDefault(); - assert( sqlite3GlobalConfig.pcache2.xInit!=0 ); - } - return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); -} -SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ - if( sqlite3GlobalConfig.pcache2.xShutdown ){ - /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ - sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg); - } -} - -/* -** Return the size in bytes of a PCache object. -*/ -SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } - -/* -** Create a new PCache object. Storage space to hold the object -** has already been allocated and is passed in as the p pointer. -** The caller discovers how much space needs to be allocated by -** calling sqlite3PcacheSize(). -** -** szExtra is some extra space allocated for each page. The first -** 8 bytes of the extra space will be zeroed as the page is allocated, -** but remaining content will be uninitialized. Though it is opaque -** to this module, the extra space really ends up being the MemPage -** structure in the pager. -*/ -SQLITE_PRIVATE int sqlite3PcacheOpen( - int szPage, /* Size of every page */ - int szExtra, /* Extra space associated with each page */ - int bPurgeable, /* True if pages are on backing store */ - int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */ - void *pStress, /* Argument to xStress */ - PCache *p /* Preallocated space for the PCache */ -){ - memset(p, 0, sizeof(PCache)); - p->szPage = 1; - p->szExtra = szExtra; - assert( szExtra>=8 ); /* First 8 bytes will be zeroed */ - p->bPurgeable = bPurgeable; - p->eCreate = 2; - p->xStress = xStress; - p->pStress = pStress; - p->szCache = 100; - p->szSpill = 1; - pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable)); - return sqlite3PcacheSetPageSize(p, szPage); -} - -/* -** Change the page size for PCache object. The caller must ensure that there -** are no outstanding page references when this function is called. -*/ -SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ - assert( pCache->nRefSum==0 && pCache->pDirty==0 ); - if( pCache->szPage ){ - sqlite3_pcache *pNew; - pNew = sqlite3GlobalConfig.pcache2.xCreate( - szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), - pCache->bPurgeable - ); - if( pNew==0 ) return SQLITE_NOMEM_BKPT; - sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); - } - pCache->pCache = pNew; - pCache->szPage = szPage; - pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage)); - } - return SQLITE_OK; -} - -/* -** Try to obtain a page from the cache. -** -** This routine returns a pointer to an sqlite3_pcache_page object if -** such an object is already in cache, or if a new one is created. -** This routine returns a NULL pointer if the object was not in cache -** and could not be created. -** -** The createFlags should be 0 to check for existing pages and should -** be 3 (not 1, but 3) to try to create a new page. -** -** If the createFlag is 0, then NULL is always returned if the page -** is not already in the cache. If createFlag is 1, then a new page -** is created only if that can be done without spilling dirty pages -** and without exceeding the cache size limit. -** -** The caller needs to invoke sqlite3PcacheFetchFinish() to properly -** initialize the sqlite3_pcache_page object and convert it into a -** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish() -** routines are split this way for performance reasons. When separated -** they can both (usually) operate without having to push values to -** the stack on entry and pop them back off on exit, which saves a -** lot of pushing and popping. -*/ -SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number to obtain */ - int createFlag /* If true, create page if it does not exist already */ -){ - int eCreate; - sqlite3_pcache_page *pRes; - - assert( pCache!=0 ); - assert( pCache->pCache!=0 ); - assert( createFlag==3 || createFlag==0 ); - assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) ); - - /* eCreate defines what to do if the page does not exist. - ** 0 Do not allocate a new page. (createFlag==0) - ** 1 Allocate a new page if doing so is inexpensive. - ** (createFlag==1 AND bPurgeable AND pDirty) - ** 2 Allocate a new page even it doing so is difficult. - ** (createFlag==1 AND !(bPurgeable AND pDirty) - */ - eCreate = createFlag & pCache->eCreate; - assert( eCreate==0 || eCreate==1 || eCreate==2 ); - assert( createFlag==0 || pCache->eCreate==eCreate ); - assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); - pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); - pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno, - createFlag?" create":"",pRes)); - pcachePageTrace(pgno, pRes); - return pRes; -} - -/* -** If the sqlite3PcacheFetch() routine is unable to allocate a new -** page because no clean pages are available for reuse and the cache -** size limit has been reached, then this routine can be invoked to -** try harder to allocate a page. This routine might invoke the stress -** callback to spill dirty pages to the journal. It will then try to -** allocate the new page and will only fail to allocate a new page on -** an OOM error. -** -** This routine should be invoked only after sqlite3PcacheFetch() fails. -*/ -SQLITE_PRIVATE int sqlite3PcacheFetchStress( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number to obtain */ - sqlite3_pcache_page **ppPage /* Write result here */ -){ - PgHdr *pPg; - if( pCache->eCreate==2 ) return 0; - - if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){ - /* Find a dirty page to write-out and recycle. First try to find a - ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC - ** cleared), but if that is not possible settle for any other - ** unreferenced dirty page. - ** - ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC - ** flag is currently referenced, then the following may leave pSynced - ** set incorrectly (pointing to other than the LRU page with NEED_SYNC - ** cleared). This is Ok, as pSynced is just an optimization. */ - for(pPg=pCache->pSynced; - pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); - pPg=pPg->pDirtyPrev - ); - pCache->pSynced = pPg; - if( !pPg ){ - for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); - } - if( pPg ){ - int rc; -#ifdef SQLITE_LOG_CACHE_SPILL - sqlite3_log(SQLITE_FULL, - "spill page %d making room for %d - cache used: %d/%d", - pPg->pgno, pgno, - sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache), - numberOfCachePages(pCache)); -#endif - pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); - rc = pCache->xStress(pCache->pStress, pPg); - pcacheDump(pCache); - if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - return rc; - } - } - } - *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); - return *ppPage==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK; -} - -/* -** This is a helper routine for sqlite3PcacheFetchFinish() -** -** In the uncommon case where the page being fetched has not been -** initialized, this routine is invoked to do the initialization. -** This routine is broken out into a separate function since it -** requires extra stack manipulation that can be avoided in the common -** case. -*/ -static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number obtained */ - sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ -){ - PgHdr *pPgHdr; - assert( pPage!=0 ); - pPgHdr = (PgHdr*)pPage->pExtra; - assert( pPgHdr->pPage==0 ); - memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); - pPgHdr->pPage = pPage; - pPgHdr->pData = pPage->pBuf; - pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, 8); - assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) ); - pPgHdr->pCache = pCache; - pPgHdr->pgno = pgno; - pPgHdr->flags = PGHDR_CLEAN; - return sqlite3PcacheFetchFinish(pCache,pgno,pPage); -} - -/* -** This routine converts the sqlite3_pcache_page object returned by -** sqlite3PcacheFetch() into an initialized PgHdr object. This routine -** must be called after sqlite3PcacheFetch() in order to get a usable -** result. -*/ -SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number obtained */ - sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ -){ - PgHdr *pPgHdr; - - assert( pPage!=0 ); - pPgHdr = (PgHdr *)pPage->pExtra; - - if( !pPgHdr->pPage ){ - return pcacheFetchFinishWithInit(pCache, pgno, pPage); - } - pCache->nRefSum++; - pPgHdr->nRef++; - assert( sqlite3PcachePageSanity(pPgHdr) ); - return pPgHdr; -} - -/* -** Decrement the reference count on a page. If the page is clean and the -** reference count drops to 0, then it is made eligible for recycling. -*/ -SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ - assert( p->nRef>0 ); - p->pCache->nRefSum--; - if( (--p->nRef)==0 ){ - if( p->flags&PGHDR_CLEAN ){ - pcacheUnpin(p); - }else{ - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); - assert( sqlite3PcachePageSanity(p) ); - } - } -} - -/* -** Increase the reference count of a supplied page by 1. -*/ -SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ - assert(p->nRef>0); - assert( sqlite3PcachePageSanity(p) ); - p->nRef++; - p->pCache->nRefSum++; -} - -/* -** Drop a page from the cache. There must be exactly one reference to the -** page. This function deletes that reference, so after it returns the -** page pointed to by p is invalid. -*/ -SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ - assert( p->nRef==1 ); - assert( sqlite3PcachePageSanity(p) ); - if( p->flags&PGHDR_DIRTY ){ - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); - } - p->pCache->nRefSum--; - sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); -} - -/* -** Make sure the page is marked as dirty. If it isn't dirty already, -** make it so. -*/ -SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ - assert( p->nRef>0 ); - assert( sqlite3PcachePageSanity(p) ); - if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/ - p->flags &= ~PGHDR_DONT_WRITE; - if( p->flags & PGHDR_CLEAN ){ - p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); - pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno)); - assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); - assert( sqlite3PcachePageSanity(p) ); - } - assert( sqlite3PcachePageSanity(p) ); - } -} - -/* -** Make sure the page is marked as clean. If it isn't clean already, -** make it so. -*/ -SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ - assert( sqlite3PcachePageSanity(p) ); - assert( (p->flags & PGHDR_DIRTY)!=0 ); - assert( (p->flags & PGHDR_CLEAN)==0 ); - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); - p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); - p->flags |= PGHDR_CLEAN; - pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); - assert( sqlite3PcachePageSanity(p) ); - if( p->nRef==0 ){ - pcacheUnpin(p); - } -} - -/* -** Make every page in the cache clean. -*/ -SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ - PgHdr *p; - pcacheTrace(("%p.CLEAN-ALL\n",pCache)); - while( (p = pCache->pDirty)!=0 ){ - sqlite3PcacheMakeClean(p); - } -} - -/* -** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages. -*/ -SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache *pCache){ - PgHdr *p; - pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache)); - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE); - } - pCache->pSynced = pCache->pDirtyTail; -} - -/* -** Clear the PGHDR_NEED_SYNC flag from all dirty pages. -*/ -SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - p->flags &= ~PGHDR_NEED_SYNC; - } - pCache->pSynced = pCache->pDirtyTail; -} - -/* -** Change the page number of page p to newPgno. -*/ -SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ - PCache *pCache = p->pCache; - sqlite3_pcache_page *pOther; - assert( p->nRef>0 ); - assert( newPgno>0 ); - assert( sqlite3PcachePageSanity(p) ); - pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); - pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0); - if( pOther ){ - PgHdr *pXPage = (PgHdr*)pOther->pExtra; - assert( pXPage->nRef==0 ); - pXPage->nRef++; - pCache->nRefSum++; - sqlite3PcacheDrop(pXPage); - } - 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( sqlite3PcachePageSanity(p) ); - } -} - -/* -** Drop every cache entry whose page number is greater than "pgno". The -** caller must ensure that there are no outstanding references to any pages -** other than page 1 with a page number greater than pgno. -** -** If there is a reference to page 1 and the pgno parameter passed to this -** function is 0, then the data area associated with page 1 is zeroed, but -** the page object is not dropped. -*/ -SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ - if( pCache->pCache ){ - PgHdr *p; - PgHdr *pNext; - pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno)); - for(p=pCache->pDirty; p; p=pNext){ - pNext = p->pDirtyNext; - /* This routine never gets call with a positive pgno except right - ** after sqlite3PcacheCleanAll(). So if there are dirty pages, - ** it must be that pgno==0. - */ - assert( p->pgno>0 ); - if( p->pgno>pgno ){ - assert( p->flags&PGHDR_DIRTY ); - sqlite3PcacheMakeClean(p); - } - } - if( pgno==0 && pCache->nRefSum ){ - sqlite3_pcache_page *pPage1; - pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0); - if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because - ** pCache->nRefSum>0 */ - memset(pPage1->pBuf, 0, pCache->szPage); - pgno = 1; - } - } - sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1); - } -} - -/* -** Close a cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ - assert( pCache->pCache!=0 ); - pcacheTrace(("%p.CLOSE\n",pCache)); - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); -} - -/* -** Discard the contents of the cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){ - sqlite3PcacheTruncate(pCache, 0); -} - -/* -** Merge two lists of pages connected by pDirty and in pgno order. -** Do not bother fixing the pDirtyPrev pointers. -*/ -static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ - PgHdr result, *pTail; - pTail = &result; - assert( pA!=0 && pB!=0 ); - for(;;){ - if( pA->pgnopgno ){ - pTail->pDirty = pA; - pTail = pA; - pA = pA->pDirty; - if( pA==0 ){ - pTail->pDirty = pB; - break; - } - }else{ - pTail->pDirty = pB; - pTail = pB; - pB = pB->pDirty; - if( pB==0 ){ - pTail->pDirty = pA; - break; - } - } - } - return result.pDirty; -} - -/* -** Sort the list of pages in ascending order by pgno. Pages are -** connected by pDirty pointers. The pDirtyPrev pointers are -** corrupted by this sort. -** -** Since there cannot be more than 2^31 distinct pages in a database, -** there cannot be more than 31 buckets required by the merge sorter. -** One extra bucket is added to catch overflow in case something -** ever changes to make the previous sentence incorrect. -*/ -#define N_SORT_BUCKET 32 -static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ - PgHdr *a[N_SORT_BUCKET], *p; - int i; - memset(a, 0, sizeof(a)); - while( pIn ){ - p = pIn; - pIn = p->pDirty; - p->pDirty = 0; - for(i=0; ALWAYS(ipDirty; p; p=p->pDirtyNext){ - p->pDirty = p->pDirtyNext; - } - return pcacheSortDirtyList(pCache->pDirty); -} - -/* -** Return the total number of references to all pages held by the cache. -** -** This is not the total number of pages referenced, but the sum of the -** reference count for all pages. -*/ -SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){ - return pCache->nRefSum; -} - -/* -** Return the number of references to the page supplied as an argument. -*/ -SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){ - return p->nRef; -} - -/* -** Return the total number of pages in the cache. -*/ -SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){ - assert( pCache->pCache!=0 ); - return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); -} - -#ifdef SQLITE_TEST -/* -** Get the suggested cache-size value. -*/ -SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){ - return numberOfCachePages(pCache); -} -#endif - -/* -** Set the suggested cache-size value. -*/ -SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ - assert( pCache->pCache!=0 ); - pCache->szCache = mxPage; - sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, - numberOfCachePages(pCache)); -} - -/* -** Set the suggested cache-spill value. Make no changes if if the -** argument is zero. Return the effective cache-spill size, which will -** be the larger of the szSpill and szCache. -*/ -SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){ - int res; - assert( p->pCache!=0 ); - if( mxPage ){ - if( mxPage<0 ){ - mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra)); - } - p->szSpill = mxPage; - } - res = numberOfCachePages(p); - if( resszSpill ) res = p->szSpill; - return res; -} - -/* -** Free up as much memory as possible from the page cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){ - assert( pCache->pCache!=0 ); - sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); -} - -/* -** Return the size of the header added by this middleware layer -** in the page-cache hierarchy. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } - -/* -** Return the number of dirty pages currently in the cache, as a percentage -** of the configured cache size. -*/ -SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache *pCache){ - PgHdr *pDirty; - int nDirty = 0; - int nCache = numberOfCachePages(pCache); - for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++; - return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; -} - -#ifdef SQLITE_DIRECT_OVERFLOW_READ -/* -** Return true if there are one or more dirty pages in the cache. Else false. -*/ -SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){ - return (pCache->pDirty!=0); -} -#endif - -#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) -/* -** For all dirty pages currently in the cache, invoke the specified -** callback. This is only used if the SQLITE_CHECK_PAGES macro is -** defined. -*/ -SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){ - PgHdr *pDirty; - for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){ - xIter(pDirty); - } -} -#endif - -/************** End of pcache.c **********************************************/ -/************** Begin file pcache1.c *****************************************/ -/* -** 2008 November 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements the default page cache implementation (the -** sqlite3_pcache interface). It also contains part of the implementation -** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. -** If the default page cache implementation is overridden, then neither of -** these two features are available. -** -** A Page cache line looks like this: -** -** ------------------------------------------------------------- -** | database page content | PgHdr1 | MemPage | PgHdr | -** ------------------------------------------------------------- -** -** The database page content is up front (so that buffer overreads tend to -** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage -** is the extension added by the btree.c module containing information such -** as the database page number and how that database page is used. PgHdr -** is added by the pcache.c layer and contains information used to keep track -** of which pages are "dirty". PgHdr1 is an extension added by this -** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page. -** PgHdr1 contains information needed to look up a page by its page number. -** The superclass sqlite3_pcache_page.pBuf points to the start of the -** database page content and sqlite3_pcache_page.pExtra points to PgHdr. -** -** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at -** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The -** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this -** size can vary according to architecture, compile-time options, and -** SQLite library version number. -** -** Historical note: It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER -** was defined, then the page content would be held in a separate memory -** allocation from the PgHdr1. This was intended to avoid clownshoe memory -** allocations. However, the btree layer needs a small (16-byte) overrun -** area after the page content buffer. The header serves as that overrun -** area. Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid -** any possibility of a memory error. -** -** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates -** with this module. Information is passed back and forth as PgHdr1 pointers. -** -** The pcache.c and pager.c modules deal pointers to PgHdr objects. -** The btree.c module deals with pointers to MemPage objects. -** -** SOURCE OF PAGE CACHE MEMORY: -** -** Memory for a page might come from any of three sources: -** -** (1) The general-purpose memory allocator - sqlite3Malloc() -** (2) Global page-cache memory provided using sqlite3_config() with -** SQLITE_CONFIG_PAGECACHE. -** (3) PCache-local bulk allocation. -** -** The third case is a chunk of heap memory (defaulting to 100 pages worth) -** that is allocated when the page cache is created. The size of the local -** bulk allocation can be adjusted using -** -** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N). -** -** If N is positive, then N pages worth of memory are allocated using a single -** sqlite3Malloc() call and that memory is used for the first N pages allocated. -** Or if N is negative, then -1024*N bytes of memory are allocated and used -** for as many pages as can be accommodated. -** -** Only one of (2) or (3) can be used. Once the memory available to (2) or -** (3) is exhausted, subsequent allocations fail over to the general-purpose -** memory allocator (1). -** -** Earlier versions of SQLite used only methods (1) and (2). But experiments -** show that method (3) with N==100 provides about a 5% performance boost for -** common workloads. -*/ -/* #include "sqliteInt.h" */ - -typedef struct PCache1 PCache1; -typedef struct PgHdr1 PgHdr1; -typedef struct PgFreeslot PgFreeslot; -typedef struct PGroup PGroup; - -/* -** Each cache entry is represented by an instance of the following -** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated -** directly before this structure and is used to cache the page content. -** -** When reading a corrupt database file, it is possible that SQLite might -** read a few bytes (no more than 16 bytes) past the end of the page buffer. -** It will only read past the end of the page buffer, never write. This -** object is positioned immediately after the page buffer to serve as an -** overrun area, so that overreads are harmless. -** -** Variables isBulkLocal and isAnchor were once type "u8". That works, -** but causes a 2-byte gap in the structure for most architectures (since -** pointers must be either 4 or 8-byte aligned). As this structure is located -** in memory directly after the associated page data, if the database is -** corrupt, code at the b-tree layer may overread the page buffer and -** read part of this structure before the corruption is detected. This -** can cause a valgrind error if the uninitialized gap is accessed. Using u16 -** ensures there is no such gap, and therefore no bytes of uninitialized -** memory in the structure. -** -** The pLruNext and pLruPrev pointers form a double-linked circular list -** of all pages that are unpinned. The PGroup.lru element (which should be -** the only element on the list with PgHdr1.isAnchor set to 1) forms the -** beginning and the end of the list. -*/ -struct PgHdr1 { - sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ - unsigned int iKey; /* Key value (page number) */ - u16 isBulkLocal; /* This page from bulk local storage */ - u16 isAnchor; /* This is the PGroup.lru element */ - PgHdr1 *pNext; /* Next in hash table chain */ - PCache1 *pCache; /* Cache that currently owns this page */ - PgHdr1 *pLruNext; /* Next in circular LRU list of unpinned pages */ - PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ - /* NB: pLruPrev is only valid if pLruNext!=0 */ -}; - -/* -** A page is pinned if it is not on the LRU list. To be "pinned" means -** that the page is in active use and must not be deallocated. -*/ -#define PAGE_IS_PINNED(p) ((p)->pLruNext==0) -#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) - -/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set -** of one or more PCaches that are able to recycle each other's unpinned -** pages when they are under memory pressure. A PGroup is an instance of -** the following object. -** -** This page cache implementation works in one of two modes: -** -** (1) Every PCache is the sole member of its own PGroup. There is -** one PGroup per PCache. -** -** (2) There is a single global PGroup that all PCaches are a member -** of. -** -** Mode 1 uses more memory (since PCache instances are not able to rob -** unused pages from other PCaches) but it also operates without a mutex, -** and is therefore often faster. Mode 2 requires a mutex in order to be -** threadsafe, but recycles pages more efficiently. -** -** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single -** PGroup which is the pcache1.grp global variable and its mutex is -** SQLITE_MUTEX_STATIC_LRU. -*/ -struct PGroup { - sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ - unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ - unsigned int nMinPage; /* Sum of nMin for purgeable caches */ - unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ - unsigned int nPurgeable; /* Number of purgeable pages allocated */ - PgHdr1 lru; /* The beginning and end of the LRU list */ -}; - -/* Each page cache is an instance of the following object. Every -** open database file (including each in-memory database and each -** temporary or transient database) has a single page cache which -** is an instance of this object. -** -** Pointers to structures of this type are cast and returned as -** opaque sqlite3_pcache* handles. -*/ -struct PCache1 { - /* Cache configuration parameters. Page size (szPage) and the purgeable - ** flag (bPurgeable) and the pnPurgeable pointer are all set when the - ** cache is created and are never changed thereafter. nMax may be - ** modified at any time by a call to the pcache1Cachesize() method. - ** The PGroup mutex must be held when accessing nMax. - */ - PGroup *pGroup; /* PGroup this cache belongs to */ - unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */ - int szPage; /* Size of database content section */ - int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ - int szAlloc; /* Total size of one pcache line */ - int bPurgeable; /* True if cache is purgeable */ - unsigned int nMin; /* Minimum number of pages reserved */ - unsigned int nMax; /* Configured "cache_size" value */ - unsigned int n90pct; /* nMax*9/10 */ - unsigned int iMaxKey; /* Largest key seen since xTruncate() */ - unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/ - - /* Hash table of all pages. The following variables may only be accessed - ** when the accessor is holding the PGroup mutex. - */ - unsigned int nRecyclable; /* Number of pages in the LRU list */ - unsigned int nPage; /* Total number of pages in apHash */ - unsigned int nHash; /* Number of slots in apHash[] */ - PgHdr1 **apHash; /* Hash table for fast lookup by key */ - PgHdr1 *pFree; /* List of unused pcache-local pages */ - void *pBulk; /* Bulk memory used by pcache-local */ -}; - -/* -** Free slots in the allocator used to divide up the global page cache -** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism. -*/ -struct PgFreeslot { - PgFreeslot *pNext; /* Next free slot */ -}; - -/* -** Global data used by this cache. -*/ -static SQLITE_WSD struct PCacheGlobal { - PGroup grp; /* The global PGroup for mode (2) */ - - /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The - ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all - ** fixed at sqlite3_initialize() time and do not require mutex protection. - ** The nFreeSlot and pFree values do require mutex protection. - */ - int isInit; /* True if initialized */ - int separateCache; /* Use a new PGroup for each PCache */ - int nInitPage; /* Initial bulk allocation size */ - int szSlot; /* Size of each free slot */ - int nSlot; /* The number of pcache slots */ - int nReserve; /* Try to keep nFreeSlot above this */ - void *pStart, *pEnd; /* Bounds of global page cache memory */ - /* Above requires no mutex. Use mutex below for variable that follow. */ - sqlite3_mutex *mutex; /* Mutex for accessing the following: */ - PgFreeslot *pFree; /* Free page blocks */ - int nFreeSlot; /* Number of unused pcache slots */ - int bUnderPressure; /* True if low on PAGECACHE memory */ -} pcache1_g; - -/* -** All code in this file should access the global structure above via the -** alias "pcache1". This ensures that the WSD emulation is used when -** compiling for systems that do not support real WSD. -*/ -#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) - -/* -** Macros to enter and leave the PCache LRU mutex. -*/ -#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 -# define pcache1EnterMutex(X) assert((X)->mutex==0) -# define pcache1LeaveMutex(X) assert((X)->mutex==0) -# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0 -#else -# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) -# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) -# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1 -#endif - -/******************************************************************************/ -/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ - - -/* -** This function is called during initialization if a static buffer is -** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE -** verb to sqlite3_config(). Parameter pBuf points to an allocation large -** enough to contain 'n' buffers of 'sz' bytes each. -** -** This routine is called from sqlite3_initialize() and so it is guaranteed -** to be serialized already. There is no need for further mutexing. -*/ -SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ - if( pcache1.isInit ){ - PgFreeslot *p; - if( pBuf==0 ) sz = n = 0; - if( n==0 ) sz = 0; - sz = ROUNDDOWN8(sz); - pcache1.szSlot = sz; - pcache1.nSlot = pcache1.nFreeSlot = n; - pcache1.nReserve = n>90 ? 10 : (n/10 + 1); - pcache1.pStart = pBuf; - pcache1.pFree = 0; - AtomicStore(&pcache1.bUnderPressure,0); - while( n-- ){ - p = (PgFreeslot*)pBuf; - p->pNext = pcache1.pFree; - pcache1.pFree = p; - pBuf = (void*)&((char*)pBuf)[sz]; - } - pcache1.pEnd = pBuf; - } -} - -/* -** Try to initialize the pCache->pFree and pCache->pBulk fields. Return -** true if pCache->pFree ends up containing one or more free pages. -*/ -static int pcache1InitBulk(PCache1 *pCache){ - i64 szBulk; - char *zBulk; - if( pcache1.nInitPage==0 ) return 0; - /* Do not bother with a bulk allocation if the cache size very small */ - if( pCache->nMax<3 ) return 0; - sqlite3BeginBenignMalloc(); - if( pcache1.nInitPage>0 ){ - szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; - }else{ - szBulk = -1024 * (i64)pcache1.nInitPage; - } - if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ - szBulk = pCache->szAlloc*(i64)pCache->nMax; - } - zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); - sqlite3EndBenignMalloc(); - if( zBulk ){ - int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; - do{ - PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; - pX->page.pBuf = zBulk; - pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); - assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); - pX->isBulkLocal = 1; - pX->isAnchor = 0; - pX->pNext = pCache->pFree; - pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ - pCache->pFree = pX; - zBulk += pCache->szAlloc; - }while( --nBulk ); - } - return pCache->pFree!=0; -} - -/* -** Malloc function used within this file to allocate space from the buffer -** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no -** such buffer exists or there is no space left in it, this function falls -** back to sqlite3Malloc(). -** -** Multiple threads can run this routine at the same time. Global variables -** in pcache1 need to be protected via mutex. -*/ -static void *pcache1Alloc(int nByte){ - void *p = 0; - assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - if( nByte<=pcache1.szSlot ){ - sqlite3_mutex_enter(pcache1.mutex); - p = (PgHdr1 *)pcache1.pFree; - if( p ){ - pcache1.pFree = pcache1.pFree->pNext; - pcache1.nFreeSlot--; - AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot=0 ); - sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); - sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); - } - sqlite3_mutex_leave(pcache1.mutex); - } - if( p==0 ){ - /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get - ** it from sqlite3Malloc instead. - */ - p = sqlite3Malloc(nByte); -#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS - if( p ){ - int sz = sqlite3MallocSize(p); - sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); - sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); - sqlite3_mutex_leave(pcache1.mutex); - } -#endif - sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); - } - return p; -} - -/* -** Free an allocated buffer obtained from pcache1Alloc(). -*/ -static void pcache1Free(void *p){ - if( p==0 ) return; - if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ - PgFreeslot *pSlot; - sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); - pSlot = (PgFreeslot*)p; - pSlot->pNext = pcache1.pFree; - pcache1.pFree = pSlot; - pcache1.nFreeSlot++; - AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot=pcache1.pStart && ppGroup->mutex) ); - if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ - assert( pCache->pFree!=0 ); - p = pCache->pFree; - pCache->pFree = p->pNext; - p->pNext = 0; - }else{ -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - /* The group mutex must be released before pcache1Alloc() is called. This - ** is because it might call sqlite3_release_memory(), which assumes that - ** this mutex is not held. */ - assert( pcache1.separateCache==0 ); - assert( pCache->pGroup==&pcache1.grp ); - pcache1LeaveMutex(pCache->pGroup); -#endif - if( benignMalloc ){ sqlite3BeginBenignMalloc(); } - pPg = pcache1Alloc(pCache->szAlloc); - if( benignMalloc ){ sqlite3EndBenignMalloc(); } -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - pcache1EnterMutex(pCache->pGroup); -#endif - if( pPg==0 ) return 0; - p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; - p->page.pBuf = pPg; - p->page.pExtra = (u8*)p + ROUND8(sizeof(*p)); - assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) ); - p->isBulkLocal = 0; - p->isAnchor = 0; - p->pLruPrev = 0; /* Initializing this saves a valgrind error */ - } - (*pCache->pnPurgeable)++; - return p; -} - -/* -** Free a page object allocated by pcache1AllocPage(). -*/ -static void pcache1FreePage(PgHdr1 *p){ - PCache1 *pCache; - assert( p!=0 ); - pCache = p->pCache; - assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); - if( p->isBulkLocal ){ - p->pNext = pCache->pFree; - pCache->pFree = p; - }else{ - pcache1Free(p->page.pBuf); - } - (*pCache->pnPurgeable)--; -} - -/* -** Malloc function used by SQLite to obtain space from the buffer configured -** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer -** exists, this function falls back to sqlite3Malloc(). -*/ -SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ - assert( sz<=65536+8 ); /* These allocations are never very large */ - return pcache1Alloc(sz); -} - -/* -** Free an allocated buffer obtained from sqlite3PageMalloc(). -*/ -SQLITE_PRIVATE void sqlite3PageFree(void *p){ - pcache1Free(p); -} - - -/* -** Return true if it desirable to avoid allocating a new page cache -** entry. -** -** If memory was allocated specifically to the page cache using -** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then -** it is desirable to avoid allocating a new page cache entry because -** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient -** for all page cache needs and we should not need to spill the -** allocation onto the heap. -** -** Or, the heap is used for all page cache memory but the heap is -** under memory pressure, then again it is desirable to avoid -** allocating a new page cache entry in order to avoid stressing -** the heap even further. -*/ -static int pcache1UnderMemoryPressure(PCache1 *pCache){ - if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ - return AtomicLoad(&pcache1.bUnderPressure); - }else{ - return sqlite3HeapNearlyFull(); - } -} - -/******************************************************************************/ -/******** General Implementation Functions ************************************/ - -/* -** This function is used to resize the hash table used by the cache passed -** as the first argument. -** -** The PCache mutex must be held when this function is called. -*/ -static void pcache1ResizeHash(PCache1 *p){ - PgHdr1 **apNew; - u64 nNew; - u32 i; - - assert( sqlite3_mutex_held(p->pGroup->mutex) ); - - nNew = 2*(u64)p->nHash; - if( nNew<256 ){ - nNew = 256; - } - - pcache1LeaveMutex(p->pGroup); - if( p->nHash ){ sqlite3BeginBenignMalloc(); } - apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew); - if( p->nHash ){ sqlite3EndBenignMalloc(); } - pcache1EnterMutex(p->pGroup); - if( apNew ){ - for(i=0; inHash; i++){ - PgHdr1 *pPage; - PgHdr1 *pNext = p->apHash[i]; - while( (pPage = pNext)!=0 ){ - unsigned int h = pPage->iKey % nNew; - pNext = pPage->pNext; - pPage->pNext = apNew[h]; - apNew[h] = pPage; - } - } - sqlite3_free(p->apHash); - p->apHash = apNew; - p->nHash = nNew; - } -} - -/* -** This function is used internally to remove the page pPage from the -** PGroup LRU list, if is part of it. If pPage is not part of the PGroup -** LRU list, then this function is a no-op. -** -** The PGroup mutex must be held when this function is called. -*/ -static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ - assert( pPage!=0 ); - assert( PAGE_IS_UNPINNED(pPage) ); - assert( pPage->pLruNext ); - assert( pPage->pLruPrev ); - assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) ); - pPage->pLruPrev->pLruNext = pPage->pLruNext; - pPage->pLruNext->pLruPrev = pPage->pLruPrev; - pPage->pLruNext = 0; - /* pPage->pLruPrev = 0; - ** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */ - assert( pPage->isAnchor==0 ); - assert( pPage->pCache->pGroup->lru.isAnchor==1 ); - pPage->pCache->nRecyclable--; - return pPage; -} - - -/* -** Remove the page supplied as an argument from the hash table -** (PCache1.apHash structure) that it is currently stored in. -** Also free the page if freePage is true. -** -** The PGroup mutex must be held when this function is called. -*/ -static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){ - unsigned int h; - PCache1 *pCache = pPage->pCache; - PgHdr1 **pp; - - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - h = pPage->iKey % pCache->nHash; - for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext); - *pp = (*pp)->pNext; - - pCache->nPage--; - if( freeFlag ) pcache1FreePage(pPage); -} - -/* -** If there are currently more than nMaxPage pages allocated, try -** to recycle pages to reduce the number allocated to nMaxPage. -*/ -static void pcache1EnforceMaxPage(PCache1 *pCache){ - PGroup *pGroup = pCache->pGroup; - PgHdr1 *p; - assert( sqlite3_mutex_held(pGroup->mutex) ); - while( pGroup->nPurgeable>pGroup->nMaxPage - && (p=pGroup->lru.pLruPrev)->isAnchor==0 - ){ - assert( p->pCache->pGroup==pGroup ); - assert( PAGE_IS_UNPINNED(p) ); - pcache1PinPage(p); - pcache1RemoveFromHash(p, 1); - } - if( pCache->nPage==0 && pCache->pBulk ){ - sqlite3_free(pCache->pBulk); - pCache->pBulk = pCache->pFree = 0; - } -} - -/* -** Discard all pages from cache pCache with a page number (key value) -** greater than or equal to iLimit. Any pinned pages that meet this -** criteria are unpinned before they are discarded. -** -** The PCache mutex must be held when this function is called. -*/ -static void pcache1TruncateUnsafe( - PCache1 *pCache, /* The cache to truncate */ - unsigned int iLimit /* Drop pages with this pgno or larger */ -){ - TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */ - unsigned int h, iStop; - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - assert( pCache->iMaxKey >= iLimit ); - assert( pCache->nHash > 0 ); - if( pCache->iMaxKey - iLimit < pCache->nHash ){ - /* If we are just shaving the last few pages off the end of the - ** cache, then there is no point in scanning the entire hash table. - ** Only scan those hash slots that might contain pages that need to - ** be removed. */ - h = iLimit % pCache->nHash; - iStop = pCache->iMaxKey % pCache->nHash; - TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */ - }else{ - /* This is the general case where many pages are being removed. - ** It is necessary to scan the entire hash table */ - h = pCache->nHash/2; - iStop = h - 1; - } - for(;;){ - PgHdr1 **pp; - PgHdr1 *pPage; - assert( hnHash ); - pp = &pCache->apHash[h]; - while( (pPage = *pp)!=0 ){ - if( pPage->iKey>=iLimit ){ - pCache->nPage--; - *pp = pPage->pNext; - if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage); - pcache1FreePage(pPage); - }else{ - pp = &pPage->pNext; - TESTONLY( if( nPage>=0 ) nPage++; ) - } - } - if( h==iStop ) break; - h = (h+1) % pCache->nHash; - } - assert( nPage<0 || pCache->nPage==(unsigned)nPage ); -} - -/******************************************************************************/ -/******** sqlite3_pcache Methods **********************************************/ - -/* -** Implementation of the sqlite3_pcache.xInit method. -*/ -static int pcache1Init(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - assert( pcache1.isInit==0 ); - memset(&pcache1, 0, sizeof(pcache1)); - - - /* - ** The pcache1.separateCache variable is true if each PCache has its own - ** private PGroup (mode-1). pcache1.separateCache is false if the single - ** PGroup in pcache1.grp is used for all page caches (mode-2). - ** - ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT - ** - ** * Use a unified cache in single-threaded applications that have - ** configured a start-time buffer for use as page-cache memory using - ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL - ** pBuf argument. - ** - ** * Otherwise use separate caches (mode-1) - */ -#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) - pcache1.separateCache = 0; -#elif SQLITE_THREADSAFE - pcache1.separateCache = sqlite3GlobalConfig.pPage==0 - || sqlite3GlobalConfig.bCoreMutex>0; -#else - pcache1.separateCache = sqlite3GlobalConfig.pPage==0; -#endif - -#if SQLITE_THREADSAFE - if( sqlite3GlobalConfig.bCoreMutex ){ - pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU); - pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM); - } -#endif - if( pcache1.separateCache - && sqlite3GlobalConfig.nPage!=0 - && sqlite3GlobalConfig.pPage==0 - ){ - pcache1.nInitPage = sqlite3GlobalConfig.nPage; - }else{ - pcache1.nInitPage = 0; - } - pcache1.grp.mxPinned = 10; - pcache1.isInit = 1; - return SQLITE_OK; -} - -/* -** Implementation of the sqlite3_pcache.xShutdown method. -** Note that the static mutex allocated in xInit does -** not need to be freed. -*/ -static void pcache1Shutdown(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - assert( pcache1.isInit!=0 ); - memset(&pcache1, 0, sizeof(pcache1)); -} - -/* forward declaration */ -static void pcache1Destroy(sqlite3_pcache *p); - -/* -** Implementation of the sqlite3_pcache.xCreate method. -** -** Allocate a new cache. -*/ -static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ - PCache1 *pCache; /* The newly created page cache */ - PGroup *pGroup; /* The group the new page cache will belong to */ - i64 sz; /* Bytes of memory required to allocate the new cache */ - - assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); - assert( szExtra < 300 ); - - sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache; - pCache = (PCache1 *)sqlite3MallocZero(sz); - if( pCache ){ - if( pcache1.separateCache ){ - pGroup = (PGroup*)&pCache[1]; - pGroup->mxPinned = 10; - }else{ - pGroup = &pcache1.grp; - } - pcache1EnterMutex(pGroup); - if( pGroup->lru.isAnchor==0 ){ - pGroup->lru.isAnchor = 1; - pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru; - } - pCache->pGroup = pGroup; - pCache->szPage = szPage; - pCache->szExtra = szExtra; - pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); - pCache->bPurgeable = (bPurgeable ? 1 : 0); - pcache1ResizeHash(pCache); - if( bPurgeable ){ - pCache->nMin = 10; - pGroup->nMinPage += pCache->nMin; - pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pCache->pnPurgeable = &pGroup->nPurgeable; - }else{ - pCache->pnPurgeable = &pCache->nPurgeableDummy; - } - pcache1LeaveMutex(pGroup); - if( pCache->nHash==0 ){ - pcache1Destroy((sqlite3_pcache*)pCache); - pCache = 0; - } - } - return (sqlite3_pcache *)pCache; -} - -/* -** Implementation of the sqlite3_pcache.xCachesize method. -** -** Configure the cache_size limit for a cache. -*/ -static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ - PCache1 *pCache = (PCache1 *)p; - u32 n; - assert( nMax>=0 ); - if( pCache->bPurgeable ){ - PGroup *pGroup = pCache->pGroup; - pcache1EnterMutex(pGroup); - 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 = n; - pCache->n90pct = pCache->nMax*9/10; - pcache1EnforceMaxPage(pCache); - pcache1LeaveMutex(pGroup); - } -} - -/* -** Implementation of the sqlite3_pcache.xShrink method. -** -** Free up as much memory as possible. -*/ -static void pcache1Shrink(sqlite3_pcache *p){ - PCache1 *pCache = (PCache1*)p; - if( pCache->bPurgeable ){ - PGroup *pGroup = pCache->pGroup; - unsigned int savedMaxPage; - pcache1EnterMutex(pGroup); - savedMaxPage = pGroup->nMaxPage; - pGroup->nMaxPage = 0; - pcache1EnforceMaxPage(pCache); - pGroup->nMaxPage = savedMaxPage; - pcache1LeaveMutex(pGroup); - } -} - -/* -** Implementation of the sqlite3_pcache.xPagecount method. -*/ -static int pcache1Pagecount(sqlite3_pcache *p){ - int n; - PCache1 *pCache = (PCache1*)p; - pcache1EnterMutex(pCache->pGroup); - n = pCache->nPage; - pcache1LeaveMutex(pCache->pGroup); - return n; -} - - -/* -** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described -** in the header of the pcache1Fetch() procedure. -** -** This steps are broken out into a separate procedure because they are -** usually not needed, and by avoiding the stack initialization required -** for these steps, the main pcache1Fetch() procedure can run faster. -*/ -static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( - PCache1 *pCache, - unsigned int iKey, - int createFlag -){ - unsigned int nPinned; - PGroup *pGroup = pCache->pGroup; - PgHdr1 *pPage = 0; - - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ - assert( pCache->nPage >= pCache->nRecyclable ); - nPinned = pCache->nPage - pCache->nRecyclable; - assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); - assert( pCache->n90pct == pCache->nMax*9/10 ); - if( createFlag==1 && ( - nPinned>=pGroup->mxPinned - || nPinned>=pCache->n90pct - || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclablenPage>=pCache->nHash ) pcache1ResizeHash(pCache); - assert( pCache->nHash>0 && pCache->apHash ); - - /* Step 4. Try to recycle a page. */ - if( pCache->bPurgeable - && !pGroup->lru.pLruPrev->isAnchor - && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache)) - ){ - PCache1 *pOther; - pPage = pGroup->lru.pLruPrev; - assert( PAGE_IS_UNPINNED(pPage) ); - pcache1RemoveFromHash(pPage, 0); - pcache1PinPage(pPage); - pOther = pPage->pCache; - if( pOther->szAlloc != pCache->szAlloc ){ - pcache1FreePage(pPage); - pPage = 0; - }else{ - pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable); - } - } - - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. - */ - if( !pPage ){ - pPage = pcache1AllocPage(pCache, createFlag==1); - } - - if( pPage ){ - unsigned int h = iKey % pCache->nHash; - pCache->nPage++; - pPage->iKey = iKey; - pPage->pNext = pCache->apHash[h]; - pPage->pCache = pCache; - pPage->pLruNext = 0; - /* pPage->pLruPrev = 0; - ** No need to clear pLruPrev since it is not accessed when pLruNext==0 */ - *(void **)pPage->page.pExtra = 0; - pCache->apHash[h] = pPage; - if( iKey>pCache->iMaxKey ){ - pCache->iMaxKey = iKey; - } - } - return pPage; -} - -/* -** Implementation of the sqlite3_pcache.xFetch method. -** -** Fetch a page by key value. -** -** Whether or not a new page may be allocated by this function depends on -** the value of the createFlag argument. 0 means do not allocate a new -** page. 1 means allocate a new page if space is easily available. 2 -** means to try really hard to allocate a new page. -** -** For a non-purgeable cache (a cache used as the storage for an in-memory -** database) there is really no difference between createFlag 1 and 2. So -** the calling function (pcache.c) will never have a createFlag of 1 on -** a non-purgeable cache. -** -** There are three different approaches to obtaining space for a page, -** depending on the value of parameter createFlag (which may be 0, 1 or 2). -** -** 1. Regardless of the value of createFlag, the cache is searched for a -** copy of the requested page. If one is found, it is returned. -** -** 2. If createFlag==0 and the page is not already in the cache, NULL is -** returned. -** -** 3. If createFlag is 1, and the page is not already in the cache, then -** return NULL (do not allocate a new page) if any of the following -** conditions are true: -** -** (a) the number of pages pinned by the cache is greater than -** PCache1.nMax, or -** -** (b) the number of pages pinned by the cache is greater than -** the sum of nMax for all purgeable caches, less the sum of -** nMin for all other purgeable caches, or -** -** 4. If none of the first three conditions apply and the cache is marked -** as purgeable, and if one of the following is true: -** -** (a) The number of pages allocated for the cache is already -** PCache1.nMax, or -** -** (b) The number of pages allocated for all purgeable caches is -** already equal to or greater than the sum of nMax for all -** purgeable caches, -** -** (c) The system is under memory pressure and wants to avoid -** unnecessary pages cache entry allocations -** -** then attempt to recycle a page from the LRU list. If it is the right -** size, return the recycled buffer. Otherwise, free the buffer and -** proceed to step 5. -** -** 5. Otherwise, allocate and return a new page buffer. -** -** There are two versions of this routine. pcache1FetchWithMutex() is -** the general case. pcache1FetchNoMutex() is a faster implementation for -** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper -** invokes the appropriate routine. -*/ -static PgHdr1 *pcache1FetchNoMutex( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = 0; - - /* Step 1: Search the hash table for an existing entry. */ - pPage = pCache->apHash[iKey % pCache->nHash]; - while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } - - /* Step 2: If the page was found in the hash table, then return it. - ** If the page was not in the hash table and createFlag is 0, abort. - ** Otherwise (page not in hash and createFlag!=0) continue with - ** subsequent steps to try to create the page. */ - if( pPage ){ - if( PAGE_IS_UNPINNED(pPage) ){ - return pcache1PinPage(pPage); - }else{ - return pPage; - } - }else if( createFlag ){ - /* Steps 3, 4, and 5 implemented by this subroutine */ - return pcache1FetchStage2(pCache, iKey, createFlag); - }else{ - return 0; - } -} -#if PCACHE1_MIGHT_USE_GROUP_MUTEX -static PgHdr1 *pcache1FetchWithMutex( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage; - - pcache1EnterMutex(pCache->pGroup); - pPage = pcache1FetchNoMutex(p, iKey, createFlag); - assert( pPage==0 || pCache->iMaxKey>=iKey ); - pcache1LeaveMutex(pCache->pGroup); - return pPage; -} -#endif -static sqlite3_pcache_page *pcache1Fetch( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ -#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG) - PCache1 *pCache = (PCache1 *)p; -#endif - - assert( offsetof(PgHdr1,page)==0 ); - assert( pCache->bPurgeable || createFlag!=1 ); - assert( pCache->bPurgeable || pCache->nMin==0 ); - assert( pCache->bPurgeable==0 || pCache->nMin==10 ); - assert( pCache->nMin==0 || pCache->bPurgeable ); - assert( pCache->nHash>0 ); -#if PCACHE1_MIGHT_USE_GROUP_MUTEX - if( pCache->pGroup->mutex ){ - return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag); - }else -#endif - { - return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag); - } -} - - -/* -** Implementation of the sqlite3_pcache.xUnpin method. -** -** Mark a page as unpinned (eligible for asynchronous recycling). -*/ -static void pcache1Unpin( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - int reuseUnlikely -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = (PgHdr1 *)pPg; - PGroup *pGroup = pCache->pGroup; - - assert( pPage->pCache==pCache ); - pcache1EnterMutex(pGroup); - - /* It is an error to call this function if the page is already - ** part of the PGroup LRU list. - */ - assert( pPage->pLruNext==0 ); - assert( PAGE_IS_PINNED(pPage) ); - - if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){ - pcache1RemoveFromHash(pPage, 1); - }else{ - /* Add the page to the PGroup LRU list. */ - PgHdr1 **ppFirst = &pGroup->lru.pLruNext; - pPage->pLruPrev = &pGroup->lru; - (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; - *ppFirst = pPage; - pCache->nRecyclable++; - } - - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xRekey method. -*/ -static void pcache1Rekey( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - unsigned int iOld, - unsigned int iNew -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = (PgHdr1 *)pPg; - PgHdr1 **pp; - unsigned int hOld, hNew; - assert( pPage->iKey==iOld ); - assert( pPage->pCache==pCache ); - assert( iOld!=iNew ); /* The page number really is changing */ - - pcache1EnterMutex(pCache->pGroup); - - 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; - - assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */ - hNew = iNew%pCache->nHash; - pPage->iKey = iNew; - pPage->pNext = pCache->apHash[hNew]; - pCache->apHash[hNew] = pPage; - if( iNew>pCache->iMaxKey ){ - pCache->iMaxKey = iNew; - } - - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xTruncate method. -** -** Discard all unpinned pages in the cache with a page number equal to -** or greater than parameter iLimit. Any pinned pages with a page number -** equal to or greater than iLimit are implicitly unpinned. -*/ -static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){ - PCache1 *pCache = (PCache1 *)p; - pcache1EnterMutex(pCache->pGroup); - if( iLimit<=pCache->iMaxKey ){ - pcache1TruncateUnsafe(pCache, iLimit); - pCache->iMaxKey = iLimit-1; - } - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xDestroy method. -** -** Destroy a cache allocated using pcache1Create(). -*/ -static void pcache1Destroy(sqlite3_pcache *p){ - PCache1 *pCache = (PCache1 *)p; - PGroup *pGroup = pCache->pGroup; - assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); - pcache1EnterMutex(pGroup); - if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0); - assert( pGroup->nMaxPage >= pCache->nMax ); - pGroup->nMaxPage -= pCache->nMax; - assert( pGroup->nMinPage >= pCache->nMin ); - pGroup->nMinPage -= pCache->nMin; - pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1EnforceMaxPage(pCache); - pcache1LeaveMutex(pGroup); - sqlite3_free(pCache->pBulk); - sqlite3_free(pCache->apHash); - sqlite3_free(pCache); -} - -/* -** This function is called during initialization (sqlite3_initialize()) to -** install the default pluggable cache module, assuming the user has not -** already provided an alternative. -*/ -SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){ - static const sqlite3_pcache_methods2 defaultMethods = { - 1, /* iVersion */ - 0, /* pArg */ - pcache1Init, /* xInit */ - pcache1Shutdown, /* xShutdown */ - pcache1Create, /* xCreate */ - pcache1Cachesize, /* xCachesize */ - pcache1Pagecount, /* xPagecount */ - pcache1Fetch, /* xFetch */ - pcache1Unpin, /* xUnpin */ - pcache1Rekey, /* xRekey */ - pcache1Truncate, /* xTruncate */ - pcache1Destroy, /* xDestroy */ - pcache1Shrink /* xShrink */ - }; - sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); -} - -/* -** Return the size of the header on each page of this PCACHE implementation. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } - -/* -** Return the global mutex used by this PCACHE implementation. The -** sqlite3_status() routine needs access to this mutex. -*/ -SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){ - return pcache1.mutex; -} - -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -/* -** This function is called to free superfluous dynamically allocated memory -** held by the pager system. Memory in use by any SQLite pager allocated -** by the current thread may be sqlite3_free()ed. -** -** nReq is the number of bytes of memory required. Once this much has -** been released, the function returns. The return value is the total number -** of bytes of memory released. -*/ -SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ - int nFree = 0; - assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - assert( sqlite3_mutex_notheld(pcache1.mutex) ); - if( sqlite3GlobalConfig.pPage==0 ){ - PgHdr1 *p; - pcache1EnterMutex(&pcache1.grp); - while( (nReq<0 || nFreeisAnchor==0 - ){ - nFree += pcache1MemSize(p->page.pBuf); - assert( PAGE_IS_UNPINNED(p) ); - pcache1PinPage(p); - pcache1RemoveFromHash(p, 1); - } - pcache1LeaveMutex(&pcache1.grp); - } - return nFree; -} -#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ - -#ifdef SQLITE_TEST -/* -** This function is used by test procedures to inspect the internal state -** of the global cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheStats( - int *pnCurrent, /* OUT: Total number of pages cached */ - int *pnMax, /* OUT: Global maximum cache size */ - int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */ - int *pnRecyclable /* OUT: Total number of pages available for recycling */ -){ - PgHdr1 *p; - int nRecyclable = 0; - for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ - assert( PAGE_IS_UNPINNED(p) ); - nRecyclable++; - } - *pnCurrent = pcache1.grp.nPurgeable; - *pnMax = (int)pcache1.grp.nMaxPage; - *pnMin = (int)pcache1.grp.nMinPage; - *pnRecyclable = nRecyclable; -} -#endif - -/************** End of pcache1.c *********************************************/ -/************** Begin file rowset.c ******************************************/ -/* -** 2008 December 3 -** -** 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 module implements an object we call a "RowSet". -** -** The RowSet object is a collection of rowids. Rowids -** are inserted into the RowSet in an arbitrary order. Inserts -** can be intermixed with tests to see if a given rowid has been -** previously inserted into the RowSet. -** -** After all inserts are finished, it is possible to extract the -** elements of the RowSet in sorted order. Once this extraction -** process has started, no new elements may be inserted. -** -** Hence, the primitive operations for a RowSet are: -** -** CREATE -** INSERT -** TEST -** SMALLEST -** DESTROY -** -** The CREATE and DESTROY primitives are the constructor and destructor, -** obviously. The INSERT primitive adds a new element to the RowSet. -** TEST checks to see if an element is already in the RowSet. SMALLEST -** extracts the least value from the RowSet. -** -** The INSERT primitive might allocate additional memory. Memory is -** allocated in chunks so most INSERTs do no allocation. There is an -** upper bound on the size of allocated memory. No memory is freed -** until DESTROY. -** -** The TEST primitive includes a "batch" number. The TEST primitive -** will only see elements that were inserted before the last change -** in the batch number. In other words, if an INSERT occurs between -** two TESTs where the TESTs have the same batch number, then the -** value added by the INSERT will not be visible to the second TEST. -** The initial batch number is zero, so if the very first TEST contains -** a non-zero batch number, it will see all prior INSERTs. -** -** No INSERTs may occurs after a SMALLEST. An assertion will fail if -** that is attempted. -** -** The cost of an INSERT is roughly constant. (Sometimes new memory -** has to be allocated on an INSERT.) The cost of a TEST with a new -** batch number is O(NlogN) where N is the number of elements in the RowSet. -** The cost of a TEST using the same batch number is O(logN). The cost -** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST -** primitives are constant time. The cost of DESTROY is O(N). -** -** TEST and SMALLEST may not be used by the same RowSet. This used to -** be possible, but the feature was not used, so it was removed in order -** to simplify the code. -*/ -/* #include "sqliteInt.h" */ - - -/* -** Target size for allocation chunks. -*/ -#define ROWSET_ALLOCATION_SIZE 1024 - -/* -** The number of rowset entries per allocation chunk. -*/ -#define ROWSET_ENTRY_PER_CHUNK \ - ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) - -/* -** Each entry in a RowSet is an instance of the following object. -** -** This same object is reused to store a linked list of trees of RowSetEntry -** objects. In that alternative use, pRight points to the next entry -** in the list, pLeft points to the tree, and v is unused. The -** RowSet.pForest value points to the head of this forest list. -*/ -struct RowSetEntry { - i64 v; /* ROWID value for this entry */ - struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ - struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ -}; - -/* -** RowSetEntry objects are allocated in large chunks (instances of the -** following structure) to reduce memory allocation overhead. The -** chunks are kept on a linked list so that they can be deallocated -** when the RowSet is destroyed. -*/ -struct RowSetChunk { - struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */ - struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */ -}; - -/* -** A RowSet in an instance of the following structure. -** -** A typedef of this structure if found in sqliteInt.h. -*/ -struct RowSet { - struct RowSetChunk *pChunk; /* List of all chunk allocations */ - sqlite3 *db; /* The database connection */ - struct RowSetEntry *pEntry; /* List of entries using pRight */ - struct RowSetEntry *pLast; /* Last entry on the pEntry list */ - struct RowSetEntry *pFresh; /* Source of new entry objects */ - struct RowSetEntry *pForest; /* List of binary trees of entries */ - u16 nFresh; /* Number of objects on pFresh */ - u16 rsFlags; /* Various flags */ - int iBatch; /* Current insert batch */ -}; - -/* -** Allowed values for RowSet.rsFlags -*/ -#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ -#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ - -/* -** Allocate a RowSet object. Return NULL if a memory allocation -** error occurs. -*/ -SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){ - RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p)); - if( p ){ - int N = sqlite3DbMallocSize(db, p); - p->pChunk = 0; - p->db = db; - p->pEntry = 0; - p->pLast = 0; - p->pForest = 0; - p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); - p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); - p->rsFlags = ROWSET_SORTED; - p->iBatch = 0; - } - return p; -} - -/* -** Deallocate all chunks from a RowSet. This frees all memory that -** the RowSet has allocated over its lifetime. This routine is -** the destructor for the RowSet. -*/ -SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){ - RowSet *p = (RowSet*)pArg; - struct RowSetChunk *pChunk, *pNextChunk; - for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ - pNextChunk = pChunk->pNextChunk; - sqlite3DbFree(p->db, pChunk); - } - p->pChunk = 0; - p->nFresh = 0; - p->pEntry = 0; - p->pLast = 0; - p->pForest = 0; - p->rsFlags = ROWSET_SORTED; -} - -/* -** Deallocate all chunks from a RowSet. This frees all memory that -** the RowSet has allocated over its lifetime. This routine is -** the destructor for the RowSet. -*/ -SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){ - sqlite3RowSetClear(pArg); - sqlite3DbFree(((RowSet*)pArg)->db, pArg); -} - -/* -** Allocate a new RowSetEntry object that is associated with the -** given RowSet. Return a pointer to the new and completely uninitialized -** object. -** -** In an OOM situation, the RowSet.db->mallocFailed flag is set and this -** routine returns NULL. -*/ -static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ - assert( p!=0 ); - if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/ - /* We could allocate a fresh RowSetEntry each time one is needed, but it - ** is more efficient to pull a preallocated entry from the pool */ - struct RowSetChunk *pNew; - pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); - if( pNew==0 ){ - return 0; - } - pNew->pNextChunk = p->pChunk; - p->pChunk = pNew; - p->pFresh = pNew->aEntry; - p->nFresh = ROWSET_ENTRY_PER_CHUNK; - } - p->nFresh--; - return p->pFresh++; -} - -/* -** Insert a new value into a RowSet. -** -** The mallocFailed flag of the database connection is set if a -** memory allocation fails. -*/ -SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ - struct RowSetEntry *pEntry; /* The new entry */ - struct RowSetEntry *pLast; /* The last prior entry */ - - /* This routine is never called after sqlite3RowSetNext() */ - assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); - - pEntry = rowSetEntryAlloc(p); - if( pEntry==0 ) return; - pEntry->v = rowid; - pEntry->pRight = 0; - pLast = p->pLast; - if( pLast ){ - if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/ - /* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags - ** where possible */ - p->rsFlags &= ~ROWSET_SORTED; - } - pLast->pRight = pEntry; - }else{ - p->pEntry = pEntry; - } - p->pLast = pEntry; -} - -/* -** Merge two lists of RowSetEntry objects. Remove duplicates. -** -** The input lists are connected via pRight pointers and are -** assumed to each already be in sorted order. -*/ -static struct RowSetEntry *rowSetEntryMerge( - struct RowSetEntry *pA, /* First sorted list to be merged */ - struct RowSetEntry *pB /* Second sorted list to be merged */ -){ - struct RowSetEntry head; - struct RowSetEntry *pTail; - - pTail = &head; - assert( pA!=0 && pB!=0 ); - for(;;){ - assert( pA->pRight==0 || pA->v<=pA->pRight->v ); - assert( pB->pRight==0 || pB->v<=pB->pRight->v ); - if( pA->v<=pB->v ){ - if( pA->vv ) pTail = pTail->pRight = pA; - pA = pA->pRight; - if( pA==0 ){ - pTail->pRight = pB; - break; - } - }else{ - pTail = pTail->pRight = pB; - pB = pB->pRight; - if( pB==0 ){ - pTail->pRight = pA; - break; - } - } - } - return head.pRight; -} - -/* -** Sort all elements on the list of RowSetEntry objects into order of -** increasing v. -*/ -static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ - unsigned int i; - struct RowSetEntry *pNext, *aBucket[40]; - - memset(aBucket, 0, sizeof(aBucket)); - while( pIn ){ - pNext = pIn->pRight; - pIn->pRight = 0; - for(i=0; aBucket[i]; i++){ - pIn = rowSetEntryMerge(aBucket[i], pIn); - aBucket[i] = 0; - } - aBucket[i] = pIn; - pIn = pNext; - } - pIn = aBucket[0]; - for(i=1; ipLeft ){ - struct RowSetEntry *p; - rowSetTreeToList(pIn->pLeft, ppFirst, &p); - p->pRight = pIn; - }else{ - *ppFirst = pIn; - } - if( pIn->pRight ){ - rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast); - }else{ - *ppLast = pIn; - } - assert( (*ppLast)->pRight==0 ); -} - - -/* -** Convert a sorted list of elements (connected by pRight) into a binary -** tree with depth of iDepth. A depth of 1 means the tree contains a single -** node taken from the head of *ppList. A depth of 2 means a tree with -** three nodes. And so forth. -** -** Use as many entries from the input list as required and update the -** *ppList to point to the unused elements of the list. If the input -** list contains too few elements, then construct an incomplete tree -** and leave *ppList set to NULL. -** -** Return a pointer to the root of the constructed binary tree. -*/ -static struct RowSetEntry *rowSetNDeepTree( - struct RowSetEntry **ppList, - int iDepth -){ - struct RowSetEntry *p; /* Root of the new tree */ - struct RowSetEntry *pLeft; /* Left subtree */ - if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/ - /* Prevent unnecessary deep recursion when we run out of entries */ - return 0; - } - if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/ - /* This branch causes a *balanced* tree to be generated. A valid tree - ** is still generated without this branch, but the tree is wildly - ** unbalanced and inefficient. */ - pLeft = rowSetNDeepTree(ppList, iDepth-1); - p = *ppList; - if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/ - /* It is safe to always return here, but the resulting tree - ** would be unbalanced */ - return pLeft; - } - p->pLeft = pLeft; - *ppList = p->pRight; - p->pRight = rowSetNDeepTree(ppList, iDepth-1); - }else{ - p = *ppList; - *ppList = p->pRight; - p->pLeft = p->pRight = 0; - } - return p; -} - -/* -** Convert a sorted list of elements into a binary tree. Make the tree -** as deep as it needs to be in order to contain the entire list. -*/ -static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ - int iDepth; /* Depth of the tree so far */ - struct RowSetEntry *p; /* Current tree root */ - struct RowSetEntry *pLeft; /* Left subtree */ - - assert( pList!=0 ); - p = pList; - pList = p->pRight; - p->pLeft = p->pRight = 0; - for(iDepth=1; pList; iDepth++){ - pLeft = p; - p = pList; - pList = p->pRight; - p->pLeft = pLeft; - p->pRight = rowSetNDeepTree(&pList, iDepth); - } - return p; -} - -/* -** Extract the smallest element from the RowSet. -** Write the element into *pRowid. Return 1 on success. Return -** 0 if the RowSet is already empty. -** -** After this routine has been called, the sqlite3RowSetInsert() -** routine may not be called again. -** -** This routine may not be called after sqlite3RowSetTest() has -** been used. Older versions of RowSet allowed that, but as the -** capability was not used by the code generator, it was removed -** for code economy. -*/ -SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ - assert( p!=0 ); - assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */ - - /* Merge the forest into a single sorted list on first call */ - if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - p->pEntry = rowSetEntrySort(p->pEntry); - } - p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT; - } - - /* Return the next entry on the list */ - if( p->pEntry ){ - *pRowid = p->pEntry->v; - p->pEntry = p->pEntry->pRight; - if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/ - /* Free memory immediately, rather than waiting on sqlite3_finalize() */ - sqlite3RowSetClear(p); - } - return 1; - }else{ - return 0; - } -} - -/* -** Check to see if element iRowid was inserted into the rowset as -** part of any insert batch prior to iBatch. Return 1 or 0. -** -** If this is the first test of a new batch and if there exist entries -** on pRowSet->pEntry, then sort those entries into the forest at -** pRowSet->pForest so that they can be tested. -*/ -SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){ - struct RowSetEntry *p, *pTree; - - /* This routine is never called after sqlite3RowSetNext() */ - assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); - - /* Sort entries into the forest on the first test of a new batch. - ** To save unnecessary work, only do this when the batch number changes. - */ - if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/ - p = pRowSet->pEntry; - if( p ){ - struct RowSetEntry **ppPrevTree = &pRowSet->pForest; - if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - /* Only sort the current set of entries if they need it */ - p = rowSetEntrySort(p); - } - for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ - ppPrevTree = &pTree->pRight; - if( pTree->pLeft==0 ){ - pTree->pLeft = rowSetListToTree(p); - break; - }else{ - struct RowSetEntry *pAux, *pTail; - rowSetTreeToList(pTree->pLeft, &pAux, &pTail); - pTree->pLeft = 0; - p = rowSetEntryMerge(pAux, p); - } - } - if( pTree==0 ){ - *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); - if( pTree ){ - pTree->v = 0; - pTree->pRight = 0; - pTree->pLeft = rowSetListToTree(p); - } - } - pRowSet->pEntry = 0; - pRowSet->pLast = 0; - pRowSet->rsFlags |= ROWSET_SORTED; - } - pRowSet->iBatch = iBatch; - } - - /* Test to see if the iRowid value appears anywhere in the forest. - ** Return 1 if it does and 0 if not. - */ - for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ - p = pTree->pLeft; - while( p ){ - if( p->vpRight; - }else if( p->v>iRowid ){ - p = p->pLeft; - }else{ - return 1; - } - } - } - return 0; -} - -/************** End of rowset.c **********************************************/ -/************** Begin file pager.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of the page cache subsystem or "pager". -** -** The pager is used to access a database disk file. It implements -** atomic commit and rollback through the use of a journal file that -** is separate from the database file. The pager also implements file -** locking to prevent two processes from writing the same database -** file simultaneously, or one process from reading the database while -** another is writing. -*/ -#ifndef SQLITE_OMIT_DISKIO -/* #include "sqliteInt.h" */ -/************** Include wal.h in the middle of pager.c ***********************/ -/************** Begin file wal.h *********************************************/ -/* -** 2010 February 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface to the write-ahead logging -** system. Refer to the comments below and the header comment attached to -** the implementation of each function in log.c for further details. -*/ - -#ifndef SQLITE_WAL_H -#define SQLITE_WAL_H - -/* #include "sqliteInt.h" */ - -/* Macros for extracting appropriate sync flags for either transaction -** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)): -*/ -#define WAL_SYNC_FLAGS(X) ((X)&0x03) -#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03) - -#ifdef SQLITE_OMIT_WAL -# define sqlite3WalOpen(x,y,z) 0 -# define sqlite3WalLimit(x,y) -# define sqlite3WalClose(v,w,x,y,z) 0 -# define sqlite3WalBeginReadTransaction(y,z) 0 -# define sqlite3WalEndReadTransaction(z) -# define sqlite3WalDbsize(y) 0 -# define sqlite3WalBeginWriteTransaction(y) 0 -# define sqlite3WalEndWriteTransaction(x) 0 -# define sqlite3WalUndo(x,y,z) 0 -# define sqlite3WalSavepoint(y,z) -# define sqlite3WalSavepointUndo(y,z) 0 -# define sqlite3WalFrames(u,v,w,x,y,z) 0 -# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 -# define sqlite3WalCallback(z) 0 -# define sqlite3WalExclusiveMode(y,z) 0 -# define sqlite3WalHeapMemory(z) 0 -# define sqlite3WalFramesize(z) 0 -# define sqlite3WalFindFrame(x,y,z) 0 -# define sqlite3WalFile(x) 0 -# undef SQLITE_USE_SEH -#else - -#define WAL_SAVEPOINT_NDATA 4 - -/* Connection to a write-ahead log (WAL) file. -** There is one object of this type for each pager. -*/ -typedef struct Wal Wal; - -/* Open and close a connection to a write-ahead log. */ -SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); - -/* Set the limiting size of a WAL file. */ -SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); - -/* Used by readers to open (lock) and close (unlock) a snapshot. A -** snapshot is like a read-transaction. It is the state of the database -** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and -** preserves the current state even if the other threads or processes -** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the -** transaction and releases the lock. -*/ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); -SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); - -/* Read a page from the write-ahead log, if it is present. */ -SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *); -SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *); - -/* If the WAL is not empty, return the size of the database. */ -SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal); - -/* Obtain or release the WRITER lock. */ -SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal); -SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal); - -/* Undo any frames written (but not committed) to the log */ -SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); - -/* Return an integer that records the current (uncommitted) write -** position in the WAL */ -SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData); - -/* Move the write position of the WAL back to iFrame. Called in -** response to a ROLLBACK TO command. */ -SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData); - -/* Write a frame or frames to the log. */ -SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); - -/* Copy pages from the log to the database file */ -SQLITE_PRIVATE int sqlite3WalCheckpoint( - Wal *pWal, /* Write-ahead log connection */ - sqlite3 *db, /* Check this handle's interrupt flag */ - int eMode, /* One of PASSIVE, FULL and RESTART */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags to sync db file with (or 0) */ - int nBuf, /* Size of buffer nBuf */ - u8 *zBuf, /* Temporary buffer to use */ - int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ -); - -/* Return the value to pass to a sqlite3_wal_hook callback, the -** number of frames in the WAL at the point of the last commit since -** sqlite3WalCallback() was called. If no commits have occurred since -** the last call, then return 0. -*/ -SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal); - -/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) -** by the pager layer on the database file. -*/ -SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); - -/* Return true if the argument is non-NULL and the WAL module is using -** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. -*/ -SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); - -#ifdef SQLITE_ENABLE_SNAPSHOT -SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); -SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal); -SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal); -#endif - -#ifdef SQLITE_ENABLE_ZIPVFS -/* If the WAL file is not empty, return the number of bytes of content -** stored in each frame (i.e. the db page-size when the WAL was created). -*/ -SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); -#endif - -/* Return the sqlite3_file object for the WAL file */ -SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal); - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); -SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); -#endif - -#ifdef SQLITE_USE_SEH -SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*); -#endif - -#endif /* ifndef SQLITE_OMIT_WAL */ -#endif /* SQLITE_WAL_H */ - -/************** End of wal.h *************************************************/ -/************** Continuing where we left off in pager.c **********************/ - - -/******************* NOTES ON THE DESIGN OF THE PAGER ************************ -** -** This comment block describes invariants that hold when using a rollback -** journal. These invariants do not apply for journal_mode=WAL, -** journal_mode=MEMORY, or journal_mode=OFF. -** -** Within this comment block, a page is deemed to have been synced -** automatically as soon as it is written when PRAGMA synchronous=OFF. -** Otherwise, the page is not synced until the xSync method of the VFS -** is called successfully on the file containing the page. -** -** Definition: A page of the database file is said to be "overwriteable" if -** one or more of the following are true about the page: -** -** (a) The original content of the page as it was at the beginning of -** the transaction has been written into the rollback journal and -** synced. -** -** (b) The page was a freelist leaf page at the start of the transaction. -** -** (c) The page number is greater than the largest page that existed in -** the database file at the start of the transaction. -** -** (1) A page of the database file is never overwritten unless one of the -** following are true: -** -** (a) The page and all other pages on the same sector are overwriteable. -** -** (b) The atomic page write optimization is enabled, and the entire -** transaction other than the update of the transaction sequence -** number consists of a single page change. -** -** (2) The content of a page written into the rollback journal exactly matches -** both the content in the database when the rollback journal was written -** and the content in the database at the beginning of the current -** transaction. -** -** (3) Writes to the database file are an integer multiple of the page size -** in length and are aligned on a page boundary. -** -** (4) Reads from the database file are either aligned on a page boundary and -** an integer multiple of the page size in length or are taken from the -** first 100 bytes of the database file. -** -** (5) All writes to the database file are synced prior to the rollback journal -** being deleted, truncated, or zeroed. -** -** (6) If a super-journal file is used, then all writes to the database file -** are synced prior to the super-journal being deleted. -** -** Definition: Two databases (or the same database at two points it time) -** are said to be "logically equivalent" if they give the same answer to -** all queries. Note in particular the content of freelist leaf -** pages can be changed arbitrarily without affecting the logical equivalence -** of the database. -** -** (7) At any time, if any subset, including the empty set and the total set, -** of the unsynced changes to a rollback journal are removed and the -** journal is rolled back, the resulting database file will be logically -** equivalent to the database file at the beginning of the transaction. -** -** (8) When a transaction is rolled back, the xTruncate method of the VFS -** is called to restore the database file to the same size it was at -** the beginning of the transaction. (In some VFSes, the xTruncate -** method is a no-op, but that does not change the fact the SQLite will -** invoke it.) -** -** (9) Whenever the database file is modified, at least one bit in the range -** of bytes from 24 through 39 inclusive will be changed prior to releasing -** the EXCLUSIVE lock, thus signaling other connections on the same -** database to flush their caches. -** -** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less -** than one billion transactions. -** -** (11) A database file is well-formed at the beginning and at the conclusion -** of every transaction. -** -** (12) An EXCLUSIVE lock is held on the database file when writing to -** the database file. -** -** (13) A SHARED lock is held on the database file while reading any -** content out of the database file. -** -******************************************************************************/ - -/* -** Macros for troubleshooting. Normally turned off -*/ -#if 0 -int sqlite3PagerTrace=1; /* True to enable tracing */ -#define sqlite3DebugPrintf printf -#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; } -#else -#define PAGERTRACE(X) -#endif - -/* -** The following two macros are used within the PAGERTRACE() macros above -** to print out file-descriptors. -** -** PAGERID() takes a pointer to a Pager struct as its argument. The -** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file -** struct as its argument. -*/ -#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd)) -#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd)) - -/* -** The Pager.eState variable stores the current 'state' of a pager. A -** pager may be in any one of the seven states shown in the following -** state diagram. -** -** OPEN <------+------+ -** | | | -** V | | -** +---------> READER-------+ | -** | | | -** | V | -** |<-------WRITER_LOCKED------> ERROR -** | | ^ -** | V | -** |<------WRITER_CACHEMOD-------->| -** | | | -** | V | -** |<-------WRITER_DBMOD---------->| -** | | | -** | V | -** +<------WRITER_FINISHED-------->+ -** -** -** List of state transitions and the C [function] that performs each: -** -** OPEN -> READER [sqlite3PagerSharedLock] -** READER -> OPEN [pager_unlock] -** -** READER -> WRITER_LOCKED [sqlite3PagerBegin] -** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] -** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] -** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] -** WRITER_*** -> READER [pager_end_transaction] -** -** WRITER_*** -> ERROR [pager_error] -** ERROR -> OPEN [pager_unlock] -** -** -** OPEN: -** -** The pager starts up in this state. Nothing is guaranteed in this -** state - the file may or may not be locked and the database size is -** unknown. The database may not be read or written. -** -** * No read or write transaction is active. -** * Any lock, or no lock at all, may be held on the database file. -** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. -** -** READER: -** -** In this state all the requirements for reading the database in -** rollback (non-WAL) mode are met. Unless the pager is (or recently -** was) in exclusive-locking mode, a user-level read transaction is -** open. The database size is known in this state. -** -** A connection running with locking_mode=normal enters this state when -** it opens a read-transaction on the database and returns to state -** OPEN after the read-transaction is completed. However a connection -** running in locking_mode=exclusive (including temp databases) remains in -** this state even after the read-transaction is closed. The only way -** a locking_mode=exclusive connection can transition from READER to OPEN -** is via the ERROR state (see below). -** -** * A read transaction may be active (but a write-transaction cannot). -** * A SHARED or greater lock is held on the database file. -** * The dbSize variable may be trusted (even if a user-level read -** transaction is not active). The dbOrigSize and dbFileSize variables -** may not be trusted at this point. -** * If the database is a WAL database, then the WAL connection is open. -** * Even if a read-transaction is not open, it is guaranteed that -** there is no hot-journal in the file-system. -** -** WRITER_LOCKED: -** -** The pager moves to this state from READER when a write-transaction -** is first opened on the database. In WRITER_LOCKED state, all locks -** required to start a write-transaction are held, but no actual -** modifications to the cache or database have taken place. -** -** In rollback mode, a RESERVED or (if the transaction was opened with -** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when -** moving to this state, but the journal file is not written to or opened -** to in this state. If the transaction is committed or rolled back while -** in WRITER_LOCKED state, all that is required is to unlock the database -** file. -** -** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. -** If the connection is running with locking_mode=exclusive, an attempt -** is made to obtain an EXCLUSIVE lock on the database file. -** -** * A write transaction is active. -** * If the connection is open in rollback-mode, a RESERVED or greater -** lock is held on the database file. -** * If the connection is open in WAL-mode, a WAL write transaction -** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully -** called). -** * The dbSize, dbOrigSize and dbFileSize variables are all valid. -** * The contents of the pager cache have not been modified. -** * The journal file may or may not be open. -** * Nothing (not even the first header) has been written to the journal. -** -** WRITER_CACHEMOD: -** -** A pager moves from WRITER_LOCKED state to this state when a page is -** first modified by the upper layer. In rollback mode the journal file -** is opened (if it is not already open) and a header written to the -** start of it. The database file on disk has not been modified. -** -** * A write transaction is active. -** * A RESERVED or greater lock is held on the database file. -** * The journal file is open and the first header has been written -** to it, but the header has not been synced to disk. -** * The contents of the page cache have been modified. -** -** WRITER_DBMOD: -** -** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state -** when it modifies the contents of the database file. WAL connections -** never enter this state (since they do not modify the database file, -** just the log file). -** -** * A write transaction is active. -** * An EXCLUSIVE or greater lock is held on the database file. -** * The journal file is open and the first header has been written -** and synced to disk. -** * The contents of the page cache have been modified (and possibly -** written to disk). -** -** WRITER_FINISHED: -** -** It is not possible for a WAL connection to enter this state. -** -** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD -** state after the entire transaction has been successfully written into the -** database file. In this state the transaction may be committed simply -** by finalizing the journal file. Once in WRITER_FINISHED state, it is -** not possible to modify the database further. At this point, the upper -** layer must either commit or rollback the transaction. -** -** * A write transaction is active. -** * An EXCLUSIVE or greater lock is held on the database file. -** * All writing and syncing of journal and database data has finished. -** If no error occurred, all that remains is to finalize the journal to -** commit the transaction. If an error did occur, the caller will need -** to rollback the transaction. -** -** ERROR: -** -** The ERROR state is entered when an IO or disk-full error (including -** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it -** difficult to be sure that the in-memory pager state (cache contents, -** db size etc.) are consistent with the contents of the file-system. -** -** Temporary pager files may enter the ERROR state, but in-memory pagers -** cannot. -** -** For example, if an IO error occurs while performing a rollback, -** the contents of the page-cache may be left in an inconsistent state. -** At this point it would be dangerous to change back to READER state -** (as usually happens after a rollback). Any subsequent readers might -** report database corruption (due to the inconsistent cache), and if -** they upgrade to writers, they may inadvertently corrupt the database -** file. To avoid this hazard, the pager switches into the ERROR state -** instead of READER following such an error. -** -** Once it has entered the ERROR state, any attempt to use the pager -** to read or write data returns an error. Eventually, once all -** outstanding transactions have been abandoned, the pager is able to -** transition back to OPEN state, discarding the contents of the -** page-cache and any other in-memory state at the same time. Everything -** is reloaded from disk (and, if necessary, hot-journal rollback performed) -** when a read-transaction is next opened on the pager (transitioning -** the pager into READER state). At that point the system has recovered -** from the error. -** -** Specifically, the pager jumps into the ERROR state if: -** -** 1. An error occurs while attempting a rollback. This happens in -** function sqlite3PagerRollback(). -** -** 2. An error occurs while attempting to finalize a journal file -** following a commit in function sqlite3PagerCommitPhaseTwo(). -** -** 3. An error occurs while attempting to write to the journal or -** database file in function pagerStress() in order to free up -** memory. -** -** In other cases, the error is returned to the b-tree layer. The b-tree -** layer then attempts a rollback operation. If the error condition -** persists, the pager enters the ERROR state via condition (1) above. -** -** Condition (3) is necessary because it can be triggered by a read-only -** statement executed within a transaction. In this case, if the error -** code were simply returned to the user, the b-tree layer would not -** automatically attempt a rollback, as it assumes that an error in a -** read-only statement cannot leave the pager in an internally inconsistent -** state. -** -** * The Pager.errCode variable is set to something other than SQLITE_OK. -** * There are one or more outstanding references to pages (after the -** last reference is dropped the pager should move back to OPEN state). -** * The pager is not an in-memory pager. -** -** -** Notes: -** -** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the -** connection is open in WAL mode. A WAL connection is always in one -** of the first four states. -** -** * Normally, a connection open in exclusive mode is never in PAGER_OPEN -** state. There are two exceptions: immediately after exclusive-mode has -** been turned on (and before any read or write transactions are -** executed), and when the pager is leaving the "error state". -** -** * See also: assert_pager_state(). -*/ -#define PAGER_OPEN 0 -#define PAGER_READER 1 -#define PAGER_WRITER_LOCKED 2 -#define PAGER_WRITER_CACHEMOD 3 -#define PAGER_WRITER_DBMOD 4 -#define PAGER_WRITER_FINISHED 5 -#define PAGER_ERROR 6 - -/* -** The Pager.eLock variable is almost always set to one of the -** following locking-states, according to the lock currently held on -** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. -** This variable is kept up to date as locks are taken and released by -** the pagerLockDb() and pagerUnlockDb() wrappers. -** -** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY -** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not -** the operation was successful. In these circumstances pagerLockDb() and -** pagerUnlockDb() take a conservative approach - eLock is always updated -** when unlocking the file, and only updated when locking the file if the -** VFS call is successful. This way, the Pager.eLock variable may be set -** to a less exclusive (lower) value than the lock that is actually held -** at the system level, but it is never set to a more exclusive value. -** -** This is usually safe. If an xUnlock fails or appears to fail, there may -** be a few redundant xLock() calls or a lock may be held for longer than -** required, but nothing really goes wrong. -** -** The exception is when the database file is unlocked as the pager moves -** from ERROR to OPEN state. At this point there may be a hot-journal file -** in the file-system that needs to be rolled back (as part of an OPEN->SHARED -** transition, by the same pager or any other). If the call to xUnlock() -** fails at this point and the pager is left holding an EXCLUSIVE lock, this -** can confuse the call to xCheckReservedLock() call made later as part -** of hot-journal detection. -** -** xCheckReservedLock() is defined as returning true "if there is a RESERVED -** lock held by this process or any others". So xCheckReservedLock may -** return true because the caller itself is holding an EXCLUSIVE lock (but -** doesn't know it because of a previous error in xUnlock). If this happens -** a hot-journal may be mistaken for a journal being created by an active -** transaction in another process, causing SQLite to read from the database -** without rolling it back. -** -** To work around this, if a call to xUnlock() fails when unlocking the -** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It -** is only changed back to a real locking state after a successful call -** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition -** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK -** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE -** lock on the database file before attempting to roll it back. See function -** PagerSharedLock() for more detail. -** -** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in -** PAGER_OPEN state. -*/ -#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) - -/* -** A macro used for invoking the codec if there is one -*/ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -# define CODEC1(P,D,N,X,E) \ - if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } -# define CODEC2(P,D,N,X,E,O) \ - if( P->xCodec==0 ){ O=(char*)D; }else \ - if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; } -#else -# define CODEC1(P,D,N,X,E) /* NO-OP */ -# define CODEC2(P,D,N,X,E,O) O=(char*)D -#endif -/* END SQLCIPHER */ - -/* -** The maximum allowed sector size. 64KiB. If the xSectorsize() method -** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. -** This could conceivably cause corruption following a power failure on -** such a system. This is currently an undocumented limit. -*/ -#define MAX_SECTOR_SIZE 0x10000 - - -/* -** An instance of the following structure is allocated for each active -** savepoint and statement transaction in the system. All such structures -** are stored in the Pager.aSavepoint[] array, which is allocated and -** resized using sqlite3Realloc(). -** -** When a savepoint is created, the PagerSavepoint.iHdrOffset field is -** set to 0. If a journal-header is written into the main journal while -** the savepoint is active, then iHdrOffset is set to the byte offset -** immediately following the last journal record written into the main -** journal before the journal-header. This is required during savepoint -** rollback (see pagerPlaybackSavepoint()). -*/ -typedef struct PagerSavepoint PagerSavepoint; -struct PagerSavepoint { - i64 iOffset; /* Starting offset in main journal */ - i64 iHdrOffset; /* See above */ - 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 -}; - -/* -** Bits of the Pager.doNotSpill flag. See further description below. -*/ -#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */ -#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */ -#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */ - -/* -** An open page cache is an instance of struct Pager. A description of -** some of the more important member variables follows: -** -** eState -** -** The current 'state' of the pager object. See the comment and state -** diagram above for a description of the pager state. -** -** eLock -** -** For a real on-disk database, the current lock held on the database file - -** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. -** -** For a temporary or in-memory database (neither of which require any -** locks), this variable is always set to EXCLUSIVE_LOCK. Since such -** databases always have Pager.exclusiveMode==1, this tricks the pager -** logic into thinking that it already has all the locks it will ever -** need (and no reason to release them). -** -** In some (obscure) circumstances, this variable may also be set to -** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for -** details. -** -** changeCountDone -** -** This boolean variable is used to make sure that the change-counter -** (the 4-byte header field at byte offset 24 of the database file) is -** not updated more often than necessary. -** -** It is set to true when the change-counter field is updated, which -** can only happen if an exclusive lock is held on the database file. -** It is cleared (set to false) whenever an exclusive lock is -** relinquished on the database file. Each time a transaction is committed, -** The changeCountDone flag is inspected. If it is true, the work of -** updating the change-counter is omitted for the current transaction. -** -** This mechanism means that when running in exclusive mode, a connection -** need only update the change-counter once, for the first transaction -** committed. -** -** setSuper -** -** When PagerCommitPhaseOne() is called to commit a transaction, it may -** (or may not) specify a super-journal name to be written into the -** journal file before it is synced to disk. -** -** Whether or not a journal file contains a super-journal pointer affects -** the way in which the journal file is finalized after the transaction is -** committed or rolled back when running in "journal_mode=PERSIST" mode. -** If a journal file does not contain a super-journal pointer, it is -** finalized by overwriting the first journal header with zeroes. If -** it does contain a super-journal pointer the journal file is finalized -** by truncating it to zero bytes, just as if the connection were -** running in "journal_mode=truncate" mode. -** -** Journal files that contain super-journal pointers cannot be finalized -** simply by overwriting the first journal-header with zeroes, as the -** super-journal pointer could interfere with hot-journal rollback of any -** subsequently interrupted transaction that reuses the journal file. -** -** The flag is cleared as soon as the journal file is finalized (either -** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the -** journal file from being successfully finalized, the setSuper flag -** is cleared anyway (and the pager will move to ERROR state). -** -** doNotSpill -** -** This variables control the behavior of cache-spills (calls made by -** the pcache module to the pagerStress() routine to write cached data -** to the file-system in order to free up memory). -** -** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set, -** writing to the database from pagerStress() is disabled altogether. -** The SPILLFLAG_ROLLBACK case is done in a very obscure case that -** comes up during savepoint rollback that requires the pcache module -** to allocate a new page to prevent the journal file from being written -** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF -** case is a user preference. -** -** If the SPILLFLAG_NOSYNC bit is set, writing to the database from -** pagerStress() is permitted, but syncing the journal file is not. -** This flag is set by sqlite3PagerWrite() when the file-system sector-size -** is larger than the database page-size in order to prevent a journal sync -** from happening in between the journalling of two pages on the same sector. -** -** subjInMemory -** -** This is a boolean variable. If true, then any required sub-journal -** is opened as an in-memory journal file. If false, then in-memory -** sub-journals are only used for in-memory pager files. -** -** This variable is updated by the upper layer each time a new -** write-transaction is opened. -** -** dbSize, dbOrigSize, dbFileSize -** -** Variable dbSize is set to the number of pages in the database file. -** It is valid in PAGER_READER and higher states (all states except for -** OPEN and ERROR). -** -** dbSize is set based on the size of the database file, which may be -** larger than the size of the database (the value stored at offset -** 28 of the database header by the btree). If the size of the file -** is not an integer multiple of the page-size, the value stored in -** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). -** Except, any file that is greater than 0 bytes in size is considered -** to have at least one page. (i.e. a 1KB file with 2K page-size leads -** to dbSize==1). -** -** During a write-transaction, if pages with page-numbers greater than -** dbSize are modified in the cache, dbSize is updated accordingly. -** Similarly, if the database is truncated using PagerTruncateImage(), -** dbSize is updated. -** -** Variables dbOrigSize and dbFileSize are valid in states -** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize -** variable at the start of the transaction. It is used during rollback, -** and to determine whether or not pages need to be journalled before -** being modified. -** -** Throughout a write-transaction, dbFileSize contains the size of -** the file on disk in pages. It is set to a copy of dbSize when the -** write-transaction is first opened, and updated when VFS calls are made -** to write or truncate the database file on disk. -** -** The only reason the dbFileSize variable is required is to suppress -** unnecessary calls to xTruncate() after committing a transaction. If, -** when a transaction is committed, the dbFileSize variable indicates -** that the database file is larger than the database image (Pager.dbSize), -** pager_truncate() is called. The pager_truncate() call uses xFilesize() -** to measure the database file on disk, and then truncates it if required. -** dbFileSize is not used when rolling back a transaction. In this case -** pager_truncate() is called unconditionally (which means there may be -** a call to xFilesize() that is not strictly required). In either case, -** pager_truncate() may cause the file to become smaller or larger. -** -** dbHintSize -** -** The dbHintSize variable is used to limit the number of calls made to -** the VFS xFileControl(FCNTL_SIZE_HINT) method. -** -** dbHintSize is set to a copy of the dbSize variable when a -** write-transaction is opened (at the same time as dbFileSize and -** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, -** dbHintSize is increased to the number of pages that correspond to the -** size-hint passed to the method call. See pager_write_pagelist() for -** details. -** -** errCode -** -** The Pager.errCode variable is only ever used in PAGER_ERROR state. It -** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode -** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX -** sub-codes. -** -** syncFlags, walSyncFlags -** -** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03). -** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode -** and contains the flags used to sync the checkpoint operations in the -** lower two bits, and sync flags used for transaction commits in the WAL -** file in bits 0x04 and 0x08. In other words, to get the correct sync flags -** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct -** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note -** that with synchronous=NORMAL in WAL mode, transaction commit is not synced -** meaning that the 0x04 and 0x08 bits are both zero. -*/ -struct Pager { - sqlite3_vfs *pVfs; /* OS functions to use for IO */ - u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ - u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ - u8 useJournal; /* Use a rollback journal on this file */ - u8 noSync; /* Do not sync the journal if true */ - u8 fullSync; /* Do extra syncs of the journal for robustness */ - u8 extraSync; /* sync directory after journal delete */ - u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ - u8 walSyncFlags; /* See description above */ - u8 tempFile; /* zFilename is a temporary or immutable file */ - u8 noLock; /* Do not lock (except in WAL mode) */ - u8 readOnly; /* True for a read-only database */ - u8 memDb; /* True to inhibit all file I/O */ - u8 memVfs; /* VFS-implemented memory database */ - - /************************************************************************** - ** The following block contains those class members that change during - ** routine operation. Class members not in this block are either fixed - ** when the pager is first created or else only change when there is a - ** significant mode change (such as changing the page_size, locking_mode, - ** or the journal_mode). From another view, these class members describe - ** the "state" of the pager, while other class members describe the - ** "configuration" of the pager. - */ - u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ - u8 eLock; /* Current lock held on database file */ - u8 changeCountDone; /* Set after incrementing the change-counter */ - u8 setSuper; /* Super-jrnl name is written into jrnl */ - u8 doNotSpill; /* Do not spill the cache when non-zero */ - u8 subjInMemory; /* True to use in-memory sub-journals */ - u8 bUseFetch; /* True to use xFetch() */ - u8 hasHeldSharedLock; /* True if a shared lock has ever been held */ - Pgno dbSize; /* Number of pages in the database */ - Pgno dbOrigSize; /* dbSize before the current transaction */ - Pgno dbFileSize; /* Number of pages in the database file */ - Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ - int errCode; /* One of several kinds of errors */ - int nRec; /* Pages journalled since last j-header written */ - u32 cksumInit; /* Quasi-random value added to every checksum */ - u32 nSubRec; /* Number of records written to sub-journal */ - Bitvec *pInJournal; /* One bit for each page in the database file */ - sqlite3_file *fd; /* File descriptor for database */ - sqlite3_file *jfd; /* File descriptor for main journal */ - sqlite3_file *sjfd; /* File descriptor for sub-journal */ - i64 journalOff; /* Current write offset in the journal file */ - i64 journalHdr; /* Byte offset to previous journal header */ - sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ - PagerSavepoint *aSavepoint; /* Array of active savepoints */ - int nSavepoint; /* Number of elements in aSavepoint[] */ - u32 iDataVersion; /* Changes whenever database content changes */ - char dbFileVers[16]; /* Changes whenever database file changes */ - - int nMmapOut; /* Number of mmap pages currently outstanding */ - sqlite3_int64 szMmap; /* Desired maximum mmap size */ - PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ - /* - ** End of the routinely-changing class members - ***************************************************************************/ - - u16 nExtra; /* Add this many bytes to each in-memory page */ - i16 nReserve; /* Number of unused bytes at end of each page */ - u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ - u32 sectorSize; /* Assumed sector size during rollback */ - 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 */ - int (*xBusyHandler)(void*); /* Function to call when busy */ - void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - u32 aStat[4]; /* Total cache hits, misses, writes, spills */ -#ifdef SQLITE_TEST - int nRead; /* Database pages read */ -#endif - void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ - int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ - void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ - void (*xCodecFree)(void*); /* Destructor for the codec */ - void *pCodec; /* First argument to xCodec... methods */ -#endif -/* END SQLCIPHER */ - char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ - PCache *pPCache; /* Pointer to page cache object */ -#ifndef SQLITE_OMIT_WAL - Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ - char *zWal; /* File name for write-ahead log */ -#endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3 *dbWal; -#endif -}; - -/* -** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains -** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS -** or CACHE_WRITE to sqlite3_db_status(). -*/ -#define PAGER_STAT_HIT 0 -#define PAGER_STAT_MISS 1 -#define PAGER_STAT_WRITE 2 -#define PAGER_STAT_SPILL 3 - -/* -** The following global variables hold counters used for -** testing purposes only. These variables do not exist in -** a non-testing build. These variables are not thread-safe. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ -SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ -SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ -# define PAGER_INCR(v) v++ -#else -# define PAGER_INCR(v) -#endif - - - -/* -** Journal files begin with the following magic string. The data -** was obtained from /dev/random. It is used only as a sanity check. -** -** Since version 2.8.0, the journal format contains additional sanity -** checking information. If the power fails while the journal is being -** written, semi-random garbage data might appear in the journal -** file after power is restored. If an attempt is then made -** to roll the journal back, the database could be corrupted. The additional -** sanity checking data is an attempt to discover the garbage in the -** journal and ignore it. -** -** The sanity checking information for the new journal format consists -** of a 32-bit checksum on each page of data. The checksum covers both -** the page number and the pPager->pageSize bytes of data for the page. -** This cksum is initialized to a 32-bit random value that appears in the -** journal file right after the header. The random initializer is important, -** because garbage data that appears at the end of a journal is likely -** data that was once in other files that have now been deleted. If the -** garbage data came from an obsolete journal file, the checksums might -** be correct. But by initializing the checksum to random value which -** is different for every journal, we minimize that risk. -*/ -static const unsigned char aJournalMagic[] = { - 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, -}; - -/* -** The size of the of each page record in the journal is given by -** the following macro. -*/ -#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) - -/* -** The journal header size for this pager. This is usually the same -** size as a single disk sector. See also setSectorSize(). -*/ -#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) - -/* -** The macro MEMDB is true if we are dealing with an in-memory database. -** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, -** the value of MEMDB will be a constant and the compiler will optimize -** out code that would never execute. -*/ -#ifdef SQLITE_OMIT_MEMORYDB -# define MEMDB 0 -#else -# define MEMDB pPager->memDb -#endif - -/* -** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch -** interfaces to access the database using memory-mapped I/O. -*/ -#if SQLITE_MAX_MMAP_SIZE>0 -# define USEFETCH(x) ((x)->bUseFetch) -#else -# define USEFETCH(x) 0 -#endif - -#ifdef SQLITE_DIRECT_OVERFLOW_READ -/* -** Return true if page pgno can be read directly from the database file -** by the b-tree layer. This is the case if: -** -** (1) the database file is open -** (2) the VFS for the database is able to do unaligned sub-page reads -** (3) there are no dirty pages in the cache, and -** (4) the desired page is not currently in the wal file. -*/ -SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ - assert( pPager!=0 ); - assert( pPager->fd!=0 ); - if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */ - if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( pPager->xCodec!=0 ) return 0; -#endif -/* END SQLCIPHER */ -#ifndef SQLITE_OMIT_WAL - if( pPager->pWal ){ - u32 iRead = 0; - (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - if( iRead ) return 0; /* Case (4) */ - } -#endif - assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 ); - if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd) - & SQLITE_IOCAP_SUBPAGE_READ)==0 ){ - return 0; /* Case (2) */ - } - return 1; -} -#endif - -#ifndef SQLITE_OMIT_WAL -# define pagerUseWal(x) ((x)->pWal!=0) -#else -# define pagerUseWal(x) 0 -# define pagerRollbackWal(x) 0 -# define pagerWalFrames(v,w,x,y) 0 -# define pagerOpenWalIfPresent(z) SQLITE_OK -# define pagerBeginReadTransaction(z) SQLITE_OK -#endif - -#ifndef NDEBUG -/* -** Usage: -** -** assert( assert_pager_state(pPager) ); -** -** This function runs many asserts to try to find inconsistencies in -** the internal state of the Pager object. -*/ -static int assert_pager_state(Pager *p){ - Pager *pPager = p; - - /* State must be valid. */ - assert( p->eState==PAGER_OPEN - || p->eState==PAGER_READER - || p->eState==PAGER_WRITER_LOCKED - || p->eState==PAGER_WRITER_CACHEMOD - || p->eState==PAGER_WRITER_DBMOD - || p->eState==PAGER_WRITER_FINISHED - || p->eState==PAGER_ERROR - ); - - /* Regardless of the current state, a temp-file connection always behaves - ** as if it has an exclusive lock on the database file. It never updates - ** the change-counter field, so the changeCountDone flag is always set. - */ - assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); - assert( p->tempFile==0 || pPager->changeCountDone ); - - /* If the useJournal flag is clear, the journal-mode must be "OFF". - ** And if the journal-mode is "OFF", the journal file must not be open. - */ - assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal ); - assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) ); - - /* Check that MEMDB implies noSync. And an in-memory journal. Since - ** this means an in-memory pager performs no IO at all, it cannot encounter - ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing - ** a journal file. (although the in-memory journal implementation may - ** return SQLITE_IOERR_NOMEM while the journal file is being written). It - ** is therefore not possible for an in-memory pager to enter the ERROR - ** state. - */ - if( MEMDB ){ - assert( !isOpen(p->fd) ); - assert( p->noSync ); - assert( p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_MEMORY - ); - assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); - assert( pagerUseWal(p)==0 ); - } - - /* If changeCountDone is set, a RESERVED lock or greater must be held - ** on the file. - */ - assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); - assert( p->eLock!=PENDING_LOCK ); - - switch( p->eState ){ - case PAGER_OPEN: - assert( !MEMDB ); - assert( pPager->errCode==SQLITE_OK ); - assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile ); - break; - - case PAGER_READER: - assert( pPager->errCode==SQLITE_OK ); - assert( p->eLock!=UNKNOWN_LOCK ); - assert( p->eLock>=SHARED_LOCK ); - break; - - case PAGER_WRITER_LOCKED: - assert( p->eLock!=UNKNOWN_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - if( !pagerUseWal(pPager) ){ - assert( p->eLock>=RESERVED_LOCK ); - } - assert( pPager->dbSize==pPager->dbOrigSize ); - assert( pPager->dbOrigSize==pPager->dbFileSize ); - assert( pPager->dbOrigSize==pPager->dbHintSize ); - assert( pPager->setSuper==0 ); - break; - - case PAGER_WRITER_CACHEMOD: - assert( p->eLock!=UNKNOWN_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - if( !pagerUseWal(pPager) ){ - /* It is possible that if journal_mode=wal here that neither the - ** journal file nor the WAL file are open. This happens during - ** a rollback transaction that switches from journal_mode=off - ** to journal_mode=wal. - */ - assert( p->eLock>=RESERVED_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - ); - } - assert( pPager->dbOrigSize==pPager->dbFileSize ); - assert( pPager->dbOrigSize==pPager->dbHintSize ); - break; - - case PAGER_WRITER_DBMOD: - assert( p->eLock==EXCLUSIVE_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - assert( !pagerUseWal(pPager) ); - assert( p->eLock>=EXCLUSIVE_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) - ); - assert( pPager->dbOrigSize<=pPager->dbHintSize ); - break; - - case PAGER_WRITER_FINISHED: - assert( p->eLock==EXCLUSIVE_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - assert( !pagerUseWal(pPager) ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) - ); - break; - - case PAGER_ERROR: - /* There must be at least one outstanding reference to the pager if - ** in ERROR state. Otherwise the pager should have already dropped - ** back to OPEN state. - */ - assert( pPager->errCode!=SQLITE_OK ); - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile ); - break; - } - - return 1; -} -#endif /* ifndef NDEBUG */ - -#ifdef SQLITE_DEBUG -/* -** Return a pointer to a human readable string in a static buffer -** containing the state of the Pager object passed as an argument. This -** is intended to be used within debuggers. For example, as an alternative -** to "print *pPager" in gdb: -** -** (gdb) printf "%s", print_pager_state(pPager) -** -** This routine has external linkage in order to suppress compiler warnings -** about an unused function. It is enclosed within SQLITE_DEBUG and so does -** not appear in normal builds. -*/ -char *print_pager_state(Pager *p){ - static char zRet[1024]; - - sqlite3_snprintf(1024, zRet, - "Filename: %s\n" - "State: %s errCode=%d\n" - "Lock: %s\n" - "Locking mode: locking_mode=%s\n" - "Journal mode: journal_mode=%s\n" - "Backing store: tempFile=%d memDb=%d useJournal=%d\n" - "Journal: journalOff=%lld journalHdr=%lld\n" - "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n" - , p->zFilename - , p->eState==PAGER_OPEN ? "OPEN" : - p->eState==PAGER_READER ? "READER" : - p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" : - p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : - p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : - p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : - p->eState==PAGER_ERROR ? "ERROR" : "?error?" - , (int)p->errCode - , p->eLock==NO_LOCK ? "NO_LOCK" : - p->eLock==RESERVED_LOCK ? "RESERVED" : - p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : - p->eLock==SHARED_LOCK ? "SHARED" : - p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?" - , p->exclusiveMode ? "exclusive" : "normal" - , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : - p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : - p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" : - p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" : - p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : - p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" - , (int)p->tempFile, (int)p->memDb, (int)p->useJournal - , p->journalOff, p->journalHdr - , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize - ); - - return zRet; -} -#endif - -/* Forward references to the various page getters */ -static int getPageNormal(Pager*,Pgno,DbPage**,int); -static int getPageError(Pager*,Pgno,DbPage**,int); -#if SQLITE_MAX_MMAP_SIZE>0 -static int getPageMMap(Pager*,Pgno,DbPage**,int); -#endif - -/* -** Set the Pager.xGet method for the appropriate routine used to fetch -** content from the pager. -*/ -static void setGetterMethod(Pager *pPager){ - if( pPager->errCode ){ - pPager->xGet = getPageError; -#if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - && pPager->xCodec==0 -#endif -/* END SQLCIPHER */ - ){ - pPager->xGet = getPageMMap; -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - }else{ - pPager->xGet = getPageNormal; - } -} - -/* -** Return true if it is necessary to write page *pPg into the sub-journal. -** A page needs to be written into the sub-journal if there exists one -** or more open savepoints for which: -** -** * The page-number is less than or equal to PagerSavepoint.nOrig, and -** * The bit corresponding to the page-number is not set in -** PagerSavepoint.pInSavepoint. -*/ -static int subjRequiresPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - PagerSavepoint *p; - Pgno pgno = pPg->pgno; - int i; - for(i=0; inSavepoint; i++){ - p = &pPager->aSavepoint[i]; - if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){ - for(i=i+1; inSavepoint; i++){ - pPager->aSavepoint[i].bTruncateOnRelease = 0; - } - return 1; - } - } - return 0; -} - -#ifdef SQLITE_DEBUG -/* -** Return true if the page is already in the journal file. -*/ -static int pageInJournal(Pager *pPager, PgHdr *pPg){ - return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno); -} -#endif - -/* -** Read a 32-bit integer from the given file descriptor. Store the integer -** that is read in *pRes. Return SQLITE_OK if everything worked, or an -** error code is something goes wrong. -** -** All values are stored on disk as big-endian. -*/ -static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){ - unsigned char ac[4]; - int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); - if( rc==SQLITE_OK ){ - *pRes = sqlite3Get4byte(ac); - } - return rc; -} - -/* -** Write a 32-bit integer into a string buffer in big-endian byte order. -*/ -#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) - - -/* -** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK -** on success or an error code is something goes wrong. -*/ -static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ - char ac[4]; - put32bits(ac, val); - return sqlite3OsWrite(fd, ac, 4, offset); -} - -/* -** Unlock the database file to level eLock, which must be either NO_LOCK -** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() -** succeeds, set the Pager.eLock variable to match the (attempted) new lock. -** -** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it. See the comment above the #define of -** UNKNOWN_LOCK for an explanation of this. -*/ -static int pagerUnlockDb(Pager *pPager, int eLock){ - int rc = SQLITE_OK; - - assert( !pPager->exclusiveMode || pPager->eLock==eLock ); - assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); - assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); - if( isOpen(pPager->fd) ){ - assert( pPager->eLock>=eLock ); - rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock); - if( pPager->eLock!=UNKNOWN_LOCK ){ - pPager->eLock = (u8)eLock; - } - IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) - } - pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */ - return rc; -} - -/* -** Lock the database file to level eLock, which must be either SHARED_LOCK, -** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the -** Pager.eLock variable to the new locking state. -** -** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. -** See the comment above the #define of UNKNOWN_LOCK for an explanation -** of this. -*/ -static int pagerLockDb(Pager *pPager, int eLock){ - int rc = SQLITE_OK; - - assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); - if( pPager->eLockeLock==UNKNOWN_LOCK ){ - rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock); - if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ - pPager->eLock = (u8)eLock; - IOTRACE(("LOCK %p %d\n", pPager, eLock)) - } - } - return rc; -} - -/* -** This function determines whether or not the atomic-write or -** atomic-batch-write optimizations can be used with this pager. The -** atomic-write optimization can be used if: -** -** (a) the value returned by OsDeviceCharacteristics() indicates that -** a database page may be written atomically, and -** (b) the value returned by OsSectorSize() is less than or equal -** to the page size. -** -** If it can be used, then the value returned is the size of the journal -** file when it contains rollback data for exactly one page. -** -** The atomic-batch-write optimization can be used if OsDeviceCharacteristics() -** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is -** returned in this case. -** -** If neither optimization can be used, 0 is returned. -*/ -static int jrnlBufferSize(Pager *pPager){ - assert( !MEMDB ); - -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) - int dc; /* Device characteristics */ - - assert( isOpen(pPager->fd) ); - dc = sqlite3OsDeviceCharacteristics(pPager->fd); -#else - UNUSED_PARAMETER(pPager); -#endif - -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){ - return -1; - } -#endif - -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - { - int nSector = pPager->sectorSize; - int szPage = pPager->pageSize; - - assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); - assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); - if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ - return 0; - } - } - - return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); -#endif - - return 0; -} - -/* -** If SQLITE_CHECK_PAGES is defined then we do some sanity checking -** on the cache using a hash function. This is used for testing -** and debugging only. -*/ -#ifdef SQLITE_CHECK_PAGES -/* -** Return a 32-bit hash of the page data for pPage. -*/ -static u32 pager_datahash(int nByte, unsigned char *pData){ - u32 hash = 0; - int i; - for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData); -} -static void pager_set_pagehash(PgHdr *pPage){ - pPage->pageHash = pager_pagehash(pPage); -} - -/* -** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES -** is defined, and NDEBUG is not defined, an assert() statement checks -** that the page is either dirty or still matches the calculated page-hash. -*/ -#define CHECK_PAGE(x) checkPage(x) -static void checkPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - assert( pPager->eState!=PAGER_ERROR ); - assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); -} - -#else -#define pager_datahash(X,Y) 0 -#define pager_pagehash(X) 0 -#define pager_set_pagehash(X) -#define CHECK_PAGE(x) -#endif /* SQLITE_CHECK_PAGES */ - -/* -** When this is called the journal file for pager pPager must be open. -** This function attempts to read a super-journal file name from the -** end of the file and, if successful, copies it into memory supplied -** by the caller. See comments above writeSuperJournal() for the format -** used to store a super-journal file name at the end of a journal file. -** -** zSuper must point to a buffer of at least nSuper bytes allocated by -** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is -** enough space to write the super-journal name). If the super-journal -** name in the journal is longer than nSuper bytes (including a -** nul-terminator), then this is handled as if no super-journal name -** were present in the journal. -** -** If a super-journal file name is present at the end of the journal -** file, then it is copied into the buffer pointed to by zSuper. A -** nul-terminator byte is appended to the buffer following the -** super-journal file name. -** -** If it is determined that no super-journal file name is present -** zSuper[0] is set to 0 and SQLITE_OK returned. -** -** If an error occurs while reading from the journal file, an SQLite -** error code is returned. -*/ -static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){ - int rc; /* Return code */ - u32 len; /* Length in bytes of super-journal name */ - i64 szJ; /* Total size in bytes of journal file pJrnl */ - u32 cksum; /* MJ checksum value read from journal */ - u32 u; /* Unsigned loop counter */ - unsigned char aMagic[8]; /* A buffer to hold the magic header */ - zSuper[0] = '\0'; - - if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) - || szJ<16 - || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) - || len>=nSuper - || len>szJ-16 - || len==0 - || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) - || memcmp(aMagic, aJournalMagic, 8) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len)) - ){ - return rc; - } - - /* See if the checksum matches the super-journal name */ - for(u=0; ujournalOff, assuming a sector -** size of pPager->sectorSize bytes. -** -** i.e for a sector size of 512: -** -** Pager.journalOff Return value -** --------------------------------------- -** 0 0 -** 512 512 -** 100 512 -** 2000 2048 -** -*/ -static i64 journalHdrOffset(Pager *pPager){ - i64 offset = 0; - i64 c = pPager->journalOff; - if( c ){ - offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); - } - assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); - assert( offset>=c ); - assert( (offset-c)jfd) ); - assert( !sqlite3JournalIsInMemory(pPager->jfd) ); - if( pPager->journalOff ){ - const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */ - - IOTRACE(("JZEROHDR %p\n", pPager)) - if( doTruncate || iLimit==0 ){ - rc = sqlite3OsTruncate(pPager->jfd, 0); - }else{ - static const char zeroHdr[28] = {0}; - rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); - } - if( rc==SQLITE_OK && !pPager->noSync ){ - rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); - } - - /* At this point the transaction is committed but the write lock - ** is still held on the file. If there is a size limit configured for - ** the persistent journal and the journal file currently consumes more - ** space than that limit allows for, truncate it now. There is no need - ** to sync the file following this operation. - */ - if( rc==SQLITE_OK && iLimit>0 ){ - i64 sz; - rc = sqlite3OsFileSize(pPager->jfd, &sz); - if( rc==SQLITE_OK && sz>iLimit ){ - rc = sqlite3OsTruncate(pPager->jfd, iLimit); - } - } - } - return rc; -} - -/* -** The journal file must be open when this routine is called. A journal -** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the -** current location. -** -** The format for the journal header is as follows: -** - 8 bytes: Magic identifying journal format. -** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. -** - 4 bytes: Random number used for page hash. -** - 4 bytes: Initial database page count. -** - 4 bytes: Sector size used by the process that wrote this journal. -** - 4 bytes: Database page size. -** -** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. -*/ -static int writeJournalHdr(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ - u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */ - u32 nWrite; /* Bytes of header sector written */ - int ii; /* Loop counter */ - - assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ - - if( nHeader>JOURNAL_HDR_SZ(pPager) ){ - nHeader = JOURNAL_HDR_SZ(pPager); - } - - /* If there are active savepoints and any of them were created - ** since the most recent journal header was written, update the - ** PagerSavepoint.iHdrOffset fields now. - */ - for(ii=0; iinSavepoint; ii++){ - if( pPager->aSavepoint[ii].iHdrOffset==0 ){ - pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; - } - } - - pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); - - /* - ** Write the nRec Field - the number of page records that follow this - ** journal header. Normally, zero is written to this value at this time. - ** After the records are added to the journal (and the journal synced, - ** if in full-sync mode), the zero is overwritten with the true number - ** of records (see syncJournal()). - ** - ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When - ** reading the journal this value tells SQLite to assume that the - ** rest of the journal file contains valid page records. This assumption - ** is dangerous, as if a failure occurred whilst writing to the journal - ** file it may contain some garbage data. There are two scenarios - ** where this risk can be ignored: - ** - ** * When the pager is in no-sync mode. Corruption can follow a - ** power failure in this case anyway. - ** - ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees - ** that garbage data is never appended to the journal file. - */ - assert( isOpen(pPager->fd) || pPager->noSync ); - if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) - || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) - ){ - memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); - put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); - }else{ - memset(zHeader, 0, sizeof(aJournalMagic)+4); - } - - - - /* The random check-hash initializer */ - if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ - sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - } -#ifdef SQLITE_DEBUG - else{ - /* The Pager.cksumInit variable is usually randomized above to protect - ** against there being existing records in the journal file. This is - ** dangerous, as following a crash they may be mistaken for records - ** written by the current transaction and rolled back into the database - ** file, causing corruption. The following assert statements verify - ** that this is not required in "journal_mode=memory" mode, as in that - ** case the journal file is always 0 bytes in size at this point. - ** It is advantageous to avoid the sqlite3_randomness() call if possible - ** as it takes the global PRNG mutex. */ - i64 sz = 0; - sqlite3OsFileSize(pPager->jfd, &sz); - assert( sz==0 ); - assert( pPager->journalOff==journalHdrOffset(pPager) ); - assert( sqlite3JournalIsInMemory(pPager->jfd) ); - } -#endif - put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); - - /* The initial database size */ - put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); - /* The assumed sector size for this process */ - put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); - - /* The page size */ - put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); - - /* Initializing the tail of the buffer is not necessary. Everything - ** works find if the following memset() is omitted. But initializing - ** the memory prevents valgrind from complaining, so we are willing to - ** take the performance hit. - */ - memset(&zHeader[sizeof(aJournalMagic)+20], 0, - nHeader-(sizeof(aJournalMagic)+20)); - - /* In theory, it is only necessary to write the 28 bytes that the - ** journal header consumes to the journal file here. Then increment the - ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next - ** record is written to the following sector (leaving a gap in the file - ** that will be implicitly filled in by the OS). - ** - ** However it has been discovered that on some systems this pattern can - ** be significantly slower than contiguously writing data to the file, - ** even if that means explicitly writing data to the block of - ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what - ** is done. - ** - ** The loop is required here in case the sector-size is larger than the - ** database page size. Since the zHeader buffer is only Pager.pageSize - ** bytes in size, more than one call to sqlite3OsWrite() may be required - ** to populate the entire journal header sector. - */ - for(nWrite=0; rc==SQLITE_OK&&nWritejournalHdr, nHeader)) - rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); - assert( pPager->journalHdr <= pPager->journalOff ); - pPager->journalOff += nHeader; - } - - return rc; -} - -/* -** The journal file must be open when this is called. A journal header file -** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal -** file. The current location in the journal file is given by -** pPager->journalOff. See comments above function writeJournalHdr() for -** a description of the journal header format. -** -** If the header is read successfully, *pNRec is set to the number of -** page records following this header and *pDbSize is set to the size of the -** database before the transaction began, in pages. Also, pPager->cksumInit -** is set to the value read from the journal header. SQLITE_OK is returned -** in this case. -** -** If the journal header file appears to be corrupted, SQLITE_DONE is -** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes -** cannot be read from the journal file an error code is returned. -*/ -static int readJournalHdr( - Pager *pPager, /* Pager object */ - int isHot, - i64 journalSize, /* Size of the open journal file in bytes */ - u32 *pNRec, /* OUT: Value read from the nRec field */ - u32 *pDbSize /* OUT: Value of original database size field */ -){ - int rc; /* Return code */ - unsigned char aMagic[8]; /* A buffer to hold the magic header */ - i64 iHdrOff; /* Offset of journal header being read */ - - assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ - - /* Advance Pager.journalOff to the start of the next sector. If the - ** journal file is too small for there to be a header stored at this - ** point, return SQLITE_DONE. - */ - pPager->journalOff = journalHdrOffset(pPager); - if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ - return SQLITE_DONE; - } - iHdrOff = pPager->journalOff; - - /* Read in the first 8 bytes of the journal header. If they do not match - ** the magic string found at the start of each journal header, return - ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, - ** proceed. - */ - if( isHot || iHdrOff!=pPager->journalHdr ){ - rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); - if( rc ){ - return rc; - } - if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ - return SQLITE_DONE; - } - } - - /* Read the first three 32-bit fields of the journal header: The nRec - ** field, the checksum-initializer and the database size at the start - ** of the transaction. Return an error code if anything goes wrong. - */ - if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize)) - ){ - return rc; - } - - if( pPager->journalOff==0 ){ - u32 iPageSize; /* Page-size field of journal header */ - u32 iSectorSize; /* Sector-size field of journal header */ - - /* Read the page-size and sector-size journal header fields. */ - if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) - ){ - return rc; - } - - /* Versions of SQLite prior to 3.5.8 set the page-size field of the - ** journal header to zero. In this case, assume that the Pager.pageSize - ** variable is already set to the correct page size. - */ - if( iPageSize==0 ){ - iPageSize = pPager->pageSize; - } - - /* Check that the values read from the page-size and sector-size fields - ** are within range. To be 'in range', both values need to be a power - ** of two greater than or equal to 512 or 32, and not greater than their - ** respective compile time maximum limits. - */ - if( iPageSize<512 || iSectorSize<32 - || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE - || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 - ){ - /* If the either the page-size or sector-size in the journal-header is - ** invalid, then the process that wrote the journal-header must have - ** crashed before the header was synced. In this case stop reading - ** the journal file here. - */ - return SQLITE_DONE; - } - - /* Update the page-size to match the value read from the journal. - ** Use a testcase() macro to make sure that malloc failure within - ** PagerSetPagesize() is tested. - */ - rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1); - testcase( rc!=SQLITE_OK ); - - /* Update the assumed sector-size to match the value used by - ** the process that created this journal. If this journal was - ** created by a process other than this one, then this routine - ** is being called from within pager_playback(). The local value - ** of Pager.sectorSize is restored at the end of that routine. - */ - pPager->sectorSize = iSectorSize; - } - - pPager->journalOff += JOURNAL_HDR_SZ(pPager); - return rc; -} - - -/* -** Write the supplied super-journal name into the journal file for pager -** pPager at the current location. The super-journal name must be the last -** thing written to a journal file. If the pager is in full-sync mode, the -** journal file descriptor is advanced to the next sector boundary before -** anything is written. The format is: -** -** + 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. -** + 8 bytes: aJournalMagic[]. -** -** The super-journal page checksum is the sum of the bytes in the super-journal -** name, where each byte is interpreted as a signed 8-bit integer. -** -** If zSuper is a NULL pointer (occurs for a single database transaction), -** this call is a no-op. -*/ -static int writeSuperJournal(Pager *pPager, const char *zSuper){ - int rc; /* Return code */ - int nSuper; /* Length of string zSuper */ - i64 iHdrOff; /* Offset of header in journal file */ - i64 jrnlSize; /* Size of journal file on disk */ - u32 cksum = 0; /* Checksum of string zSuper */ - - assert( pPager->setSuper==0 ); - assert( !pagerUseWal(pPager) ); - - if( !zSuper - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || !isOpen(pPager->jfd) - ){ - return SQLITE_OK; - } - pPager->setSuper = 1; - assert( pPager->journalHdr <= pPager->journalOff ); - - /* Calculate the length in bytes and the checksum of zSuper */ - for(nSuper=0; zSuper[nSuper]; nSuper++){ - cksum += zSuper[nSuper]; - } - - /* If in full-sync mode, advance to the next disk sector before writing - ** the super-journal name. This is in case the previous page written to - ** the journal has already been synced. - */ - if( pPager->fullSync ){ - pPager->journalOff = journalHdrOffset(pPager); - } - iHdrOff = pPager->journalOff; - - /* 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_SJ_PGNO(pPager)))) - || (0 != (rc = 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))) - || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, - iHdrOff+4+nSuper+8))) - ){ - return rc; - } - pPager->journalOff += (nSuper+20); - - /* If the pager is in persistent-journal mode, then the physical - ** journal-file may extend past the end of the super-journal name - ** and 8 bytes of magic data just written to the file. This is - ** dangerous because the code to rollback a hot-journal file - ** will not be able to find the super-journal name to determine - ** whether or not the journal is hot. - ** - ** Easiest thing to do in this scenario is to truncate the journal - ** file to the required size. - */ - if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize)) - && jrnlSize>pPager->journalOff - ){ - rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff); - } - return rc; -} - -/* -** Discard the entire contents of the in-memory page-cache. -*/ -static void pager_reset(Pager *pPager){ - pPager->iDataVersion++; - sqlite3BackupRestart(pPager->pBackup); - sqlite3PcacheClear(pPager->pPCache); -} - -/* -** Return the pPager->iDataVersion value -*/ -SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ - return pPager->iDataVersion; -} - -/* -** Free all structures in the Pager.aSavepoint[] array and set both -** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal -** if it is open and the pager is not in exclusive mode. -*/ -static void releaseAllSavepoints(Pager *pPager){ - int ii; /* Iterator for looping through Pager.aSavepoint */ - for(ii=0; iinSavepoint; ii++){ - sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); - } - if( !pPager->exclusiveMode || sqlite3JournalIsInMemory(pPager->sjfd) ){ - sqlite3OsClose(pPager->sjfd); - } - sqlite3_free(pPager->aSavepoint); - pPager->aSavepoint = 0; - pPager->nSavepoint = 0; - pPager->nSubRec = 0; -} - -/* -** Set the bit number pgno in the PagerSavepoint.pInSavepoint -** bitvecs of all open savepoints. Return SQLITE_OK if successful -** or SQLITE_NOMEM if a malloc failure occurs. -*/ -static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ - int ii; /* Loop counter */ - int rc = SQLITE_OK; /* Result code */ - - for(ii=0; iinSavepoint; ii++){ - PagerSavepoint *p = &pPager->aSavepoint[ii]; - if( pgno<=p->nOrig ){ - rc |= sqlite3BitvecSet(p->pInSavepoint, pgno); - testcase( rc==SQLITE_NOMEM ); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - } - } - return rc; -} - -/* -** This function is a no-op if the pager is in exclusive mode and not -** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN -** state. -** -** If the pager is not in exclusive-access mode, the database file is -** completely unlocked. If the file is unlocked and the file-system does -** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is -** closed (if it is open). -** -** If the pager is in ERROR state when this function is called, the -** contents of the pager cache are discarded before switching back to -** the OPEN state. Regardless of whether the pager is in exclusive-mode -** or not, any journal file left in the file-system will be treated -** as a hot-journal and rolled back the next time a read-transaction -** is opened (by this or by any other connection). -*/ -static void pager_unlock(Pager *pPager){ - - assert( pPager->eState==PAGER_READER - || pPager->eState==PAGER_OPEN - || pPager->eState==PAGER_ERROR - ); - - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - releaseAllSavepoints(pPager); - - if( pagerUseWal(pPager) ){ - assert( !isOpen(pPager->jfd) ); - if( pPager->eState==PAGER_ERROR ){ - /* If an IO error occurs in wal.c while attempting to wrap the wal file, - ** then the Wal object may be holding a write-lock but no read-lock. - ** This call ensures that the write-lock is dropped as well. We cannot - ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once - ** did, because this would break "BEGIN EXCLUSIVE" handling for - ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */ - sqlite3WalEndWriteTransaction(pPager->pWal); - } - sqlite3WalEndReadTransaction(pPager->pWal); - pPager->eState = PAGER_OPEN; - }else if( !pPager->exclusiveMode ){ - int rc; /* Error code returned by pagerUnlockDb() */ - int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; - - /* If the operating system support deletion of open files, then - ** close the journal file when dropping the database lock. Otherwise - ** another connection with journal_mode=delete might delete the file - ** out from under us. - */ - assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 ); - assert( (PAGER_JOURNALMODE_OFF & 5)!=1 ); - assert( (PAGER_JOURNALMODE_WAL & 5)!=1 ); - assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 ); - assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); - assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); - if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) - || 1!=(pPager->journalMode & 5) - ){ - sqlite3OsClose(pPager->jfd); - } - - /* If the pager is in the ERROR state and the call to unlock the database - ** file fails, set the current lock to UNKNOWN_LOCK. See the comment - ** above the #define for UNKNOWN_LOCK for an explanation of why this - ** is necessary. - */ - rc = pagerUnlockDb(pPager, NO_LOCK); - if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){ - pPager->eLock = UNKNOWN_LOCK; - } - - /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here - ** without clearing the error code. This is intentional - the error - ** code is cleared and the cache reset in the block below. - */ - assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); - pPager->eState = PAGER_OPEN; - } - - /* If Pager.errCode is set, the contents of the pager cache cannot be - ** trusted. Now that there are no outstanding references to the pager, - ** it can safely move back to PAGER_OPEN state. This happens in both - ** normal and exclusive-locking mode. - */ - assert( pPager->errCode==SQLITE_OK || !MEMDB ); - if( pPager->errCode ){ - if( pPager->tempFile==0 ){ - pager_reset(pPager); - pPager->changeCountDone = 0; - pPager->eState = PAGER_OPEN; - }else{ - pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER); - } - if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); - pPager->errCode = SQLITE_OK; - setGetterMethod(pPager); - } - - pPager->journalOff = 0; - pPager->journalHdr = 0; - pPager->setSuper = 0; -} - -/* -** This function is called whenever an IOERR or FULL error that requires -** the pager to transition into the ERROR state may have occurred. -** The first argument is a pointer to the pager structure, the second -** the error-code about to be returned by a pager API function. The -** value returned is a copy of the second argument to this function. -** -** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the -** IOERR sub-codes, the pager enters the ERROR state and the error code -** is stored in Pager.errCode. While the pager remains in the ERROR state, -** all major API calls on the Pager will immediately return Pager.errCode. -** -** The ERROR state indicates that the contents of the pager-cache -** cannot be trusted. This state can be cleared by completely discarding -** the contents of the pager-cache. If a transaction was active when -** the persistent error occurred, then the rollback journal may need -** to be replayed to restore the contents of the database file (as if -** it were a hot-journal). -*/ -static int pager_error(Pager *pPager, int rc){ - int rc2 = rc & 0xff; - assert( rc==SQLITE_OK || !MEMDB ); - assert( - pPager->errCode==SQLITE_FULL || - pPager->errCode==SQLITE_OK || - (pPager->errCode & 0xff)==SQLITE_IOERR - ); - if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ - pPager->errCode = rc; - pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); - } - return rc; -} - -static int pager_truncate(Pager *pPager, Pgno nPage); - -/* -** The write transaction open on pPager is being committed (bCommit==1) -** or rolled back (bCommit==0). -** -** Return TRUE if and only if all dirty pages should be flushed to disk. -** -** Rules: -** -** * For non-TEMP databases, always sync to disk. This is necessary -** for transactions to be durable. -** -** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing -** file has been created already (via a spill on pagerStress()) and -** when the number of dirty pages in memory exceeds 25% of the total -** cache size. -*/ -static int pagerFlushOnCommit(Pager *pPager, int bCommit){ - if( pPager->tempFile==0 ) return 1; - if( !bCommit ) return 0; - if( !isOpen(pPager->fd) ) return 0; - return (sqlite3PCachePercentDirty(pPager->pPCache)>=25); -} - -/* -** This routine ends a transaction. A transaction is usually ended by -** either a COMMIT or a ROLLBACK operation. This routine may be called -** after rollback of a hot-journal, or if an error occurs while opening -** the journal file or writing the very first journal-header of a -** database transaction. -** -** This routine is never called in PAGER_ERROR state. If it is called -** in PAGER_NONE or PAGER_SHARED state and the lock held is less -** exclusive than a RESERVED lock, it is a no-op. -** -** Otherwise, any active savepoints are released. -** -** If the journal file is open, then it is "finalized". Once a journal -** file has been finalized it is not possible to use it to roll back a -** transaction. Nor will it be considered to be a hot-journal by this -** or any other database connection. Exactly how a journal is finalized -** depends on whether or not the pager is running in exclusive mode and -** the current journal-mode (Pager.journalMode value), as follows: -** -** journalMode==MEMORY -** Journal file descriptor is simply closed. This destroys an -** in-memory journal. -** -** journalMode==TRUNCATE -** Journal file is truncated to zero bytes in size. -** -** journalMode==PERSIST -** The first 28 bytes of the journal file are zeroed. This invalidates -** the first journal header in the file, and hence the entire journal -** file. An invalid journal file cannot be rolled back. -** -** journalMode==DELETE -** The journal file is closed and deleted using sqlite3OsDelete(). -** -** If the pager is running in exclusive mode, this method of finalizing -** the journal file is never used. Instead, if the journalMode is -** DELETE and the pager is in exclusive mode, the method described under -** journalMode==PERSIST is used instead. -** -** After the journal is finalized, the pager moves to PAGER_READER state. -** If running in non-exclusive rollback mode, the lock on the file is -** downgraded to a SHARED_LOCK. -** -** SQLITE_OK is returned if no error occurs. If an error occurs during -** any of the IO operations to finalize the journal file or unlock the -** database then the IO error code is returned to the user. If the -** operation to finalize the journal file fails, then the code still -** tries to unlock the database file if not in exclusive mode. If the -** unlock operation fails as well, then the first error code related -** to the first error encountered (the journal finalization one) is -** returned. -*/ -static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ - int rc = SQLITE_OK; /* Error code from journal finalization operation */ - int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ - - /* Do nothing if the pager does not have an open write transaction - ** or at least a RESERVED lock. This function may be called when there - ** is no write-transaction active but a RESERVED or greater lock is - ** held under two circumstances: - ** - ** 1. After a successful hot-journal rollback, it is called with - ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. - ** - ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE - ** lock switches back to locking_mode=normal and then executes a - ** read-transaction, this function is called with eState==PAGER_READER - ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. - */ - assert( assert_pager_state(pPager) ); - assert( pPager->eState!=PAGER_ERROR ); - if( pPager->eStateeLockjfd) || pPager->pInJournal==0 - || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC) - ); - if( isOpen(pPager->jfd) ){ - assert( !pagerUseWal(pPager) ); - - /* Finalize the journal file. */ - if( sqlite3JournalIsInMemory(pPager->jfd) ){ - /* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */ - sqlite3OsClose(pPager->jfd); - }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ - if( pPager->journalOff==0 ){ - rc = SQLITE_OK; - }else{ - rc = sqlite3OsTruncate(pPager->jfd, 0); - if( rc==SQLITE_OK && pPager->fullSync ){ - /* Make sure the new file size is written into the inode right away. - ** Otherwise the journal might resurrect following a power loss and - ** cause the last transaction to roll back. See - ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773 - */ - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); - } - } - pPager->journalOff = 0; - }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST - || (pPager->exclusiveMode && pPager->journalModetempFile); - pPager->journalOff = 0; - }else{ - /* This branch may be executed with Pager.journalMode==MEMORY if - ** a hot-journal was just rolled back. In this case the journal - ** file should be closed and deleted. If this connection writes to - ** the database file, it will do so using an in-memory journal. - */ - int bDelete = !pPager->tempFile; - assert( sqlite3JournalIsInMemory(pPager->jfd)==0 ); - assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - sqlite3OsClose(pPager->jfd); - if( bDelete ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); - } - } - } - -#ifdef SQLITE_CHECK_PAGES - sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); - if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ - PgHdr *p = sqlite3PagerLookup(pPager, 1); - if( p ){ - p->pageHash = 0; - sqlite3PagerUnrefNotNull(p); - } - } -#endif - - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - pPager->nRec = 0; - if( rc==SQLITE_OK ){ - if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){ - sqlite3PcacheCleanAll(pPager->pPCache); - }else{ - sqlite3PcacheClearWritable(pPager->pPCache); - } - sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); - } - - if( pagerUseWal(pPager) ){ - /* Drop the WAL write-lock, if any. Also, if the connection was in - ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE - ** lock held on the database file. - */ - rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); - assert( rc2==SQLITE_OK ); - }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ - /* This branch is taken when committing a transaction in rollback-journal - ** mode if the database file on disk is larger than the database image. - ** At this point the journal has been finalized and the transaction - ** successfully committed, but the EXCLUSIVE lock is still held on the - ** file. So it is safe to truncate the database file to its minimum - ** required size. */ - assert( pPager->eLock==EXCLUSIVE_LOCK ); - rc = pager_truncate(pPager, pPager->dbSize); - } - - if( rc==SQLITE_OK && bCommit ){ - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - } - - if( !pPager->exclusiveMode - && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) - ){ - rc2 = pagerUnlockDb(pPager, SHARED_LOCK); - } - pPager->eState = PAGER_READER; - pPager->setSuper = 0; - - return (rc==SQLITE_OK?rc2:rc); -} - -/* Forward reference */ -static int pager_playback(Pager *pPager, int isHot); - -/* -** Execute a rollback if a transaction is active and unlock the -** database file. -** -** If the pager has already entered the ERROR state, do not attempt -** the rollback at this time. Instead, pager_unlock() is called. The -** call to pager_unlock() will discard all in-memory pages, unlock -** the database file and move the pager back to OPEN state. If this -** means that there is a hot-journal left in the file-system, the next -** connection to obtain a shared lock on the pager (which may be this one) -** will roll it back. -** -** If the pager has not already entered the ERROR state, but an IO or -** malloc error occurs during a rollback, then this will itself cause -** the pager to enter the ERROR state. Which will be cleared by the -** call to pager_unlock(), as described above. -*/ -static void pagerUnlockAndRollback(Pager *pPager){ - if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){ - assert( assert_pager_state(pPager) ); - if( pPager->eState>=PAGER_WRITER_LOCKED ){ - sqlite3BeginBenignMalloc(); - sqlite3PagerRollback(pPager); - sqlite3EndBenignMalloc(); - }else if( !pPager->exclusiveMode ){ - assert( pPager->eState==PAGER_READER ); - pager_end_transaction(pPager, 0, 0); - } - }else if( pPager->eState==PAGER_ERROR - && pPager->journalMode==PAGER_JOURNALMODE_MEMORY - && isOpen(pPager->jfd) - ){ - /* Special case for a ROLLBACK due to I/O error with an in-memory - ** journal: We have to rollback immediately, before the journal is - ** closed, because once it is closed, all content is forgotten. */ - int errCode = pPager->errCode; - u8 eLock = pPager->eLock; - pPager->eState = PAGER_OPEN; - pPager->errCode = SQLITE_OK; - pPager->eLock = EXCLUSIVE_LOCK; - pager_playback(pPager, 1); - pPager->errCode = errCode; - pPager->eLock = eLock; - } - pager_unlock(pPager); -} - -/* -** Parameter aData must point to a buffer of pPager->pageSize bytes -** of data. Compute and return a checksum based on the contents of the -** page of data and the current value of pPager->cksumInit. -** -** This is not a real checksum. It is really just the sum of the -** random initial value (pPager->cksumInit) and every 200th byte -** of the page data, starting with byte offset (pPager->pageSize%200). -** Each byte is interpreted as an 8-bit unsigned integer. -** -** Changing the formula used to compute this checksum results in an -** incompatible journal file format. -** -** If journal corruption occurs due to a power failure, the most likely -** scenario is that one end or the other of the record will be changed. -** It is much less likely that the two ends of the journal record will be -** correct and the middle be corrupt. Thus, this "checksum" scheme, -** though fast and simple, catches the mostly likely kind of corruption. -*/ -static u32 pager_cksum(Pager *pPager, const u8 *aData){ - u32 cksum = pPager->cksumInit; /* Checksum value to return */ - int i = pPager->pageSize-200; /* Loop counter */ - while( i>0 ){ - cksum += aData[i]; - i -= 200; - } - return cksum; -} - -/* -** Report the current page size and number of reserved bytes back -** to the codec. -*/ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -static void pagerReportSize(Pager *pPager){ - if( pPager->xCodecSizeChng ){ - pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize, - (int)pPager->nReserve); - } -} -#else -# define pagerReportSize(X) /* No-op if we do not support a codec */ -#endif -/* END SQLCIPHER */ - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -/* -** Make sure the number of reserved bits is the same in the destination -** pager as it is in the source. This comes up when a VACUUM changes the -** number of reserved bits to the "optimal" amount. -*/ -SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){ - if( pDest->nReserve!=pSrc->nReserve ){ - pDest->nReserve = pSrc->nReserve; - pagerReportSize(pDest); - } -} -#endif -/* END SQLCIPHER */ - -/* -** Read a single page from either the journal file (if isMainJrnl==1) or -** from the sub-journal (if isMainJrnl==0) and playback that page. -** The page begins at offset *pOffset into the file. The *pOffset -** value is increased to the start of the next page in the journal. -** -** The main rollback journal uses checksums - the statement journal does -** not. -** -** If the page number of the page record read from the (sub-)journal file -** is greater than the current value of Pager.dbSize, then playback is -** skipped and SQLITE_OK is returned. -** -** If pDone is not NULL, then it is a record of pages that have already -** been played back. If the page at *pOffset has already been played back -** (if the corresponding pDone bit is set) then skip the playback. -** Make sure the pDone bit corresponding to the *pOffset page is set -** prior to returning. -** -** If the page record is successfully read from the (sub-)journal file -** and played back, then SQLITE_OK is returned. If an IO error occurs -** while reading the record from the (sub-)journal file or while writing -** to the database file, then the IO error code is returned. If data -** is successfully read from the (sub-)journal file but appears to be -** corrupted, SQLITE_DONE is returned. Data is considered corrupted in -** two circumstances: -** -** * 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. -** -** Neither of these two scenarios are possible during a savepoint rollback. -** -** If this is a savepoint rollback, then memory may have to be dynamically -** allocated by this function. If this is the case and an allocation fails, -** SQLITE_NOMEM is returned. -*/ -static int pager_playback_one_page( - Pager *pPager, /* The pager being played back */ - i64 *pOffset, /* Offset of record to playback */ - Bitvec *pDone, /* Bitvec of pages already played back */ - int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */ - int isSavepnt /* True for a savepoint rollback */ -){ - int rc; - PgHdr *pPg; /* An existing page in the cache */ - Pgno pgno; /* The page number of a page in journal */ - u32 cksum; /* Checksum used for sanity checking */ - char *aData; /* Temporary storage for the page */ - sqlite3_file *jfd; /* The file descriptor for the journal file */ - int isSynced; /* True if journal page is synced */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - /* The jrnlEnc flag is true if Journal pages should be passed through - ** the codec. It is false for pure in-memory journals. */ - const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0); -#endif -/* END SQLCIPHER */ - - assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */ - assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */ - assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */ - assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */ - - aData = pPager->pTmpSpace; - assert( aData ); /* Temp storage must have already been allocated */ - assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); - - /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction - ** or savepoint rollback done at the request of the caller) or this is - ** a hot-journal rollback. If it is a hot-journal rollback, the pager - ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback - ** only reads from the main journal, not the sub-journal. - */ - assert( pPager->eState>=PAGER_WRITER_CACHEMOD - || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK) - ); - assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl ); - - /* Read the page number and page data from the journal or sub-journal - ** file. Return an error code to the caller if an IO error occurs. - */ - jfd = isMainJrnl ? pPager->jfd : pPager->sjfd; - rc = read32bits(jfd, *pOffset, &pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4); - if( rc!=SQLITE_OK ) return rc; - *pOffset += pPager->pageSize + 4 + isMainJrnl*4; - - /* Sanity checking on the page. This is more important that I originally - ** thought. If a power failure occurs while the journal is being written, - ** it could cause invalid data to be written into the journal. We need to - ** detect this invalid data (with high probability) and ignore it. - */ - if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){ - assert( !isSavepnt ); - return SQLITE_DONE; - } - if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){ - return SQLITE_OK; - } - if( isMainJrnl ){ - rc = read32bits(jfd, (*pOffset)-4, &cksum); - if( rc ) return rc; - if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){ - return SQLITE_DONE; - } - } - - /* If this page has already been played back before during the current - ** rollback, then don't bother to play it back again. - */ - if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ - return rc; - } - - /* When playing back page 1, restore the nReserve setting - */ - if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){ - pPager->nReserve = ((u8*)aData)[20]; - pagerReportSize(pPager); - } - - /* If the pager is in CACHEMOD state, then there must be a copy of this - ** page in the pager cache. In this case just update the pager cache, - ** not the database file. The page is left marked dirty in this case. - ** - ** An exception to the above rule: If the database is in no-sync mode - ** and a page is moved during an incremental vacuum then the page may - ** not be in the pager cache. Later: if a malloc() or IO error occurs - ** during a Movepage() call, then the page may not be in the cache - ** either. So the condition described in the above paragraph is not - ** assert()able. - ** - ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the - ** pager cache if it exists and the main file. The page is then marked - ** not dirty. Since this code is only executed in PAGER_OPEN state for - ** a hot-journal rollback, it is guaranteed that the page-cache is empty - ** if the pager is in OPEN state. - ** - ** Ticket #1171: The statement journal might contain page content that is - ** different from the page content at the start of the transaction. - ** This occurs when a page is changed prior to the start of a statement - ** then changed again within the statement. When rolling back such a - ** statement we must not write to the original database unless we know - ** for certain that original page contents are synced into the main rollback - ** journal. Otherwise, a power loss might leave modified data in the - ** database file without an entry in the rollback journal that can - ** restore the database to its original form. Two conditions must be - ** met before writing to the database files. (1) the database must be - ** locked. (2) we know that the original page content is fully synced - ** in the main journal either because the page is not in cache or else - ** the page is marked as needSync==0. - ** - ** 2008-04-14: When attempting to vacuum a corrupt database file, it - ** is possible to fail a statement on a database that does not yet exist. - ** Do not attempt to write if database file has never been opened. - */ - if( pagerUseWal(pPager) ){ - pPg = 0; - }else{ - pPg = sqlite3PagerLookup(pPager, pgno); - } - assert( pPg || !MEMDB ); - assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile ); - PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", - PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), - (isMainJrnl?"main-journal":"sub-journal") - )); - if( isMainJrnl ){ - isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr); - }else{ - isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC)); - } - if( isOpen(pPager->fd) - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - && isSynced - ){ - i64 ofst = (pgno-1)*(i64)pPager->pageSize; - testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); - assert( !pagerUseWal(pPager) ); - - /* Write the data read from the journal back into the database file. - ** This is usually safe even for an encrypted database - as the data - ** was encrypted before it was written to the journal file. The exception - ** is if the data was just read from an in-memory sub-journal. In that - ** case it must be encrypted here before it is copied into the database - ** file. */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( !jrnlEnc ){ - CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData); - rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst); - CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT); - }else -#endif -/* END SQLCIPHER */ - rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst); - - if( pgno>pPager->dbFileSize ){ - pPager->dbFileSize = pgno; - } - if( pPager->pBackup ){ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( jrnlEnc ){ - CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT); - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); - CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData); - }else -#endif -/* END SQLCIPHER */ - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); - } - }else if( !isMainJrnl && pPg==0 ){ - /* If this is a rollback of a savepoint and data was not written to - ** the database and the page is not in-memory, there is a potential - ** problem. When the page is next fetched by the b-tree layer, it - ** will be read from the database file, which may or may not be - ** current. - ** - ** There are a couple of different ways this can happen. All are quite - ** obscure. When running in synchronous mode, this can only happen - ** if the page is on the free-list at the start of the transaction, then - ** populated, then moved using sqlite3PagerMovepage(). - ** - ** The solution is to add an in-memory page to the cache containing - ** the data just read from the sub-journal. Mark the page as dirty - ** and if the pager requires a journal-sync, then mark the page as - ** requiring a journal-sync before it is written. - */ - assert( isSavepnt ); - assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 ); - pPager->doNotSpill |= SPILLFLAG_ROLLBACK; - rc = sqlite3PagerGet(pPager, pgno, &pPg, 1); - assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); - pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; - if( rc!=SQLITE_OK ) return rc; - sqlite3PcacheMakeDirty(pPg); - } - if( pPg ){ - /* No page should ever be explicitly rolled back that is in use, except - ** for page 1 which is held in use in order to keep the lock on the - ** database active. However such a page may be rolled back as a result - ** of an internal error resulting in an automatic call to - ** sqlite3PagerRollback(). - */ - void *pData; - pData = pPg->pData; - memcpy(pData, (u8*)aData, pPager->pageSize); - pPager->xReiniter(pPg); - /* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But - ** that call was dangerous and had no detectable benefit since the cache - ** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so - ** has been removed. */ - pager_set_pagehash(pPg); - - /* If this was page 1, then restore the value of Pager.dbFileVers. - ** Do this before any decoding. */ - if( pgno==1 ){ - memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); - } - - /* Decode the page just read from disk */ -/* BEGIN SQLCIPHER */ -#if SQLITE_HAS_CODEC - if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); } -#endif -/* END SQLCIPHER */ - sqlite3PcacheRelease(pPg); - } - return rc; -} - -/* -** Parameter zSuper is the name of a super-journal file. A single journal -** file that referred to the super-journal file has just been rolled back. -** This routine checks if it is possible to delete the super-journal file, -** and does so if it is. -** -** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not -** available for use within this function. -** -** When a super-journal file is created, it is populated with the names -** of all of its child journals, one after another, formatted as utf-8 -** encoded text. The end of each child journal file is marked with a -** nul-terminator byte (0x00). i.e. the entire contents of a super-journal -** file for a transaction involving two databases might be: -** -** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00" -** -** A super-journal file may only be deleted once all of its child -** journals have been rolled back. -** -** This function reads the contents of the super-journal file into -** memory and loops through each of the child journal names. For -** each child journal, it checks if: -** -** * if the child journal exists, and if so -** * if the child journal contains a reference to super-journal -** file zSuper -** -** If a child journal can be found that matches both of the criteria -** above, this function returns without doing anything. Otherwise, if -** no such child journal can be found, file zSuper is deleted from -** the file-system using sqlite3OsDelete(). -** -** If an IO error within this function, an error code is returned. This -** function allocates memory by calling sqlite3Malloc(). If an allocation -** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors -** occur, SQLITE_OK is returned. -** -** TODO: This function allocates a single block of memory to load -** the entire contents of the super-journal file. This could be -** a couple of kilobytes or so - potentially larger than the page -** size. -*/ -static int pager_delsuper(Pager *pPager, const char *zSuper){ - sqlite3_vfs *pVfs = pPager->pVfs; - int rc; /* Return code */ - sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */ - sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */ - char *zSuperJournal = 0; /* Contents of super-journal file */ - i64 nSuperJournal; /* Size of super-journal file */ - char *zJournal; /* Pointer to one journal within MJ file */ - char *zSuperPtr; /* Space to hold super-journal filename */ - char *zFree = 0; /* Free this buffer */ - i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */ - - /* Allocate space for both the pJournal and pSuper file descriptors. - ** If successful, open the super-journal file for reading. - */ - pSuper = (sqlite3_file *)sqlite3MallocZero(2 * (i64)pVfs->szOsFile); - if( !pSuper ){ - rc = SQLITE_NOMEM_BKPT; - pJournal = 0; - }else{ - const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL); - rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0); - pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile); - } - if( rc!=SQLITE_OK ) goto delsuper_out; - - /* Load the entire super-journal file into space obtained from - ** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain - ** sufficient space (in zSuperPtr) to hold the names of super-journal - ** files extracted from regular rollback-journals. - */ - rc = sqlite3OsFileSize(pSuper, &nSuperJournal); - if( rc!=SQLITE_OK ) goto delsuper_out; - nSuperPtr = 1 + (i64)pVfs->mxPathname; - assert( nSuperJournal>=0 && nSuperPtr>0 ); - zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2); - if( !zFree ){ - rc = SQLITE_NOMEM_BKPT; - goto delsuper_out; - }else{ - assert( nSuperJournal<=0x7fffffff ); - } - zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0; - zSuperJournal = &zFree[4]; - zSuperPtr = &zSuperJournal[nSuperJournal+2]; - rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0); - if( rc!=SQLITE_OK ) goto delsuper_out; - zSuperJournal[nSuperJournal] = 0; - zSuperJournal[nSuperJournal+1] = 0; - - zJournal = zSuperJournal; - while( (zJournal-zSuperJournal)pageSize bytes). -** If the file on disk is currently larger than nPage pages, then use the VFS -** xTruncate() method to truncate it. -** -** Or, it might be the case that the file on disk is smaller than -** nPage pages. Some operating system implementations can get confused if -** you try to truncate a file to some size that is larger than it -** currently is, so detect this case and write a single zero byte to -** the end of the new file instead. -** -** If successful, return SQLITE_OK. If an IO error occurs while modifying -** the database file, return the error code to the caller. -*/ -static int pager_truncate(Pager *pPager, Pgno nPage){ - int rc = SQLITE_OK; - assert( pPager->eState!=PAGER_ERROR ); - assert( pPager->eState!=PAGER_READER ); - PAGERTRACE(("Truncate %d npage %u\n", PAGERID(pPager), nPage)); - - - if( isOpen(pPager->fd) - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - ){ - i64 currentSize, newSize; - int szPage = pPager->pageSize; - assert( pPager->eLock==EXCLUSIVE_LOCK ); - /* TODO: Is it safe to use Pager.dbFileSize here? */ - rc = sqlite3OsFileSize(pPager->fd, ¤tSize); - newSize = szPage*(i64)nPage; - if( rc==SQLITE_OK && currentSize!=newSize ){ - if( currentSize>newSize ){ - rc = sqlite3OsTruncate(pPager->fd, newSize); - }else if( (currentSize+szPage)<=newSize ){ - char *pTmp = pPager->pTmpSpace; - memset(pTmp, 0, szPage); - testcase( (newSize-szPage) == currentSize ); - testcase( (newSize-szPage) > currentSize ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize); - rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); - } - if( rc==SQLITE_OK ){ - pPager->dbFileSize = nPage; - } - } - } - return rc; -} - -/* -** Return a sanitized version of the sector-size of OS file pFile. The -** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE. -*/ -SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){ - int iRet = sqlite3OsSectorSize(pFile); - if( iRet<32 ){ - iRet = 512; - }else if( iRet>MAX_SECTOR_SIZE ){ - assert( MAX_SECTOR_SIZE>=512 ); - iRet = MAX_SECTOR_SIZE; - } - return iRet; -} - -/* -** Set the value of the Pager.sectorSize variable for the given -** pager based on the value returned by the xSectorSize method -** of the open database file. The sector size will be used -** to determine the size and alignment of journal header and -** super-journal pointers within created journal files. -** -** For temporary files the effective sector size is always 512 bytes. -** -** Otherwise, for non-temporary files, the effective sector size is -** the value returned by the xSectorSize() method rounded up to 32 if -** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it -** is greater than MAX_SECTOR_SIZE. -** -** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set -** the effective sector size to its minimum value (512). The purpose of -** pPager->sectorSize is to define the "blast radius" of bytes that -** might change if a crash occurs while writing to a single byte in -** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero -** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector -** size. For backwards compatibility of the rollback journal file format, -** we cannot reduce the effective sector size below 512. -*/ -static void setSectorSize(Pager *pPager){ - assert( isOpen(pPager->fd) || pPager->tempFile ); - - if( pPager->tempFile - || (sqlite3OsDeviceCharacteristics(pPager->fd) & - SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0 - ){ - /* Sector size doesn't matter for temporary files. Also, the file - ** may not have been opened yet, in which case the OsSectorSize() - ** call will segfault. */ - pPager->sectorSize = 512; - }else{ - pPager->sectorSize = sqlite3SectorSize(pPager->fd); - } -} - -/* -** Playback the journal and thus restore the database file to -** the state it was in before we started making changes. -** -** The journal file format is as follows: -** -** (1) 8 byte prefix. A copy of aJournalMagic[]. -** (2) 4 byte big-endian integer which is the number of valid page records -** in the journal. If this value is 0xffffffff, then compute the -** number of page records from the journal size. -** (3) 4 byte big-endian integer which is the initial value for the -** sanity checksum. -** (4) 4 byte integer which is the number of pages to truncate the -** database to during a rollback. -** (5) 4 byte big-endian integer which is the sector size. The header -** is this many bytes in size. -** (6) 4 byte big-endian integer which is the page size. -** (7) zero padding out to the next sector size. -** (8) Zero or more pages instances, each as follows: -** + 4 byte page number. -** + pPager->pageSize bytes of data. -** + 4 byte checksum -** -** When we speak of the journal header, we mean the first 7 items above. -** Each entry in the journal is an instance of the 8th item. -** -** Call the value from the second bullet "nRec". nRec is the number of -** valid page entries in the journal. In most cases, you can compute the -** value of nRec from the size of the journal file. But if a power -** failure occurred while the journal was being written, it could be the -** case that the size of the journal file had already been increased but -** the extra entries had not yet made it safely to disk. In such a case, -** the value of nRec computed from the file size would be too large. For -** that reason, we always use the nRec value in the header. -** -** If the nRec value is 0xffffffff it means that nRec should be computed -** from the file size. This value is used when the user selects the -** no-sync option for the journal. A power failure could lead to corruption -** in this case. But for things like temporary table (which will be -** deleted when the power is restored) we don't care. -** -** If the file opened as the journal file is not a well-formed -** journal file then all pages up to the first corrupted page are rolled -** back (or no pages if the journal header is corrupted). The journal file -** is then deleted and SQLITE_OK returned, just as if no corruption had -** been encountered. -** -** If an I/O or malloc() error occurs, the journal-file is not deleted -** and an error code is returned. -** -** The isHot parameter indicates that we are trying to rollback a journal -** that might be a hot journal. Or, it could be that the journal is -** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE. -** If the journal really is hot, reset the pager cache prior rolling -** back any content. If the journal is merely persistent, no reset is -** needed. -*/ -static int pager_playback(Pager *pPager, int isHot){ - sqlite3_vfs *pVfs = pPager->pVfs; - i64 szJ; /* Size of the journal file in bytes */ - u32 nRec; /* Number of Records in the journal */ - u32 u; /* Unsigned loop counter */ - Pgno mxPg = 0; /* Size of the original file in pages */ - int rc; /* Result code of a subroutine */ - int res = 1; /* Value returned by sqlite3OsAccess() */ - char *zSuper = 0; /* Name of super-journal file if any */ - int needPagerReset; /* True to reset page prior to first page rollback */ - int nPlayback = 0; /* Total number of pages restored from journal */ - u32 savedPageSize = pPager->pageSize; - - /* Figure out how many records are in the journal. Abort early if - ** the journal is empty. - */ - assert( isOpen(pPager->jfd) ); - rc = sqlite3OsFileSize(pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - - /* Read the super-journal name from the journal, if it is present. - ** If a super-journal file name is specified, but the file is not - ** present on disk, then the journal is not hot and does not need to be - ** played back. - ** - ** TODO: Technically the following is an error because it assumes that - ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that - ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c, - ** mxPathname is 512, which is the same as the minimum allowable value - ** for pageSize. - */ - zSuper = pPager->pTmpSpace; - rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname); - if( rc==SQLITE_OK && zSuper[0] ){ - rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res); - } - zSuper = 0; - if( rc!=SQLITE_OK || !res ){ - goto end_playback; - } - pPager->journalOff = 0; - needPagerReset = isHot; - - /* This loop terminates either when a readJournalHdr() or - ** pager_playback_one_page() call returns SQLITE_DONE or an IO error - ** occurs. - */ - while( 1 ){ - /* Read the next journal header from the journal file. If there are - ** not enough bytes left in the journal file for a complete header, or - ** it is corrupted, then a process must have failed while writing it. - ** This indicates nothing more needs to be rolled back. - */ - rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - goto end_playback; - } - - /* If nRec is 0xffffffff, then this journal was created by a process - ** working in no-sync mode. This means that the rest of the journal - ** file consists of pages, there are no more journal headers. Compute - ** the value of nRec based on this assumption. - */ - if( nRec==0xffffffff ){ - assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); - nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager)); - } - - /* If nRec is 0 and this rollback is of a transaction created by this - ** process and if this is the final header in the journal, then it means - ** that this part of the journal was being filled but has not yet been - ** synced to disk. Compute the number of pages based on the remaining - ** size of the file. - ** - ** The third term of the test was added to fix ticket #2565. - ** When rolling back a hot journal, nRec==0 always means that the next - ** chunk of the journal contains zero pages to be rolled back. But - ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in - ** the journal, it means that the journal might contain additional - ** pages that need to be rolled back and that the number of pages - ** should be computed based on the journal file size. - */ - if( nRec==0 && !isHot && - pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ - nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager)); - } - - /* If this is the first header read from the journal, truncate the - ** database file back to its original size. - */ - if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ - rc = pager_truncate(pPager, mxPg); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - pPager->dbSize = mxPg; - if( pPager->mxPgnomxPgno = mxPg; - } - } - - /* Copy original pages out of the journal and back into the - ** database file and/or page cache. - */ - for(u=0; ujournalOff,0,1,0); - if( rc==SQLITE_OK ){ - nPlayback++; - }else{ - if( rc==SQLITE_DONE ){ - pPager->journalOff = szJ; - break; - }else if( rc==SQLITE_IOERR_SHORT_READ ){ - /* If the journal has been truncated, simply stop reading and - ** processing the journal. This might happen if the journal was - ** not completely written and synced prior to a crash. In that - ** case, the database should have never been written in the - ** first place so it is OK to simply abandon the rollback. */ - rc = SQLITE_OK; - goto end_playback; - }else{ - /* If we are unable to rollback, quit and return the error - ** code. This will cause the pager to enter the error state - ** so that no further harm will be done. Perhaps the next - ** process to come along will be able to rollback the database. - */ - goto end_playback; - } - } - } - } - /*NOTREACHED*/ - assert( 0 ); - -end_playback: - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1); - } - /* Following a rollback, the database file should be back in its original - ** state prior to the start of the transaction, so invoke the - ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the - ** assertion that the transaction counter was modified. - */ -#ifdef SQLITE_DEBUG - sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); -#endif - - /* If this playback is happening automatically as a result of an IO or - ** malloc error that occurred after the change-counter was updated but - ** before the transaction was committed, then the change-counter - ** modification may just have been reverted. If this happens in exclusive - ** mode, then subsequent transactions performed by the connection will not - ** update the change-counter at all. This may lead to cache inconsistency - ** problems for other processes at some point in the future. So, just - ** in case this has happened, clear the changeCountDone flag now. - */ - pPager->changeCountDone = pPager->tempFile; - - if( rc==SQLITE_OK ){ - /* Leave 4 bytes of space before the super-journal filename in memory. - ** This is because it may end up being passed to sqlite3OsOpen(), in - ** which case it requires 4 0x00 bytes in memory immediately before - ** the filename. */ - zSuper = &pPager->pTmpSpace[4]; - rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname); - testcase( rc!=SQLITE_OK ); - } - if( rc==SQLITE_OK - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - ){ - rc = sqlite3PagerSync(pPager, 0); - } - if( rc==SQLITE_OK ){ - rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0); - testcase( rc!=SQLITE_OK ); - } - if( rc==SQLITE_OK && zSuper[0] && res ){ - /* If there was a super-journal and this routine will return success, - ** see if it is possible to delete the super-journal. - */ - assert( zSuper==&pPager->pTmpSpace[4] ); - memset(pPager->pTmpSpace, 0, 4); - rc = pager_delsuper(pPager, zSuper); - testcase( rc!=SQLITE_OK ); - } - if( isHot && nPlayback ){ - sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s", - nPlayback, pPager->zJournal); - } - - /* The Pager.sectorSize variable may have been updated while rolling - ** back a journal created by a process with a different sector size - ** value. Reset it to the correct value for this process. - */ - setSectorSize(pPager); - return rc; -} - - -/* -** Read the content for page pPg out of the database file (or out of -** the WAL if that is where the most recent copy if found) into -** pPg->pData. A shared lock or greater must be held on the database -** file before this function is called. -** -** If page 1 is read, then the value of Pager.dbFileVers[] is set to -** the value read from the database file. -** -** If an IO error occurs, then the IO error is returned to the caller. -** Otherwise, SQLITE_OK is returned. -*/ -static int readDbPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ - int rc = SQLITE_OK; /* Return code */ - -#ifndef SQLITE_OMIT_WAL - u32 iFrame = 0; /* Frame of WAL containing pgno */ - - assert( pPager->eState>=PAGER_READER && !MEMDB ); - assert( isOpen(pPager->fd) ); - - if( pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); - if( rc ) return rc; - } - if( iFrame ){ - rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData); - }else -#endif - { - i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize; - rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - } - - if( pPg->pgno==1 ){ - if( rc ){ - /* If the read is unsuccessful, set the dbFileVers[] to something - ** that will never be a valid file version. dbFileVers[] is a copy - ** of bytes 24..39 of the database. Bytes 28..31 should always be - ** zero or the size of the database in page. Bytes 32..35 and 35..39 - ** should be page numbers which are never 0xffffffff. So filling - ** pPager->dbFileVers[] with all 0xff bytes should suffice. - ** - ** For an encrypted database, the situation is more complex: bytes - ** 24..39 of the database are white noise. But the probability of - ** white noise equaling 16 bytes of 0xff is vanishingly small so - ** we should still be ok. - */ - memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers)); - }else{ - u8 *dbFileVers = &((u8*)pPg->pData)[24]; - memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); - } - } - CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT); - - PAGER_INCR(sqlite3_pager_readdb_count); - PAGER_INCR(pPager->nRead); - IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno)); - PAGERTRACE(("FETCH %d page %d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, pager_pagehash(pPg))); - - return rc; -} - -/* -** Update the value of the change-counter at offsets 24 and 92 in -** the header and the sqlite version number at offset 96. -** -** This is an unconditional update. See also the pager_incr_changecounter() -** routine which only updates the change-counter if the update is actually -** needed, as determined by the pPager->changeCountDone state variable. -*/ -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 = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; - put32bits(((char*)pPg->pData)+24, change_counter); - - /* Also store the SQLite version number in bytes 96..99 and in - ** bytes 92..95 store the change counter for which the version number - ** is valid. */ - put32bits(((char*)pPg->pData)+92, change_counter); - put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); -} - -#ifndef SQLITE_OMIT_WAL -/* -** This function is invoked once for each page that has already been -** written into the log file when a WAL transaction is rolled back. -** Parameter iPg is the page number of said page. The pCtx argument -** is actually a pointer to the Pager structure. -** -** If page iPg is present in the cache, and has no outstanding references, -** it is discarded. Otherwise, if there are one or more outstanding -** references, the page content is reloaded from the database. If the -** attempt to reload content from the database is required and fails, -** return an SQLite error code. Otherwise, SQLITE_OK. -*/ -static int pagerUndoCallback(void *pCtx, Pgno iPg){ - int rc = SQLITE_OK; - Pager *pPager = (Pager *)pCtx; - PgHdr *pPg; - - assert( pagerUseWal(pPager) ); - pPg = sqlite3PagerLookup(pPager, iPg); - if( pPg ){ - if( sqlite3PcachePageRefcount(pPg)==1 ){ - sqlite3PcacheDrop(pPg); - }else{ - rc = readDbPage(pPg); - if( rc==SQLITE_OK ){ - pPager->xReiniter(pPg); - } - sqlite3PagerUnrefNotNull(pPg); - } - } - - /* Normally, if a transaction is rolled back, any backup processes are - ** updated as data is copied out of the rollback journal and into the - ** database. This is not generally possible with a WAL database, as - ** rollback involves simply truncating the log file. Therefore, if one - ** or more frames have already been written to the log (and therefore - ** also copied into the backup databases) as part of this transaction, - ** the backups must be restarted. - */ - sqlite3BackupRestart(pPager->pBackup); - - return rc; -} - -/* -** This function is called to rollback a transaction on a WAL database. -*/ -static int pagerRollbackWal(Pager *pPager){ - int rc; /* Return Code */ - PgHdr *pList; /* List of dirty pages to revert */ - - /* For all pages in the cache that are currently dirty or have already - ** been written (but not committed) to the log file, do one of the - ** following: - ** - ** + Discard the cached page (if refcount==0), or - ** + Reload page content from the database (if refcount>0). - */ - pPager->dbSize = pPager->dbOrigSize; - rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager); - pList = sqlite3PcacheDirtyList(pPager->pPCache); - while( pList && rc==SQLITE_OK ){ - PgHdr *pNext = pList->pDirty; - rc = pagerUndoCallback((void *)pPager, pList->pgno); - pList = pNext; - } - - return rc; -} - -/* -** This function is a wrapper around sqlite3WalFrames(). As well as logging -** the contents of the list of pages headed by pList (connected by pDirty), -** this function notifies any active backup processes that the pages have -** changed. -** -** The list of pages passed into this routine is always sorted by page number. -** Hence, if page 1 appears anywhere on the list, it will be the first page. -*/ -static int pagerWalFrames( - Pager *pPager, /* Pager object */ - PgHdr *pList, /* List of frames to log */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit /* True if this is a commit */ -){ - int rc; /* Return code */ - int nList; /* Number of pages in pList */ - PgHdr *p; /* For looping over pages */ - - assert( pPager->pWal ); - assert( pList ); -#ifdef SQLITE_DEBUG - /* Verify that the page list is in ascending order */ - for(p=pList; p && p->pDirty; p=p->pDirty){ - assert( p->pgno < p->pDirty->pgno ); - } -#endif - - assert( pList->pDirty==0 || isCommit ); - if( isCommit ){ - /* If a WAL transaction is being committed, there is no point in writing - ** any pages with page numbers greater than nTruncate into the WAL file. - ** They will never be read by any client. So remove them from the pDirty - ** list here. */ - PgHdr **ppNext = &pList; - nList = 0; - for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ - if( p->pgno<=nTruncate ){ - ppNext = &p->pDirty; - nList++; - } - } - assert( pList ); - }else{ - nList = 1; - } - pPager->aStat[PAGER_STAT_WRITE] += nList; - - if( pList->pgno==1 ) pager_write_changecounter(pList); - rc = sqlite3WalFrames(pPager->pWal, - pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags - ); - if( rc==SQLITE_OK && pPager->pBackup ){ - for(p=pList; p; p=p->pDirty){ - sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); - } - } - -#ifdef SQLITE_CHECK_PAGES - pList = sqlite3PcacheDirtyList(pPager->pPCache); - for(p=pList; p; p=p->pDirty){ - pager_set_pagehash(p); - } -#endif - - return rc; -} - -/* -** Begin a read transaction on the WAL. -** -** This routine used to be called "pagerOpenSnapshot()" because it essentially -** makes a snapshot of the database at the current point in time and preserves -** that snapshot for use by the reader in spite of concurrently changes by -** other writers or checkpointers. -*/ -static int pagerBeginReadTransaction(Pager *pPager){ - int rc; /* Return code */ - int changed = 0; /* True if cache must be reset */ - - assert( pagerUseWal(pPager) ); - assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); - - /* sqlite3WalEndReadTransaction() was not called for the previous - ** transaction in locking_mode=EXCLUSIVE. So call it now. If we - ** are in locking_mode=NORMAL and EndRead() was previously called, - ** the duplicate call is harmless. - */ - sqlite3WalEndReadTransaction(pPager->pWal); - - rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); - if( rc!=SQLITE_OK || changed ){ - pager_reset(pPager); - if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); - } - - return rc; -} -#endif - -/* -** This function is called as part of the transition from PAGER_OPEN -** to PAGER_READER state to determine the size of the database file -** in pages (assuming the page size currently stored in Pager.pageSize). -** -** If no error occurs, SQLITE_OK is returned and the size of the database -** in pages is stored in *pnPage. Otherwise, an error code (perhaps -** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. -*/ -static int pagerPagecount(Pager *pPager, Pgno *pnPage){ - Pgno nPage; /* Value to return via *pnPage */ - - /* Query the WAL sub-system for the database size. The WalDbsize() - ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or - ** if the database size is not available. The database size is not - ** available from the WAL sub-system if the log file is empty or - ** contains no valid committed transactions. - */ - assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK ); - assert( isOpen(pPager->fd) ); - assert( pPager->tempFile==0 ); - nPage = sqlite3WalDbsize(pPager->pWal); - - /* If the number of pages in the database is not available from the - ** WAL sub-system, determine the page count based on the size of - ** the database file. If the size of the database file is not an - ** integer multiple of the page-size, round up the result. - */ - if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){ - i64 n = 0; /* Size of db file in bytes */ - int rc = sqlite3OsFileSize(pPager->fd, &n); - if( rc!=SQLITE_OK ){ - return rc; - } - nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize); - } - - /* If the current number of pages in the file is greater than the - ** configured maximum pager number, increase the allowed limit so - ** that the file can be read. - */ - if( nPage>pPager->mxPgno ){ - pPager->mxPgno = (Pgno)nPage; - } - - *pnPage = nPage; - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_WAL -/* -** Check if the *-wal file that corresponds to the database opened by pPager -** exists if the database is not empty, or verify that the *-wal file does -** not exist (by deleting it) if the database file is empty. -** -** If the database is not empty and the *-wal file exists, open the pager -** in WAL mode. If the database is empty or if no *-wal file exists and -** if no error occurs, make sure Pager.journalMode is not set to -** PAGER_JOURNALMODE_WAL. -** -** Return SQLITE_OK or an error code. -** -** The caller must hold a SHARED lock on the database file to call this -** function. Because an EXCLUSIVE lock on the db file is required to delete -** a WAL on a none-empty database, this ensures there is no race condition -** between the xAccess() below and an xDelete() being executed by some -** other connection. -*/ -static int pagerOpenWalIfPresent(Pager *pPager){ - int rc = SQLITE_OK; - assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK ); - - if( !pPager->tempFile ){ - int isWal; /* True if WAL file exists */ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal - ); - if( rc==SQLITE_OK ){ - if( isWal ){ - Pgno nPage; /* Size of the database file */ - - rc = pagerPagecount(pPager, &nPage); - if( rc ) return rc; - if( nPage==0 ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); - }else{ - testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); - rc = sqlite3PagerOpenWal(pPager, 0); - } - }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ - pPager->journalMode = PAGER_JOURNALMODE_DELETE; - } - } - } - return rc; -} -#endif - -/* -** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback -** the entire super-journal file. The case pSavepoint==NULL occurs when -** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction -** savepoint. -** -** When pSavepoint is not NULL (meaning a non-transaction savepoint is -** being rolled back), then the rollback consists of up to three stages, -** performed in the order specified: -** -** * Pages are played back from the main journal starting at byte -** offset PagerSavepoint.iOffset and continuing to -** PagerSavepoint.iHdrOffset, or to the end of the main journal -** file if PagerSavepoint.iHdrOffset is zero. -** -** * If PagerSavepoint.iHdrOffset is not zero, then pages are played -** back starting from the journal header immediately following -** PagerSavepoint.iHdrOffset to the end of the main journal file. -** -** * Pages are then played back from the sub-journal file, starting -** with the PagerSavepoint.iSubRec and continuing to the end of -** the journal file. -** -** Throughout the rollback process, each time a page is rolled back, the -** corresponding bit is set in a bitvec structure (variable pDone in the -** implementation below). This is used to ensure that a page is only -** rolled back the first time it is encountered in either journal. -** -** If pSavepoint is NULL, then pages are only played back from the main -** journal file. There is no need for a bitvec in this case. -** -** In either case, before playback commences the Pager.dbSize variable -** is reset to the value that it held at the start of the savepoint -** (or transaction). No page with a page-number greater than this value -** is played back. If one is encountered it is simply skipped. -*/ -static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ - i64 szJ; /* Effective size of the main journal */ - i64 iHdrOff; /* End of first segment of main-journal records */ - int rc = SQLITE_OK; /* Return code */ - Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ - - assert( pPager->eState!=PAGER_ERROR ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - - /* Allocate a bitvec to use to store the set of pages rolled back */ - if( pSavepoint ){ - pDone = sqlite3BitvecCreate(pSavepoint->nOrig); - if( !pDone ){ - return SQLITE_NOMEM_BKPT; - } - } - - /* Set the database size back to the value it was before the savepoint - ** being reverted was opened. - */ - pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize; - pPager->changeCountDone = pPager->tempFile; - - if( !pSavepoint && pagerUseWal(pPager) ){ - return pagerRollbackWal(pPager); - } - - /* Use pPager->journalOff as the effective size of the main rollback - ** journal. The actual file might be larger than this in - ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything - ** past pPager->journalOff is off-limits to us. - */ - szJ = pPager->journalOff; - assert( pagerUseWal(pPager)==0 || szJ==0 ); - - /* Begin by rolling back records from the main journal starting at - ** PagerSavepoint.iOffset and continuing to the next journal header. - ** There might be records in the main journal that have a page number - ** greater than the current database size (pPager->dbSize) but those - ** will be skipped automatically. Pages are added to pDone as they - ** are played back. - */ - if( pSavepoint && !pagerUseWal(pPager) ){ - iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ; - pPager->journalOff = pSavepoint->iOffset; - while( rc==SQLITE_OK && pPager->journalOffjournalOff, pDone, 1, 1); - } - assert( rc!=SQLITE_DONE ); - }else{ - pPager->journalOff = 0; - } - - /* Continue rolling back records out of the main journal starting at - ** the first journal header seen and continuing until the effective end - ** of the main journal file. Continue to skip out-of-range pages and - ** continue adding pages rolled back to pDone. - */ - while( rc==SQLITE_OK && pPager->journalOffjournalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff" - ** test is related to ticket #2565. See the discussion in the - ** pager_playback() function for additional information. - */ - if( nJRec==0 - && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff - ){ - nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager)); - } - for(ii=0; rc==SQLITE_OK && iijournalOffjournalOff, pDone, 1, 1); - } - assert( rc!=SQLITE_DONE ); - } - assert( rc!=SQLITE_OK || pPager->journalOff>=szJ ); - - /* Finally, rollback pages from the sub-journal. Page that were - ** previously rolled back out of the main journal (and are hence in pDone) - ** will be skipped. Out-of-range pages are also skipped. - */ - if( pSavepoint ){ - u32 ii; /* Loop counter */ - i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize); - - if( pagerUseWal(pPager) ){ - rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData); - } - for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && iinSubRec; ii++){ - assert( offset==(i64)ii*(4+pPager->pageSize) ); - rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1); - } - assert( rc!=SQLITE_DONE ); - } - - sqlite3BitvecDestroy(pDone); - if( rc==SQLITE_OK ){ - pPager->journalOff = szJ; - } - - return rc; -} - -/* -** Change the maximum number of in-memory pages that are allowed -** before attempting to recycle clean and unused pages. -*/ -SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ - sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); -} - -/* -** Change the maximum number of in-memory pages that are allowed -** before attempting to spill pages to journal. -*/ -SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){ - return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage); -} - -/* -** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. -*/ -static void pagerFixMaplimit(Pager *pPager){ -#if SQLITE_MAX_MMAP_SIZE>0 - sqlite3_file *fd = pPager->fd; - if( isOpen(fd) && fd->pMethods->iVersion>=3 ){ - sqlite3_int64 sz; - sz = pPager->szMmap; - pPager->bUseFetch = (sz>0); - setGetterMethod(pPager); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); - } -#endif -} - -/* -** Change the maximum size of any memory mapping made of the database file. -*/ -SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){ - pPager->szMmap = szMmap; - pagerFixMaplimit(pPager); -} - -/* -** Free as much memory as possible from the pager. -*/ -SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){ - sqlite3PcacheShrink(pPager->pPCache); -} - -/* -** Adjust settings of the pager to those specified in the pgFlags parameter. -** -** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness -** of the database to damage due to OS crashes or power failures by -** changing the number of syncs()s when writing the journals. -** There are four levels: -** -** OFF sqlite3OsSync() is never called. This is the default -** for temporary and transient files. -** -** NORMAL The journal is synced once before writes begin on the -** database. This is normally adequate protection, but -** it is theoretically possible, though very unlikely, -** that an inopertune power failure could leave the journal -** in a state which would cause damage to the database -** when it is rolled back. -** -** FULL The journal is synced twice before writes begin on the -** database (with some additional information - the nRec field -** of the journal header - being written in between the two -** syncs). If we assume that writing a -** single disk sector is atomic, then this mode provides -** assurance that the journal will not be corrupted to the -** point of causing damage to the database during rollback. -** -** EXTRA This is like FULL except that is also syncs the directory -** that contains the rollback journal after the rollback -** journal is unlinked. -** -** The above is for a rollback-journal mode. For WAL mode, OFF continues -** to mean that no syncs ever occur. NORMAL means that the WAL is synced -** prior to the start of checkpoint and that the database file is synced -** at the conclusion of the checkpoint if the entire content of the WAL -** was written back into the database. But no sync operations occur for -** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL -** file is synced following each commit operation, in addition to the -** syncs associated with NORMAL. There is no difference between FULL -** and EXTRA for WAL mode. -** -** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The -** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync -** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an -** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL -** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the -** synchronous=FULL versus synchronous=NORMAL setting determines when -** the xSync primitive is called and is relevant to all platforms. -** -** Numeric values associated with these states are OFF==1, NORMAL=2, -** and FULL=3. -*/ -SQLITE_PRIVATE void sqlite3PagerSetFlags( - Pager *pPager, /* The pager to set safety level for */ - unsigned pgFlags /* Various flags */ -){ - unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; - if( pPager->tempFile ){ - pPager->noSync = 1; - pPager->fullSync = 0; - pPager->extraSync = 0; - }else{ - pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; - pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; - pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; - } - if( pPager->noSync ){ - pPager->syncFlags = 0; - }else if( pgFlags & PAGER_FULLFSYNC ){ - pPager->syncFlags = SQLITE_SYNC_FULL; - }else{ - pPager->syncFlags = SQLITE_SYNC_NORMAL; - } - pPager->walSyncFlags = (pPager->syncFlags<<2); - if( pPager->fullSync ){ - pPager->walSyncFlags |= pPager->syncFlags; - } - if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){ - pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2); - } - if( pgFlags & PAGER_CACHESPILL ){ - pPager->doNotSpill &= ~SPILLFLAG_OFF; - }else{ - pPager->doNotSpill |= SPILLFLAG_OFF; - } -} - -/* -** The following global variable is incremented whenever the library -** attempts to open a temporary file. This information is used for -** testing and analysis only. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_opentemp_count = 0; -#endif - -/* -** Open a temporary file. -** -** Write the file descriptor into *pFile. Return SQLITE_OK on success -** or some other error code if we fail. The OS will automatically -** delete the temporary file when it is closed. -** -** The flags passed to the VFS layer xOpen() call are those specified -** by parameter vfsFlags ORed with the following: -** -** SQLITE_OPEN_READWRITE -** SQLITE_OPEN_CREATE -** SQLITE_OPEN_EXCLUSIVE -** SQLITE_OPEN_DELETEONCLOSE -*/ -static int pagerOpentemp( - Pager *pPager, /* The pager object */ - sqlite3_file *pFile, /* Write the file descriptor here */ - int vfsFlags /* Flags passed through to the VFS */ -){ - int rc; /* Return code */ - -#ifdef SQLITE_TEST - sqlite3_opentemp_count++; /* Used for testing and analysis only */ -#endif - - vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; - rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0); - assert( rc!=SQLITE_OK || isOpen(pFile) ); - return rc; -} - -/* -** Set the busy handler function. -** -** The pager invokes the busy-handler if sqlite3OsLock() returns -** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock, -** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE -** lock. It does *not* invoke the busy handler when upgrading from -** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE -** (which occurs during hot-journal rollback). Summary: -** -** Transition | Invokes xBusyHandler -** -------------------------------------------------------- -** NO_LOCK -> SHARED_LOCK | Yes -** SHARED_LOCK -> RESERVED_LOCK | No -** SHARED_LOCK -> EXCLUSIVE_LOCK | No -** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes -** -** If the busy-handler callback returns non-zero, the lock is -** retried. If it returns zero, then the SQLITE_BUSY error is -** returned to the caller of the pager API function. -*/ -SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( - Pager *pPager, /* Pager object */ - int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ - void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ -){ - void **ap; - pPager->xBusyHandler = xBusyHandler; - pPager->pBusyHandlerArg = pBusyHandlerArg; - ap = (void **)&pPager->xBusyHandler; - assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); - assert( ap[1]==pBusyHandlerArg ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); -} - -/* -** Change the page size used by the Pager object. The new page size -** is passed in *pPageSize. -** -** If the pager is in the error state when this function is called, it -** is a no-op. The value returned is the error state error code (i.e. -** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). -** -** Otherwise, if all of the following are true: -** -** * the new page size (value of *pPageSize) is valid (a power -** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and -** -** * there are no outstanding page references, and -** -** * the database is either not an in-memory database or it is -** an in-memory database that currently consists of zero pages. -** -** then the pager object page size is set to *pPageSize. -** -** If the page size is changed, then this function uses sqlite3PagerMalloc() -** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt -** fails, SQLITE_NOMEM is returned and the page size remains unchanged. -** In all other cases, SQLITE_OK is returned. -** -** If the page size is not changed, either because one of the enumerated -** conditions above is not true, the pager was in error state when this -** function was called, or because the memory allocation attempt failed, -** then *pPageSize is set to the old, retained page size before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ - int rc = SQLITE_OK; - - /* It is not possible to do a full assert_pager_state() here, as this - ** function may be called from within PagerOpen(), before the state - ** of the Pager object is internally consistent. - ** - ** At one point this function returned an error if the pager was in - ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that - ** there is at least one outstanding page reference, this function - ** is a no-op for that case anyhow. - */ - - u32 pageSize = *pPageSize; - assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); - if( (pPager->memDb==0 || pPager->dbSize==0) - && sqlite3PcacheRefCount(pPager->pPCache)==0 - && pageSize && pageSize!=(u32)pPager->pageSize - ){ - char *pNew = NULL; /* New temp space */ - i64 nByte = 0; - - if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ - rc = sqlite3OsFileSize(pPager->fd, &nByte); - } - if( rc==SQLITE_OK ){ - /* 8 bytes of zeroed overrun space is sufficient so that the b-tree - * cell header parser will never run off the end of the allocation */ - pNew = (char *)sqlite3PageMalloc(pageSize+8); - if( !pNew ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - memset(pNew+pageSize, 0, 8); - } - } - - if( rc==SQLITE_OK ){ - pager_reset(pPager); - rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); - } - if( rc==SQLITE_OK ){ - sqlite3PageFree(pPager->pTmpSpace); - pPager->pTmpSpace = pNew; - pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); - pPager->pageSize = pageSize; - pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1; - }else{ - sqlite3PageFree(pNew); - } - } - - *pPageSize = pPager->pageSize; - if( rc==SQLITE_OK ){ - if( nReserve<0 ) nReserve = pPager->nReserve; - assert( nReserve>=0 && nReserve<1000 ); - pPager->nReserve = (i16)nReserve; - pagerReportSize(pPager); - pagerFixMaplimit(pPager); - } - return rc; -} - -/* -** Return a pointer to the "temporary page" buffer held internally -** by the pager. This is a buffer that is big enough to hold the -** entire content of a database page. This buffer is used internally -** during rollback and will be overwritten whenever a rollback -** occurs. But other modules are free to use it too, as long as -** no rollbacks are happening. -*/ -SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){ - return pPager->pTmpSpace; -} - -/* -** Attempt to set the maximum database page count if mxPage is positive. -** Make no changes if mxPage is zero or negative. And never reduce the -** maximum page count below the current size of the database. -** -** Regardless of mxPage, return the current maximum page count. -*/ -SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){ - if( mxPage>0 ){ - pPager->mxPgno = mxPage; - } - assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ - /* assert( pPager->mxPgno>=pPager->dbSize ); */ - /* OP_MaxPgcnt ensures that the parameter passed to this function is not - ** less than the total number of valid pages in the database. But this - ** may be less than Pager.dbSize, and so the assert() above is not valid */ - return pPager->mxPgno; -} - -/* -** The following set of routines are used to disable the simulated -** I/O error mechanism. These routines are used to avoid simulated -** errors in places where we do not care about errors. -** -** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops -** and generate no code. -*/ -#ifdef SQLITE_TEST -SQLITE_API extern int sqlite3_io_error_pending; -SQLITE_API extern int sqlite3_io_error_hit; -static int saved_cnt; -void disable_simulated_io_errors(void){ - saved_cnt = sqlite3_io_error_pending; - sqlite3_io_error_pending = -1; -} -void enable_simulated_io_errors(void){ - sqlite3_io_error_pending = saved_cnt; -} -#else -# define disable_simulated_io_errors() -# define enable_simulated_io_errors() -#endif - -/* -** Read the first N bytes from the beginning of the file into memory -** that pDest points to. -** -** If the pager was opened on a transient file (zFilename==""), or -** opened on a file less than N bytes in size, the output buffer is -** zeroed and SQLITE_OK returned. The rationale for this is that this -** function is used to read database headers, and a new transient or -** zero sized database has a header than consists entirely of zeroes. -** -** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered, -** the error code is returned to the caller and the contents of the -** output buffer undefined. -*/ -SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ - int rc = SQLITE_OK; - memset(pDest, 0, N); - assert( isOpen(pPager->fd) || pPager->tempFile ); - - /* This routine is only called by btree immediately after creating - ** the Pager object. There has not been an opportunity to transition - ** to WAL mode yet. - */ - assert( !pagerUseWal(pPager) ); - - if( isOpen(pPager->fd) ){ - IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) - rc = sqlite3OsRead(pPager->fd, pDest, N, 0); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - } - return rc; -} - -/* -** This function may only be called when a read-transaction is open on -** the pager. It returns the total number of pages in the database. -** -** However, if the file is between 1 and bytes in size, then -** this is considered a 1 page file. -*/ -SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){ - assert( pPager->eState>=PAGER_READER ); - assert( pPager->eState!=PAGER_WRITER_FINISHED ); - *pnPage = (int)pPager->dbSize; -} - - -/* -** Try to obtain a lock of type locktype on the database file. If -** a similar or greater lock is already held, this function is a no-op -** (returning SQLITE_OK immediately). -** -** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke -** the busy callback if the lock is currently not available. Repeat -** until the busy callback returns false or until the attempt to -** obtain the lock succeeds. -** -** Return SQLITE_OK on success and an error code if we cannot obtain -** the lock. If the lock is obtained successfully, set the Pager.state -** variable to locktype before returning. -*/ -static int pager_wait_on_lock(Pager *pPager, int locktype){ - int rc; /* Return code */ - - /* Check that this is either a no-op (because the requested lock is - ** already held), or one of the transitions that the busy-handler - ** may be invoked during, according to the comment above - ** sqlite3PagerSetBusyhandler(). - */ - assert( (pPager->eLock>=locktype) - || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK) - || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK) - ); - - do { - rc = pagerLockDb(pPager, locktype); - }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); - return rc; -} - -/* -** Function assertTruncateConstraint(pPager) checks that one of the -** following is true for all dirty pages currently in the page-cache: -** -** a) The page number is less than or equal to the size of the -** 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. -** -** If the condition asserted by this function were not true, and the -** dirty page were to be discarded from the cache via the pagerStress() -** routine, pagerStress() would not write the current page content to -** the database file. If a savepoint transaction were rolled back after -** this happened, the correct behavior would be to restore the current -** content of the page. However, since this content is not present in either -** the database file or the portion of the rollback journal and -** sub-journal rolled back the content could not be restored and the -** database image would become corrupt. It is therefore fortunate that -** this circumstance cannot arise. -*/ -#if defined(SQLITE_DEBUG) -static void assertTruncateConstraintCb(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - assert( pPg->flags&PGHDR_DIRTY ); - if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */ - Pgno pgno = pPg->pgno; - int i; - for(i=0; ipPager->nSavepoint; i++){ - PagerSavepoint *p = &pPager->aSavepoint[i]; - assert( p->nOrigpInSavepoint,pgno) ); - } - } -} -static void assertTruncateConstraint(Pager *pPager){ - sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); -} -#else -# define assertTruncateConstraint(pPager) -#endif - -/* -** Truncate the in-memory database file image to nPage pages. This -** function does not actually modify the database file on disk. It -** just sets the internal state of the pager object so that the -** truncation will be done when the current transaction is committed. -** -** This function is only called right before committing a transaction. -** Once this function has been called, the transaction must either be -** rolled back or committed. It is not safe to call this function and -** then continue writing to the database. -*/ -SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ - assert( pPager->dbSize>=nPage || CORRUPT_DB ); - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); - pPager->dbSize = nPage; - - /* At one point the code here called assertTruncateConstraint() to - ** ensure that all pages being truncated away by this operation are, - ** if one or more savepoints are open, present in the savepoint - ** journal so that they can be restored if the savepoint is rolled - ** back. This is no longer necessary as this function is now only - ** called right before committing a transaction. So although the - ** Pager object may still have open savepoints (Pager.nSavepoint!=0), - ** they cannot be rolled back. So the assertTruncateConstraint() call - ** is no longer correct. */ -} - - -/* -** This function is called before attempting a hot-journal rollback. It -** syncs the journal file to disk, then sets pPager->journalHdr to the -** size of the journal file so that the pager_playback() routine knows -** that the entire journal file has been synced. -** -** Syncing a hot-journal to disk before attempting to roll it back ensures -** that if a power-failure occurs during the rollback, the process that -** attempts rollback following system recovery sees the same journal -** content as this process. -** -** If everything goes as planned, SQLITE_OK is returned. Otherwise, -** an SQLite error code. -*/ -static int pagerSyncHotJournal(Pager *pPager){ - int rc = SQLITE_OK; - if( !pPager->noSync ){ - rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL); - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); - } - return rc; -} - -#if SQLITE_MAX_MMAP_SIZE>0 -/* -** Obtain a reference to a memory mapped page object for page number pgno. -** The new object will use the pointer pData, obtained from xFetch(). -** If successful, set *ppPage to point to the new page reference -** and return SQLITE_OK. Otherwise, return an SQLite error code and set -** *ppPage to zero. -** -** Page references obtained by calling this function should be released -** by calling pagerReleaseMapPage(). -*/ -static int pagerAcquireMapPage( - Pager *pPager, /* Pager object */ - Pgno pgno, /* Page number */ - void *pData, /* xFetch()'d data for this page */ - PgHdr **ppPage /* OUT: Acquired page object */ -){ - PgHdr *p; /* Memory mapped page to return */ - - if( pPager->pMmapFreelist ){ - *ppPage = p = pPager->pMmapFreelist; - pPager->pMmapFreelist = p->pDirty; - p->pDirty = 0; - assert( pPager->nExtra>=8 ); - memset(p->pExtra, 0, 8); - }else{ - *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); - if( p==0 ){ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); - return SQLITE_NOMEM_BKPT; - } - p->pExtra = (void *)&p[1]; - assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) ); - p->flags = PGHDR_MMAP; - p->nRef = 1; - p->pPager = pPager; - } - - assert( p->pExtra==(void *)&p[1] ); - assert( p->pPage==0 ); - assert( p->flags==PGHDR_MMAP ); - assert( p->pPager==pPager ); - assert( p->nRef==1 ); - - p->pgno = pgno; - p->pData = pData; - pPager->nMmapOut++; - - return SQLITE_OK; -} -#endif - -/* -** Release a reference to page pPg. pPg must have been returned by an -** earlier call to pagerAcquireMapPage(). -*/ -static void pagerReleaseMapPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - pPager->nMmapOut--; - pPg->pDirty = pPager->pMmapFreelist; - pPager->pMmapFreelist = pPg; - - assert( pPager->fd->pMethods->iVersion>=3 ); - sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData); -} - -/* -** Free all PgHdr objects stored in the Pager.pMmapFreelist list. -*/ -static void pagerFreeMapHdrs(Pager *pPager){ - PgHdr *p; - PgHdr *pNext; - for(p=pPager->pMmapFreelist; p; p=pNext){ - pNext = p->pDirty; - sqlite3_free(p); - } -} - -/* Verify that the database file has not be deleted or renamed out from -** under the pager. Return SQLITE_OK if the database is still where it ought -** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error -** code from sqlite3OsAccess()) if the database has gone missing. -*/ -static int databaseIsUnmoved(Pager *pPager){ - int bHasMoved = 0; - int rc; - - if( pPager->tempFile ) return SQLITE_OK; - if( pPager->dbSize==0 ) return SQLITE_OK; - assert( pPager->zFilename && pPager->zFilename[0] ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); - if( rc==SQLITE_NOTFOUND ){ - /* If the HAS_MOVED file-control is unimplemented, assume that the file - ** has not been moved. That is the historical behavior of SQLite: prior to - ** version 3.8.3, it never checked */ - rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bHasMoved ){ - rc = SQLITE_READONLY_DBMOVED; - } - return rc; -} - - -/* -** Shutdown the page cache. Free all memory and close all files. -** -** If a transaction was in progress when this routine is called, that -** transaction is rolled back. All outstanding pages are invalidated -** and their memory is freed. Any attempt to use a page associated -** with this page cache after this function returns will likely -** result in a coredump. -** -** This function always succeeds. If a transaction is active an attempt -** is made to roll it back. If an error occurs during the rollback -** a hot journal may be left in the filesystem but no error is returned -** to the caller. -*/ -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ - u8 *pTmp = (u8*)pPager->pTmpSpace; - assert( db || pagerUseWal(pPager)==0 ); - assert( assert_pager_state(pPager) ); - disable_simulated_io_errors(); - sqlite3BeginBenignMalloc(); - pagerFreeMapHdrs(pPager); - /* pPager->errCode = 0; */ - pPager->exclusiveMode = 0; -#ifndef SQLITE_OMIT_WAL - { - u8 *a = 0; - assert( db || pPager->pWal==0 ); - if( db && 0==(db->flags & SQLITE_NoCkptOnClose) - && SQLITE_OK==databaseIsUnmoved(pPager) - ){ - a = pTmp; - } - sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); - pPager->pWal = 0; - } -#endif - pager_reset(pPager); - if( MEMDB ){ - pager_unlock(pPager); - }else{ - /* If it is open, sync the journal file before calling UnlockAndRollback. - ** If this is not done, then an unsynced portion of the open journal - ** file may be played back into the database. If a power failure occurs - ** while this is happening, the database could become corrupt. - ** - ** If an error occurs while trying to sync the journal, shift the pager - ** into the ERROR state. This causes UnlockAndRollback to unlock the - ** database and close the journal file without attempting to roll it - ** back or finalize it. The next database user will have to do hot-journal - ** rollback before accessing the database file. - */ - if( isOpen(pPager->jfd) ){ - pager_error(pPager, pagerSyncHotJournal(pPager)); - } - pagerUnlockAndRollback(pPager); - } - sqlite3EndBenignMalloc(); - enable_simulated_io_errors(); - PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); - IOTRACE(("CLOSE %p\n", pPager)) - sqlite3OsClose(pPager->jfd); - sqlite3OsClose(pPager->fd); - sqlite3PageFree(pTmp); - sqlite3PcacheClose(pPager->pPCache); - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); -#endif -/* END SQLCIPHER */ - - assert( !pPager->aSavepoint && !pPager->pInJournal ); - assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ); - - sqlite3_free(pPager); - return SQLITE_OK; -} - -#if !defined(NDEBUG) || defined(SQLITE_TEST) -/* -** Return the page number for page pPg. -*/ -SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){ - return pPg->pgno; -} -#endif - -/* -** Increment the reference count for page pPg. -*/ -SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){ - sqlite3PcacheRef(pPg); -} - -/* -** Sync the journal. In other words, make sure all the pages that have -** been written to the journal have actually reached the surface of the -** disk and can be restored in the event of a hot-journal rollback. -** -** If the Pager.noSync flag is set, then this function is a no-op. -** Otherwise, the actions required depend on the journal-mode and the -** device characteristics of the file-system, as follows: -** -** * If the journal file is an in-memory journal file, no action need -** be taken. -** -** * Otherwise, if the device does not support the SAFE_APPEND property, -** then the nRec field of the most recently written journal header -** is updated to contain the number of journal records that have -** been written following it. If the pager is operating in full-sync -** mode, then the journal file is synced before this field is updated. -** -** * If the device does not support the SEQUENTIAL property, then -** journal file is synced. -** -** Or, in pseudo-code: -** -** if( NOT ){ -** if( NOT SAFE_APPEND ){ -** if( ) xSync(); -** -** } -** if( NOT SEQUENTIAL ) xSync(); -** } -** -** If successful, this routine clears the PGHDR_NEED_SYNC flag of every -** page currently held in memory before returning SQLITE_OK. If an IO -** error is encountered, then the IO error code is returned to the caller. -*/ -static int syncJournal(Pager *pPager, int newHdr){ - int rc; /* Return code */ - - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - assert( !pagerUseWal(pPager) ); - - rc = sqlite3PagerExclusiveLock(pPager); - if( rc!=SQLITE_OK ) return rc; - - if( !pPager->noSync ){ - assert( !pPager->tempFile ); - if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ - const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); - assert( isOpen(pPager->jfd) ); - - if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ - /* This block deals with an obscure problem. If the last connection - ** that wrote to this database was operating in persistent-journal - ** mode, then the journal file may at this point actually be larger - ** than Pager.journalOff bytes. If the next thing in the journal - ** file happens to be a journal-header (written as part of the - ** previous connection's transaction), and a crash or power-failure - ** occurs after nRec is updated but before this connection writes - ** anything else to the journal file (or commits/rolls back its - ** transaction), then SQLite may become confused when doing the - ** hot-journal rollback following recovery. It may roll back all - ** of this connections data, then proceed to rolling back the old, - ** out-of-date data that follows it. Database corruption. - ** - ** To work around this, if the journal file does appear to contain - ** a valid header following Pager.journalOff, then write a 0x00 - ** byte to the start of it to prevent it from being recognized. - ** - ** Variable iNextHdrOffset is set to the offset at which this - ** problematic header will occur, if it exists. aMagic is used - ** as a temporary buffer to inspect the first couple of bytes of - ** the potential journal header. - */ - i64 iNextHdrOffset; - u8 aMagic[8]; - u8 zHeader[sizeof(aJournalMagic)+4]; - - memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); - put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec); - - iNextHdrOffset = journalHdrOffset(pPager); - rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset); - if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){ - static const u8 zerobyte = 0; - rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset); - } - if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ - return rc; - } - - /* Write the nRec value into the journal file header. If in - ** full-synchronous mode, sync the journal first. This ensures that - ** all data has really hit the disk before nRec is updated to mark - ** it as a candidate for rollback. - ** - ** This is not required if the persistent media supports the - ** SAFE_APPEND property. Because in this case it is not possible - ** for garbage data to be appended to the file, the nRec field - ** is populated with 0xFFFFFFFF when the journal header is written - ** and never needs to be updated. - */ - if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ - PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); - IOTRACE(("JSYNC %p\n", pPager)) - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); - if( rc!=SQLITE_OK ) return rc; - } - IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); - rc = sqlite3OsWrite( - pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr - ); - if( rc!=SQLITE_OK ) return rc; - } - if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ - PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); - IOTRACE(("JSYNC %p\n", pPager)) - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| - (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) - ); - if( rc!=SQLITE_OK ) return rc; - } - - pPager->journalHdr = pPager->journalOff; - if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ - pPager->nRec = 0; - rc = writeJournalHdr(pPager); - if( rc!=SQLITE_OK ) return rc; - } - }else{ - pPager->journalHdr = pPager->journalOff; - } - } - - /* Unless the pager is in noSync mode, the journal file was just - ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on - ** all pages. - */ - sqlite3PcacheClearSyncFlags(pPager->pPCache); - pPager->eState = PAGER_WRITER_DBMOD; - assert( assert_pager_state(pPager) ); - return SQLITE_OK; -} - -/* -** The argument is the first in a linked list of dirty pages connected -** by the PgHdr.pDirty pointer. This function writes each one of the -** in-memory pages in the list to the database file. The argument may -** be NULL, representing an empty list. In this case this function is -** a no-op. -** -** The pager must hold at least a RESERVED lock when this function -** is called. Before writing anything to the database file, this lock -** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained, -** SQLITE_BUSY is returned and no data is written to the database file. -** -** If the pager is a temp-file pager and the actual file-system file -** is not yet open, it is created and opened before any data is -** written out. -** -** Once the lock has been upgraded and, if necessary, the file opened, -** the pages are written out to the database file in list order. Writing -** a page is skipped if it meets either of the following criteria: -** -** * The page number is greater than Pager.dbSize, or -** * The PGHDR_DONT_WRITE flag is set on the page. -** -** If writing out a page causes the database file to grow, Pager.dbFileSize -** is updated accordingly. If page 1 is written out, then the value cached -** in Pager.dbFileVers[] is updated to match the new value stored in -** the database file. -** -** If everything is successful, SQLITE_OK is returned. If an IO error -** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot -** be obtained, SQLITE_BUSY is returned. -*/ -static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ - int rc = SQLITE_OK; /* Return code */ - - /* This function is only called for rollback pagers in WRITER_DBMOD state. */ - assert( !pagerUseWal(pPager) ); - assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD ); - assert( pPager->eLock==EXCLUSIVE_LOCK ); - assert( isOpen(pPager->fd) || pList->pDirty==0 ); - - /* If the file is a temp-file has not yet been opened, open it now. It - ** is not possible for rc to be other than SQLITE_OK if this branch - ** is taken, as pager_wait_on_lock() is a no-op for temp-files. - */ - if( !isOpen(pPager->fd) ){ - assert( pPager->tempFile && rc==SQLITE_OK ); - rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); - } - - /* Before the first write, give the VFS a hint of what the final - ** file size will be. - */ - assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); - if( rc==SQLITE_OK - && pPager->dbHintSizedbSize - && (pList->pDirty || pList->pgno>pPager->dbHintSize) - ){ - sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); - pPager->dbHintSize = pPager->dbSize; - } - - while( rc==SQLITE_OK && pList ){ - Pgno pgno = pList->pgno; - - /* If there are dirty pages in the page cache with page numbers greater - ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to - ** make the file smaller (presumably by auto-vacuum code). Do not write - ** any such pages to the file. - ** - ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag - ** set (set by sqlite3PagerDontWrite()). - */ - if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ - i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ - char *pData; /* Data to write */ - - assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); - if( pList->pgno==1 ) pager_write_changecounter(pList); - - /* Encode the database */ - CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData); - - /* Write out the page data. */ - rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); - - /* If page 1 was just written, update Pager.dbFileVers to match - ** the value now stored in the database file. If writing this - ** page caused the database file to grow, update dbFileSize. - */ - if( pgno==1 ){ - memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); - } - if( pgno>pPager->dbFileSize ){ - pPager->dbFileSize = pgno; - } - pPager->aStat[PAGER_STAT_WRITE]++; - - /* Update any backup objects copying the contents of this pager. */ - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); - - PAGERTRACE(("STORE %d page %d hash(%08x)\n", - PAGERID(pPager), pgno, pager_pagehash(pList))); - IOTRACE(("PGOUT %p %d\n", pPager, pgno)); - PAGER_INCR(sqlite3_pager_writedb_count); - }else{ - PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); - } - pager_set_pagehash(pList); - pList = pList->pDirty; - } - - return rc; -} - -/* -** Ensure that the sub-journal file is open. If it is already open, this -** function is a no-op. -** -** SQLITE_OK is returned if everything goes according to plan. An -** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() -** fails. -*/ -static int openSubJournal(Pager *pPager){ - int rc = SQLITE_OK; - if( !isOpen(pPager->sjfd) ){ - const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE - | SQLITE_OPEN_DELETEONCLOSE; - int nStmtSpill = sqlite3Config.nStmtSpill; - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ - nStmtSpill = -1; - } - rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nStmtSpill); - } - return rc; -} - -/* -** Append a record of the current state of page pPg to the sub-journal. -** -** If successful, set the bit corresponding to pPg->pgno in the bitvecs -** for all open savepoints before returning. -** -** This function returns SQLITE_OK if everything is successful, an IO -** error code if the attempt to write to the sub-journal fails, or -** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint -** bitvec. -*/ -static int subjournalPage(PgHdr *pPg){ - int rc = SQLITE_OK; - Pager *pPager = pPg->pPager; - if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - - /* Open the sub-journal, if it has not already been opened */ - assert( pPager->useJournal ); - assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); - assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); - assert( pagerUseWal(pPager) - || pageInJournal(pPager, pPg) - || pPg->pgno>pPager->dbOrigSize - ); - rc = openSubJournal(pPager); - - /* If the sub-journal was opened successfully (or was already open), - ** write the journal record into the file. */ - if( rc==SQLITE_OK ){ - void *pData = pPg->pData; - i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); - char *pData2; - -/* BEGIN SQLCIPHER */ -#if SQLITE_HAS_CODEC - if( !pPager->subjInMemory ){ - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); - }else -#endif -/* END SQLCIPHER */ - pData2 = pData; - PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); - rc = write32bits(pPager->sjfd, offset, pPg->pgno); - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4); - } - } - } - if( rc==SQLITE_OK ){ - pPager->nSubRec++; - assert( pPager->nSavepoint>0 ); - rc = addToSavepointBitvecs(pPager, pPg->pgno); - } - return rc; -} -static int subjournalPageIfRequired(PgHdr *pPg){ - if( subjRequiresPage(pPg) ){ - return subjournalPage(pPg); - }else{ - return SQLITE_OK; - } -} - -/* -** This function is called by the pcache layer when it has reached some -** soft memory limit. The first argument is a pointer to a Pager object -** (cast as a void*). The pager is always 'purgeable' (not an in-memory -** database). The second argument is a reference to a page that is -** currently dirty but has no outstanding references. The page -** is always associated with the Pager object passed as the first -** argument. -** -** The job of this function is to make pPg clean by writing its contents -** out to the database file, if possible. This may involve syncing the -** journal file. -** -** If successful, sqlite3PcacheMakeClean() is called on the page and -** SQLITE_OK returned. If an IO error occurs while trying to make the -** page clean, the IO error code is returned. If the page cannot be -** made clean for some other reason, but no error occurs, then SQLITE_OK -** is returned by sqlite3PcacheMakeClean() is not called. -*/ -static int pagerStress(void *p, PgHdr *pPg){ - Pager *pPager = (Pager *)p; - int rc = SQLITE_OK; - - assert( pPg->pPager==pPager ); - assert( pPg->flags&PGHDR_DIRTY ); - - /* The doNotSpill NOSYNC bit is set during times when doing a sync of - ** journal (and adding a new header) is not allowed. This occurs - ** during calls to sqlite3PagerWrite() while trying to journal multiple - ** pages belonging to the same sector. - ** - ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling - ** regardless of whether or not a sync is required. This is set during - ** a rollback or by user request, respectively. - ** - ** Spilling is also prohibited when in an error state since that could - ** lead to database corruption. In the current implementation it - ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3 - ** while in the error state, hence it is impossible for this routine to - ** be called in the error state. Nevertheless, we include a NEVER() - ** test for the error state as a safeguard against future changes. - */ - if( NEVER(pPager->errCode) ) return SQLITE_OK; - testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK ); - testcase( pPager->doNotSpill & SPILLFLAG_OFF ); - testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC ); - if( pPager->doNotSpill - && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0 - || (pPg->flags & PGHDR_NEED_SYNC)!=0) - ){ - return SQLITE_OK; - } - - pPager->aStat[PAGER_STAT_SPILL]++; - pPg->pDirty = 0; - if( pagerUseWal(pPager) ){ - /* Write a single frame for this page to the log. */ - rc = subjournalPageIfRequired(pPg); - if( rc==SQLITE_OK ){ - rc = pagerWalFrames(pPager, pPg, 0, 0); - } - }else{ - -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( pPager->tempFile==0 ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ) return pager_error(pPager, rc); - } -#endif - - /* Sync the journal file if required. */ - if( pPg->flags&PGHDR_NEED_SYNC - || pPager->eState==PAGER_WRITER_CACHEMOD - ){ - rc = syncJournal(pPager, 1); - } - - /* Write the contents of the page out to the database file. */ - if( rc==SQLITE_OK ){ - assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); - rc = pager_write_pagelist(pPager, pPg); - } - } - - /* Mark the page as clean. */ - if( rc==SQLITE_OK ){ - PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); - sqlite3PcacheMakeClean(pPg); - } - - return pager_error(pPager, rc); -} - -/* -** Flush all unreferenced dirty pages to disk. -*/ -SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){ - int rc = pPager->errCode; - if( !MEMDB ){ - PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); - assert( assert_pager_state(pPager) ); - while( rc==SQLITE_OK && pList ){ - PgHdr *pNext = pList->pDirty; - if( pList->nRef==0 ){ - rc = pagerStress((void*)pPager, pList); - } - pList = pNext; - } - } - - return rc; -} - -/* -** Allocate and initialize a new Pager object and put a pointer to it -** in *ppPager. The pager should eventually be freed by passing it -** to sqlite3PagerClose(). -** -** The zFilename argument is the path to the database file to open. -** If zFilename is NULL then a randomly-named temporary file is created -** and used as the file to be cached. Temporary files are be deleted -** automatically when they are closed. If zFilename is ":memory:" then -** all information is held in cache. It is never written to disk. -** This can be used to implement an in-memory database. -** -** The nExtra parameter specifies the number of bytes of space allocated -** along with each page reference. This space is available to the user -** via the sqlite3PagerGetExtra() API. When a new page is allocated, the -** first 8 bytes of this space are zeroed but the remainder is uninitialized. -** (The extra space is used by btree as the MemPage object.) -** -** The flags argument is used to specify properties that affect the -** operation of the pager. It should be passed some bitwise combination -** of the PAGER_* flags. -** -** The vfsFlags parameter is a bitmask to pass to the flags parameter -** of the xOpen() method of the supplied VFS when opening files. -** -** If the pager object is allocated and the specified file opened -** successfully, SQLITE_OK is returned and *ppPager set to point to -** the new pager object. If an error occurs, *ppPager is set to NULL -** and error code returned. This function may return SQLITE_NOMEM -** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or -** various SQLITE_IO_XXX errors. -*/ -SQLITE_PRIVATE int sqlite3PagerOpen( - sqlite3_vfs *pVfs, /* The virtual file system to use */ - Pager **ppPager, /* OUT: Return the Pager structure here */ - const char *zFilename, /* Name of the database file to open */ - int nExtra, /* Extra bytes append to each in-memory page */ - int flags, /* flags controlling this file */ - int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ - void (*xReinit)(DbPage*) /* Function to reinitialize pages */ -){ - u8 *pPtr; - Pager *pPager = 0; /* Pager object to allocate and return */ - 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 */ - int memJM = 0; /* Memory journal mode */ - int readOnly = 0; /* True if this is a read-only file */ - int journalFileSize; /* Bytes to allocate for each journal fd */ - char *zPathname = 0; /* Full path to database file */ - int nPathname = 0; /* Number of bytes in zPathname */ - int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ - int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ - u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ - const char *zUri = 0; /* URI args to copy */ - int nUriByte = 1; /* Number of bytes of URI args at *zUri */ - - - /* Figure out how much space is required for each journal file-handle - ** (there are two of them, the main journal and the sub-journal). */ - journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); - - /* Set the output variable to NULL in case an error occurs. */ - *ppPager = 0; - -#ifndef SQLITE_OMIT_MEMORYDB - if( flags & PAGER_MEMORY ){ - memDb = 1; - if( zFilename && zFilename[0] ){ - zPathname = sqlite3DbStrDup(0, zFilename); - if( zPathname==0 ) return SQLITE_NOMEM_BKPT; - nPathname = sqlite3Strlen30(zPathname); - zFilename = 0; - } - } -#endif - - /* Compute and store the full pathname in an allocated buffer pointed - ** to by zPathname, length nPathname. Or, if this is a temporary file, - ** leave both nPathname and zPathname set to 0. - */ - if( zFilename && zFilename[0] ){ - const char *z; - nPathname = pVfs->mxPathname + 1; - zPathname = sqlite3DbMallocRaw(0, 2*(i64)nPathname); - if( zPathname==0 ){ - return SQLITE_NOMEM_BKPT; - } - zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ - rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_OK_SYMLINK ){ - if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){ - rc = SQLITE_CANTOPEN_SYMLINK; - }else{ - rc = SQLITE_OK; - } - } - } - nPathname = sqlite3Strlen30(zPathname); - z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1]; - while( *z ){ - z += strlen(z)+1; - z += strlen(z)+1; - } - nUriByte = (int)(&z[1] - zUri); - assert( nUriByte>=1 ); - if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ - /* This branch is taken when the journal path required by - ** the database being opened will be more than pVfs->mxPathname - ** bytes in length. This means the database cannot be opened, - ** as it will not be possible to open the journal file or even - ** check for a hot-journal before reading. - */ - rc = SQLITE_CANTOPEN_BKPT; - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(0, zPathname); - return rc; - } - } - - /* Allocate memory for the Pager structure, PCache object, the - ** three file descriptors, the database file name and the journal - ** file name. The layout in memory is as follows: - ** - ** Pager object (sizeof(Pager) bytes) - ** PCache object (sqlite3PcacheSize() bytes) - ** Database file handle (pVfs->szOsFile bytes) - ** Sub-journal file handle (journalFileSize bytes) - ** Main journal file handle (journalFileSize bytes) - ** Ptr back to the Pager (sizeof(Pager*) bytes) - ** \0\0\0\0 database prefix (4 bytes) - ** Database file name (nPathname+1 bytes) - ** URI query parameters (nUriByte bytes) - ** Journal filename (nPathname+8+1 bytes) - ** WAL filename (nPathname+4+1 bytes) - ** \0\0\0 terminator (3 bytes) - ** - ** Some 3rd-party software, over which we have no control, depends on - ** the specific order of the filenames and the \0 separators between them - ** so that it can (for example) find the database filename given the WAL - ** filename without using the sqlite3_filename_database() API. This is a - ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party - ** software is in widespread use, so we try to avoid changing the filename - ** order and formatting if possible. In particular, the details of the - ** filename format expected by 3rd-party software should be as follows: - ** - ** - Main Database Path - ** - \0 - ** - Multiple URI components consisting of: - ** - Key - ** - \0 - ** - Value - ** - \0 - ** - \0 - ** - Journal Path - ** - \0 - ** - WAL Path (zWALName) - ** - \0 - ** - ** The sqlite3_create_filename() interface and the databaseFilename() utility - ** that is used by sqlite3_filename_database() and kin also depend on the - ** specific formatting and order of the various filenames, so if the format - ** changes here, be sure to change it there as well. - */ - assert( SQLITE_PTRSIZE==sizeof(Pager*) ); - pPtr = (u8 *)sqlite3MallocZero( - ROUND8(sizeof(*pPager)) + /* Pager structure */ - ROUND8(pcacheSize) + /* PCache object */ - ROUND8(pVfs->szOsFile) + /* The main db file */ - (u64)journalFileSize * 2 + /* The two journal files */ - SQLITE_PTRSIZE + /* Space to hold a pointer */ - 4 + /* Database prefix */ - (u64)nPathname + 1 + /* database filename */ - (u64)nUriByte + /* query parameters */ - (u64)nPathname + 8 + 1 + /* Journal filename */ -#ifndef SQLITE_OMIT_WAL - (u64)nPathname + 4 + 1 + /* WAL filename */ -#endif - 3 /* Terminator */ - ); - assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); - if( !pPtr ){ - sqlite3DbFree(0, zPathname); - return SQLITE_NOMEM_BKPT; - } - pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager)); - pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize); - pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile); - pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; - pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; - assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); - memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE; - - /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ - pPtr += 4; /* Skip zero prefix */ - pPager->zFilename = (char*)pPtr; - if( nPathname>0 ){ - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1; - if( zUri ){ - memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte; - }else{ - pPtr++; - } - } - - - /* Fill in Pager.zJournal */ - if( nPathname>0 ){ - pPager->zJournal = (char*)pPtr; - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; - memcpy(pPtr, "-journal",8); pPtr += 8 + 1; -#ifdef SQLITE_ENABLE_8_3_NAMES - sqlite3FileSuffix3(zFilename,pPager->zJournal); - pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1); -#endif - }else{ - pPager->zJournal = 0; - } - -#ifndef SQLITE_OMIT_WAL - /* Fill in Pager.zWal */ - if( nPathname>0 ){ - pPager->zWal = (char*)pPtr; - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; - memcpy(pPtr, "-wal", 4); pPtr += 4 + 1; -#ifdef SQLITE_ENABLE_8_3_NAMES - sqlite3FileSuffix3(zFilename, pPager->zWal); - pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1); -#endif - }else{ - pPager->zWal = 0; - } -#endif - (void)pPtr; /* Suppress warning about unused pPtr value */ - - if( nPathname ) sqlite3DbFree(0, zPathname); - pPager->pVfs = pVfs; - pPager->vfsFlags = vfsFlags; - - /* Open the pager file. - */ - if( zFilename && zFilename[0] ){ - int fout = 0; /* VFS flags returned by xOpen() */ - rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); - assert( !memDb ); - pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0; - readOnly = (fout&SQLITE_OPEN_READONLY)!=0; - - /* If the file was successfully opened for read/write access, - ** choose a default page size in case we have to create the - ** database file. The default page size is the maximum of: - ** - ** + SQLITE_DEFAULT_PAGE_SIZE, - ** + The value returned by sqlite3OsSectorSize() - ** + The largest page size that can be written atomically. - */ - if( rc==SQLITE_OK ){ - int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); - if( !readOnly ){ - setSectorSize(pPager); - assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); - if( szPageDfltsectorSize ){ - if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ - szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; - }else{ - szPageDflt = (u32)pPager->sectorSize; - } - } -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - { - int ii; - assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); - assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); - assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); - for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ - if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ - szPageDflt = ii; - } - } - } -#endif - } - pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0); - if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 - || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){ - vfsFlags |= SQLITE_OPEN_READONLY; - goto act_like_temp_file; - } - } - }else{ - /* If a temporary file is requested, it is not opened immediately. - ** In this case we accept the default page size and delay actually - ** opening the file until the first call to OsWrite(). - ** - ** This branch is also run for an in-memory database. An in-memory - ** database is the same as a temp-file that is never written out to - ** disk and uses an in-memory rollback journal. - ** - ** This branch also runs for files marked as immutable. - */ -act_like_temp_file: - tempFile = 1; - pPager->eState = PAGER_READER; /* Pretend we already have a lock */ - pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */ - pPager->noLock = 1; /* Do no locking */ - readOnly = (vfsFlags&SQLITE_OPEN_READONLY); - } - - /* The following call to PagerSetPagesize() serves to set the value of - ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. - */ - if( rc==SQLITE_OK ){ - assert( pPager->memDb==0 ); - rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1); - testcase( rc!=SQLITE_OK ); - } - - /* Initialize the PCache object. */ - if( rc==SQLITE_OK ){ - nExtra = ROUND8(nExtra); - assert( nExtra>=8 && nExtra<1000 ); - rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, - !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); - } - - /* If an error occurred above, free the Pager structure and close the file. - */ - if( rc!=SQLITE_OK ){ - sqlite3OsClose(pPager->fd); - sqlite3PageFree(pPager->pTmpSpace); - sqlite3_free(pPager); - return rc; - } - - PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename)); - IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) - - pPager->useJournal = (u8)useJournal; - /* pPager->stmtOpen = 0; */ - /* pPager->stmtInUse = 0; */ - /* pPager->nRef = 0; */ - /* pPager->stmtSize = 0; */ - /* pPager->stmtJSize = 0; */ - /* pPager->nPage = 0; */ - pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; - /* pPager->state = PAGER_UNLOCK; */ - /* pPager->errMask = 0; */ - pPager->tempFile = (u8)tempFile; - assert( tempFile==PAGER_LOCKINGMODE_NORMAL - || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); - assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); - pPager->exclusiveMode = (u8)tempFile; - pPager->changeCountDone = pPager->tempFile; - pPager->memDb = (u8)memDb; - pPager->readOnly = (u8)readOnly; - assert( useJournal || pPager->tempFile ); - sqlite3PagerSetFlags(pPager, (SQLITE_DEFAULT_SYNCHRONOUS+1)|PAGER_CACHESPILL); - /* pPager->pFirst = 0; */ - /* pPager->pFirstSynced = 0; */ - /* pPager->pLast = 0; */ - pPager->nExtra = (u16)nExtra; - pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; - assert( isOpen(pPager->fd) || tempFile ); - setSectorSize(pPager); - if( !useJournal ){ - pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb || memJM ){ - pPager->journalMode = PAGER_JOURNALMODE_MEMORY; - } - /* pPager->xBusyHandler = 0; */ - /* pPager->pBusyHandlerArg = 0; */ - pPager->xReiniter = xReinit; - setGetterMethod(pPager); - /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ - /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ - - *ppPager = pPager; - return SQLITE_OK; -} - -/* -** Return the sqlite3_file for the main database given the name -** of the corresponding WAL or Journal name as passed into -** xOpen. -*/ -SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ - Pager *pPager; - const char *p; - while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ - zName--; - } - p = zName - 4 - sizeof(Pager*); - assert( EIGHT_BYTE_ALIGNMENT(p) ); - pPager = *(Pager**)p; - return pPager->fd; -} - - -/* -** This function is called after transitioning from PAGER_UNLOCK to -** PAGER_SHARED state. It tests if there is a hot journal present in -** the file-system for the given pager. A hot journal is one that -** needs to be played back. According to this function, a hot-journal -** file exists if the following criteria are met: -** -** * The journal file exists in the file system, and -** * No process holds a RESERVED or greater lock on the database file, and -** * The database file itself is greater than 0 bytes in size, and -** * The first byte of the journal file exists and is not 0x00. -** -** If the current size of the database file is 0 but a journal file -** exists, that is probably an old journal left over from a prior -** database with the same name. In this case the journal file is -** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK -** is returned. -** -** This routine does not check if there is a super-journal filename -** at the end of the file. If there is, and that super-journal file -** does not exist, then the journal file is not really hot. In this -** case this routine will return a false-positive. The pager_playback() -** routine will discover that the journal file is not really hot and -** will not roll it back. -** -** If a hot-journal file is found to exist, *pExists is set to 1 and -** SQLITE_OK returned. If no hot-journal file is present, *pExists is -** set to 0 and SQLITE_OK returned. If an IO error occurs while trying -** to determine whether or not a hot-journal file exists, the IO error -** code is returned and the value of *pExists is undefined. -*/ -static int hasHotJournal(Pager *pPager, int *pExists){ - sqlite3_vfs * const pVfs = pPager->pVfs; - int rc = SQLITE_OK; /* Return code */ - int exists = 1; /* True if a journal file is present */ - int jrnlOpen = !!isOpen(pPager->jfd); - - assert( pPager->useJournal ); - assert( isOpen(pPager->fd) ); - assert( pPager->eState==PAGER_OPEN ); - - assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) & - SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN - )); - - *pExists = 0; - if( !jrnlOpen ){ - rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); - } - if( rc==SQLITE_OK && exists ){ - int locked = 0; /* True if some process holds a RESERVED lock */ - - /* Race condition here: Another process might have been holding the - ** the RESERVED lock and have a journal open at the sqlite3OsAccess() - ** call above, but then delete the journal and drop the lock before - ** we get to the following sqlite3OsCheckReservedLock() call. If that - ** is the case, this routine might think there is a hot journal when - ** in fact there is none. This results in a false-positive which will - ** be dealt with by the playback routine. Ticket #3883. - */ - rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); - if( rc==SQLITE_OK && !locked ){ - Pgno nPage; /* Number of pages in database file */ - - assert( pPager->tempFile==0 ); - rc = pagerPagecount(pPager, &nPage); - if( rc==SQLITE_OK ){ - /* If the database is zero pages in size, that means that either (1) the - ** journal is a remnant from a prior database with the same name where - ** the database file but not the journal was deleted, or (2) the initial - ** transaction that populates a new database is being rolled back. - ** In either case, the journal file can be deleted. However, take care - ** not to delete the journal file if it is already open due to - ** journal_mode=PERSIST. - */ - if( nPage==0 && !jrnlOpen ){ - sqlite3BeginBenignMalloc(); - if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ - sqlite3OsDelete(pVfs, pPager->zJournal, 0); - if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); - } - sqlite3EndBenignMalloc(); - }else{ - /* The journal file exists and no other connection has a reserved - ** or greater lock on the database file. Now check that there is - ** at least one non-zero bytes at the start of the journal file. - ** If there is, then we consider this journal to be hot. If not, - ** it can be ignored. - */ - if( !jrnlOpen ){ - int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL; - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f); - } - if( rc==SQLITE_OK ){ - u8 first = 0; - rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - if( !jrnlOpen ){ - sqlite3OsClose(pPager->jfd); - } - *pExists = (first!=0); - }else if( rc==SQLITE_CANTOPEN ){ - /* If we cannot open the rollback journal file in order to see if - ** it has a zero header, that might be due to an I/O error, or - ** it might be due to the race condition described above and in - ** ticket #3883. Either way, assume that the journal is hot. - ** This might be a false positive. But if it is, then the - ** automatic journal playback and recovery mechanism will deal - ** with it under an EXCLUSIVE lock where we do not need to - ** worry so much with race conditions. - */ - *pExists = 1; - rc = SQLITE_OK; - } - } - } - } - } - - return rc; -} - -/* -** This function is called to obtain a shared lock on the database file. -** It is illegal to call sqlite3PagerGet() until after this function -** has been successfully called. If a shared-lock is already held when -** this function is called, it is a no-op. -** -** The following operations are also performed by this function. -** -** 1) If the pager is currently in PAGER_OPEN state (no lock held -** on the database file), then an attempt is made to obtain a -** SHARED lock on the database file. Immediately after obtaining -** the SHARED lock, the file-system is checked for a hot-journal, -** which is played back if present. Following any hot-journal -** rollback, the contents of the cache are validated by checking -** the 'change-counter' field of the database file header and -** discarded if they are found to be invalid. -** -** 2) If the pager is running in exclusive-mode, and there are currently -** no outstanding references to any pages, and is in the error state, -** then an attempt is made to clear the error state by discarding -** the contents of the page cache and rolling back any open journal -** file. -** -** If everything is successful, SQLITE_OK is returned. If an IO error -** occurs while locking the database, checking for a hot-journal file or -** rolling back a journal file, the IO error code is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - - /* This routine is only called from b-tree and only when there are no - ** outstanding pages. This implies that the pager state should either - ** be OPEN or READER. READER is only possible if the pager is or was in - ** exclusive access mode. */ - assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); - assert( assert_pager_state(pPager) ); - assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); - assert( pPager->errCode==SQLITE_OK ); - - if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ - int bHotJournal = 1; /* True if there exists a hot journal-file */ - - assert( !MEMDB ); - assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK ); - - rc = pager_wait_on_lock(pPager, SHARED_LOCK); - if( rc!=SQLITE_OK ){ - assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); - goto failed; - } - - /* If a journal file exists, and there is no RESERVED lock on the - ** database file, then it either needs to be played back or deleted. - */ - if( pPager->eLock<=SHARED_LOCK ){ - rc = hasHotJournal(pPager, &bHotJournal); - } - if( rc!=SQLITE_OK ){ - goto failed; - } - if( bHotJournal ){ - if( pPager->readOnly ){ - rc = SQLITE_READONLY_ROLLBACK; - goto failed; - } - - /* Get an EXCLUSIVE lock on the database file. At this point it is - ** important that a RESERVED lock is not obtained on the way to the - ** EXCLUSIVE lock. If it were, another process might open the - ** database file, detect the RESERVED lock, and conclude that the - ** database is safe to read while this process is still rolling the - ** hot-journal back. - ** - ** Because the intermediate RESERVED lock is not requested, any - ** other process attempting to access the database file will get to - ** this point in the code and fail to obtain its own EXCLUSIVE lock - ** on the database file. - ** - ** Unless the pager is in locking_mode=exclusive mode, the lock is - ** downgraded to SHARED_LOCK before this function returns. - */ - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - goto failed; - } - - /* If it is not already open and the file exists on disk, open the - ** journal for read/write access. Write access is required because - ** in exclusive-access mode the file descriptor will be kept open - ** and possibly used for a transaction later on. Also, write-access - ** is usually required to finalize the journal in journal_mode=persist - ** mode (and also for journal_mode=truncate on some systems). - ** - ** If the journal does not exist, it usually means that some - ** other connection managed to get in and roll it back before - ** this connection obtained the exclusive lock above. Or, it - ** 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) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - sqlite3_vfs * const pVfs = pPager->pVfs; - int bExists; /* True if journal file exists */ - rc = sqlite3OsAccess( - pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); - if( rc==SQLITE_OK && bExists ){ - int fout = 0; - int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; - assert( !pPager->tempFile ); - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); - if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ - rc = SQLITE_CANTOPEN_BKPT; - sqlite3OsClose(pPager->jfd); - } - } - } - - /* Playback and delete the journal. Drop the database write - ** lock and reacquire the read lock. Purge the cache before - ** playing back the hot-journal so that we don't end up with - ** an inconsistent cache. Sync the hot journal before playing - ** it back since the process that crashed and left the hot journal - ** probably did not sync it and we are required to always sync - ** the journal before playing it back. - */ - if( isOpen(pPager->jfd) ){ - assert( rc==SQLITE_OK ); - rc = pagerSyncHotJournal(pPager); - if( rc==SQLITE_OK ){ - rc = pager_playback(pPager, !pPager->tempFile); - pPager->eState = PAGER_OPEN; - } - }else if( !pPager->exclusiveMode ){ - pagerUnlockDb(pPager, SHARED_LOCK); - } - - if( rc!=SQLITE_OK ){ - /* This branch is taken if an error occurs while trying to open - ** or roll back a hot-journal while holding an EXCLUSIVE lock. The - ** pager_unlock() routine will be called before returning to unlock - ** the file. If the unlock attempt fails, then Pager.eLock must be - ** set to UNKNOWN_LOCK (see the comment above the #define for - ** UNKNOWN_LOCK above for an explanation). - ** - ** In order to get pager_unlock() to do this, set Pager.eState to - ** PAGER_ERROR now. This is not actually counted as a transition - ** to ERROR state in the state diagram at the top of this file, - ** since we know that the same call to pager_unlock() will very - ** shortly transition the pager object to the OPEN state. Calling - ** assert_pager_state() would fail now, as it should not be possible - ** to be in ERROR state when there are zero outstanding page - ** references. - */ - pager_error(pPager, rc); - goto failed; - } - - assert( pPager->eState==PAGER_OPEN ); - assert( (pPager->eLock==SHARED_LOCK) - || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) - ); - } - - if( !pPager->tempFile && pPager->hasHeldSharedLock ){ - /* The shared-lock has just been acquired then check to - ** see if the database has been modified. If the database has changed, - ** flush the cache. The hasHeldSharedLock flag prevents this from - ** occurring on the very first access to a file, in order to save a - ** single unnecessary sqlite3OsRead() call at the start-up. - ** - ** Database changes are detected by looking at 15 bytes beginning - ** at offset 24 into the file. The first 4 of these 16 bytes are - ** a 32-bit counter that is incremented with each change. The - ** other bytes change randomly with each file change when - ** a codec is in use. - ** - ** There is a vanishingly small chance that a change will not be - ** detected. The chance of an undetected change is so small that - ** it can be neglected. - */ - char dbFileVers[sizeof(pPager->dbFileVers)]; - - IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); - rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); - if( rc!=SQLITE_OK ){ - if( rc!=SQLITE_IOERR_SHORT_READ ){ - goto failed; - } - memset(dbFileVers, 0, sizeof(dbFileVers)); - } - - if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ - pager_reset(pPager); - - /* Unmap the database file. It is possible that external processes - ** may have truncated the database file and then extended it back - ** to its original size while this process was not holding a lock. - ** In this case there may exist a Pager.pMap mapping that appears - ** to be the right size but is not actually valid. Avoid this - ** possibility by unmapping the db here. */ - if( USEFETCH(pPager) ){ - sqlite3OsUnfetch(pPager->fd, 0, 0); - } - } - } - - /* If there is a WAL file in the file-system, open this database in WAL - ** mode. Otherwise, the following function call is a no-op. - */ - rc = pagerOpenWalIfPresent(pPager); -#ifndef SQLITE_OMIT_WAL - assert( pPager->pWal==0 || rc==SQLITE_OK ); -#endif - } - - if( pagerUseWal(pPager) ){ - assert( rc==SQLITE_OK ); - rc = pagerBeginReadTransaction(pPager); - } - - if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ - rc = pagerPagecount(pPager, &pPager->dbSize); - } - - failed: - if( rc!=SQLITE_OK ){ - assert( !MEMDB ); - pager_unlock(pPager); - assert( pPager->eState==PAGER_OPEN ); - }else{ - pPager->eState = PAGER_READER; - pPager->hasHeldSharedLock = 1; - } - return rc; -} - -/* -** If the reference count has reached zero, rollback any active -** transaction and unlock the pager. -** -** Except, in locking_mode=EXCLUSIVE when there is nothing to in -** the rollback journal, the unlock is not performed and there is -** nothing to rollback, so this routine is a no-op. -*/ -static void pagerUnlockIfUnused(Pager *pPager){ - if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){ - assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */ - pagerUnlockAndRollback(pPager); - } -} - -/* -** The page getter methods each try to acquire a reference to a -** page with page number pgno. If the requested reference is -** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. -** -** There are different implementations of the getter method depending -** on the current state of the pager. -** -** getPageNormal() -- The normal getter -** getPageError() -- Used if the pager is in an error state -** getPageMmap() -- Used if memory-mapped I/O is enabled -** -** If the requested page is already in the cache, it is returned. -** Otherwise, a new page object is allocated and populated with data -** read from the database file. In some cases, the pcache module may -** choose not to allocate a new page object and may reuse an existing -** object with no outstanding references. -** -** The extra data appended to a page is always initialized to zeros the -** first time a page is loaded into memory. If the page requested is -** already in the cache when this function is called, then the extra -** data is left as it was when the page object was last used. -** -** If the database image is smaller than the requested page or if -** the flags parameter contains the PAGER_GET_NOCONTENT bit and the -** requested page is not already stored in the cache, then no -** actual disk read occurs. In this case the memory image of the -** page is initialized to all zeros. -** -** If PAGER_GET_NOCONTENT is true, it means that we do not care about -** the contents of the page. This occurs in two scenarios: -** -** a) When reading a free-list leaf page from the database, and -** -** b) When a savepoint is being rolled back and we need to load -** a new page into the cache to be filled with the data read -** from the savepoint journal. -** -** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead -** of being read from the database. Additionally, the bits corresponding -** to pgno in Pager.pInJournal (bitvec of pages already written to the -** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open -** savepoints are set. This means if the page is made writable at any -** point in the future, using a call to sqlite3PagerWrite(), its contents -** will not be journaled. This saves IO. -** -** The acquisition might fail for several reasons. In all cases, -** an appropriate error code is returned and *ppPage is set to NULL. -** -** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt -** to find a page in the in-memory cache first. If the page is not already -** in memory, this routine goes to disk to read it in whereas Lookup() -** just returns 0. This routine acquires a read-lock the first time it -** has to go to disk, and could also playback an old journal if necessary. -** Since Lookup() never goes to disk, it never has to deal with locks -** or journal files. -*/ -static int getPageNormal( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - int rc = SQLITE_OK; - PgHdr *pPg; - u8 noContent; /* True if PAGER_GET_NOCONTENT is set */ - sqlite3_pcache_page *pBase; - - assert( pPager->errCode==SQLITE_OK ); - assert( pPager->eState>=PAGER_READER ); - assert( assert_pager_state(pPager) ); - assert( pPager->hasHeldSharedLock==1 ); - - if( pgno==0 ) return SQLITE_CORRUPT_BKPT; - pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); - if( pBase==0 ){ - pPg = 0; - rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - if( pBase==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto pager_acquire_err; - } - } - pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); - assert( pPg==(*ppPage) ); - assert( pPg->pgno==pgno ); - assert( pPg->pPager==pPager || pPg->pPager==0 ); - - noContent = (flags & PAGER_GET_NOCONTENT)!=0; - if( pPg->pPager && !noContent ){ - /* In this case the pcache already contains an initialized copy of - ** the page. Return without further ado. */ - assert( pgno!=PAGER_SJ_PGNO(pPager) ); - pPager->aStat[PAGER_STAT_HIT]++; - return SQLITE_OK; - - }else{ - /* The pager cache has created a new page. Its content needs to - ** be initialized. But first some error checks: - ** - ** (*) obsolete. Was: maximum page number is 2^31 - ** (2) Never try to fetch the locking page - */ - if( pgno==PAGER_SJ_PGNO(pPager) ){ - rc = SQLITE_CORRUPT_BKPT; - goto pager_acquire_err; - } - - pPg->pPager = pPager; - - assert( !isOpen(pPager->fd) || !MEMDB ); - if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ - rc = SQLITE_FULL; - if( pgno<=pPager->dbSize ){ - sqlite3PcacheRelease(pPg); - pPg = 0; - } - goto pager_acquire_err; - } - if( noContent ){ - /* Failure to set the bits in the InJournal bit-vectors is benign. - ** It merely means that we might do some extra work to journal a - ** page that does not need to be journaled. Nevertheless, be sure - ** to test the case where a malloc error occurs while trying to set - ** a bit in a bit vector. - */ - sqlite3BeginBenignMalloc(); - if( pgno<=pPager->dbOrigSize ){ - TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno); - testcase( rc==SQLITE_NOMEM ); - } - TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); - testcase( rc==SQLITE_NOMEM ); - sqlite3EndBenignMalloc(); - } - memset(pPg->pData, 0, pPager->pageSize); - IOTRACE(("ZERO %p %d\n", pPager, pgno)); - }else{ - assert( pPg->pPager==pPager ); - pPager->aStat[PAGER_STAT_MISS]++; - rc = readDbPage(pPg); - if( rc!=SQLITE_OK ){ - goto pager_acquire_err; - } - } - pager_set_pagehash(pPg); - } - return SQLITE_OK; - -pager_acquire_err: - assert( rc!=SQLITE_OK ); - if( pPg ){ - sqlite3PcacheDrop(pPg); - } - pagerUnlockIfUnused(pPager); - *ppPage = 0; - return rc; -} - -#if SQLITE_MAX_MMAP_SIZE>0 -/* The page getter for when memory-mapped I/O is enabled */ -static int getPageMMap( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - int rc = SQLITE_OK; - PgHdr *pPg = 0; - u32 iFrame = 0; /* Frame to read from WAL file */ - - /* It is acceptable to use a read-only (mmap) page for any page except - ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY - ** flag was specified by the caller. And so long as the db is not a - ** temporary or in-memory database. */ - const int bMmapOk = (pgno>1 - && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) - ); - - assert( USEFETCH(pPager) ); -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - assert( pPager->xCodec==0 ); -#endif -/* END SQLCIPHER */ - - /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here - ** allows the compiler optimizer to reuse the results of the "pgno>1" - ** test in the previous statement, and avoid testing pgno==0 in the - ** common case where pgno is large. */ - if( pgno<=1 && pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } - assert( pPager->eState>=PAGER_READER ); - assert( assert_pager_state(pPager) ); - assert( pPager->hasHeldSharedLock==1 ); - assert( pPager->errCode==SQLITE_OK ); - - if( bMmapOk && pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ){ - *ppPage = 0; - return rc; - } - } - if( bMmapOk && iFrame==0 ){ - void *pData = 0; - rc = sqlite3OsFetch(pPager->fd, - (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData - ); - if( rc==SQLITE_OK && pData ){ - if( pPager->eState>PAGER_READER || pPager->tempFile ){ - pPg = sqlite3PagerLookup(pPager, pgno); - } - if( pPg==0 ){ - rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); - } - if( pPg ){ - assert( rc==SQLITE_OK ); - *ppPage = pPg; - return SQLITE_OK; - } - } - if( rc!=SQLITE_OK ){ - *ppPage = 0; - return rc; - } - } - return getPageNormal(pPager, pgno, ppPage, flags); -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* The page getter method for when the pager is an error state */ -static int getPageError( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - UNUSED_PARAMETER(pgno); - UNUSED_PARAMETER(flags); - assert( pPager->errCode!=SQLITE_OK ); - *ppPage = 0; - return pPager->errCode; -} - - -/* Dispatch all page fetch requests to the appropriate getter method. -*/ -SQLITE_PRIVATE int sqlite3PagerGet( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ -#if 0 /* Trace page fetch by setting to 1 */ - int rc; - printf("PAGE %u\n", pgno); - fflush(stdout); - rc = pPager->xGet(pPager, pgno, ppPage, flags); - if( rc ){ - printf("PAGE %u failed with 0x%02x\n", pgno, rc); - fflush(stdout); - } - return rc; -#else - /* Normal, high-speed version of sqlite3PagerGet() */ - return pPager->xGet(pPager, pgno, ppPage, flags); -#endif -} - -/* -** Acquire a page if it is already in the in-memory cache. Do -** not read the page from disk. Return a pointer to the page, -** or 0 if the page is not in cache. -** -** See also sqlite3PagerGet(). The difference between this routine -** and sqlite3PagerGet() is that _get() will go to the disk and read -** in the page if the page is not already in cache. This routine -** returns NULL if the page is not in cache or if a disk I/O error -** has ever happened. -*/ -SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ - sqlite3_pcache_page *pPage; - assert( pPager!=0 ); - assert( pgno!=0 ); - assert( pPager->pPCache!=0 ); - pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); - assert( pPage==0 || pPager->hasHeldSharedLock ); - if( pPage==0 ) return 0; - return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); -} - -/* -** Release a page reference. -** -** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be used -** if we know that the page being released is not the last reference to page1. -** The btree layer always holds page1 open until the end, so these first -** two routines can be used to release any page other than BtShared.pPage1. -** The assert() at tag-20230419-2 proves that this constraint is always -** honored. -** -** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine -** checks the total number of outstanding pages and if the number of -** pages reaches zero it drops the database lock. -*/ -SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ - TESTONLY( Pager *pPager = pPg->pPager; ) - assert( pPg!=0 ); - if( pPg->flags & PGHDR_MMAP ){ - assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */ - pagerReleaseMapPage(pPg); - }else{ - sqlite3PcacheRelease(pPg); - } - /* Do not use this routine to release the last reference to page1 */ - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); /* tag-20230419-2 */ -} -SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ - if( pPg ) sqlite3PagerUnrefNotNull(pPg); -} -SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){ - Pager *pPager; - assert( pPg!=0 ); - assert( pPg->pgno==1 ); - assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ - pPager = pPg->pPager; - sqlite3PcacheRelease(pPg); - pagerUnlockIfUnused(pPager); -} - -/* -** This function is called at the start of every write transaction. -** There must already be a RESERVED or EXCLUSIVE lock on the database -** file when this routine is called. -** -** Open the journal file for pager pPager and write a journal header -** to the start of it. If there are active savepoints, open the sub-journal -** as well. This function is only used when the journal file is being -** opened to write a rollback log for a transaction. It is not used -** when opening a hot journal file to roll it back. -** -** If the journal file is already open (as it may be in exclusive mode), -** then this function just writes a journal header to the start of the -** already open file. -** -** Whether or not the journal file is opened by this function, the -** Pager.pInJournal bitvec structure is allocated. -** -** Return SQLITE_OK if everything is successful. Otherwise, return -** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or -** an IO error code if opening or writing the journal file fails. -*/ -static int pager_open_journal(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ - - assert( pPager->eState==PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - assert( pPager->pInJournal==0 ); - - /* If already in the error state, this function is a no-op. But on - ** the other hand, this routine is never called if we are already in - ** an error state. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); - if( pPager->pInJournal==0 ){ - return SQLITE_NOMEM_BKPT; - } - - /* Open the journal file if it is not already open. */ - if( !isOpen(pPager->jfd) ){ - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ - sqlite3MemJournalOpen(pPager->jfd); - }else{ - int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; - int nSpill; - - if( pPager->tempFile ){ - flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); - flags |= SQLITE_OPEN_EXCLUSIVE; - nSpill = sqlite3Config.nStmtSpill; - }else{ - flags |= SQLITE_OPEN_MAIN_JOURNAL; - nSpill = jrnlBufferSize(pPager); - } - - /* Verify that the database still has the same name as it did when - ** it was originally opened. */ - rc = databaseIsUnmoved(pPager); - if( rc==SQLITE_OK ){ - rc = sqlite3JournalOpen ( - pVfs, pPager->zJournal, pPager->jfd, flags, nSpill - ); - } - } - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); - } - - - /* Write the first journal header to the journal file and open - ** the sub-journal if necessary. - */ - if( rc==SQLITE_OK ){ - /* TODO: Check if all of these are really required. */ - pPager->nRec = 0; - pPager->journalOff = 0; - pPager->setSuper = 0; - pPager->journalHdr = 0; - rc = writeJournalHdr(pPager); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - pPager->journalOff = 0; - }else{ - assert( pPager->eState==PAGER_WRITER_LOCKED ); - pPager->eState = PAGER_WRITER_CACHEMOD; - } - - return rc; -} - -/* -** Begin a write-transaction on the specified pager object. If a -** write-transaction has already been opened, this function is a no-op. -** -** If the exFlag argument is false, then acquire at least a RESERVED -** lock on the database file. If exFlag is true, then acquire at least -** an EXCLUSIVE lock. If such a lock is already held, no locking -** functions need be called. -** -** If the subjInMemory argument is non-zero, then any sub-journal opened -** within this transaction will be opened as an in-memory file. This -** has no effect if the sub-journal is already opened (as it may be when -** running in exclusive mode) or if the transaction does not require a -** sub-journal. If the subjInMemory argument is zero, then any required -** sub-journal is implemented in-memory if pPager is an in-memory database, -** or using a temporary file otherwise. -*/ -SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ - int rc = SQLITE_OK; - - if( pPager->errCode ) return pPager->errCode; - assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory; - - if( pPager->eState==PAGER_READER ){ - assert( pPager->pInJournal==0 ); - - if( pagerUseWal(pPager) ){ - /* If the pager is configured to use locking_mode=exclusive, and an - ** exclusive lock on the database is not already held, obtain it now. - */ - if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - return rc; - } - (void)sqlite3WalExclusiveMode(pPager->pWal, 1); - } - - /* Grab the write lock on the log file. If successful, upgrade to - ** PAGER_RESERVED state. Otherwise, return an error code to the caller. - ** The busy-handler is not invoked if another connection already - ** holds the write-lock. If possible, the upper layer will call it. - */ - rc = sqlite3WalBeginWriteTransaction(pPager->pWal); - }else{ - /* Obtain a RESERVED lock on the database file. If the exFlag parameter - ** is true, then immediately upgrade this to an EXCLUSIVE lock. The - ** busy-handler callback can be used when upgrading to the EXCLUSIVE - ** lock, but not when obtaining the RESERVED lock. - */ - rc = pagerLockDb(pPager, RESERVED_LOCK); - if( rc==SQLITE_OK && exFlag ){ - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); - } - } - - if( rc==SQLITE_OK ){ - /* Change to WRITER_LOCKED state. - ** - ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD - ** when it has an open transaction, but never to DBMOD or FINISHED. - ** This is because in those states the code to roll back savepoint - ** transactions may copy data from the sub-journal into the database - ** file as well as into the page cache. Which would be incorrect in - ** WAL mode. - */ - pPager->eState = PAGER_WRITER_LOCKED; - pPager->dbHintSize = pPager->dbSize; - pPager->dbFileSize = pPager->dbSize; - pPager->dbOrigSize = pPager->dbSize; - pPager->journalOff = 0; - } - - assert( rc==SQLITE_OK || pPager->eState==PAGER_READER ); - assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - } - - PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); - return rc; -} - -/* -** Write page pPg onto the end of the rollback journal. -*/ -static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - int rc; - u32 cksum; - char *pData2; - i64 iOff = pPager->journalOff; - - /* 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_SJ_PGNO(pPager) ); - - assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); - cksum = pager_cksum(pPager, (u8*)pData2); - - /* Even if an IO or diskfull error occurs while journalling the - ** page in the block above, set the need-sync flag for the page. - ** Otherwise, when the transaction is rolled back, the logic in - ** playback_one_page() will think that the page needs to be restored - ** in the database file. And if an IO error occurs while doing so, - ** then corruption may follow. - */ - pPg->flags |= PGHDR_NEED_SYNC; - - rc = write32bits(pPager->jfd, iOff, pPg->pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); - if( rc!=SQLITE_OK ) return rc; - rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); - if( rc!=SQLITE_OK ) return rc; - - IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, - pPager->journalOff, pPager->pageSize)); - PAGER_INCR(sqlite3_pager_writej_count); - PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); - - pPager->journalOff += 8 + pPager->pageSize; - pPager->nRec++; - assert( pPager->pInJournal!=0 ); - rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); - testcase( rc==SQLITE_NOMEM ); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - rc |= addToSavepointBitvecs(pPager, pPg->pgno); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - return rc; -} - -/* -** Mark a single data page as writeable. The page is written into the -** main journal or sub-journal as required. If the page is written into -** one of the journals, the corresponding bit is set in the -** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs -** of any open savepoints as appropriate. -*/ -static int pager_write(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - int rc = SQLITE_OK; - - /* This routine is not called unless a write-transaction has already - ** been started. The journal file may or may not be open at this point. - ** It is never called in the ERROR state. - */ - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - assert( pPager->errCode==0 ); - assert( pPager->readOnly==0 ); - CHECK_PAGE(pPg); - - /* The journal file needs to be opened. Higher level routines have already - ** obtained the necessary locks to begin the write-transaction, but the - ** rollback journal might not yet be open. Open it now if this is the case. - ** - ** This is done before calling sqlite3PcacheMakeDirty() on the page. - ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then - ** an error might occur and the pager would end up in WRITER_LOCKED state - ** with pages marked as dirty in the cache. - */ - if( pPager->eState==PAGER_WRITER_LOCKED ){ - rc = pager_open_journal(pPager); - if( rc!=SQLITE_OK ) return rc; - } - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); - assert( assert_pager_state(pPager) ); - - /* Mark the page that is about to be modified as dirty. */ - sqlite3PcacheMakeDirty(pPg); - - /* If a rollback journal is in use, them make sure the page that is about - ** to change is in the rollback journal, or if the page is a new page off - ** then end of the file, make sure it is marked as PGHDR_NEED_SYNC. - */ - assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) ); - if( pPager->pInJournal!=0 - && sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0 - ){ - assert( pagerUseWal(pPager)==0 ); - if( pPg->pgno<=pPager->dbOrigSize ){ - rc = pagerAddPageToRollbackJournal(pPg); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - if( pPager->eState!=PAGER_WRITER_DBMOD ){ - pPg->flags |= PGHDR_NEED_SYNC; - } - PAGERTRACE(("APPEND %d page %d needSync=%d\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); - } - } - - /* The PGHDR_DIRTY bit is set above when the page was added to the dirty-list - ** and before writing the page into the rollback journal. Wait until now, - ** after the page has been successfully journalled, before setting the - ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified. - */ - pPg->flags |= PGHDR_WRITEABLE; - - /* If the statement journal is open and the page is not in it, - ** then write the page into the statement journal. - */ - if( pPager->nSavepoint>0 ){ - rc = subjournalPageIfRequired(pPg); - } - - /* Update the database size and return. */ - if( pPager->dbSizepgno ){ - pPager->dbSize = pPg->pgno; - } - return rc; -} - -/* -** This is a variant of sqlite3PagerWrite() that runs when the sector size -** is larger than the page size. SQLite makes the (reasonable) assumption that -** all bytes of a sector are written together by hardware. Hence, all bytes of -** a sector need to be journalled in case of a power loss in the middle of -** a write. -** -** Usually, the sector size is less than or equal to the page size, in which -** case pages can be individually written. This routine only runs in the -** exceptional case where the page size is smaller than the sector size. -*/ -static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ - int rc = SQLITE_OK; /* Return code */ - Pgno nPageCount; /* Total number of pages in database file */ - Pgno pg1; /* First page of the sector pPg is located on. */ - int nPage = 0; /* Number of pages starting at pg1 to journal */ - int ii; /* Loop counter */ - int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - Pager *pPager = pPg->pPager; /* The pager that owns pPg */ - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - - /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow - ** a journal header to be written between the pages journaled by - ** this function. - */ - assert( !MEMDB ); - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); - pPager->doNotSpill |= SPILLFLAG_NOSYNC; - - /* This trick assumes that both the page-size and sector-size are - ** an integer power of 2. It sets variable pg1 to the identifier - ** of the first page of the sector pPg is located on. - */ - pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; - - nPageCount = pPager->dbSize; - if( pPg->pgno>nPageCount ){ - nPage = (pPg->pgno - pg1)+1; - }else if( (pg1+nPagePerSector-1)>nPageCount ){ - nPage = nPageCount+1-pg1; - }else{ - nPage = nPagePerSector; - } - assert(nPage>0); - assert(pg1<=pPg->pgno); - assert((pg1+nPage)>pPg->pgno); - - for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_SJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage, 0); - if( rc==SQLITE_OK ){ - rc = pager_write(pPage); - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){ - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages - ** starting at pg1, then it needs to be set for all of them. Because - ** writing to any of these nPage pages may damage the others, the - ** journal file must contain sync()ed copies of all of them - ** before any of them can be written out to the database file. - */ - if( rc==SQLITE_OK && needSync ){ - assert( !MEMDB ); - for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnrefNotNull(pPage); - } - } - } - - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); - pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; - return rc; -} - -/* -** Mark a data page as writeable. This routine must be called before -** making changes to a page. The caller must check the return value -** of this function and be careful not to change any page data unless -** this routine returns SQLITE_OK. -** -** The difference between this function and pager_write() is that this -** function also deals with the special case where 2 or more pages -** fit on a single disk sector. In this case all co-resident pages -** must have been written to the journal file before returning. -** -** If an error occurs, SQLITE_NOMEM or an IO error code is returned -** as appropriate. Otherwise, SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - assert( (pPg->flags & PGHDR_MMAP)==0 ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ - if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); - return SQLITE_OK; - }else if( pPager->errCode ){ - return pPager->errCode; - }else if( pPager->sectorSize > (u32)pPager->pageSize ){ - assert( pPager->tempFile==0 ); - return pagerWriteLargeSector(pPg); - }else{ - return pager_write(pPg); - } -} - -/* -** Return TRUE if the page given in the argument was previously passed -** to sqlite3PagerWrite(). In other words, return TRUE if it is ok -** to change the content of the page. -*/ -#ifndef NDEBUG -SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ - return pPg->flags & PGHDR_WRITEABLE; -} -#endif - -/* -** A call to this routine tells the pager that it is not necessary to -** write the information on page pPg back to the disk, even though -** that page might be marked as dirty. This happens, for example, when -** the page has been added as a leaf of the freelist and so its -** content no longer matters. -** -** The overlying software layer calls this routine when all of the data -** on the given page is unused. The pager marks the page as clean so -** that it does not get written to disk. -** -** Tests show that this optimization can quadruple the speed of large -** DELETE operations. -** -** This optimization cannot be used with a temp-file, as the page may -** have been dirty at the start of the transaction. In that case, if -** memory pressure forces page pPg out of the cache, the data does need -** to be written out to disk so that it may be read back in if the -** current transaction is rolled back. -*/ -SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ - PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); - IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) - pPg->flags |= PGHDR_DONT_WRITE; - pPg->flags &= ~PGHDR_WRITEABLE; - testcase( pPg->flags & PGHDR_NEED_SYNC ); - pager_set_pagehash(pPg); - } -} - -/* -** This routine is called to increment the value of the database file -** change-counter, stored as a 4-byte big-endian integer starting at -** byte offset 24 of the pager file. The secondary change counter at -** 92 is also updated, as is the SQLite version number at offset 96. -** -** But this only happens if the pPager->changeCountDone flag is false. -** To avoid excess churning of page 1, the update only happens once. -** See also the pager_write_changecounter() routine that does an -** unconditional update of the change counters. -** -** If the isDirectMode flag is zero, then this is done by calling -** sqlite3PagerWrite() on page 1, then modifying the contents of the -** page data. In this case the file will be updated when the current -** transaction is committed. -** -** The isDirectMode flag may only be non-zero if the library was compiled -** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, -** if isDirect is non-zero, then the database file is updated directly -** by writing an updated version of page 1 using a call to the -** sqlite3OsWrite() function. -*/ -static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ - int rc = SQLITE_OK; - - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - - /* Declare and initialize constant integer 'isDirect'. If the - ** atomic-write optimization is enabled in this build, then isDirect - ** is initialized to the value passed as the isDirectMode parameter - ** to this function. Otherwise, it is always set to zero. - ** - ** The idea is that if the atomic-write optimization is not - ** enabled at compile time, the compiler can omit the tests of - ** 'isDirect' below, as well as the block enclosed in the - ** "if( isDirect )" condition. - */ -#ifndef SQLITE_ENABLE_ATOMIC_WRITE -# define DIRECT_MODE 0 - assert( isDirectMode==0 ); - UNUSED_PARAMETER(isDirectMode); -#else -# define DIRECT_MODE isDirectMode -#endif - - if( !pPager->changeCountDone && pPager->dbSize>0 ){ - PgHdr *pPgHdr; /* Reference to page 1 */ - - assert( !pPager->tempFile && isOpen(pPager->fd) ); - - /* Open page 1 of the file for writing. */ - rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0); - assert( pPgHdr==0 || rc==SQLITE_OK ); - - /* If page one was fetched successfully, and this function is not - ** operating in direct-mode, make page 1 writable. When not in - ** direct mode, page 1 is always held in cache and hence the PagerGet() - ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. - */ - if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ - rc = sqlite3PagerWrite(pPgHdr); - } - - if( rc==SQLITE_OK ){ - /* Actually do the update of the change counter */ - pager_write_changecounter(pPgHdr); - - /* If running in direct mode, write the contents of page 1 to the file. */ - if( DIRECT_MODE ){ - const void *zBuf; - assert( pPager->dbFileSize>0 ); - CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf); - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); - pPager->aStat[PAGER_STAT_WRITE]++; - } - if( rc==SQLITE_OK ){ - /* Update the pager's copy of the change-counter. Otherwise, the - ** next time a read transaction is opened the cache will be - ** flushed (as the change-counter values will not match). */ - const void *pCopy = (const void *)&((const char *)zBuf)[24]; - memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers)); - pPager->changeCountDone = 1; - } - }else{ - pPager->changeCountDone = 1; - } - } - - /* Release the page reference. */ - sqlite3PagerUnref(pPgHdr); - } - return rc; -} - -/* -** Sync the database file to disk. This is a no-op for in-memory databases -** or pages with the Pager.noSync flag set. -** -** If successful, or if called on a pager for which it is a no-op, this -** function returns SQLITE_OK. Otherwise, an IO error code is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper){ - int rc = SQLITE_OK; - void *pArg = (void*)zSuper; - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - if( rc==SQLITE_OK && !pPager->noSync ){ - assert( !MEMDB ); - rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); - } - return rc; -} - -/* -** This function may only be called while a write-transaction is active in -** rollback. If the connection is in WAL mode, this call is a no-op. -** Otherwise, if the connection does not already have an EXCLUSIVE lock on -** the database file, an attempt is made to obtain one. -** -** If the EXCLUSIVE lock is already held or the attempt to obtain it is -** successful, or the connection is in WAL mode, SQLITE_OK is returned. -** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is -** returned. -*/ -SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ - int rc = pPager->errCode; - assert( assert_pager_state(pPager) ); - if( rc==SQLITE_OK ){ - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_WRITER_LOCKED - ); - assert( assert_pager_state(pPager) ); - if( 0==pagerUseWal(pPager) ){ - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); - } - } - return rc; -} - -/* -** Sync the database file for the pager pPager. zSuper points to the name -** of a super-journal file that should be written into the individual -** journal file. zSuper may be NULL, which is interpreted as no -** super-journal (a single database transaction). -** -** This routine ensures that: -** -** * The database file change-counter is updated, -** * the journal is synced (unless the atomic-write optimization is used), -** * all dirty pages are written to the database file, -** * the database file is truncated (if required), and -** * the database file synced. -** -** The only thing that remains to commit the transaction is to finalize -** (delete, truncate or zero the first part of) the journal file (or -** delete the super-journal file if specified). -** -** Note that if zSuper==NULL, this does not overwrite a previous value -** passed to an sqlite3PagerCommitPhaseOne() call. -** -** If the final parameter - noSync - is true, then the database file itself -** is not synced. The caller must call sqlite3PagerSync() directly to -** sync the database file before calling CommitPhaseTwo() to delete the -** journal file in this case. -*/ -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( - Pager *pPager, /* Pager object */ - const char *zSuper, /* If not NULL, the super-journal name */ - int noSync /* True to omit the xSync on the db file */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_ERROR - ); - assert( assert_pager_state(pPager) ); - - /* If a prior error occurred, report that error again. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - /* Provide the ability to easily simulate an I/O error during testing */ - if( sqlite3FaultSim(400) ) return SQLITE_IOERR; - - PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n", - pPager->zFilename, zSuper, pPager->dbSize)); - - /* If no database changes have been made, return early. */ - if( pPager->eStatetempFile ); - assert( isOpen(pPager->fd) || pPager->tempFile ); - if( 0==pagerFlushOnCommit(pPager, 1) ){ - /* If this is an in-memory db, or no pages have been written to, or this - ** function has already been called, it is mostly a no-op. However, any - ** backup in progress needs to be restarted. */ - sqlite3BackupRestart(pPager->pBackup); - }else{ - PgHdr *pList; - if( pagerUseWal(pPager) ){ - PgHdr *pPageOne = 0; - pList = sqlite3PcacheDirtyList(pPager->pPCache); - if( pList==0 ){ - /* Must have at least one page for the WAL commit flag. - ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ - rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0); - pList = pPageOne; - pList->pDirty = 0; - } - assert( rc==SQLITE_OK ); - if( ALWAYS(pList) ){ - rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1); - } - sqlite3PagerUnref(pPageOne); - if( rc==SQLITE_OK ){ - sqlite3PcacheCleanAll(pPager->pPCache); - } - }else{ - /* The bBatch boolean is true if the batch-atomic-write commit method - ** should be used. No rollback journal is created if batch-atomic-write - ** is enabled. - */ -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - sqlite3_file *fd = pPager->fd; - int bBatch = zSuper==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ - && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) - && !pPager->noSync - && sqlite3JournalIsInMemory(pPager->jfd); -#else -# define bBatch 0 -#endif - -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - /* The following block updates the change-counter. Exactly how it - ** does this depends on whether or not the atomic-update optimization - ** was enabled at compile time, and if this transaction meets the - ** runtime criteria to use the operation: - ** - ** * The file-system supports the atomic-write property for - ** blocks of size page-size, and - ** * This commit is not part of a multi-file transaction, and - ** * Exactly one page has been modified and store in the journal file. - ** - ** If the optimization was not enabled at compile time, then the - ** pager_incr_changecounter() function is called to update the change - ** counter in 'indirect-mode'. If the optimization is compiled in but - ** is not applicable to this transaction, call sqlite3JournalCreate() - ** to make sure the journal file has actually been created, then call - ** pager_incr_changecounter() to update the change-counter in indirect - ** mode. - ** - ** Otherwise, if the optimization is both enabled and applicable, - ** then call pager_incr_changecounter() to update the change-counter - ** in 'direct' mode. In this case the journal file will never be - ** created for this transaction. - */ - if( bBatch==0 ){ - PgHdr *pPg; - assert( isOpen(pPager->jfd) - || pPager->journalMode==PAGER_JOURNALMODE_OFF - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - if( !zSuper && isOpen(pPager->jfd) - && pPager->journalOff==jrnlBufferSize(pPager) - && pPager->dbSize>=pPager->dbOrigSize - && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) - ){ - /* Update the db file change counter via the direct-write method. The - ** following call will modify the in-memory representation of page 1 - ** to include the updated change counter and then write page 1 - ** directly to the database file. Because of the atomic-write - ** property of the host file-system, this is safe. - */ - rc = pager_incr_changecounter(pPager, 1); - }else{ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc==SQLITE_OK ){ - rc = pager_incr_changecounter(pPager, 0); - } - } - } -#else /* SQLITE_ENABLE_ATOMIC_WRITE */ -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( zSuper ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - assert( bBatch==0 ); - } -#endif - rc = pager_incr_changecounter(pPager, 0); -#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */ - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Write the super-journal name into the journal file. If a - ** super-journal file name has already been written to the journal file, - ** or if zSuper is NULL (no super-journal), then this call is a no-op. - */ - rc = writeSuperJournal(pPager, zSuper); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Sync the journal file and write all dirty pages to the database. - ** If the atomic-update optimization is being used, this sync will not - ** create the journal file or perform any real IO. - ** - ** Because the change-counter page was just modified, unless the - ** atomic-update optimization is used it is almost certain that the - ** journal requires a sync here. However, in locking_mode=exclusive - ** on a system under memory pressure it is just possible that this is - ** not the case. In this case it is likely enough that the redundant - ** xSync() call will be changed to a no-op by the OS anyhow. - */ - rc = syncJournal(pPager, 0); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - pList = sqlite3PcacheDirtyList(pPager->pPCache); -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( bBatch ){ - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); - if( rc==SQLITE_OK ){ - rc = pager_write_pagelist(pPager, pList); - if( rc==SQLITE_OK && pPager->dbSize>pPager->dbFileSize ){ - char *pTmp = pPager->pTmpSpace; - int szPage = (int)pPager->pageSize; - memset(pTmp, 0, szPage); - rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, - ((i64)pPager->dbSize*pPager->pageSize)-szPage); - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); - } - if( rc!=SQLITE_OK ){ - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); - } - } - - if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ){ - sqlite3OsClose(pPager->jfd); - goto commit_phase_one_exit; - } - bBatch = 0; - }else{ - sqlite3OsClose(pPager->jfd); - } - } -#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ - - if( bBatch==0 ){ - rc = pager_write_pagelist(pPager, pList); - } - if( rc!=SQLITE_OK ){ - assert( rc!=SQLITE_IOERR_BLOCKED ); - goto commit_phase_one_exit; - } - sqlite3PcacheCleanAll(pPager->pPCache); - - /* If the file on disk is smaller than the database image, use - ** pager_truncate to grow the file here. This can happen if the database - ** image was extended as part of the current transaction and then the - ** last page in the db image moved to the free-list. In this case the - ** 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_SJ_PGNO(pPager)); - assert( pPager->eState==PAGER_WRITER_DBMOD ); - rc = pager_truncate(pPager, nNew); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - } - - /* Finally, sync the database file. */ - if( !noSync ){ - rc = sqlite3PagerSync(pPager, zSuper); - } - IOTRACE(("DBSYNC %p\n", pPager)) - } - } - -commit_phase_one_exit: - if( rc==SQLITE_OK && !pagerUseWal(pPager) ){ - pPager->eState = PAGER_WRITER_FINISHED; - } - return rc; -} - - -/* -** When this function is called, the database file has been completely -** updated to reflect the changes made by the current transaction and -** synced to disk. The journal file still exists in the file-system -** though, and if a failure occurs at this point it will eventually -** be used as a hot-journal and the current transaction rolled back. -** -** This function finalizes the journal file, either by deleting, -** truncating or partially zeroing it, so that it cannot be used -** for hot-journal rollback. Once this is done the transaction is -** irrevocably committed. -** -** If an error occurs, an IO error code is returned and the pager -** moves into the error state. Otherwise, SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - - /* This routine should not be called if a prior error has occurred. - ** But if (due to a coding error elsewhere in the system) it does get - ** called, just return the same error code without doing anything. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - pPager->iDataVersion++; - - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_FINISHED - || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD) - ); - assert( assert_pager_state(pPager) ); - - /* An optimization. If the database was not actually modified during - ** this transaction, the pager is running in exclusive-mode and is - ** using persistent journals, then this function is a no-op. - ** - ** The start of the journal file currently contains a single journal - ** header with the nRec field set to 0. If such a journal is used as - ** a hot-journal during hot-journal rollback, 0 changes will be made - ** to the database file. So there is no need to zero the journal - ** header. Since the pager is in exclusive mode, there is no need - ** to drop any locks either. - */ - if( pPager->eState==PAGER_WRITER_LOCKED - && pPager->exclusiveMode - && pPager->journalMode==PAGER_JOURNALMODE_PERSIST - ){ - assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); - pPager->eState = PAGER_READER; - return SQLITE_OK; - } - - PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); - rc = pager_end_transaction(pPager, pPager->setSuper, 1); - return pager_error(pPager, rc); -} - -/* -** If a write transaction is open, then all changes made within the -** transaction are reverted and the current write-transaction is closed. -** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR -** state if an error occurs. -** -** If the pager is already in PAGER_ERROR state when this function is called, -** it returns Pager.errCode immediately. No work is performed in this case. -** -** Otherwise, in rollback mode, this function performs two functions: -** -** 1) It rolls back the journal file, restoring all database file and -** in-memory cache pages to the state they were in when the transaction -** was opened, and -** -** 2) It finalizes the journal file, so that it is not used for hot -** rollback at any point in the future. -** -** Finalization of the journal file (task 2) is only performed if the -** rollback is successful. -** -** In WAL mode, all cache-entries containing data modified within the -** current transaction are either expelled from the cache or reverted to -** their pre-transaction state by re-reading data from the database or -** WAL files. The WAL transaction is then closed. -*/ -SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); - - /* PagerRollback() is a no-op if called in READER or OPEN state. If - ** the pager is already in the ERROR state, the rollback is not - ** attempted here. Instead, the error code is returned to the caller. - */ - assert( assert_pager_state(pPager) ); - if( pPager->eState==PAGER_ERROR ) return pPager->errCode; - if( pPager->eState<=PAGER_READER ) return SQLITE_OK; - - if( pagerUseWal(pPager) ){ - int rc2; - rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); - rc2 = pager_end_transaction(pPager, pPager->setSuper, 0); - if( rc==SQLITE_OK ) rc = rc2; - }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ - int eState = pPager->eState; - rc = pager_end_transaction(pPager, 0, 0); - if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ - /* This can happen using journal_mode=off. Move the pager to the error - ** state to indicate that the contents of the cache may not be trusted. - ** Any active readers will get SQLITE_ABORT. - */ - pPager->errCode = SQLITE_ABORT; - pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); - return rc; - } - }else{ - rc = pager_playback(pPager, 0); - } - - assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); - assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT - || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR - || rc==SQLITE_CANTOPEN - ); - - /* If an error occurs during a ROLLBACK, we can no longer trust the pager - ** cache. So call pager_error() on the way out to make any error persistent. - */ - return pager_error(pPager, rc); -} - -/* -** Return TRUE if the database file is opened read-only. Return FALSE -** if the database is (in theory) writable. -*/ -SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){ - return pPager->readOnly; -} - -#ifdef SQLITE_DEBUG -/* -** Return the sum of the reference counts for all pages held by pPager. -*/ -SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){ - return sqlite3PcacheRefCount(pPager->pPCache); -} -#endif - -/* -** Return the approximate number of bytes of memory currently -** used by the pager and its associated cache. -*/ -SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){ - int perPageSize = pPager->pageSize + pPager->nExtra - + (int)(sizeof(PgHdr) + 5*sizeof(void*)); - return perPageSize*sqlite3PcachePagecount(pPager->pPCache) - + sqlite3MallocSize(pPager) - + pPager->pageSize; -} - -/* -** Return the number of references to the specified page. -*/ -SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){ - return sqlite3PcachePageRefcount(pPage); -} - -#ifdef SQLITE_TEST -/* -** This routine is used for testing and analysis only. -*/ -SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ - static int a[11]; - a[0] = sqlite3PcacheRefCount(pPager->pPCache); - a[1] = sqlite3PcachePagecount(pPager->pPCache); - a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); - a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; - a[4] = pPager->eState; - a[5] = pPager->errCode; - a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff; - a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff; - a[8] = 0; /* Used to be pPager->nOvfl */ - a[9] = pPager->nRead; - a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff; - return a; -} -#endif - -/* -** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE, -** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation -** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because -** it was added later. -** -** Before returning, *pnVal is incremented by the -** current cache hit or miss count, according to the value of eStat. If the -** reset parameter is non-zero, the cache hit or miss count is zeroed before -** returning. -*/ -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){ - - assert( eStat==SQLITE_DBSTATUS_CACHE_HIT - || eStat==SQLITE_DBSTATUS_CACHE_MISS - || eStat==SQLITE_DBSTATUS_CACHE_WRITE - || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 - ); - - assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); - assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); - assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 - && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 ); - - eStat -= SQLITE_DBSTATUS_CACHE_HIT; - *pnVal += pPager->aStat[eStat]; - if( reset ){ - pPager->aStat[eStat] = 0; - } -} - -/* -** Return true if this is an in-memory or temp-file backed pager. -*/ -SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ - return pPager->tempFile || pPager->memVfs; -} - -/* -** Check that there are at least nSavepoint savepoints open. If there are -** currently less than nSavepoints open, then open one or more savepoints -** to make up the difference. If the number of savepoints is already -** equal to nSavepoint, then this function is a no-op. -** -** If a memory allocation fails, SQLITE_NOMEM is returned. If an error -** occurs while opening the sub-journal file, then an IO error code is -** returned. Otherwise, SQLITE_OK. -*/ -static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ - int rc = SQLITE_OK; /* Return code */ - int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ - int ii; /* Iterator variable */ - PagerSavepoint *aNew; /* New Pager.aSavepoint array */ - - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - assert( nSavepoint>nCurrent && pPager->useJournal ); - - /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM - ** if the allocation fails. Otherwise, zero the new portion in case a - ** malloc failure occurs while populating it in the for(...) loop below. - */ - aNew = (PagerSavepoint *)sqlite3Realloc( - pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint - ); - if( !aNew ){ - return SQLITE_NOMEM_BKPT; - } - memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); - pPager->aSavepoint = aNew; - - /* Populate the PagerSavepoint structures just allocated. */ - for(ii=nCurrent; iidbSize; - if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ - aNew[ii].iOffset = pPager->journalOff; - }else{ - aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); - } - aNew[ii].iSubRec = pPager->nSubRec; - aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); - aNew[ii].bTruncateOnRelease = 1; - if( !aNew[ii].pInSavepoint ){ - return SQLITE_NOMEM_BKPT; - } - if( pagerUseWal(pPager) ){ - sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); - } - pPager->nSavepoint = ii+1; - } - assert( pPager->nSavepoint==nSavepoint ); - assertTruncateConstraint(pPager); - return rc; -} -SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - - if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){ - return pagerOpenSavepoint(pPager, nSavepoint); - }else{ - return SQLITE_OK; - } -} - - -/* -** This function is called to rollback or release (commit) a savepoint. -** The savepoint to release or rollback need not be the most recently -** created savepoint. -** -** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE. -** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with -** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes -** that have occurred since the specified savepoint was created. -** -** The savepoint to rollback or release is identified by parameter -** iSavepoint. A value of 0 means to operate on the outermost savepoint -** (the first created). A value of (Pager.nSavepoint-1) means operate -** on the most recently created savepoint. If iSavepoint is greater than -** (Pager.nSavepoint-1), then this function is a no-op. -** -** If a negative value is passed to this function, then the current -** transaction is rolled back. This is different to calling -** sqlite3PagerRollback() because this function does not terminate -** the transaction or unlock the database, it just restores the -** contents of the database to its original state. -** -** In any case, all savepoints with an index greater than iSavepoint -** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE), -** then savepoint iSavepoint is also destroyed. -** -** This function may return SQLITE_NOMEM if a memory allocation fails, -** or an IO error code if an IO error occurs while rolling back a -** savepoint. If no errors occur, SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ - int rc = pPager->errCode; - -#ifdef SQLITE_ENABLE_ZIPVFS - if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK; -#endif - - assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); - assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); - - if( rc==SQLITE_OK && iSavepointnSavepoint ){ - int ii; /* Iterator variable */ - int nNew; /* Number of remaining savepoints after this op. */ - - /* Figure out how many savepoints will still be active after this - ** operation. Store this value in nNew. Then free resources associated - ** with any savepoints that are destroyed by this operation. - */ - nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); - for(ii=nNew; iinSavepoint; ii++){ - sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); - } - pPager->nSavepoint = nNew; - - /* Truncate the sub-journal so that it only includes the parts - ** that are still in use. */ - if( op==SAVEPOINT_RELEASE ){ - PagerSavepoint *pRel = &pPager->aSavepoint[nNew]; - if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){ - /* Only truncate if it is an in-memory sub-journal. */ - if( sqlite3JournalIsInMemory(pPager->sjfd) ){ - i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec; - rc = sqlite3OsTruncate(pPager->sjfd, sz); - assert( rc==SQLITE_OK ); - } - pPager->nSubRec = pRel->iSubRec; - } - } - /* Else this is a rollback operation, playback the specified savepoint. - ** If this is a temp-file, it is possible that the journal file has - ** not yet been opened. In this case there have been no changes to - ** the database file, so the playback operation can be skipped. - */ - else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){ - PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; - rc = pagerPlaybackSavepoint(pPager, pSavepoint); - assert(rc!=SQLITE_DONE); - } - -#ifdef SQLITE_ENABLE_ZIPVFS - /* If the cache has been modified but the savepoint cannot be rolled - ** back journal_mode=off, put the pager in the error state. This way, - ** if the VFS used by this pager includes ZipVFS, the entire transaction - ** can be rolled back at the ZipVFS level. */ - else if( - pPager->journalMode==PAGER_JOURNALMODE_OFF - && pPager->eState>=PAGER_WRITER_CACHEMOD - ){ - pPager->errCode = SQLITE_ABORT; - pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); - } -#endif - } - - return rc; -} - -/* -** Return the full pathname of the database file. -** -** Except, if the pager is in-memory only, then return an empty string if -** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when -** used to report the filename to the user, for compatibility with legacy -** behavior. But when the Btree needs to know the filename for matching to -** shared cache, it uses nullIfMemDb==0 so that in-memory databases can -** participate in shared-cache. -** -** The return value to this routine is always safe to use with -** sqlite3_uri_parameter() and sqlite3_filename_database() and friends. -*/ -SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){ - static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - if( nullIfMemDb && (pPager->memDb || sqlite3IsMemdb(pPager->pVfs)) ){ - return &zFake[4]; - }else{ - return pPager->zFilename; - } -} - -/* -** Return the VFS structure for the pager. -*/ -SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ - return pPager->pVfs; -} - -/* -** Return the file handle for the database file associated -** with the pager. This might return NULL if the file has -** not yet been opened. -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ - return pPager->fd; -} - -/* -** Return the file handle for the journal file (if it exists). -** This will be either the rollback journal or the WAL file. -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ -#ifdef SQLITE_OMIT_WAL - return pPager->jfd; -#else - return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd; -#endif -} - -/* -** Return the full pathname of the journal file. -*/ -SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){ - return pPager->zJournal; -} - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -/* -** Set (or overwrite) the codec for this pager. If there is -** already a codec context (pCodec) attached, it WILL NOT be freed. -** The caller is responsible for freeing the old codec context prior -** setting a new one. -*/ -void sqlcipherPagerSetCodec( - Pager *pPager, - void *(*xCodec)(void*,void*,Pgno,int), - void (*xCodecSizeChng)(void*,int,int), - void (*xCodecFree)(void*), - void *pCodec -){ - pager_reset(pPager); - pPager->xCodec = pPager->memDb ? 0 : xCodec; - pPager->xCodecSizeChng = xCodecSizeChng; - pPager->xCodecFree = xCodecFree; - pPager->pCodec = pCodec; - setGetterMethod(pPager); - pagerReportSize(pPager); -} -/* Retrieve the codec for this pager */ -void *sqlcipherPagerGetCodec(Pager *pPager){ - return pPager->pCodec; -} - -/* -** This function is called by the wal module when writing page content -** into the log file. -** -** This function returns a pointer to a buffer containing the encrypted -** page content. If a malloc fails, this function may return NULL. -*/ -void *sqlcipherPagerCodec(PgHdr *pPg){ - void *aData = 0; - CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); - return aData; -} -#endif /* SQLITE_HAS_CODEC */ -/* END SQLCIPHER */ - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Move the page pPg to location pgno in the file. -** -** There must be no references to the page previously located at -** pgno (which we call pPgOld) though that page is allowed to be -** in cache. If the page previously located at pgno is not already -** in the rollback journal, it is not put there by by this routine. -** -** References to the page pPg remain valid. Updating any -** meta-data associated with pPg (i.e. data stored in the nExtra bytes -** allocated along with the page) is the responsibility of the caller. -** -** A transaction must be active when this routine is called. It used to be -** required that a statement transaction was not active, but this restriction -** has been removed (CREATE INDEX needs to move a page when a statement -** transaction is active). -** -** If the fourth argument, isCommit, is non-zero, then this page is being -** moved as part of a database reorganization just before the transaction -** is being committed. In this case, it is guaranteed that the database page -** pPg refers to will not be written to again within this transaction. -** -** This function may return SQLITE_NOMEM or an IO error code if an error -** occurs. Otherwise, it returns SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ - PgHdr *pPgOld; /* The page being overwritten. */ - Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */ - int rc; /* Return code */ - Pgno origPgno; /* The original page number */ - - assert( pPg->nRef>0 ); - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - - /* In order to be able to rollback, an in-memory database must journal - ** the page we are moving from. - */ - assert( pPager->tempFile || !MEMDB ); - if( pPager->tempFile ){ - rc = sqlite3PagerWrite(pPg); - if( rc ) return rc; - } - - /* If the page being moved is dirty and has not been saved by the latest - ** savepoint, then save the current contents of the page into the - ** sub-journal now. This is required to handle the following scenario: - ** - ** BEGIN; - ** - ** SAVEPOINT one; - ** - ** ROLLBACK TO one; - ** - ** If page X were not written to the sub-journal here, it would not - ** be possible to restore its contents when the "ROLLBACK TO one" - ** statement were is processed. - ** - ** subjournalPage() may need to allocate space to store pPg->pgno into - ** one or more savepoint bitvecs. This is the reason this function - ** may return SQLITE_NOMEM. - */ - if( (pPg->flags & PGHDR_DIRTY)!=0 - && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg)) - ){ - return rc; - } - - PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", - PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); - IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) - - /* If the journal needs to be sync()ed before page pPg->pgno can - ** be written to, store pPg->pgno in local variable needSyncPgno. - ** - ** If the isCommit flag is set, there is no need to remember that - ** the journal needs to be sync()ed before database page pPg->pgno - ** can be written to. The caller has already promised not to write to it. - */ - if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ - needSyncPgno = pPg->pgno; - assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || - pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); - assert( pPg->flags&PGHDR_DIRTY ); - } - - /* If the cache contains a page with page-number pgno, remove it - ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for - ** page pgno before the 'move' operation, it needs to be retained - ** for the page moved there. - */ - pPg->flags &= ~PGHDR_NEED_SYNC; - pPgOld = sqlite3PagerLookup(pPager, pgno); - assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB ); - if( pPgOld ){ - if( NEVER(pPgOld->nRef>1) ){ - sqlite3PagerUnrefNotNull(pPgOld); - return SQLITE_CORRUPT_BKPT; - } - pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); - if( pPager->tempFile ){ - /* Do not discard pages from an in-memory database since we might - ** need to rollback later. Just move the page out of the way. */ - sqlite3PcacheMove(pPgOld, pPager->dbSize+1); - }else{ - sqlite3PcacheDrop(pPgOld); - } - } - - origPgno = pPg->pgno; - sqlite3PcacheMove(pPg, pgno); - sqlite3PcacheMakeDirty(pPg); - - /* For an in-memory database, make sure the original page continues - ** to exist, in case the transaction needs to roll back. Use pPgOld - ** as the original page since it has already been allocated. - */ - if( pPager->tempFile && pPgOld ){ - sqlite3PcacheMove(pPgOld, origPgno); - sqlite3PagerUnrefNotNull(pPgOld); - } - - if( needSyncPgno ){ - /* If needSyncPgno is non-zero, then the journal file needs to be - ** sync()ed before any data is written to database file page needSyncPgno. - ** Currently, no such page exists in the page-cache and the - ** "is journaled" bitvec flag has been set. This needs to be remedied by - ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC - ** flag. - ** - ** If the attempt to load the page into the page-cache fails, (due - ** to a malloc() or IO failure), clear the bit in the pInJournal[] - ** array. Otherwise, if the page is loaded and written again in - ** this transaction, it may be written to the database file before - ** it is synced into the journal file. This way, it may end up in - ** the journal file twice, but that is not a problem. - */ - PgHdr *pPgHdr; - rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0); - if( rc!=SQLITE_OK ){ - if( needSyncPgno<=pPager->dbOrigSize ){ - assert( pPager->pTmpSpace!=0 ); - sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace); - } - return rc; - } - pPgHdr->flags |= PGHDR_NEED_SYNC; - sqlite3PcacheMakeDirty(pPgHdr); - sqlite3PagerUnrefNotNull(pPgHdr); - } - - return SQLITE_OK; -} -#endif - -/* -** The page handle passed as the first argument refers to a dirty page -** with a page number other than iNew. This function changes the page's -** page number to iNew and sets the value of the PgHdr.flags field to -** the value passed as the third parameter. -*/ -SQLITE_PRIVATE void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){ - assert( pPg->pgno!=iNew ); - pPg->flags = flags; - sqlite3PcacheMove(pPg, iNew); -} - -/* -** Return a pointer to the data for the specified page. -*/ -SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){ - assert( pPg->nRef>0 || pPg->pPager->memDb ); - return pPg->pData; -} - -/* -** Return a pointer to the Pager.nExtra bytes of "extra" space -** allocated along with the specified page. -*/ -SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ - return pPg->pExtra; -} - -/* -** Get/set the locking-mode for this pager. Parameter eMode must be one -** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or -** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then -** the locking-mode is set to the value specified. -** -** The returned value is either PAGER_LOCKINGMODE_NORMAL or -** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) -** locking-mode. -*/ -SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){ - assert( eMode==PAGER_LOCKINGMODE_QUERY - || eMode==PAGER_LOCKINGMODE_NORMAL - || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); - assert( PAGER_LOCKINGMODE_QUERY<0 ); - assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); - assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) ); - if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){ - pPager->exclusiveMode = (u8)eMode; - } - return (int)pPager->exclusiveMode; -} - -/* -** Set the journal-mode for this pager. Parameter eMode must be one of: -** -** PAGER_JOURNALMODE_DELETE -** PAGER_JOURNALMODE_TRUNCATE -** PAGER_JOURNALMODE_PERSIST -** PAGER_JOURNALMODE_OFF -** PAGER_JOURNALMODE_MEMORY -** PAGER_JOURNALMODE_WAL -** -** The journalmode is set to the value specified if the change is allowed. -** The change may be disallowed for the following reasons: -** -** * An in-memory database can only have its journal_mode set to _OFF -** or _MEMORY. -** -** * Temporary databases cannot have _WAL journalmode. -** -** The returned indicate the current (possibly updated) journal-mode. -*/ -SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ - u8 eOld = pPager->journalMode; /* Prior journalmode */ - - /* The eMode parameter is always valid */ - 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 - ** to WAL mode. - */ - assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL ); - - /* Do allow the journalmode of an in-memory database to be set to - ** anything other than MEMORY or OFF - */ - if( MEMDB ){ - assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF ); - if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){ - eMode = eOld; - } - } - - if( eMode!=eOld ){ - - /* Change the journal mode. */ - assert( pPager->eState!=PAGER_ERROR ); - pPager->journalMode = (u8)eMode; - - /* When transitioning from TRUNCATE or PERSIST to any other journal - ** mode except WAL, unless the pager is in locking_mode=exclusive mode, - ** delete the journal file. - */ - assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); - assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); - assert( (PAGER_JOURNALMODE_DELETE & 5)==0 ); - assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 ); - assert( (PAGER_JOURNALMODE_OFF & 5)==0 ); - assert( (PAGER_JOURNALMODE_WAL & 5)==5 ); - - 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. - ** - ** Before deleting the journal file, obtain a RESERVED lock on the - ** database file. This ensures that the journal file is not deleted - ** while it is in use by some other client. - */ - sqlite3OsClose(pPager->jfd); - if( pPager->eLock>=RESERVED_LOCK ){ - sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - }else{ - int rc = SQLITE_OK; - int state = pPager->eState; - assert( state==PAGER_OPEN || state==PAGER_READER ); - if( state==PAGER_OPEN ){ - rc = sqlite3PagerSharedLock(pPager); - } - if( pPager->eState==PAGER_READER ){ - assert( rc==SQLITE_OK ); - rc = pagerLockDb(pPager, RESERVED_LOCK); - } - if( rc==SQLITE_OK ){ - sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - } - if( rc==SQLITE_OK && state==PAGER_READER ){ - pagerUnlockDb(pPager, SHARED_LOCK); - }else if( state==PAGER_OPEN ){ - pager_unlock(pPager); - } - assert( state==pPager->eState ); - } - }else if( eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ){ - sqlite3OsClose(pPager->jfd); - } - } - - /* Return the new journal mode */ - return (int)pPager->journalMode; -} - -/* -** Return the current journal mode. -*/ -SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ - return (int)pPager->journalMode; -} - -/* -** Return TRUE if the pager is in a state where it is OK to change the -** journalmode. Journalmode changes can only happen when the database -** is unmodified. -*/ -SQLITE_PRIVATE int 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; - return 1; -} - -/* -** Get/set the size-limit used for persistent journal files. -** -** Setting the size limit to -1 means no limit is enforced. -** An attempt to set a limit smaller than -1 is a no-op. -*/ -SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ - if( iLimit>=-1 ){ - pPager->journalSizeLimit = iLimit; - sqlite3WalLimit(pPager->pWal, iLimit); - } - return pPager->journalSizeLimit; -} - -/* -** Return a pointer to the pPager->pBackup variable. The backup module -** in backup.c maintains the content of this variable. This module -** uses it opaquely as an argument to sqlite3BackupRestart() and -** sqlite3BackupUpdate() only. -*/ -SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){ - return &pPager->pBackup; -} - -#ifndef SQLITE_OMIT_VACUUM -/* -** Unless this is an in-memory or temporary database, clear the pager cache. -*/ -SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){ - assert( MEMDB==0 || pPager->tempFile ); - if( pPager->tempFile==0 ) pager_reset(pPager); -} -#endif - - -#ifndef SQLITE_OMIT_WAL -/* -** This function is called when the user invokes "PRAGMA wal_checkpoint", -** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() -** or wal_blocking_checkpoint() API functions. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. -*/ -SQLITE_PRIVATE int sqlite3PagerCheckpoint( - Pager *pPager, /* Checkpoint on this pager */ - sqlite3 *db, /* Db handle used to check for interrupts */ - int eMode, /* Type of checkpoint */ - int *pnLog, /* OUT: Final number of frames in log */ - 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 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 - ** sqlite3_wal_checkpoint() call, but it happens very rarely. - ** https://sqlite.org/forum/forumpost/fd0f19d229156939 - */ - sqlite3_exec(db, "PRAGMA table_list",0,0,0); - } - if( pPager->pWal ){ - rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, - (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), - pPager->pBusyHandlerArg, - pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, - pnLog, pnCkpt - ); - } - return rc; -} - -SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ - return sqlite3WalCallback(pPager->pWal); -} - -/* -** Return true if the underlying VFS for the given pager supports the -** primitives necessary for write-ahead logging. -*/ -SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ - const sqlite3_io_methods *pMethods = pPager->fd->pMethods; - if( pPager->noLock ) return 0; - return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); -} - -/* -** Attempt to take an exclusive lock on the database file. If a PENDING lock -** is obtained instead, immediately release it. -*/ -static int pagerExclusiveLock(Pager *pPager){ - int rc; /* Return code */ - u8 eOrigLock; /* Original lock */ - - assert( pPager->eLock>=SHARED_LOCK ); - eOrigLock = pPager->eLock; - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - /* If the attempt to grab the exclusive lock failed, release the - ** pending lock that may have been obtained instead. */ - pagerUnlockDb(pPager, eOrigLock); - } - - return rc; -} - -/* -** Call sqlite3WalOpen() to open the WAL handle. If the pager is in -** exclusive-locking mode when this function is called, take an EXCLUSIVE -** lock on the database file and use heap-memory to store the wal-index -** in. Otherwise, use the normal shared-memory. -*/ -static int pagerOpenWal(Pager *pPager){ - int rc = SQLITE_OK; - - assert( pPager->pWal==0 && pPager->tempFile==0 ); - assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); - - /* If the pager is already in exclusive-mode, the WAL module will use - ** heap-memory for the wal-index instead of the VFS shared-memory - ** implementation. Take the exclusive lock now, before opening the WAL - ** file, to make sure this is safe. - */ - if( pPager->exclusiveMode ){ - rc = pagerExclusiveLock(pPager); - } - - /* Open the connection to the log file. If this operation fails, - ** (e.g. due to malloc() failure), return an error code. - */ - if( rc==SQLITE_OK ){ - rc = sqlite3WalOpen(pPager->pVfs, - pPager->fd, pPager->zWal, pPager->exclusiveMode, - pPager->journalSizeLimit, &pPager->pWal - ); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_OK ){ - sqlite3WalDb(pPager->pWal, pPager->dbWal); - } -#endif - } - pagerFixMaplimit(pPager); - - return rc; -} - - -/* -** The caller must be holding a SHARED lock on the database file to call -** this function. -** -** If the pager passed as the first argument is open on a real database -** file (not a temp file or an in-memory database), and the WAL file -** is not already open, make an attempt to open it now. If successful, -** return SQLITE_OK. If an error occurs or the VFS used by the pager does -** not support the xShmXXX() methods, return an error code. *pbOpen is -** not modified in either case. -** -** If the pager is open on a temp-file (or in-memory database), or if -** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK -** without doing anything. -*/ -SQLITE_PRIVATE int sqlite3PagerOpenWal( - Pager *pPager, /* Pager object */ - int *pbOpen /* OUT: Set to true if call is a no-op */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( assert_pager_state(pPager) ); - assert( pPager->eState==PAGER_OPEN || pbOpen ); - assert( pPager->eState==PAGER_READER || !pbOpen ); - assert( pbOpen==0 || *pbOpen==0 ); - assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) ); - - if( !pPager->tempFile && !pPager->pWal ){ - if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; - - /* Close any rollback journal previously open */ - sqlite3OsClose(pPager->jfd); - - rc = pagerOpenWal(pPager); - if( rc==SQLITE_OK ){ - pPager->journalMode = PAGER_JOURNALMODE_WAL; - pPager->eState = PAGER_OPEN; - } - }else{ - *pbOpen = 1; - } - - return rc; -} - -/* -** This function is called to close the connection to the log file prior -** to switching from WAL to rollback mode. -** -** Before closing the log file, this function attempts to take an -** EXCLUSIVE lock on the database file. If this cannot be obtained, an -** error (SQLITE_BUSY) is returned and the log connection is not closed. -** If successful, the EXCLUSIVE lock is not released before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ - int rc = SQLITE_OK; - - assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); - - /* If the log file is not already open, but does exist in the file-system, - ** it may need to be checkpointed before the connection can switch to - ** rollback mode. Open it now so this can happen. - */ - if( !pPager->pWal ){ - int logexists = 0; - rc = pagerLockDb(pPager, SHARED_LOCK); - if( rc==SQLITE_OK ){ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists - ); - } - if( rc==SQLITE_OK && logexists ){ - rc = pagerOpenWal(pPager); - } - } - - /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on - ** the database file, the log and log-summary files will be deleted. - */ - if( rc==SQLITE_OK && pPager->pWal ){ - rc = pagerExclusiveLock(pPager); - if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, - pPager->pageSize, (u8*)pPager->pTmpSpace); - pPager->pWal = 0; - pagerFixMaplimit(pPager); - if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); - } - } - return rc; -} - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -/* -** If pager pPager is a wal-mode database not in exclusive locking mode, -** invoke the sqlite3WalWriteLock() function on the associated Wal object -** with the same db and bLock parameters as were passed to this function. -** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. -*/ -SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){ - int rc = SQLITE_OK; - if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){ - rc = sqlite3WalWriteLock(pPager->pWal, bLock); - } - return rc; -} - -/* -** Set the database handle used by the wal layer to determine if -** blocking locks are required. -*/ -SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ - pPager->dbWal = db; - if( pagerUseWal(pPager) ){ - sqlite3WalDb(pPager->pWal, db); - } -} -#endif - -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** If this is a WAL database, obtain a snapshot handle for the snapshot -** currently open. Otherwise, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ - int rc = SQLITE_ERROR; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot); - } - return rc; -} - -/* -** If this is a WAL database, store a pointer to pSnapshot. Next time a -** read transaction is opened, attempt to read from the snapshot it -** identifies. If this is not a WAL database, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen( - Pager *pPager, - sqlite3_snapshot *pSnapshot -){ - int rc = SQLITE_OK; - if( pPager->pWal ){ - sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); - }else{ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this -** is not a WAL database, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ - int rc; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotRecover(pPager->pWal); - }else{ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** The caller currently has a read transaction open on the database. -** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise, -** this function takes a SHARED lock on the CHECKPOINTER slot and then -** checks if the snapshot passed as the second argument is still -** available. If so, SQLITE_OK is returned. -** -** If the snapshot is not available, SQLITE_ERROR is returned. Or, if -** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error -** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER -** lock is released before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){ - int rc; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot); - }else{ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** Release a lock obtained by an earlier successful call to -** sqlite3PagerSnapshotCheck(). -*/ -SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ - assert( pPager->pWal ); - sqlite3WalSnapshotUnlock(pPager->pWal); -} - -#endif /* SQLITE_ENABLE_SNAPSHOT */ -#endif /* !SQLITE_OMIT_WAL */ - -#ifdef SQLITE_ENABLE_ZIPVFS -/* -** A read-lock must be held on the pager when this function is called. If -** the pager is in WAL mode and the WAL file currently contains one or more -** frames, return the size in bytes of the page images stored within the -** WAL frames. Otherwise, if this is not a WAL database or the WAL file -** is empty, return 0. -*/ -SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ - assert( pPager->eState>=PAGER_READER ); - return sqlite3WalFramesize(pPager->pWal); -} -#endif - -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) -SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ - return sqlite3WalSystemErrno(pPager->pWal); -} -#endif - -#endif /* SQLITE_OMIT_DISKIO */ - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - -SQLITE_API int sqlite3pager_is_sj_pgno(Pager *pPager, Pgno pgno) { - return (PAGER_SJ_PGNO(pPager) == pgno) ? 1 : 0; -} - -SQLITE_API void sqlite3pager_error(Pager *pPager, int error) { - pPager->errCode = error; - pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); -} - -SQLITE_API void sqlite3pager_reset(Pager *pPager){ - pager_reset(pPager); -} - -#endif -/* END SQLCIPHER */ - - -/************** End of pager.c ***********************************************/ -/************** Begin file wal.c *********************************************/ -/* -** 2010 February 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the implementation of a write-ahead log (WAL) used in -** "journal_mode=WAL" mode. -** -** WRITE-AHEAD LOG (WAL) FILE FORMAT -** -** A WAL file consists of a header followed by zero or more "frames". -** Each frame records the revised content of a single page from the -** database file. All changes to the database are recorded by writing -** frames into the WAL. Transactions commit when a frame is written that -** contains a commit marker. A single WAL can and usually does record -** multiple transactions. Periodically, the content of the WAL is -** transferred back into the database file in an operation called a -** "checkpoint". -** -** A single WAL file can be used multiple times. In other words, the -** WAL can fill up with frames and then be checkpointed and then new -** frames can overwrite the old ones. A WAL always grows from beginning -** toward the end. Checksums and counters attached to each frame are -** used to determine which frames within the WAL are valid and which -** are leftovers from prior checkpoints. -** -** The WAL header is 32 bytes in size and consists of the following eight -** big-endian 32-bit unsigned integer values: -** -** 0: Magic number. 0x377f0682 or 0x377f0683 -** 4: File format version. Currently 3007000 -** 8: Database page size. Example: 1024 -** 12: Checkpoint sequence number -** 16: Salt-1, random integer incremented with each checkpoint -** 20: Salt-2, a different random integer changing with each ckpt -** 24: Checksum-1 (first part of checksum for first 24 bytes of header). -** 28: Checksum-2 (second part of checksum for first 24 bytes of header). -** -** Immediately following the wal-header are zero or more frames. Each -** frame consists of a 24-byte frame-header followed by bytes -** of page data. The frame-header is six big-endian 32-bit unsigned -** integer values, as follows: -** -** 0: Page number. -** 4: For commit records, the size of the database image in pages -** after the commit. For all other records, zero. -** 8: Salt-1 (copied from the header) -** 12: Salt-2 (copied from the header) -** 16: Checksum-1. -** 20: Checksum-2. -** -** A frame is considered valid if and only if the following conditions are -** true: -** -** (1) The salt-1 and salt-2 values in the frame-header match -** salt values in the wal-header -** -** (2) The checksum values in the final 8 bytes of the frame-header -** exactly match the checksum computed consecutively on the -** WAL header and the first 8 bytes and the content of all frames -** up to and including the current frame. -** -** The checksum is computed using 32-bit big-endian integers if the -** magic number in the first 4 bytes of the WAL is 0x377f0683 and it -** is computed using little-endian if the magic number is 0x377f0682. -** The checksum values are always stored in the frame header in a -** big-endian format regardless of which byte order is used to compute -** the checksum. The checksum is computed by interpreting the input as -** an even number of unsigned 32-bit integers: x[0] through x[N]. The -** algorithm used for the checksum is as follows: -** -** for i from 0 to n-1 step 2: -** s0 += x[i] + s1; -** s1 += x[i+1] + s0; -** endfor -** -** Note that s0 and s1 are both weighted checksums using fibonacci weights -** in reverse order (the largest fibonacci weight occurs on the first element -** of the sequence being summed.) The s1 value spans all 32-bit -** terms of the sequence whereas s0 omits the final term. -** -** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the -** WAL is transferred into the database, then the database is VFS.xSync-ed. -** The VFS.xSync operations serve as write barriers - all writes launched -** before the xSync must complete before any write that launches after the -** xSync begins. -** -** After each checkpoint, the salt-1 value is incremented and the salt-2 -** value is randomized. This prevents old and new frames in the WAL from -** being considered valid at the same time and being checkpointing together -** following a crash. -** -** READER ALGORITHM -** -** To read a page from the database (call it page number P), a reader -** first checks the WAL to see if it contains page P. If so, then the -** last valid instance of page P that is a followed by a commit frame -** or is a commit frame itself becomes the value read. If the WAL -** contains no copies of page P that are valid and which are a commit -** frame or are followed by a commit frame, then page P is read from -** the database file. -** -** To start a read transaction, the reader records the index of the last -** valid frame in the WAL. The reader uses this recorded "mxFrame" value -** for all subsequent read operations. New transactions can be appended -** to the WAL, but as long as the reader uses its original mxFrame value -** and ignores the newly appended content, it will see a consistent snapshot -** of the database from a single point in time. This technique allows -** multiple concurrent readers to view different versions of the database -** content simultaneously. -** -** The reader algorithm in the previous paragraphs works correctly, but -** because frames for page P can appear anywhere within the WAL, the -** reader has to scan the entire WAL looking for page P frames. If the -** WAL is large (multiple megabytes is typical) that scan can be slow, -** and read performance suffers. To overcome this problem, a separate -** data structure called the wal-index is maintained to expedite the -** search for frames of a particular page. -** -** WAL-INDEX FORMAT -** -** Conceptually, the wal-index is shared memory, though VFS implementations -** might choose to implement the wal-index using a mmapped file. Because -** the wal-index is shared memory, SQLite does not support journal_mode=WAL -** on a network filesystem. All users of the database must be able to -** share memory. -** -** In the default unix and windows implementation, the wal-index is a mmapped -** file whose name is the database name with a "-shm" suffix added. For that -** reason, the wal-index is sometimes called the "shm" file. -** -** The wal-index is transient. After a crash, the wal-index can (and should -** be) reconstructed from the original WAL file. In fact, the VFS is required -** to either truncate or zero the header of the wal-index when the last -** connection to it closes. Because the wal-index is transient, it can -** use an architecture-specific format; it does not have to be cross-platform. -** Hence, unlike the database and WAL file formats which store all values -** as big endian, the wal-index can store multi-byte values in the native -** byte order of the host computer. -** -** The purpose of the wal-index is to answer this question quickly: Given -** a page number P and a maximum frame index M, return the index of the -** last frame in the wal before frame M for page P in the WAL, or return -** NULL if there are no frames for page P in the WAL prior to M. -** -** The wal-index consists of a header region, followed by an one or -** more index blocks. -** -** The wal-index header contains the total number of frames within the WAL -** in the mxFrame field. -** -** Each index block except for the first contains information on -** HASHTABLE_NPAGE frames. The first index block contains information on -** 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. 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 -** that allows readers to query an index block for a specific page number. -** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE -** for the first index block) 32-bit page numbers. The first entry in the -** first index-block contains the database page number corresponding to the -** first frame in the WAL file. The first entry in the second index block -** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in -** the log, and so on. -** -** The last index block in a wal-index usually contains less than the full -** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers, -** depending on the contents of the WAL file. This does not change the -** allocated size of the page-mapping array - the page-mapping array merely -** contains unused entries. -** -** Even without using the hash table, the last frame for page P -** can be found by scanning the page-mapping sections of each index block -** starting with the last index block and moving toward the first, and -** within each index block, starting at the end and moving toward the -** beginning. The first entry that equals P corresponds to the frame -** holding the content for that page. -** -** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers. -** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the -** hash table for each page number in the mapping section, so the hash -** table is never more than half full. The expected number of collisions -** prior to finding a match is 1. Each entry of the hash table is an -** 1-based index of an entry in the mapping section of the same -** index block. Let K be the 1-based index of the largest entry in -** the mapping section. (For index blocks other than the last, K will -** always be exactly HASHTABLE_NPAGE (4096) and for the last index block -** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table -** contain a value of 0. -** -** To look for page P in the hash table, first compute a hash iKey on -** P as follows: -** -** iKey = (P * 383) % HASHTABLE_NSLOT -** -** Then start scanning entries of the hash table, starting with iKey -** (wrapping around to the beginning when the end of the hash table is -** reached) until an unused hash slot is found. Let the first unused slot -** be at index iUnused. (iUnused might be less than iKey if there was -** wrap-around.) Because the hash table is never more than half full, -** the search is guaranteed to eventually hit an unused entry. Let -** iMax be the value between iKey and iUnused, closest to iUnused, -** where aHash[iMax]==P. If there is no iMax entry (if there exists -** no hash slot such that aHash[i]==p) then page P is not in the -** current index block. Otherwise the iMax-th mapping entry of the -** current index block corresponds to the last entry that references -** page P. -** -** A hash search begins with the last index block and moves toward the -** first index block, looking for entries corresponding to page P. On -** average, only two or three slots in each index block need to be -** examined in order to either find the last entry for page P, or to -** establish that no such entry exists in the block. Each index block -** holds over 4000 entries. So two or three index blocks are sufficient -** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10 -** comparisons (on average) suffice to either locate a frame in the -** WAL or to establish that the frame does not exist in the WAL. This -** is much faster than scanning the entire 10MB WAL. -** -** Note that entries are added in order of increasing K. Hence, one -** reader might be using some value K0 and a second reader that started -** at a later time (after additional transactions were added to the WAL -** and to the wal-index) might be using a different value K1, where K1>K0. -** Both readers can use the same hash table and mapping section to get -** the correct result. There may be entries in the hash table with -** K>K0 but to the first reader, those entries will appear to be unused -** slots in the hash table and so the first reader will get an answer as -** if no values greater than K0 had ever been inserted into the hash table -** in the first place - which is what reader one wants. Meanwhile, the -** second reader using K1 will see additional values that were inserted -** later, which is exactly what reader two wants. -** -** When a rollback occurs, the value of K is decreased. Hash table entries -** that correspond to frames greater than the new K value are removed -** from the hash table at this point. -*/ -#ifndef SQLITE_OMIT_WAL - -/* #include "wal.h" */ - -/* -** Trace output macros -*/ -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3WalTrace = 0; -# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X -#else -# define WALTRACE(X) -#endif - -/* -** The maximum (and only) versions of the wal and wal-index formats -** that may be interpreted by this version of SQLite. -** -** If a client begins recovering a WAL file and finds that (a) the checksum -** values in the wal-header are correct and (b) the version field is not -** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. -** -** Similarly, if a client successfully reads a wal-index header (i.e. the -** checksum test is successful) and finds that the version field is not -** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite -** returns SQLITE_CANTOPEN. -*/ -#define WAL_MAX_VERSION 3007000 -#define WALINDEX_MAX_VERSION 3007000 - -/* -** Index numbers for various locking bytes. WAL_NREADER is the number -** of available reader locks and should be at least 3. The default -** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5. -** -** Technically, the various VFSes are free to implement these locks however -** they see fit. However, compatibility is encouraged so that VFSes can -** interoperate. The standard implementation used on both unix and windows -** is for the index number to indicate a byte offset into the -** WalCkptInfo.aLock[] array in the wal-index header. In other words, all -** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which -** should be 120) is the location in the shm file for the first locking -** byte. -*/ -#define WAL_WRITE_LOCK 0 -#define WAL_ALL_BUT_WRITE 1 -#define WAL_CKPT_LOCK 1 -#define WAL_RECOVER_LOCK 2 -#define WAL_READ_LOCK(I) (3+(I)) -#define WAL_NREADER (SQLITE_SHM_NLOCK-3) - - -/* Object declarations */ -typedef struct WalIndexHdr WalIndexHdr; -typedef struct WalIterator WalIterator; -typedef struct WalCkptInfo WalCkptInfo; - - -/* -** The following object holds a copy of the wal-index header content. -** -** The actual header in the wal-index consists of two copies of this -** object followed by one instance of the WalCkptInfo object. -** For all versions of SQLite through 3.10.0 and probably beyond, -** the locking bytes (WalCkptInfo.aLock) start at offset 120 and -** the total header size is 136 bytes. -** -** The szPage value can be any power of 2 between 512 and 32768, inclusive. -** Or it can be 1 to represent a 65536-byte page. The latter case was -** added in 3.7.1 when support for 64K pages was added. -*/ -struct WalIndexHdr { - u32 iVersion; /* Wal-index version */ - u32 unused; /* Unused (padding) field */ - u32 iChange; /* Counter incremented each transaction */ - u8 isInit; /* 1 when initialized */ - u8 bigEndCksum; /* True if checksums in WAL are big-endian */ - u16 szPage; /* Database page size in bytes. 1==64K */ - u32 mxFrame; /* Index of last valid frame in the WAL */ - u32 nPage; /* Size of database in pages */ - u32 aFrameCksum[2]; /* Checksum of last frame in log */ - u32 aSalt[2]; /* Two salt values copied from WAL header */ - u32 aCksum[2]; /* Checksum over all prior fields */ -}; - -/* -** A copy of the following object occurs in the wal-index immediately -** following the second copy of the WalIndexHdr. This object stores -** information used by checkpoint. -** -** nBackfill is the number of frames in the WAL that have been written -** back into the database. (We call the act of moving content from WAL to -** database "backfilling".) The nBackfill number is never greater than -** WalIndexHdr.mxFrame. nBackfill can only be increased by threads -** holding the WAL_CKPT_LOCK lock (which includes a recovery thread). -** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from -** mxFrame back to zero when the WAL is reset. -** -** nBackfillAttempted is the largest value of nBackfill that a checkpoint -** has attempted to achieve. Normally nBackfill==nBackfillAtempted, however -** the nBackfillAttempted is set before any backfilling is done and the -** nBackfill is only set after all backfilling completes. So if a checkpoint -** crashes, nBackfillAttempted might be larger than nBackfill. The -** WalIndexHdr.mxFrame must never be less than nBackfillAttempted. -** -** The aLock[] field is a set of bytes used for locking. These bytes should -** never be read or written. -** -** There is one entry in aReadMark[] for each reader lock. If a reader -** holds read-lock K, then the value in aReadMark[K] is no greater than -** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) -** for any aReadMark[] means that entry is unused. aReadMark[0] is -** a special case; its value is never used and it exists as a place-holder -** to avoid having to offset aReadMark[] indexes by one. Readers holding -** WAL_READ_LOCK(0) always ignore the entire WAL and read all content -** directly from the database. -** -** The value of aReadMark[K] may only be changed by a thread that -** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of -** aReadMark[K] cannot changed while there is a reader is using that mark -** since the reader will be holding a shared lock on WAL_READ_LOCK(K). -** -** The checkpointer may only transfer frames from WAL to database where -** the frame numbers are less than or equal to every aReadMark[] that is -** in use (that is, every aReadMark[j] for which there is a corresponding -** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the -** largest value and will increase an unused aReadMark[] to mxFrame if there -** is not already an aReadMark[] equal to mxFrame. The exception to the -** previous sentence is when nBackfill equals mxFrame (meaning that everything -** in the WAL has been backfilled into the database) then new readers -** will choose aReadMark[0] which has value 0 and hence such reader will -** get all their all content directly from the database file and ignore -** the WAL. -** -** Writers normally append new frames to the end of the WAL. However, -** if nBackfill equals mxFrame (meaning that all WAL content has been -** written back into the database) and if no readers are using the WAL -** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then -** the writer will first "reset" the WAL back to the beginning and start -** writing new content beginning at frame 1. -** -** We assume that 32-bit loads are atomic and so no locks are needed in -** order to read from any aReadMark[] entries. -*/ -struct WalCkptInfo { - u32 nBackfill; /* Number of WAL frames backfilled into DB */ - u32 aReadMark[WAL_NREADER]; /* Reader marks */ - u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */ - u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */ - u32 notUsed0; /* Available for future enhancements */ -}; -#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 -** only support mandatory file-locks, we do not read or write data -** from the region of the file on which locks are applied. -*/ -#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock)) -#define WALINDEX_HDR_SIZE (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo)) - -/* Size of header before each frame in wal */ -#define WAL_FRAME_HDRSIZE 24 - -/* Size of write ahead log header, including checksum. */ -#define WAL_HDRSIZE 32 - -/* WAL magic value. Either this value, or the same value with the least -** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit -** big-endian format in the first 4 bytes of a WAL file. -** -** If the LSB is set, then the checksums for each frame within the WAL -** file are calculated by treating all data as an array of 32-bit -** big-endian words. Otherwise, they are calculated by interpreting -** all data as 32-bit little-endian words. -*/ -#define WAL_MAGIC 0x377f0682 - -/* -** Return the offset of frame iFrame in the write-ahead log file, -** assuming a database page size of szPage bytes. The offset returned -** is to the start of the write-ahead log frame-header. -*/ -#define walFrameOffset(iFrame, szPage) ( \ - WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \ -) - -/* -** An open write-ahead log file is represented by an instance of the -** following object. -** -** writeLock: -** This is usually set to 1 whenever the WRITER lock is held. However, -** if it is set to 2, then the WRITER lock is held but must be released -** by walHandleException() if a SEH exception is thrown. -*/ -struct Wal { - sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ - sqlite3_file *pDbFd; /* File handle for the database file */ - sqlite3_file *pWalFd; /* File handle for WAL file */ - u32 iCallback; /* Value to pass to log callback (or 0) */ - i64 mxWalSize; /* Truncate WAL to this size upon reset */ - int nWiData; /* Size of array apWiData */ - int szFirstBlock; /* Size of first block written to WAL file */ - volatile u32 **apWiData; /* Pointer to wal-index content in memory */ - u32 szPage; /* Database page size */ - i16 readLock; /* Which read lock is being held. -1 for none */ - u8 syncFlags; /* Flags to use to sync header writes */ - u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */ - u8 writeLock; /* True if in a write transaction */ - u8 ckptLock; /* True if holding a checkpoint lock */ - u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */ - u8 truncateOnCommit; /* True to truncate WAL file on commit */ - u8 syncHeader; /* Fsync the WAL header if true */ - u8 padToSectorBoundary; /* Pad transactions out to the next sector */ - u8 bShmUnreliable; /* SHM content is read-only and unreliable */ - WalIndexHdr hdr; /* Wal-index header for current transaction */ - u32 minFrame; /* Ignore wal frames before this one */ - u32 iReCksum; /* On commit, recalculate checksums from here */ - const char *zWalName; /* Name of WAL file */ - u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -#ifdef SQLITE_USE_SEH - u32 lockMask; /* Mask of locks held */ - void *pFree; /* Pointer to sqlite3_free() if exception thrown */ - u32 *pWiValue; /* Value to write into apWiData[iWiPg] */ - int iWiPg; /* Write pWiValue into apWiData[iWiPg] */ - int iSysErrno; /* System error code following exception */ -#endif -#ifdef SQLITE_DEBUG - int nSehTry; /* Number of nested SEH_TRY{} blocks */ - u8 lockError; /* True if a locking error has occurred */ -#endif -#ifdef SQLITE_ENABLE_SNAPSHOT - WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ - int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */ -#endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3 *db; -#endif -}; - -/* -** Candidate values for Wal.exclusiveMode. -*/ -#define WAL_NORMAL_MODE 0 -#define WAL_EXCLUSIVE_MODE 1 -#define WAL_HEAPMEMORY_MODE 2 - -/* -** Possible values for WAL.readOnly -*/ -#define WAL_RDWR 0 /* Normal read/write connection */ -#define WAL_RDONLY 1 /* The WAL file is readonly */ -#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */ - -/* -** Each page of the wal-index mapping contains a hash-table made up of -** an array of HASHTABLE_NSLOT elements of the following type. -*/ -typedef u16 ht_slot; - -/* -** This structure is used to implement an iterator that loops through -** all frames in the WAL in database page order. Where two or more frames -** correspond to the same database page, the iterator visits only the -** frame most recently written to the WAL (in other words, the frame with -** the largest index). -** -** The internals of this structure are only accessed by: -** -** walIteratorInit() - Create a new iterator, -** walIteratorNext() - Step an iterator, -** walIteratorFree() - Free an iterator. -** -** This functionality is used by the checkpoint code (see walCheckpoint()). -*/ -struct WalIterator { - u32 iPrior; /* Last result returned from the iterator */ - int nSegment; /* Number of entries in aSegment[] */ - struct WalSegment { - int iNext; /* Next slot in aIndex[] not yet returned */ - ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ - u32 *aPgno; /* Array of page numbers. */ - int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */ - int iZero; /* Frame number associated with aPgno[0] */ - } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */ -}; - -/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ -#define SZ_WALITERATOR(N) \ - (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment)) - -/* -** Define the parameters of the hash tables in the wal-index file. There -** is a hash-table following every HASHTABLE_NPAGE page numbers in the -** wal-index. -** -** Changing any of these constants will alter the wal-index format and -** create incompatibilities. -*/ -#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */ -#define HASHTABLE_HASH_1 383 /* Should be prime */ -#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */ - -/* -** The block of page numbers associated with the first hash-table in a -** wal-index is smaller than usual. This is so that there is a complete -** hash-table on each aligned 32KB page of the wal-index. -*/ -#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32))) - -/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ -#define WALINDEX_PGSZ ( \ - sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ -) - -/* -** Structured Exception Handling (SEH) is a Windows-specific technique -** for catching exceptions raised while accessing memory-mapped files. -** -** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and -** deal with system-level errors that arise during WAL -shm file processing. -** Without this compile-time option, any system-level faults that appear -** while accessing the memory-mapped -shm file will cause a process-wide -** signal to be deliver, which will more than likely cause the entire -** process to exit. -*/ -#ifdef SQLITE_USE_SEH -#include - -/* Beginning of a block of code in which an exception might occur */ -# define SEH_TRY __try { \ - assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ - VVA_ONLY(pWal->nSehTry++); - -/* The end of a block of code in which an exception might occur */ -# define SEH_EXCEPT(X) \ - VVA_ONLY(pWal->nSehTry--); \ - assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } - -/* Simulate a memory-mapping fault in the -shm file for testing purposes */ -# define SEH_INJECT_FAULT sehInjectFault(pWal) - -/* -** The second argument is the return value of GetExceptionCode() for the -** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code -** indicates that the exception may have been caused by accessing the *-shm -** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. -*/ -static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ - VVA_ONLY(pWal->nSehTry--); - if( eCode==EXCEPTION_IN_PAGE_ERROR ){ - if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ - /* From MSDN: For this type of exception, the first element of the - ** ExceptionInformation[] array is a read-write flag - 0 if the exception - ** was thrown while reading, 1 if while writing. The second element is - ** the virtual address being accessed. The "third array element specifies - ** the underlying NTSTATUS code that resulted in the exception". */ - pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; - } - return EXCEPTION_EXECUTE_HANDLER; - } - return EXCEPTION_CONTINUE_SEARCH; -} - -/* -** If one is configured, invoke the xTestCallback callback with 650 as -** the argument. If it returns true, throw the same exception that is -** thrown by the system if the *-shm file mapping is accessed after it -** has been invalidated. -*/ -static void sehInjectFault(Wal *pWal){ - int res; - assert( pWal->nSehTry>0 ); - - res = sqlite3FaultSim(650); - if( res!=0 ){ - ULONG_PTR aArg[3]; - aArg[0] = 0; - aArg[1] = 0; - aArg[2] = (ULONG_PTR)res; - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); - } -} - -/* -** There are two ways to use this macro. To set a pointer to be freed -** if an exception is thrown: -** -** SEH_FREE_ON_ERROR(0, pPtr); -** -** and to cancel the same: -** -** SEH_FREE_ON_ERROR(pPtr, 0); -** -** In the first case, there must not already be a pointer registered to -** be freed. In the second case, pPtr must be the registered pointer. -*/ -#define SEH_FREE_ON_ERROR(X,Y) \ - assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y - -/* -** There are two ways to use this macro. To arrange for pWal->apWiData[iPg] -** to be set to pValue if an exception is thrown: -** -** SEH_SET_ON_ERROR(iPg, pValue); -** -** and to cancel the same: -** -** SEH_SET_ON_ERROR(0, 0); -*/ -#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y - -#else -# define SEH_TRY VVA_ONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); -# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); -# define SEH_FREE_ON_ERROR(X,Y) -# define SEH_SET_ON_ERROR(X,Y) -#endif /* ifdef SQLITE_USE_SEH */ - - -/* -** Obtain a pointer to the iPage'th page of the wal-index. The wal-index -** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are -** numbered from zero. -** -** If the wal-index is currently smaller the iPage pages then the size -** of the wal-index might be increased, but only if it is safe to do -** so. It is safe to enlarge the wal-index if pWal->writeLock is true -** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE. -** -** 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 */ - int iPage, /* The page we seek */ - volatile u32 **ppPage /* Write the page pointer here */ -){ - int rc = SQLITE_OK; - - /* Enlarge the pWal->apWiData[] array if required */ - if( pWal->nWiData<=iPage ){ - sqlite3_int64 nByte = sizeof(u32*)*(1+(i64)iPage); - volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte); - if( !apNew ){ - *ppPage = 0; - return SQLITE_NOMEM_BKPT; - } - memset((void*)&apNew[pWal->nWiData], 0, - sizeof(u32*)*(iPage+1-pWal->nWiData)); - pWal->apWiData = apNew; - pWal->nWiData = iPage+1; - } - - /* Request a pointer to the required page from the VFS */ - assert( pWal->apWiData[iPage]==0 ); - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, - pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] - ); - 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 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM; - }else if( (rc&0xff)==SQLITE_READONLY ){ - pWal->readOnly |= WAL_SHM_RDONLY; - if( rc==SQLITE_READONLY ){ - rc = SQLITE_OK; - } - } - } - - *ppPage = pWal->apWiData[iPage]; - assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); - return rc; -} -static int walIndexPage( - Wal *pWal, /* The WAL context */ - int iPage, /* The page we seek */ - volatile u32 **ppPage /* Write the page pointer here */ -){ - SEH_INJECT_FAULT; - if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ - return walIndexPageRealloc(pWal, iPage, ppPage); - } - return SQLITE_OK; -} - -/* -** Return a pointer to the WalCkptInfo structure in the wal-index. -*/ -static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - SEH_INJECT_FAULT; - return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); -} - -/* -** Return a pointer to the WalIndexHdr structure in the wal-index. -*/ -static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - SEH_INJECT_FAULT; - return (volatile WalIndexHdr*)pWal->apWiData[0]; -} - -/* -** The argument to this macro must be of type u32. On a little-endian -** architecture, it returns the u32 value that results from interpreting -** the 4 bytes as a big-endian value. On a big-endian architecture, it -** returns the value that would be produced by interpreting the 4 bytes -** of the input value as a little-endian integer. -*/ -#define BYTESWAP32(x) ( \ - (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \ - + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \ -) - -/* -** Generate or extend an 8 byte checksum based on the data in -** array aByte[] and the initial values of aIn[0] and aIn[1] (or -** initial values of 0 and 0 if aIn==NULL). -** -** The checksum is written back into aOut[] before returning. -** -** nByte must be a positive multiple of 8. -*/ -static void walChecksumBytes( - int nativeCksum, /* True for native byte-order, false for non-native */ - u8 *a, /* Content to be checksummed */ - int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */ - const u32 *aIn, /* Initial checksum value input */ - u32 *aOut /* OUT: Final checksum value output */ -){ - u32 s1, s2; - u32 *aData = (u32 *)a; - u32 *aEnd = (u32 *)&a[nByte]; - - if( aIn ){ - s1 = aIn[0]; - s2 = aIn[1]; - }else{ - s1 = s2 = 0; - } - - /* nByte is a multiple of 8 between 8 and 65536 */ - assert( nByte>=8 && (nByte&7)==0 && nByte<=65536 ); - - if( !nativeCksum ){ - do { - s1 += BYTESWAP32(aData[0]) + s2; - s2 += BYTESWAP32(aData[1]) + s1; - aData += 2; - }while( aDataexclusiveMode!=WAL_HEAPMEMORY_MODE ){ - sqlite3OsShmBarrier(pWal->pDbFd); - } -} - -/* -** Add the SQLITE_NO_TSAN as part of the return-type of a function -** definition as a hint that the function contains constructs that -** might give false-positive TSAN warnings. -** -** See tag-20200519-1. -*/ -#if defined(__clang__) && !defined(SQLITE_NO_TSAN) -# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread)) -#else -# define SQLITE_NO_TSAN -#endif - -/* -** Write the header information in pWal->hdr into the wal-index. -** -** The checksum on pWal->hdr is updated before it is written. -*/ -static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){ - volatile WalIndexHdr *aHdr = walIndexHdr(pWal); - const int nCksum = offsetof(WalIndexHdr, aCksum); - - assert( pWal->writeLock ); - pWal->hdr.isInit = 1; - pWal->hdr.iVersion = WALINDEX_MAX_VERSION; - walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); - /* Possible TSAN false-positive. See tag-20200519-1 */ - memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); - walShmBarrier(pWal); - memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); -} - -/* -** This function encodes a single frame header and writes it to a buffer -** supplied by the caller. A frame-header is made up of a series of -** 4-byte big-endian integers, as follows: -** -** 0: Page number. -** 4: For commit records, the size of the database image in pages -** after the commit. For all other records, zero. -** 8: Salt-1 (copied from the wal-header) -** 12: Salt-2 (copied from the wal-header) -** 16: Checksum-1. -** 20: Checksum-2. -*/ -static void walEncodeFrame( - Wal *pWal, /* The write-ahead log */ - u32 iPage, /* Database page number for frame */ - u32 nTruncate, /* New db size (or 0 for non-commit frames) */ - u8 *aData, /* Pointer to page data */ - u8 *aFrame /* OUT: Write encoded frame here */ -){ - int nativeCksum; /* True for native byte-order checksums */ - u32 *aCksum = pWal->hdr.aFrameCksum; - assert( WAL_FRAME_HDRSIZE==24 ); - sqlite3Put4byte(&aFrame[0], iPage); - sqlite3Put4byte(&aFrame[4], nTruncate); - if( pWal->iReCksum==0 ){ - memcpy(&aFrame[8], pWal->hdr.aSalt, 8); - - nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); - walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); - walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - - sqlite3Put4byte(&aFrame[16], aCksum[0]); - sqlite3Put4byte(&aFrame[20], aCksum[1]); - }else{ - memset(&aFrame[8], 0, 16); - } -} - -/* -** Check to see if the frame with header in aFrame[] and content -** in aData[] is valid. If it is a valid frame, fill *piPage and -** *pnTruncate and return true. Return if the frame is not valid. -*/ -static int walDecodeFrame( - Wal *pWal, /* The write-ahead log */ - u32 *piPage, /* OUT: Database page number for frame */ - u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */ - u8 *aData, /* Pointer to page data (for checksum) */ - u8 *aFrame /* Frame data */ -){ - int nativeCksum; /* True for native byte-order checksums */ - u32 *aCksum = pWal->hdr.aFrameCksum; - u32 pgno; /* Page number of the frame */ - assert( WAL_FRAME_HDRSIZE==24 ); - - /* A frame is only valid if the salt values in the frame-header - ** match the salt values in the wal-header. - */ - if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){ - return 0; - } - - /* A frame is only valid if the page number is greater than zero. - */ - pgno = sqlite3Get4byte(&aFrame[0]); - if( pgno==0 ){ - return 0; - } - - /* A frame is only valid if a checksum of the WAL header, - ** all prior frames, the first 16 bytes of this frame-header, - ** and the frame-data matches the checksum in the last 8 - ** bytes of this frame-header. - */ - nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); - walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); - walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) - || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) - ){ - /* Checksum failed. */ - return 0; - } - - /* If we reach this point, the frame is valid. Return the page number - ** and the new database size. - */ - *piPage = pgno; - *pnTruncate = sqlite3Get4byte(&aFrame[4]); - return 1; -} - - -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -/* -** Names of locks. This routine is used to provide debugging output and is not -** a part of an ordinary build. -*/ -static const char *walLockName(int lockIdx){ - if( lockIdx==WAL_WRITE_LOCK ){ - return "WRITE-LOCK"; - }else if( lockIdx==WAL_CKPT_LOCK ){ - return "CKPT-LOCK"; - }else if( lockIdx==WAL_RECOVER_LOCK ){ - return "RECOVER-LOCK"; - }else{ - static char zName[15]; - sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]", - lockIdx-WAL_READ_LOCK(0)); - return zName; - } -} -#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ - - -/* -** Set or release locks on the WAL. Locks are either shared or exclusive. -** A lock cannot be moved directly between shared and exclusive - it must go -** through the unlocked state first. -** -** In locking_mode=EXCLUSIVE, all of these routines become no-ops. -*/ -static int walLockShared(Wal *pWal, int lockIdx){ - int rc; - if( pWal->exclusiveMode ) return SQLITE_OK; - rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, - SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); - WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, - walLockName(lockIdx), rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) -#ifdef SQLITE_USE_SEH - if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); -#endif - return rc; -} -static void walUnlockShared(Wal *pWal, int lockIdx){ - if( pWal->exclusiveMode ) return; - (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, - SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); -#ifdef SQLITE_USE_SEH - pWal->lockMask &= ~(1 << lockIdx); -#endif - WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); -} -static int walLockExclusive(Wal *pWal, int lockIdx, int n){ - int rc; - if( pWal->exclusiveMode ) return SQLITE_OK; - rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, - SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); - WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, - walLockName(lockIdx), n, rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) -#ifdef SQLITE_USE_SEH - if( rc==SQLITE_OK ){ - pWal->lockMask |= (((1<exclusiveMode ) return; - (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, - SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); -#ifdef SQLITE_USE_SEH - pWal->lockMask &= ~(((1<0 ); - assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 ); - return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1); -} -static int walNextHash(int iPriorHash){ - return (iPriorHash+1)&(HASHTABLE_NSLOT-1); -} - -/* -** An instance of the WalHashLoc object is used to describe the location -** of a page hash table in the wal-index. This becomes the return value -** from walHashGet(). -*/ -typedef struct WalHashLoc WalHashLoc; -struct WalHashLoc { - volatile ht_slot *aHash; /* Start of the wal-index hash table */ - volatile u32 *aPgno; /* aPgno[1] is the page of first frame indexed */ - u32 iZero; /* One less than the frame number of first indexed*/ -}; - -/* -** Return pointers to the hash table and page number array stored on -** page iHash of the wal-index. The wal-index is broken into 32KB pages -** numbered starting from 0. -** -** Set output variable pLoc->aHash to point to the start of the hash table -** in the wal-index file. Set pLoc->iZero to one less than the frame -** number of the first frame indexed by this hash table. If a -** 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[0] is the page number of the -** first frame indexed by the hash table, frame (pLoc->iZero). -*/ -static int walHashGet( - Wal *pWal, /* WAL handle */ - int iHash, /* Find the iHash'th table */ - WalHashLoc *pLoc /* OUT: Hash table location */ -){ - int rc; /* Return code */ - - rc = walIndexPage(pWal, iHash, &pLoc->aPgno); - assert( rc==SQLITE_OK || iHash>0 ); - - if( pLoc->aPgno ){ - pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE]; - if( iHash==0 ){ - pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; - pLoc->iZero = 0; - }else{ - pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; - } - }else if( NEVER(rc==SQLITE_OK) ){ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** Return the number of the wal-index page that contains the hash-table -** and page-number array that contain entries corresponding to WAL frame -** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages -** are numbered starting from 0. -*/ -static int walFramePage(u32 iFrame){ - int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE; - assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE) - && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE) - && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)) - && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE) - && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE)) - ); - assert( iHash>=0 ); - return iHash; -} - -/* -** Return the page number associated with frame iFrame in this WAL. -*/ -static u32 walFramePgno(Wal *pWal, u32 iFrame){ - int iHash = walFramePage(iFrame); - SEH_INJECT_FAULT; - if( iHash==0 ){ - return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; - } - return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; -} - -/* -** Remove entries from the hash table that point to WAL slots greater -** than pWal->hdr.mxFrame. -** -** This function is called whenever pWal->hdr.mxFrame is decreased due -** to a rollback or savepoint. -** -** At most only the hash table containing pWal->hdr.mxFrame needs to be -** updated. Any later hash tables will be automatically cleared when -** pWal->hdr.mxFrame advances to the point where those hash tables are -** actually needed. -*/ -static void walCleanupHash(Wal *pWal){ - WalHashLoc sLoc; /* Hash table location */ - int iLimit = 0; /* Zero values greater than this */ - int nByte; /* Number of bytes to zero in aPgno[] */ - int i; /* Used to iterate through aHash[] */ - - assert( pWal->writeLock ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 ); - - if( pWal->hdr.mxFrame==0 ) return; - - /* Obtain pointers to the hash-table and page-number array containing - ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed - ** that the page said hash-table and array reside on is already mapped.(1) - */ - assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); - assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); - 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. - */ - iLimit = pWal->hdr.mxFrame - sLoc.iZero; - assert( iLimit>0 ); - for(i=0; iiLimit ){ - sLoc.aHash[i] = 0; - } - } - - /* 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]); - 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 - ** via the hash table even after the cleanup. - */ - if( iLimit ){ - int j; /* Loop counter */ - int iKey; /* Hash key */ - for(j=0; j=0 ); - memset((void*)sLoc.aPgno, 0, nByte); - } - - /* If the entry in aPgno[] is already set, then the previous writer - ** must have exited unexpectedly in the middle of a transaction (after - ** writing one or more dirty pages to the WAL to free up memory). - ** Remove the remnants of that writers uncommitted transaction from - ** the hash-table before writing any new entries. - */ - if( sLoc.aPgno[idx-1] ){ - walCleanupHash(pWal); - assert( !sLoc.aPgno[idx-1] ); - } - - /* Write the aPgno[] array entry and the hash-table slot. */ - nCollide = idx; - for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ - if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; - } - sLoc.aPgno[idx-1] = iPage; - AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx); - -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - /* Verify that the number of entries in the hash table exactly equals - ** the number of entries in the mapping region. - */ - { - int i; /* Loop counter */ - int nEntry = 0; /* Number of entries in the hash table */ - for(i=0; ickptLock==1 || pWal->ckptLock==0 ); - assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 ); - assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); - assert( pWal->writeLock ); - iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; - rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); - if( rc ){ - return rc; - } - - WALTRACE(("WAL%p: recovery begin...\n", pWal)); - - memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); - - rc = sqlite3OsFileSize(pWal->pWalFd, &nSize); - if( rc!=SQLITE_OK ){ - goto recovery_error; - } - - if( nSize>WAL_HDRSIZE ){ - u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ - u32 *aPrivate = 0; /* Heap copy of *-shm hash being populated */ - u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ - int szFrame; /* Number of bytes in buffer aFrame[] */ - u8 *aData; /* Pointer to data part of aFrame buffer */ - int szPage; /* Page size according to the log */ - u32 magic; /* Magic value read from WAL header */ - u32 version; /* Magic value read from WAL header */ - int isValid; /* True if this frame is valid */ - u32 iPg; /* Current 32KB wal-index page */ - u32 iLastFrame; /* Last frame in wal, based on nSize alone */ - - /* Read in the WAL header. */ - rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); - if( rc!=SQLITE_OK ){ - goto recovery_error; - } - - /* If the database page size is not a power of two, or is greater than - ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid - ** data. Similarly, if the 'magic' value is invalid, ignore the whole - ** WAL file. - */ - magic = sqlite3Get4byte(&aBuf[0]); - szPage = sqlite3Get4byte(&aBuf[8]); - if( (magic&0xFFFFFFFE)!=WAL_MAGIC - || szPage&(szPage-1) - || szPage>SQLITE_MAX_PAGE_SIZE - || szPage<512 - ){ - goto finished; - } - pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); - pWal->szPage = szPage; - pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); - memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); - - /* Verify that the WAL header checksum is correct */ - walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, - aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum - ); - if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24]) - || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28]) - ){ - goto finished; - } - - /* Verify that the version number on the WAL format is one that - ** are able to understand */ - version = sqlite3Get4byte(&aBuf[4]); - if( version!=WAL_MAX_VERSION ){ - rc = SQLITE_CANTOPEN_BKPT; - goto finished; - } - - /* Malloc a buffer to read frames into. */ - szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); - SEH_FREE_ON_ERROR(0, aFrame); - if( !aFrame ){ - rc = SQLITE_NOMEM_BKPT; - goto recovery_error; - } - aData = &aFrame[WAL_FRAME_HDRSIZE]; - aPrivate = (u32*)&aData[szPage]; - - /* Read all frames from the log file. */ - iLastFrame = (nSize - WAL_HDRSIZE) / szFrame; - for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){ - u32 *aShare; - u32 iFrame; /* Index of last frame read */ - u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE); - u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE); - u32 nHdr, nHdr32; - rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare); - assert( aShare!=0 || rc!=SQLITE_OK ); - if( aShare==0 ) break; - SEH_SET_ON_ERROR(iPg, aShare); - pWal->apWiData[iPg] = aPrivate; - - for(iFrame=iFirst; iFrame<=iLast; iFrame++){ - i64 iOffset = walFrameOffset(iFrame, szPage); - u32 pgno; /* Database page number for frame */ - u32 nTruncate; /* dbsize field from frame header */ - - /* Read and decode the next log frame. */ - rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); - if( rc!=SQLITE_OK ) break; - isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame); - if( !isValid ) break; - rc = walIndexAppend(pWal, iFrame, pgno); - if( NEVER(rc!=SQLITE_OK) ) break; - - /* If nTruncate is non-zero, this is a commit record. */ - if( nTruncate ){ - pWal->hdr.mxFrame = iFrame; - pWal->hdr.nPage = nTruncate; - pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; - aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; - } - } - pWal->apWiData[iPg] = aShare; - SEH_SET_ON_ERROR(0,0); - nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0); - nHdr32 = nHdr / sizeof(u32); -#ifndef SQLITE_SAFER_WALINDEX_RECOVERY - /* Memcpy() should work fine here, on all reasonable implementations. - ** Technically, memcpy() might change the destination to some - ** intermediate value before setting to the final value, and that might - ** cause a concurrent reader to malfunction. Memcpy() is allowed to - ** do that, according to the spec, but no memcpy() implementation that - ** we know of actually does that, which is why we say that memcpy() - ** is safe for this. Memcpy() is certainly a lot faster. - */ - memcpy(&aShare[nHdr32], &aPrivate[nHdr32], WALINDEX_PGSZ-nHdr); -#else - /* In the event that some platform is found for which memcpy() - ** changes the destination to some intermediate value before - ** setting the final value, this alternative copy routine is - ** provided. - */ - { - int i; - for(i=nHdr32; ihdr.aFrameCksum[0] = aFrameCksum[0]; - pWal->hdr.aFrameCksum[1] = aFrameCksum[1]; - walIndexWriteHdr(pWal); - - /* Reset the checkpoint-header. This is safe because this thread is - ** currently holding locks that exclude all other writers and - ** checkpointers. Then set the values of read-mark slots 1 through N. - */ - pInfo = walCkptInfo(pWal); - pInfo->nBackfill = 0; - pInfo->nBackfillAttempted = pWal->hdr.mxFrame; - pInfo->aReadMark[0] = 0; - for(i=1; ihdr.mxFrame ){ - pInfo->aReadMark[i] = pWal->hdr.mxFrame; - }else{ - pInfo->aReadMark[i] = READMARK_NOT_USED; - } - SEH_INJECT_FAULT; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc!=SQLITE_BUSY ){ - goto recovery_error; - } - } - - /* If more than one frame was recovered from the log file, report an - ** event via sqlite3_log(). This is to help with identifying performance - ** problems caused by applications routinely shutting down without - ** checkpointing the log file. - */ - if( pWal->hdr.nPage ){ - sqlite3_log(SQLITE_NOTICE_RECOVER_WAL, - "recovered %d frames from WAL file %s", - pWal->hdr.mxFrame, pWal->zWalName - ); - } - } - -recovery_error: - WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); - walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); - return rc; -} - -/* -** Close an open wal-index. -*/ -static void walIndexClose(Wal *pWal, int isDelete){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){ - int i; - for(i=0; inWiData; i++){ - sqlite3_free((void *)pWal->apWiData[i]); - pWal->apWiData[i] = 0; - } - } - if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){ - sqlite3OsShmUnmap(pWal->pDbFd, isDelete); - } -} - -/* -** Open a connection to the WAL file zWalName. The database file must -** already be opened on connection pDbFd. The buffer that zWalName points -** to must remain valid for the lifetime of the returned Wal* handle. -** -** A SHARED lock should be held on the database file when this function -** is called. The purpose of this SHARED lock is to prevent any other -** client from unlinking the WAL or wal-index file. If another process -** were to do this just after this client opened one of these files, the -** system would be badly broken. -** -** If the log file is successfully opened, SQLITE_OK is returned and -** *ppWal is set to point to a new WAL handle. If an error occurs, -** an SQLite error code is returned and *ppWal is left unmodified. -*/ -SQLITE_PRIVATE int sqlite3WalOpen( - sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ - sqlite3_file *pDbFd, /* The open database file */ - const char *zWalName, /* Name of the WAL file */ - int bNoShm, /* True to run in heap-memory mode */ - i64 mxWalSize, /* Truncate WAL to this size on reset */ - Wal **ppWal /* OUT: Allocated Wal handle */ -){ - int rc; /* Return Code */ - Wal *pRet; /* Object to allocate and return */ - int flags; /* Flags passed to OsOpen() */ - - 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. - */ -#ifdef WIN_SHM_BASE - assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif -#ifdef UNIX_SHM_BASE - assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif - - - /* Allocate an instance of struct Wal to return. */ - *ppWal = 0; - pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); - if( !pRet ){ - return SQLITE_NOMEM_BKPT; - } - - pRet->pVfs = pVfs; - pRet->pWalFd = (sqlite3_file *)&pRet[1]; - pRet->pDbFd = pDbFd; - pRet->readLock = -1; - pRet->mxWalSize = mxWalSize; - pRet->zWalName = zWalName; - pRet->syncHeader = 1; - pRet->padToSectorBoundary = 1; - pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); - - /* Open file handle on the write-ahead log file. */ - flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); - rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags); - if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){ - pRet->readOnly = WAL_RDONLY; - } - - if( rc!=SQLITE_OK ){ - walIndexClose(pRet, 0); - sqlite3OsClose(pRet->pWalFd); - sqlite3_free(pRet); - }else{ - int iDC = sqlite3OsDeviceCharacteristics(pDbFd); - if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } - if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ - pRet->padToSectorBoundary = 0; - } - *ppWal = pRet; - WALTRACE(("WAL%d: opened\n", pRet)); - } - return rc; -} - -/* -** Change the size to which the WAL file is truncated on each reset. -*/ -SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){ - if( pWal ) pWal->mxWalSize = iLimit; -} - -/* -** Find the smallest page number out of all pages held in the WAL that -** has not been returned by any prior invocation of this method on the -** same WalIterator object. Write into *piFrame the frame index where -** that page was last written into the WAL. Write into *piPage the page -** number. -** -** Return 0 on success. If there are no pages in the WAL with a page -** number larger than *piPage, then return 1. -*/ -static int walIteratorNext( - WalIterator *p, /* Iterator */ - u32 *piPage, /* OUT: The page number of the next page */ - u32 *piFrame /* OUT: Wal frame index of next page */ -){ - u32 iMin; /* Result pgno must be greater than iMin */ - u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */ - int i; /* For looping through segments */ - - iMin = p->iPrior; - assert( iMin<0xffffffff ); - for(i=p->nSegment-1; i>=0; i--){ - struct WalSegment *pSegment = &p->aSegment[i]; - while( pSegment->iNextnEntry ){ - u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]]; - if( iPg>iMin ){ - if( iPgiZero + pSegment->aIndex[pSegment->iNext]; - } - break; - } - pSegment->iNext++; - } - } - - *piPage = p->iPrior = iRet; - return (iRet==0xFFFFFFFF); -} - -/* -** This function merges two sorted lists into a single sorted list. -** -** aLeft[] and aRight[] are arrays of indices. The sort key is -** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following -** is guaranteed for all J0 && nRight>0 ); - while( iRight=nRight || aContent[aLeft[iLeft]]=nLeft || aContent[aLeft[iLeft]]>dbpage ); - assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage ); - } - - *paRight = aLeft; - *pnRight = iOut; - memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut); -} - -/* -** Sort the elements in list aList using aContent[] as the sort key. -** Remove elements with duplicate keys, preferring to keep the -** larger aList[] values. -** -** The aList[] entries are indices into aContent[]. The values in -** aList[] are to be sorted so that for all J0 ); - assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); - - for(iList=0; iListaList && p->nList<=(1<aList==&aList[iList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); - } - aSub[iSub].aList = aMerge; - aSub[iSub].nList = nMerge; - } - - for(iSub++; iSubnList<=(1<aList==&aList[nList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); - } - } - assert( aMerge==aList ); - *pnList = nMerge; - -#ifdef SQLITE_DEBUG - { - int i; - for(i=1; i<*pnList; i++){ - assert( aContent[aList[i]] > aContent[aList[i-1]] ); - } - } -#endif -} - -/* -** Free an iterator allocated by walIteratorInit(). -*/ -static void walIteratorFree(WalIterator *p){ - sqlite3_free(p); -} - -/* -** Construct a WalInterator object that can be used to loop over all -** pages in the WAL following frame nBackfill in ascending order. Frames -** nBackfill or earlier may be included - excluding them is an optimization -** only. The caller must hold the checkpoint lock. -** -** On success, make *pp point to the newly allocated WalInterator object -** return SQLITE_OK. Otherwise, return an error code. If this routine -** returns an error, the value of *pp is undefined. -** -** The calling routine should invoke walIteratorFree() to destroy the -** WalIterator object when it has finished with it. -*/ -static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ - WalIterator *p; /* Return value */ - int nSegment; /* Number of segments to merge */ - u32 iLast; /* Last frame in log */ - sqlite3_int64 nByte; /* Number of bytes to allocate */ - int i; /* Iterator variable */ - ht_slot *aTmp; /* Temp space used by merge-sort */ - int rc = SQLITE_OK; /* Return Code */ - - /* This routine only runs while holding the checkpoint lock. And - ** it only runs if there is actually content in the log (mxFrame>0). - */ - assert( pWal->ckptLock && pWal->hdr.mxFrame>0 ); - iLast = pWal->hdr.mxFrame; - - /* Allocate space for the WalIterator object. */ - nSegment = walFramePage(iLast) + 1; - nByte = SZ_WALITERATOR(nSegment) - + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte - + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !p ){ - return SQLITE_NOMEM_BKPT; - } - memset(p, 0, nByte); - p->nSegment = nSegment; - aTmp = (ht_slot*)&(((u8*)p)[nByte]); - SEH_FREE_ON_ERROR(0, p); - for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[p->nSegment])[sLoc.iZero]; - sLoc.iZero++; - - for(j=0; jaSegment[i].iZero = sLoc.iZero; - p->aSegment[i].nEntry = nEntry; - p->aSegment[i].aIndex = aIndex; - p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; - } - } - if( rc!=SQLITE_OK ){ - SEH_FREE_ON_ERROR(p, 0); - walIteratorFree(p); - p = 0; - } - *pp = p; - return rc; -} - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - - -/* -** Attempt to enable blocking locks that block for nMs ms. Return 1 if -** blocking locks are successfully enabled, or 0 otherwise. -*/ -static int walEnableBlockingMs(Wal *pWal, int nMs){ - int rc = sqlite3OsFileControl( - pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs - ); - return (rc==SQLITE_OK); -} - -/* -** Attempt to enable blocking locks. Blocking locks are enabled only if (a) -** they are supported by the VFS, and (b) the database handle is configured -** with a busy-timeout. Return 1 if blocking locks are successfully enabled, -** or 0 otherwise. -*/ -static int walEnableBlocking(Wal *pWal){ - int res = 0; - if( pWal->db ){ - int tmout = pWal->db->setlkTimeout; - if( tmout ){ - res = walEnableBlockingMs(pWal, tmout); - } - } - return res; -} - -/* -** Disable blocking locks. -*/ -static void walDisableBlocking(Wal *pWal){ - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); -} - -/* -** If parameter bLock is true, attempt to enable blocking locks, take -** the WRITER lock, and then disable blocking locks. If blocking locks -** cannot be enabled, no attempt to obtain the WRITER lock is made. Return -** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not -** an error if blocking locks can not be enabled. -** -** If the bLock parameter is false and the WRITER lock is held, release it. -*/ -SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){ - int rc = SQLITE_OK; - assert( pWal->readLock<0 || bLock==0 ); - if( bLock ){ - assert( pWal->db ); - if( walEnableBlocking(pWal) ){ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - } - walDisableBlocking(pWal); - } - }else if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - } - return rc; -} - -/* -** Set the database handle used to determine if blocking locks are required. -*/ -SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){ - pWal->db = db; -} - -#else -# define walEnableBlocking(x) 0 -# define walDisableBlocking(x) -# define walEnableBlockingMs(pWal, ms) 0 -# define sqlite3WalDb(pWal, db) -#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ - - -/* -** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and -** n. If the attempt fails and parameter xBusy is not NULL, then it is a -** busy-handler function. Invoke it and retry the lock until either the -** lock is successfully obtained or the busy-handler returns 0. -*/ -static int walBusyLock( - Wal *pWal, /* WAL connection */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int lockIdx, /* Offset of first byte to lock */ - int n /* Number of bytes to lock */ -){ - int rc; - do { - rc = walLockExclusive(pWal, lockIdx, n); - }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ){ - walDisableBlocking(pWal); - rc = SQLITE_BUSY; - } -#endif - return rc; -} - -/* -** The cache of the wal-index header must be valid to call this function. -** Return the page-size in bytes used by the database. -*/ -static int walPagesize(Wal *pWal){ - return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); -} - -/* -** The following is guaranteed when this function is called: -** -** a) the WRITER lock is held, -** b) the entire log file has been checkpointed, and -** c) any existing readers are reading exclusively from the database -** file - there are no readers that may attempt to read a frame from -** the log file. -** -** This function updates the shared-memory structures so that the next -** client to write to the database (which may be this one) does so by -** writing frames into the start of the log file. -** -** The value of parameter salt1 is used as the aSalt[1] value in the -** new wal-index header. It should be passed a pseudo-random value (i.e. -** one obtained from sqlite3_randomness()). -*/ -static void walRestartHdr(Wal *pWal, u32 salt1){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int i; /* Loop counter */ - u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ - pWal->nCkpt++; - pWal->hdr.mxFrame = 0; - sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); - memcpy(&pWal->hdr.aSalt[1], &salt1, 4); - walIndexWriteHdr(pWal); - AtomicStore(&pInfo->nBackfill, 0); - pInfo->nBackfillAttempted = 0; - pInfo->aReadMark[1] = 0; - for(i=2; iaReadMark[i] = READMARK_NOT_USED; - assert( pInfo->aReadMark[0]==0 ); -} - -/* -** Copy as much content as we can from the WAL back into the database file -** in response to an sqlite3_wal_checkpoint() request or the equivalent. -** -** The amount of information copies from WAL to database might be limited -** by active readers. This routine will never overwrite a database page -** that a concurrent reader might be using. -** -** All I/O barrier operations (a.k.a fsyncs) occur in this routine when -** SQLite is in WAL-mode in synchronous=NORMAL. That means that if -** checkpoints are always run by a background thread or background -** process, foreground threads will never block on a lengthy fsync call. -** -** Fsync is called on the WAL before writing content out of the WAL and -** into the database. This ensures that if the new content is persistent -** in the WAL and can be recovered following a power-loss or hard reset. -** -** Fsync is also called on the database file if (and only if) the entire -** WAL content is copied into the database file. This second fsync makes -** it safe to delete the WAL since the new content will persist in the -** database file. -** -** This routine uses and updates the nBackfill field of the wal-index header. -** This is the only routine that will increase the value of nBackfill. -** (A WAL reset or recovery will revert nBackfill to zero, but not increase -** its value.) -** -** The caller must be holding sufficient locks to ensure that no other -** checkpoint is running (in any other thread or process) at the same -** time. -*/ -static int walCheckpoint( - Wal *pWal, /* Wal connection */ - sqlite3 *db, /* Check for interrupts on this handle */ - int eMode, /* One of PASSIVE, FULL or RESTART */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags for OsSync() (or 0) */ - u8 *zBuf /* Temporary buffer to use */ -){ - int rc = SQLITE_OK; /* Return code */ - int szPage; /* Database page-size */ - WalIterator *pIter = 0; /* Wal iterator context */ - u32 iDbpage = 0; /* Next database page to write */ - u32 iFrame = 0; /* Wal frame containing data for iDbpage */ - u32 mxSafeFrame; /* Max frame that can be backfilled */ - u32 mxPage; /* Max database page to write */ - int i; /* Loop counter */ - volatile WalCkptInfo *pInfo; /* The checkpoint status information */ - - szPage = walPagesize(pWal); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - pInfo = walCkptInfo(pWal); - if( pInfo->nBackfillhdr.mxFrame ){ - - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked - ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); - - /* Compute in mxSafeFrame the index of the last frame of the WAL that is - ** safe to write into the database. Frames beyond mxSafeFrame might - ** overwrite database pages that are in use by active readers and thus - ** cannot be backfilled from the WAL. - */ - mxSafeFrame = pWal->hdr.mxFrame; - mxPage = pWal->hdr.nPage; - for(i=1; iaReadMark+i); SEH_INJECT_FAULT; - if( mxSafeFrame>y ){ - assert( y<=pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); - if( rc==SQLITE_OK ){ - u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc==SQLITE_BUSY ){ - mxSafeFrame = y; - xBusy = 0; - }else{ - goto walcheckpoint_out; - } - } - } - - /* Allocate the iterator */ - if( pInfo->nBackfillnBackfill, &pIter); - assert( rc==SQLITE_OK || pIter==0 ); - } - - if( pIter - && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK - ){ - u32 nBackfill = pInfo->nBackfill; - pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; - - /* Sync the WAL to disk */ - rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); - - /* If the database may grow as a result of this checkpoint, hint - ** about the eventual size of the db file to the VFS layer. - */ - if( rc==SQLITE_OK ){ - i64 nReq = ((i64)mxPage * szPage); - i64 nSize; /* Current size of database file */ - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0); - rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); - if( rc==SQLITE_OK && nSizehdr.mxFrame*szPage)pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq); - } - } - - } - - /* Iterate through the contents of the WAL, copying data to the db file */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ - i64 iOffset; - assert( walFramePgno(pWal, iFrame)==iDbpage ); - SEH_INJECT_FAULT; - if( AtomicLoad(&db->u1.isInterrupted) ){ - rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; - break; - } - if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ - continue; - } - iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ - rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - iOffset = (iDbpage-1)*(i64)szPage; - testcase( IS_BIG_INT(iOffset) ); - rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - } - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0); - - /* If work was actually accomplished... */ - if( rc==SQLITE_OK ){ - if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ - i64 szDb = pWal->hdr.nPage*(i64)szPage; - testcase( IS_BIG_INT(szDb) ); - rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK ){ - rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); - } - } - if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; - } - } - - /* Release the reader lock held while backfilling */ - walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); - } - - if( rc==SQLITE_BUSY ){ - /* Reset the return code so as not to report a checkpoint failure - ** just because there are active readers. */ - rc = SQLITE_OK; - } - } - - /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the - ** entire wal file has been copied into the database file, then block - ** until all readers have finished using the wal file. This ensures that - ** the next process to write to the database restarts the wal file. - */ - if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - assert( pWal->writeLock ); - SEH_INJECT_FAULT; - if( pInfo->nBackfillhdr.mxFrame ){ - rc = SQLITE_BUSY; - }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ - u32 salt1; - sqlite3_randomness(4, &salt1); - assert( pInfo->nBackfill==pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); - if( rc==SQLITE_OK ){ - if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ - /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as - ** SQLITE_CHECKPOINT_RESTART with the addition that it also - ** truncates the log file to zero bytes just prior to a - ** successful return. - ** - ** In theory, it might be safe to do this without updating the - ** wal-index header in shared memory, as all subsequent reader or - ** writer clients should see that the entire log file has been - ** checkpointed and behave accordingly. This seems unsafe though, - ** as it would leave the system in a state where the contents of - ** the wal-index header do not match the contents of the - ** file-system. To avoid this, update the wal-index header to - ** indicate that the log file contains zero valid frames. */ - walRestartHdr(pWal, salt1); - rc = sqlite3OsTruncate(pWal->pWalFd, 0); - } - walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - } - } - } - - walcheckpoint_out: - SEH_FREE_ON_ERROR(pIter, 0); - walIteratorFree(pIter); - return rc; -} - -/* -** If the WAL file is currently larger than nMax bytes in size, truncate -** it to exactly nMax bytes. If an error occurs while doing so, ignore it. -*/ -static void walLimitSize(Wal *pWal, i64 nMax){ - i64 sz; - int rx; - sqlite3BeginBenignMalloc(); - rx = sqlite3OsFileSize(pWal->pWalFd, &sz); - if( rx==SQLITE_OK && (sz > nMax ) ){ - rx = sqlite3OsTruncate(pWal->pWalFd, nMax); - } - sqlite3EndBenignMalloc(); - if( rx ){ - sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); - } -} - -#ifdef SQLITE_USE_SEH -/* -** This is the "standard" exception handler used in a few places to handle -** an exception thrown by reading from the *-shm mapping after it has become -** invalid in SQLITE_USE_SEH builds. It is used as follows: -** -** SEH_TRY { ... } -** SEH_EXCEPT( rc = walHandleException(pWal); ) -** -** This function does three things: -** -** 1) Determines the locks that should be held, based on the contents of -** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other -** held locks are assumed to be transient locks that would have been -** released had the exception not been thrown and are dropped. -** -** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). -** -** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL -** -** 4) Returns SQLITE_IOERR. -*/ -static int walHandleException(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<writeLock==2 ) pWal->writeLock = 0; - mUnlock = pWal->lockMask & ~( - (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) - ); - for(ii=0; iipFree); - pWal->pFree = 0; - if( pWal->pWiValue ){ - pWal->apWiData[pWal->iWiPg] = pWal->pWiValue; - pWal->pWiValue = 0; - } - return SQLITE_IOERR_IN_PAGE; -} - -/* -** Assert that the Wal.lockMask mask, which indicates the locks held -** by the connection, is consistent with the Wal.readLock, Wal.writeLock -** and Wal.ckptLock variables. To be used as: -** -** assert( walAssertLockmask(pWal) ); -*/ -static int walAssertLockmask(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) -#ifdef SQLITE_ENABLE_SNAPSHOT - | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) -#endif - ); - assert( mExpect==pWal->lockMask ); - } - return 1; -} - -/* -** Return and zero the "system error" field set when an -** EXCEPTION_IN_PAGE_ERROR exception is caught. -*/ -SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){ - int iRet = 0; - if( pWal ){ - iRet = pWal->iSysErrno; - pWal->iSysErrno = 0; - } - return iRet; -} - -#else -# define walAssertLockmask(x) 1 -#endif /* ifdef SQLITE_USE_SEH */ - -/* -** Close a connection to a log file. -*/ -SQLITE_PRIVATE int sqlite3WalClose( - Wal *pWal, /* Wal to close */ - sqlite3 *db, /* For interrupt flag */ - int sync_flags, /* Flags to pass to OsSync() (or 0) */ - int nBuf, - u8 *zBuf /* Buffer of at least nBuf bytes */ -){ - int rc = SQLITE_OK; - if( pWal ){ - int isDelete = 0; /* True to unlink wal and wal-index files */ - - assert( walAssertLockmask(pWal) ); - - /* If an EXCLUSIVE lock can be obtained on the database file (using the - ** ordinary, rollback-mode locking methods, this guarantees that the - ** connection associated with this log file is the only connection to - ** the database. In this case checkpoint the database and unlink both - ** the wal and wal-index files. - ** - ** The EXCLUSIVE lock is not released before returning. - */ - if( zBuf!=0 - && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) - ){ - if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; - } - rc = sqlite3WalCheckpoint(pWal, db, - SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 - ); - if( rc==SQLITE_OK ){ - int bPersist = -1; - sqlite3OsFileControlHint( - pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist - ); - if( bPersist!=1 ){ - /* Try to delete the WAL file if the checkpoint completed and - ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal - ** mode (!bPersist) */ - isDelete = 1; - }else if( pWal->mxWalSize>=0 ){ - /* Try to truncate the WAL file to zero bytes if the checkpoint - ** completed and fsynced (rc==SQLITE_OK) and we are in persistent - ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a - ** non-negative value (pWal->mxWalSize>=0). Note that we truncate - ** to zero bytes as truncating to the journal_size_limit might - ** leave a corrupt WAL file on disk. */ - walLimitSize(pWal, 0); - } - } - } - - walIndexClose(pWal, isDelete); - sqlite3OsClose(pWal->pWalFd); - if( isDelete ){ - sqlite3BeginBenignMalloc(); - sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); - sqlite3EndBenignMalloc(); - } - WALTRACE(("WAL%p: closed\n", pWal)); - sqlite3_free((void *)pWal->apWiData); - sqlite3_free(pWal); - } - return rc; -} - -/* -** Try to read the wal-index header. Return 0 on success and 1 if -** there is a problem. -** -** The wal-index is in shared memory. Another thread or process might -** be writing the header at the same time this procedure is trying to -** read it, which might result in inconsistency. A dirty read is detected -** by verifying that both copies of the header are the same and also by -** a checksum on the header. -** -** If and only if the read is consistent and the header is different from -** pWal->hdr, then pWal->hdr is updated to the content of the new header -** and *pChanged is set to 1. -** -** If the checksum cannot be verified return non-zero. If the header -** is read successfully and the checksum verified, return zero. -*/ -static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){ - u32 aCksum[2]; /* Checksum on the header content */ - WalIndexHdr h1, h2; /* Two copies of the header content */ - WalIndexHdr volatile *aHdr; /* Header in shared memory */ - - /* The first page of the wal-index must be mapped at this point. */ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - - /* Read the header. This might happen concurrently with a write to the - ** same area of shared memory on a different CPU in a SMP, - ** meaning it is possible that an inconsistent snapshot is read - ** from the file. If this happens, return non-zero. - ** - ** tag-20200519-1: - ** There are two copies of the header at the beginning of the wal-index. - ** When reading, read [0] first then [1]. Writes are in the reverse order. - ** Memory barriers are used to prevent the compiler or the hardware from - ** reordering the reads and writes. TSAN and similar tools can sometimes - ** give false-positive warnings about these accesses because the tools do not - ** account for the double-read and the memory barrier. The use of mutexes - ** here would be problematic as the memory being accessed is potentially - ** shared among multiple processes and not all mutex implementations work - ** reliably in that environment. - */ - aHdr = walIndexHdr(pWal); - memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */ - walShmBarrier(pWal); - memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); - - if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ - return 1; /* Dirty read */ - } - if( h1.isInit==0 ){ - return 1; /* Malformed header - probably all zeros */ - } - walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum); - if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){ - return 1; /* Checksum does not match */ - } - - if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){ - *pChanged = 1; - memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr)); - pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); - testcase( pWal->szPage<=32768 ); - testcase( pWal->szPage>=65536 ); - } - - /* The header was successfully read. Return zero. */ - return 0; -} - -/* -** This is the value that walTryBeginRead returns when it needs to -** be retried. -*/ -#define WAL_RETRY (-1) - -/* -** Read the wal-index header from the wal-index and into pWal->hdr. -** If the wal-header appears to be corrupt, try to reconstruct the -** wal-index from the WAL before returning. -** -** Set *pChanged to 1 if the wal-index header value in pWal->hdr is -** changed by this operation. If pWal->hdr is unchanged, set *pChanged -** to 0. -** -** If the wal-index header is successfully read, return SQLITE_OK. -** Otherwise an SQLite error code. -*/ -static int walIndexReadHdr(Wal *pWal, int *pChanged){ - int rc; /* Return code */ - int badHdr; /* True if a header read failed */ - volatile u32 *page0; /* Chunk of wal-index containing header */ - - /* Ensure that page 0 of the wal-index (the page that contains the - ** wal-index header) is mapped. Return early if an error occurs here. - */ - assert( pChanged ); - rc = walIndexPage(pWal, 0, &page0); - if( rc!=SQLITE_OK ){ - assert( rc!=SQLITE_READONLY ); /* READONLY changed to OK in walIndexPage */ - if( rc==SQLITE_READONLY_CANTINIT ){ - /* The SQLITE_READONLY_CANTINIT return means that the shared-memory - ** was openable but is not writable, and this thread is unable to - ** confirm that another write-capable connection has the shared-memory - ** open, and hence the content of the shared-memory is unreliable, - ** since the shared-memory might be inconsistent with the WAL file - ** and there is no writer on hand to fix it. */ - assert( page0==0 ); - assert( pWal->writeLock==0 ); - assert( pWal->readOnly & WAL_SHM_RDONLY ); - pWal->bShmUnreliable = 1; - pWal->exclusiveMode = WAL_HEAPMEMORY_MODE; - *pChanged = 1; - }else{ - return rc; /* Any other non-OK return is just an error */ - } - }else{ - /* page0 can be NULL if the SHM is zero bytes in size and pWal->writeLock - ** is zero, which prevents the SHM from growing */ - testcase( page0!=0 ); - } - assert( page0!=0 || pWal->writeLock==0 ); - - /* If the first page of the wal-index has been mapped, try to read the - ** wal-index header immediately, without holding any lock. This usually - ** works, but may fail if the wal-index header is corrupt or currently - ** being modified by another thread or process. - */ - badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); - - /* If the first attempt failed, it might have been due to a race - ** with a writer. So get a WRITE lock and try again. - */ - if( badHdr ){ - if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){ - if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ - walUnlockShared(pWal, WAL_WRITE_LOCK); - rc = SQLITE_READONLY_RECOVERY; - } - }else{ - int bWriteLock = pWal->writeLock; - if( bWriteLock - || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) - ){ - /* If the write-lock was just obtained, set writeLock to 2 instead of - ** the usual 1. This causes walIndexPage() to behave as if the - ** write-lock were held (so that it allocates new pages as required), - ** and walHandleException() to unlock the write-lock if a SEH exception - ** is thrown. */ - if( !bWriteLock ) pWal->writeLock = 2; - if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ - badHdr = walIndexTryHdr(pWal, pChanged); - if( badHdr ){ - /* If the wal-index header is still malformed even while holding - ** a WRITE lock, it can only mean that the header is corrupted and - ** needs to be reconstructed. So run recovery to do exactly that. - ** Disable blocking locks first. */ - walDisableBlocking(pWal); - rc = walIndexRecover(pWal); - *pChanged = 1; - } - } - if( bWriteLock==0 ){ - pWal->writeLock = 0; - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - } - } - } - } - - /* If the header is read successfully, check the version number to make - ** sure the wal-index was not constructed with some future format that - ** this version of SQLite cannot understand. - */ - if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ - rc = SQLITE_CANTOPEN_BKPT; - } - if( pWal->bShmUnreliable ){ - if( rc!=SQLITE_OK ){ - walIndexClose(pWal, 0); - pWal->bShmUnreliable = 0; - assert( pWal->nWiData>0 && pWal->apWiData[0]==0 ); - /* walIndexRecover() might have returned SHORT_READ if a concurrent - ** writer truncated the WAL out from under it. If that happens, it - ** indicates that a writer has fixed the SHM file for us, so retry */ - if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; - } - pWal->exclusiveMode = WAL_NORMAL_MODE; - } - - return rc; -} - -/* -** Open a transaction in a connection where the shared-memory is read-only -** and where we cannot verify that there is a separate write-capable connection -** on hand to keep the shared-memory up-to-date with the WAL file. -** -** This can happen, for example, when the shared-memory is implemented by -** memory-mapping a *-shm file, where a prior writer has shut down and -** left the *-shm file on disk, and now the present connection is trying -** to use that database but lacks write permission on the *-shm file. -** Other scenarios are also possible, depending on the VFS implementation. -** -** Precondition: -** -** The *-wal file has been read and an appropriate wal-index has been -** constructed in pWal->apWiData[] using heap memory instead of shared -** memory. -** -** If this function returns SQLITE_OK, then the read transaction has -** been successfully opened. In this case output variable (*pChanged) -** is set to true before returning if the caller should discard the -** contents of the page cache before proceeding. Or, if it returns -** WAL_RETRY, then the heap memory wal-index has been discarded and -** the caller should retry opening the read transaction from the -** beginning (including attempting to map the *-shm file). -** -** If an error occurs, an SQLite error code is returned. -*/ -static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ - i64 szWal; /* Size of wal file on disk in bytes */ - i64 iOffset; /* Current offset when reading wal file */ - u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ - u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ - int szFrame; /* Number of bytes in buffer aFrame[] */ - u8 *aData; /* Pointer to data part of aFrame buffer */ - volatile void *pDummy; /* Dummy argument for xShmMap */ - int rc; /* Return code */ - u32 aSaveCksum[2]; /* Saved copy of pWal->hdr.aFrameCksum */ - - assert( pWal->bShmUnreliable ); - assert( pWal->readOnly & WAL_SHM_RDONLY ); - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - - /* Take WAL_READ_LOCK(0). This has the effect of preventing any - ** writers from running a checkpoint, but does not stop them - ** from running recovery. */ - rc = walLockShared(pWal, WAL_READ_LOCK(0)); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_BUSY ) rc = WAL_RETRY; - goto begin_unreliable_shm_out; - } - pWal->readLock = 0; - - /* Check to see if a separate writer has attached to the shared-memory area, - ** thus making the shared-memory "reliable" again. Do this by invoking - ** the xShmMap() routine of the VFS and looking to see if the return - ** is SQLITE_READONLY instead of SQLITE_READONLY_CANTINIT. - ** - ** If the shared-memory is now "reliable" return WAL_RETRY, which will - ** cause the heap-memory WAL-index to be discarded and the actual - ** shared memory to be used in its place. - ** - ** This step is important because, even though this connection is holding - ** the WAL_READ_LOCK(0) which prevents a checkpoint, a writer might - ** have already checkpointed the WAL file and, while the current - ** is active, wrap the WAL and start overwriting frames that this - ** process wants to use. - ** - ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has - ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY - ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations, - ** even if some external agent does a "chmod" to make the shared-memory - ** writable by us, until sqlite3OsShmUnmap() has been called. - ** This is a requirement on the VFS implementation. - */ - rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy); - assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */ - if( rc!=SQLITE_READONLY_CANTINIT ){ - rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc); - goto begin_unreliable_shm_out; - } - - /* We reach this point only if the real shared-memory is still unreliable. - ** Assume the in-memory WAL-index substitute is correct and load it - ** into pWal->hdr. - */ - memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - /* Make sure some writer hasn't come in and changed the WAL file out - ** from under us, then disconnected, while we were not looking. - */ - rc = sqlite3OsFileSize(pWal->pWalFd, &szWal); - if( rc!=SQLITE_OK ){ - goto begin_unreliable_shm_out; - } - if( szWalhdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY); - goto begin_unreliable_shm_out; - } - - /* Check the salt keys at the start of the wal file still match. */ - rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); - if( rc!=SQLITE_OK ){ - goto begin_unreliable_shm_out; - } - if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){ - /* Some writer has wrapped the WAL file while we were not looking. - ** Return WAL_RETRY which will cause the in-memory WAL-index to be - ** rebuilt. */ - rc = WAL_RETRY; - goto begin_unreliable_shm_out; - } - - /* Allocate a buffer to read frames into */ - assert( (pWal->szPage & (pWal->szPage-1))==0 ); - assert( pWal->szPage>=512 && pWal->szPage<=65536 ); - szFrame = pWal->szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc64(szFrame); - if( aFrame==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto begin_unreliable_shm_out; - } - aData = &aFrame[WAL_FRAME_HDRSIZE]; - - /* Check to see if a complete transaction has been appended to the - ** wal file since the heap-memory wal-index was created. If so, the - ** heap-memory wal-index is discarded and WAL_RETRY returned to - ** the caller. */ - aSaveCksum[0] = pWal->hdr.aFrameCksum[0]; - aSaveCksum[1] = pWal->hdr.aFrameCksum[1]; - for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage); - iOffset+szFrame<=szWal; - iOffset+=szFrame - ){ - u32 pgno; /* Database page number for frame */ - u32 nTruncate; /* dbsize field from frame header */ - - /* Read and decode the next log frame. */ - rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); - if( rc!=SQLITE_OK ) break; - if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break; - - /* If nTruncate is non-zero, then a complete transaction has been - ** appended to this wal file. Set rc to WAL_RETRY and break out of - ** the loop. */ - if( nTruncate ){ - rc = WAL_RETRY; - break; - } - } - pWal->hdr.aFrameCksum[0] = aSaveCksum[0]; - pWal->hdr.aFrameCksum[1] = aSaveCksum[1]; - - begin_unreliable_shm_out: - sqlite3_free(aFrame); - if( rc!=SQLITE_OK ){ - int i; - for(i=0; inWiData; i++){ - sqlite3_free((void*)pWal->apWiData[i]); - pWal->apWiData[i] = 0; - } - pWal->bShmUnreliable = 0; - sqlite3WalEndReadTransaction(pWal); - *pChanged = 1; - } - return rc; -} - -/* -** The final argument passed to walTryBeginRead() is of type (int*). The -** caller should invoke walTryBeginRead as follows: -** -** int cnt = 0; -** do { -** rc = walTryBeginRead(..., &cnt); -** }while( rc==WAL_RETRY ); -** -** The final value of "cnt" is of no use to the caller. It is used by -** the implementation of walTryBeginRead() as follows: -** -** + Each time walTryBeginRead() is called, it is incremented. Once -** it reaches WAL_RETRY_PROTOCOL_LIMIT - indicating that walTryBeginRead() -** has many times been invoked and failed with WAL_RETRY - walTryBeginRead() -** returns SQLITE_PROTOCOL. -** -** + If SQLITE_ENABLE_SETLK_TIMEOUT is defined and walTryBeginRead() failed -** because a blocking lock timed out (SQLITE_BUSY_TIMEOUT from the OS -** layer), the WAL_RETRY_BLOCKED_MASK bit is set in "cnt". In this case -** the next invocation of walTryBeginRead() may omit an expected call to -** sqlite3OsSleep(). There has already been a delay when the previous call -** waited on a lock. -*/ -#define WAL_RETRY_PROTOCOL_LIMIT 100 -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -# define WAL_RETRY_BLOCKED_MASK 0x10000000 -#else -# define WAL_RETRY_BLOCKED_MASK 0 -#endif - -/* -** Attempt to start a read transaction. This might fail due to a race or -** other transient condition. When that happens, it returns WAL_RETRY to -** indicate to the caller that it is safe to retry immediately. -** -** On success return SQLITE_OK. On a permanent failure (such an -** I/O error or an SQLITE_BUSY because another process is running -** recovery) return a positive error code. -** -** The useWal parameter is true to force the use of the WAL and disable -** the case where the WAL is bypassed because it has been completely -** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() -** to make a copy of the wal-index header into pWal->hdr. If the -** wal-index header has changed, *pChanged is set to 1 (as an indication -** to the caller that the local page cache is obsolete and needs to be -** flushed.) When useWal==1, the wal-index header is assumed to already -** be loaded and the pChanged parameter is unused. -** -** The caller must set the cnt parameter to the number of prior calls to -** this routine during the current read attempt that returned WAL_RETRY. -** This routine will start taking more aggressive measures to clear the -** race conditions after multiple WAL_RETRY returns, and after an excessive -** number of errors will ultimately return SQLITE_PROTOCOL. The -** SQLITE_PROTOCOL return indicates that some other process has gone rogue -** and is not honoring the locking protocol. There is a vanishingly small -** chance that SQLITE_PROTOCOL could be returned because of a run of really -** bad luck when there is lots of contention for the wal-index, but that -** possibility is so small that it can be safely neglected, we believe. -** -** On success, this routine obtains a read lock on -** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is -** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1) -** that means the Wal does not hold any read lock. The reader must not -** access any database page that is modified by a WAL frame up to and -** including frame number aReadMark[pWal->readLock]. The reader will -** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0 -** Or if pWal->readLock==0, then the reader will ignore the WAL -** completely and get all content directly from the database file. -** If the useWal parameter is 1 then the WAL will never be ignored and -** this routine will always set pWal->readLock>0 on success. -** When the read transaction is completed, the caller must release the -** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1. -** -** This routine uses the nBackfill and aReadMark[] fields of the header -** to select a particular WAL_READ_LOCK() that strives to let the -** checkpoint process do as much work as possible. This routine might -** update values of the aReadMark[] array in the header, but if it does -** so it takes care to hold an exclusive lock on the corresponding -** WAL_READ_LOCK() while changing values. -*/ -static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){ - volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ - int rc = SQLITE_OK; /* Return code */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int nBlockTmout = 0; -#endif - - assert( pWal->readLock<0 ); /* Not currently locked */ - - /* useWal may only be set for read/write connections */ - assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 ); - - /* Take steps to avoid spinning forever if there is a protocol error. - ** - ** Circumstances that cause a RETRY should only last for the briefest - ** instances of time. No I/O or other system calls are done while the - ** locks are held, so the locks should not be held for very long. But - ** if we are unlucky, another process that is holding a lock might get - ** paged out or take a page-fault that is time-consuming to resolve, - ** during the few nanoseconds that it is holding the lock. In that case, - ** it might take longer than normal for the lock to free. - ** - ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few - ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this - ** is more of a scheduler yield than an actual delay. But on the 10th - ** an subsequent retries, the delays start becoming longer and longer, - ** so that on the 100th (and last) RETRY we delay for 323 milliseconds. - ** The total delay time before giving up is less than 10 seconds. - */ - (*pCnt)++; - if( *pCnt>5 ){ - int nDelay = 1; /* Pause time in microseconds */ - int cnt = (*pCnt & ~WAL_RETRY_BLOCKED_MASK); - if( cnt>WAL_RETRY_PROTOCOL_LIMIT ){ - VVA_ONLY( pWal->lockError = 1; ) - return SQLITE_PROTOCOL; - } - if( *pCnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor - ** to block for locks for approximately nDelay us. This affects three - ** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if - ** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the - ** first attempted read fails, and (c) the shared lock taken on the - ** read-mark. - ** - ** If the previous call failed due to an SQLITE_BUSY_TIMEOUT error, - ** then sleep for the minimum of 1us. The previous call already provided - ** an extra delay while it was blocking on the lock. - */ - nBlockTmout = (nDelay+998) / 1000; - if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){ - if( *pCnt & WAL_RETRY_BLOCKED_MASK ) nDelay = 1; - } -#endif - sqlite3OsSleep(pWal->pVfs, nDelay); - *pCnt &= ~WAL_RETRY_BLOCKED_MASK; - } - - if( !useWal ){ - assert( rc==SQLITE_OK ); - if( pWal->bShmUnreliable==0 ){ - rc = walIndexReadHdr(pWal, pChanged); - } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ){ - rc = SQLITE_BUSY; - *pCnt |= WAL_RETRY_BLOCKED_MASK; - } -#endif - if( rc==SQLITE_BUSY ){ - /* If there is not a recovery running in another thread or process - ** then convert BUSY errors to WAL_RETRY. If recovery is known to - ** be running, convert BUSY to BUSY_RECOVERY. There is a race here - ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY - ** would be technically correct. But the race is benign since with - ** WAL_RETRY this routine will be called again and will probably be - ** right on the second iteration. - */ - (void)walEnableBlocking(pWal); - if( pWal->apWiData[0]==0 ){ - /* This branch is taken when the xShmMap() method returns SQLITE_BUSY. - ** We assume this is a transient condition, so return WAL_RETRY. The - ** xShmMap() implementation used by the default unix and win32 VFS - ** modules may return SQLITE_BUSY due to a race condition in the - ** code that determines whether or not the shared-memory region - ** must be zeroed before the requested page is returned. - */ - rc = WAL_RETRY; - }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ - walUnlockShared(pWal, WAL_RECOVER_LOCK); - rc = WAL_RETRY; - }else if( rc==SQLITE_BUSY ){ - rc = SQLITE_BUSY_RECOVERY; - } - } - walDisableBlocking(pWal); - if( rc!=SQLITE_OK ){ - return rc; - } - else if( pWal->bShmUnreliable ){ - return walBeginShmUnreliable(pWal, pChanged); - } - } - - assert( pWal->nWiData>0 ); - assert( pWal->apWiData[0]!=0 ); - pInfo = walCkptInfo(pWal); - SEH_INJECT_FAULT; - { - u32 mxReadMark; /* Largest aReadMark[] value */ - int mxI; /* Index of largest aReadMark[] value */ - int i; /* Loop counter */ - u32 mxFrame; /* Wal frame to lock to */ - if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame -#ifdef SQLITE_ENABLE_SNAPSHOT - && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0) -#endif - ){ - /* The WAL has been completely backfilled (or it is empty). - ** and can be safely ignored. - */ - rc = walLockShared(pWal, WAL_READ_LOCK(0)); - walShmBarrier(pWal); - if( rc==SQLITE_OK ){ - if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){ - /* It is not safe to allow the reader to continue here if frames - ** may have been appended to the log before READ_LOCK(0) was obtained. - ** When holding READ_LOCK(0), the reader ignores the entire log file, - ** which implies that the database file contains a trustworthy - ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from - ** happening, this is usually correct. - ** - ** However, if frames have been appended to the log (or if the log - ** is wrapped and written for that matter) before the READ_LOCK(0) - ** is obtained, that is not necessarily true. A checkpointer may - ** have started to backfill the appended frames but crashed before - ** it finished. Leaving a corrupt image in the database file. - */ - walUnlockShared(pWal, WAL_READ_LOCK(0)); - return WAL_RETRY; - } - pWal->readLock = 0; - return SQLITE_OK; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - - /* If we get this far, it means that the reader will want to use - ** the WAL to get at content from recent commits. The job now is - ** to select one of the aReadMark[] entries that is closest to - ** but not exceeding pWal->hdr.mxFrame and lock that entry. - */ - mxReadMark = 0; - mxI = 0; - mxFrame = pWal->hdr.mxFrame; -#ifdef SQLITE_ENABLE_SNAPSHOT - if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame; - } -#endif - for(i=1; iaReadMark+i); SEH_INJECT_FAULT; - if( mxReadMark<=thisMark && thisMark<=mxFrame ){ - assert( thisMark!=READMARK_NOT_USED ); - mxReadMark = thisMark; - mxI = i; - } - } - if( (pWal->readOnly & WAL_SHM_RDONLY)==0 - && (mxReadMarkaReadMark+i,mxFrame); - mxReadMark = mxFrame; - mxI = i; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - break; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - } - if( mxI==0 ){ - assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); - return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; - } - - (void)walEnableBlockingMs(pWal, nBlockTmout); - rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); - walDisableBlocking(pWal); - if( rc ){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ){ - *pCnt |= WAL_RETRY_BLOCKED_MASK; - } -#else - assert( rc!=SQLITE_BUSY_TIMEOUT ); -#endif - assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT); - return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc; - } - /* Now that the read-lock has been obtained, check that neither the - ** value in the aReadMark[] array or the contents of the wal-index - ** header have changed. - ** - ** It is necessary to check that the wal-index header did not change - ** between the time it was read and when the shared-lock was obtained - ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility - ** that the log file may have been wrapped by a writer, or that frames - ** that occur later in the log than pWal->hdr.mxFrame may have been - ** copied into the database by a checkpointer. If either of these things - ** happened, then reading the database with the current value of - ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry - ** instead. - ** - ** Before checking that the live wal-index header has not changed - ** since it was read, set Wal.minFrame to the first frame in the wal - ** file that has not yet been checkpointed. This client will not need - ** to read any frames earlier than minFrame from the wal file - they - ** can be safely read directly from the database file. - ** - ** Because a ShmBarrier() call is made between taking the copy of - ** nBackfill and checking that the wal-header in shared-memory still - ** matches the one cached in pWal->hdr, it is guaranteed that the - ** checkpointer that set nBackfill was not working with a wal-index - ** header newer than that cached in pWal->hdr. If it were, that could - ** cause a problem. The checkpointer could omit to checkpoint - ** a version of page X that lies before pWal->minFrame (call that version - ** A) on the basis that there is a newer version (version B) of the same - ** page later in the wal file. But if version B happens to like past - ** frame pWal->hdr.mxFrame - then the client would incorrectly assume - ** that it can read version A from the database file. However, since - ** we can guarantee that the checkpointer that set nBackfill could not - ** see any pages past pWal->hdr.mxFrame, this problem does not come up. - */ - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; - walShmBarrier(pWal); - if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark - || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) - ){ - walUnlockShared(pWal, WAL_READ_LOCK(mxI)); - return WAL_RETRY; - }else{ - assert( mxReadMark<=pWal->hdr.mxFrame ); - pWal->readLock = (i16)mxI; - } - } - return rc; -} - -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** This function does the work of sqlite3WalSnapshotRecover(). -*/ -static int walSnapshotRecover( - Wal *pWal, /* WAL handle */ - void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ - void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ -){ - int szPage = (int)pWal->szPage; - int rc; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ - WalHashLoc sLoc; /* Hash table location */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &sLoc); - if( rc!=SQLITE_OK ) break; - assert( i - sLoc.iZero - 1 >=0 ); - pgno = sLoc.aPgno[i-sLoc.iZero-1]; - iDbOff = (i64)(pgno-1) * szPage; - - if( iDbOff+szPage<=szDb ){ - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); - - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); - } - - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ - break; - } - } - - pInfo->nBackfillAttempted = i-1; - } - } - - return rc; -} - -/* -** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted -** variable so that older snapshots can be accessed. To do this, loop -** through all wal frames from nBackfillAttempted to (nBackfill+1), -** comparing their content to the corresponding page with the database -** file, if any. Set nBackfillAttempted to the frame number of the -** first frame for which the wal file content matches the db file. -** -** This is only really safe if the file-system is such that any page -** writes made by earlier checkpointers were atomic operations, which -** is not always true. It is also possible that nBackfillAttempted -** may be left set to a value larger than expected, if a wal frame -** contains content that duplicate of an earlier version of the same -** page. -** -** SQLITE_OK is returned if successful, or an SQLite error code if an -** error occurs. It is not an error if nBackfillAttempted cannot be -** decreased at all. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ - int rc; - - assert( pWal->readLock>=0 ); - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(pWal->szPage); - void *pBuf2 = sqlite3_malloc(pWal->szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - pWal->ckptLock = 1; - SEH_TRY { - rc = walSnapshotRecover(pWal, pBuf1, pBuf2); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - pWal->ckptLock = 0; - } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - } - - return rc; -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ - -/* -** This function does the work of sqlite3WalBeginReadTransaction() (see -** below). That function simply calls this one inside an SEH_TRY{...} block. -*/ -static int walBeginReadTransaction(Wal *pWal, int *pChanged){ - int rc; /* Return code */ - int cnt = 0; /* Number of TryBeginRead attempts */ -#ifdef SQLITE_ENABLE_SNAPSHOT - int ckptLock = 0; - int bChanged = 0; - WalIndexHdr *pSnapshot = pWal->pSnapshot; -#endif - - assert( pWal->ckptLock==0 ); - assert( pWal->nSehTry>0 ); - -#ifdef SQLITE_ENABLE_SNAPSHOT - if( pSnapshot ){ - if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - bChanged = 1; - } - - /* It is possible that there is a checkpointer thread running - ** concurrent with this code. If this is the case, it may be that the - ** checkpointer has already determined that it will checkpoint - ** snapshot X, where X is later in the wal file than pSnapshot, but - ** has not yet set the pInfo->nBackfillAttempted variable to indicate - ** its intent. To avoid the race condition this leads to, ensure that - ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. */ - (void)walEnableBlocking(pWal); - rc = walLockShared(pWal, WAL_CKPT_LOCK); - walDisableBlocking(pWal); - - if( rc!=SQLITE_OK ){ - return rc; - } - ckptLock = 1; - } -#endif - - do{ - rc = walTryBeginRead(pWal, pChanged, 0, &cnt); - }while( rc==WAL_RETRY ); - testcase( (rc&0xff)==SQLITE_BUSY ); - testcase( (rc&0xff)==SQLITE_IOERR ); - testcase( rc==SQLITE_PROTOCOL ); - testcase( rc==SQLITE_OK ); - -#ifdef SQLITE_ENABLE_SNAPSHOT - if( rc==SQLITE_OK ){ - if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - /* At this point the client has a lock on an aReadMark[] slot holding - ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr - ** is populated with the wal-index header corresponding to the head - ** of the wal file. Verify that pSnapshot is still valid before - ** continuing. Reasons why pSnapshot might no longer be valid: - ** - ** (1) The WAL file has been reset since the snapshot was taken. - ** In this case, the salt will have changed. - ** - ** (2) A checkpoint as been attempted that wrote frames past - ** pSnapshot->mxFrame into the database file. Note that the - ** checkpoint need not have completed for this to cause problems. - */ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - - assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 ); - assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame ); - - /* Check that the wal file has not been wrapped. Assuming that it has - ** not, also check that no checkpointer has attempted to checkpoint any - ** frames beyond pSnapshot->mxFrame. If either of these conditions are - ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr - ** with *pSnapshot and set *pChanged as appropriate for opening the - ** snapshot. */ - if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - && pSnapshot->mxFrame>=pInfo->nBackfillAttempted - ){ - assert( pWal->readLock>0 ); - memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); - *pChanged = bChanged; - }else{ - rc = SQLITE_ERROR_SNAPSHOT; - } - - /* A client using a non-current snapshot may not ignore any frames - ** from the start of the wal file. This is because, for a system - ** where (minFrame < iSnapshot < maxFrame), a checkpointer may - ** have omitted to checkpoint a frame earlier than minFrame in - ** the file because there exists a frame after iSnapshot that - ** is the same database page. */ - pWal->minFrame = 1; - - if( rc!=SQLITE_OK ){ - sqlite3WalEndReadTransaction(pWal); - } - } - } - - /* Release the shared CKPT lock obtained above. */ - if( ckptLock ){ - assert( pSnapshot ); - walUnlockShared(pWal, WAL_CKPT_LOCK); - } -#endif - return rc; -} - -/* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that its cache is stale and -** needs to be flushed. -*/ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ - int rc; - SEH_TRY { - rc = walBeginReadTransaction(pWal, pChanged); - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - -/* -** Finish with a read transaction. All this does is release the -** read-lock. -*/ -SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ -#ifndef SQLITE_ENABLE_SETLK_TIMEOUT - assert( pWal->writeLock==0 || pWal->readLock<0 ); -#endif - if( pWal->readLock>=0 ){ - sqlite3WalEndWriteTransaction(pWal); - walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->readLock = -1; - } -} - -/* -** Search the wal file for page pgno. If found, set *piRead to the frame that -** contains the page. Otherwise, if pgno is not in the wal file, set *piRead -** to zero. -** -** Return SQLITE_OK if successful, or an error code if an error occurs. If an -** error does occur, the final value of *piRead is undefined. -*/ -static int walFindFrame( - Wal *pWal, /* WAL handle */ - Pgno pgno, /* Database page number to read data for */ - u32 *piRead /* OUT: Frame number (or zero) */ -){ - u32 iRead = 0; /* If !=0, WAL frame to return data from */ - u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ - int iHash; /* Used to loop through N hash tables */ - int iMinHash; - - /* This routine is only be called from within a read transaction. */ - assert( pWal->readLock>=0 || pWal->lockError ); - - /* If the "last page" field of the wal-index header snapshot is 0, then - ** no data will be read from the wal under any circumstances. Return early - ** in this case as an optimization. Likewise, if pWal->readLock==0, - ** then the WAL is ignored by the reader so return early, as if the - ** WAL were empty. - */ - if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){ - *piRead = 0; - return SQLITE_OK; - } - - /* Search the hash table or tables for an entry matching page number - ** pgno. Each iteration of the following for() loop searches one - ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames). - ** - ** This code might run concurrently to the code in walIndexAppend() - ** that adds entries to the wal-index (and possibly to this hash - ** table). This means the value just read from the hash - ** slot (aHash[iKey]) may have been added before or after the - ** current read transaction was opened. Values added after the - ** read transaction was opened may have been written incorrectly - - ** i.e. these slots may contain garbage data. However, we assume - ** that any slots written before the current read transaction was - ** opened remain unmodified. - ** - ** For the reasons above, the if(...) condition featured in the inner - ** loop of the following block is more stringent that would be required - ** if we had exclusive access to the hash-table: - ** - ** (aPgno[iFrame]==pgno): - ** This condition filters out normal hash-table collisions. - ** - ** (iFrame<=iLast): - ** This condition filters out entries that were added to the hash - ** table after the current read-transaction had started. - */ - iMinHash = walFramePage(pWal->minFrame); - for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ - WalHashLoc sLoc; /* Hash table location */ - int iKey; /* Hash slot index */ - int nCollide; /* Number of hash collisions remaining */ - int rc; /* Error code */ - u32 iH; - - rc = walHashGet(pWal, iHash, &sLoc); - if( rc!=SQLITE_OK ){ - return rc; - } - nCollide = HASHTABLE_NSLOT; - iKey = walHash(pgno); - SEH_INJECT_FAULT; - while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ - u32 iFrame = iH + sLoc.iZero; - if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ - assert( iFrame>iRead || CORRUPT_DB ); - iRead = iFrame; - } - if( (nCollide--)==0 ){ - *piRead = 0; - return SQLITE_CORRUPT_BKPT; - } - iKey = walNextHash(iKey); - } - if( iRead ) break; - } - -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - /* If expensive assert() statements are available, do a linear search - ** of the wal-index file content. Make sure the results agree with the - ** result obtained using the hash indexes above. */ - { - u32 iRead2 = 0; - u32 iTest; - assert( pWal->bShmUnreliable || pWal->minFrame>0 ); - for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){ - if( walFramePgno(pWal, iTest)==pgno ){ - iRead2 = iTest; - break; - } - } - assert( iRead==iRead2 ); - } -#endif - - *piRead = iRead; - return SQLITE_OK; -} - -/* -** Search the wal file for page pgno. If found, set *piRead to the frame that -** contains the page. Otherwise, if pgno is not in the wal file, set *piRead -** to zero. -** -** Return SQLITE_OK if successful, or an error code if an error occurs. If an -** error does occur, the final value of *piRead is undefined. -** -** The difference between this function and walFindFrame() is that this -** function wraps walFindFrame() in an SEH_TRY{...} block. -*/ -SQLITE_PRIVATE int sqlite3WalFindFrame( - Wal *pWal, /* WAL handle */ - Pgno pgno, /* Database page number to read data for */ - u32 *piRead /* OUT: Frame number (or zero) */ -){ - int rc; - SEH_TRY { - rc = walFindFrame(pWal, pgno, piRead); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - return rc; -} - -/* -** Read the contents of frame iRead from the wal file into buffer pOut -** (which is nOut bytes in size). Return SQLITE_OK if successful, or an -** error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3WalReadFrame( - Wal *pWal, /* WAL handle */ - u32 iRead, /* Frame to read */ - int nOut, /* Size of buffer pOut in bytes */ - u8 *pOut /* Buffer to write page data to */ -){ - int sz; - i64 iOffset; - sz = pWal->hdr.szPage; - sz = (sz&0xfe00) + ((sz&0x0001)<<16); - testcase( sz<=32768 ); - testcase( sz>=65536 ); - iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ - return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); -} - -/* -** Return the size of the database in pages (or zero, if unknown). -*/ -SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ - if( pWal && ALWAYS(pWal->readLock>=0) ){ - return pWal->hdr.nPage; - } - return 0; -} - - -/* -** This function starts a write transaction on the WAL. -** -** A read transaction must have already been started by a prior call -** to sqlite3WalBeginReadTransaction(). -** -** If another thread or process has written into the database since -** the read transaction was started, then it is not possible for this -** thread to write as doing so would cause a fork. So this routine -** returns SQLITE_BUSY in that case and no write transaction is started. -** -** There can only be a single writer active at a time. -*/ -SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ - int rc; - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If the write-lock is already held, then it was obtained before the - ** read-transaction was even opened, making this call a no-op. - ** Return early. */ - if( pWal->writeLock ){ - assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) ); - return SQLITE_OK; - } -#endif - - /* Cannot start a write transaction without first holding a read - ** transaction. */ - assert( pWal->readLock>=0 ); - assert( pWal->writeLock==0 && pWal->iReCksum==0 ); - - if( pWal->readOnly ){ - return SQLITE_READONLY; - } - - /* Only one writer allowed at a time. Get the write lock. Return - ** SQLITE_BUSY if unable. - */ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc ){ - return rc; - } - pWal->writeLock = 1; - - /* If another connection has written to the database file since the - ** time the read transaction on this connection was started, then - ** the write is disallowed. - */ - SEH_TRY { - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ - rc = SQLITE_BUSY_SNAPSHOT; - } - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - - if( rc!=SQLITE_OK ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - } - return rc; -} - -/* -** End a write transaction. The commit has already been done. This -** routine merely releases the lock. -*/ -SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){ - if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - pWal->iReCksum = 0; - pWal->truncateOnCommit = 0; - } - return SQLITE_OK; -} - -/* -** If any data has been written (but not committed) to the log file, this -** function moves the write-pointer back to the start of the transaction. -** -** Additionally, the callback function is invoked for each frame written -** to the WAL since the start of the transaction. If the callback returns -** other than SQLITE_OK, it is not invoked again and the error code is -** returned to the caller. -** -** Otherwise, if the callback function does not return an error, this -** function returns SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ - int rc = SQLITE_OK; - if( ALWAYS(pWal->writeLock) ){ - Pgno iMax = pWal->hdr.mxFrame; - Pgno iFrame; - - SEH_TRY { - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. - */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); - } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - pWal->iReCksum = 0; - } - return rc; -} - -/* -** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 -** values. This function populates the array with values required to -** "rollback" the write position of the WAL handle back to the current -** point in the event of a savepoint rollback (via WalSavepointUndo()). -*/ -SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){ - assert( pWal->writeLock ); - aWalData[0] = pWal->hdr.mxFrame; - aWalData[1] = pWal->hdr.aFrameCksum[0]; - aWalData[2] = pWal->hdr.aFrameCksum[1]; - aWalData[3] = pWal->nCkpt; -} - -/* -** Move the write position of the WAL back to the point identified by -** the values in the aWalData[] array. aWalData must point to an array -** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated -** by a call to WalSavepoint(). -*/ -SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ - int rc = SQLITE_OK; - - assert( pWal->writeLock ); - assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame ); - - if( aWalData[3]!=pWal->nCkpt ){ - /* This savepoint was opened immediately after the write-transaction - ** was started. Right after that, the writer decided to wrap around - ** to the start of the log. Update the savepoint values to match. - */ - aWalData[0] = 0; - aWalData[3] = pWal->nCkpt; - } - - if( aWalData[0]hdr.mxFrame ){ - pWal->hdr.mxFrame = aWalData[0]; - pWal->hdr.aFrameCksum[0] = aWalData[1]; - pWal->hdr.aFrameCksum[1] = aWalData[2]; - SEH_TRY { - walCleanupHash(pWal); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - if( pWal->iReCksum>pWal->hdr.mxFrame ){ - pWal->iReCksum = 0; - } - } - - return rc; -} - -/* -** This function is called just before writing a set of frames to the log -** file (see sqlite3WalFrames()). It checks to see if, instead of appending -** to the current log file, it is possible to overwrite the start of the -** existing log file with the new frames (i.e. "reset" the log). If so, -** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left -** unchanged. -** -** SQLITE_OK is returned if no error is encountered (regardless of whether -** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned -** if an error occurs. -*/ -static int walRestartLog(Wal *pWal){ - int rc = SQLITE_OK; - int cnt; - - if( pWal->readLock==0 ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - assert( pInfo->nBackfill==pWal->hdr.mxFrame ); - if( pInfo->nBackfill>0 ){ - u32 salt1; - sqlite3_randomness(4, &salt1); - rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - if( rc==SQLITE_OK ){ - /* If all readers are using WAL_READ_LOCK(0) (in other words if no - ** readers are currently using the WAL), then the transactions - ** frames will overwrite the start of the existing log. Update the - ** wal-index header to reflect this. - ** - ** In theory it would be Ok to update the cache of the header only - ** at this point. But updating the actual wal-index header is also - ** safe and means there is no special case for sqlite3WalUndo() - ** to handle if this transaction is rolled back. */ - walRestartHdr(pWal, salt1); - walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - walUnlockShared(pWal, WAL_READ_LOCK(0)); - pWal->readLock = -1; - cnt = 0; - do{ - int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, &cnt); - }while( rc==WAL_RETRY ); - assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ - testcase( (rc&0xff)==SQLITE_IOERR ); - testcase( rc==SQLITE_PROTOCOL ); - testcase( rc==SQLITE_OK ); - } - return rc; -} - -/* -** Information about the current state of the WAL file and where -** the next fsync should occur - passed from sqlite3WalFrames() into -** walWriteToLog(). -*/ -typedef struct WalWriter { - Wal *pWal; /* The complete WAL information */ - sqlite3_file *pFd; /* The WAL file to which we write */ - sqlite3_int64 iSyncPoint; /* Fsync at this offset */ - int syncFlags; /* Flags for the fsync */ - int szPage; /* Size of one page */ -} WalWriter; - -/* -** Write iAmt bytes of content into the WAL file beginning at iOffset. -** Do a sync when crossing the p->iSyncPoint boundary. -** -** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt, -** first write the part before iSyncPoint, then sync, then write the -** rest. -*/ -static int walWriteToLog( - WalWriter *p, /* WAL to write to */ - void *pContent, /* Content to be written */ - int iAmt, /* Number of bytes to write */ - sqlite3_int64 iOffset /* Start writing at this offset */ -){ - int rc; - if( iOffsetiSyncPoint && iOffset+iAmt>=p->iSyncPoint ){ - int iFirstAmt = (int)(p->iSyncPoint - iOffset); - rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset); - if( rc ) return rc; - iOffset += iFirstAmt; - iAmt -= iFirstAmt; - pContent = (void*)(iFirstAmt + (char*)pContent); - assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 ); - rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags)); - if( iAmt==0 || rc ) return rc; - } - rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); - return rc; -} - -/* -** Write out a single frame of the WAL -*/ -static int walWriteOneFrame( - WalWriter *p, /* Where to write the frame */ - PgHdr *pPage, /* The page of the frame to be written */ - int nTruncate, /* The commit flag. Usually 0. >0 for commit */ - sqlite3_int64 iOffset /* Byte offset at which to write */ -){ - int rc; /* Result code from subfunctions */ - void *pData; /* Data actually written */ - u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ -#if defined(SQLITE_HAS_CODEC) - if( (pData = sqlcipherPagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT; -#else - pData = pPage->pData; -#endif - walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); - rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); - if( rc ) return rc; - /* Write the page data */ - rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); - return rc; -} - -/* -** This function is called as part of committing a transaction within which -** one or more frames have been overwritten. It updates the checksums for -** all frames written to the wal file by the current transaction starting -** with the earliest to have been overwritten. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int walRewriteChecksums(Wal *pWal, u32 iLast){ - const int szPage = pWal->szPage;/* Database page size */ - int rc = SQLITE_OK; /* Return code */ - u8 *aBuf; /* Buffer to load data from wal file into */ - u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */ - u32 iRead; /* Next frame to read from wal file */ - i64 iCksumOff; - - aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE); - if( aBuf==0 ) return SQLITE_NOMEM_BKPT; - - /* Find the checksum values to use as input for the recalculating the - ** first checksum. If the first frame is frame 1 (implying that the current - ** transaction restarted the wal file), these values must be read from the - ** wal-file header. Otherwise, read them from the frame header of the - ** previous frame. */ - assert( pWal->iReCksum>0 ); - if( pWal->iReCksum==1 ){ - iCksumOff = 24; - }else{ - iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16; - } - rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff); - pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf); - pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]); - - iRead = pWal->iReCksum; - pWal->iReCksum = 0; - for(; rc==SQLITE_OK && iRead<=iLast; iRead++){ - i64 iOff = walFrameOffset(iRead, szPage); - rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff); - if( rc==SQLITE_OK ){ - u32 iPgno, nDbSize; - iPgno = sqlite3Get4byte(aBuf); - nDbSize = sqlite3Get4byte(&aBuf[4]); - - walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame); - rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff); - } - } - - sqlite3_free(aBuf); - return rc; -} - -/* -** Write a set of frames to the log. The caller must hold the write-lock -** on the log file (obtained using sqlite3WalBeginWriteTransaction()). -*/ -static int walFrames( - Wal *pWal, /* Wal handle to write to */ - int szPage, /* Database page-size in bytes */ - PgHdr *pList, /* List of dirty pages to write */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit, /* True if this is a commit */ - int sync_flags /* Flags to pass to OsSync() (or 0) */ -){ - int rc; /* Used to catch return codes */ - u32 iFrame; /* Next frame address */ - PgHdr *p; /* Iterator to run through pList with. */ - PgHdr *pLast = 0; /* Last frame in list */ - int nExtra = 0; /* Number of extra copies of last page */ - int szFrame; /* The size of a single frame */ - i64 iOffset; /* Next byte to write in WAL file */ - WalWriter w; /* The writer */ - u32 iFirst = 0; /* First frame that may be overwritten */ - WalIndexHdr *pLive; /* Pointer to shared header */ - - assert( pList ); - assert( pWal->writeLock ); - - /* If this frame set completes a transaction, then nTruncate>0. If - ** nTruncate==0 then this frame set does not complete the transaction. */ - assert( (isCommit!=0)==(nTruncate!=0) ); - -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) - { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){} - WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n", - pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill")); - } -#endif - - pLive = (WalIndexHdr*)walIndexHdr(pWal); - if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){ - iFirst = pLive->mxFrame+1; - } - - /* See if it is possible to write these frames into the start of the - ** log file, instead of appending to it at pWal->hdr.mxFrame. - */ - if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ - return rc; - } - - /* If this is the first frame written into the log, write the WAL - ** header to the start of the WAL file. See comments at the top of - ** this source file for a description of the WAL header format. - */ - iFrame = pWal->hdr.mxFrame; - if( iFrame==0 ){ - u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */ - u32 aCksum[2]; /* Checksum for wal-header */ - - sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN)); - sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION); - sqlite3Put4byte(&aWalHdr[8], szPage); - sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); - if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt); - memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); - walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); - sqlite3Put4byte(&aWalHdr[24], aCksum[0]); - sqlite3Put4byte(&aWalHdr[28], aCksum[1]); - - pWal->szPage = szPage; - pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; - pWal->hdr.aFrameCksum[0] = aCksum[0]; - pWal->hdr.aFrameCksum[1] = aCksum[1]; - pWal->truncateOnCommit = 1; - - rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); - WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless - ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise - ** an out-of-order write following a WAL restart could result in - ** database corruption. See the ticket: - ** - ** https://sqlite.org/src/info/ff5be73dee - */ - if( pWal->syncHeader ){ - rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); - if( rc ) return rc; - } - } - if( (int)pWal->szPage!=szPage ){ - return SQLITE_CORRUPT_BKPT; /* TH3 test case: cov1/corrupt155.test */ - } - - /* Setup information needed to write frames into the WAL */ - w.pWal = pWal; - w.pFd = pWal->pWalFd; - w.iSyncPoint = 0; - w.syncFlags = sync_flags; - w.szPage = szPage; - iOffset = walFrameOffset(iFrame+1, szPage); - szFrame = szPage + WAL_FRAME_HDRSIZE; - - /* Write all frames into the log file exactly once */ - for(p=pList; p; p=p->pDirty){ - int nDbSize; /* 0 normally. Positive == commit flag */ - - /* Check if this page has already been written into the wal file by - ** the current transaction. If so, overwrite the existing frame and - ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that - ** checksums must be recomputed when the transaction is committed. */ - if( iFirst && (p->pDirty || isCommit==0) ){ - u32 iWrite = 0; - VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); - assert( rc==SQLITE_OK || iWrite==0 ); - if( iWrite>=iFirst ){ - i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; - void *pData; - if( pWal->iReCksum==0 || iWriteiReCksum ){ - pWal->iReCksum = iWrite; - } -#if defined(SQLITE_HAS_CODEC) - if( (pData = sqlcipherPagerCodec(p))==0 ) return SQLITE_NOMEM; -#else - pData = p->pData; -#endif - rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); - if( rc ) return rc; - p->flags &= ~PGHDR_WAL_APPEND; - continue; - } - } - - iFrame++; - assert( iOffset==walFrameOffset(iFrame, szPage) ); - nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; - rc = walWriteOneFrame(&w, p, nDbSize, iOffset); - if( rc ) return rc; - pLast = p; - iOffset += szFrame; - p->flags |= PGHDR_WAL_APPEND; - } - - /* Recalculate checksums within the wal file if required. */ - if( isCommit && pWal->iReCksum ){ - rc = walRewriteChecksums(pWal, iFrame); - if( rc ) return rc; - } - - /* If this is the end of a transaction, then we might need to pad - ** the transaction and/or sync the WAL file. - ** - ** Padding and syncing only occur if this set of frames complete a - ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL - ** or synchronous==OFF, then no padding or syncing are needed. - ** - ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not - ** needed and only the sync is done. If padding is needed, then the - ** final frame is repeated (with its commit mark) until the next sector - ** boundary is crossed. Only the part of the WAL prior to the last - ** sector boundary is synced; the part of the last frame that extends - ** past the sector boundary is written after the sync. - */ - if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){ - int bSync = 1; - if( pWal->padToSectorBoundary ){ - int sectorSize = sqlite3SectorSize(pWal->pWalFd); - w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; - bSync = (w.iSyncPoint==iOffset); - testcase( bSync ); - while( iOffsettruncateOnCommit && pWal->mxWalSize>=0 ){ - i64 sz = pWal->mxWalSize; - if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){ - sz = walFrameOffset(iFrame+nExtra+1, szPage); - } - walLimitSize(pWal, sz); - pWal->truncateOnCommit = 0; - } - - /* Append data to the wal-index. It is not necessary to lock the - ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index - ** guarantees that there are no other writers, and no data that may - ** be in use by existing readers is being overwritten. - */ - iFrame = pWal->hdr.mxFrame; - for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){ - if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue; - iFrame++; - rc = walIndexAppend(pWal, iFrame, p->pgno); - } - assert( pLast!=0 || nExtra==0 ); - while( rc==SQLITE_OK && nExtra>0 ){ - iFrame++; - nExtra--; - rc = walIndexAppend(pWal, iFrame, pLast->pgno); - } - - if( rc==SQLITE_OK ){ - /* Update the private copy of the header. */ - pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - pWal->hdr.mxFrame = iFrame; - if( isCommit ){ - pWal->hdr.iChange++; - pWal->hdr.nPage = nTruncate; - } - /* If this is a commit, update the wal-index header too. */ - if( isCommit ){ - walIndexWriteHdr(pWal); - pWal->iCallback = iFrame; - } - } - - WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); - return rc; -} - -/* -** Write a set of frames to the log. The caller must hold the write-lock -** on the log file (obtained using sqlite3WalBeginWriteTransaction()). -** -** The difference between this function and walFrames() is that this -** function wraps walFrames() in an SEH_TRY{...} block. -*/ -SQLITE_PRIVATE int sqlite3WalFrames( - Wal *pWal, /* Wal handle to write to */ - int szPage, /* Database page-size in bytes */ - PgHdr *pList, /* List of dirty pages to write */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit, /* True if this is a commit */ - int sync_flags /* Flags to pass to OsSync() (or 0) */ -){ - int rc; - SEH_TRY { - rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - -/* -** This routine is called to implement sqlite3_wal_checkpoint() and -** related interfaces. -** -** Obtain a CHECKPOINT lock and then backfill as much information as -** we can from WAL into the database. -** -** If parameter xBusy is not NULL, it is a pointer to a busy-handler -** callback. In this case this function runs a blocking checkpoint. -*/ -SQLITE_PRIVATE int sqlite3WalCheckpoint( - Wal *pWal, /* Wal connection */ - sqlite3 *db, /* Check this handle's interrupt flag */ - int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags to sync db file with (or 0) */ - int nBuf, /* Size of temporary buffer */ - u8 *zBuf, /* Temporary buffer to use */ - int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ -){ - int rc; /* Return code */ - int isChanged = 0; /* True if a new wal-index header is loaded */ - int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ - int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ - - assert( pWal->ckptLock==0 ); - assert( pWal->writeLock==0 ); - - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked - ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); - - if( pWal->readOnly ) return SQLITE_READONLY; - WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - - /* Enable blocking locks, if possible. */ - sqlite3WalDb(pWal, db); - if( xBusy2 ) (void)walEnableBlocking(pWal); - - /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive - ** "checkpoint" lock on the database file. - ** EVIDENCE-OF: R-10421-19736 If any other process is running a - ** checkpoint operation at the same time, the lock cannot be obtained and - ** SQLITE_BUSY is returned. - ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, - ** it will not be invoked in this case. - */ - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - testcase( rc==SQLITE_BUSY ); - testcase( rc!=SQLITE_OK && xBusy2!=0 ); - if( rc==SQLITE_OK ){ - pWal->ckptLock = 1; - - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and - ** TRUNCATE modes also obtain the exclusive "writer" lock on the database - ** file. - ** - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained - ** immediately, and a busy-handler is configured, it is invoked and the - ** writer lock retried until either the busy-handler returns 0 or the - ** lock is successfully obtained. - */ - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - }else if( rc==SQLITE_BUSY ){ - eMode2 = SQLITE_CHECKPOINT_PASSIVE; - xBusy2 = 0; - rc = SQLITE_OK; - } - } - } - - - /* Read the wal-index header. */ - SEH_TRY { - if( rc==SQLITE_OK ){ - /* For a passive checkpoint, do not re-enable blocking locks after - ** reading the wal-index header. A passive checkpoint should not block - ** or invoke the busy handler. The only lock such a checkpoint may - ** attempt to obtain is a lock on a read-slot, and it should give up - ** immediately and do a partial checkpoint if it cannot obtain it. */ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); - } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - SEH_INJECT_FAULT; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); - } - } - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - - if( isChanged ){ - /* If a new wal-index header was loaded before the checkpoint was - ** performed, then the pager-cache associated with pWal is now - ** out of date. So zero the cached wal-index header to ensure that - ** next time the pager opens a snapshot on this database it knows that - ** the cache needs to be reset. - */ - memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); - } - - walDisableBlocking(pWal); - sqlite3WalDb(pWal, 0); - - /* Release the locks. */ - sqlite3WalEndWriteTransaction(pWal); - if( pWal->ckptLock ){ - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - pWal->ckptLock = 0; - } - WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; -#endif - return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); -} - -/* Return the value to pass to a sqlite3_wal_hook callback, the -** number of frames in the WAL at the point of the last commit since -** sqlite3WalCallback() was called. If no commits have occurred since -** the last call, then return 0. -*/ -SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){ - u32 ret = 0; - if( pWal ){ - ret = pWal->iCallback; - pWal->iCallback = 0; - } - return (int)ret; -} - -/* -** This function is called to change the WAL subsystem into or out -** of locking_mode=EXCLUSIVE. -** -** If op is zero, then attempt to change from locking_mode=EXCLUSIVE -** into locking_mode=NORMAL. This means that we must acquire a lock -** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL -** or if the acquisition of the lock fails, then return 0. If the -** transition out of exclusive-mode is successful, return 1. This -** operation must occur while the pager is still holding the exclusive -** lock on the main database file. -** -** If op is one, then change from locking_mode=NORMAL into -** locking_mode=EXCLUSIVE. This means that the pWal->readLock must -** be released. Return 1 if the transition is made and 0 if the -** WAL is already in exclusive-locking mode - meaning that this -** routine is a no-op. The pager must already hold the exclusive lock -** on the main database file before invoking this operation. -** -** If op is negative, then do a dry-run of the op==1 case but do -** not actually change anything. The pager uses this to see if it -** should acquire the database exclusive lock prior to invoking -** the op==1 case. -*/ -SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ - int rc; - assert( pWal->writeLock==0 ); - assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 ); - - /* pWal->readLock is usually set, but might be -1 if there was a - ** prior error while attempting to acquire are read-lock. This cannot - ** happen if the connection is actually in exclusive mode (as no xShmLock - ** locks are taken in this case). Nor should the pager attempt to - ** upgrade to exclusive-mode following such an error. - */ -#ifndef SQLITE_USE_SEH - assert( pWal->readLock>=0 || pWal->lockError ); -#endif - assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); - - if( op==0 ){ - if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ - pWal->exclusiveMode = WAL_NORMAL_MODE; - if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; - } - rc = pWal->exclusiveMode==WAL_NORMAL_MODE; - }else{ - /* Already in locking_mode=NORMAL */ - rc = 0; - } - }else if( op>0 ){ - assert( pWal->exclusiveMode==WAL_NORMAL_MODE ); - assert( pWal->readLock>=0 ); - walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; - rc = 1; - }else{ - rc = pWal->exclusiveMode==WAL_NORMAL_MODE; - } - return rc; -} - -/* -** Return true if the argument is non-NULL and the WAL module is using -** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. -*/ -SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ - return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); -} - -#ifdef SQLITE_ENABLE_SNAPSHOT -/* Create a snapshot object. The content of a snapshot is opaque to -** every other subsystem, so the WAL module can put whatever it needs -** in the object. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ - int rc = SQLITE_OK; - WalIndexHdr *pRet; - static const u32 aZero[4] = { 0, 0, 0, 0 }; - - assert( pWal->readLock>=0 && pWal->writeLock==0 ); - - if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){ - *ppSnapshot = 0; - return SQLITE_ERROR; - } - pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); - if( pRet==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); - *ppSnapshot = (sqlite3_snapshot*)pRet; - } - - return rc; -} - -/* Try to open on pSnapshot when the next read-transaction starts -*/ -SQLITE_PRIVATE void sqlite3WalSnapshotOpen( - Wal *pWal, - sqlite3_snapshot *pSnapshot -){ - if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){ - /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In - ** this case set the bGetSnapshot flag so that if the call to - ** sqlite3_snapshot_get() is about to read transaction on this wal - ** file, it does not take read-lock 0 if the wal file has been completely - ** checkpointed. Taking read-lock 0 would work, but then it would be - ** possible for a subsequent writer to destroy the snapshot even while - ** this connection is holding its read-transaction open. This is contrary - ** to user expectations, so we avoid it by not taking read-lock 0. */ - pWal->bGetSnapshot = 1; - }else{ - pWal->pSnapshot = (WalIndexHdr*)pSnapshot; - pWal->bGetSnapshot = 0; - } -} - -/* -** Return a +ve value if snapshot p1 is newer than p2. A -ve value if -** p1 is older than p2 and zero if p1 and p2 are the same snapshot. -*/ -SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ - WalIndexHdr *pHdr1 = (WalIndexHdr*)p1; - WalIndexHdr *pHdr2 = (WalIndexHdr*)p2; - - /* aSalt[0] is a copy of the value stored in the wal file header. It - ** is incremented each time the wal file is restarted. */ - if( pHdr1->aSalt[0]aSalt[0] ) return -1; - if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1; - if( pHdr1->mxFramemxFrame ) return -1; - if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1; - return 0; -} - -/* -** The caller currently has a read transaction open on the database. -** This function takes a SHARED lock on the CHECKPOINTER slot and then -** checks if the snapshot passed as the second argument is still -** available. If so, SQLITE_OK is returned. -** -** If the snapshot is not available, SQLITE_ERROR is returned. Or, if -** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error -** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER -** lock is released before returning. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ - int rc; - SEH_TRY { - rc = walLockShared(pWal, WAL_CKPT_LOCK); - if( rc==SQLITE_OK ){ - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - || pNew->mxFramenBackfillAttempted - ){ - rc = SQLITE_ERROR_SNAPSHOT; - walUnlockShared(pWal, WAL_CKPT_LOCK); - } - } - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - -/* -** Release a lock obtained by an earlier successful call to -** sqlite3WalSnapshotCheck(). -*/ -SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal){ - assert( pWal ); - walUnlockShared(pWal, WAL_CKPT_LOCK); -} - - -#endif /* SQLITE_ENABLE_SNAPSHOT */ - -#ifdef SQLITE_ENABLE_ZIPVFS -/* -** If the argument is not NULL, it points to a Wal object that holds a -** read-lock. This function returns the database page-size if it is known, -** or zero if it is not (or if pWal is NULL). -*/ -SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ - assert( pWal==0 || pWal->readLock>=0 ); - return (pWal ? pWal->szPage : 0); -} -#endif - -/* Return the sqlite3_file object for the WAL file -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ - return pWal->pWalFd; -} - -#endif /* #ifndef SQLITE_OMIT_WAL */ - -/************** End of wal.c *************************************************/ -/************** Begin file btmutex.c *****************************************/ -/* -** 2007 August 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 code used to implement mutexes on Btree objects. -** This code really belongs in btree.c. But btree.c is getting too -** big and we want to break it down some. This packaged seemed like -** a good breakout. -*/ -/************** 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 The size of the database in pages -** 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 bits 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 -** 0x81 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 allocates 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 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 sqlite3.mutex. -*/ -struct Btree { - 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 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 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 */ - 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 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 sqlite3BtreeSchema() */ - void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ - 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 - -/* -** Maximum amount of storage local to a database page, regardless of -** page size. -*/ -#define BT_MAX_LOCAL 65501 /* 65536 - 35 */ - -/* -** 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 sqlite3BtreeNext() is a no-op if skipNext>0 and -** 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 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 - ** 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 to 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 sqlite3BtreeNext() or sqlite3BtreePrevious() -** operation should be a no-op. -** -** CURSOR_REQUIRESEEK: -** The table that this cursor was opened on still exists, but has been -** modified since the cursor was last used. The cursor position is saved -** 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) (pBt->autoVacuum) -#else -#define ISAUTOVACUUM(pBt) 0 -#endif - - -/* -** This structure is passed around through all the PRAGMA integrity_check -** 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 nCkPage; /* Pages in the database. 0 for partial check */ - int mxErr; /* Stop accumulating errors when this reaches zero */ - int nErr; /* Number of messages written to zErrMsg so far */ - int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */ - u32 nStep; /* Number of steps into the integrity_check process */ - const char *zPfx; /* Error message prefix */ - Pgno v0; /* Value for first %u substitution in zPfx (root page) */ - Pgno v1; /* Value for second %u substitution in zPfx (current pg) */ - int v2; /* Value for third %d substitution in zPfx */ - StrAccum errMsg; /* Accumulate the error message text here */ - u32 *heap; /* Min-heap used for analyzing cell coverage */ - sqlite3 *db; /* Database connection running the check */ - i64 nRow; /* Number of rows visited in current tree */ -}; - -/* -** 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 sqlite3Get4byte -#define put4byte sqlite3Put4byte - -/* -** get2byteAligned(), unlike get2byte(), requires that its argument point to a -** two-byte aligned address. get2byteAligned() 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 - -/* -** Obtain the BtShared mutex associated with B-Tree handle p. Also, -** set BtShared.db to the database handle associated with p and the -** p->locked boolean to true. -*/ -static void lockBtreeMutex(Btree *p){ - assert( p->locked==0 ); - assert( sqlite3_mutex_notheld(p->pBt->mutex) ); - assert( sqlite3_mutex_held(p->db->mutex) ); - - sqlite3_mutex_enter(p->pBt->mutex); - p->pBt->db = p->db; - p->locked = 1; -} - -/* -** Release the BtShared mutex associated with B-Tree handle p and -** clear the p->locked boolean. -*/ -static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ - BtShared *pBt = p->pBt; - assert( p->locked==1 ); - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( sqlite3_mutex_held(p->db->mutex) ); - assert( p->db==pBt->db ); - - sqlite3_mutex_leave(pBt->mutex); - p->locked = 0; -} - -/* Forward reference */ -static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); - -/* -** Enter a mutex on the given BTree object. -** -** If the object is not sharable, then no mutex is ever required -** and this routine is a no-op. The underlying mutex is non-recursive. -** But we keep a reference count in Btree.wantToLock so the behavior -** of this interface is recursive. -** -** To avoid deadlocks, multiple Btrees are locked in the same order -** by all database connections. The p->pNext is a list of other -** Btrees belonging to the same database connection as the p Btree -** which need to be locked after p. If we cannot get a lock on -** p, then first unlock all of the others on p->pNext, then wait -** for the lock to become available on p, then relock all of the -** subsequent Btrees that desire a lock. -*/ -SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ - /* Some basic sanity checking on the Btree. The list of Btrees - ** connected by pNext and pPrev should be in sorted order by - ** Btree.pBt value. All elements of the list should belong to - ** the same connection. Only shared Btrees are on the list. */ - assert( p->pNext==0 || p->pNext->pBt>p->pBt ); - assert( p->pPrev==0 || p->pPrev->pBtpBt ); - assert( p->pNext==0 || p->pNext->db==p->db ); - assert( p->pPrev==0 || p->pPrev->db==p->db ); - assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); - - /* Check for locking consistency */ - assert( !p->locked || p->wantToLock>0 ); - assert( p->sharable || p->wantToLock==0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - /* Unless the database is sharable and unlocked, then BtShared.db - ** should already be set correctly. */ - assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); - - if( !p->sharable ) return; - p->wantToLock++; - if( p->locked ) return; - btreeLockCarefully(p); -} - -/* This is a helper function for sqlite3BtreeLock(). By moving -** complex, but seldom used logic, out of sqlite3BtreeLock() and -** into this routine, we avoid unnecessary stack pointer changes -** and thus help the sqlite3BtreeLock() routine to run much faster -** in the common case. -*/ -static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ - Btree *pLater; - - /* In most cases, we should be able to acquire the lock we - ** want without having to go through the ascending lock - ** procedure that follows. Just be sure not to block. - */ - if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ - p->pBt->db = p->db; - p->locked = 1; - return; - } - - /* To avoid deadlock, first release all locks with a larger - ** BtShared address. Then acquire our lock. Then reacquire - ** the other BtShared locks that we used to hold in ascending - ** order. - */ - for(pLater=p->pNext; pLater; pLater=pLater->pNext){ - assert( pLater->sharable ); - assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); - assert( !pLater->locked || pLater->wantToLock>0 ); - if( pLater->locked ){ - unlockBtreeMutex(pLater); - } - } - lockBtreeMutex(p); - for(pLater=p->pNext; pLater; pLater=pLater->pNext){ - if( pLater->wantToLock ){ - lockBtreeMutex(pLater); - } - } -} - - -/* -** Exit the recursive mutex on a Btree. -*/ -SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){ - assert( sqlite3_mutex_held(p->db->mutex) ); - if( p->sharable ){ - assert( p->wantToLock>0 ); - p->wantToLock--; - if( p->wantToLock==0 ){ - unlockBtreeMutex(p); - } - } -} - -#ifndef NDEBUG -/* -** Return true if the BtShared mutex is held on the btree, or if the -** B-Tree is not marked as sharable. -** -** This routine is used only from within assert() statements. -*/ -SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ - assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); - assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); - assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) ); - assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); - - return (p->sharable==0 || p->locked); -} -#endif - - -/* -** Enter the mutex on every Btree associated with a database -** connection. This is needed (for example) prior to parsing -** a statement since we will be comparing table and column names -** against all schemas and we do not want those schemas being -** reset out from under us. -** -** There is a corresponding leave-all procedures. -** -** Enter the mutexes in ascending order by BtShared pointer address -** to avoid the possibility of deadlock when two threads with -** two or more btrees in common both try to lock all their btrees -** at the same instant. -*/ -static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ - int i; - u8 skipOk = 1; - Btree *p; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inDb; i++){ - p = db->aDb[i].pBt; - if( p && p->sharable ){ - sqlite3BtreeEnter(p); - skipOk = 0; - } - } - db->noSharedCache = skipOk; -} -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - if( db->noSharedCache==0 ) btreeEnterAll(db); -} -static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ - int i; - Btree *p; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inDb; i++){ - p = db->aDb[i].pBt; - if( p ) sqlite3BtreeLeave(p); - } -} -SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ - if( db->noSharedCache==0 ) btreeLeaveAll(db); -} - -#ifndef NDEBUG -/* -** Return true if the current thread holds the database connection -** mutex and all required BtShared mutexes. -** -** This routine is used inside assert() statements only. -*/ -SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ - int i; - if( !sqlite3_mutex_held(db->mutex) ){ - return 0; - } - for(i=0; inDb; i++){ - Btree *p; - p = db->aDb[i].pBt; - if( p && p->sharable && - (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ - return 0; - } - } - return 1; -} -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Return true if the correct mutexes are held for accessing the -** db->aDb[iDb].pSchema structure. The mutexes required for schema -** access are: -** -** (1) The mutex on db -** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt. -** -** If pSchema is not NULL, then iDb is computed from pSchema and -** db using sqlite3SchemaToIndex(). -*/ -SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ - Btree *p; - assert( db!=0 ); - if( db->pVfs==0 && db->nDb==0 ) return 1; - if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema); - assert( iDb>=0 && iDbnDb ); - if( !sqlite3_mutex_held(db->mutex) ) return 0; - if( iDb==1 ) return 1; - p = db->aDb[iDb].pBt; - assert( p!=0 ); - return p->sharable==0 || p->locked==1; -} -#endif /* NDEBUG */ - -#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ -/* -** The following are special cases for mutex enter routines for use -** in single threaded applications that use shared cache. Except for -** these two routines, all mutex operations are no-ops in that case and -** are null #defines in btree.h. -** -** If shared cache is disabled, then all btree mutex routines, including -** the ones below, are no-ops and are null #defines in btree.h. -*/ - -SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ - p->pBt->db = p->db; -} -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - int i; - for(i=0; inDb; i++){ - Btree *p = db->aDb[i].pBt; - if( p ){ - p->pBt->db = p->db; - } - } -} -#endif /* if SQLITE_THREADSAFE */ - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** Enter a mutex on a Btree given a cursor owned by that Btree. -** -** These entry points are used by incremental I/O only. Enter() is required -** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not -** the build is threadsafe. Leave() is only required by threadsafe builds. -*/ -SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){ - sqlite3BtreeEnter(pCur->pBtree); -} -# if SQLITE_THREADSAFE -SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){ - sqlite3BtreeLeave(pCur->pBtree); -} -# endif -#endif /* ifndef SQLITE_OMIT_INCRBLOB */ - -#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ - -/************** End of btmutex.c *********************************************/ -/************** Begin file btree.c *******************************************/ -/* -** 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. -** See the header comment on "btreeInt.h" for additional information. -** Including a description of file format and an overview of operation. -*/ -/* #include "btreeInt.h" */ - -/* -** The header string that appears at the beginning of every -** SQLite database. -*/ -static const char zMagicHeader[] = SQLITE_FILE_HEADER; - -/* -** Set this global variable to 1 to enable tracing using the TRACE -** macro. -*/ -#if 0 -int sqlite3BtreeTrace=1; /* True to enable tracing */ -# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} -#else -# define TRACE(X) -#endif - -/* -** Extract a 2-byte big-endian integer from an array of unsigned bytes. -** But if the value is zero, make it 65536. -** -** This routine is used to extract the "offset to cell content area" value -** from the header of a btree page. If the page size is 65536 and the page -** is empty, the offset should be 65536, but the 2-byte value stores zero. -** This routine makes the necessary adjustment to 65536. -*/ -#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) - -/* -** Values passed as the 5th argument to allocateBtreePage() -*/ -#define BTALLOC_ANY 0 /* Allocate any page */ -#define BTALLOC_EXACT 1 /* Allocate exact page if possible */ -#define BTALLOC_LE 2 /* Allocate any page <= the parameter */ - -/* -** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not -** defined, or 0 if it is. For example: -** -** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum); -*/ -#ifndef SQLITE_OMIT_AUTOVACUUM -#define IfNotOmitAV(expr) (expr) -#else -#define IfNotOmitAV(expr) 0 -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** A list of BtShared objects that are eligible for participation -** in shared cache. This variable has file scope during normal builds, -** but the test harness needs to access it so we make it global for -** test builds. -** -** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN. -*/ -#ifdef SQLITE_TEST -SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; -#else -static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; -#endif -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Enable or disable the shared pager and schema features. -** -** This routine has no effect on existing database connections. -** The shared cache setting effects only future calls to -** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). -*/ -SQLITE_API int sqlite3_enable_shared_cache(int enable){ - sqlite3GlobalConfig.sharedCacheEnabled = enable; - return SQLITE_OK; -} -#endif - - - -#ifdef SQLITE_OMIT_SHARED_CACHE - /* - ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(), - ** and clearAllSharedCacheTableLocks() - ** manipulate entries in the BtShared.pLock linked list used to store - ** shared-cache table level locks. If the library is compiled with the - ** shared-cache feature disabled, then there is only ever one user - ** of each BtShared structure and so this locking is not necessary. - ** So define the lock related functions as no-ops. - */ - #define querySharedCacheTableLock(a,b,c) SQLITE_OK - #define setSharedCacheTableLock(a,b,c) SQLITE_OK - #define clearAllSharedCacheTableLocks(a) - #define downgradeAllSharedCacheTableLocks(a) - #define hasSharedCacheTableLock(a,b,c,d) 1 - #define hasReadConflicts(a, b) 0 -#endif - -#ifdef SQLITE_DEBUG -/* -** Return and reset the seek counter for a Btree object. -*/ -SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ - u64 n = pBt->nSeek; - pBt->nSeek = 0; - return n; -} -#endif - -/* -** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single -** (MemPage*) as an argument. The (MemPage*) must not be NULL. -** -** If SQLITE_DEBUG is not defined, then this macro is equivalent to -** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message -** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented -** with the page number and filename associated with the (MemPage*). -*/ -#ifdef SQLITE_DEBUG -int corruptPageError(int lineno, MemPage *p){ - char *zMsg; - sqlite3BeginBenignMalloc(); - zMsg = sqlite3_mprintf("database corruption page %u of %s", - p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) - ); - sqlite3EndBenignMalloc(); - if( zMsg ){ - sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); - } - sqlite3_free(zMsg); - return SQLITE_CORRUPT_BKPT; -} -# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) -#else -# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) -#endif - -/* Default value for SHARED_LOCK_TRACE macro if shared-cache is disabled -** or if the lock tracking is disabled. This is always the value for -** release builds. -*/ -#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) /*no-op*/ - -#ifndef SQLITE_OMIT_SHARED_CACHE - -#if 0 -/* ^---- Change to 1 and recompile to enable shared-lock tracing -** for debugging purposes. -** -** Print all shared-cache locks on a BtShared. Debugging use only. -*/ -static void sharedLockTrace( - BtShared *pBt, - const char *zMsg, - int iRoot, - int eLockType -){ - BtLock *pLock; - if( iRoot>0 ){ - printf("%s-%p %u%s:", zMsg, pBt, iRoot, eLockType==READ_LOCK?"R":"W"); - }else{ - printf("%s-%p:", zMsg, pBt); - } - for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ - printf(" %p/%u%s", pLock->pBtree, pLock->iTable, - pLock->eLock==READ_LOCK ? "R" : "W"); - while( pLock->pNext && pLock->pBtree==pLock->pNext->pBtree ){ - pLock = pLock->pNext; - printf(",%u%s", pLock->iTable, pLock->eLock==READ_LOCK ? "R" : "W"); - } - } - printf("\n"); - fflush(stdout); -} -#undef SHARED_LOCK_TRACE -#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) sharedLockTrace(X,MSG,TAB,TYPE) -#endif /* Shared-lock tracing */ - -#ifdef SQLITE_DEBUG -/* -**** This function is only used as part of an assert() statement. *** -** -** Check to see if pBtree holds the required locks to read or write to the -** table with root page iRoot. Return 1 if it does and 0 if not. -** -** For example, when writing to a table with root-page iRoot via -** Btree connection pBtree: -** -** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) ); -** -** When writing to an index that resides in a sharable database, the -** caller should have first obtained a lock specifying the root page of -** the corresponding table. This makes things a bit more complicated, -** as this module treats each table as a separate structure. To determine -** the table corresponding to the index being written, this -** function has to search through the database schema. -** -** Instead of a lock on the table/index rooted at page iRoot, the caller may -** hold a write-lock on the schema table (root page 1). This is also -** acceptable. -*/ -static int hasSharedCacheTableLock( - Btree *pBtree, /* Handle that must hold lock */ - Pgno iRoot, /* Root page of b-tree */ - int isIndex, /* True if iRoot is the root of an index b-tree */ - int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */ -){ - Schema *pSchema = (Schema *)pBtree->pBt->pSchema; - Pgno iTab = 0; - BtLock *pLock; - - /* If this database is not shareable, or if the client is reading - ** and has the read-uncommitted flag set, then no lock is required. - ** Return true immediately. - */ - if( (pBtree->sharable==0) - || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit)) - ){ - return 1; - } - - /* If the client is reading or writing an index and the schema is - ** not loaded, then it is too difficult to actually check to see if - ** the correct locks are held. So do not bother - just return true. - ** This case does not come up very often anyhow. - */ - if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){ - return 1; - } - - /* Figure out the root-page that the lock should be held on. For table - ** b-trees, this is just the root page of the b-tree being read or - ** written. For index b-trees, it is the root page of the associated - ** table. */ - if( isIndex ){ - HashElem *p; - int bSeen = 0; - for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ - Index *pIdx = (Index *)sqliteHashData(p); - 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 - ** useful in that case. */ - return 1; - } - iTab = pIdx->pTable->tnum; - bSeen = 1; - } - } - }else{ - iTab = iRoot; - } - - SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType); - - /* Search for the required lock. Either a write-lock on root-page iTab, a - ** write-lock on the schema table, or (if the client is reading) a - ** read-lock on iTab will suffice. Return 1 if any of these are found. */ - for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){ - if( pLock->pBtree==pBtree - && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1)) - && pLock->eLock>=eLockType - ){ - return 1; - } - } - - /* Failed to find the required lock. */ - return 0; -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -**** This function may be used as part of assert() statements only. **** -** -** Return true if it would be illegal for pBtree to write into the -** table or index rooted at iRoot because other shared connections are -** simultaneously reading that same table or index. -** -** It is illegal for pBtree to write if some other Btree object that -** shares the same BtShared object is currently reading or writing -** the iRoot table. Except, if the other Btree object has the -** read-uncommitted flag set, then it is OK for the other object to -** have a read cursor. -** -** For example, before writing to any part of the table or index -** rooted at page iRoot, one should call: -** -** assert( !hasReadConflicts(pBtree, iRoot) ); -*/ -static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ - BtCursor *p; - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==iRoot - && p->pBtree!=pBtree - && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit) - ){ - return 1; - } - } - return 0; -} -#endif /* #ifdef SQLITE_DEBUG */ - -/* -** Query to see if Btree handle p may obtain a lock of type eLock -** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return -** SQLITE_OK if the lock may be obtained (by calling -** setSharedCacheTableLock()), or SQLITE_LOCKED if not. -*/ -static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ - BtShared *pBt = p->pBt; - BtLock *pIter; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); - assert( p->db!=0 ); - assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 ); - - /* If requesting a write-lock, then the Btree must have an open write - ** transaction on this file. And, obviously, for this to be so there - ** must be an open write transaction on the file itself. - */ - assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) ); - assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE ); - - /* This routine is a no-op if the shared-cache is not enabled */ - if( !p->sharable ){ - return SQLITE_OK; - } - - /* If some other connection is holding an exclusive lock, the - ** requested lock may not be obtained. - */ - if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){ - sqlite3ConnectionBlocked(p->db, pBt->pWriter->db); - return SQLITE_LOCKED_SHAREDCACHE; - } - - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - /* The condition (pIter->eLock!=eLock) in the following if(...) - ** statement is a simplification of: - ** - ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) - ** - ** since we know that if eLock==WRITE_LOCK, then no other connection - ** may hold a WRITE_LOCK on any table in this file (since there can - ** only be a single writer). - */ - assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK ); - assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK); - if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){ - sqlite3ConnectionBlocked(p->db, pIter->pBtree->db); - if( eLock==WRITE_LOCK ){ - assert( p==pBt->pWriter ); - pBt->btsFlags |= BTS_PENDING; - } - return SQLITE_LOCKED_SHAREDCACHE; - } - } - return SQLITE_OK; -} -#endif /* !SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Add a lock on the table with root-page iTable to the shared-btree used -** by Btree handle p. Parameter eLock must be either READ_LOCK or -** WRITE_LOCK. -** -** This function assumes the following: -** -** (a) The specified Btree object p is connected to a sharable -** database (one with the BtShared.sharable flag set), and -** -** (b) No other Btree objects hold a lock that conflicts -** with the requested lock (i.e. querySharedCacheTableLock() has -** already been called and returned SQLITE_OK). -** -** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM -** is returned if a malloc attempt fails. -*/ -static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ - BtShared *pBt = p->pBt; - BtLock *pLock = 0; - BtLock *pIter; - - SHARED_LOCK_TRACE(pBt,"setLock", iTable, eLock); - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); - assert( p->db!=0 ); - - /* A connection with the read-uncommitted flag set will never try to - ** obtain a read-lock using this function. The only read-lock obtained - ** by a connection in read-uncommitted mode is on the sqlite_schema - ** table, and that lock is obtained in BtreeBeginTrans(). */ - assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK ); - - /* This function should only be called on a sharable b-tree after it - ** has been determined that no other b-tree holds a conflicting lock. */ - assert( p->sharable ); - assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); - - /* First search the list for an existing lock on this table. */ - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - if( pIter->iTable==iTable && pIter->pBtree==p ){ - pLock = pIter; - break; - } - } - - /* If the above search did not find a BtLock struct associating Btree p - ** with table iTable, allocate one and link it into the list. - */ - if( !pLock ){ - pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); - if( !pLock ){ - return SQLITE_NOMEM_BKPT; - } - pLock->iTable = iTable; - pLock->pBtree = p; - pLock->pNext = pBt->pLock; - pBt->pLock = pLock; - } - - /* Set the BtLock.eLock variable to the maximum of the current lock - ** and the requested lock. This means if a write-lock was already held - ** and a read-lock requested, we don't incorrectly downgrade the lock. - */ - assert( WRITE_LOCK>READ_LOCK ); - if( eLock>pLock->eLock ){ - pLock->eLock = eLock; - } - - return SQLITE_OK; -} -#endif /* !SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Release all the table locks (locks obtained via calls to -** the setSharedCacheTableLock() procedure) held by Btree object p. -** -** This function assumes that Btree p has an open read or write -** transaction. If it does not, then the BTS_PENDING flag -** may be incorrectly cleared. -*/ -static void clearAllSharedCacheTableLocks(Btree *p){ - BtShared *pBt = p->pBt; - BtLock **ppIter = &pBt->pLock; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( p->sharable || 0==*ppIter ); - assert( p->inTrans>0 ); - - SHARED_LOCK_TRACE(pBt, "clearAllLocks", 0, 0); - - while( *ppIter ){ - BtLock *pLock = *ppIter; - assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree ); - assert( pLock->pBtree->inTrans>=pLock->eLock ); - if( pLock->pBtree==p ){ - *ppIter = pLock->pNext; - assert( pLock->iTable!=1 || pLock==&p->lock ); - if( pLock->iTable!=1 ){ - sqlite3_free(pLock); - } - }else{ - ppIter = &pLock->pNext; - } - } - - assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter ); - if( pBt->pWriter==p ){ - pBt->pWriter = 0; - pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); - }else if( pBt->nTransaction==2 ){ - /* This function is called when Btree p is concluding its - ** transaction. If there currently exists a writer, and p is not - ** that writer, then the number of locks held by connections other - ** than the writer must be about to drop to zero. In this case - ** set the BTS_PENDING flag to 0. - ** - ** If there is not currently a writer, then BTS_PENDING must - ** be zero already. So this next line is harmless in that case. - */ - pBt->btsFlags &= ~BTS_PENDING; - } -} - -/* -** This function changes all write-locks held by Btree p into read-locks. -*/ -static void downgradeAllSharedCacheTableLocks(Btree *p){ - BtShared *pBt = p->pBt; - - SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0); - - if( pBt->pWriter==p ){ - BtLock *pLock; - pBt->pWriter = 0; - pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); - for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ - assert( pLock->eLock==READ_LOCK || pLock->pBtree==p ); - pLock->eLock = READ_LOCK; - } - } -} - -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -static void releasePage(MemPage *pPage); /* Forward reference */ -static void releasePageOne(MemPage *pPage); /* Forward reference */ -static void releasePageNotNull(MemPage *pPage); /* Forward reference */ - -/* -***** This routine is used inside of assert() only **** -** -** Verify that the cursor holds the mutex on its BtShared -*/ -#ifdef SQLITE_DEBUG -static int cursorHoldsMutex(BtCursor *p){ - return sqlite3_mutex_held(p->pBt->mutex); -} - -/* Verify that the cursor and the BtShared agree about what is the current -** database connetion. This is important in shared-cache mode. If the database -** connection pointers get out-of-sync, it is possible for routines like -** btreeInitPage() to reference an stale connection pointer that references a -** a connection that has already closed. This routine is used inside assert() -** statements only and for the purpose of double-checking that the btree code -** does keep the database connection pointers up-to-date. -*/ -static int cursorOwnsBtShared(BtCursor *p){ - assert( cursorHoldsMutex(p) ); - return (p->pBtree->db==p->pBt->db); -} -#endif - -/* -** Invalidate the overflow cache of the cursor passed as the first argument. -** on the shared btree structure pBt. -*/ -#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl) - -/* -** Invalidate the overflow page-list cache for all cursors opened -** on the shared btree structure pBt. -*/ -static void invalidateAllOverflowCache(BtShared *pBt){ - BtCursor *p; - assert( sqlite3_mutex_held(pBt->mutex) ); - for(p=pBt->pCursor; p; p=p->pNext){ - invalidateOverflowCache(p); - } -} - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** This function is called before modifying the contents of a table -** to invalidate any incrblob cursors that are open on the -** row or one of the rows being modified. -** -** If argument isClearTable is true, then the entire contents of the -** table is about to be deleted. In this case invalidate all incrblob -** cursors open on any row within the table with root-page pgnoRoot. -** -** Otherwise, if argument isClearTable is false, then the row with -** rowid iRow is being replaced or deleted. In this case invalidate -** only those incrblob cursors open on that specific row. -*/ -static void invalidateIncrblobCursors( - Btree *pBtree, /* The database file to check */ - Pgno pgnoRoot, /* The table that might be changing */ - i64 iRow, /* The rowid that might be changing */ - int isClearTable /* True if all rows are being deleted */ -){ - BtCursor *p; - assert( pBtree->hasIncrblobCur ); - assert( sqlite3BtreeHoldsMutex(pBtree) ); - pBtree->hasIncrblobCur = 0; - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( (p->curFlags & BTCF_Incrblob)!=0 ){ - pBtree->hasIncrblobCur = 1; - if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){ - p->eState = CURSOR_INVALID; - } - } - } -} - -#else - /* Stub function when INCRBLOB is omitted */ - #define invalidateIncrblobCursors(w,x,y,z) -#endif /* SQLITE_OMIT_INCRBLOB */ - -/* -** Set bit pgno of the BtShared.pHasContent bitvec. This is called -** when a page that previously contained data becomes a free-list leaf -** page. -** -** The BtShared.pHasContent bitvec exists to work around an obscure -** bug caused by the interaction of two useful IO optimizations surrounding -** free-list leaf pages: -** -** 1) When all data is deleted from a page and the page becomes -** a free-list leaf page, the page is not written to the database -** (as free-list leaf pages contain no meaningful data). Sometimes -** such a page is not even journalled (as it will not be modified, -** why bother journalling it?). -** -** 2) When a free-list leaf page is reused, its content is not read -** from the database or written to the journal file (why should it -** be, if it is not at all meaningful?). -** -** By themselves, these optimizations work fine and provide a handy -** performance boost to bulk delete or insert operations. However, if -** a page is moved to the free-list and then reused within the same -** transaction, a problem comes up. If the page is not journalled when -** it is moved to the free-list and it is also not journalled when it -** is extracted from the free-list and reused, then the original data -** may be lost. In the event of a rollback, it may not be possible -** to restore the database to its original configuration. -** -** The solution is the BtShared.pHasContent bitvec. Whenever a page is -** moved to become a free-list leaf page, the corresponding bit is -** set in the bitvec. Whenever a leaf page is extracted from the free-list, -** optimization 2 above is omitted if the corresponding bit is already -** set in BtShared.pHasContent. The contents of the bitvec are cleared -** at the end of every transaction. -*/ -static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ - int rc = SQLITE_OK; - if( !pBt->pHasContent ){ - assert( pgno<=pBt->nPage ); - pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage); - if( !pBt->pHasContent ){ - rc = SQLITE_NOMEM_BKPT; - } - } - if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){ - rc = sqlite3BitvecSet(pBt->pHasContent, pgno); - } - return rc; -} - -/* -** Query the BtShared.pHasContent vector. -** -** This function is called when a free-list leaf page is removed from the -** free-list for reuse. It returns false if it is safe to retrieve the -** page from the pager layer with the 'no-content' flag set. True otherwise. -*/ -static int btreeGetHasContent(BtShared *pBt, Pgno pgno){ - Bitvec *p = pBt->pHasContent; - return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno)); -} - -/* -** Clear (destroy) the BtShared.pHasContent bitvec. This should be -** invoked at the conclusion of each write-transaction. -*/ -static void btreeClearHasContent(BtShared *pBt){ - sqlite3BitvecDestroy(pBt->pHasContent); - pBt->pHasContent = 0; -} - -/* -** Release all of the apPage[] pages for a cursor. -*/ -static void btreeReleaseAllCursorPages(BtCursor *pCur){ - int i; - if( pCur->iPage>=0 ){ - for(i=0; iiPage; i++){ - releasePageNotNull(pCur->apPage[i]); - } - releasePageNotNull(pCur->pPage); - pCur->iPage = -1; - } -} - -/* -** The cursor passed as the only argument must point to a valid entry -** when this function is called (i.e. have eState==CURSOR_VALID). This -** function saves the current cursor key in variables pCur->nKey and -** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error -** code otherwise. -** -** If the cursor is open on an intkey table, then the integer key -** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to -** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is -** set to point to a malloced buffer pCur->nKey bytes in size containing -** the key. -*/ -static int saveCursorKey(BtCursor *pCur){ - int rc = SQLITE_OK; - assert( CURSOR_VALID==pCur->eState ); - assert( 0==pCur->pKey ); - assert( cursorHoldsMutex(pCur) ); - - if( pCur->curIntKey ){ - /* Only the rowid is required for a table btree */ - pCur->nKey = sqlite3BtreeIntegerKey(pCur); - }else{ - /* For an index btree, save the complete key content. It is possible - ** that the current key is corrupt. In that case, it is possible that - ** the sqlite3VdbeRecordUnpack() function may overread the buffer by - ** up to the size of 1 varint plus 1 8-byte value when the cursor - ** position is restored. Hence the 17 bytes of padding allocated - ** below. */ - void *pKey; - pCur->nKey = sqlite3BtreePayloadSize(pCur); - pKey = sqlite3Malloc( ((i64)pCur->nKey) + 9 + 8 ); - if( pKey ){ - rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey); - if( rc==SQLITE_OK ){ - memset(((u8*)pKey)+pCur->nKey, 0, 9+8); - pCur->pKey = pKey; - }else{ - sqlite3_free(pKey); - } - }else{ - rc = SQLITE_NOMEM_BKPT; - } - } - assert( !pCur->curIntKey || !pCur->pKey ); - return rc; -} - -/* -** Save the current cursor position in the variables BtCursor.nKey -** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. -** -** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) -** prior to calling this routine. -*/ -static int saveCursorPosition(BtCursor *pCur){ - int rc; - - assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); - assert( 0==pCur->pKey ); - assert( cursorHoldsMutex(pCur) ); - - if( pCur->curFlags & BTCF_Pinned ){ - return SQLITE_CONSTRAINT_PINNED; - } - if( pCur->eState==CURSOR_SKIPNEXT ){ - pCur->eState = CURSOR_VALID; - }else{ - pCur->skipNext = 0; - } - - rc = saveCursorKey(pCur); - if( rc==SQLITE_OK ){ - btreeReleaseAllCursorPages(pCur); - pCur->eState = CURSOR_REQUIRESEEK; - } - - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast); - return rc; -} - -/* Forward reference */ -static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); - -/* -** Save the positions of all cursors (except pExcept) that are open on -** the table with root-page iRoot. "Saving the cursor position" means that -** the location in the btree is remembered in such a way that it can be -** moved back to the same spot after the btree has been modified. This -** routine is called just before cursor pExcept is used to modify the -** table, for example in BtreeDelete() or BtreeInsert(). -** -** If there are two or more cursors on the same btree, then all such -** cursors should have their BTCF_Multiple flag set. The btreeCursor() -** routine enforces that rule. This routine only needs to be called in -** the uncommon case when pExpect has the BTCF_Multiple flag set. -** -** If pExpect!=NULL and if no other cursors are found on the same root-page, -** then the BTCF_Multiple flag on pExpect is cleared, to avoid another -** pointless call to this routine. -** -** Implementation note: This routine merely checks to see if any cursors -** need to be saved. It calls out to saveCursorsOnList() in the (unusual) -** event that cursors are in need to being saved. -*/ -static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ - BtCursor *p; - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pExcept==0 || pExcept->pBt==pBt ); - for(p=pBt->pCursor; p; p=p->pNext){ - if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; - } - if( p ) return saveCursorsOnList(p, iRoot, pExcept); - if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple; - return SQLITE_OK; -} - -/* This helper routine to saveAllCursors does the actual work of saving -** the cursors if and when a cursor is found that actually requires saving. -** The common case is that no cursors need to be saved, so this routine is -** broken out from its caller to avoid unnecessary stack pointer movement. -*/ -static int SQLITE_NOINLINE saveCursorsOnList( - BtCursor *p, /* The first cursor that needs saving */ - Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */ - BtCursor *pExcept /* Do not save this cursor */ -){ - do{ - if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ - int rc = saveCursorPosition(p); - if( SQLITE_OK!=rc ){ - return rc; - } - }else{ - testcase( p->iPage>=0 ); - btreeReleaseAllCursorPages(p); - } - } - p = p->pNext; - }while( p ); - return SQLITE_OK; -} - -/* -** Clear the current cursor position. -*/ -SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - sqlite3_free(pCur->pKey); - pCur->pKey = 0; - pCur->eState = CURSOR_INVALID; -} - -/* -** 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 sqlite3BtreeIndexMoveto() to do the work. -*/ -static int btreeMoveto( - BtCursor *pCur, /* Cursor open on the btree to be searched */ - const void *pKey, /* Packed key if the btree is an index */ - i64 nKey, /* Integer key for tables. Size of pKey for indices */ - int bias, /* Bias search to the high end */ - int *pRes /* Write search results here */ -){ - int rc; /* Status code */ - UnpackedRecord *pIdxKey; /* Unpacked index key */ - - if( pKey ){ - KeyInfo *pKeyInfo = pCur->pKeyInfo; - assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); - if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; - sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); - if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); - } - sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); - }else{ - pIdxKey = 0; - rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes); - } - return rc; -} - -/* -** Restore the cursor to the position it was in (or as close to as possible) -** when saveCursorPosition() was called. Note that this call deletes the -** saved position info stored by saveCursorPosition(), so there can be -** at most one effective restoreCursorPosition() call after each -** saveCursorPosition(). -*/ -static int btreeRestoreCursorPosition(BtCursor *pCur){ - int rc; - int skipNext = 0; - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->eState>=CURSOR_REQUIRESEEK ); - if( pCur->eState==CURSOR_FAULT ){ - return pCur->skipNext; - } - pCur->eState = CURSOR_INVALID; - if( sqlite3FaultSim(410) ){ - rc = SQLITE_IOERR; - }else{ - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); - } - if( rc==SQLITE_OK ){ - sqlite3_free(pCur->pKey); - pCur->pKey = 0; - assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); - if( skipNext ) pCur->skipNext = skipNext; - if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ - pCur->eState = CURSOR_SKIPNEXT; - } - } - return rc; -} - -#define restoreCursorPosition(p) \ - (p->eState>=CURSOR_REQUIRESEEK ? \ - btreeRestoreCursorPosition(p) : \ - SQLITE_OK) - -/* -** Determine whether or not a cursor has moved from the position where -** it was last placed, or has been invalidated for any other reason. -** Cursors can move when the row they are pointing at is deleted out -** from under them, for example. Cursor might also move if a btree -** is rebalanced. -** -** Calling this routine with a NULL cursor pointer returns false. -** -** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor -** back to where it ought to be if this routine returns true. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ - assert( EIGHT_BYTE_ALIGNMENT(pCur) - || pCur==sqlite3BtreeFakeValidCursor() ); - assert( offsetof(BtCursor, eState)==0 ); - assert( sizeof(pCur->eState)==1 ); - return CURSOR_VALID != *(u8*)pCur; -} - -/* -** Return a pointer to a fake BtCursor object that will always answer -** false to the sqlite3BtreeCursorHasMoved() routine above. The fake -** cursor returned must not be used with any other Btree interface. -*/ -SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){ - static u8 fakeCursor = CURSOR_VALID; - assert( offsetof(BtCursor, eState)==0 ); - return (BtCursor*)&fakeCursor; -} - -/* -** This routine restores a cursor back to its original position after it -** has been moved by some outside activity (such as a btree rebalance or -** a row having been deleted out from under the cursor). -** -** On success, the *pDifferentRow parameter is false if the cursor is left -** pointing at exactly the same row. *pDifferntRow is the row the cursor -** was pointing to has been deleted, forcing the cursor to point to some -** nearby row. -** -** This routine should only be called for a cursor that just returned -** TRUE from sqlite3BtreeCursorHasMoved(). -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ - int rc; - - assert( pCur!=0 ); - assert( pCur->eState!=CURSOR_VALID ); - rc = restoreCursorPosition(pCur); - if( rc ){ - *pDifferentRow = 1; - return rc; - } - if( pCur->eState!=CURSOR_VALID ){ - *pDifferentRow = 1; - }else{ - *pDifferentRow = 0; - } - return SQLITE_OK; -} - -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Provide hints to the cursor. The particular hint given (and the type -** and number of the varargs parameters) is determined by the eHintType -** parameter. See the definitions of the BTREE_HINT_* macros for details. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){ - /* Used only by system that substitute their own storage engine */ -#ifdef SQLITE_DEBUG - if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){ - va_list ap; - Expr *pExpr; - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3CursorRangeHintExprCheck; - va_start(ap, eHintType); - pExpr = va_arg(ap, Expr*); - w.u.aMem = va_arg(ap, Mem*); - va_end(ap); - assert( pExpr!=0 ); - assert( w.u.aMem!=0 ); - sqlite3WalkExpr(&w, pExpr); - } -#endif /* SQLITE_DEBUG */ -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ - - -/* -** Provide flag hints to the cursor. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ - assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 ); - pCur->hints = (u8)x; -} - - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Given a page number of a regular database page, return the page -** number for the pointer-map page that contains the entry for the -** input page number. -** -** Return 0 (not a valid page) for pgno==1 since there is -** no pointer map associated with page 1. The integrity_check logic -** requires that ptrmapPageno(*,1)!=1. -*/ -static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ - int nPagesPerMapPage; - Pgno iPtrMap, ret; - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno<2 ) return 0; - nPagesPerMapPage = (pBt->usableSize/5)+1; - iPtrMap = (pgno-2)/nPagesPerMapPage; - ret = (iPtrMap*nPagesPerMapPage) + 2; - if( ret==PENDING_BYTE_PAGE(pBt) ){ - ret++; - } - return ret; -} - -/* -** Write an entry into the pointer map. -** -** This routine updates the pointer map entry for page number 'key' -** so that it maps to type 'eType' and parent page number 'pgno'. -** -** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is -** a no-op. If an error occurs, the appropriate error code is written -** into *pRC. -*/ -static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ - DbPage *pDbPage; /* The pointer map page */ - u8 *pPtrmap; /* The pointer map data */ - Pgno iPtrmap; /* The pointer map page number */ - int offset; /* Offset in pointer map page */ - int rc; /* Return code from subfunctions */ - - if( *pRC ) return; - - assert( sqlite3_mutex_held(pBt->mutex) ); - /* The super-journal page number must never be used as a pointer map page */ - assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); - - assert( pBt->autoVacuum ); - if( key==0 ){ - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); - if( rc!=SQLITE_OK ){ - *pRC = rc; - return; - } - if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){ - /* The first byte of the extra data is the MemPage.isInit byte. - ** If that byte is set, it means this page is also being used - ** as a btree page. */ - *pRC = SQLITE_CORRUPT_BKPT; - goto ptrmap_exit; - } - offset = PTRMAP_PTROFFSET(iPtrmap, key); - if( offset<0 ){ - *pRC = SQLITE_CORRUPT_BKPT; - goto ptrmap_exit; - } - assert( offset <= (int)pBt->usableSize-5 ); - pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); - - if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ - TRACE(("PTRMAP_UPDATE: %u->(%u,%u)\n", key, eType, parent)); - *pRC= rc = sqlite3PagerWrite(pDbPage); - if( rc==SQLITE_OK ){ - pPtrmap[offset] = eType; - put4byte(&pPtrmap[offset+1], parent); - } - } - -ptrmap_exit: - sqlite3PagerUnref(pDbPage); -} - -/* -** Read an entry from the pointer map. -** -** This routine retrieves the pointer map entry for page 'key', writing -** the type and parent page number to *pEType and *pPgno respectively. -** An error code is returned if something goes wrong, otherwise SQLITE_OK. -*/ -static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ - DbPage *pDbPage; /* The pointer map page */ - int iPtrmap; /* Pointer map page index */ - u8 *pPtrmap; /* Pointer map page data */ - int offset; /* Offset of entry in pointer map */ - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - - iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); - if( rc!=0 ){ - return rc; - } - pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); - - offset = PTRMAP_PTROFFSET(iPtrmap, key); - if( offset<0 ){ - sqlite3PagerUnref(pDbPage); - return SQLITE_CORRUPT_BKPT; - } - assert( offset <= (int)pBt->usableSize-5 ); - assert( pEType!=0 ); - *pEType = pPtrmap[offset]; - if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); - - sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap); - return SQLITE_OK; -} - -#else /* if defined SQLITE_OMIT_AUTOVACUUM */ - #define ptrmapPut(w,x,y,z,rc) - #define ptrmapGet(w,x,y,z) SQLITE_OK - #define ptrmapPutOvflPtr(x, y, z, rc) -#endif - -/* -** Given a btree page and a cell index (0 means the first cell on -** the page, 1 means the second cell, and so forth) return a pointer -** to the cell content. -** -** findCellPastPtr() does the same except it skips past the initial -** 4-byte child pointer found on interior pages, if there is one. -** -** This routine works only for pages that do not contain overflow cells. -*/ -#define findCell(P,I) \ - ((P)->aData + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) -#define findCellPastPtr(P,I) \ - ((P)->aDataOfst + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) - - -/* -** This is common tail processing for btreeParseCellPtr() and -** btreeParseCellPtrIndex() for the case when the cell does not fit entirely -** on a single B-tree page. Make necessary adjustments to the CellInfo -** structure. -*/ -static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - /* If the payload will not fit completely on the local page, we have - ** to decide how much to store locally and how much to spill onto - ** overflow pages. The strategy is to minimize the amount of unused - ** space on overflow pages while keeping the amount of local storage - ** in between minLocal and maxLocal. - ** - ** Warning: changing the way overflow payload is distributed in any - ** way will result in an incompatible file format. - */ - int minLocal; /* Minimum amount of payload held locally */ - int maxLocal; /* Maximum amount of payload held locally */ - int surplus; /* Overflow payload available for local storage */ - - minLocal = pPage->minLocal; - maxLocal = pPage->maxLocal; - surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4); - testcase( surplus==maxLocal ); - testcase( surplus==maxLocal+1 ); - if( surplus <= maxLocal ){ - pInfo->nLocal = (u16)surplus; - }else{ - pInfo->nLocal = (u16)minLocal; - } - pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4; -} - -/* -** 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; - assert( nPayload>=0 ); - if( nPayload<=maxLocal ){ - return (int)nPayload; - }else{ - int minLocal; /* Minimum amount of payload held locally */ - int surplus; /* Overflow payload available for local storage */ - minLocal = pPage->minLocal; - surplus = (int)(minLocal +(nPayload - minLocal)%(pPage->pBt->usableSize-4)); - return (surplus <= maxLocal) ? surplus : minLocal; - } -} - -/* -** The following routines are implementations of the MemPage.xParseCell() -** method. -** -** Parse a cell content block and fill in the CellInfo structure. -** -** btreeParseCellPtr() => table btree leaf nodes -** btreeParseCellNoPayload() => table btree internal nodes -** btreeParseCellPtrIndex() => index btree nodes -** -** There is also a wrapper function btreeParseCell() that works for -** all MemPage types and that references the cell by index rather than -** by pointer. -*/ -static void btreeParseCellPtrNoPayload( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->leaf==0 ); - assert( pPage->childPtrSize==4 ); -#ifndef SQLITE_DEBUG - UNUSED_PARAMETER(pPage); -#endif - pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey); - pInfo->nPayload = 0; - pInfo->nLocal = 0; - pInfo->pPayload = 0; - return; -} -static void btreeParseCellPtr( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - u8 *pIter; /* For scanning through pCell */ - u32 nPayload; /* Number of bytes of cell payload */ - u64 iKey; /* Extracted Key value */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->leaf==0 || pPage->leaf==1 ); - assert( pPage->intKeyLeaf ); - assert( pPage->childPtrSize==0 ); - pIter = pCell; - - /* The next block of code is equivalent to: - ** - ** pIter += getVarint32(pIter, nPayload); - ** - ** The code is inlined to avoid a function call. - */ - nPayload = *pIter; - if( nPayload>=0x80 ){ - u8 *pEnd = &pIter[8]; - nPayload &= 0x7f; - do{ - nPayload = (nPayload<<7) | (*++pIter & 0x7f); - }while( (*pIter)>=0x80 && pIternKey); - ** - ** The code is inlined and the loop is unrolled for performance. - ** This routine is a high-runner. - */ - iKey = *pIter; - if( iKey>=0x80 ){ - u8 x; - iKey = (iKey<<7) ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<8) ^ 0x8000 ^ (*++pIter); - } - } - } - } - } - }else{ - iKey ^= 0x204000; - } - }else{ - iKey ^= 0x4000; - } - } - pIter++; - - pInfo->nKey = *(i64*)&iKey; - pInfo->nPayload = nPayload; - pInfo->pPayload = pIter; - testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==(u32)pPage->maxLocal+1 ); - assert( nPayload>=0 ); - assert( pPage->maxLocal <= BT_MAX_LOCAL ); - if( nPayload<=pPage->maxLocal ){ - /* This is the (easy) common case where the entire payload fits - ** on the local page. No overflow is required. - */ - pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell); - if( pInfo->nSize<4 ) pInfo->nSize = 4; - pInfo->nLocal = (u16)nPayload; - }else{ - btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); - } -} -static void btreeParseCellPtrIndex( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - u8 *pIter; /* For scanning through pCell */ - u32 nPayload; /* Number of bytes of cell payload */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->leaf==0 || pPage->leaf==1 ); - assert( pPage->intKeyLeaf==0 ); - pIter = pCell + pPage->childPtrSize; - nPayload = *pIter; - if( nPayload>=0x80 ){ - u8 *pEnd = &pIter[8]; - nPayload &= 0x7f; - do{ - nPayload = (nPayload<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pIternKey = nPayload; - pInfo->nPayload = nPayload; - pInfo->pPayload = pIter; - testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==(u32)pPage->maxLocal+1 ); - assert( nPayload>=0 ); - assert( pPage->maxLocal <= BT_MAX_LOCAL ); - if( nPayload<=pPage->maxLocal ){ - /* This is the (easy) common case where the entire payload fits - ** on the local page. No overflow is required. - */ - pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell); - if( pInfo->nSize<4 ) pInfo->nSize = 4; - pInfo->nLocal = (u16)nPayload; - }else{ - btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); - } -} -static void btreeParseCell( - MemPage *pPage, /* Page containing the cell */ - int iCell, /* The cell index. First cell is 0 */ - CellInfo *pInfo /* Fill in this structure */ -){ - pPage->xParseCell(pPage, findCell(pPage, iCell), pInfo); -} - -/* -** The following routines are implementations of the MemPage.xCellSize -** method. -** -** Compute the total number of bytes that a Cell needs in the cell -** data area of the btree-page. The return number includes the cell -** data header and the local payload, but not any overflow page or -** the space used by the cell pointer. -** -** cellSizePtrNoPayload() => table internal nodes -** cellSizePtrTableLeaf() => table leaf nodes -** cellSizePtr() => index internal nodes -** cellSizeIdxLeaf() => index leaf nodes -*/ -static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell + 4; /* 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 - - assert( pPage->childPtrSize==4 ); - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pItermaxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); - if( nSize<=pPage->maxLocal ){ - nSize += (u32)(pIter - pCell); - assert( 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; -} -static u16 cellSizePtrIdxLeaf(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 - - assert( pPage->childPtrSize==0 ); - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pItermaxLocal ); - 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; -} -static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell + 4; /* For looping over bytes of pCell */ - u8 *pEnd; /* End mark for a varint */ - -#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); -#else - UNUSED_PARAMETER(pPage); -#endif - - assert( pPage->childPtrSize==4 ); - pEnd = pIter + 9; - while( (*pIter++)&0x80 && pIterxParseCell(pPage, pCell, &debuginfo); -#endif - - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pItermaxLocal ); - 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 -/* This variation on cellSizePtr() is used inside of assert() statements -** only. */ -static u16 cellSize(MemPage *pPage, int iCell){ - return pPage->xCellSize(pPage, findCell(pPage, iCell)); -} -#endif - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** The cell pCell is currently part of page pSrc but will ultimately be part -** 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. -*/ -static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ - CellInfo info; - if( *pRC ) return; - assert( pCell!=0 ); - pPage->xParseCell(pPage, pCell, &info); - if( info.nLocalaDataEnd, pCell, pCell+info.nLocal) ){ - testcase( pSrc!=pPage ); - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - ovfl = get4byte(&pCell[info.nSize-4]); - ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); - } -} -#endif - - -/* -** Defragment the page given. This routine reorganizes cells within the -** page so that there are no free-blocks on the free-block list. -** -** Parameter nMaxFrag is the maximum amount of fragmented space that may be -** present in the page after this routine returns. -** -** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a -** b-tree page so that there are no freeblocks or fragment bytes, all -** unused bytes are contained in the unallocated space region, and all -** cells are packed tightly at the end of the page. -*/ -static int defragmentPage(MemPage *pPage, int nMaxFrag){ - int i; /* Loop counter */ - int pc; /* Address of the i-th cell */ - int hdr; /* Offset to the page header */ - int size; /* Size of a cell */ - int usableSize; /* Number of usable bytes on a page */ - int cellOffset; /* Offset to the cell pointer array */ - int cbrk; /* Offset to the cell content area */ - int nCell; /* Number of cells on the page */ - unsigned char *data; /* The page data */ - unsigned char *temp; /* Temp area for cell content */ - 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( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( pPage->pBt!=0 ); - assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); - assert( pPage->nOverflow==0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - data = pPage->aData; - hdr = pPage->hdrOffset; - cellOffset = pPage->cellOffset; - nCell = pPage->nCell; - assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB ); - iCellFirst = cellOffset + 2*nCell; - usableSize = pPage->pBt->usableSize; - - /* This block handles pages with two or fewer free blocks and nMaxFrag - ** or fewer fragmented bytes. In this case it is faster to move the - ** two (or one) blocks of cells using memmove() and add the required - ** offsets to each pointer in the cell-pointer array than it is to - ** reconstruct the entire page. */ - if( (int)data[hdr+7]<=nMaxFrag ){ - int iFree = get2byte(&data[hdr+1]); - if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); - if( iFree ){ - int iFree2 = get2byte(&data[iFree]); - if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); - if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ - u8 *pEnd = &data[cellOffset + nCell*2]; - u8 *pAddr; - int sz2 = 0; - int sz = get2byte(&data[iFree+2]); - int top = get2byte(&data[hdr+5]); - if( top>=iFree ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( iFree2 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage); - sz2 = get2byte(&data[iFree2+2]); - if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); - memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); - sz += sz2; - }else if( iFree+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - - cbrk = top+sz; - assert( cbrk+(iFree-top) <= usableSize ); - memmove(&data[cbrk], &data[top], iFree-top); - for(pAddr=&data[cellOffset]; pAddr0 ){ - temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - memcpy(temp, data, usableSize); - src = temp; - for(i=0; iiCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( pc>=0 && pc<=iCellLast ); - size = pPage->xCellSize(pPage, &src[pc]); - cbrk -= size; - if( cbrkusableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( cbrk+size<=usableSize && cbrk>=iCellStart ); - testcase( cbrk+size==usableSize ); - testcase( pc+size==usableSize ); - put2byte(pAddr, cbrk); - memcpy(&data[cbrk], &src[pc], size); - } - } - data[hdr+7] = 0; - -defragment_out: - assert( pPage->nFree>=0 ); - if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( cbrk>=iCellFirst ); - put2byte(&data[hdr+5], cbrk); - data[hdr+1] = 0; - data[hdr+2] = 0; - memset(&data[iCellFirst], 0, cbrk-iCellFirst); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - return SQLITE_OK; -} - -/* -** Search the free-list on page pPg for space to store a cell nByte bytes in -** size. If one can be found, return a pointer to the space and remove it -** from the free-list. -** -** If no suitable space can be found on the free-list, return NULL. -** -** This function may detect corruption within pPg. If corruption is -** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned. -** -** Slots on the free list that are between 1 and 3 bytes larger than nByte -** will be ignored if adding the extra space to the fragmentation count -** causes the fragmentation count to exceed 60. -*/ -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 */ - 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 */ - - assert( pc>0 ); - while( pc<=maxPC ){ - /* 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. */ - pTmp = &aData[pc+2]; - size = get2byte(pTmp); - if( (x = size - nByte)>=0 ){ - testcase( x==4 ); - testcase( x==3 ); - if( x<4 ){ - /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total - ** number of bytes in fragments may not exceed 60. */ - if( aData[hdr+7]>57 ) return 0; - - /* Remove the slot from the free-list. Update the number of - ** fragmented bytes within the page. */ - memcpy(&aData[iAddr], &aData[pc], 2); - aData[hdr+7] += (u8)x; - 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); - return 0; - }else{ - /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ - put2byte(&aData[pc+2], x); - } - return &aData[pc + x]; - } - iAddr = pc; - pTmp = &aData[pc]; - pc = get2byte(pTmp); - if( pc<=iAddr ){ - if( pc ){ - /* The next slot in the chain comes before the current slot */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - } - return 0; - } - } - if( pc>maxPC+nByte-4 ){ - /* The free slot chain extends off the end of the page */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - } - return 0; -} - -/* -** Allocate nByte bytes of space from within the B-Tree page passed -** as the first argument. Write into *pIdx the index into pPage->aData[] -** of the first byte of allocated space. Return either SQLITE_OK or -** an error code (usually SQLITE_CORRUPT). -** -** The caller guarantees that there is sufficient space to make the -** allocation. This routine might need to defragment in order to bring -** all the space together, however. This routine will avoid using -** the first two bytes past the cell pointer area since presumably this -** allocation is being made in order to insert a new cell, so we will -** also end up needing a new cell pointer. -*/ -static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ - const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ - 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( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( pPage->pBt ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( nByte>=0 ); /* Minimum cell size is 4 */ - assert( pPage->nFree>=nByte ); - assert( pPage->nOverflow==0 ); - assert( nByte < (int)(pPage->pBt->usableSize-8) ); - - assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); - gap = pPage->cellOffset + 2*pPage->nCell; - assert( gap<=65536 ); - /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size - ** and the reserved space is zero (the usual value for reserved space) - ** 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. */ - pTmp = &data[hdr+5]; - top = get2byte(pTmp); - if( gap>top ){ - if( top==0 && pPage->pBt->usableSize==65536 ){ - top = 65536; - }else{ - return SQLITE_CORRUPT_PAGE(pPage); - } - }else if( top>(int)pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - - /* If there is enough space between gap and top for one more cell pointer, - ** and if the freelist is not empty, then search the - ** freelist looking for a slot big enough to satisfy the request. - */ - testcase( gap+2==top ); - testcase( gap+1==top ); - testcase( gap==top ); - if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ - u8 *pSpace = pageFindSlot(pPage, nByte, &rc); - if( pSpace ){ - int g2; - assert( pSpace+nByte<=data+pPage->pBt->usableSize ); - *pIdx = g2 = (int)(pSpace-data); - if( g2<=gap ){ - return SQLITE_CORRUPT_PAGE(pPage); - }else{ - return SQLITE_OK; - } - }else if( rc ){ - return rc; - } - } - - /* The request could not be fulfilled using a freelist slot. Check - ** to see if defragmentation is necessary. - */ - testcase( gap+2+nByte==top ); - if( gap+2+nByte>top ){ - assert( pPage->nCell>0 || CORRUPT_DB ); - assert( pPage->nFree>=0 ); - rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); - if( rc ) return rc; - top = get2byteNotZero(&data[hdr+5]); - assert( gap+2+nByte<=top ); - } - - - /* Allocate memory from the gap in between the cell pointer array - ** and the cell content area. The btreeComputeFreeSpace() call has already - ** validated the freelist. Given that the freelist is valid, there - ** is no way that the allocation can extend off the end of the page. - ** The assert() below verifies the previous sentence. - */ - top -= nByte; - put2byte(&data[hdr+5], top); - assert( top+nByte <= (int)pPage->pBt->usableSize ); - *pIdx = top; - return SQLITE_OK; -} - -/* -** Return a section of the pPage->aData to the freelist. -** The first byte of the new free block is pPage->aData[iStart] -** and the size of the block is iSize bytes. -** -** Adjacent freeblocks are coalesced. -** -** Even though the freeblock list was checked by btreeComputeFreeSpace(), -** that routine will not detect overlap between cells or freeblocks. Nor -** does it detect cells or freeblocks that encroach into the reserved bytes -** at the end of the page. So do additional corruption checks inside this -** routine and return SQLITE_CORRUPT if any problems are found. -*/ -static int freeSpace(MemPage *pPage, int iStart, int iSize){ - int iPtr; /* Address of ptr to next freeblock */ - int iFreeBlk; /* Address of the next freeblock */ - u8 hdr; /* Page header size. 0 or 100 */ - int nFrag = 0; /* Reduction in fragmentation */ - int iOrigSize = iSize; /* Original value of iSize */ - int x; /* Offset to cell content area */ - int 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( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( iSize>=4 ); /* Minimum cell size is 4 */ - assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 ); - - /* The list of freeblocks must be in ascending order. Find the - ** spot on the list where iStart should be inserted. - */ - hdr = pPage->hdrOffset; - iPtr = hdr + 1; - if( data[iPtr+1]==0 && data[iPtr]==0 ){ - iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ - }else{ - while( (iFreeBlk = get2byte(&data[iPtr]))(int)pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); - - /* At this point: - ** iFreeBlk: First freeblock after iStart, or zero if none - ** iPtr: The address of a pointer to iFreeBlk - ** - ** Check to see if iFreeBlk should be coalesced onto the end of iStart. - */ - if( iFreeBlk && iEnd+3>=iFreeBlk ){ - nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); - iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); - if( iEnd > (int)pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - iSize = iEnd - iStart; - iFreeBlk = get2byte(&data[iFreeBlk]); - } - - /* If iPtr is another freeblock (that is, if iPtr is not the freelist - ** pointer in the page header) then check to see if iStart should be - ** coalesced onto the end of iPtr. - */ - if( iPtr>hdr+1 ){ - int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); - if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); - nFrag += iStart - iPtrEnd; - iSize = iEnd - iPtr; - iStart = iPtr; - } - } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); - data[hdr+7] -= (u8)nFrag; - } - pTmp = &data[hdr+5]; - x = get2byte(pTmp); - if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ - memset(&data[iStart], 0, iSize); - } - 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 - ** freelist entry */ - if( iStart=0 && iSize<=0xffff ); - put2byte(&data[iStart+2], (u16)iSize); - } - pPage->nFree += iOrigSize; - return SQLITE_OK; -} - -/* -** Decode the flags byte (the first byte of the header) for a page -** and initialize fields of the MemPage structure accordingly. -** -** Only the following combinations are supported. Anything different -** indicates a corrupt database files: -** -** PTF_ZERODATA (0x02, 2) -** PTF_LEAFDATA | PTF_INTKEY (0x05, 5) -** PTF_ZERODATA | PTF_LEAF (0x0a, 10) -** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF (0x0d, 13) -*/ -static int decodeFlags(MemPage *pPage, int flagByte){ - BtShared *pBt; /* A copy of pPage->pBt */ - - assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pBt = pPage->pBt; - pPage->max1bytePayload = pBt->max1bytePayload; - if( flagByte>=(PTF_ZERODATA | PTF_LEAF) ){ - pPage->childPtrSize = 0; - pPage->leaf = 1; - if( flagByte==(PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF) ){ - pPage->intKeyLeaf = 1; - pPage->xCellSize = cellSizePtrTableLeaf; - pPage->xParseCell = btreeParseCellPtr; - pPage->intKey = 1; - pPage->maxLocal = pBt->maxLeaf; - pPage->minLocal = pBt->minLeaf; - }else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtrIdxLeaf; - pPage->xParseCell = btreeParseCellPtrIndex; - pPage->maxLocal = pBt->maxLocal; - pPage->minLocal = pBt->minLocal; - }else{ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtrIdxLeaf; - pPage->xParseCell = btreeParseCellPtrIndex; - return SQLITE_CORRUPT_PAGE(pPage); - } - }else{ - pPage->childPtrSize = 4; - pPage->leaf = 0; - if( flagByte==(PTF_ZERODATA) ){ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtr; - pPage->xParseCell = btreeParseCellPtrIndex; - pPage->maxLocal = pBt->maxLocal; - pPage->minLocal = pBt->minLocal; - }else if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtrNoPayload; - pPage->xParseCell = btreeParseCellPtrNoPayload; - pPage->intKey = 1; - pPage->maxLocal = pBt->maxLeaf; - pPage->minLocal = pBt->minLeaf; - }else{ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtr; - pPage->xParseCell = btreeParseCellPtrIndex; - return SQLITE_CORRUPT_PAGE(pPage); - } - } - return SQLITE_OK; -} - -/* -** Compute the amount of freespace on the page. In other words, fill -** in the pPage->nFree field. -*/ -static int btreeComputeFreeSpace(MemPage *pPage){ - int pc; /* Address of a freeblock within pPage->aData[] */ - u8 hdr; /* Offset to beginning of page header */ - u8 *data; /* Equal to pPage->aData */ - int usableSize; /* Amount of usable space on each page */ - int nFree; /* Number of unused bytes on the page */ - int top; /* First byte of the cell content area */ - int iCellFirst; /* First allowable cell or freeblock offset */ - int iCellLast; /* Last possible cell or freeblock offset */ - - assert( pPage->pBt!=0 ); - assert( pPage->pBt->db!=0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); - assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - assert( pPage->isInit==1 ); - assert( pPage->nFree<0 ); - - usableSize = pPage->pBt->usableSize; - hdr = pPage->hdrOffset; - data = pPage->aData; - /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates - ** the start of the cell content area. A zero value for this integer is - ** interpreted as 65536. */ - top = get2byteNotZero(&data[hdr+5]); - iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell; - iCellLast = usableSize - 4; - - /* Compute the total free space on the page - ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the - ** start of the first freeblock on the page, or is zero if there are no - ** freeblocks. */ - pc = get2byte(&data[hdr+1]); - nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ - if( pc>0 ){ - u32 next, size; - if( pciCellLast ){ - /* Freeblock off the end of the page */ - return SQLITE_CORRUPT_PAGE(pPage); - } - next = get2byte(&data[pc]); - size = get2byte(&data[pc+2]); - nFree = nFree + size; - if( next<=pc+size+3 ) break; - pc = next; - } - if( next>0 ){ - /* Freeblock not in ascending order */ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( pc+size>(unsigned int)usableSize ){ - /* Last freeblock extends past page end */ - return SQLITE_CORRUPT_PAGE(pPage); - } - } - - /* At this point, nFree contains the sum of the offset to the start - ** of the cell-content area plus the number of free bytes within - ** the cell-content area. If this is greater than the usable-size - ** of the page, then the page must be corrupted. This check also - ** serves to verify that the offset to the start of the cell-content - ** area, according to the page header, lies within the page. - */ - if( nFree>usableSize || nFreenFree = (u16)(nFree - iCellFirst); - return SQLITE_OK; -} - -/* -** Do additional sanity check after btreeInitPage() if -** PRAGMA cell_size_check=ON -*/ -static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){ - int iCellFirst; /* First allowable cell or freeblock offset */ - int iCellLast; /* Last possible cell or freeblock offset */ - int i; /* Index into the cell pointer array */ - int sz; /* Size of a cell */ - int pc; /* Address of a freeblock within pPage->aData[] */ - u8 *data; /* Equal to pPage->aData */ - int usableSize; /* Maximum usable space on the page */ - int cellOffset; /* Start of cell content area */ - - iCellFirst = pPage->cellOffset + 2*pPage->nCell; - usableSize = pPage->pBt->usableSize; - iCellLast = usableSize - 4; - data = pPage->aData; - cellOffset = pPage->cellOffset; - if( !pPage->leaf ) iCellLast--; - for(i=0; inCell; i++){ - pc = get2byteAligned(&data[cellOffset+i*2]); - testcase( pc==iCellFirst ); - testcase( pc==iCellLast ); - if( pciCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - sz = pPage->xCellSize(pPage, &data[pc]); - testcase( pc+sz==usableSize ); - if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - } - return SQLITE_OK; -} - -/* -** Initialize the auxiliary information for a disk block. -** -** Return SQLITE_OK on success. If we see that the page does -** not contain a well-formed database page, then return -** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not -** guarantee that the page is well-formed. It only shows that -** we failed to detect any corruption. -*/ -static int btreeInitPage(MemPage *pPage){ - u8 *data; /* Equal to pPage->aData */ - BtShared *pBt; /* The main btree structure */ - - assert( pPage->pBt!=0 ); - assert( pPage->pBt->db!=0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); - assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - assert( pPage->isInit==0 ); - - pBt = pPage->pBt; - data = pPage->aData + pPage->hdrOffset; - /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating - ** the b-tree page type. */ - if( decodeFlags(pPage, data[0]) ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nOverflow = 0; - pPage->cellOffset = (u16)(pPage->hdrOffset + 8 + pPage->childPtrSize); - pPage->aCellIdx = data + pPage->childPtrSize + 8; - 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. */ - pPage->nCell = get2byte(&data[3]); - if( pPage->nCell>MX_CELL(pBt) ){ - /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PAGE(pPage); - } - testcase( pPage->nCell==MX_CELL(pBt) ); - /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only - ** possible for a root page of a table that contains no rows) then the - ** offset to the cell content area will equal the page size minus the - ** bytes of reserved space. */ - assert( pPage->nCell>0 - || get2byteNotZero(&data[5])==(int)pBt->usableSize - || CORRUPT_DB ); - pPage->nFree = -1; /* Indicate that this value is yet uncomputed */ - pPage->isInit = 1; - if( pBt->db->flags & SQLITE_CellSizeCk ){ - return btreeCellSizeCheck(pPage); - } - return SQLITE_OK; -} - -/* -** Set up a raw page so that it looks like a database page holding -** no entries. -*/ -static void zeroPage(MemPage *pPage, int flags){ - unsigned char *data = pPage->aData; - BtShared *pBt = pPage->pBt; - int hdr = pPage->hdrOffset; - int first; - - assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage) == data ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->btsFlags & BTS_FAST_SECURE ){ - memset(&data[hdr], 0, pBt->usableSize - hdr); - } - data[hdr] = (char)flags; - first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8); - memset(&data[hdr+1], 0, 4); - data[hdr+7] = 0; - put2byte(&data[hdr+5], pBt->usableSize); - pPage->nFree = (u16)(pBt->usableSize - first); - decodeFlags(pPage, flags); - pPage->cellOffset = (u16)first; - pPage->aDataEnd = &data[pBt->pageSize]; - pPage->aCellIdx = &data[first]; - pPage->aDataOfst = &data[pPage->childPtrSize]; - pPage->nOverflow = 0; - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nCell = 0; - pPage->isInit = 1; -} - - -/* -** Convert a DbPage obtained from the pager into a MemPage used by -** the btree layer. -*/ -static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){ - MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( pgno!=pPage->pgno ){ - pPage->aData = sqlite3PagerGetData(pDbPage); - pPage->pDbPage = pDbPage; - pPage->pBt = pBt; - pPage->pgno = pgno; - pPage->hdrOffset = pgno==1 ? 100 : 0; - } - assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); - return pPage; -} - -/* -** Get a page from the pager. Initialize the MemPage.pBt and -** MemPage.aData elements if needed. See also: btreeGetUnusedPage(). -** -** If the PAGER_GET_NOCONTENT flag is set, it means that we do not care -** about the content of the page at this time. So do not go to the disk -** to fetch the content. Just fill in the content with zeros for now. -** If in the future we call sqlite3PagerWrite() on this page, that -** means we have started to be concerned about content and the disk -** read should occur at that point. -*/ -static int btreeGetPage( - BtShared *pBt, /* The btree */ - Pgno pgno, /* Number of the page to fetch */ - MemPage **ppPage, /* Return the page in this parameter */ - int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */ -){ - int rc; - DbPage *pDbPage; - - assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY ); - assert( sqlite3_mutex_held(pBt->mutex) ); - rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); - if( rc ) return rc; - *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); - return SQLITE_OK; -} - -/* -** Retrieve a page from the pager cache. If the requested page is not -** already in the pager cache return NULL. Initialize the MemPage.pBt and -** MemPage.aData elements if needed. -*/ -static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){ - DbPage *pDbPage; - assert( sqlite3_mutex_held(pBt->mutex) ); - pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); - if( pDbPage ){ - return btreePageFromDbPage(pDbPage, pgno, pBt); - } - return 0; -} - -/* -** Return the size of the database file in pages. If there is any kind of -** error, return ((unsigned int)-1). -*/ -static Pgno btreePagecount(BtShared *pBt){ - return pBt->nPage; -} -SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){ - assert( sqlite3BtreeHoldsMutex(p) ); - return btreePagecount(p->pBt); -} - -/* -** Get a page from the pager and initialize it. -*/ -static int getAndInitPage( - BtShared *pBt, /* The database file */ - Pgno pgno, /* Number of the page to get */ - MemPage **ppPage, /* Write the page pointer here */ - int bReadOnly /* True for a read-only page */ -){ - int rc; - DbPage *pDbPage; - MemPage *pPage; - assert( sqlite3_mutex_held(pBt->mutex) ); - - if( pgno>btreePagecount(pBt) ){ - *ppPage = 0; - return SQLITE_CORRUPT_BKPT; - } - rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); - if( rc ){ - *ppPage = 0; - return rc; - } - pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( pPage->isInit==0 ){ - btreePageFromDbPage(pDbPage, pgno, pBt); - rc = btreeInitPage(pPage); - if( rc!=SQLITE_OK ){ - releasePage(pPage); - *ppPage = 0; - return rc; - } - } - assert( pPage->pgno==pgno || CORRUPT_DB ); - assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); - *ppPage = pPage; - return SQLITE_OK; -} - -/* -** Release a MemPage. This should be called once for each prior -** call to btreeGetPage. -** -** Page1 is a special case and must be released using releasePageOne(). -*/ -static void releasePageNotNull(MemPage *pPage){ - assert( pPage->aData ); - assert( pPage->pBt ); - assert( pPage->pDbPage!=0 ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnrefNotNull(pPage->pDbPage); -} -static void releasePage(MemPage *pPage){ - if( pPage ) releasePageNotNull(pPage); -} -static void releasePageOne(MemPage *pPage){ - assert( pPage!=0 ); - assert( pPage->aData ); - assert( pPage->pBt ); - assert( pPage->pDbPage!=0 ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnrefPageOne(pPage->pDbPage); -} - -/* -** Get an unused page. -** -** This works just like btreeGetPage() with the addition: -** -** * If the page is already in use for some other purpose, immediately -** release it and return an SQLITE_CURRUPT error. -** * Make sure the isInit flag is clear -*/ -static int btreeGetUnusedPage( - BtShared *pBt, /* The btree */ - Pgno pgno, /* Number of the page to fetch */ - MemPage **ppPage, /* Return the page in this parameter */ - int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */ -){ - int rc = btreeGetPage(pBt, pgno, ppPage, flags); - if( rc==SQLITE_OK ){ - if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ - releasePage(*ppPage); - *ppPage = 0; - return SQLITE_CORRUPT_BKPT; - } - (*ppPage)->isInit = 0; - }else{ - *ppPage = 0; - } - return rc; -} - - -/* -** During a rollback, when the pager reloads information into the cache -** so that the cache is restored to its original state at the start of -** the transaction, for each page restored this routine is called. -** -** This routine needs to reset the extra data section at the end of the -** page to agree with the restored data. -*/ -static void pageReinit(DbPage *pData){ - MemPage *pPage; - pPage = (MemPage *)sqlite3PagerGetExtra(pData); - assert( sqlite3PagerPageRefcount(pData)>0 ); - if( pPage->isInit ){ - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->isInit = 0; - if( sqlite3PagerPageRefcount(pData)>1 ){ - /* pPage might not be a btree page; it might be an overflow page - ** or ptrmap page or a free page. In those cases, the following - ** call to btreeInitPage() will likely return SQLITE_CORRUPT. - ** But no harm is done by this. And it is very important that - ** btreeInitPage() be called on every btree page so we make - ** the call for every page that comes in for re-initializing. */ - btreeInitPage(pPage); - } - } -} - -/* -** Invoke the busy handler for a btree. -*/ -static int btreeInvokeBusyHandler(void *pArg){ - BtShared *pBt = (BtShared*)pArg; - assert( pBt->db ); - assert( sqlite3_mutex_held(pBt->db->mutex) ); - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); -} - -/* -** Open a database file. -** -** zFilename is the name of the database file. If zFilename is NULL -** then an ephemeral database is created. The ephemeral database might -** be exclusively in memory, or it might use a disk-based memory cache. -** Either way, the ephemeral database will be automatically deleted -** when sqlite3BtreeClose() is called. -** -** If zFilename is ":memory:" then an in-memory database is created -** that is automatically destroyed when it is closed. -** -** The "flags" parameter is a bitmask that might contain bits like -** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY. -** -** If the database is already opened in the same database connection -** and we are in shared cache mode, then the open will fail with an -** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared -** objects in the same database connection since doing so will lead -** to problems with locking. -*/ -SQLITE_PRIVATE int sqlite3BtreeOpen( - sqlite3_vfs *pVfs, /* VFS to use for this b-tree */ - const char *zFilename, /* Name of the file containing the BTree database */ - sqlite3 *db, /* Associated database handle */ - Btree **ppBtree, /* Pointer to new Btree object written here */ - int flags, /* Options */ - int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ -){ - BtShared *pBt = 0; /* Shared part of btree structure */ - Btree *p; /* Handle to return */ - sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */ - int rc = SQLITE_OK; /* Result code from this function */ - u8 nReserve; /* Byte of unused space on each page */ - unsigned char zDbHeader[100]; /* Database header content */ - - /* True if opening an ephemeral, temporary database */ - const int isTempDb = zFilename==0 || zFilename[0]==0; - - /* Set the variable isMemdb to true for an in-memory database, or - ** false for a file-based database. - */ -#ifdef SQLITE_OMIT_MEMORYDB - const int isMemdb = 0; -#else - const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) - || (isTempDb && sqlite3TempInMemory(db)) - || (vfsFlags & SQLITE_OPEN_MEMORY)!=0; -#endif - - assert( db!=0 ); - assert( pVfs!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( (flags&0xff)==flags ); /* flags fit in 8 bits */ - - /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ - assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); - - /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ - assert( (flags & BTREE_SINGLE)==0 || isTempDb ); - - if( isMemdb ){ - flags |= BTREE_MEMORY; - } - if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ - vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; - } - p = sqlite3MallocZero(sizeof(Btree)); - if( !p ){ - return SQLITE_NOMEM_BKPT; - } - p->inTrans = TRANS_NONE; - p->db = db; -#ifndef SQLITE_OMIT_SHARED_CACHE - p->lock.pBtree = p; - p->lock.iTable = 1; -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* - ** If this Btree is a candidate for shared cache, try to find an - ** existing BtShared object that we can share with - */ - if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ - if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ - int nFilename = sqlite3Strlen30(zFilename)+1; - int nFullPathname = pVfs->mxPathname+1; - char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); - MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - - p->sharable = 1; - if( !zFullPathname ){ - sqlite3_free(p); - return SQLITE_NOMEM_BKPT; - } - if( isMemdb ){ - memcpy(zFullPathname, zFilename, nFilename); - }else{ - rc = sqlite3OsFullPathname(pVfs, zFilename, - nFullPathname, zFullPathname); - if( rc ){ - if( rc==SQLITE_OK_SYMLINK ){ - rc = SQLITE_OK; - }else{ - sqlite3_free(zFullPathname); - sqlite3_free(p); - return rc; - } - } - } -#if SQLITE_THREADSAFE - mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN); - sqlite3_mutex_enter(mutexOpen); - mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); - sqlite3_mutex_enter(mutexShared); -#endif - for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ - assert( pBt->nRef>0 ); - if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0)) - && sqlite3PagerVfs(pBt->pPager)==pVfs ){ - int iDb; - for(iDb=db->nDb-1; iDb>=0; iDb--){ - Btree *pExisting = db->aDb[iDb].pBt; - if( pExisting && pExisting->pBt==pBt ){ - sqlite3_mutex_leave(mutexShared); - sqlite3_mutex_leave(mutexOpen); - sqlite3_free(zFullPathname); - sqlite3_free(p); - return SQLITE_CONSTRAINT; - } - } - p->pBt = pBt; - pBt->nRef++; - break; - } - } - sqlite3_mutex_leave(mutexShared); - sqlite3_free(zFullPathname); - } -#ifdef SQLITE_DEBUG - else{ - /* In debug mode, we mark all persistent databases as sharable - ** even when they are not. This exercises the locking code and - ** gives more opportunity for asserts(sqlite3_mutex_held()) - ** statements to find locking problems. - */ - p->sharable = 1; - } -#endif - } -#endif - if( pBt==0 ){ - /* - ** The following asserts make sure that structures used by the btree are - ** the right size. This is to guard against size changes that result - ** when compiling on a different architecture. - */ - assert( sizeof(i64)==8 ); - assert( sizeof(u64)==8 ); - assert( sizeof(u32)==4 ); - assert( sizeof(u16)==2 ); - assert( sizeof(Pgno)==4 ); - - /* Suppress false-positive compiler warning from PVS-Studio */ - memset(&zDbHeader[16], 0, 8); - - pBt = sqlite3MallocZero( sizeof(*pBt) ); - if( pBt==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto btree_open_out; - } - rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - sizeof(MemPage), flags, vfsFlags, pageReinit); - if( rc==SQLITE_OK ){ - sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); - rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); - } - if( rc!=SQLITE_OK ){ - goto btree_open_out; - } - pBt->openFlags = (u8)flags; - pBt->db = db; - sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); - p->pBt = pBt; - - pBt->pCursor = 0; - pBt->pPage1 = 0; - if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; -#if defined(SQLITE_SECURE_DELETE) - pBt->btsFlags |= BTS_SECURE_DELETE; -#elif defined(SQLITE_FAST_SECURE_DELETE) - pBt->btsFlags |= BTS_OVERWRITE; -#endif - /* EVIDENCE-OF: R-51873-39618 The page size for a database file is - ** determined by the 2-byte integer located at an offset of 16 bytes from - ** the beginning of the database file. */ - pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16); - if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE - || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ - pBt->pageSize = 0; -#ifndef SQLITE_OMIT_AUTOVACUUM - /* If the magic name ":memory:" will create an in-memory database, then - ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if - ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if - ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a - ** regular file-name. In this case the auto-vacuum applies as per normal. - */ - if( zFilename && !isMemdb ){ - pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); - pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); - } -#endif - nReserve = 0; - }else{ - /* EVIDENCE-OF: R-37497-42412 The size of the reserved region is - ** determined by the one-byte unsigned integer found at an offset of 20 - ** into the database file header. */ - nReserve = zDbHeader[20]; - pBt->btsFlags |= BTS_PAGESIZE_FIXED; -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); - pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); -#endif - } - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); - if( rc ) goto btree_open_out; - pBt->usableSize = pBt->pageSize - nReserve; - assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* Add the new BtShared object to the linked list sharable BtShareds. - */ - pBt->nRef = 1; - if( p->sharable ){ - MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);) - if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ - pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); - if( pBt->mutex==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto btree_open_out; - } - } - sqlite3_mutex_enter(mutexShared); - pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); - GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt; - sqlite3_mutex_leave(mutexShared); - } -#endif - } - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* If the new Btree uses a sharable pBtShared, then link the new - ** Btree into the list of all sharable Btrees for the same connection. - ** The list is kept in ascending order by pBt address. - */ - if( p->sharable ){ - int i; - Btree *pSib; - for(i=0; inDb; i++){ - if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ - while( pSib->pPrev ){ pSib = pSib->pPrev; } - if( (uptr)p->pBt<(uptr)pSib->pBt ){ - p->pNext = pSib; - p->pPrev = 0; - pSib->pPrev = p; - }else{ - while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){ - pSib = pSib->pNext; - } - p->pNext = pSib->pNext; - p->pPrev = pSib; - if( p->pNext ){ - p->pNext->pPrev = p; - } - pSib->pNext = p; - } - break; - } - } - } -#endif - *ppBtree = p; - -btree_open_out: - if( rc!=SQLITE_OK ){ - if( pBt && pBt->pPager ){ - sqlite3PagerClose(pBt->pPager, 0); - } - sqlite3_free(pBt); - sqlite3_free(p); - *ppBtree = 0; - }else{ - sqlite3_file *pFile; - - /* If the B-Tree was successfully opened, set the pager-cache size to the - ** default value. Except, when opening on an existing shared pager-cache, - ** do not change the pager-cache size. - */ - if( sqlite3BtreeSchema(p, 0, 0)==0 ){ - sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE); - } - - pFile = sqlite3PagerFile(pBt->pPager); - if( pFile->pMethods ){ - sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); - } - } - if( mutexOpen ){ - assert( sqlite3_mutex_held(mutexOpen) ); - sqlite3_mutex_leave(mutexOpen); - } - assert( rc!=SQLITE_OK || sqlite3BtreeConnectionCount(*ppBtree)>0 ); - return rc; -} - -/* -** Decrement the BtShared.nRef counter. When it reaches zero, -** remove the BtShared structure from the sharing list. Return -** true if the BtShared.nRef counter reaches zero and return -** false if it is still positive. -*/ -static int removeFromSharingList(BtShared *pBt){ -#ifndef SQLITE_OMIT_SHARED_CACHE - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) - BtShared *pList; - int removed = 0; - - assert( sqlite3_mutex_notheld(pBt->mutex) ); - MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(pMainMtx); - pBt->nRef--; - if( pBt->nRef<=0 ){ - if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){ - GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext; - }else{ - pList = GLOBAL(BtShared*,sqlite3SharedCacheList); - while( ALWAYS(pList) && pList->pNext!=pBt ){ - pList=pList->pNext; - } - if( ALWAYS(pList) ){ - pList->pNext = pBt->pNext; - } - } - if( SQLITE_THREADSAFE ){ - sqlite3_mutex_free(pBt->mutex); - } - removed = 1; - } - sqlite3_mutex_leave(pMainMtx); - return removed; -#else - return 1; -#endif -} - -/* -** Make sure pBt->pTmpSpace points to an allocation of -** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child -** pointer. -*/ -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 = 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 uninitialized - ** 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; -} - -/* -** Free the pBt->pTmpSpace allocation -*/ -static void freeTempSpace(BtShared *pBt){ - if( pBt->pTmpSpace ){ - pBt->pTmpSpace -= 4; - sqlite3PageFree(pBt->pTmpSpace); - pBt->pTmpSpace = 0; - } -} - -/* -** Close an open database and invalidate all cursors. -*/ -SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ - BtShared *pBt = p->pBt; - - /* Close all cursors opened via this handle. */ - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - - /* 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 sqlite3BtreeRollback() drops any table-locks held by - ** this handle. - */ - sqlite3BtreeRollback(p, SQLITE_OK, 0); - sqlite3BtreeLeave(p); - - /* If there are still other outstanding references to the shared-btree - ** structure, return now. The remainder of this procedure cleans - ** up the shared-btree. - */ - assert( p->wantToLock==0 && p->locked==0 ); - if( !p->sharable || removeFromSharingList(pBt) ){ - /* The pBt is no longer on the sharing list, so we can access - ** it without having to hold the mutex. - ** - ** Clean out and delete the BtShared object. - */ - assert( !pBt->pCursor ); - sqlite3PagerClose(pBt->pPager, p->db); - if( pBt->xFreeSchema && pBt->pSchema ){ - pBt->xFreeSchema(pBt->pSchema); - } - sqlite3DbFree(0, pBt->pSchema); - freeTempSpace(pBt); - sqlite3_free(pBt); - } - -#ifndef SQLITE_OMIT_SHARED_CACHE - assert( p->wantToLock==0 ); - assert( p->locked==0 ); - if( p->pPrev ) p->pPrev->pNext = p->pNext; - if( p->pNext ) p->pNext->pPrev = p->pPrev; -#endif - - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Change the "soft" limit on the number of pages in the cache. -** Unused and unmodified pages will be recycled when the number of -** pages in the cache exceeds this soft limit. But the size of the -** cache is allowed to grow larger than this limit if it contains -** dirty pages or pages still in active use. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - sqlite3PagerSetCachesize(pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} - -/* -** Change the "spill" limit on the number of pages in the cache. -** If the number of pages exceeds this limit during a write transaction, -** the pager might attempt to "spill" pages to the journal early in -** order to free up memory. -** -** The value returned is the current spill size. If zero is passed -** as an argument, no changes are made to the spill size setting, so -** using mxPage of 0 is a way to query the current spill size. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){ - BtShared *pBt = p->pBt; - int res; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return res; -} - -#if SQLITE_MAX_MMAP_SIZE>0 -/* -** Change the limit on the amount of the database file that may be -** memory mapped. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - sqlite3PagerSetMmapLimit(pBt->pPager, szMmap); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* -** Change the way data is synced to disk in order to increase or decrease -** how well the database resists damage due to OS crashes and power -** failures. Level 1 is the same as asynchronous (no syncs() occur and -** there is a high probability of damage) Level 2 is the default. There -** is a very low but non-zero probability of damage. Level 3 reduces the -** probability of damage to near zero but with a write performance reduction. -*/ -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags( - Btree *p, /* The btree to set the safety level on */ - unsigned pgFlags /* Various PAGER_* flags */ -){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - sqlite3PagerSetFlags(pBt->pPager, pgFlags); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} -#endif - -/* -** Change the default pages size and the number of reserved bytes per page. -** Or, if the page size has already been fixed, return SQLITE_READONLY -** without changing anything. -** -** The page size must be a power of 2 between 512 and 65536. If the page -** size supplied does not meet this constraint then the page size is not -** changed. -** -** Page sizes are constrained to be a power of two so that the region -** of the database file used for locking (beginning at PENDING_BYTE, -** the first byte past the 1GB boundary, 0x40000000) needs to occur -** at the beginning of a page. -** -** If parameter nReserve is less than zero, then the number of reserved -** bytes per page is left unchanged. -** -** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size -** and autovacuum mode can no longer be changed. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ - int rc = SQLITE_OK; - int x; - BtShared *pBt = p->pBt; - assert( nReserve>=0 && nReserve<=255 ); - sqlite3BtreeEnter(p); - pBt->nReserveWanted = (u8)nReserve; - x = pBt->pageSize - pBt->usableSize; - if( nReservebtsFlags & BTS_PAGESIZE_FIXED ){ - sqlite3BtreeLeave(p); - return SQLITE_READONLY; - } - assert( nReserve>=0 && nReserve<=255 ); - if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && - ((pageSize-1)&pageSize)==0 ){ - assert( (pageSize & 7)==0 ); - assert( !pBt->pCursor ); - if( nReserve>32 && pageSize==512 ) pageSize = 1024; - pBt->pageSize = (u32)pageSize; - freeTempSpace(pBt); - } - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); - pBt->usableSize = pBt->pageSize - (u16)nReserve; - if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED; - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Return the currently defined page size -*/ -SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ - return p->pBt->pageSize; -} - -/* -** This function is similar to sqlite3BtreeGetReserve(), except that it -** may only be called if it is guaranteed that the b-tree mutex is already -** held. -** -** This is useful in one special case in the backup API code where it is -** known that the shared b-tree mutex is held, but the mutex on the -** database handle that owns *p is not. In this case if sqlite3BtreeEnter() -** were to be called, it might collide with some other operation on the -** database handle that owns *p, causing undefined behavior. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ - int n; - assert( sqlite3_mutex_held(p->pBt->mutex) ); - n = p->pBt->pageSize - p->pBt->usableSize; - return n; -} - -/* -** Return the number of bytes of space at the end of every page that -** are intentionally left unused. This is the "reserved" space that is -** sometimes used by extensions. -** -** The value returned is the larger of the current reserve size and -** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES. -** The amount of reserve can only grow - never shrink. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){ - int n1, n2; - sqlite3BtreeEnter(p); - n1 = (int)p->pBt->nReserveWanted; - n2 = sqlite3BtreeGetReserveNoMutex(p); - sqlite3BtreeLeave(p); - return n1>n2 ? n1 : n2; -} - - -/* -** Set the maximum page count for a database if mxPage is positive. -** No changes are made if mxPage is 0 or negative. -** Regardless of the value of mxPage, return the maximum page count. -*/ -SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){ - Pgno n; - sqlite3BtreeEnter(p); - n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return n; -} - -/* -** Change the values for the BTS_SECURE_DELETE and BTS_OVERWRITE flags: -** -** newFlag==0 Both BTS_SECURE_DELETE and BTS_OVERWRITE are cleared -** newFlag==1 BTS_SECURE_DELETE set and BTS_OVERWRITE is cleared -** newFlag==2 BTS_SECURE_DELETE cleared and BTS_OVERWRITE is set -** newFlag==(-1) No changes -** -** This routine acts as a query if newFlag is less than zero -** -** With BTS_OVERWRITE set, deleted content is overwritten by zeros, but -** freelist leaf pages are not written back to the database. Thus in-page -** deleted content is cleared, but freelist deleted content is not. -** -** With BTS_SECURE_DELETE, operation is like BTS_OVERWRITE with the addition -** that freelist leaf pages are written back into the database, increasing -** the amount of disk I/O. -*/ -SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ - int b; - if( p==0 ) return 0; - sqlite3BtreeEnter(p); - assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 ); - assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) ); - if( newFlag>=0 ){ - p->pBt->btsFlags &= ~BTS_FAST_SECURE; - p->pBt->btsFlags |= (u16)(BTS_SECURE_DELETE*newFlag); - } - b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE; - sqlite3BtreeLeave(p); - return b; -} - -/* -** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' -** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it -** is disabled. The default value for the auto-vacuum property is -** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ -#ifdef SQLITE_OMIT_AUTOVACUUM - return SQLITE_READONLY; -#else - BtShared *pBt = p->pBt; - int rc = SQLITE_OK; - u8 av = (u8)autoVacuum; - - sqlite3BtreeEnter(p); - if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){ - rc = SQLITE_READONLY; - }else{ - pBt->autoVacuum = av ?1:0; - pBt->incrVacuum = av==2 ?1:0; - } - sqlite3BtreeLeave(p); - return rc; -#endif -} - -/* -** Return the value of the 'auto-vacuum' property. If auto-vacuum is -** enabled 1 is returned. Otherwise 0. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ -#ifdef SQLITE_OMIT_AUTOVACUUM - return BTREE_AUTOVACUUM_NONE; -#else - int rc; - sqlite3BtreeEnter(p); - rc = ( - (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: - (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: - BTREE_AUTOVACUUM_INCR - ); - sqlite3BtreeLeave(p); - return rc; -#endif -} - -/* -** If the user has not set the safety-level for this database connection -** using "PRAGMA synchronous", and if the safety-level is not already -** set to the value passed to this function as the second parameter, -** set it so. -*/ -#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \ - && !defined(SQLITE_OMIT_WAL) -static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ - sqlite3 *db; - Db *pDb; - if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){ - while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; } - if( pDb->bSyncSet==0 - && pDb->safety_level!=safety_level - && pDb!=&db->aDb[1] - ){ - pDb->safety_level = safety_level; - sqlite3PagerSetFlags(pBt->pPager, - pDb->safety_level | (db->flags & PAGER_FLAGS_MASK)); - } - } -} -#else -# define setDefaultSyncFlag(pBt,safety_level) -#endif - -/* Forward declaration */ -static int newDatabase(BtShared*); - - -/* -** Get a reference to pPage1 of the database file. This will -** also acquire a readlock on that file. -** -** SQLITE_OK is returned on success. If the file is not a -** well-formed database file, then SQLITE_CORRUPT is returned. -** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM -** is returned if we run out of memory. -*/ -static int lockBtree(BtShared *pBt){ - int rc; /* Result code from subfunctions */ - 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 */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pBt->pPage1==0 ); - rc = sqlite3PagerSharedLock(pBt->pPager); - if( rc!=SQLITE_OK ) return rc; - rc = btreeGetPage(pBt, 1, &pPage1, 0); - if( rc!=SQLITE_OK ) return rc; - - /* Do some checking to help insure the file we opened really is - ** a valid database file. - */ - nPage = get4byte(28+(u8*)pPage1->aData); - sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile); - if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ - nPage = nPageFile; - } - if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ - nPage = 0; - } - if( nPage>0 ){ - u32 pageSize; - u32 usableSize; - u8 *page1 = pPage1->aData; - rc = SQLITE_NOTADB; - /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins - ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d - ** 61 74 20 33 00. */ - if( memcmp(page1, zMagicHeader, 16)!=0 ){ - goto page1_init_failed; - } - -#ifdef SQLITE_OMIT_WAL - if( page1[18]>1 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } - if( page1[19]>1 ){ - goto page1_init_failed; - } -#else - if( page1[18]>2 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } - if( page1[19]>2 ){ - goto page1_init_failed; - } - - /* 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 - ** required as the version of page 1 currently in the page1 buffer - ** may not be the latest version - there may be a newer one in the log - ** file. - */ - if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){ - int isOpen = 0; - rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); - if( rc!=SQLITE_OK ){ - goto page1_init_failed; - }else{ - setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1); - if( isOpen==0 ){ - releasePageOne(pPage1); - return SQLITE_OK; - } - } - rc = SQLITE_NOTADB; - }else{ - setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1); - } -#endif - - /* EVIDENCE-OF: R-15465-20813 The maximum and minimum embedded payload - ** fractions and the leaf payload fraction values must be 64, 32, and 32. - ** - ** The original design allowed these amounts to vary, but as of - ** version 3.6.0, we require them to be fixed. - */ - if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ - goto page1_init_failed; - } - /* EVIDENCE-OF: R-51873-39618 The page size for a database file is - ** determined by the 2-byte integer located at an offset of 16 bytes from - ** the beginning of the database file. */ - pageSize = (page1[16]<<8) | (page1[17]<<16); - /* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two - ** between 512 and 65536 inclusive. */ - if( ((pageSize-1)&pageSize)!=0 - || pageSize>SQLITE_MAX_PAGE_SIZE - || pageSize<=256 - ){ - goto page1_init_failed; - } - assert( (pageSize & 7)==0 ); - /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte - ** integer at offset 20 is the number of bytes of space at the end of - ** each page to reserve for extensions. - ** - ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is - ** determined by the one-byte unsigned integer found at an offset of 20 - ** into the database file header. */ - usableSize = pageSize - page1[20]; - if( (u32)pageSize!=pBt->pageSize ){ - /* After reading the first page of the database assuming a page size - ** of BtShared.pageSize, we have discovered that the page-size is - ** actually pageSize. Unlock the database, leave pBt->pPage1 at - ** zero and return SQLITE_OK. The caller will call this function - ** again with the correct page-size. - */ - releasePageOne(pPage1); - pBt->usableSize = usableSize; - pBt->pageSize = pageSize; - pBt->btsFlags |= BTS_PAGESIZE_FIXED; - freeTempSpace(pBt); - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, - pageSize-usableSize); - return rc; - } - if( nPage>nPageFile ){ - if( 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 - ** reserved space size cannot exceed 32. */ - if( usableSize<480 ){ - goto page1_init_failed; - } - pBt->btsFlags |= BTS_PAGESIZE_FIXED; - pBt->pageSize = pageSize; - pBt->usableSize = usableSize; -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); - pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); -#endif - } - - /* maxLocal is the maximum amount of payload to store locally for - ** a cell. Make sure it is small enough so that at least minFanout - ** cells can will fit on one page. We assume a 10-byte page header. - ** Besides the payload, the cell must store: - ** 2-byte pointer to the cell - ** 4-byte child pointer - ** 9-byte nKey value - ** 4-byte nData value - ** 4-byte overflow page pointer - ** So a cell consists of a 2-byte pointer, a header which is as much as - ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow - ** page pointer. - */ - pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23); - pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23); - pBt->maxLeaf = (u16)(pBt->usableSize - 35); - pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23); - if( pBt->maxLocal>127 ){ - pBt->max1bytePayload = 127; - }else{ - pBt->max1bytePayload = (u8)pBt->maxLocal; - } - assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); - pBt->pPage1 = pPage1; - pBt->nPage = nPage; - return SQLITE_OK; - -page1_init_failed: - releasePageOne(pPage1); - pBt->pPage1 = 0; - return rc; -} - -#ifndef NDEBUG -/* -** Return the number of cursors open on pBt. This is for use -** in assert() expressions, so it is only compiled if NDEBUG is not -** defined. -** -** Only write cursors are counted if wrOnly is true. If wrOnly is -** false then all cursors are counted. -** -** For the purposes of this routine, a cursor is any cursor that -** is capable of reading or writing to the database. Cursors that -** have been tripped into the CURSOR_FAULT state are not counted. -*/ -static int countValidCursors(BtShared *pBt, int wrOnly){ - BtCursor *pCur; - int r = 0; - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0) - && pCur->eState!=CURSOR_FAULT ) r++; - } - return r; -} -#endif - -/* -** If there are no outstanding cursors and we are not in the middle -** of a transaction but there is a read lock on the database, then -** this routine unrefs the first page of the database file which -** has the effect of releasing the read lock. -** -** If there is a transaction in progress, this routine is a no-op. -*/ -static void unlockBtreeIfUnused(BtShared *pBt){ - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE ); - if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ - MemPage *pPage1 = pBt->pPage1; - assert( pPage1->aData ); - assert( sqlite3PagerRefcount(pBt->pPager)==1 ); - pBt->pPage1 = 0; - releasePageOne(pPage1); - } -} - -/* -** If pBt points to an empty file then convert that empty file -** into a new empty database by initializing the first page of -** the database. -*/ -static int newDatabase(BtShared *pBt){ - MemPage *pP1; - unsigned char *data; - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->nPage>0 ){ - return SQLITE_OK; - } - pP1 = pBt->pPage1; - assert( pP1!=0 ); - data = pP1->aData; - rc = sqlite3PagerWrite(pP1->pDbPage); - if( rc ) return rc; - memcpy(data, zMagicHeader, sizeof(zMagicHeader)); - assert( sizeof(zMagicHeader)==16 ); - data[16] = (u8)((pBt->pageSize>>8)&0xff); - data[17] = (u8)((pBt->pageSize>>16)&0xff); - data[18] = 1; - data[19] = 1; - assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize); - data[20] = (u8)(pBt->pageSize - pBt->usableSize); - data[21] = 64; - data[22] = 32; - data[23] = 32; - memset(&data[24], 0, 100-24); - zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); - pBt->btsFlags |= BTS_PAGESIZE_FIXED; -#ifndef SQLITE_OMIT_AUTOVACUUM - assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); - assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); - put4byte(&data[36 + 4*4], pBt->autoVacuum); - put4byte(&data[36 + 7*4], pBt->incrVacuum); -#endif - pBt->nPage = 1; - data[31] = 1; - return SQLITE_OK; -} - -/* -** Initialize the first page of the database file (creating a database -** consisting of a single page and no schema objects). Return SQLITE_OK -** if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ - int rc; - sqlite3BtreeEnter(p); - p->pBt->nPage = 0; - rc = newDatabase(p->pBt); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Attempt to start a new transaction. A write-transaction -** is started if the second argument is nonzero, otherwise a read- -** transaction. If the second argument is 2 or more and exclusive -** transaction is started, meaning that no other process is allowed -** to access the database. A preexisting transaction may not be -** upgraded to exclusive by calling this routine a second time - the -** exclusivity flag only works for a new transaction. -** -** A write-transaction must be started before attempting any -** changes to the database. None of the following routines -** will work unless a transaction is started first: -** -** sqlite3BtreeCreateTable() -** sqlite3BtreeCreateIndex() -** sqlite3BtreeClearTable() -** sqlite3BtreeDropTable() -** sqlite3BtreeInsert() -** sqlite3BtreeDelete() -** sqlite3BtreeUpdateMeta() -** -** If an initial attempt to acquire the lock fails because of lock contention -** and the database was previously unlocked, then invoke the busy handler -** if there is one. But if there was previously a read-lock, do not -** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is -** returned when there is already a read-lock in order to avoid a deadlock. -** -** Suppose there are two processes A and B. A has a read lock and B has -** a reserved lock. B tries to promote to exclusive but is blocked because -** of A's read lock. A tries to promote to reserved but is blocked by B. -** One or the other of the two processes must give way or there can be -** no progress. By returning SQLITE_BUSY and not invoking the busy callback -** when A already has a read lock, we encourage A to give up and let B -** proceed. -*/ -static SQLITE_NOINLINE int btreeBeginTrans( - Btree *p, /* The btree in which to start the transaction */ - int wrflag, /* True to start a write transaction */ - int *pSchemaVersion /* Put schema version number here, if not NULL */ -){ - BtShared *pBt = p->pBt; - Pager *pPager = pBt->pPager; - int rc = SQLITE_OK; - - sqlite3BtreeEnter(p); - btreeIntegrity(p); - - /* If the btree is already in a write-transaction, or it - ** is already in a read-transaction and a read-transaction - ** is requested, this is a no-op. - */ - if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ - goto trans_begun; - } - assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); - - if( (p->db->flags & SQLITE_ResetDatabase) - && sqlite3PagerIsreadonly(pPager)==0 - ){ - pBt->btsFlags &= ~BTS_READ_ONLY; - } - - /* Write transactions are not possible on a read-only database */ - if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ - rc = SQLITE_READONLY; - goto trans_begun; - } - -#ifndef SQLITE_OMIT_SHARED_CACHE - { - sqlite3 *pBlock = 0; - /* If another database handle has already opened a write transaction - ** on this shared-btree structure and a second write transaction is - ** requested, return SQLITE_LOCKED. - */ - if( (wrflag && pBt->inTransaction==TRANS_WRITE) - || (pBt->btsFlags & BTS_PENDING)!=0 - ){ - pBlock = pBt->pWriter->db; - }else if( wrflag>1 ){ - BtLock *pIter; - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - if( pIter->pBtree!=p ){ - pBlock = pIter->pBtree->db; - break; - } - } - } - if( pBlock ){ - sqlite3ConnectionBlocked(p->db, pBlock); - rc = SQLITE_LOCKED_SHAREDCACHE; - goto trans_begun; - } - } -#endif - - /* Any read-only or read-write transaction implies a read-lock on - ** page 1. So if some other shared-cache client already has a write-lock - ** on page 1, the transaction cannot be opened. */ - rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); - if( SQLITE_OK!=rc ) goto trans_begun; - - pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; - if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; - do { - sqlite3PagerWalDb(pPager, p->db); - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If transitioning from no transaction directly to a write transaction, - ** block for the WRITER lock first if possible. */ - if( pBt->pPage1==0 && wrflag ){ - assert( pBt->inTransaction==TRANS_NONE ); - rc = sqlite3PagerWalWriteLock(pPager, 1); - if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break; - } -#endif - - /* Call lockBtree() until either pBt->pPage1 is populated or - ** lockBtree() returns something other than SQLITE_OK. lockBtree() - ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after - ** reading page 1 it discovers that the page-size of the database - ** file is not pBt->pageSize. In this case lockBtree() will update - ** pBt->pageSize to the page-size of the file on disk. - */ - while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) ); - - if( rc==SQLITE_OK && wrflag ){ - if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){ - rc = SQLITE_READONLY; - }else{ - rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db)); - if( rc==SQLITE_OK ){ - rc = newDatabase(pBt); - }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){ - /* if there was no transaction opened when this function was - ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error - ** code to SQLITE_BUSY. */ - rc = SQLITE_BUSY; - } - } - } - - if( rc!=SQLITE_OK ){ - (void)sqlite3PagerWalWriteLock(pPager, 0); - unlockBtreeIfUnused(pBt); - } -#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) - if( rc==SQLITE_BUSY_TIMEOUT ){ - /* If a blocking lock timed out, break out of the loop here so that - ** the busy-handler is not invoked. */ - break; - } -#endif - }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && - btreeInvokeBusyHandler(pBt) ); - sqlite3PagerWalDb(pPager, 0); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; -#endif - - if( rc==SQLITE_OK ){ - if( p->inTrans==TRANS_NONE ){ - pBt->nTransaction++; -#ifndef SQLITE_OMIT_SHARED_CACHE - if( p->sharable ){ - assert( p->lock.pBtree==p && p->lock.iTable==1 ); - p->lock.eLock = READ_LOCK; - p->lock.pNext = pBt->pLock; - pBt->pLock = &p->lock; - } -#endif - } - p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); - if( p->inTrans>pBt->inTransaction ){ - pBt->inTransaction = p->inTrans; - } - if( wrflag ){ - MemPage *pPage1 = pBt->pPage1; -#ifndef SQLITE_OMIT_SHARED_CACHE - assert( !pBt->pWriter ); - pBt->pWriter = p; - pBt->btsFlags &= ~BTS_EXCLUSIVE; - if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE; -#endif - - /* If the db-size header field is incorrect (as it may be if an old - ** client has been writing the database file), update it now. Doing - ** this sooner rather than later means the database size can safely - ** re-read the database size from page 1 if a savepoint or transaction - ** rollback occurs within the transaction. - */ - if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pPage1->aData[28], pBt->nPage); - } - } - } - } - -trans_begun: - if( rc==SQLITE_OK ){ - if( pSchemaVersion ){ - *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); - } - if( wrflag ){ - /* This call makes sure that the pager has the correct number of - ** open savepoints. If the second parameter is greater than 0 and - ** the sub-journal is not already open, then it will be opened here. - */ - rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint); - } - } - - btreeIntegrity(p); - sqlite3BtreeLeave(p); - return rc; -} -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ - BtShared *pBt; - if( p->sharable - || p->inTrans==TRANS_NONE - || (p->inTrans==TRANS_READ && wrflag!=0) - ){ - return btreeBeginTrans(p,wrflag,pSchemaVersion); - } - pBt = p->pBt; - if( pSchemaVersion ){ - *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); - } - if( wrflag ){ - /* This call makes sure that the pager has the correct number of - ** open savepoints. If the second parameter is greater than 0 and - ** the sub-journal is not already open, then it will be opened here. - */ - return sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); - }else{ - return SQLITE_OK; - } -} - -#ifndef SQLITE_OMIT_AUTOVACUUM - -/* -** Set the pointer-map entries for all children of page pPage. Also, if -** pPage contains cells that point to overflow pages, set the pointer -** map entries for the overflow pages as well. -*/ -static int setChildPtrmaps(MemPage *pPage){ - int i; /* Counter variable */ - int nCell; /* Number of cells in page pPage */ - int rc; /* Return code */ - BtShared *pBt = pPage->pBt; - Pgno pgno = pPage->pgno; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage); - if( rc!=SQLITE_OK ) return rc; - nCell = pPage->nCell; - - for(i=0; ileaf ){ - Pgno childPgno = get4byte(pCell); - ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); - } - } - - if( !pPage->leaf ){ - Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); - } - - return rc; -} - -/* -** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so -** that it points to iTo. Parameter eType describes the type of pointer to -** be modified, as follows: -** -** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child -** page of pPage. -** -** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow -** page pointed to by one of the cells on pPage. -** -** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next -** overflow page in the list. -*/ -static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - if( eType==PTRMAP_OVERFLOW2 ){ - /* The pointer is always the first 4 bytes of the page in this case. */ - if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - put4byte(pPage->aData, iTo); - }else{ - int i; - int nCell; - int rc; - - rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage); - if( rc ) return rc; - nCell = pPage->nCell; - - for(i=0; ixParseCell(pPage, pCell, &info); - if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( iFrom==get4byte(pCell+info.nSize-4) ){ - put4byte(pCell+info.nSize-4, iTo); - break; - } - } - }else{ - if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( get4byte(pCell)==iFrom ){ - put4byte(pCell, iTo); - break; - } - } - } - - if( i==nCell ){ - if( eType!=PTRMAP_BTREE || - get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); - } - } - return SQLITE_OK; -} - - -/* -** Move the open database page pDbPage to location iFreePage in the -** database. The pDbPage reference remains valid. -** -** The isCommit flag indicates that there is no need to remember that -** the journal needs to be sync()ed before database page pDbPage->pgno -** can be written to. The caller has already promised not to write to that -** page. -*/ -static int relocatePage( - BtShared *pBt, /* Btree */ - MemPage *pDbPage, /* Open page to move */ - u8 eType, /* Pointer map 'type' entry for pDbPage */ - Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ - Pgno iFreePage, /* The location to move pDbPage to */ - int isCommit /* isCommit flag passed to sqlite3PagerMovepage */ -){ - MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ - Pgno iDbPage = pDbPage->pgno; - Pager *pPager = pBt->pPager; - int rc; - - assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || - eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pDbPage->pBt==pBt ); - if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; - - /* Move page iDbPage from its current location to page number iFreePage */ - TRACE(("AUTOVACUUM: Moving %u to free page %u (ptr page %u type %u)\n", - iDbPage, iFreePage, iPtrPage, eType)); - rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); - if( rc!=SQLITE_OK ){ - return rc; - } - pDbPage->pgno = iFreePage; - - /* If pDbPage was a btree-page, then it may have child pages and/or cells - ** that point to overflow pages. The pointer map entries for all these - ** pages need to be changed. - ** - ** If pDbPage is an overflow page, then the first 4 bytes may store a - ** pointer to a subsequent overflow page. If this is the case, then - ** the pointer map needs to be updated for the subsequent overflow page. - */ - if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ - rc = setChildPtrmaps(pDbPage); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - Pgno nextOvfl = get4byte(pDbPage->aData); - if( nextOvfl!=0 ){ - ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc); - if( rc!=SQLITE_OK ){ - return rc; - } - } - } - - /* Fix the database pointer on page iPtrPage that pointed at iDbPage so - ** that it points at iFreePage. Also fix the pointer map entry for - ** iPtrPage. - */ - if( eType!=PTRMAP_ROOTPAGE ){ - rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = sqlite3PagerWrite(pPtrPage->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pPtrPage); - return rc; - } - rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); - releasePage(pPtrPage); - if( rc==SQLITE_OK ){ - ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc); - } - } - return rc; -} - -/* Forward declaration required by incrVacuumStep(). */ -static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); - -/* -** Perform a single step of an incremental-vacuum. If successful, return -** SQLITE_OK. If there is no work to do (and therefore no point in -** calling this function again), return SQLITE_DONE. Or, if an error -** occurs, return some other error code. -** -** More specifically, this function attempts to re-organize the database so -** that the last page of the file currently in use is no longer in use. -** -** Parameter nFin is the number of pages that this database would contain -** were this function called until it returns SQLITE_DONE. -** -** If the bCommit parameter is non-zero, this function assumes that the -** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE -** or an error. bCommit is passed true for an auto-vacuum-on-commit -** operation, or false for an incremental vacuum. -*/ -static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ - Pgno nFreeList; /* Number of pages still on the free-list */ - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( iLastPg>nFin ); - - if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ - u8 eType; - Pgno iPtrPage; - - nFreeList = get4byte(&pBt->pPage1->aData[36]); - if( nFreeList==0 ){ - return SQLITE_DONE; - } - - rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); - if( rc!=SQLITE_OK ){ - return rc; - } - if( eType==PTRMAP_ROOTPAGE ){ - return SQLITE_CORRUPT_BKPT; - } - - if( eType==PTRMAP_FREEPAGE ){ - if( bCommit==0 ){ - /* Remove the page from the files free-list. This is not required - ** if bCommit is non-zero. In that case, the free-list will be - ** truncated to zero after this function returns, so it doesn't - ** matter if it still contains some garbage entries. - */ - Pgno iFreePg; - MemPage *pFreePg; - rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( iFreePg==iLastPg ); - releasePage(pFreePg); - } - } else { - Pgno iFreePg; /* Index of free page to move pLastPg to */ - MemPage *pLastPg; - u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ - Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ - - rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* If bCommit is zero, this loop runs exactly once and page pLastPg - ** is swapped with the first free page pulled off the free list. - ** - ** On the other hand, if bCommit is greater than zero, then keep - ** looping until a free-page located within the first nFin pages - ** of the file is found. - */ - if( bCommit==0 ){ - eMode = BTALLOC_LE; - iNear = nFin; - } - 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( iFreePgbDoTruncate = 1; - pBt->nPage = iLastPg; - } - return SQLITE_OK; -} - -/* -** The database opened by the first argument is an auto-vacuum database -** nOrig pages in size containing nFree free pages. Return the expected -** size of the database in pages following an auto-vacuum operation. -*/ -static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ - int nEntry; /* Number of entries on one ptrmap page */ - Pgno nPtrmap; /* Number of PtrMap pages to be freed */ - Pgno nFin; /* Return value */ - - nEntry = pBt->usableSize/5; - nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; - nFin = nOrig - nFree - nPtrmap; - if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinpBt; - - sqlite3BtreeEnter(p); - assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); - if( !pBt->autoVacuum ){ - rc = SQLITE_DONE; - }else{ - Pgno nOrig = btreePagecount(pBt); - Pgno nFree = get4byte(&pBt->pPage1->aData[36]); - Pgno nFin = finalDbSize(pBt, nOrig, nFree); - - if( nOrig=nOrig ){ - rc = SQLITE_CORRUPT_BKPT; - }else if( nFree>0 ){ - rc = saveAllCursors(pBt, 0, 0); - if( rc==SQLITE_OK ){ - invalidateAllOverflowCache(pBt); - rc = incrVacuumStep(pBt, nFin, nOrig, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - put4byte(&pBt->pPage1->aData[28], pBt->nPage); - } - }else{ - rc = SQLITE_DONE; - } - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** This routine is called prior to sqlite3PagerCommit when a transaction -** is committed for an auto-vacuum database. -*/ -static int autoVacuumCommit(Btree *p){ - int rc = SQLITE_OK; - Pager *pPager; - BtShared *pBt; - sqlite3 *db; - VVA_ONLY( int nRef ); - - assert( p!=0 ); - pBt = p->pBt; - pPager = pBt->pPager; - VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); ) - - assert( sqlite3_mutex_held(pBt->mutex) ); - invalidateAllOverflowCache(pBt); - assert(pBt->autoVacuum); - 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 */ - - nOrig = btreePagecount(pBt); - if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ - /* It is not possible to create a database for which the final page - ** is either a pointer-map page or the pending-byte page. If one - ** is encountered, this indicates corruption. - */ - return SQLITE_CORRUPT_BKPT; - } - - nFree = get4byte(&pBt->pPage1->aData[36]); - db = p->db; - if( db->xAutovacPages ){ - int iDb; - for(iDb=0; ALWAYS(iDbnDb); 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( nFinnFin && rc==SQLITE_OK; iFree--){ - rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree); - } - if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - 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; - } - if( rc!=SQLITE_OK ){ - sqlite3PagerRollback(pPager); - } - } - - assert( nRef>=sqlite3PagerRefcount(pPager) ); - return rc; -} - -#else /* ifndef SQLITE_OMIT_AUTOVACUUM */ -# define setChildPtrmaps(x) SQLITE_OK -#endif - -/* -** This routine does the first phase of a two-phase commit. This routine -** causes a rollback journal to be created (if it does not already exist) -** and populated with enough information so that if a power loss occurs -** the database can be restored to its original state by playing back -** the journal. Then the contents of the journal are flushed out to -** the disk. After the journal is safely on oxide, the changes to the -** database are written into the database file and flushed to oxide. -** At the end of this call, the rollback journal still exists on the -** disk and we are still holding all locks, so the transaction has not -** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the -** commit process. -** -** This call is a no-op if no write-transaction is currently active on pBt. -** -** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to -** the name of a super-journal file that should be written into the -** individual journal file, or is NULL, indicating no super-journal file -** (single database transaction). -** -** When this is called, the super-journal should already have been -** created, populated with this journal pointer and synced to disk. -** -** Once this is routine has returned, the only thing required to commit -** the write-transaction for this database file is to delete the journal. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){ - int rc = SQLITE_OK; - if( p->inTrans==TRANS_WRITE ){ - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - rc = autoVacuumCommit(p); - if( rc!=SQLITE_OK ){ - sqlite3BtreeLeave(p); - return rc; - } - } - if( pBt->bDoTruncate ){ - sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); - } -#endif - rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0); - sqlite3BtreeLeave(p); - } - return rc; -} - -/* -** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() -** at the conclusion of a transaction. -*/ -static void btreeEndTransaction(Btree *p){ - BtShared *pBt = p->pBt; - sqlite3 *db = p->db; - assert( sqlite3BtreeHoldsMutex(p) ); - -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->bDoTruncate = 0; -#endif - if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){ - /* If there are other active statements that belong to this database - ** handle, downgrade to a read-only transaction. The other statements - ** may still be reading from the database. */ - downgradeAllSharedCacheTableLocks(p); - p->inTrans = TRANS_READ; - }else{ - /* If the handle had any kind of transaction open, decrement the - ** transaction count of the shared btree. If the transaction count - ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() - ** call below will unlock the pager. */ - if( p->inTrans!=TRANS_NONE ){ - clearAllSharedCacheTableLocks(p); - pBt->nTransaction--; - if( 0==pBt->nTransaction ){ - pBt->inTransaction = TRANS_NONE; - } - } - - /* Set the current transaction state to TRANS_NONE and unlock the - ** pager if this call closed the only read or write transaction. */ - p->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - } - - btreeIntegrity(p); -} - -/* -** Commit the transaction currently in progress. -** -** This routine implements the second phase of a 2-phase commit. The -** sqlite3BtreeCommitPhaseOne() routine does the first phase and should -** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne() -** routine did all the work of writing information out to disk and flushing the -** contents so that they are written onto the disk platter. All this -** routine has to do is delete or truncate or zero the header in the -** the rollback journal (which causes the transaction to commit) and -** drop locks. -** -** Normally, if an error occurs while the pager layer is attempting to -** finalize the underlying journal file, this function returns an error and -** the upper layer will attempt a rollback. However, if the second argument -** is non-zero then this b-tree transaction is part of a multi-file -** transaction. In this case, the transaction has already been committed -** (by deleting a super-journal file) and the caller will ignore this -** functions return code. So, even if an error occurs in the pager layer, -** reset the b-tree objects internal state to indicate that the write -** transaction has been closed. This is quite safe, as the pager will have -** transitioned to the error state. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){ - - if( p->inTrans==TRANS_NONE ) return SQLITE_OK; - sqlite3BtreeEnter(p); - btreeIntegrity(p); - - /* If the handle has a write-transaction open, commit the shared-btrees - ** transaction and set the shared state to TRANS_READ. - */ - if( p->inTrans==TRANS_WRITE ){ - int rc; - BtShared *pBt = p->pBt; - assert( pBt->inTransaction==TRANS_WRITE ); - assert( pBt->nTransaction>0 ); - rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); - if( rc!=SQLITE_OK && bCleanup==0 ){ - sqlite3BtreeLeave(p); - return rc; - } - p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */ - pBt->inTransaction = TRANS_READ; - btreeClearHasContent(pBt); - } - - btreeEndTransaction(p); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} - -/* -** Do both phases of a commit. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ - int rc; - sqlite3BtreeEnter(p); - rc = sqlite3BtreeCommitPhaseOne(p, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeCommitPhaseTwo(p, 0); - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** This routine sets the state to CURSOR_FAULT and the error -** code to errCode for every cursor on any BtShared that pBtree -** references. Or if the writeOnly flag is set to 1, then only -** trip write cursors and leave read cursors unchanged. -** -** Every cursor is a candidate to be tripped, including cursors -** that belong to other database connections that happen to be -** sharing the cache with pBtree. -** -** This routine gets called when a rollback occurs. If the writeOnly -** flag is true, then only write-cursors need be tripped - read-only -** cursors save their current positions so that they may continue -** following the rollback. Or, if writeOnly is false, all cursors are -** tripped. In general, writeOnly is false if the transaction being -** rolled back modified the database schema. In this case b-tree root -** pages may be moved or deleted from the database altogether, making -** it unsafe for read cursors to continue. -** -** If the writeOnly flag is true and an error is encountered while -** saving the current position of a read-only cursor, all cursors, -** including all read-cursors are tripped. -** -** SQLITE_OK is returned if successful, or if an error occurs while -** saving a cursor position, an SQLite error code. -*/ -SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ - BtCursor *p; - int rc = SQLITE_OK; - - assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); - if( pBtree ){ - sqlite3BtreeEnter(pBtree); - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ - if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ - rc = saveCursorPosition(p); - if( rc!=SQLITE_OK ){ - (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); - break; - } - } - }else{ - sqlite3BtreeClearCursor(p); - p->eState = CURSOR_FAULT; - p->skipNext = errCode; - } - btreeReleaseAllCursorPages(p); - } - sqlite3BtreeLeave(pBtree); - } - return rc; -} - -/* -** Set the pBt->nPage field correctly, according to the current -** state of the database. Assume pBt->pPage1 is valid. -*/ -static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){ - int nPage = get4byte(&pPage1->aData[28]); - testcase( nPage==0 ); - if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); - testcase( pBt->nPage!=(u32)nPage ); - pBt->nPage = nPage; -} - -/* -** Rollback the transaction in progress. -** -** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). -** Only write cursors are tripped if writeOnly is true but all cursors are -** tripped if writeOnly is false. Any attempt to use -** a tripped cursor will result in an error. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ - int rc; - BtShared *pBt = p->pBt; - MemPage *pPage1; - - assert( writeOnly==1 || writeOnly==0 ); - assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK ); - sqlite3BtreeEnter(p); - if( tripCode==SQLITE_OK ){ - rc = tripCode = saveAllCursors(pBt, 0, 0); - if( rc ) writeOnly = 0; - }else{ - rc = SQLITE_OK; - } - if( tripCode ){ - int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly); - assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) ); - if( rc2!=SQLITE_OK ) rc = rc2; - } - btreeIntegrity(p); - - if( p->inTrans==TRANS_WRITE ){ - int rc2; - - assert( TRANS_WRITE==pBt->inTransaction ); - rc2 = sqlite3PagerRollback(pBt->pPager); - if( rc2!=SQLITE_OK ){ - rc = rc2; - } - - /* The rollback may have destroyed the pPage1->aData value. So - ** call btreeGetPage() on page 1 again to make - ** sure pPage1->aData is set correctly. */ - if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ - btreeSetNPage(pBt, pPage1); - releasePageOne(pPage1); - } - assert( countValidCursors(pBt, 1)==0 ); - pBt->inTransaction = TRANS_READ; - btreeClearHasContent(pBt); - } - - btreeEndTransaction(p); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Start a statement subtransaction. The subtransaction can be rolled -** back independently of the main transaction. You must start a transaction -** before starting a subtransaction. The subtransaction is ended automatically -** if the main transaction commits or rolls back. -** -** Statement subtransactions are used around individual SQL statements -** that are contained within a BEGIN...COMMIT block. If a constraint -** error occurs within the statement, the effect of that one statement -** can be rolled back without having to rollback the entire transaction. -** -** A statement sub-transaction is implemented as an anonymous savepoint. The -** value passed as the second parameter is the total number of savepoints, -** including the new anonymous savepoint, open on the B-Tree. i.e. if there -** are no active savepoints and no other statement-transactions open, -** iStatement is 1. This anonymous savepoint can be released or rolled back -** using the sqlite3BtreeSavepoint() function. -*/ -SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){ - int rc; - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( iStatement>0 ); - assert( iStatement>p->db->nSavepoint ); - assert( pBt->inTransaction==TRANS_WRITE ); - /* At the pager level, a statement transaction is a savepoint with - ** an index greater than all savepoints created explicitly using - ** SQL statements. It is illegal to open, release or rollback any - ** such savepoints while the statement transaction savepoint is active. - */ - rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** The second argument to this function, op, is always SAVEPOINT_ROLLBACK -** or SAVEPOINT_RELEASE. This function either releases or rolls back the -** savepoint identified by parameter iSavepoint, depending on the value -** of op. -** -** Normally, iSavepoint is greater than or equal to zero. However, if op is -** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the -** contents of the entire transaction are rolled back. This is different -** from a normal transaction rollback, as no locks are released and the -** transaction remains open. -*/ -SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ - int rc = SQLITE_OK; - if( p && p->inTrans==TRANS_WRITE ){ - BtShared *pBt = p->pBt; - assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); - assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) ); - sqlite3BtreeEnter(p); - if( op==SAVEPOINT_ROLLBACK ){ - rc = saveAllCursors(pBt, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); - } - if( rc==SQLITE_OK ){ - if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){ - pBt->nPage = 0; - } - rc = newDatabase(pBt); - btreeSetNPage(pBt, pBt->pPage1); - - /* pBt->nPage might be zero if the database was corrupt when - ** the transaction was started. Otherwise, it must be at least 1. */ - assert( CORRUPT_DB || pBt->nPage>0 ); - } - sqlite3BtreeLeave(p); - } - return rc; -} - -/* -** Create a new cursor for the BTree whose root is on the page -** iTable. If a read-only cursor is requested, it is assumed that -** the caller already has at least a read-only transaction open -** on the database already. If a write-cursor is requested, then -** the caller is assumed to have an open write transaction. -** -** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only -** be used for reading. If the BTREE_WRCSR bit is set, then the cursor -** can be used for reading or for writing if other conditions for writing -** are also met. These are the conditions that must be met in order -** for writing to be allowed: -** -** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR -** -** 2: Other database connections that share the same pager cache -** but which are not in the READ_UNCOMMITTED state may not have -** cursors open with wrFlag==0 on the same table. Otherwise -** the changes made by this write cursor would be visible to -** the read cursors in the other database connection. -** -** 3: The database must be writable (not on read-only media) -** -** 4: There must be an active transaction. -** -** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR -** is set. If FORDELETE is set, that is a hint to the implementation that -** this cursor will only be used to seek to and delete entries of an index -** as part of a larger DELETE statement. The FORDELETE hint is not used by -** this implementation. But in a hypothetical alternative storage engine -** in which index entries are automatically deleted when corresponding table -** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE -** operations on this cursor can be no-ops and all READ operations can -** return a null row (2-bytes: 0x01 0x00). -** -** No checking is done to make sure that page iTable really is the -** root page of a b-tree. If it is not, then the cursor acquired -** will not work correctly. -** -** It is assumed that the sqlite3BtreeCursorZero() has been called -** on pCur to initialize the memory space prior to invoking this routine. -*/ -static int btreeCursor( - Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to comparison function */ - BtCursor *pCur /* Space for new cursor */ -){ - BtShared *pBt = p->pBt; /* Shared b-tree handle */ - BtCursor *pX; /* Looping over other all cursors */ - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( wrFlag==0 - || wrFlag==BTREE_WRCSR - || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE) - ); - - /* The following assert statements verify that if this is a sharable - ** b-tree database, the connection is holding the required table locks, - ** and that no other connection has any open cursor that conflicts with - ** this lock. The iTable<1 term disables the check for corrupt schemas. */ - assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) - || iTable<1 ); - assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); - - /* Assert that the caller has opened the required transaction. */ - assert( p->inTrans>TRANS_NONE ); - assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); - assert( pBt->pPage1 && pBt->pPage1->aData ); - assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); - - if( iTable<=1 ){ - if( iTable<1 ){ - return SQLITE_CORRUPT_BKPT; - }else if( btreePagecount(pBt)==0 ){ - assert( wrFlag==0 ); - iTable = 0; - } - } - - /* Now that no other errors can occur, finish filling in the BtCursor - ** variables and link the cursor into the BtShared list. */ - pCur->pgnoRoot = iTable; - pCur->iPage = -1; - pCur->pKeyInfo = pKeyInfo; - pCur->pBtree = p; - pCur->pBt = pBt; - 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->eState = CURSOR_INVALID; - pCur->pNext = pBt->pCursor; - pBt->pCursor = pCur; - 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( - Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to comparison function */ - BtCursor *pCur /* Space for new cursor */ -){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); - sqlite3BtreeLeave(p); - return rc; -} -SQLITE_PRIVATE int sqlite3BtreeCursor( - Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ - BtCursor *pCur /* Write new cursor here */ -){ - if( p->sharable ){ - return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur); - }else{ - return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); - } -} - -/* -** Return the size of a BtCursor object in bytes. -** -** This interfaces is needed so that users of cursors can preallocate -** sufficient storage to hold a cursor. The BtCursor object is opaque -** to users so they cannot do the sizeof() themselves - they must call -** this routine. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ - return ROUND8(sizeof(BtCursor)); -} - -#ifdef SQLITE_DEBUG -/* -** Return true if and only if the Btree object will be automatically -** closed with the BtCursor closes. This is used within assert() statements -** only. -*/ -SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor( - Btree *pBtree, /* the btree object */ - BtCursor *pCur /* Corresponding cursor */ -){ - BtShared *pBt = pBtree->pBt; - if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0; - if( pBt->pCursor!=pCur ) return 0; - if( pCur->pNext!=0 ) return 0; - if( pCur->pBtree!=pBtree ) return 0; - return 1; -} -#endif - -/* -** Initialize memory that will be converted into a BtCursor object. -** -** The simple approach here would be to memset() the entire object -** to zero. But it turns out that the apPage[] and aiIdx[] arrays -** do not need to be zeroed and they are large, so we can save a lot -** of run-time by skipping the initialization of those elements. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ - memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT)); -} - -/* -** Close a cursor. The read lock on the database file is released -** when the last cursor is closed. -*/ -SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ - Btree *pBtree = pCur->pBtree; - if( pBtree ){ - BtShared *pBt = pCur->pBt; - sqlite3BtreeEnter(pBtree); - assert( pBt->pCursor!=0 ); - if( pBt->pCursor==pCur ){ - pBt->pCursor = pCur->pNext; - }else{ - BtCursor *pPrev = pBt->pCursor; - do{ - if( pPrev->pNext==pCur ){ - pPrev->pNext = pCur->pNext; - break; - } - pPrev = pPrev->pNext; - }while( ALWAYS(pPrev) ); - } - btreeReleaseAllCursorPages(pCur); - unlockBtreeIfUnused(pBt); - sqlite3_free(pCur->aOverflow); - sqlite3_free(pCur->pKey); - if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){ - /* Since the BtShared is not sharable, there is no need to - ** worry about the missing sqlite3BtreeLeave() call here. */ - assert( pBtree->sharable==0 ); - sqlite3BtreeClose(pBtree); - }else{ - sqlite3BtreeLeave(pBtree); - } - pCur->pBtree = 0; - } - return SQLITE_OK; -} - -/* -** Make sure the BtCursor* given in the argument has a valid -** BtCursor.info structure. If it is not already valid, call -** btreeParseCell() to fill it in. -** -** BtCursor.info is a cache of the information in the current cell. -** Using this cache reduces the number of calls to btreeParseCell(). -*/ -#ifndef NDEBUG - static int cellInfoEqual(CellInfo *a, CellInfo *b){ - if( a->nKey!=b->nKey ) return 0; - if( a->pPayload!=b->pPayload ) return 0; - if( a->nPayload!=b->nPayload ) return 0; - if( a->nLocal!=b->nLocal ) return 0; - if( a->nSize!=b->nSize ) return 0; - return 1; - } - static void assertCellInfo(BtCursor *pCur){ - CellInfo info; - memset(&info, 0, sizeof(info)); - btreeParseCell(pCur->pPage, pCur->ix, &info); - assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) ); - } -#else - #define assertCellInfo(x) -#endif -static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ - if( pCur->info.nSize==0 ){ - pCur->curFlags |= BTCF_ValidNKey; - btreeParseCell(pCur->pPage,pCur->ix,&pCur->info); - }else{ - assertCellInfo(pCur); - } -} - -#ifndef NDEBUG /* The next routine used only within assert() statements */ -/* -** Return true if the given BtCursor is valid. A valid cursor is one -** that is currently pointing to a row in a (non-empty) table. -** This is a verification routine is used only within assert() statements. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ - return pCur && pCur->eState==CURSOR_VALID; -} -#endif /* NDEBUG */ -SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){ - assert( pCur!=0 ); - return pCur->eState==CURSOR_VALID; -} - -/* -** Return the value of the integer key or "rowid" for a table btree. -** This routine is only valid for a cursor that is pointing into a -** ordinary table btree. If the cursor points to an index btree or -** is invalid, the result of this routine is undefined. -*/ -SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->curIntKey ); - getCellInfo(pCur); - return pCur->info.nKey; -} - -/* -** Pin or unpin a cursor. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){ - assert( (pCur->curFlags & BTCF_Pinned)==0 ); - pCur->curFlags |= BTCF_Pinned; -} -SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){ - assert( (pCur->curFlags & BTCF_Pinned)!=0 ); - pCur->curFlags &= ~BTCF_Pinned; -} - -/* -** Return the offset into the database file for the start of the -** payload to which the cursor is pointing. -*/ -SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - getCellInfo(pCur); - return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + - (i64)(pCur->info.pPayload - pCur->pPage->aData); -} - -/* -** Return the number of bytes of payload for the entry that pCur is -** currently pointing to. For table btrees, this will be the amount -** of data. For index btrees, this will be the size of the key. -** -** The caller must guarantee that the cursor is pointing to a non-NULL -** valid entry. In other words, the calling procedure must guarantee -** that the cursor has Cursor.eState==CURSOR_VALID. -*/ -SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - getCellInfo(pCur); - return pCur->info.nPayload; -} - -/* -** Return an upper bound on the size of any record for the table -** that the cursor is pointing into. -** -** This is an optimization. Everything will still work if this -** routine always returns 2147483647 (which is the largest record -** that SQLite can handle) or more. But returning a smaller value might -** prevent large memory allocations when trying to interpret a -** corrupt database. -** -** The current implementation merely returns the size of the underlying -** database file. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage; -} - -/* -** Given the page number of an overflow page in the database (parameter -** ovfl), this function finds the page number of the next page in the -** linked list of overflow pages. If possible, it uses the auto-vacuum -** pointer-map data instead of reading the content of page ovfl to do so. -** -** If an error occurs an SQLite error code is returned. Otherwise: -** -** The page number of the next overflow page in the linked list is -** written to *pPgnoNext. If page ovfl is the last page in its linked -** list, *pPgnoNext is set to zero. -** -** If ppPage is not NULL, and a reference to the MemPage object corresponding -** to page number pOvfl was obtained, then *ppPage is set to point to that -** reference. It is the responsibility of the caller to call releasePage() -** on *ppPage to free the reference. In no reference was obtained (because -** the pointer-map was used to obtain the value for *pPgnoNext), then -** *ppPage is set to zero. -*/ -static int getOverflowPage( - BtShared *pBt, /* The database file */ - Pgno ovfl, /* Current overflow page number */ - MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */ - Pgno *pPgnoNext /* OUT: Next overflow page number */ -){ - Pgno next = 0; - MemPage *pPage = 0; - int rc = SQLITE_OK; - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert(pPgnoNext); - -#ifndef SQLITE_OMIT_AUTOVACUUM - /* Try to find the next page in the overflow list using the - ** autovacuum pointer-map pages. Guess that the next page in - ** the overflow list is page number (ovfl+1). If that guess turns - ** out to be wrong, fall back to loading the data of page - ** number ovfl to determine the next page number. - */ - if( pBt->autoVacuum ){ - Pgno pgno; - Pgno iGuess = ovfl+1; - u8 eType; - - while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ - iGuess++; - } - - if( iGuess<=btreePagecount(pBt) ){ - rc = ptrmapGet(pBt, iGuess, &eType, &pgno); - if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ - next = iGuess; - rc = SQLITE_DONE; - } - } - } -#endif - - assert( next==0 || rc==SQLITE_DONE ); - if( rc==SQLITE_OK ){ - rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0); - assert( rc==SQLITE_OK || pPage==0 ); - if( rc==SQLITE_OK ){ - next = get4byte(pPage->aData); - } - } - - *pPgnoNext = next; - if( ppPage ){ - *ppPage = pPage; - }else{ - releasePage(pPage); - } - return (rc==SQLITE_DONE ? SQLITE_OK : rc); -} - -/* -** Copy data from a buffer to a page, or from a page to a buffer. -** -** pPayload is a pointer to data stored on database page pDbPage. -** If argument eOp is false, then nByte bytes of data are copied -** from pPayload to the buffer pointed at by pBuf. If eOp is true, -** then sqlite3PagerWrite() is called on pDbPage and nByte bytes -** of data are copied from the buffer pBuf to pPayload. -** -** SQLITE_OK is returned on success, otherwise an error code. -*/ -static int copyPayload( - void *pPayload, /* Pointer to page data */ - void *pBuf, /* Pointer to buffer */ - int nByte, /* Number of bytes to copy */ - int eOp, /* 0 -> copy from page, 1 -> copy to page */ - DbPage *pDbPage /* Page containing pPayload */ -){ - if( eOp ){ - /* Copy data from buffer to page (a write operation) */ - int rc = sqlite3PagerWrite(pDbPage); - if( rc!=SQLITE_OK ){ - return rc; - } - memcpy(pPayload, pBuf, nByte); - }else{ - /* Copy data from page to buffer (a read operation) */ - memcpy(pBuf, pPayload, nByte); - } - return SQLITE_OK; -} - -/* -** This function is used to read or overwrite payload information -** for the entry that the pCur cursor is pointing to. The eOp -** argument is interpreted as follows: -** -** 0: The operation is a read. Populate the overflow cache. -** 1: The operation is a write. Populate the overflow cache. -** -** A total of "amt" bytes are read or written beginning at "offset". -** Data is read to or from the buffer pBuf. -** -** The content being read or written might appear on the main page -** or be scattered out on multiple overflow pages. -** -** If the current cursor entry uses one or more overflow pages -** this function may allocate space for and lazily populate -** the overflow page-list cache array (BtCursor.aOverflow). -** Subsequent calls use this cache to make seeking to the supplied offset -** more efficient. -** -** Once an overflow page-list cache has been allocated, it must be -** invalidated if some other cursor writes to the same table, or if -** the cursor is moved to a different row. Additionally, in auto-vacuum -** mode, the following events may invalidate an overflow page-list cache. -** -** * An incremental vacuum, -** * A commit in auto_vacuum="full" mode, -** * Creating a table (may require moving an overflow page). -*/ -static int accessPayload( - BtCursor *pCur, /* Cursor pointing to entry to read from */ - u32 offset, /* Begin reading this far into payload */ - u32 amt, /* Read this many bytes */ - unsigned char *pBuf, /* Write the bytes into this buffer */ - int eOp /* zero to read. non-zero to write. */ -){ - unsigned char *aPayload; - int rc = SQLITE_OK; - int iIdx = 0; - MemPage *pPage = pCur->pPage; /* Btree page of current entry */ - BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ -#ifdef SQLITE_DIRECT_OVERFLOW_READ - unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ -#endif - - assert( pPage ); - assert( eOp==0 || eOp==1 ); - assert( pCur->eState==CURSOR_VALID ); - if( pCur->ix>=pPage->nCell ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( cursorHoldsMutex(pCur) ); - - getCellInfo(pCur); - aPayload = pCur->info.pPayload; - assert( offset+amt <= pCur->info.nPayload ); - - assert( aPayload > pPage->aData ); - if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ - /* Trying to read or write past the end of the data is an error. The - ** conditional above is really: - ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] - ** but is recast into its current form to avoid integer overflow problems - */ - return SQLITE_CORRUPT_PAGE(pPage); - } - - /* Check if data must be read/written to/from the btree page itself. */ - if( offsetinfo.nLocal ){ - int a = amt; - if( a+offset>pCur->info.nLocal ){ - a = pCur->info.nLocal - offset; - } - rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); - offset = 0; - pBuf += a; - amt -= a; - }else{ - offset -= pCur->info.nLocal; - } - - - if( rc==SQLITE_OK && amt>0 ){ - const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ - Pgno nextPage; - - nextPage = get4byte(&aPayload[pCur->info.nLocal]); - - /* If the BtCursor.aOverflow[] has not been allocated, allocate it now. - ** - ** The aOverflow[] array is sized at one entry for each overflow page - ** in the overflow chain. The page number of the first overflow page is - ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array - ** means "not yet known" (the cache is lazily populated). - */ - if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ - int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - if( pCur->aOverflow==0 - || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) - ){ - Pgno *aNew; - if( sqlite3FaultSim(413) ){ - aNew = 0; - }else{ - aNew = (Pgno*)sqlite3Realloc(pCur->aOverflow, nOvfl*2*sizeof(Pgno)); - } - if( aNew==0 ){ - return SQLITE_NOMEM_BKPT; - }else{ - pCur->aOverflow = aNew; - } - } - memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); - pCur->curFlags |= BTCF_ValidOvfl; - }else{ - /* Sanity check the validity of the overflow page cache */ - assert( pCur->aOverflow[0]==nextPage - || pCur->aOverflow[0]==0 - || CORRUPT_DB ); - assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 ); - - /* If the overflow page-list cache has been allocated and the - ** entry for the first required overflow page is valid, skip - ** directly to it. - */ - if( pCur->aOverflow[offset/ovflSize] ){ - iIdx = (offset/ovflSize); - nextPage = pCur->aOverflow[iIdx]; - offset = (offset%ovflSize); - } - } - - assert( rc==SQLITE_OK && amt>0 ); - while( nextPage ){ - /* If required, populate the overflow page-list cache. */ - if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT; - assert( pCur->aOverflow[iIdx]==0 - || pCur->aOverflow[iIdx]==nextPage - || CORRUPT_DB ); - pCur->aOverflow[iIdx] = nextPage; - - if( offset>=ovflSize ){ - /* The only reason to read this page is to obtain the page - ** number for the next page in the overflow chain. The page - ** data is not required. So first try to lookup the overflow - ** page-list cache, if any, then fall back to the getOverflowPage() - ** function. - */ - assert( pCur->curFlags & BTCF_ValidOvfl ); - assert( pCur->pBtree->db==pBt->db ); - if( pCur->aOverflow[iIdx+1] ){ - nextPage = pCur->aOverflow[iIdx+1]; - }else{ - rc = getOverflowPage(pBt, nextPage, 0, &nextPage); - } - offset -= ovflSize; - }else{ - /* Need to read this page properly. It contains some of the - ** range of data that is being read (eOp==0) or written (eOp!=0). - */ - int a = amt; - if( a + offset > ovflSize ){ - a = ovflSize - offset; - } - -#ifdef SQLITE_DIRECT_OVERFLOW_READ - /* If all the following are true: - ** - ** 1) this is a read operation, and - ** 2) data is required from the start of this overflow page, and - ** 3) there are no dirty pages in the page-cache - ** 4) the database is file-backed, and - ** 5) the page is not in the WAL file - ** 6) at least 4 bytes have already been read into the output buffer - ** - ** then data can be read directly from the database file into the - ** output buffer, bypassing the page-cache altogether. This speeds - ** up loading large records that span many overflow pages. - */ - if( eOp==0 /* (1) */ - && offset==0 /* (2) */ - && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ - && &pBuf[-4]>=pBufStart /* (6) */ - ){ - sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); - u8 aSave[4]; - u8 *aWrite = &pBuf[-4]; - assert( aWrite>=pBufStart ); /* due to (6) */ - memcpy(aSave, aWrite, 4); - rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); - nextPage = get4byte(aWrite); - memcpy(aWrite, aSave, 4); - }else -#endif - - { - DbPage *pDbPage; - rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage, - (eOp==0 ? PAGER_GET_READONLY : 0) - ); - if( rc==SQLITE_OK ){ - aPayload = sqlite3PagerGetData(pDbPage); - nextPage = get4byte(aPayload); - rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); - sqlite3PagerUnref(pDbPage); - offset = 0; - } - } - amt -= a; - if( amt==0 ) return rc; - pBuf += a; - } - if( rc ) break; - iIdx++; - } - } - - if( rc==SQLITE_OK && amt>0 ){ - /* Overflow chain ends prematurely */ - return SQLITE_CORRUPT_PAGE(pPage); - } - return rc; -} - -/* -** Read part of the payload for the row at which that cursor pCur is currently -** pointing. "amt" bytes will be transferred into pBuf[]. The transfer -** begins at "offset". -** -** pCur can be pointing to either a table or an index b-tree. -** If pointing to a table btree, then the content section is read. If -** pCur is pointing to an index b-tree then the key section is read. -** -** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing -** to a valid row in the table. For sqlite3BtreePayloadChecked(), the -** cursor might be invalid or might need to be restored before being read. -** -** Return SQLITE_OK on success or an error code if anything goes -** wrong. An error is returned if "offset+amt" is larger than -** the available payload. -*/ -SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->pPage ); - return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); -} - -/* -** This variant of sqlite3BtreePayload() works even if the cursor has not -** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read() -** interface. -*/ -#ifndef SQLITE_OMIT_INCRBLOB -static SQLITE_NOINLINE int accessPayloadChecked( - BtCursor *pCur, - u32 offset, - u32 amt, - void *pBuf -){ - int rc; - if ( pCur->eState==CURSOR_INVALID ){ - return SQLITE_ABORT; - } - assert( cursorOwnsBtShared(pCur) ); - rc = btreeRestoreCursorPosition(pCur); - return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0); -} -SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - if( pCur->eState==CURSOR_VALID ){ - assert( cursorOwnsBtShared(pCur) ); - return accessPayload(pCur, offset, amt, pBuf, 0); - }else{ - return accessPayloadChecked(pCur, offset, amt, pBuf); - } -} -#endif /* SQLITE_OMIT_INCRBLOB */ - -/* -** Return a pointer to payload information from the entry that the -** pCur cursor is pointing to. The pointer is to the beginning of -** the key if index btrees (pPage->intKey==0) and is the data for -** table btrees (pPage->intKey==1). The number of bytes of available -** key/data is written into *pAmt. If *pAmt==0, then the value -** returned will not be a valid pointer. -** -** This routine is an optimization. It is common for the entire key -** and data to fit on the local page and for there to be no overflow -** pages. When that is so, this routine can be used to access the -** key and data without making a copy. If the key and/or data spills -** onto overflow pages, then accessPayload() must be used to reassemble -** the key/data and copy it into a preallocated buffer. -** -** The pointer returned by this routine looks directly into the cached -** page of the database. The data might change or move the next time -** any btree routine is called. -*/ -static const void *fetchPayload( - BtCursor *pCur, /* Cursor pointing to entry to read from */ - u32 *pAmt /* Write the number of available bytes here */ -){ - int amt; - assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage); - assert( pCur->eState==CURSOR_VALID ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->ixpPage->nCell || CORRUPT_DB ); - assert( pCur->info.nSize>0 ); - assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB ); - assert( pCur->info.pPayloadpPage->aDataEnd ||CORRUPT_DB); - amt = pCur->info.nLocal; - if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){ - /* There is too little space on the page for the expected amount - ** of local content. Database must be corrupt. */ - assert( CORRUPT_DB ); - amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload)); - } - *pAmt = (u32)amt; - return (void*)pCur->info.pPayload; -} - - -/* -** For the entry that cursor pCur is point to, return as -** many bytes of the key or data as are available on the local -** b-tree page. Write the number of available bytes into *pAmt. -** -** The pointer returned is ephemeral. The key/data may move -** or be destroyed on the next call to any Btree routine, -** including calls from other threads against the same cache. -** Hence, a mutex on the BtShared should be held prior to calling -** this routine. -** -** These routines is used to get quick access to key and data -** in the common case where no overflow pages are used. -*/ -SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ - return fetchPayload(pCur, pAmt); -} - - -/* -** Move the cursor down to a new child page. The newPgno argument is the -** page number of the child page to move to. -** -** This function returns SQLITE_CORRUPT if the page-header flags field of -** the new child page does not match the flags field of the parent (i.e. -** if an intkey page appears to be the parent of a non-intkey page, or -** vice-versa). -*/ -static int moveToChild(BtCursor *pCur, u32 newPgno){ - int rc; - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPageiPage>=0 ); - if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ - return SQLITE_CORRUPT_BKPT; - } - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - pCur->aiIdx[pCur->iPage] = pCur->ix; - pCur->apPage[pCur->iPage] = pCur->pPage; - pCur->ix = 0; - pCur->iPage++; - rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags); - assert( pCur->pPage!=0 || rc!=SQLITE_OK ); - if( rc==SQLITE_OK - && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) - ){ - releasePage(pCur->pPage); - rc = SQLITE_CORRUPT_PGNO(newPgno); - } - if( rc ){ - pCur->pPage = pCur->apPage[--pCur->iPage]; - } - return rc; -} - -#ifdef SQLITE_DEBUG -/* -** Page pParent is an internal (non-leaf) tree page. This function -** asserts that page number iChild is the left-child if the iIdx'th -** cell in page pParent. Or, if iIdx is equal to the total number of -** cells in pParent, that page number iChild is the right-child of -** the page. -*/ -static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ - if( CORRUPT_DB ) return; /* The conditions tested below might not be true - ** in a corrupt database */ - assert( iIdx<=pParent->nCell ); - if( iIdx==pParent->nCell ){ - assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); - }else{ - assert( get4byte(findCell(pParent, iIdx))==iChild ); - } -} -#else -# define assertParentIndex(x,y,z) -#endif - -/* -** Move the cursor up to the parent page. -** -** pCur->idx is set to the cell index that contains the pointer -** to the page we are coming from. If we are coming from the -** right-most child page then pCur->idx is set to one more than -** the largest cell index. -*/ -static void moveToParent(BtCursor *pCur){ - MemPage *pLeaf; - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>0 ); - assert( pCur->pPage ); - assertParentIndex( - pCur->apPage[pCur->iPage-1], - pCur->aiIdx[pCur->iPage-1], - pCur->pPage->pgno - ); - testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - pCur->ix = pCur->aiIdx[pCur->iPage-1]; - pLeaf = pCur->pPage; - pCur->pPage = pCur->apPage[--pCur->iPage]; - releasePageNotNull(pLeaf); -} - -/* -** Move the cursor to point to the root page of its b-tree structure. -** -** If the table has a virtual root page, then the cursor is moved to point -** to the virtual root page instead of the actual root page. A table has a -** virtual root page when the actual root page contains no cells and a -** single child page. This can only happen with the table rooted at page 1. -** -** If the b-tree structure is empty, the cursor state is set to -** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise, -** the cursor is set to point to the first cell located on the root -** (or virtual root) page and the cursor state is set to CURSOR_VALID. -** -** If this function returns successfully, it may be assumed that the -** page-header flags indicate that the [virtual] root-page is the expected -** kind of b-tree page (i.e. if when opening the cursor the caller did not -** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D, -** indicating a table b-tree, or if the caller did specify a KeyInfo -** structure the flags byte is set to 0x02 or 0x0A, indicating an index -** b-tree). -*/ -static int moveToRoot(BtCursor *pCur){ - MemPage *pRoot; - int rc = SQLITE_OK; - - assert( cursorOwnsBtShared(pCur) ); - assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); - assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); - assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); - assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 ); - assert( pCur->pgnoRoot>0 || pCur->iPage<0 ); - - if( pCur->iPage>=0 ){ - if( pCur->iPage ){ - releasePageNotNull(pCur->pPage); - while( --pCur->iPage ){ - releasePageNotNull(pCur->apPage[pCur->iPage]); - } - pRoot = pCur->pPage = pCur->apPage[0]; - goto skip_init; - } - }else if( pCur->pgnoRoot==0 ){ - pCur->eState = CURSOR_INVALID; - return SQLITE_EMPTY; - }else{ - assert( pCur->iPage==(-1) ); - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - sqlite3BtreeClearCursor(pCur); - } - rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage, - pCur->curPagerFlags); - if( rc!=SQLITE_OK ){ - pCur->eState = CURSOR_INVALID; - return rc; - } - pCur->iPage = 0; - pCur->curIntKey = pCur->pPage->intKey; - } - pRoot = pCur->pPage; - 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 - ** NULL, the caller expects a table b-tree. If this is not the case, - ** return an SQLITE_CORRUPT error. - ** - ** Earlier versions of SQLite assumed that this test could not fail - ** if the root page was already loaded when this function was called (i.e. - ** if pCur->iPage>=0). But this is not so if the database is corrupted - ** in such a way that page pRoot is linked into a second b-tree table - ** (or the freelist). */ - assert( pRoot->intKey==1 || pRoot->intKey==0 ); - if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_PAGE(pCur->pPage); - } - -skip_init: - pCur->ix = 0; - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); - - if( pRoot->nCell>0 ){ - pCur->eState = CURSOR_VALID; - }else if( !pRoot->leaf ){ - Pgno subpage; - if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; - subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); - pCur->eState = CURSOR_VALID; - rc = moveToChild(pCur, subpage); - }else{ - pCur->eState = CURSOR_INVALID; - rc = SQLITE_EMPTY; - } - return rc; -} - -/* -** Move the cursor down to the left-most leaf entry beneath the -** entry to which it is currently pointing. -** -** The left-most leaf is the one with the smallest key - the first -** in ascending order. -*/ -static int moveToLeftmost(BtCursor *pCur){ - Pgno pgno; - int rc = SQLITE_OK; - MemPage *pPage; - - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ - assert( pCur->ixnCell ); - pgno = get4byte(findCell(pPage, pCur->ix)); - rc = moveToChild(pCur, pgno); - } - return rc; -} - -/* -** Move the cursor down to the right-most leaf entry beneath the -** page to which it is currently pointing. Notice the difference -** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() -** finds the left-most entry beneath the *entry* whereas moveToRightmost() -** finds the right-most entry beneath the *page*. -** -** The right-most entry is the one with the largest key - the last -** key in ascending order. -*/ -static int moveToRightmost(BtCursor *pCur){ - Pgno pgno; - int rc = SQLITE_OK; - MemPage *pPage = 0; - - assert( cursorOwnsBtShared(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - while( !(pPage = pCur->pPage)->leaf ){ - pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - pCur->ix = pPage->nCell; - rc = moveToChild(pCur, pgno); - if( rc ) return rc; - } - pCur->ix = pPage->nCell-1; - assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & BTCF_ValidNKey)==0 ); - return SQLITE_OK; -} - -/* Move the cursor to the first entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ - int rc; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - rc = moveToRoot(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->pPage->nCell>0 ); - *pRes = 0; - rc = moveToLeftmost(pCur); - }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); - *pRes = 1; - rc = SQLITE_OK; - } - return rc; -} - -#ifdef SQLITE_DEBUG -/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that -** this flags are true for a consistent database. -** -** This routine is is called from within assert() statements only. -** It is an internal verification routine and does not appear in production -** builds. -*/ -static int cursorIsAtLastEntry(BtCursor *pCur){ - int ii; - for(ii=0; iiiPage; ii++){ - if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0; - } - return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0; -} -#endif - -/* Move the cursor to the last entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -static SQLITE_NOINLINE int btreeLast(BtCursor *pCur, int *pRes){ - int rc = moveToRoot(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_VALID ); - *pRes = 0; - rc = moveToRightmost(pCur); - if( rc==SQLITE_OK ){ - pCur->curFlags |= BTCF_AtLast; - }else{ - pCur->curFlags &= ~BTCF_AtLast; - } - }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); - *pRes = 1; - rc = SQLITE_OK; - } - return rc; -} -SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - - /* If the cursor already points to the last entry, this is a no-op. */ - if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ - assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); - *pRes = 0; - return SQLITE_OK; - } - return btreeLast(pCur, pRes); -} - -/* 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 -** 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 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. -** -** *pRes>0 The cursor is left pointing at an entry that -** is larger than intKey. -*/ -SQLITE_PRIVATE int sqlite3BtreeTableMoveto( - BtCursor *pCur, /* The cursor to be moved */ - i64 intKey, /* The table key */ - int biasRight, /* If true, bias the search to the high end */ - int *pRes /* Write search results here */ -){ - int rc; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( pRes ); - 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( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ - if( pCur->info.nKey==intKey ){ - *pRes = 0; - return SQLITE_OK; - } - if( pCur->info.nKeycurFlags & BTCF_AtLast)!=0 ){ - assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); - *pRes = -1; - return SQLITE_OK; - } - /* If the requested key is one more than the previous key, then - ** try to get there using sqlite3BtreeNext() rather than a full - ** binary search. This is an optimization only. The correct answer - ** is still obtained without this case, only a little more slowly. */ - if( pCur->info.nKey+1==intKey ){ - *pRes = 0; - rc = sqlite3BtreeNext(pCur, 0); - if( rc==SQLITE_OK ){ - getCellInfo(pCur); - if( pCur->info.nKey==intKey ){ - return SQLITE_OK; - } - }else if( rc!=SQLITE_DONE ){ - return rc; - } - } - } - } - -#ifdef SQLITE_DEBUG - pCur->pBtree->nSeek++; /* Performance measurement during testing */ -#endif - - rc = moveToRoot(pCur); - if( rc ){ - if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); - *pRes = -1; - return SQLITE_OK; - } - return rc; - } - assert( pCur->pPage ); - assert( pCur->pPage->isInit ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->pPage->nCell > 0 ); - assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey ); - assert( pCur->curIntKey ); - - 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 ); - lwr = 0; - upr = pPage->nCell-1; - assert( biasRight==0 || biasRight==1 ); - idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ - 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( nCellKeyupr ){ 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{ - 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+1 || !pPage->leaf ); - assert( pPage->isInit ); - if( pPage->leaf ){ - assert( pCur->ixpPage->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{ - 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; iiPage; i++){ - MemPage *pPage = pCur->apPage[i]; - if( pCur->aiIdx[i]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 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( 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 = 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|BTCF_AtLast); - 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 = sqlite3Malloc( (u64)nCell+(u64)nOverrun ); - if( pCellKey==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto moveto_index_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 ){ - sqlite3_free(pCellKey); - goto moveto_index_finish; - } - c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); - 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->ixpPage->nCell || CORRUPT_DB ); - pCur->ix = (u16)idx; - *pRes = c; - rc = SQLITE_OK; - goto moveto_index_finish; - } - if( lwr>=pPage->nCell ){ - chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); - }else{ - chldPg = get4byte(findCell(pPage, lwr)); - } - - /* This block is similar to an in-lined version of: - ** - ** pCur->ix = (u16)lwr; - ** rc = moveToChild(pCur, chldPg); - ** if( rc ) break; - */ - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ - return SQLITE_CORRUPT_BKPT; - } - pCur->aiIdx[pCur->iPage] = (u16)lwr; - pCur->apPage[pCur->iPage] = pCur->pPage; - pCur->ix = 0; - pCur->iPage++; - rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags); - if( rc==SQLITE_OK - && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) - ){ - releasePage(pCur->pPage); - rc = SQLITE_CORRUPT_PGNO(chldPg); - } - if( rc ){ - pCur->pPage = pCur->apPage[--pCur->iPage]; - break; - } - /* - ***** End of in-lined moveToChild() call */ - } -moveto_index_finish: - pCur->info.nSize = 0; - assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); - return rc; -} - - -/* -** Return TRUE if the cursor is not pointing at an entry of the table. -** -** TRUE will be returned after a call to sqlite3BtreeNext() moves -** past the last entry in the table or sqlite3BtreePrev() moves past -** the first entry. TRUE is also returned if the table is empty. -*/ -SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ - /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries - ** have been deleted? This API will need to change to return an error code - ** as well as the boolean result value. - */ - return (CURSOR_VALID!=pCur->eState); -} - -/* -** Return an estimate for the number of rows in the table that pCur is -** pointing to. Return a negative number if no estimate is currently -** available. -*/ -SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ - i64 n; - u8 i; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - - /* Currently this interface is only called by the OP_IfSizeBetween - ** opcode and the OP_Count opcode with P3=1. In either case, - ** the cursor will always be valid unless the btree is empty. */ - if( pCur->eState!=CURSOR_VALID ) return 0; - if( NEVER(pCur->pPage->leaf==0) ) return -1; - - n = pCur->pPage->nCell; - for(i=0; iiPage; i++){ - n *= pCur->apPage[i]->nCell; - } - return n; -} - -/* -** Advance the cursor to the next entry in the database. -** Return value: -** -** SQLITE_OK success -** SQLITE_DONE cursor is already pointing at the last element -** otherwise some kind of error occurred -** -** The main entry point is sqlite3BtreeNext(). That routine is optimized -** for the common case of merely incrementing the cell counter BtCursor.aiIdx -** to the next cell on the current page. The (slower) btreeNext() helper -** routine is called when it is necessary to move to a different page or -** to restore the cursor. -** -** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the -** cursor corresponds to an SQL index and this routine could have been -** skipped if the SQL index had been a unique index. The F argument -** is a hint to the implement. SQLite btree implementation does not use -** this hint, but COMDB2 does. -*/ -static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){ - int rc; - int idx; - MemPage *pPage; - - assert( cursorOwnsBtShared(pCur) ); - if( pCur->eState!=CURSOR_VALID ){ - assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); - rc = restoreCursorPosition(pCur); - if( rc!=SQLITE_OK ){ - return rc; - } - if( CURSOR_INVALID==pCur->eState ){ - return SQLITE_DONE; - } - if( pCur->eState==CURSOR_SKIPNEXT ){ - pCur->eState = CURSOR_VALID; - if( pCur->skipNext>0 ) return SQLITE_OK; - } - } - - pPage = pCur->pPage; - idx = ++pCur->ix; - if( sqlite3FaultSim(412) ) pPage->isInit = 0; - if( !pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } - - if( idx>=pPage->nCell ){ - if( !pPage->leaf ){ - rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); - if( rc ) return rc; - return moveToLeftmost(pCur); - } - do{ - if( pCur->iPage==0 ){ - pCur->eState = CURSOR_INVALID; - return SQLITE_DONE; - } - moveToParent(pCur); - pPage = pCur->pPage; - }while( pCur->ix>=pPage->nCell ); - if( pPage->intKey ){ - return sqlite3BtreeNext(pCur, 0); - }else{ - return SQLITE_OK; - } - } - if( pPage->leaf ){ - return SQLITE_OK; - }else{ - return moveToLeftmost(pCur); - } -} -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){ - MemPage *pPage; - UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ - assert( cursorOwnsBtShared(pCur) ); - assert( flags==0 || flags==1 ); - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur); - pPage = pCur->pPage; - if( (++pCur->ix)>=pPage->nCell ){ - pCur->ix--; - return btreeNext(pCur); - } - if( pPage->leaf ){ - return SQLITE_OK; - }else{ - return moveToLeftmost(pCur); - } -} - -/* -** Step the cursor to the back to the previous entry in the database. -** Return values: -** -** SQLITE_OK success -** SQLITE_DONE the cursor is already on the first element of the table -** otherwise some kind of error occurred -** -** The main entry point is sqlite3BtreePrevious(). That routine is optimized -** for the common case of merely decrementing the cell counter BtCursor.aiIdx -** to the previous cell on the current page. The (slower) btreePrevious() -** helper routine is called when it is necessary to move to a different page -** or to restore the cursor. -** -** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then -** the cursor corresponds to an SQL index and this routine could have been -** skipped if the SQL index had been a unique index. The F argument is a -** hint to the implement. The native SQLite btree implementation does not -** use this hint, but COMDB2 does. -*/ -static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){ - int rc; - MemPage *pPage; - - assert( cursorOwnsBtShared(pCur) ); - assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 ); - assert( pCur->info.nSize==0 ); - if( pCur->eState!=CURSOR_VALID ){ - rc = restoreCursorPosition(pCur); - if( rc!=SQLITE_OK ){ - return rc; - } - if( CURSOR_INVALID==pCur->eState ){ - return SQLITE_DONE; - } - if( CURSOR_SKIPNEXT==pCur->eState ){ - pCur->eState = CURSOR_VALID; - if( pCur->skipNext<0 ) return SQLITE_OK; - } - } - - pPage = pCur->pPage; - if( sqlite3FaultSim(412) ) pPage->isInit = 0; - if( !pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } - if( !pPage->leaf ){ - int idx = pCur->ix; - rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); - if( rc ) return rc; - rc = moveToRightmost(pCur); - }else{ - while( pCur->ix==0 ){ - if( pCur->iPage==0 ){ - pCur->eState = CURSOR_INVALID; - return SQLITE_DONE; - } - moveToParent(pCur); - } - assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); - - pCur->ix--; - pPage = pCur->pPage; - if( pPage->intKey && !pPage->leaf ){ - rc = sqlite3BtreePrevious(pCur, 0); - }else{ - rc = SQLITE_OK; - } - } - return rc; -} -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){ - assert( cursorOwnsBtShared(pCur) ); - assert( flags==0 || flags==1 ); - UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ - pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey); - pCur->info.nSize = 0; - if( pCur->eState!=CURSOR_VALID - || pCur->ix==0 - || pCur->pPage->leaf==0 - ){ - return btreePrevious(pCur); - } - pCur->ix--; - return SQLITE_OK; -} - -/* -** Allocate a new page from the database file. -** -** The new page is marked as dirty. (In other words, sqlite3PagerWrite() -** has already been called on the new page.) The new page has also -** been referenced and the calling routine is responsible for calling -** sqlite3PagerUnref() on the new page when it is done. -** -** SQLITE_OK is returned on success. Any other return value indicates -** an error. *ppPage is set to NULL in the event of an error. -** -** If the "nearby" parameter is not 0, then an effort is made to -** locate a page close to the page number "nearby". This can be used in an -** attempt to keep related pages close to each other in the database file, -** which in turn can make database access faster. -** -** If the eMode parameter is BTALLOC_EXACT and the nearby page exists -** anywhere on the free-list, then it is guaranteed to be returned. If -** eMode is BTALLOC_LT then the page returned will be less than or equal -** to nearby if any such page exists. If eMode is BTALLOC_ANY then there -** are no restrictions on which page is returned. -*/ -static int allocateBtreePage( - BtShared *pBt, /* The btree */ - MemPage **ppPage, /* Store pointer to the allocated page here */ - Pgno *pPgno, /* Store the page number here */ - Pgno nearby, /* Search for a page near this one */ - u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */ -){ - MemPage *pPage1; - int rc; - u32 n; /* Number of pages on the freelist */ - u32 k; /* Number of leaves on the trunk of the freelist */ - MemPage *pTrunk = 0; - MemPage *pPrevTrunk = 0; - Pgno mxPage; /* Total size of the database file */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); - pPage1 = pBt->pPage1; - mxPage = btreePagecount(pBt); - /* EVIDENCE-OF: R-21003-45125 The 4-byte big-endian integer at offset 36 - ** stores the total number of pages on the freelist. */ - n = get4byte(&pPage1->aData[36]); - testcase( n==mxPage-1 ); - if( n>=mxPage ){ - return SQLITE_CORRUPT_BKPT; - } - if( n>0 ){ - /* There are pages on the freelist. Reuse one of those pages. */ - Pgno iTrunk; - u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ - u32 nSearch = 0; /* Count of the number of search attempts */ - - /* If eMode==BTALLOC_EXACT and a query of the pointer-map - ** shows that the page 'nearby' is somewhere on the free-list, then - ** the entire-list will be searched for that page. - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( eMode==BTALLOC_EXACT ){ - if( nearby<=mxPage ){ - u8 eType; - assert( nearby>0 ); - assert( pBt->autoVacuum ); - rc = ptrmapGet(pBt, nearby, &eType, 0); - if( rc ) return rc; - if( eType==PTRMAP_FREEPAGE ){ - searchList = 1; - } - } - }else if( eMode==BTALLOC_LE ){ - searchList = 1; - } -#endif - - /* Decrement the free-list count by 1. Set iTrunk to the index of the - ** first free-list trunk page. iPrevTrunk is initially 1. - */ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc ) return rc; - put4byte(&pPage1->aData[36], n-1); - - /* The code within this loop is run only once if the 'searchList' variable - ** is not true. Otherwise, it runs once for each trunk-page on the - ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT) - ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT) - */ - do { - pPrevTrunk = pTrunk; - if( pPrevTrunk ){ - /* EVIDENCE-OF: R-01506-11053 The first integer on a freelist trunk page - ** is the page number of the next freelist trunk page in the list or - ** zero if this is the last freelist trunk page. */ - iTrunk = get4byte(&pPrevTrunk->aData[0]); - }else{ - /* EVIDENCE-OF: R-59841-13798 The 4-byte big-endian integer at offset 32 - ** stores the page number of the first page of the freelist, or zero if - ** the freelist is empty. */ - iTrunk = get4byte(&pPage1->aData[32]); - } - testcase( iTrunk==mxPage ); - if( iTrunk>mxPage || nSearch++ > n ){ - rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1); - }else{ - rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); - } - if( rc ){ - pTrunk = 0; - goto end_allocate_page; - } - assert( pTrunk!=0 ); - assert( pTrunk->aData!=0 ); - /* EVIDENCE-OF: R-13523-04394 The second integer on a freelist trunk page - ** is the number of leaf page pointers to follow. */ - k = get4byte(&pTrunk->aData[4]); - if( k==0 && !searchList ){ - /* The trunk has no leaves and the list is not being searched. - ** So extract the trunk page itself and use it as the newly - ** allocated page */ - assert( pPrevTrunk==0 ); - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc ){ - goto end_allocate_page; - } - *pPgno = iTrunk; - memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); - *ppPage = pTrunk; - pTrunk = 0; - TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); - }else if( k>(u32)(pBt->usableSize/4 - 2) ){ - /* Value of k is out of range. Database corruption */ - rc = SQLITE_CORRUPT_PGNO(iTrunk); - goto end_allocate_page; -#ifndef SQLITE_OMIT_AUTOVACUUM - }else if( searchList - && (nearby==iTrunk || (iTrunkpDbPage); - if( rc ){ - goto end_allocate_page; - } - if( k==0 ){ - if( !pPrevTrunk ){ - memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); - }else{ - rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); - if( rc!=SQLITE_OK ){ - goto end_allocate_page; - } - memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); - } - }else{ - /* The trunk page is required by the caller but it contains - ** pointers to free-list leaves. The first leaf becomes a trunk - ** page in this case. - */ - MemPage *pNewTrunk; - Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); - if( iNewTrunk>mxPage ){ - rc = SQLITE_CORRUPT_PGNO(iTrunk); - goto end_allocate_page; - } - testcase( iNewTrunk==mxPage ); - rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0); - if( rc!=SQLITE_OK ){ - goto end_allocate_page; - } - rc = sqlite3PagerWrite(pNewTrunk->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pNewTrunk); - goto end_allocate_page; - } - memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); - put4byte(&pNewTrunk->aData[4], k-1); - memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); - releasePage(pNewTrunk); - if( !pPrevTrunk ){ - assert( sqlite3PagerIswriteable(pPage1->pDbPage) ); - put4byte(&pPage1->aData[32], iNewTrunk); - }else{ - rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); - if( rc ){ - goto end_allocate_page; - } - put4byte(&pPrevTrunk->aData[0], iNewTrunk); - } - } - pTrunk = 0; - TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); -#endif - }else if( k>0 ){ - /* Extract a leaf from the trunk */ - u32 closest; - Pgno iPage; - unsigned char *aData = pTrunk->aData; - if( nearby>0 ){ - u32 i; - closest = 0; - if( eMode==BTALLOC_LE ){ - for(i=0; imxPage || iPage<2 ){ - rc = SQLITE_CORRUPT_PGNO(iTrunk); - goto end_allocate_page; - } - testcase( iPage==mxPage ); - if( !searchList - || (iPage==nearby || (iPagepgno, n-1)); - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc ) goto end_allocate_page; - if( closestpDbPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - *ppPage = 0; - } - } - searchList = 0; - } - } - releasePage(pPrevTrunk); - pPrevTrunk = 0; - }while( searchList ); - }else{ - /* There are no pages on the freelist, so append a new page to the - ** database image. - ** - ** Normally, new pages allocated by this block can be requested from the - ** pager layer with the 'no-content' flag set. This prevents the pager - ** from trying to read the pages content from disk. However, if the - ** current transaction has already run one or more incremental-vacuum - ** steps, then the page we are about to allocate may contain content - ** that is required in the event of a rollback. In this case, do - ** not set the no-content flag. This causes the pager to load and journal - ** the current page content before overwriting it. - ** - ** Note that the pager will not actually attempt to load or journal - ** content for any page that really does lie past the end of the database - ** file on disk. So the effects of disabling the no-content optimization - ** here are confined to those pages that lie between the end of the - ** database image and the end of the database file. - */ - int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate))? PAGER_GET_NOCONTENT:0; - - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc ) return rc; - pBt->nPage++; - if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; - -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ - /* If *pPgno refers to a pointer-map page, allocate two new pages - ** at the end of the file instead of one. The first allocated page - ** becomes a new pointer-map page, the second is used by the caller. - */ - MemPage *pPg = 0; - TRACE(("ALLOCATE: %u from end of file (pointer-map page)\n", pBt->nPage)); - assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pPg->pDbPage); - releasePage(pPg); - } - if( rc ) return rc; - pBt->nPage++; - if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } - } -#endif - put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); - *pPgno = pBt->nPage; - - assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent); - if( rc ) return rc; - rc = sqlite3PagerWrite((*ppPage)->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - *ppPage = 0; - } - TRACE(("ALLOCATE: %u from end of file\n", *pPgno)); - } - - assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) ); - -end_allocate_page: - releasePage(pTrunk); - releasePage(pPrevTrunk); - assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 ); - assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 ); - return rc; -} - -/* -** This function is used to add page iPage to the database file free-list. -** It is assumed that the page is not already a part of the free-list. -** -** The value passed as the second argument to this function is optional. -** If the caller happens to have a pointer to the MemPage object -** corresponding to page iPage handy, it may pass it as the second value. -** Otherwise, it may pass NULL. -** -** If a pointer to a MemPage object is passed as the second argument, -** its reference count is not altered by this function. -*/ -static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ - MemPage *pTrunk = 0; /* Free-list trunk page */ - Pgno iTrunk = 0; /* Page number of free-list trunk page */ - MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ - MemPage *pPage; /* Page being freed. May be NULL. */ - int rc; /* Return Code */ - u32 nFree; /* Initial number of pages on free-list */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( CORRUPT_DB || iPage>1 ); - assert( !pMemPage || pMemPage->pgno==iPage ); - - if( iPage<2 || iPage>pBt->nPage ){ - return SQLITE_CORRUPT_BKPT; - } - if( pMemPage ){ - pPage = pMemPage; - sqlite3PagerRef(pPage->pDbPage); - }else{ - pPage = btreePageLookup(pBt, iPage); - } - - /* Increment the free page count on pPage1 */ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc ) goto freepage_out; - nFree = get4byte(&pPage1->aData[36]); - put4byte(&pPage1->aData[36], nFree+1); - - if( pBt->btsFlags & BTS_SECURE_DELETE ){ - /* If the secure_delete option is enabled, then - ** always fully overwrite deleted information with zeros. - */ - if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) - || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) - ){ - goto freepage_out; - } - memset(pPage->aData, 0, pPage->pBt->pageSize); - } - - /* If the database supports auto-vacuum, write an entry in the pointer-map - ** to indicate that the page is free. - */ - if( ISAUTOVACUUM(pBt) ){ - ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); - if( rc ) goto freepage_out; - } - - /* Now manipulate the actual database free-list structure. There are two - ** possibilities. If the free-list is currently empty, or if the first - ** trunk page in the free-list is full, then this page will become a - ** new free-list trunk page. Otherwise, it will become a leaf of the - ** first trunk page in the current free-list. This block tests if it - ** is possible to add the page as a new free-list leaf. - */ - if( nFree!=0 ){ - u32 nLeaf; /* Initial number of leaf cells on trunk page */ - - iTrunk = get4byte(&pPage1->aData[32]); - if( iTrunk>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; - goto freepage_out; - } - rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); - if( rc!=SQLITE_OK ){ - goto freepage_out; - } - - nLeaf = get4byte(&pTrunk->aData[4]); - assert( pBt->usableSize>32 ); - if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ - rc = SQLITE_CORRUPT_BKPT; - goto freepage_out; - } - if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ - /* In this case there is room on the trunk page to insert the page - ** being freed as a new leaf. - ** - ** Note that the trunk page is not really full until it contains - ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have - ** coded. But due to a coding error in versions of SQLite prior to - ** 3.6.0, databases with freelist trunk pages holding more than - ** usableSize/4 - 8 entries will be reported as corrupt. In order - ** to maintain backwards compatibility with older versions of SQLite, - ** we will continue to restrict the number of entries to usableSize/4 - 8 - ** for now. At some point in the future (once everyone has upgraded - ** to 3.6.0 or later) we should consider fixing the conditional above - ** to read "usableSize/4-2" instead of "usableSize/4-8". - ** - ** EVIDENCE-OF: R-19920-11576 However, newer versions of SQLite still - ** avoid using the last six entries in the freelist trunk page array in - ** order that database files created by newer versions of SQLite can be - ** read by older versions of SQLite. - */ - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pTrunk->aData[4], nLeaf+1); - put4byte(&pTrunk->aData[8+nLeaf*4], iPage); - if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ - sqlite3PagerDontWrite(pPage->pDbPage); - } - rc = btreeSetHasContent(pBt, iPage); - } - TRACE(("FREE-PAGE: %u leaf on trunk page %u\n",pPage->pgno,pTrunk->pgno)); - goto freepage_out; - } - } - - /* If control flows to this point, then it was not possible to add the - ** the page being freed as a leaf page of the first trunk in the free-list. - ** Possibly because the free-list is empty, or possibly because the - ** first trunk in the free-list is full. Either way, the page being freed - ** will become the new first trunk page in the free-list. - */ - if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ - goto freepage_out; - } - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc!=SQLITE_OK ){ - goto freepage_out; - } - put4byte(pPage->aData, iTrunk); - put4byte(&pPage->aData[4], 0); - put4byte(&pPage1->aData[32], iPage); - TRACE(("FREE-PAGE: %u new trunk page replacing %u\n", pPage->pgno, iTrunk)); - -freepage_out: - if( pPage ){ - pPage->isInit = 0; - } - releasePage(pPage); - releasePage(pTrunk); - return rc; -} -static void freePage(MemPage *pPage, int *pRC){ - if( (*pRC)==SQLITE_OK ){ - *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); - } -} - -/* -** Free the overflow pages associated with the given Cell. -*/ -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 */ -){ - BtShared *pBt; - Pgno ovflPgno; - int rc; - int nOvfl; - u32 ovflPageSize; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pInfo->nLocal!=pInfo->nPayload ); - testcase( pCell + pInfo->nSize == pPage->aDataEnd ); - testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); - if( pCell + pInfo->nSize > pPage->aDataEnd ){ - /* Cell extends past end of page */ - return SQLITE_CORRUPT_PAGE(pPage); - } - ovflPgno = get4byte(pCell + pInfo->nSize - 4); - pBt = pPage->pBt; - assert( pBt->usableSize > 4 ); - ovflPageSize = pBt->usableSize - 4; - nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; - assert( nOvfl>0 || - (CORRUPT_DB && (pInfo->nPayload + ovflPageSize)btreePagecount(pBt) ){ - /* 0 is not a legal page number and page 1 cannot be an - ** overflow page. Therefore if ovflPgno<2 or past the end of the - ** file the database must be corrupt. */ - return SQLITE_CORRUPT_BKPT; - } - if( nOvfl ){ - rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); - if( rc ) return rc; - } - - if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) ) - && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 - ){ - /* There is no reason any cursor should have an outstanding reference - ** to an overflow page belonging to a cell that is being deleted/updated. - ** So if there exists more than one reference to this page, then it - ** must not really be an overflow page and the database must be corrupt. - ** It is helpful to detect this before calling freePage2(), as - ** freePage2() may zero the page contents if secure-delete mode is - ** enabled. If this 'overflow' page happens to be a page that the - ** caller is iterating through or using in some other way, this - ** can be problematic. - */ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = freePage2(pBt, pOvfl, ovflPgno); - } - - if( pOvfl ){ - sqlite3PagerUnref(pOvfl->pDbPage); - } - if( rc ) return rc; - ovflPgno = iNext; - } - 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 -** allocated and filled in as necessary. The calling procedure -** is responsible for making sure sufficient space has been allocated -** for pCell[]. -** -** Note that pCell does not necessary need to point to the pPage->aData -** area. pCell might point to some temporary storage. The cell will -** be constructed in this temporary area then copied into pPage->aData -** later. -*/ -static int fillInCell( - MemPage *pPage, /* The page that contains the cell */ - unsigned char *pCell, /* Complete text of the cell */ - const BtreePayload *pX, /* Payload with which to construct the cell */ - int *pnSize /* Write cell size here */ -){ - int nPayload; - const u8 *pSrc; - int nSrc, n, rc, mn; - int spaceLeft; - MemPage *pToRelease; - unsigned char *pPrior; - unsigned char *pPayload; - BtShared *pBt; - Pgno pgnoOvfl; - int nHeader; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - - /* pPage is not necessarily writeable since pCell might be auxiliary - ** buffer space that is separate from the pPage buffer area */ - assert( pCellaData || pCell>=&pPage->aData[pPage->pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - /* Fill in the header. */ - nHeader = pPage->childPtrSize; - if( pPage->intKey ){ - nPayload = pX->nData + pX->nZero; - pSrc = pX->pData; - nSrc = pX->nData; - assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */ - nHeader += putVarint32(&pCell[nHeader], nPayload); - nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey); - }else{ - assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); - nSrc = nPayload = (int)pX->nKey; - pSrc = pX->pKey; - nHeader += putVarint32(&pCell[nHeader], nPayload); - } - - /* Fill in the payload */ - pPayload = &pCell[nHeader]; - if( nPayload<=pPage->maxLocal ){ - /* This is the common case where everything fits on the btree page - ** and no overflow pages are required. */ - n = nHeader + nPayload; - testcase( n==3 ); - testcase( n==4 ); - if( n<4 ){ - n = 4; - pPayload[nPayload] = 0; - } - *pnSize = n; - assert( nSrc<=nPayload ); - testcase( nSrcminLocal; - n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); - testcase( n==pPage->maxLocal ); - testcase( n==pPage->maxLocal+1 ); - if( n > pPage->maxLocal ) n = mn; - spaceLeft = n; - *pnSize = n + nHeader + 4; - pPrior = &pCell[nHeader+n]; - pToRelease = 0; - pgnoOvfl = 0; - pBt = pPage->pBt; - - /* At this point variables should be set as follows: - ** - ** nPayload Total payload size in bytes - ** pPayload Begin writing payload here - ** spaceLeft Space available at pPayload. If nPayload>spaceLeft, - ** that means content must spill into overflow pages. - ** *pnSize Size of the local cell (not counting overflow pages) - ** pPrior Where to write the pgno of the first overflow page - ** - ** Use a call to btreeParseCellPtr() to verify that the values above - ** were computed correctly. - */ -#ifdef SQLITE_DEBUG - { - CellInfo info; - pPage->xParseCell(pPage, pCell, &info); - assert( nHeader==(int)(info.pPayload - pCell) ); - assert( info.nKey==pX->nKey ); - assert( *pnSize == info.nSize ); - assert( spaceLeft == info.nLocal ); - } -#endif - - /* Write the payload into the local Cell and any extra into overflow pages */ - while( 1 ){ - n = nPayload; - if( n>spaceLeft ) n = spaceLeft; - - /* If pToRelease is not zero than pPayload points into the data area - ** of pToRelease. Make sure pToRelease is still writeable. */ - assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); - - /* If pPayload is part of the data area of pPage, then make sure pPage - ** is still writeable */ - assert( pPayloadaData || pPayload>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - if( nSrc>=n ){ - memcpy(pPayload, pSrc, n); - }else if( nSrc>0 ){ - n = nSrc; - memcpy(pPayload, pSrc, n); - }else{ - memset(pPayload, 0, n); - } - nPayload -= n; - if( nPayload<=0 ) break; - pPayload += n; - pSrc += n; - nSrc -= n; - spaceLeft -= n; - if( spaceLeft==0 ){ - MemPage *pOvfl = 0; -#ifndef SQLITE_OMIT_AUTOVACUUM - Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ - if( pBt->autoVacuum ){ - do{ - pgnoOvfl++; - } while( - PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) - ); - } -#endif - rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); -#ifndef SQLITE_OMIT_AUTOVACUUM - /* If the database supports auto-vacuum, and the second or subsequent - ** overflow page is being allocated, add an entry to the pointer-map - ** for that page now. - ** - ** If this is the first overflow page, then write a partial entry - ** to the pointer-map. If we write nothing to this pointer-map slot, - ** then the optimistic overflow chain processing in clearCell() - ** may misinterpret the uninitialized values and delete the - ** wrong pages from the database. - */ - if( pBt->autoVacuum && rc==SQLITE_OK ){ - u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); - ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); - if( rc ){ - releasePage(pOvfl); - } - } -#endif - if( rc ){ - releasePage(pToRelease); - return rc; - } - - /* If pToRelease is not zero than pPrior points into the data area - ** of pToRelease. Make sure pToRelease is still writeable. */ - assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); - - /* If pPrior is part of the data area of pPage, then make sure pPage - ** is still writeable */ - assert( pPrioraData || pPrior>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - put4byte(pPrior, pgnoOvfl); - releasePage(pToRelease); - pToRelease = pOvfl; - pPrior = pOvfl->aData; - put4byte(pPrior, 0); - pPayload = &pOvfl->aData[4]; - spaceLeft = pBt->usableSize - 4; - } - } - releasePage(pToRelease); - return SQLITE_OK; -} - -/* -** Remove the i-th cell from pPage. This routine effects pPage only. -** The cell content is not freed or deallocated. It is assumed that -** the cell content has been copied someplace else. This routine just -** removes the reference to the cell from pPage. -** -** "sz" must be the number of bytes in the cell. -*/ -static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ - u32 pc; /* Offset to cell content of cell being deleted */ - u8 *data; /* pPage->aData */ - u8 *ptr; /* Used to move bytes around within data[] */ - int rc; /* The return code */ - int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ - - if( *pRC ) return; - assert( idx>=0 ); - assert( idxnCell ); - assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( 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==(u32)get2byte(&data[hdr+5]) ); - testcase( pc+sz==pPage->pBt->usableSize ); - if( pc+sz > pPage->pBt->usableSize ){ - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - rc = freeSpace(pPage, pc, sz); - if( rc ){ - *pRC = rc; - return; - } - pPage->nCell--; - if( pPage->nCell==0 ){ - memset(&data[hdr+1], 0, 4); - data[hdr+7] = 0; - put2byte(&data[hdr+5], pPage->pBt->usableSize); - pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset - - pPage->childPtrSize - 8; - }else{ - memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); - put2byte(&data[hdr+3], pPage->nCell); - pPage->nFree += 2; - } -} - -/* -** Insert a new cell on pPage at cell index "i". pCell points to the -** content of the cell. -** -** If the cell content will fit on the page, then put it there. If it -** will not fit, then make a copy of the cell content into pTemp if -** pTemp is not null. Regardless of pTemp, allocate a new entry -** in pPage->apOvfl[] and make it point to the cell content (either -** in pTemp or the original pCell) and also record its index. -** Allocating a new entry in pPage->aCell[] implies that -** pPage->nOverflow is incremented. -** -** The insertCellFast() routine below works exactly the same as -** insertCell() except that it lacks the pTemp and iChild parameters -** which are assumed zero. Other than that, the two routines are the -** same. -** -** Fixes or enhancements to this routine should be reflected in -** insertCellFast()! -*/ -static int insertCell( - MemPage *pPage, /* Page into which we are copying */ - int i, /* New cell becomes the i-th cell of the page */ - u8 *pCell, /* Content of the new cell */ - int sz, /* Bytes of content in pCell */ - u8 *pTemp, /* Temp storage space for pCell, if needed */ - Pgno iChild /* If non-zero, replace first 4 bytes with this value */ -){ - int idx = 0; /* Where to write new cell content in data[] */ - int j; /* Loop counter */ - u8 *data; /* The content of the whole page */ - u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ - - assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); - assert( MX_CELL(pPage->pBt)<=10921 ); - assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); - assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); - assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); - assert( pPage->nFree>=0 ); - assert( iChild>0 ); - if( pPage->nOverflow || sz+2>pPage->nFree ){ - if( pTemp ){ - memcpy(pTemp, pCell, sz); - pCell = pTemp; - } - put4byte(pCell, iChild); - j = pPage->nOverflow++; - /* Comparison against ArraySize-1 since we hold back one extra slot - ** as a contingency. In other words, never need more than 3 overflow - ** slots but 4 are allocated, just to be safe. */ - assert( j < ArraySize(pPage->apOvfl)-1 ); - pPage->apOvfl[j] = pCell; - pPage->aiOvfl[j] = (u16)i; - - /* When multiple overflows occur, they are always sequential and in - ** sorted order. This invariants arise because multiple overflows can - ** only occur when inserting divider cells into the parent page during - ** balancing, and the dividers are adjacent and sorted. - */ - assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */ - assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */ - }else{ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( NEVER(rc!=SQLITE_OK) ){ - return rc; - } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - data = pPage->aData; - assert( &data[pPage->cellOffset]==pPage->aCellIdx ); - rc = allocateSpace(pPage, sz, &idx); - if( rc ){ return rc; } - /* The allocateSpace() routine guarantees the following properties - ** if it returns successfully */ - assert( idx >= 0 ); - assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); - assert( idx+sz <= (int)pPage->pBt->usableSize ); - pPage->nFree -= (u16)(2 + sz); - /* In a corrupt database where an entry in the cell index section of - ** a btree page has a value of 3 or less, the pCell value might point - ** as many as 4 bytes in front of the start of the aData buffer for - ** the source page. Make sure this does not cause problems by not - ** reading the first 4 bytes */ - memcpy(&data[idx+4], pCell+4, sz-4); - put4byte(&data[idx], iChild); - pIns = pPage->aCellIdx + i*2; - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); - put2byte(pIns, idx); - pPage->nCell++; - /* increment the cell count */ - if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pPage->pBt->autoVacuum ){ - int rc2 = SQLITE_OK; - /* The cell may contain a pointer to an overflow page. If so, write - ** the entry for the overflow page into the pointer map. - */ - ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2); - if( rc2 ) return rc2; - } -#endif - } - return SQLITE_OK; -} - -/* -** This variant of insertCell() assumes that the pTemp and iChild -** parameters are both zero. Use this variant in sqlite3BtreeInsert() -** for performance improvement, and also so that this variant is only -** called from that one place, and is thus inlined, and thus runs must -** faster. -** -** Fixes or enhancements to this routine should be reflected into -** the insertCell() routine. -*/ -static int insertCellFast( - MemPage *pPage, /* Page into which we are copying */ - int i, /* New cell becomes the i-th cell of the page */ - u8 *pCell, /* Content of the new cell */ - int sz /* Bytes of content in pCell */ -){ - int idx = 0; /* Where to write new cell content in data[] */ - int j; /* Loop counter */ - u8 *data; /* The content of the whole page */ - u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ - - assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); - assert( MX_CELL(pPage->pBt)<=10921 ); - assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); - assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); - assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); - assert( pPage->nFree>=0 ); - assert( pPage->nOverflow==0 ); - if( sz+2>pPage->nFree ){ - j = pPage->nOverflow++; - /* Comparison against ArraySize-1 since we hold back one extra slot - ** as a contingency. In other words, never need more than 3 overflow - ** slots but 4 are allocated, just to be safe. */ - assert( j < ArraySize(pPage->apOvfl)-1 ); - pPage->apOvfl[j] = pCell; - pPage->aiOvfl[j] = (u16)i; - - /* When multiple overflows occur, they are always sequential and in - ** sorted order. This invariants arise because multiple overflows can - ** only occur when inserting divider cells into the parent page during - ** balancing, and the dividers are adjacent and sorted. - */ - assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */ - assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */ - }else{ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - data = pPage->aData; - assert( &data[pPage->cellOffset]==pPage->aCellIdx ); - rc = allocateSpace(pPage, sz, &idx); - if( rc ){ return rc; } - /* The allocateSpace() routine guarantees the following properties - ** if it returns successfully */ - assert( idx >= 0 ); - assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); - assert( idx+sz <= (int)pPage->pBt->usableSize ); - pPage->nFree -= (u16)(2 + sz); - memcpy(&data[idx], pCell, sz); - pIns = pPage->aCellIdx + i*2; - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); - put2byte(pIns, idx); - pPage->nCell++; - /* increment the cell count */ - if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pPage->pBt->autoVacuum ){ - int rc2 = SQLITE_OK; - /* The cell may contain a pointer to an overflow page. If so, write - ** the entry for the overflow page into the pointer map. - */ - ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2); - if( rc2 ) return rc2; - } -#endif - } - return SQLITE_OK; -} - -/* -** The following parameters determine how many adjacent pages get involved -** in a balancing operation. NN is the number of neighbors on either side -** of the page that participate in the balancing operation. NB is the -** total number of pages that participate, including the target page and -** NN neighbors on either side. -** -** The minimum value of NN is 1 (of course). Increasing NN above 1 -** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance -** in exchange for a larger degradation in INSERT and UPDATE performance. -** The value of NN appears to give the best results overall. -** -** (Later:) The description above makes it seem as if these values are -** tunable - as if you could change them and recompile and it would all work. -** But that is unlikely. NB has been 3 since the inception of SQLite and -** we have never tested any other value. -*/ -#define NN 1 /* Number of neighbors on either side of pPage */ -#define NB 3 /* (NN*2+1): Total pages involved in the balance */ - -/* -** A CellArray object contains a cache of pointers and sizes for a -** consecutive sequence of cells that might be held on multiple pages. -** -** The cells in this array are the divider cell or cells from the pParent -** page plus up to three child pages. There are a total of nCell cells. -** -** pRef is a pointer to one of the pages that contributes cells. This is -** used to access information such as MemPage.intKey and MemPage.pBt->pageSize -** which should be common to all pages that contribute cells to this array. -** -** apCell[] and szCell[] hold, respectively, pointers to the start of each -** cell and the size of each cell. Some of the apCell[] pointers might refer -** to overflow cells. In other words, some apCel[] pointers might not point -** to content area of the pages. -** -** A szCell[] of zero means the size of that cell has not yet been computed. -** -** The cells come from as many as four different pages: -** -** ----------- -** | Parent | -** ----------- -** / | \ -** / | \ -** --------- --------- --------- -** |Child-1| |Child-2| |Child-3| -** --------- --------- --------- -** -** The order of cells is in the array is for an index btree is: -** -** 1. All cells from Child-1 in order -** 2. The first divider cell from Parent -** 3. All cells from Child-2 in order -** 4. The second divider cell from Parent -** 5. All cells from Child-3 in order -** -** For a table-btree (with rowids) the items 2 and 4 are empty because -** content exists only in leaves and there are no divider cells. -** -** For an index btree, the apEnd[] array holds pointer to the end of page -** for Child-1, the Parent, Child-2, the Parent (again), and Child-3, -** respectively. The ixNx[] array holds the number of cells contained in -** each of these 5 stages, and all stages to the left. Hence: -** -** ixNx[0] = Number of cells in Child-1. -** ixNx[1] = Number of cells in Child-1 plus 1 for first divider. -** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider. -** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells -** ixNx[4] = Total number of cells. -** -** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2] -** are used and they point to the leaf pages only, and the ixNx value are: -** -** ixNx[0] = Number of cells in Child-1. -** ixNx[1] = Number of cells in Child-1 and Child-2. -** ixNx[2] = Total number of cells. -** -** Sometimes when deleting, a child page can have zero cells. In those -** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[] -** entries, shift down. The end result is that each ixNx[] entry should -** be larger than the previous -*/ -typedef struct CellArray CellArray; -struct CellArray { - int nCell; /* Number of cells in apCell[] */ - MemPage *pRef; /* Reference page */ - u8 **apCell; /* All cells begin balanced */ - u16 *szCell; /* Local size of all cells in apCell[] */ - u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */ - int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */ -}; - -/* -** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been -** computed. -*/ -static void populateCellCache(CellArray *p, int idx, int N){ - MemPage *pRef = p->pRef; - u16 *szCell = p->szCell; - assert( idx>=0 && idx+N<=p->nCell ); - while( N>0 ){ - assert( p->apCell[idx]!=0 ); - if( szCell[idx]==0 ){ - szCell[idx] = pRef->xCellSize(pRef, p->apCell[idx]); - }else{ - assert( CORRUPT_DB || - szCell[idx]==pRef->xCellSize(pRef, p->apCell[idx]) ); - } - idx++; - N--; - } -} - -/* -** Return the size of the Nth element of the cell array -*/ -static SQLITE_NOINLINE u16 computeCellSize(CellArray *p, int N){ - assert( N>=0 && NnCell ); - assert( p->szCell[N]==0 ); - p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]); - return p->szCell[N]; -} -static u16 cachedCellSize(CellArray *p, int N){ - assert( N>=0 && NnCell ); - if( p->szCell[N] ) return p->szCell[N]; - return computeCellSize(p, N); -} - -/* -** Array apCell[] contains pointers to nCell b-tree page cells. The -** szCell[] array contains the size in bytes of each cell. This function -** replaces the current contents of page pPg with the contents of the cell -** array. -** -** Some of the cells in apCell[] may currently be stored in pPg. This -** function works around problems caused by this by making a copy of any -** such cells before overwriting the page data. -** -** The MemPage.nFree field is invalidated by this function. It is the -** responsibility of the caller to set it correctly. -*/ -static int rebuildPage( - CellArray *pCArray, /* Content to be added to page pPg */ - int iFirst, /* First cell in pCArray to use */ - int nCell, /* Final number of cells on page */ - MemPage *pPg /* The page to be reconstructed */ -){ - const int hdr = pPg->hdrOffset; /* Offset of header on pPg */ - u8 * const aData = pPg->aData; /* Pointer to data for pPg */ - const int usableSize = pPg->pBt->usableSize; - u8 * const pEnd = &aData[usableSize]; - int i = iFirst; /* Which cell to copy from pCArray*/ - u32 j; /* Start of cell content area */ - int iEnd = i+nCell; /* Loop terminator */ - u8 *pCellptr = pPg->aCellIdx; - u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); - u8 *pData; - int k; /* Current slot in pCArray->apEnd[] */ - u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */ - - assert( nCell>0 ); - assert( i(u32)usableSize ){ j = 0; } - memcpy(&pTmp[j], &aData[j], usableSize - j); - - assert( pCArray->ixNx[NB*2-1]>i ); - for(k=0; pCArray->ixNx[k]<=i; k++){} - pSrcEnd = pCArray->apEnd[k]; - - pData = pEnd; - while( 1/*exit by break*/ ){ - u8 *pCell = pCArray->apCell[i]; - u16 sz = pCArray->szCell[i]; - assert( sz>0 ); - 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 - && (uptr)(pCell)<(uptr)pSrcEnd - ){ - return SQLITE_CORRUPT_BKPT; - } - - pData -= sz; - put2byte(pCellptr, (pData - aData)); - pCellptr += 2; - if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT; - memmove(pData, pCell, sz); - assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB ); - i++; - if( i>=iEnd ) break; - if( pCArray->ixNx[k]<=i ){ - k++; - pSrcEnd = pCArray->apEnd[k]; - } - } - - /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ - assert( nCell < 10922 ); - pPg->nCell = (u16)nCell; - pPg->nOverflow = 0; - - put2byte(&aData[hdr+1], 0); - put2byte(&aData[hdr+3], pPg->nCell); - put2byte(&aData[hdr+5], pData - aData); - aData[hdr+7] = 0x00; - return SQLITE_OK; -} - -/* -** The pCArray objects contains pointers to b-tree cells and the cell sizes. -** This function attempts to add the cells stored in the array to page pPg. -** If it cannot (because the page needs to be defragmented before the cells -** will fit), non-zero is returned. Otherwise, if the cells are added -** successfully, zero is returned. -** -** Argument pCellptr points to the first entry in the cell-pointer array -** (part of page pPg) to populate. After cell apCell[0] is written to the -** page body, a 16-bit offset is written to pCellptr. And so on, for each -** cell in the array. It is the responsibility of the caller to ensure -** that it is safe to overwrite this part of the cell-pointer array. -** -** When this function is called, *ppData points to the start of the -** content area on page pPg. If the size of the content area is extended, -** *ppData is updated to point to the new start of the content area -** before returning. -** -** Finally, argument pBegin points to the byte immediately following the -** end of the space required by this page for the cell-pointer area (for -** all cells - not just those inserted by the current call). If the content -** area must be extended to before this point in order to accommodate all -** cells in apCell[], then the cells do not fit and non-zero is returned. -*/ -static int pageInsertArray( - MemPage *pPg, /* Page to add cells to */ - u8 *pBegin, /* End of cell-pointer array */ - u8 **ppData, /* IN/OUT: Page content-area pointer */ - u8 *pCellptr, /* Pointer to cell-pointer area */ - int iFirst, /* Index of first cell to add */ - int nCell, /* Number of cells to add to pPg */ - CellArray *pCArray /* Array of cells */ -){ - int i = iFirst; /* Loop counter - cell index to insert */ - u8 *aData = pPg->aData; /* Complete page */ - u8 *pData = *ppData; /* Content area. A subset of aData[] */ - int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */ - int k; /* Current slot in pCArray->apEnd[] */ - u8 *pEnd; /* Maximum extent of cell data */ - assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ - if( iEnd<=iFirst ) return 0; - assert( pCArray->ixNx[NB*2-1]>i ); - for(k=0; pCArray->ixNx[k]<=i ; k++){} - pEnd = pCArray->apEnd[k]; - while( 1 /*Exit by break*/ ){ - int sz, rc; - u8 *pSlot; - assert( pCArray->szCell[i]!=0 ); - sz = pCArray->szCell[i]; - if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ - if( (pData - pBegin)apCell[i] will never overlap on a well-formed - ** database. But they might for a corrupt database. Hence use memmove() - ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */ - assert( (pSlot+sz)<=pCArray->apCell[i] - || pSlot>=(pCArray->apCell[i]+sz) - || CORRUPT_DB ); - if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd - && (uptr)(pCArray->apCell[i])<(uptr)pEnd - ){ - assert( CORRUPT_DB ); - (void)SQLITE_CORRUPT_BKPT; - return 1; - } - memmove(pSlot, pCArray->apCell[i], sz); - put2byte(pCellptr, (pSlot - aData)); - pCellptr += 2; - i++; - if( i>=iEnd ) break; - if( pCArray->ixNx[k]<=i ){ - k++; - pEnd = pCArray->apEnd[k]; - } - } - *ppData = pData; - return 0; -} - -/* -** The pCArray object contains pointers to b-tree cells and their sizes. -** -** This function adds the space associated with each cell in the array -** that is currently stored within the body of pPg to the pPg free-list. -** The cell-pointers and other fields of the page are not updated. -** -** This function returns the total number of cells added to the free-list. -*/ -static int pageFreeArray( - MemPage *pPg, /* Page to edit */ - int iFirst, /* First cell to delete */ - int nCell, /* Cells to delete */ - CellArray *pCArray /* Array of cells */ -){ - u8 * const aData = pPg->aData; - u8 * const pEnd = &aData[pPg->pBt->usableSize]; - u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; - int nRet = 0; - int i, j; - int iEnd = iFirst + nCell; - int nFree = 0; - int aOfst[10]; - int aAfter[10]; - - for(i=iFirst; iapCell[i]; - if( SQLITE_WITHIN(pCell, pStart, pEnd) ){ - int sz; - int iAfter; - int iOfst; - /* No need to use cachedCellSize() here. The sizes of all cells that - ** are to be freed have already been computing while deciding which - ** cells need freeing */ - sz = pCArray->szCell[i]; assert( sz>0 ); - iOfst = (u16)(pCell - aData); - iAfter = iOfst+sz; - for(j=0; j=nFree ){ - if( nFree>=(int)(sizeof(aOfst)/sizeof(aOfst[0])) ){ - for(j=0; jpEnd ) return 0; - nFree++; - } - nRet++; - } - } - for(j=0; jnCell cells starting with -** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells -** starting at apCell[iNew]. -** -** This routine makes the necessary adjustments to pPg so that it contains -** the correct cells after being balanced. -** -** The pPg->nFree field is invalid when this function returns. It is the -** responsibility of the caller to set it correctly. -*/ -static int editPage( - MemPage *pPg, /* Edit this page */ - int iOld, /* Index of first cell currently on page */ - int iNew, /* Index of new first cell on page */ - int nNew, /* Final number of cells on page */ - CellArray *pCArray /* Array of cells and sizes */ -){ - u8 * const aData = pPg->aData; - const int hdr = pPg->hdrOffset; - u8 *pBegin = &pPg->aCellIdx[nNew * 2]; - int nCell = pPg->nCell; /* Cells stored on pPg */ - u8 *pData; - u8 *pCellptr; - int i; - int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; - int iNewEnd = iNew + nNew; - -#ifdef SQLITE_DEBUG - u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); - memcpy(pTmp, aData, pPg->pBt->usableSize); -#endif - - /* Remove cells from the start and end of the page */ - assert( nCell>=0 ); - if( iOldnCell) ) return SQLITE_CORRUPT_BKPT; - memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); - nCell -= nShift; - } - if( iNewEnd < iOldEnd ){ - int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); - assert( nCell>=nTail ); - nCell -= nTail; - } - - pData = &aData[get2byte(&aData[hdr+5])]; - if( pDatapPg->aDataEnd) ) goto editpage_fail; - - /* Add cells to the start of the page */ - if( iNew=0 ); - pCellptr = pPg->aCellIdx; - memmove(&pCellptr[nAdd*2], pCellptr, nCell*2); - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iNew, nAdd, pCArray - ) ) goto editpage_fail; - nCell += nAdd; - } - - /* Add any overflow cells */ - for(i=0; inOverflow; i++){ - int iCell = (iOld + pPg->aiOvfl[i]) - iNew; - if( iCell>=0 && iCellaCellIdx[iCell * 2]; - if( nCell>iCell ){ - memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); - } - nCell++; - cachedCellSize(pCArray, iCell+iNew); - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iCell+iNew, 1, pCArray - ) ) goto editpage_fail; - } - } - - /* Append cells to the end of the page */ - assert( nCell>=0 ); - pCellptr = &pPg->aCellIdx[nCell*2]; - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iNew+nCell, nNew-nCell, pCArray - ) - ){ - goto editpage_fail; - } - - assert( nNew < 10922 ); - pPg->nCell = (u16)nNew; - pPg->nOverflow = 0; - - put2byte(&aData[hdr+3], pPg->nCell); - put2byte(&aData[hdr+5], pData - aData); - -#ifdef SQLITE_DEBUG - for(i=0; iapCell[i+iNew]; - int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); - if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){ - pCell = &pTmp[pCell - aData]; - } - assert( 0==memcmp(pCell, &aData[iOff], - pCArray->pRef->xCellSize(pCArray->pRef, pCArray->apCell[i+iNew])) ); - } -#endif - - return SQLITE_OK; - editpage_fail: - /* Unable to edit this page. Rebuild it from scratch instead. */ - if( nNew<1 ) return SQLITE_CORRUPT_BKPT; - populateCellCache(pCArray, iNew, nNew); - return rebuildPage(pCArray, iNew, nNew, pPg); -} - - -#ifndef SQLITE_OMIT_QUICKBALANCE -/* -** This version of balance() handles the common special case where -** a new entry is being inserted on the extreme right-end of the -** tree, in other words, when the new entry will become the largest -** entry in the tree. -** -** Instead of trying to balance the 3 right-most leaf pages, just add -** a new page to the right-hand side and put the one new entry in -** that page. This leaves the right side of the tree somewhat -** unbalanced. But odds are that we will be inserting new entries -** at the end soon afterwards so the nearly empty page will quickly -** fill up. On average. -** -** pPage is the leaf page which is the right-most page in the tree. -** pParent is its parent. pPage must have a single overflow entry -** which is also the right-most entry on the page. -** -** The pSpace buffer is used to store a temporary copy of the divider -** cell that will be inserted into pParent. Such a cell consists of a 4 -** byte page number followed by a variable length integer. In other -** words, at most 13 bytes. Hence the pSpace buffer must be at -** least 13 bytes in size. -*/ -static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ - BtShared *const pBt = pPage->pBt; /* B-Tree Database */ - MemPage *pNew; /* Newly allocated page */ - int rc; /* Return Code */ - Pgno pgnoNew; /* Page number of pNew */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - assert( pPage->nOverflow==1 ); - - if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */ - assert( pPage->nFree>=0 ); - assert( pParent->nFree>=0 ); - - /* Allocate a new page. This page will become the right-sibling of - ** pPage. Make the parent page writable, so that the new divider cell - ** may be inserted. If both these operations are successful, proceed. - */ - rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); - - if( rc==SQLITE_OK ){ - - u8 *pOut = &pSpace[4]; - u8 *pCell = pPage->apOvfl[0]; - u16 szCell = pPage->xCellSize(pPage, pCell); - u8 *pStop; - CellArray b; - - assert( sqlite3PagerIswriteable(pNew->pDbPage) ); - assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); - zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); - b.nCell = 1; - b.pRef = pPage; - b.apCell = &pCell; - b.szCell = &szCell; - b.apEnd[0] = pPage->aDataEnd; - b.ixNx[0] = 2; - b.ixNx[NB*2-1] = 0x7fffffff; - rc = rebuildPage(&b, 0, 1, pNew); - if( NEVER(rc) ){ - releasePage(pNew); - return rc; - } - pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell; - - /* If this is an auto-vacuum database, update the pointer map - ** with entries for the new page, and any pointer from the - ** cell on the page to an overflow page. If either of these - ** operations fails, the return code is set, but the contents - ** of the parent page are still manipulated by the code below. - ** That is Ok, at this point the parent page is guaranteed to - ** be marked as dirty. Returning an error code will cause a - ** rollback, undoing any changes made to the parent page. - */ - if( ISAUTOVACUUM(pBt) ){ - ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); - if( szCell>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pNew, pCell, &rc); - } - } - - /* Create a divider cell to insert into pParent. The divider cell - ** consists of a 4-byte page number (the page number of pPage) and - ** a variable length key value (which must be the same value as the - ** largest key on pPage). - ** - ** To find the largest key value on pPage, first find the right-most - ** cell on pPage. The first two fields of this cell are the - ** record-length (a variable length integer at most 32-bits in size) - ** and the key value (a variable length integer, may have any value). - ** The first of the while(...) loops below skips over the record-length - ** field. The second while(...) loop copies the key value from the - ** cell on pPage into the pSpace buffer. - */ - pCell = findCell(pPage, pPage->nCell-1); - pStop = &pCell[9]; - while( (*(pCell++)&0x80) && pCellnCell, pSpace, (int)(pOut-pSpace), - 0, pPage->pgno); - } - - /* Set the right-child pointer of pParent to point to the new page. */ - put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); - - /* Release the reference to the new page. */ - releasePage(pNew); - } - - return rc; -} -#endif /* SQLITE_OMIT_QUICKBALANCE */ - -#if 0 -/* -** This function does not contribute anything to the operation of SQLite. -** it is sometimes activated temporarily while debugging code responsible -** for setting pointer-map entries. -*/ -static int ptrmapCheckPages(MemPage **apPage, int nPage){ - int i, j; - for(i=0; ipBt; - assert( pPage->isInit ); - - for(j=0; jnCell; j++){ - CellInfo info; - u8 *z; - - z = findCell(pPage, j); - pPage->xParseCell(pPage, z, &info); - if( info.nLocalpgno && e==PTRMAP_OVERFLOW1 ); - } - if( !pPage->leaf ){ - Pgno child = get4byte(z); - ptrmapGet(pBt, child, &e, &n); - assert( n==pPage->pgno && e==PTRMAP_BTREE ); - } - } - if( !pPage->leaf ){ - Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]); - ptrmapGet(pBt, child, &e, &n); - assert( n==pPage->pgno && e==PTRMAP_BTREE ); - } - } - return 1; -} -#endif - -/* -** This function is used to copy the contents of the b-tree node stored -** on page pFrom to page pTo. If page pFrom was not a leaf page, then -** the pointer-map entries for each child page are updated so that the -** parent page stored in the pointer map is page pTo. If pFrom contained -** any cells with overflow page pointers, then the corresponding pointer -** map entries are also updated so that the parent page is page pTo. -** -** If pFrom is currently carrying any overflow cells (entries in the -** MemPage.apOvfl[] array), they are not copied to pTo. -** -** Before returning, page pTo is reinitialized using btreeInitPage(). -** -** The performance of this function is not critical. It is only used by -** the balance_shallower() and balance_deeper() procedures, neither of -** which are called often under normal circumstances. -*/ -static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ - if( (*pRC)==SQLITE_OK ){ - BtShared * const pBt = pFrom->pBt; - u8 * const aFrom = pFrom->aData; - u8 * const aTo = pTo->aData; - int const iFromHdr = pFrom->hdrOffset; - int const iToHdr = ((pTo->pgno==1) ? 100 : 0); - int rc; - int iData; - - - assert( pFrom->isInit ); - assert( pFrom->nFree>=iToHdr ); - assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize ); - - /* Copy the b-tree node content from page pFrom to page pTo. */ - iData = get2byte(&aFrom[iFromHdr+5]); - memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); - memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); - - /* Reinitialize page pTo so that the contents of the MemPage structure - ** match the new data. The initialization of pTo can actually fail under - ** fairly obscure circumstances, even though it is a copy of initialized - ** page pFrom. - */ - pTo->isInit = 0; - rc = btreeInitPage(pTo); - if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo); - if( rc!=SQLITE_OK ){ - *pRC = rc; - return; - } - - /* If this is an auto-vacuum database, update the pointer-map entries - ** for any b-tree or overflow pages that pTo now contains the pointers to. - */ - if( ISAUTOVACUUM(pBt) ){ - *pRC = setChildPtrmaps(pTo); - } - } -} - -/* -** This routine redistributes cells on the iParentIdx'th child of pParent -** (hereafter "the page") and up to 2 siblings so that all pages have about the -** same amount of free space. Usually a single sibling on either side of the -** page are used in the balancing, though both siblings might come from one -** side if the page is the first or last child of its parent. If the page -** has fewer than 2 siblings (something which can only happen if the page -** is a root page or a child of a root page) then all available siblings -** participate in the balancing. -** -** The number of siblings of the page might be increased or decreased by -** one or two in an effort to keep pages nearly full but not over full. -** -** Note that when this routine is called, some of the cells on the page -** might not actually be stored in MemPage.aData[]. This can happen -** if the page is overfull. This routine ensures that all cells allocated -** to the page and its siblings fit into MemPage.aData[] before returning. -** -** In the course of balancing the page and its siblings, cells may be -** inserted into or removed from the parent page (pParent). Doing so -** may cause the parent page to become overfull or underfull. If this -** happens, it is the responsibility of the caller to invoke the correct -** balancing routine to fix this problem (see the balance() routine). -** -** If this routine fails for any reason, it might leave the database -** in a corrupted state. So if this routine fails, the database should -** be rolled back. -** -** The third argument to this function, aOvflSpace, is a pointer to a -** buffer big enough to hold one page. If while inserting cells into the parent -** page (pParent) the parent page becomes overfull, this buffer is -** used to store the parent's overflow cells. Because this function inserts -** a maximum of four divider cells into the parent page, and the maximum -** size of a cell stored within an internal node is always less than 1/4 -** of the page-size, the aOvflSpace[] buffer is guaranteed to be large -** enough for all overflow cells. -** -** If aOvflSpace is set to a null pointer, this function returns -** SQLITE_NOMEM. -*/ -static int balance_nonroot( - MemPage *pParent, /* Parent page of siblings being balanced */ - int iParentIdx, /* Index of "the page" in pParent */ - u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ - int isRoot, /* True if pParent is a root-page */ - int bBulk /* True if this call is part of a bulk load */ -){ - BtShared *pBt; /* The whole database */ - int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ - int nNew = 0; /* Number of pages in apNew[] */ - int nOld; /* Number of pages in apOld[] */ - int i, j, k; /* Loop counters */ - int nxDiv; /* Next divider slot in pParent->aCell[] */ - int rc = SQLITE_OK; /* The return code */ - u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */ - int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ - int usableSpace; /* Bytes in pPage beyond the header */ - int pageFlags; /* Value of pPage->aData[0] */ - int iSpace1 = 0; /* First unused byte of aSpace1[] */ - int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ - u64 szScratch; /* Size of scratch memory requested */ - MemPage *apOld[NB]; /* pPage and up to two siblings */ - MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ - u8 *pRight; /* Location in parent of right-sibling pointer */ - u8 *apDiv[NB-1]; /* Divider cells in pParent */ - int cntNew[NB+2]; /* Index in b.paCell[] of cell after i-th page */ - int cntOld[NB+2]; /* Old index in b.apCell[] */ - int szNew[NB+2]; /* Combined size of cells placed on i-th page */ - u8 *aSpace1; /* Space for copies of dividers cells */ - 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 */ - CellArray b; /* Parsed information on cells being balanced */ - - memset(abDone, 0, sizeof(abDone)); - assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) ); - memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0])); - b.ixNx[NB*2-1] = 0x7fffffff; - pBt = pParent->pBt; - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - - /* At this point pParent may have at most one overflow cell. And if - ** this overflow cell is present, it must be the cell with - ** index iParentIdx. This scenario comes about when this function - ** is called (indirectly) from sqlite3BtreeDelete(). - */ - assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); - assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); - - if( !aOvflSpace ){ - return SQLITE_NOMEM_BKPT; - } - assert( pParent->nFree>=0 ); - - /* Find the sibling pages to balance. Also locate the cells in pParent - ** that divide the siblings. An attempt is made to find NN siblings on - ** either side of pPage. More siblings are taken from one side, however, - ** if there are fewer than NN siblings on the other side. If pParent - ** has NB or fewer children then all children of pParent are taken. - ** - ** This loop also drops the divider cells from the parent page. This - ** way, the remainder of the function does not have to deal with any - ** overflow cells in the parent page, since if any existed they will - ** have already been removed. - */ - i = pParent->nOverflow + pParent->nCell; - if( i<2 ){ - nxDiv = 0; - }else{ - assert( bBulk==0 || bBulk==1 ); - if( iParentIdx==0 ){ - nxDiv = 0; - }else if( iParentIdx==i ){ - nxDiv = i-2+bBulk; - }else{ - nxDiv = iParentIdx-1; - } - i = 2-bBulk; - } - nOld = i+1; - if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ - pRight = &pParent->aData[pParent->hdrOffset+8]; - }else{ - pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); - } - pgno = get4byte(pRight); - while( 1 ){ - if( rc==SQLITE_OK ){ - rc = getAndInitPage(pBt, pgno, &apOld[i], 0); - } - if( rc ){ - memset(apOld, 0, (i+1)*sizeof(MemPage*)); - goto balance_cleanup; - } - if( apOld[i]->nFree<0 ){ - rc = btreeComputeFreeSpace(apOld[i]); - if( rc ){ - memset(apOld, 0, (i)*sizeof(MemPage*)); - goto balance_cleanup; - } - } - nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl); - if( (i--)==0 ) break; - - if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ - apDiv[i] = pParent->apOvfl[0]; - pgno = get4byte(apDiv[i]); - szNew[i] = pParent->xCellSize(pParent, apDiv[i]); - pParent->nOverflow = 0; - }else{ - apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); - pgno = get4byte(apDiv[i]); - szNew[i] = pParent->xCellSize(pParent, apDiv[i]); - - /* Drop the cell from the parent page. apDiv[i] still points to - ** the cell within the parent, even though it has been dropped. - ** This is safe because dropping a cell only overwrites the first - ** four bytes of it, and this function does not need the first - ** four bytes of the divider cell. So the pointer is safe to use - ** later on. - ** - ** But not if we are in secure-delete mode. In secure-delete mode, - ** the dropCell() routine will overwrite the entire cell with zeroes. - ** In this case, temporarily copy the cell into the aOvflSpace[] - ** buffer. It will be copied out again as soon as the aSpace[] buffer - ** is allocated. */ - 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 ){ - memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); - apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; - } - } - dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); - } - } - - /* Make nMaxCells a multiple of 4 in order to preserve 8-byte - ** alignment */ - nMaxCells = (nMaxCells + 3)&~3; - - /* - ** Allocate space for memory structures - */ - szScratch = - nMaxCells*sizeof(u8*) /* b.apCell */ - + nMaxCells*sizeof(u16) /* b.szCell */ - + pBt->pageSize; /* aSpace1 */ - - assert( szScratch<=7*(int)pBt->pageSize ); - b.apCell = sqlite3StackAllocRaw(0, szScratch ); - if( b.apCell==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto balance_cleanup; - } - b.szCell = (u16*)&b.apCell[nMaxCells]; - aSpace1 = (u8*)&b.szCell[nMaxCells]; - assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); - - /* - ** Load pointers to all cells on sibling pages and the divider cells - ** into the local b.apCell[] array. Make copies of the divider cells - ** into space obtained from aSpace1[]. The divider cells have already - ** been removed from pParent. - ** - ** If the siblings are on leaf pages, then the child pointers of the - ** divider cells are stripped from the cells before they are copied - ** into aSpace1[]. In this way, all cells in b.apCell[] are without - ** child pointers. If siblings are not leaves, then all cell in - ** b.apCell[] include child pointers. Either way, all cells in b.apCell[] - ** are alike. - ** - ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. - ** leafData: 1 if pPage holds key+data and pParent holds only keys. - */ - b.pRef = apOld[0]; - leafCorrection = b.pRef->leaf*4; - leafData = b.pRef->intKeyLeaf; - for(i=0; inCell; - u8 *aData = pOld->aData; - u16 maskPage = pOld->maskPage; - u8 *piCell = aData + pOld->cellOffset; - u8 *piEnd; - VVA_ONLY( int nCellAtStart = b.nCell; ) - - /* Verify that all sibling pages are of the same "type" (table-leaf, - ** table-interior, index-leaf, or index-interior). - */ - if( pOld->aData[0]!=apOld[0]->aData[0] ){ - rc = SQLITE_CORRUPT_PAGE(pOld); - goto balance_cleanup; - } - - /* Load b.apCell[] with pointers to all cells in pOld. If pOld - ** contains overflow cells, include them in the b.apCell[] array - ** in the correct spot. - ** - ** Note that when there are multiple overflow cells, it is always the - ** case that they are sequential and adjacent. This invariant arises - ** because multiple overflows can only occurs when inserting divider - ** cells into a parent on a prior balance, and divider cells are always - ** adjacent and are inserted in order. There is an assert() tagged - ** with "NOTE 1" in the overflow cell insertion loop to prove this - ** invariant. - ** - ** This must be done in advance. Once the balance starts, the cell - ** offset section of the btree page will be overwritten and we will no - ** long be able to find the cells if a pointer to each cell is not saved - ** first. - */ - memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow)); - if( pOld->nOverflow>0 ){ - if( NEVER(limitaiOvfl[0]) ){ - rc = SQLITE_CORRUPT_PAGE(pOld); - goto balance_cleanup; - } - limit = pOld->aiOvfl[0]; - for(j=0; jnOverflow; k++){ - assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */ - b.apCell[b.nCell] = pOld->apOvfl[k]; - b.nCell++; - } - } - piEnd = aData + pOld->cellOffset + 2*pOld->nCell; - while( piCellnCell+pOld->nOverflow) ); - - cntOld[i] = b.nCell; - if( imaxLocal+23 ); - assert( iSpace1 <= (int)pBt->pageSize ); - memcpy(pTemp, apDiv[i], sz); - b.apCell[b.nCell] = pTemp+leafCorrection; - assert( leafCorrection==0 || leafCorrection==4 ); - b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection; - if( !pOld->leaf ){ - assert( leafCorrection==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); - }else{ - assert( leafCorrection==4 ); - while( b.szCell[b.nCell]<4 ){ - /* Do not allow any cells smaller than 4 bytes. If a smaller cell - ** does exist, pad it with 0x00 bytes. */ - assert( b.szCell[b.nCell]==3 || CORRUPT_DB ); - assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || CORRUPT_DB ); - aSpace1[iSpace1++] = 0x00; - b.szCell[b.nCell]++; - } - } - b.nCell++; - } - } - - /* - ** Figure out the number of pages needed to hold all b.nCell cells. - ** Store this number in "k". Also compute szNew[] which is the total - ** size of all cells on the i-th page and cntNew[] which is the index - ** in b.apCell[] of the cell that divides page i from page i+1. - ** cntNew[k] should equal b.nCell. - ** - ** Values computed by this block: - ** - ** k: The total number of sibling pages - ** szNew[i]: Spaced used on the i-th sibling page. - ** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to - ** the right of the i-th sibling page. - ** usableSpace: Number of bytes of space available on each sibling. - ** - */ - usableSpace = pBt->usableSize - 12 + leafCorrection; - for(i=k=0; iaDataEnd; - b.ixNx[k] = cntOld[i]; - if( k && b.ixNx[k]==b.ixNx[k-1] ){ - k--; /* Omit b.ixNx[] entry for child pages with no cells */ - } - if( !leafData ){ - k++; - b.apEnd[k] = pParent->aDataEnd; - b.ixNx[k] = cntOld[i]+1; - } - assert( p->nFree>=0 ); - szNew[i] = usableSpace - p->nFree; - for(j=0; jnOverflow; j++){ - szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); - } - cntNew[i] = cntOld[i]; - } - k = nOld; - for(i=0; iusableSpace ){ - if( i+1>=k ){ - k = i+2; - if( k>NB+2 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } - szNew[k-1] = 0; - cntNew[k-1] = b.nCell; - } - sz = 2 + cachedCellSize(&b, cntNew[i]-1); - szNew[i] -= sz; - if( !leafData ){ - if( cntNew[i]usableSpace ) break; - szNew[i] += sz; - cntNew[i]++; - if( !leafData ){ - if( cntNew[i]=b.nCell ){ - k = i+1; - }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - } - - /* - ** The packing computed by the previous block is biased toward the siblings - ** on the left side (siblings with smaller keys). The left siblings are - ** always nearly full, while the right-most sibling might be nearly empty. - ** The next block of code attempts to adjust the packing of siblings to - ** get a better balance. - ** - ** This adjustment is more than an optimization. The packing above might - ** be so out of balance as to be illegal. For example, the right-most - ** sibling might be completely empty. This adjustment is not optional. - */ - for(i=k-1; i>0; i--){ - int szRight = szNew[i]; /* Size of sibling on the right */ - int szLeft = szNew[i-1]; /* Size of sibling on the left */ - int r; /* Index of right-most cell in left sibling */ - int d; /* Index of first cell to the left of right sibling */ - - r = cntNew[i-1] - 1; - d = r + 1 - leafData; - (void)cachedCellSize(&b, d); - do{ - int szR, szD; - assert( d szLeft-(szR+(i==k-1?0:2)))){ - break; - } - szRight += szD + 2; - szLeft -= szR + 2; - cntNew[i-1] = r; - r--; - d--; - }while( r>=0 ); - szNew[i] = szRight; - szNew[i-1] = szLeft; - if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - } - - /* Sanity check: For a non-corrupt database file one of the following - ** must be true: - ** (1) We found one or more cells (cntNew[0])>0), or - ** (2) pPage is a virtual root page. A virtual root page is when - ** the real root page is page 1 and we are the only child of - ** that page. - */ - assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); - TRACE(("BALANCE: old: %u(nc=%u) %u(nc=%u) %u(nc=%u)\n", - apOld[0]->pgno, apOld[0]->nCell, - nOld>=2 ? apOld[1]->pgno : 0, nOld>=2 ? apOld[1]->nCell : 0, - nOld>=3 ? apOld[2]->pgno : 0, nOld>=3 ? apOld[2]->nCell : 0 - )); - - /* - ** Allocate k new pages. Reuse old pages where possible. - */ - pageFlags = apOld[0]->aData[0]; - for(i=0; ipDbPage); - nNew++; - if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) - && rc==SQLITE_OK - ){ - rc = SQLITE_CORRUPT_BKPT; - } - if( rc ) goto balance_cleanup; - }else{ - assert( i>0 ); - rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); - if( rc ) goto balance_cleanup; - zeroPage(pNew, pageFlags); - apNew[i] = pNew; - nNew++; - cntOld[i] = b.nCell; - - /* Set the pointer-map entry for the new sibling page. */ - if( ISAUTOVACUUM(pBt) ){ - ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } - } - } - - /* - ** Reassign page numbers so that the new pages are in ascending order. - ** This helps to keep entries in the disk file in order so that a scan - ** 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*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; ipgno; - assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE ); - assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY ); - } - for(i=0; ipgno < apNew[iB]->pgno ) iB = j; - } - - /* 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; - sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB); - sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); - sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); - apNew[i]->pgno = pgnoB; - apNew[iB]->pgno = pgnoA; - } - } - - TRACE(("BALANCE: new: %u(%u nc=%u) %u(%u nc=%u) %u(%u nc=%u) " - "%u(%u nc=%u) %u(%u nc=%u)\n", - apNew[0]->pgno, szNew[0], cntNew[0], - nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, - nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0, - nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, - nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0, - nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, - nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0, - nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0, - nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0 - )); - - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - assert( nNew>=1 && nNew<=ArraySize(apNew) ); - assert( apNew[nNew-1]!=0 ); - put4byte(pRight, apNew[nNew-1]->pgno); - - /* If the sibling pages are not leaves, ensure that the right-child pointer - ** of the right-most new sibling page is set to the value that was - ** originally in the same field of the right-most old sibling page. */ - if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ - MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1]; - memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4); - } - - /* Make any required updates to pointer map entries associated with - ** cells stored on sibling pages following the balance operation. Pointer - ** map entries associated with divider cells are set by the insertCell() - ** routine. The associated pointer map entries are: - ** - ** a) if the cell contains a reference to an overflow chain, the - ** entry associated with the first page in the overflow chain, and - ** - ** b) if the sibling pages are not leaves, the child page associated - ** with the cell. - ** - ** If the sibling pages are not leaves, then the pointer map entry - ** associated with the right-child of each sibling may also need to be - ** updated. This happens below, after the sibling pages have been - ** populated, not here. - */ - if( ISAUTOVACUUM(pBt) ){ - MemPage *pOld; - MemPage *pNew = pOld = apNew[0]; - int cntOldNext = pNew->nCell + pNew->nOverflow; - int iNew = 0; - int iOld = 0; - - for(i=0; i=0 && iOldnCell + pOld->nOverflow + !leafData; - } - if( i==cntNew[iNew] ){ - pNew = apNew[++iNew]; - if( !leafData ) continue; - } - - /* Cell pCell is destined for new sibling page pNew. Originally, it - ** was either part of sibling page iOld (possibly an overflow cell), - ** or else the divider cell to the left of sibling page iOld. So, - ** if sibling page iOld had the same page number as pNew, and if - ** pCell really was a part of sibling page iOld (not a divider or - ** overflow cell), we can skip updating the pointer map entries. */ - if( iOld>=nNew - || pNew->pgno!=aPgno[iOld] - || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd) - ){ - if( !leafCorrection ){ - ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); - } - if( cachedCellSize(&b,i)>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pOld, pCell, &rc); - } - if( rc ) goto balance_cleanup; - } - } - } - - /* Insert new divider cells into pParent. */ - for(i=0; ileaf ){ - memcpy(&pNew->aData[8], pCell, 4); - }else if( leafData ){ - /* If the tree is a leaf-data tree, and the siblings are leaves, - ** then there is no divider cell in b.apCell[]. Instead, the divider - ** cell consists of the integer key for the right-most cell of - ** the sibling-page assembled above only. - */ - CellInfo info; - j--; - pNew->xParseCell(pNew, b.apCell[j], &info); - pCell = pTemp; - sz = 4 + putVarint(&pCell[4], info.nKey); - pTemp = 0; - }else{ - pCell -= 4; - /* Obscure case for non-leaf-data trees: If the cell at pCell was - ** previously stored on a leaf node, and its reported size was 4 - ** bytes, then it may actually be smaller than this - ** (see btreeParseCellPtr(), 4 bytes is the minimum size of - ** any cell). But it is important to pass the correct size to - ** insertCell(), so reparse the cell now. - ** - ** This can only happen for b-trees used to evaluate "IN (SELECT ...)" - ** and WITHOUT ROWID tables with exactly one column which is the - ** primary key. - */ - if( b.szCell[j]==4 ){ - assert(leafCorrection==4); - sz = pParent->xCellSize(pParent, pCell); - } - } - iOvflSpace += sz; - assert( sz<=pBt->maxLocal+23 ); - assert( iOvflSpace <= (int)pBt->pageSize ); - assert( b.ixNx[NB*2-1]>j ); - for(k=0; b.ixNx[k]<=j; k++){} - pSrcEnd = b.apEnd[k]; - if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - rc = insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno); - if( rc!=SQLITE_OK ) goto balance_cleanup; - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - } - - /* Now update the actual sibling pages. The order in which they are updated - ** is important, as this code needs to avoid disrupting any page from which - ** cells may still to be read. In practice, this means: - ** - ** (1) If cells are moving left (from apNew[iPg] to apNew[iPg-1]) - ** then it is not safe to update page apNew[iPg] until after - ** the left-hand sibling apNew[iPg-1] has been updated. - ** - ** (2) If cells are moving right (from apNew[iPg] to apNew[iPg+1]) - ** then it is not safe to update page apNew[iPg] until after - ** the right-hand sibling apNew[iPg+1] has been updated. - ** - ** If neither of the above apply, the page is safe to update. - ** - ** The iPg value in the following loop starts at nNew-1 goes down - ** to 0, then back up to nNew-1 again, thus making two passes over - ** the pages. On the initial downward pass, only condition (1) above - ** needs to be tested because (2) will always be true from the previous - ** step. On the upward pass, both conditions are always true, so the - ** upwards pass simply processes pages that were missed on the downward - ** pass. - */ - for(i=1-nNew; i=0 && iPg=1 || i>=0 ); - assert( iPg=0 /* On the upwards pass, or... */ - || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ - ){ - int iNew; - int iOld; - int nNewCell; - - /* Verify condition (1): If cells are moving left, update iPg - ** only after iPg-1 has already been updated. */ - assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] ); - - /* Verify condition (2): If cells are moving right, update iPg - ** only after iPg+1 has already been updated. */ - assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] ); - - if( iPg==0 ){ - iNew = iOld = 0; - nNewCell = cntNew[0]; - }else{ - iOld = iPgnFree = usableSpace-szNew[iPg]; - assert( apNew[iPg]->nOverflow==0 ); - assert( apNew[iPg]->nCell==nNewCell ); - } - } - - /* All pages have been processed exactly once */ - assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 ); - - assert( nOld>0 ); - assert( nNew>0 ); - - if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){ - /* The root page of the b-tree now contains no cells. The only sibling - ** page is the right-child of the parent. Copy the contents of the - ** child page into the parent, decreasing the overall height of the - ** b-tree structure by one. This is described as the "balance-shallower" - ** sub-algorithm in some documentation. - ** - ** If this is an auto-vacuum database, the call to copyNodeContent() - ** sets all pointer-map entries corresponding to database image pages - ** for which the pointer is stored within the content being copied. - ** - ** It is critical that the child page be defragmented before being - ** copied into the parent, because if the parent is page 1 then it will - ** by smaller than the child due to the database header, and so all the - ** free space needs to be up front. - */ - assert( nNew==1 || CORRUPT_DB ); - rc = defragmentPage(apNew[0], -1); - testcase( rc!=SQLITE_OK ); - assert( apNew[0]->nFree == - (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset - - apNew[0]->nCell*2) - || rc!=SQLITE_OK - ); - copyNodeContent(apNew[0], pParent, &rc); - freePage(apNew[0], &rc); - }else if( ISAUTOVACUUM(pBt) && !leafCorrection ){ - /* Fix the pointer map entries associated with the right-child of each - ** sibling page. All other pointer map entries have already been taken - ** care of. */ - for(i=0; iaData[8]); - ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); - } - } - - assert( pParent->isInit ); - TRACE(("BALANCE: finished: old=%u new=%u cells=%u\n", - nOld, nNew, b.nCell)); - - /* Free any old pages that were not reused as new pages. - */ - for(i=nNew; iisInit ){ - /* The ptrmapCheckPages() contains assert() statements that verify that - ** all pointer map pages are set correctly. This is helpful while - ** debugging. This is usually disabled because a corrupt database may - ** cause an assert() statement to fail. */ - ptrmapCheckPages(apNew, nNew); - ptrmapCheckPages(&pParent, 1); - } -#endif - - /* - ** Cleanup before returning. - */ -balance_cleanup: - sqlite3StackFree(0, b.apCell); - for(i=0; ipBt; /* The BTree */ - - assert( pRoot->nOverflow>0 ); - assert( sqlite3_mutex_held(pBt->mutex) ); - - /* Make pRoot, the root page of the b-tree, writable. Allocate a new - ** page that will become the new right-child of pPage. Copy the contents - ** of the node stored on pRoot into the new child page. - */ - rc = sqlite3PagerWrite(pRoot->pDbPage); - if( rc==SQLITE_OK ){ - rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); - copyNodeContent(pRoot, pChild, &rc); - if( ISAUTOVACUUM(pBt) ){ - ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); - } - } - if( rc ){ - *ppChild = 0; - releasePage(pChild); - return rc; - } - assert( sqlite3PagerIswriteable(pChild->pDbPage) ); - assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); - - TRACE(("BALANCE: copy root %u into %u\n", pRoot->pgno, pChild->pgno)); - - /* Copy the overflow cells from pRoot to pChild */ - memcpy(pChild->aiOvfl, pRoot->aiOvfl, - pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); - memcpy(pChild->apOvfl, pRoot->apOvfl, - pRoot->nOverflow*sizeof(pRoot->apOvfl[0])); - pChild->nOverflow = pRoot->nOverflow; - - /* Zero the contents of pRoot. Then install pChild as the right-child. */ - zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF); - put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild); - - *ppChild = pChild; - return SQLITE_OK; -} - -/* -** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid -** on the same B-tree as pCur. -** -** 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 -** rebalance, that can change content out from under the cursor on the -** first SQL table, violating invariants on the first insert. -*/ -static int anotherValidCursor(BtCursor *pCur){ - BtCursor *pOther; - for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){ - if( pOther!=pCur - && pOther->eState==CURSOR_VALID - && pOther->pPage==pCur->pPage - ){ - return SQLITE_CORRUPT_PAGE(pCur->pPage); - } - } - return SQLITE_OK; -} - -/* -** The page that pCur currently points to has just been modified in -** some way. This function figures out if this modification means the -** tree needs to be balanced, and if so calls the appropriate balancing -** routine. Balancing routines are: -** -** balance_quick() -** balance_deeper() -** balance_nonroot() -*/ -static int balance(BtCursor *pCur){ - int rc = SQLITE_OK; - u8 aBalanceQuickSpace[13]; - u8 *pFree = 0; - - VVA_ONLY( int balance_quick_called = 0 ); - VVA_ONLY( int balance_deeper_called = 0 ); - - do { - int iPage; - MemPage *pPage = pCur->pPage; - - if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break; - 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 ){ - /* The root page of the b-tree is overfull. In this case call the - ** balance_deeper() function to create a new child for the root-page - ** and copy the current contents of the root-page to it. The - ** next iteration of the do-loop will balance the child page. - */ - assert( balance_deeper_called==0 ); - VVA_ONLY( balance_deeper_called++ ); - rc = balance_deeper(pPage, &pCur->apPage[1]); - if( rc==SQLITE_OK ){ - pCur->iPage = 1; - pCur->ix = 0; - pCur->aiIdx[0] = 0; - pCur->apPage[0] = pPage; - pCur->pPage = pCur->apPage[1]; - assert( pCur->pPage->nOverflow ); - } - }else{ - break; - } - }else if( sqlite3PagerPageRefcount(pPage->pDbPage)>1 ){ - /* The page being written is not a root page, and there is currently - ** more than one reference to it. This only happens if the page is one - ** of its own ancestor pages. Corruption. */ - rc = SQLITE_CORRUPT_PAGE(pPage); - }else{ - MemPage * const pParent = pCur->apPage[iPage-1]; - int const iIdx = pCur->aiIdx[iPage-1]; - - rc = sqlite3PagerWrite(pParent->pDbPage); - if( rc==SQLITE_OK && pParent->nFree<0 ){ - rc = btreeComputeFreeSpace(pParent); - } - if( rc==SQLITE_OK ){ -#ifndef SQLITE_OMIT_QUICKBALANCE - if( pPage->intKeyLeaf - && pPage->nOverflow==1 - && pPage->aiOvfl[0]==pPage->nCell - && pParent->pgno!=1 - && pParent->nCell==iIdx - ){ - /* Call balance_quick() to create a new sibling of pPage on which - ** to store the overflow cell. balance_quick() inserts a new cell - ** into pParent, which may cause pParent overflow. If this - ** happens, the next iteration of the do-loop will balance pParent - ** use either balance_nonroot() or balance_deeper(). Until this - ** happens, the overflow cell is stored in the aBalanceQuickSpace[] - ** buffer. - ** - ** The purpose of the following assert() is to check that only a - ** single call to balance_quick() is made for each call to this - ** function. If this were not verified, a subtle bug involving reuse - ** of the aBalanceQuickSpace[] might sneak in. - */ - assert( balance_quick_called==0 ); - VVA_ONLY( balance_quick_called++ ); - rc = balance_quick(pParent, pPage, aBalanceQuickSpace); - }else -#endif - { - /* In this case, call balance_nonroot() to redistribute cells - ** between pPage and up to 2 of its sibling pages. This involves - ** modifying the contents of pParent, which may cause pParent to - ** become overfull or underfull. The next iteration of the do-loop - ** will balance the parent page to correct this. - ** - ** If the parent page becomes overfull, the overflow cell or cells - ** are stored in the pSpace buffer allocated immediately below. - ** A subsequent iteration of the do-loop will deal with this by - ** calling balance_nonroot() (balance_deeper() may be called first, - ** but it doesn't deal with overflow cells - just moves them to a - ** different page). Once this subsequent call to balance_nonroot() - ** has completed, it is safe to release the pSpace buffer used by - ** the previous call, as the overflow cell data will have been - ** copied either into the body of a database page or into the new - ** pSpace buffer passed to the latter call to balance_nonroot(). - */ - u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); - rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, - pCur->hints&BTREE_BULKLOAD); - if( pFree ){ - /* If pFree is not NULL, it points to the pSpace buffer used - ** by a previous call to balance_nonroot(). Its contents are - ** now stored either on real database pages or within the - ** new pSpace buffer, so it may be safely freed here. */ - sqlite3PageFree(pFree); - } - - /* The pSpace buffer will be freed after the next call to - ** balance_nonroot(), or just before this function returns, whichever - ** comes first. */ - pFree = pSpace; - } - } - - pPage->nOverflow = 0; - - /* The next iteration of the do-loop balances the parent page. */ - releasePage(pPage); - pCur->iPage--; - assert( pCur->iPage>=0 ); - pCur->pPage = pCur->apPage[pCur->iPage]; - } - }while( rc==SQLITE_OK ); - - if( pFree ){ - sqlite3PageFree(pFree); - } - return rc; -} - -/* Overwrite content from pX into pDest. Only do the write if the -** content is different from what is already there. -*/ -static int btreeOverwriteContent( - MemPage *pPage, /* MemPage on which writing will occur */ - u8 *pDest, /* Pointer to the place to start writing */ - const BtreePayload *pX, /* Source of data to write */ - int iOffset, /* Offset of first byte to write */ - int iAmt /* Number of bytes to be written */ -){ - int nData = pX->nData - iOffset; - if( nData<=0 ){ - /* Overwriting with zeros */ - int i; - for(i=0; ipDbPage); - if( rc ) return rc; - memset(pDest + i, 0, iAmt - i); - } - }else{ - if( nDatapData) + iOffset, iAmt)!=0 ){ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ) return rc; - /* In a corrupt database, it is possible for the source and destination - ** buffers to overlap. This is harmless since the database is already - ** corrupt but it does cause valgrind and ASAN warnings. So use - ** memmove(). */ - memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt); - } - } - return SQLITE_OK; -} - -/* -** Overwrite the cell that cursor pCur is pointing to with fresh content -** contained in pX. In this variant, pCur is pointing to an overflow -** cell. -*/ -static SQLITE_NOINLINE int btreeOverwriteOverflowCell( - BtCursor *pCur, /* Cursor pointing to cell to overwrite */ - const BtreePayload *pX /* Content to write into the cell */ -){ - int iOffset; /* Next byte of pX->pData to write */ - int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ - int rc; /* Return code */ - MemPage *pPage = pCur->pPage; /* Page being written */ - BtShared *pBt; /* Btree */ - Pgno ovflPgno; /* Next overflow page to write */ - u32 ovflPageSize; /* Size to write on overflow page */ - - assert( pCur->info.nLocalinfo.pPayload, pX, - 0, pCur->info.nLocal); - if( rc ) return rc; - - /* Now overwrite the overflow pages */ - iOffset = pCur->info.nLocal; - assert( nTotal>=0 ); - assert( iOffset>=0 ); - ovflPgno = get4byte(pCur->info.pPayload + iOffset); - pBt = pPage->pBt; - ovflPageSize = pBt->usableSize - 4; - do{ - rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); - if( rc ) return rc; - if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){ - rc = SQLITE_CORRUPT_PAGE(pPage); - }else{ - if( iOffset+ovflPageSize<(u32)nTotal ){ - ovflPgno = get4byte(pPage->aData); - }else{ - ovflPageSize = nTotal - iOffset; - } - rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, - iOffset, ovflPageSize); - } - sqlite3PagerUnref(pPage->pDbPage); - if( rc ) return rc; - iOffset += ovflPageSize; - }while( iOffsetnData + pX->nZero; /* Total bytes of to write */ - MemPage *pPage = pCur->pPage; /* Page being written */ - - if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd - || pCur->info.pPayload < pPage->aData + pPage->cellOffset - ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( pCur->info.nLocal==nTotal ){ - /* The entire cell is local */ - return btreeOverwriteContent(pPage, pCur->info.pPayload, pX, - 0, pCur->info.nLocal); - }else{ - /* The cell contains overflow content */ - return btreeOverwriteOverflowCell(pCur, pX); - } -} - - -/* -** Insert a new record into the BTree. The content of the new record -** is described by the pX object. The pCur cursor is used only to -** define what table the record should be inserted into, and is left -** pointing at a random location. -** -** For a table btree (used for rowid tables), only the pX.nKey value of -** the key is used. The pX.pKey value must be NULL. The pX.nKey is the -** rowid or INTEGER PRIMARY KEY of the row. The pX.nData,pData,nZero fields -** hold the content of the row. -** -** For an index btree (used for indexes and WITHOUT ROWID tables), the -** key is an arbitrary byte sequence stored in pX.pKey,nKey. The -** pX.pData,nData,nZero fields must be zero. -** -** If the seekResult parameter is non-zero, then a successful call to -** 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 -** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell -** that is larger than (pKey,nKey). -** -** If seekResult==0, that means pCur is pointing at some unknown location. -** In that case, this routine must seek the cursor to the correct insertion -** point for (pKey,nKey) before doing the insertion. For index btrees, -** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked -** key values and pX->aMem can be used instead of pX->pKey to avoid having -** to decode the key. -*/ -SQLITE_PRIVATE int 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 IndexMoveto() call */ -){ - int rc; - int loc = seekResult; /* -1: before desired location +1: after */ - int szNew = 0; - int idx; - MemPage *pPage; - Btree *p = pCur->pBtree; - unsigned char *oldCell; - unsigned char *newCell = 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. - ** - ** In some cases, the call to btreeMoveto() below is a no-op. For - ** example, when inserting data into a table with auto-generated integer - ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the - ** integer key to use. It then calls this function to actually insert the - ** data into the intkey B-Tree. In this case btreeMoveto() recognizes - ** that the cursor is already where it needs to be and returns without - ** doing any work. To avoid thwarting these optimizations, it is important - ** not to clear the cursor here. - */ - if( pCur->curFlags & BTCF_Multiple ){ - rc = saveAllCursors(p->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_PGNO(pCur->pgnoRoot); - } - } - - /* 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 - && p->pBt->inTransaction==TRANS_WRITE - && (p->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 */ - 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. - */ -#ifdef SQLITE_DEBUG - if( flags & BTREE_SAVEPOSITION ){ - assert( pCur->curFlags & BTCF_ValidNKey ); - assert( pX->nKey==pCur->info.nKey ); - assert( loc==0 ); - } -#endif - - /* On the other hand, BTREE_SAVEPOSITION==0 does not imply - ** that the cursor is not pointing to a row to be overwritten. - ** So do a complete check. - */ - if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ - /* The cursor is pointing to the entry that is to be - ** overwritten */ - assert( pX->nData>=0 && pX->nZero>=0 ); - if( pCur->info.nSize!=0 - && pCur->info.nPayload==(u32)pX->nData+pX->nZero - ){ - /* New entry is the same size as the old. Do an overwrite */ - return btreeOverwriteCell(pCur, pX); - } - assert( loc==0 ); - }else if( loc==0 ){ - /* The cursor is *not* pointing to the cell to be overwritten, nor - ** to an adjacent cell. Move the cursor so that it is pointing either - ** to the cell to be overwritten or an adjacent cell. - */ - rc = sqlite3BtreeTableMoveto(pCur, pX->nKey, - (flags & BTREE_APPEND)!=0, &loc); - if( rc ) return rc; - } - }else{ - /* This is an index or a WITHOUT ROWID table */ - - /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing - ** to a row with the same key as the new entry being inserted. - */ - assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); - - /* If the cursor is not already pointing either to the cell to be - ** overwritten, or if a new cell is being inserted, if the cursor is - ** not pointing to an immediately adjacent cell, then move the cursor - ** so that it does. - */ - if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ - if( pX->nMem ){ - UnpackedRecord r; - r.pKeyInfo = pCur->pKeyInfo; - r.aMem = pX->aMem; - r.nField = pX->nMem; - r.default_rc = 0; - r.eqSeen = 0; - rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc); - }else{ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, - (flags & BTREE_APPEND)!=0, &loc); - } - if( rc ) return rc; - } - - /* If the cursor is currently pointing to an entry to be overwritten - ** and the new content is the same as as the old, then use the - ** overwrite optimization. - */ - if( loc==0 ){ - getCellInfo(pCur); - if( pCur->info.nKey==pX->nKey ){ - BtreePayload x2; - x2.pData = pX->pKey; - x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff ); - x2.nZero = 0; - return btreeOverwriteCell(pCur, &x2); - } - } - } - assert( pCur->eState==CURSOR_VALID - || (pCur->eState==CURSOR_INVALID && loc) || CORRUPT_DB ); - - pPage = pCur->pPage; - assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); - assert( pPage->leaf || !pPage->intKey ); - if( pPage->nFree<0 ){ - if( NEVER(pCur->eState>CURSOR_INVALID) ){ - /* ^^^^^--- due to the moveToRoot() call above */ - rc = SQLITE_CORRUPT_PAGE(pPage); - }else{ - rc = btreeComputeFreeSpace(pPage); - } - if( rc ) return rc; - } - - TRACE(("INSERT: table=%u nkey=%lld ndata=%u page=%u %s\n", - pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, - loc==0 ? "overwrite" : "new entry")); - assert( pPage->isInit || CORRUPT_DB ); - newCell = p->pBt->pTmpSpace; - assert( newCell!=0 ); - assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); - if( flags & BTREE_PREFORMAT ){ - rc = SQLITE_OK; - szNew = p->pBt->nPreformatSize; - if( szNew<4 ){ - szNew = 4; - newCell[3] = 0; - } - if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){ - CellInfo info; - pPage->xParseCell(pPage, newCell, &info); - if( info.nPayload!=info.nLocal ){ - Pgno ovfl = get4byte(&newCell[szNew-4]); - ptrmapPut(p->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc); - if( NEVER(rc) ) goto end_insert; - } - } - }else{ - rc = fillInCell(pPage, newCell, pX, &szNew); - if( rc ) goto end_insert; - } - assert( szNew==pPage->xCellSize(pPage, newCell) ); - assert( szNew <= MX_CELL_SIZE(p->pBt) ); - idx = pCur->ix; - pCur->info.nSize = 0; - if( loc==0 ){ - CellInfo info; - assert( idx>=0 ); - if( idx>=pPage->nCell ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ){ - goto end_insert; - } - oldCell = findCell(pPage, idx); - if( !pPage->leaf ){ - memcpy(newCell, oldCell, 4); - } - BTREE_CLEAR_CELL(rc, pPage, oldCell, info); - testcase( pCur->curFlags & BTCF_ValidOvfl ); - invalidateOverflowCache(pCur); - if( info.nSize==szNew && info.nLocal==info.nPayload - && (!ISAUTOVACUUM(p->pBt) || szNewminLocal) - ){ - /* Overwrite the old cell with the new if they are the same size. - ** We could also try to do this if the old cell is smaller, then add - ** the leftover space to the free list. But experiments show that - ** doing that is no faster then skipping this optimization and just - ** calling dropCell() and insertCell(). - ** - ** This optimization cannot be used on an autovacuum database if the - ** new entry uses overflow pages, as the insertCell() call below is - ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */ - assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ - if( oldCell < pPage->aData+pPage->hdrOffset+10 ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( oldCell+szNew > pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - memcpy(oldCell, newCell, szNew); - return SQLITE_OK; - } - dropCell(pPage, idx, info.nSize, &rc); - if( rc ) goto end_insert; - }else if( loc<0 && pPage->nCell>0 ){ - assert( pPage->leaf ); - idx = ++pCur->ix; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - }else{ - assert( pPage->leaf ); - } - rc = insertCellFast(pPage, idx, newCell, szNew); - assert( pPage->nOverflow==0 || rc==SQLITE_OK ); - assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); - - /* If no error has occurred and pPage has an overflow cell, call balance() - ** to redistribute the cells within the tree. Since balance() may move - ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey - ** variables. - ** - ** Previous versions of SQLite called moveToRoot() to move the cursor - ** back to the root page as balance() used to invalidate the contents - ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that, - ** set the cursor state to "invalid". This makes common insert operations - ** slightly faster. - ** - ** There is a subtle but important optimization here too. When inserting - ** multiple records into an intkey b-tree using a single cursor (as can - ** happen while processing an "INSERT INTO ... SELECT" statement), it - ** is advantageous to leave the cursor pointing to the last entry in - ** the b-tree if possible. If the cursor is left pointing to the last - ** entry in the table, and the next row inserted has an integer key - ** larger than the largest existing key, it is possible to insert the - ** row without seeking the cursor. This can be a big performance boost. - */ - if( pPage->nOverflow ){ - assert( rc==SQLITE_OK ); - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - rc = balance(pCur); - - /* Must make sure nOverflow is reset to zero even if the balance() - ** fails. Internal data structure corruption will result otherwise. - ** Also, set the cursor state to invalid. This stops saveCursorPosition() - ** from trying to save the current position of the cursor. */ - pCur->pPage->nOverflow = 0; - pCur->eState = CURSOR_INVALID; - if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){ - btreeReleaseAllCursorPages(pCur); - if( pCur->pKeyInfo ){ - assert( pCur->pKey==0 ); - pCur->pKey = sqlite3Malloc( pX->nKey ); - if( pCur->pKey==0 ){ - rc = SQLITE_NOMEM; - }else{ - memcpy(pCur->pKey, pX->pKey, pX->nKey); - } - } - pCur->eState = CURSOR_REQUIRESEEK; - pCur->nKey = pX->nKey; - } - } - assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 ); - -end_insert: - return rc; -} - -/* -** 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 sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){ - 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++) = (u8)pSrc->info.nPayload; - }else{ - aOut += 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_PAGE(pSrc->pPage); - } - nRem = pSrc->info.nPayload; - if( nIn==nRem && nInpPage->maxLocal ){ - memcpy(aOut, aIn, nIn); - pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace); - return SQLITE_OK; - }else{ - int rc = SQLITE_OK; - 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 = (int)nOut + (int)(aOut - pBt->pTmpSpace); - if( nOutinfo.nPayload ){ - pPgnoOut = &aOut[nOut]; - pBt->nPreformatSize += 4; - } - - if( nRem>nIn ){ - if( aIn+nIn+4>pSrc->pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pSrc->pPage); - } - 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 ){ - sqlite3PagerUnref(pPageIn); - pPageIn = 0; - rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY); - if( rc==SQLITE_OK ){ - aIn = (const u8*)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(pBt) && 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); - 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 -** the cursor is left pointing at an arbitrary location after the delete. -** But if that bit is set, then the cursor is left in a state such that -** the next call to BtreeNext() or BtreePrev() moves it to the same row -** as it would have been on if the call to BtreeDelete() had been omitted. -** -** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes -** associated with a single table entry and its indexes. Only one of those -** deletes is considered the "primary" delete. The primary delete occurs -** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete -** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. -** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, -** but which might be used by alternative storage engines. -*/ -SQLITE_PRIVATE int 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 */ - u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */ - - assert( cursorOwnsBtShared(pCur) ); - assert( pBt->inTransaction==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( pCur->curFlags & BTCF_WriteFlag ); - 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_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_PGNO(pCur->pgnoRoot); - } - } - assert( pCur->eState==CURSOR_VALID ); - - iCellDepth = pCur->iPage; - iCellIdx = pCur->ix; - pPage = pCur->pPage; - if( pPage->nCell<=iCellIdx ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - pCell = findCell(pPage, iCellIdx); - if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( pCell<&pPage->aCellIdx[pPage->nCell] ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - - /* 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. - ** - ** 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. - ** - ** 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+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. - ** Save the cursor key. */ - rc = saveCursorKey(pCur); - if( rc ) return rc; - }else{ - bPreserve = 2; - } - } - - /* If the page containing the entry to delete is not a leaf page, move - ** the cursor to the largest entry in the tree that is smaller than - ** the entry being deleted. This cell will replace the cell being deleted - ** from the internal node. The 'previous' entry is used for this instead - ** of the 'next' entry, as the previous entry is always a part of the - ** sub-tree headed by the child page of the cell being deleted. This makes - ** balancing the tree following the delete operation easier. */ - if( !pPage->leaf ){ - rc = sqlite3BtreePrevious(pCur, 0); - assert( rc!=SQLITE_DONE ); - if( rc ) return rc; - } - - /* Save the positions of any other cursors open on this table before - ** making any modifications. */ - if( pCur->curFlags & BTCF_Multiple ){ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - } - - /* 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 && p->hasIncrblobCur ){ - invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0); - } - - /* Make the page containing the entry to be deleted writable. Then free any - ** overflow pages associated with the entry and finally remove the cell - ** itself from within the page. */ - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ) return rc; - BTREE_CLEAR_CELL(rc, pPage, pCell, info); - dropCell(pPage, iCellIdx, info.nSize, &rc); - if( rc ) return rc; - - /* If the cell deleted was not located on a leaf page, then the cursor - ** is currently pointing to the largest entry in the sub-tree headed - ** by the child-page of the cell that was just deleted from an internal - ** node. The cell from the leaf node needs to be moved to the internal - ** node to replace the deleted cell. */ - if( !pPage->leaf ){ - MemPage *pLeaf = pCur->pPage; - int nCell; - Pgno n; - unsigned char *pTmp; - - if( pLeaf->nFree<0 ){ - rc = btreeComputeFreeSpace(pLeaf); - if( rc ) return rc; - } - if( iCellDepthiPage-1 ){ - n = pCur->apPage[iCellDepth+1]->pgno; - }else{ - n = pCur->pPage->pgno; - } - pCell = findCell(pLeaf, pLeaf->nCell-1); - if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_PAGE(pLeaf); - nCell = pLeaf->xCellSize(pLeaf, pCell); - assert( MX_CELL_SIZE(pBt) >= nCell ); - pTmp = pBt->pTmpSpace; - assert( pTmp!=0 ); - rc = sqlite3PagerWrite(pLeaf->pDbPage); - if( rc==SQLITE_OK ){ - rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n); - } - dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); - if( rc ) return rc; - } - - /* Balance the tree. If the entry deleted was located on a leaf page, - ** then the cursor still points to that page. In this case the first - ** call to balance() repairs the tree, and the if(...) condition is - ** never true. - ** - ** Otherwise, if the entry deleted was on an internal node page, then - ** pCur is pointing to the leaf page from which a cell was removed to - ** replace the cell deleted from the internal node. This is slightly - ** tricky as the leaf node may be underfull, and the internal node may - ** be either under or overfull. In this case run the balancing algorithm - ** on the leaf node first. If the balance proceeds far enough up the - ** tree that we can be sure that any problem in the internal node has - ** 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. */ - 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--; - while( pCur->iPage>iCellDepth ){ - releasePage(pCur->apPage[pCur->iPage--]); - } - pCur->pPage = pCur->apPage[pCur->iPage]; - rc = balance(pCur); - } - - if( rc==SQLITE_OK ){ - 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; - if( iCellIdx>=pPage->nCell ){ - pCur->skipNext = -1; - pCur->ix = pPage->nCell-1; - }else{ - pCur->skipNext = 1; - } - }else{ - rc = moveToRoot(pCur); - if( bPreserve ){ - btreeReleaseAllCursorPages(pCur); - pCur->eState = CURSOR_REQUIRESEEK; - } - if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; - } - } - return rc; -} - -/* -** Create a new BTree table. Write into *piTable the page -** number for the root page of the new table. -** -** The type of type is determined by the flags parameter. Only the -** following values of flags are currently in use. Other values for -** flags might not work: -** -** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys -** BTREE_ZERODATA Used for SQL indices -*/ -static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ - BtShared *pBt = p->pBt; - MemPage *pRoot; - Pgno pgnoRoot; - int rc; - int ptfFlags; /* Page-type flags for the root page of new table */ - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( pBt->inTransaction==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - -#ifdef SQLITE_OMIT_AUTOVACUUM - rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); - if( rc ){ - return rc; - } -#else - if( pBt->autoVacuum ){ - Pgno pgnoMove; /* Move a page here to make room for the root-page */ - MemPage *pPageMove; /* The page to move to. */ - - /* Creating a new table may probably require moving an existing database - ** to make room for the new tables root page. In case this page turns - ** out to be an overflow page, delete all overflow page-map caches - ** held by open cursors. - */ - invalidateAllOverflowCache(pBt); - - /* Read the value of meta[3] from the database to determine where the - ** root page of the new table should go. meta[3] is the largest root-page - ** created so far, so the new root-page is (meta[3]+1). - */ - sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); - if( pgnoRoot>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(pgnoRoot); - } - pgnoRoot++; - - /* The new root-page may not be allocated on a pointer-map page, or the - ** PENDING_BYTE page. - */ - while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || - pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ - pgnoRoot++; - } - assert( pgnoRoot>=3 ); - - /* Allocate a page. The page that currently resides at pgnoRoot will - ** be moved to the allocated page (unless the allocated page happens - ** to reside at pgnoRoot). - */ - rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT); - if( rc!=SQLITE_OK ){ - return rc; - } - - if( pgnoMove!=pgnoRoot ){ - /* pgnoRoot is the page that will be used for the root-page of - ** the new table (assuming an error did not occur). But we were - ** allocated pgnoMove. If required (i.e. if it was not allocated - ** by extending the file), the current page at position pgnoMove - ** is already journaled. - */ - u8 eType = 0; - Pgno iPtrPage = 0; - - /* Save the positions of any open cursors. This is required in - ** case they are holding a reference to an xFetch reference - ** corresponding to page pgnoRoot. */ - rc = saveAllCursors(pBt, 0, 0); - releasePage(pPageMove); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Move the page currently at pgnoRoot to pgnoMove. */ - rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); - if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ - rc = SQLITE_CORRUPT_PGNO(pgnoRoot); - } - if( rc!=SQLITE_OK ){ - releasePage(pRoot); - return rc; - } - assert( eType!=PTRMAP_ROOTPAGE ); - assert( eType!=PTRMAP_FREEPAGE ); - rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); - releasePage(pRoot); - - /* Obtain the page at pgnoRoot */ - if( rc!=SQLITE_OK ){ - return rc; - } - rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = sqlite3PagerWrite(pRoot->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pRoot); - return rc; - } - }else{ - pRoot = pPageMove; - } - - /* Update the pointer-map and meta-data with the new root-page number. */ - ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); - if( rc ){ - releasePage(pRoot); - return rc; - } - - /* When the new root page was allocated, page 1 was made writable in - ** order either to increase the database filesize, or to decrement the - ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail. - */ - assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) ); - rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); - if( NEVER(rc) ){ - releasePage(pRoot); - return rc; - } - - }else{ - rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); - if( rc ) return rc; - } -#endif - assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - if( createTabFlags & BTREE_INTKEY ){ - ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF; - }else{ - ptfFlags = PTF_ZERODATA | PTF_LEAF; - } - zeroPage(pRoot, ptfFlags); - sqlite3PagerUnref(pRoot->pDbPage); - assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); - *piTable = pgnoRoot; - return SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeCreateTable(p, piTable, flags); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Erase the given database page and all its children. Return -** the page to the freelist. -*/ -static int clearDatabasePage( - BtShared *pBt, /* The BTree that contains the table */ - Pgno pgno, /* Page number to clear */ - int freePageFlag, /* Deallocate page if true */ - i64 *pnChange /* Add number of Cells freed to this counter */ -){ - MemPage *pPage; - int rc; - unsigned char *pCell; - int i; - int hdr; - CellInfo info; - - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(pgno); - } - rc = getAndInitPage(pBt, pgno, &pPage, 0); - if( rc ) return rc; - if( (pBt->openFlags & BTREE_SINGLE)==0 - && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) - ){ - rc = SQLITE_CORRUPT_PAGE(pPage); - goto cleardatabasepage_out; - } - hdr = pPage->hdrOffset; - for(i=0; inCell; i++){ - pCell = findCell(pPage, i); - if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); - if( rc ) goto cleardatabasepage_out; - } - 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; - if( pPage->intKey ) pnChange = 0; - } - if( pnChange ){ - testcase( !pPage->intKey ); - *pnChange += pPage->nCell; - } - if( freePageFlag ){ - freePage(pPage, &rc); - }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ - zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); - } - -cleardatabasepage_out: - releasePage(pPage); - return rc; -} - -/* -** Delete all information from a single table in the database. iTable is -** the page number of the root of the table. After this routine returns, -** the root page is empty, but still exists. -** -** This routine will fail with SQLITE_LOCKED if there are any open -** read cursors on the table. Open write cursors are moved to the -** root of 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 sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){ - int rc; - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - - rc = saveAllCursors(pBt, (Pgno)iTable, 0); - - if( SQLITE_OK==rc ){ - /* 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). */ - if( p->hasIncrblobCur ){ - invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1); - } - rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Delete all information from the single table that pCur is open on. -** -** This routine only work for pCur on an ephemeral table. -*/ -SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){ - return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0); -} - -/* -** Erase all information in a table and add the root of the table to -** the freelist. Except, the root of the principle table (the one on -** page 1) is never added to the freelist. -** -** This routine will fail with SQLITE_LOCKED if there are any open -** cursors on the table. -** -** If AUTOVACUUM is enabled and the page at iTable is not the last -** root page in the database file, then the last root page -** in the database file is moved into the slot formerly occupied by -** iTable and that last slot formerly occupied by the last root page -** is added to the freelist instead of iTable. In this say, all -** root pages are kept at the beginning of the database file, which -** is necessary for AUTOVACUUM to work right. *piMoved is set to the -** page number that used to be the last root page in the file before -** the move. If no page gets moved, *piMoved is set to 0. -** The last root page is recorded in meta[3] and the value of -** meta[3] is updated by this procedure. -*/ -static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ - int rc; - MemPage *pPage = 0; - BtShared *pBt = p->pBt; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( p->inTrans==TRANS_WRITE ); - assert( iTable>=2 ); - if( iTable>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(iTable); - } - - rc = sqlite3BtreeClearTable(p, iTable, 0); - if( rc ) return rc; - rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); - if( NEVER(rc) ){ - releasePage(pPage); - return rc; - } - - *piMoved = 0; - -#ifdef SQLITE_OMIT_AUTOVACUUM - freePage(pPage, &rc); - releasePage(pPage); -#else - if( pBt->autoVacuum ){ - Pgno maxRootPgno; - sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); - - if( iTable==maxRootPgno ){ - /* If the table being dropped is the table with the largest root-page - ** number in the database, put the root page on the free list. - */ - freePage(pPage, &rc); - releasePage(pPage); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - /* The table being dropped does not have the largest root-page - ** number in the database. So move the page that does into the - ** gap left by the deleted root-page. - */ - MemPage *pMove; - releasePage(pPage); - rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); - releasePage(pMove); - if( rc!=SQLITE_OK ){ - return rc; - } - pMove = 0; - rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); - freePage(pMove, &rc); - releasePage(pMove); - if( rc!=SQLITE_OK ){ - return rc; - } - *piMoved = maxRootPgno; - } - - /* Set the new 'max-root-page' value in the database header. This - ** is the old value less one, less one more if that happens to - ** be a root-page number, less one again if that is the - ** PENDING_BYTE_PAGE. - */ - maxRootPgno--; - while( maxRootPgno==PENDING_BYTE_PAGE(pBt) - || PTRMAP_ISPAGE(pBt, maxRootPgno) ){ - maxRootPgno--; - } - assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); - - rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); - }else{ - freePage(pPage, &rc); - releasePage(pPage); - } -#endif - return rc; -} -SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeDropTable(p, iTable, piMoved); - sqlite3BtreeLeave(p); - return rc; -} - - -/* -** This function may only be called if the b-tree connection already -** has a read or write transaction open on the database. -** -** Read the meta-information out of a database file. Meta[0] -** is the number of free pages currently in the database. Meta[1] -** through meta[15] are available for use by higher layers. Meta[0] -** is read-only, the others are read/write. -** -** The schema layer numbers meta values differently. At the schema -** layer (and the SetCookie and ReadCookie opcodes) the number of -** free pages is not visible. So Cookie[0] is the same as Meta[1]. -** -** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead -** of reading the value out of the header, it instead loads the "DataVersion" -** from the pager. The BTREE_DATA_VERSION value is not actually stored in the -** database file. It is a number computed by the pager. But its access -** pattern is the same as header meta values, and so it is convenient to -** read it from this routine. -*/ -SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ - BtShared *pBt = p->pBt; - - sqlite3BtreeEnter(p); - assert( p->inTrans>TRANS_NONE ); - assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) ); - assert( pBt->pPage1 ); - assert( idx>=0 && idx<=15 ); - - if( idx==BTREE_DATA_VERSION ){ - *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion; - }else{ - *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); - } - - /* If auto-vacuum is disabled in this build and this is an auto-vacuum - ** database, mark the database as read-only. */ -#ifdef SQLITE_OMIT_AUTOVACUUM - if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } -#endif - - sqlite3BtreeLeave(p); -} - -/* -** Write meta-information back into the database. Meta[0] is -** read-only and may not be written. -*/ -SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ - BtShared *pBt = p->pBt; - unsigned char *pP1; - int rc; - assert( idx>=1 && idx<=15 ); - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - assert( pBt->pPage1!=0 ); - pP1 = pBt->pPage1->aData; - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pP1[36 + idx*4], iMeta); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( idx==BTREE_INCR_VACUUM ){ - assert( pBt->autoVacuum || iMeta==0 ); - assert( iMeta==0 || iMeta==1 ); - pBt->incrVacuum = (u8)iMeta; - } -#endif - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** The first argument, pCur, is a cursor opened on some b-tree. Count the -** number of entries in the b-tree and write the result to *pnEntry. -** -** SQLITE_OK is returned if the operation is successfully executed. -** Otherwise, if an error is encountered (i.e. an IO error or database -** corruption) an SQLite error code is returned. -*/ -SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){ - i64 nEntry = 0; /* Value to return in *pnEntry */ - int rc; /* Return code */ - - rc = moveToRoot(pCur); - if( rc==SQLITE_EMPTY ){ - *pnEntry = 0; - return SQLITE_OK; - } - - /* Unless an error occurs, the following loop runs one iteration for each - ** page in the B-Tree structure (not including overflow pages). - */ - while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){ - int iIdx; /* Index of child node in parent */ - MemPage *pPage; /* Current page of the b-tree */ - - /* If this is a leaf page or the tree is not an int-key tree, then - ** this page contains countable entries. Increment the entry counter - ** accordingly. - */ - pPage = pCur->pPage; - if( pPage->leaf || !pPage->intKey ){ - nEntry += pPage->nCell; - } - - /* pPage is a leaf node. This loop navigates the cursor so that it - ** points to the first interior cell that it points to the parent of - ** the next page in the tree that has not yet been visited. The - ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell - ** of the page, or to the number of cells in the page if the next page - ** to visit is the right-child of its parent. - ** - ** If all pages in the tree have been visited, return SQLITE_OK to the - ** caller. - */ - if( pPage->leaf ){ - do { - if( pCur->iPage==0 ){ - /* All pages of the b-tree have been visited. Return successfully. */ - *pnEntry = nEntry; - return moveToRoot(pCur); - } - moveToParent(pCur); - }while ( pCur->ix>=pCur->pPage->nCell ); - - pCur->ix++; - pPage = pCur->pPage; - } - - /* Descend to the child node of the cell that the cursor currently - ** points at. This is the right-child if (iIdx==pPage->nCell). - */ - iIdx = pCur->ix; - if( iIdx==pPage->nCell ){ - rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); - }else{ - rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx))); - } - } - - /* An error has occurred. Return an error code. */ - return rc; -} - -/* -** Return the pager associated with a BTree. This routine is used for -** testing and debugging only. -*/ -SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ - return p->pBt->pPager; -} - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** Record an OOM error during integrity_check -*/ -static void checkOom(IntegrityCk *pCheck){ - pCheck->rc = SQLITE_NOMEM; - pCheck->mxErr = 0; /* Causes integrity_check processing to stop */ - if( pCheck->nErr==0 ) pCheck->nErr++; -} - -/* -** Invoke the progress handler, if appropriate. Also check for an -** interrupt. -*/ -static void checkProgress(IntegrityCk *pCheck){ - sqlite3 *db = pCheck->db; - if( AtomicLoad(&db->u1.isInterrupted) ){ - pCheck->rc = SQLITE_INTERRUPT; - pCheck->nErr++; - pCheck->mxErr = 0; - } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - assert( db->nProgressOps>0 ); - pCheck->nStep++; - if( (pCheck->nStep % db->nProgressOps)==0 - && db->xProgress(db->pProgressArg) - ){ - pCheck->rc = SQLITE_INTERRUPT; - pCheck->nErr++; - pCheck->mxErr = 0; - } - } -#endif -} - -/* -** Append a message to the error message string. -*/ -static void checkAppendMsg( - IntegrityCk *pCheck, - const char *zFormat, - ... -){ - va_list ap; - checkProgress(pCheck); - if( !pCheck->mxErr ) return; - pCheck->mxErr--; - pCheck->nErr++; - va_start(ap, zFormat); - if( pCheck->errMsg.nChar ){ - sqlite3_str_append(&pCheck->errMsg, "\n", 1); - } - if( pCheck->zPfx ){ - sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, - pCheck->v0, pCheck->v1, pCheck->v2); - } - sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); - va_end(ap); - if( pCheck->errMsg.accError==SQLITE_NOMEM ){ - checkOom(pCheck); - } -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK - -/* -** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that -** corresponds to page iPg is already set. -*/ -static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); - assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); - return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); -} - -/* -** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. -*/ -static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); - assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); - pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); -} - - -/* -** Add 1 to the reference count for page iPage. If this is the second -** reference to the page, add an error message to pCheck->zErrMsg. -** Return 1 if there are 2 or more references to the page and 0 if -** if this is the first reference to the page. -** -** Also check that the page number is in bounds. -*/ -static int checkRef(IntegrityCk *pCheck, Pgno iPage){ - if( iPage>pCheck->nCkPage || iPage==0 ){ - checkAppendMsg(pCheck, "invalid page number %u", iPage); - return 1; - } - if( getPageReferenced(pCheck, iPage) ){ - checkAppendMsg(pCheck, "2nd reference to page %u", iPage); - return 1; - } - setPageReferenced(pCheck, iPage); - return 0; -} - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Check that the entry in the pointer-map for page iChild maps to -** page iParent, pointer type ptrType. If not, append an error message -** to pCheck. -*/ -static void checkPtrmap( - IntegrityCk *pCheck, /* Integrity check context */ - Pgno iChild, /* Child page number */ - u8 eType, /* Expected pointer map type */ - Pgno iParent /* Expected pointer map parent page number */ -){ - int rc; - u8 ePtrmapType; - Pgno iPtrmapParent; - - rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck); - checkAppendMsg(pCheck, "Failed to read ptrmap key=%u", iChild); - return; - } - - if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ - checkAppendMsg(pCheck, - "Bad ptr map entry key=%u expected=(%u,%u) got=(%u,%u)", - iChild, eType, iParent, ePtrmapType, iPtrmapParent); - } -} -#endif - -/* -** Check the integrity of the freelist or of an overflow page list. -** Verify that the number of pages on the list is N. -*/ -static void checkList( - IntegrityCk *pCheck, /* Integrity checking context */ - int isFreeList, /* True for a freelist. False for overflow page list */ - Pgno iPage, /* Page number for first page in the list */ - u32 N /* Expected number of pages in the list */ -){ - int i; - u32 expected = N; - int nErrAtStart = pCheck->nErr; - while( iPage!=0 && pCheck->mxErr ){ - DbPage *pOvflPage; - unsigned char *pOvflData; - if( checkRef(pCheck, iPage) ) break; - N--; - if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ - checkAppendMsg(pCheck, "failed to get page %u", iPage); - break; - } - pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); - if( isFreeList ){ - u32 n = (u32)get4byte(&pOvflData[4]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pCheck->pBt->autoVacuum ){ - checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0); - } -#endif - if( n>pCheck->pBt->usableSize/4-2 ){ - checkAppendMsg(pCheck, - "freelist leaf count too big on page %u", iPage); - N--; - }else{ - for(i=0; i<(int)n; i++){ - Pgno iFreePage = get4byte(&pOvflData[8+i*4]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pCheck->pBt->autoVacuum ){ - checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0); - } -#endif - checkRef(pCheck, iFreePage); - } - N -= n; - } - } -#ifndef SQLITE_OMIT_AUTOVACUUM - else{ - /* If this database supports auto-vacuum and iPage is not the last - ** page in this overflow list, check that the pointer-map entry for - ** the following page matches iPage. - */ - if( pCheck->pBt->autoVacuum && N>0 ){ - i = get4byte(pOvflData); - checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage); - } - } -#endif - iPage = get4byte(pOvflData); - sqlite3PagerUnref(pOvflPage); - } - if( N && nErrAtStart==pCheck->nErr ){ - checkAppendMsg(pCheck, - "%s is %u but should be %u", - isFreeList ? "size" : "overflow list length", - expected-N, expected); - } -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -/* -** An implementation of a min-heap. -** -** aHeap[0] is the number of elements on the heap. aHeap[1] is the -** root element. The daughter nodes of aHeap[N] are aHeap[N*2] -** and aHeap[N*2+1]. -** -** The heap property is this: Every node is less than or equal to both -** of its daughter nodes. A consequence of the heap property is that the -** root node aHeap[1] is always the minimum value currently in the heap. -** -** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto -** the heap, preserving the heap property. The btreeHeapPull() routine -** removes the root element from the heap (the minimum value in the heap) -** and then moves other nodes around as necessary to preserve the heap -** property. -** -** This heap is used for cell overlap and coverage testing. Each u32 -** entry represents the span of a cell or freeblock on a btree page. -** The upper 16 bits are the index of the first byte of a range and the -** lower 16 bits are the index of the last byte of that range. -*/ -static void btreeHeapInsert(u32 *aHeap, u32 x){ - u32 j, i; - assert( aHeap!=0 ); - i = ++aHeap[0]; - aHeap[i] = x; - while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ - x = aHeap[j]; - aHeap[j] = aHeap[i]; - aHeap[i] = x; - i = j; - } -} -static int btreeHeapPull(u32 *aHeap, u32 *pOut){ - u32 j, i, x; - if( (x = aHeap[0])==0 ) return 0; - *pOut = aHeap[1]; - aHeap[1] = aHeap[x]; - aHeap[x] = 0xffffffff; - aHeap[0]--; - i = 1; - while( (j = i*2)<=aHeap[0] ){ - if( aHeap[j]>aHeap[j+1] ) j++; - if( aHeap[i]zPfx; - int saved_v1 = pCheck->v1; - int saved_v2 = pCheck->v2; - u8 savedIsInit = 0; - - /* Check that the page exists - */ - checkProgress(pCheck); - if( pCheck->mxErr==0 ) goto end_of_check; - pBt = pCheck->pBt; - usableSize = pBt->usableSize; - if( iPage==0 ) return 0; - if( checkRef(pCheck, iPage) ) return 0; - pCheck->zPfx = "Tree %u page %u: "; - pCheck->v1 = iPage; - if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ - checkAppendMsg(pCheck, - "unable to get the page. error code=%d", rc); - if( rc==SQLITE_IOERR_NOMEM ) pCheck->rc = SQLITE_NOMEM; - goto end_of_check; - } - - /* Clear MemPage.isInit to make sure the corruption detection code in - ** btreeInitPage() is executed. */ - savedIsInit = pPage->isInit; - pPage->isInit = 0; - if( (rc = btreeInitPage(pPage))!=0 ){ - assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ - checkAppendMsg(pCheck, - "btreeInitPage() returns error code %d", rc); - goto end_of_check; - } - if( (rc = btreeComputeFreeSpace(pPage))!=0 ){ - assert( rc==SQLITE_CORRUPT ); - checkAppendMsg(pCheck, "free space corruption", rc); - goto end_of_check; - } - data = pPage->aData; - hdr = pPage->hdrOffset; - - /* Set up for cell analysis */ - pCheck->zPfx = "Tree %u page %u cell %u: "; - contentOffset = get2byteNotZero(&data[hdr+5]); - assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ - - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ - nCell = get2byte(&data[hdr+3]); - assert( pPage->nCell==nCell ); - if( pPage->leaf || pPage->intKey==0 ){ - pCheck->nRow += nCell; - } - - /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page - ** immediately follows the b-tree page header. */ - cellStart = hdr + 12 - 4*pPage->leaf; - assert( pPage->aCellIdx==&data[cellStart] ); - pCellIdx = &data[cellStart + 2*(nCell-1)]; - - if( !pPage->leaf ){ - /* Analyze the right-child page of internal pages */ - pgno = get4byte(&data[hdr+8]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - pCheck->zPfx = "Tree %u page %u right child: "; - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); - } -#endif - depth = checkTreePage(pCheck, pgno, &maxKey, maxKey); - keyCanBeEqual = 0; - }else{ - /* For leaf pages, the coverage check will occur in the same loop - ** as the other cell checks, so initialize the heap. */ - heap = pCheck->heap; - heap[0] = 0; - } - - /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte - ** integer offsets to the cell contents. */ - for(i=nCell-1; i>=0 && pCheck->mxErr; i--){ - CellInfo info; - - /* Check cell size */ - pCheck->v2 = i; - assert( pCellIdx==&data[cellStart + i*2] ); - pc = get2byteAligned(pCellIdx); - pCellIdx -= 2; - if( pcusableSize-4 ){ - checkAppendMsg(pCheck, "Offset %u out of range %u..%u", - pc, contentOffset, usableSize-4); - doCoverageCheck = 0; - continue; - } - pCell = &data[pc]; - pPage->xParseCell(pPage, pCell, &info); - if( pc+info.nSize>usableSize ){ - checkAppendMsg(pCheck, "Extends off end of page"); - doCoverageCheck = 0; - continue; - } - - /* Check for integer primary key out of range */ - if( pPage->intKey ){ - if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){ - checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey); - } - maxKey = info.nKey; - keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */ - } - - /* Check the content overflow list */ - if( info.nPayload>info.nLocal ){ - u32 nPage; /* Number of pages on the overflow chain */ - Pgno pgnoOvfl; /* First page of the overflow chain */ - assert( pc + info.nSize - 4 <= usableSize ); - nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); - pgnoOvfl = get4byte(&pCell[info.nSize - 4]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage); - } -#endif - checkList(pCheck, 0, pgnoOvfl, nPage); - } - - if( !pPage->leaf ){ - /* Check sanity of left child page for internal pages */ - pgno = get4byte(pCell); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); - } -#endif - d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey); - keyCanBeEqual = 0; - if( d2!=depth ){ - checkAppendMsg(pCheck, "Child page depth differs"); - depth = d2; - } - }else{ - /* Populate the coverage-checking heap for leaf pages */ - btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1)); - } - } - *piMinKey = maxKey; - - /* Check for complete coverage of the page - */ - pCheck->zPfx = 0; - if( doCoverageCheck && pCheck->mxErr>0 ){ - /* For leaf pages, the min-heap has already been initialized and the - ** cells have already been inserted. But for internal pages, that has - ** not yet been done, so do it now */ - if( !pPage->leaf ){ - heap = pCheck->heap; - heap[0] = 0; - for(i=nCell-1; i>=0; i--){ - u32 size; - pc = get2byteAligned(&data[cellStart+i*2]); - size = pPage->xCellSize(pPage, &data[pc]); - btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); - } - } - assert( heap!=0 ); - /* Add the freeblocks to the min-heap - ** - ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header - ** is the offset of the first freeblock, or zero if there are no - ** freeblocks on the page. - */ - i = get2byte(&data[hdr+1]); - while( i>0 ){ - int size, j; - assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ - size = get2byte(&data[i+2]); - assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */ - btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); - /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a - ** big-endian integer which is the offset in the b-tree page of the next - ** freeblock in the chain, or zero if the freeblock is the last on the - ** chain. */ - j = get2byte(&data[i]); - /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of - ** increasing offset. */ - assert( j==0 || j>i+size ); /* Enforced by btreeComputeFreeSpace() */ - assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ - i = j; - } - /* Analyze the min-heap looking for overlap between cells and/or - ** freeblocks, and counting the number of untracked bytes in nFrag. - ** - ** Each min-heap entry is of the form: (start_address<<16)|end_address. - ** There is an implied first entry the covers the page header, the cell - ** pointer index, and the gap between the cell pointer index and the start - ** of cell content. - ** - ** The loop below pulls entries from the min-heap in order and compares - ** the start_address against the previous end_address. If there is an - ** overlap, that means bytes are used multiple times. If there is a gap, - ** that gap is added to the fragmentation count. - */ - nFrag = 0; - prev = contentOffset - 1; /* Implied first min-heap entry */ - while( btreeHeapPull(heap,&x) ){ - if( (prev&0xffff)>=(x>>16) ){ - checkAppendMsg(pCheck, - "Multiple uses for byte %u of page %u", x>>16, iPage); - break; - }else{ - nFrag += (x>>16) - (prev&0xffff) - 1; - prev = x; - } - } - nFrag += usableSize - (prev&0xffff) - 1; - /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments - ** is stored in the fifth field of the b-tree page header. - ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the - ** number of fragmented free bytes within the cell content area. - */ - if( heap[0]==0 && nFrag!=data[hdr+7] ){ - checkAppendMsg(pCheck, - "Fragmentation of %u bytes reported as %u on page %u", - nFrag, data[hdr+7], iPage); - } - } - -end_of_check: - if( !doCoverageCheck ) pPage->isInit = savedIsInit; - releasePage(pPage); - pCheck->zPfx = saved_zPfx; - pCheck->v1 = saved_v1; - pCheck->v2 = saved_v2; - return depth+1; -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** This routine does a complete check of the given BTree file. aRoot[] is -** an array of pages numbers were each page number is the root page of -** a table. nRoot is the number of entries in aRoot. -** -** A read-only or read-write transaction must be opened before calling -** this function. -** -** Write the number of error seen in *pnErr. Except for some memory -** allocation errors, an error message held in memory obtained from -** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is -** returned. If a memory allocation error occurs, NULL is returned. -** -** If the first entry in aRoot[] is 0, that indicates that the list of -** root pages is incomplete. This is a "partial integrity-check". This -** happens when performing an integrity check on a single table. The -** zero is skipped, of course. But in addition, the freelist checks -** and the checks to make sure every page is referenced are also skipped, -** since obviously it is not possible to know which pages are covered by -** the unverified btrees. Except, if aRoot[1] is 1, then the freelist -** checks are still performed. -*/ -SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( - sqlite3 *db, /* Database connection that is running the check */ - Btree *p, /* The btree to be checked */ - Pgno *aRoot, /* An array of root pages numbers for individual trees */ - Mem *aCnt, /* Memory cells to write counts for each tree to */ - int nRoot, /* Number of entries in aRoot[] */ - int mxErr, /* Stop reporting errors after this many */ - int *pnErr, /* OUT: Write number of errors seen to this variable */ - char **pzOut /* OUT: Write the error message string here */ -){ - Pgno i; - IntegrityCk sCheck; - BtShared *pBt = p->pBt; - u64 savedDbFlags = pBt->db->flags; - char zErr[100]; - int bPartial = 0; /* True if not checking all btrees */ - int bCkFreelist = 1; /* True to scan the freelist */ - VVA_ONLY( int nRef ); - - assert( nRoot>0 ); - assert( aCnt!=0 ); - - /* aRoot[0]==0 means this is a partial check */ - if( aRoot[0]==0 ){ - assert( nRoot>1 ); - bPartial = 1; - if( aRoot[1]!=1 ) bCkFreelist = 0; - } - - sqlite3BtreeEnter(p); - assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); - VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); - assert( nRef>=0 ); - memset(&sCheck, 0, sizeof(sCheck)); - sCheck.db = db; - sCheck.pBt = pBt; - sCheck.pPager = pBt->pPager; - sCheck.nCkPage = btreePagecount(sCheck.pBt); - sCheck.mxErr = mxErr; - sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); - sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; - if( sCheck.nCkPage==0 ){ - goto integrity_ck_cleanup; - } - - sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); - if( !sCheck.aPgRef ){ - checkOom(&sCheck); - goto integrity_ck_cleanup; - } - sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); - if( sCheck.heap==0 ){ - checkOom(&sCheck); - goto integrity_ck_cleanup; - } - - i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nCkPage ) setPageReferenced(&sCheck, i); - - /* Check the integrity of the freelist - */ - if( bCkFreelist ){ - sCheck.zPfx = "Freelist: "; - checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), - get4byte(&pBt->pPage1->aData[36])); - sCheck.zPfx = 0; - } - - /* Check all the tables. - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( !bPartial ){ - if( pBt->autoVacuum ){ - Pgno mx = 0; - Pgno mxInHdr; - for(i=0; (int)ipPage1->aData[52]); - if( mx!=mxInHdr ){ - checkAppendMsg(&sCheck, - "max rootpage (%u) disagrees with header (%u)", - mx, mxInHdr - ); - } - }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){ - checkAppendMsg(&sCheck, - "incremental_vacuum enabled with a max rootpage of zero" - ); - } - } -#endif - testcase( pBt->db->flags & SQLITE_CellSizeCk ); - pBt->db->flags &= ~(u64)SQLITE_CellSizeCk; - for(i=0; (int)iautoVacuum && aRoot[i]>1 && !bPartial ){ - checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); - } -#endif - sCheck.v0 = aRoot[i]; - checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); - } - sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow); - } - pBt->db->flags = savedDbFlags; - - /* Make sure every page in the file is referenced - */ - if( !bPartial ){ - for(i=1; i<=sCheck.nCkPage && sCheck.mxErr; i++){ -#ifdef SQLITE_OMIT_AUTOVACUUM - if( getPageReferenced(&sCheck, i)==0 ){ - checkAppendMsg(&sCheck, "Page %u: never used", i); - } -#else - /* If the database supports auto-vacuum, make sure no tables contain - ** references to pointer-map pages. - */ - if( getPageReferenced(&sCheck, i)==0 && - (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %u: never used", i); - } - if( getPageReferenced(&sCheck, i)!=0 && - (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %u: pointer map referenced", i); - } -#endif - } - } - - /* Clean up and report errors. - */ -integrity_ck_cleanup: - sqlite3PageFree(sCheck.heap); - sqlite3_free(sCheck.aPgRef); - *pnErr = sCheck.nErr; - if( sCheck.nErr==0 ){ - sqlite3_str_reset(&sCheck.errMsg); - *pzOut = 0; - }else{ - *pzOut = sqlite3StrAccumFinish(&sCheck.errMsg); - } - /* Make sure this analysis did not leave any unref() pages. */ - assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); - sqlite3BtreeLeave(p); - return sCheck.rc; -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -/* -** Return the full pathname of the underlying database file. Return -** an empty string if the database is in-memory or a TEMP database. -** -** The pager filename is invariant as long as the pager is -** open so it is safe to access without the BtShared mutex. -*/ -SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){ - assert( p->pBt->pPager!=0 ); - return sqlite3PagerFilename(p->pBt->pPager, 1); -} - -/* -** Return the pathname of the journal file for this database. The return -** value of this routine is the same regardless of whether the journal file -** has been created or not. -** -** The pager journal filename is invariant as long as the pager is -** open so it is safe to access without the BtShared mutex. -*/ -SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){ - assert( p->pBt->pPager!=0 ); - return sqlite3PagerJournalname(p->pBt->pPager); -} - -/* -** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE -** to describe the current transaction state of Btree p. -*/ -SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree *p){ - assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); - return p ? p->inTrans : 0; -} - -#ifndef SQLITE_OMIT_WAL -/* -** Run a checkpoint on the Btree passed as the first argument. -** -** Return SQLITE_LOCKED if this or any other connection has an open -** transaction on the shared-cache the argument Btree is connected to. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. -*/ -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){ - int rc = SQLITE_OK; - if( p ){ - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - if( pBt->inTransaction!=TRANS_NONE ){ - rc = SQLITE_LOCKED; - }else{ - rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); - } - sqlite3BtreeLeave(p); - } - return rc; -} -#endif - -/* -** Return true if there is currently a backup running on Btree p. -*/ -SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){ - assert( p ); - assert( sqlite3_mutex_held(p->db->mutex) ); - return p->nBackup!=0; -} - -/* -** This function returns a pointer to a blob of memory associated with -** a single shared-btree. The memory is used by client code for its own -** purposes (for example, to store a high-level schema associated with -** the shared-btree). The btree layer manages reference counting issues. -** -** The first time this is called on a shared-btree, nBytes bytes of memory -** are allocated, zeroed, and returned to the caller. For each subsequent -** call the nBytes parameter is ignored and a pointer to the same blob -** of memory returned. -** -** If the nBytes parameter is 0 and the blob of memory has not yet been -** allocated, a null pointer is returned. If the blob has already been -** allocated, it is returned as normal. -** -** Just before the shared-btree is closed, the function passed as the -** xFree argument when the memory allocation was made is invoked on the -** blob of allocated memory. The xFree function should not call sqlite3_free() -** on the memory, the btree layer does that. -*/ -SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ - BtShared *pBt = p->pBt; - assert( nBytes==0 || nBytes==sizeof(Schema) ); - sqlite3BtreeEnter(p); - if( !pBt->pSchema && nBytes ){ - pBt->pSchema = sqlite3DbMallocZero(0, nBytes); - pBt->xFreeSchema = xFree; - } - sqlite3BtreeLeave(p); - return pBt->pSchema; -} - -/* -** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared -** btree as the argument handle holds an exclusive lock on the -** sqlite_schema table. Otherwise SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ - int rc; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); - assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); - sqlite3BtreeLeave(p); - return rc; -} - - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Obtain a lock on the table whose root page is iTab. The -** lock is a write lock if isWritelock is true or a read lock -** if it is false. -*/ -SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ - int rc = SQLITE_OK; - assert( p->inTrans!=TRANS_NONE ); - if( p->sharable ){ - u8 lockType = READ_LOCK + isWriteLock; - assert( READ_LOCK+1==WRITE_LOCK ); - assert( isWriteLock==0 || isWriteLock==1 ); - - sqlite3BtreeEnter(p); - rc = querySharedCacheTableLock(p, iTab, lockType); - if( rc==SQLITE_OK ){ - rc = setSharedCacheTableLock(p, iTab, lockType); - } - sqlite3BtreeLeave(p); - } - return rc; -} -#endif - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** Argument pCsr must be a cursor opened for writing on an -** INTKEY table currently pointing at a valid table entry. -** This function modifies the data stored as part of that entry. -** -** Only the data content may only be modified, it is not possible to -** change the length of the data stored. If this function is called with -** parameters that attempt to write past the end of the existing data, -** no modifications are made and SQLITE_CORRUPT is returned. -*/ -SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ - int rc; - assert( cursorOwnsBtShared(pCsr) ); - assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); - assert( pCsr->curFlags & BTCF_Incrblob ); - - rc = restoreCursorPosition(pCsr); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pCsr->eState!=CURSOR_REQUIRESEEK ); - if( pCsr->eState!=CURSOR_VALID ){ - return SQLITE_ABORT; - } - - /* Save the positions of all other cursors open on this table. This is - ** required in case any of them are holding references to an xFetch - ** version of the b-tree page modified by the accessPayload call below. - ** - ** Note that pCsr must be open on a INTKEY table and saveCursorPosition() - ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence - ** saveAllCursors can only return SQLITE_OK. - */ - VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr); - assert( rc==SQLITE_OK ); - - /* Check some assumptions: - ** (a) the cursor is open for writing, - ** (b) there is a read/write transaction open, - ** (c) the connection holds a write-lock on the table (if required), - ** (d) there are no conflicting read-locks, and - ** (e) the cursor points at a valid row of an intKey table. - */ - if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){ - return SQLITE_READONLY; - } - assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 - && pCsr->pBt->inTransaction==TRANS_WRITE ); - assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); - assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); - assert( pCsr->pPage->intKey ); - - return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); -} - -/* -** Mark this cursor as an incremental blob cursor. -*/ -SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ - pCur->curFlags |= BTCF_Incrblob; - pCur->pBtree->hasIncrblobCur = 1; -} -#endif - -/* -** Set both the "read version" (single byte at byte offset 18) and -** "write version" (single byte at byte offset 19) fields in the database -** header to iVersion. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ - BtShared *pBt = pBtree->pBt; - int rc; /* Return code */ - - assert( iVersion==1 || iVersion==2 ); - - /* If setting the version fields to 1, do not automatically open the - ** WAL connection, even if the version fields are currently set to 2. - */ - pBt->btsFlags &= ~BTS_NO_WAL; - if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; - - rc = sqlite3BtreeBeginTrans(pBtree, 0, 0); - if( rc==SQLITE_OK ){ - u8 *aData = pBt->pPage1->aData; - if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ - rc = sqlite3BtreeBeginTrans(pBtree, 2, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc==SQLITE_OK ){ - aData[18] = (u8)iVersion; - aData[19] = (u8)iVersion; - } - } - } - } - - pBt->btsFlags &= ~BTS_NO_WAL; - return rc; -} - -/* -** Return true if the cursor has a hint specified. This routine is -** only used from within assert() statements -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ - return (pCsr->hints & mask)!=0; -} - -/* -** Return true if the given Btree is read-only. -*/ -SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){ - return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; -} - -/* -** Return the size of the header added to each page by this module. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } - -/* -** If no transaction is active and the database is not a temp-db, clear -** the in-memory pager cache. -*/ -SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree *p){ - BtShared *pBt = p->pBt; - if( pBt->inTransaction==TRANS_NONE ){ - sqlite3PagerClearCache(pBt->pPager); - } -} - -#if !defined(SQLITE_OMIT_SHARED_CACHE) -/* -** Return true if the Btree passed as the only argument is sharable. -*/ -SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){ - return p->sharable; -} - -/* -** Return the number of connections to the BtShared object accessed by -** the Btree handle passed as the only argument. For private caches -** this is always 1. For shared caches it may be 1 or greater. -*/ -SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){ - testcase( p->sharable ); - return p->pBt->nRef; -} -#endif - -/************** End of btree.c ***********************************************/ -/************** Begin file backup.c ******************************************/ -/* -** 2009 January 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the implementation of the sqlite3_backup_XXX() -** API functions and the related features. -*/ -/* #include "sqliteInt.h" */ -/* #include "btreeInt.h" */ - -/* -** Structure allocated for each backup operation. -*/ -struct sqlite3_backup { - sqlite3* pDestDb; /* Destination database handle */ - Btree *pDest; /* Destination b-tree file */ - u32 iDestSchema; /* Original schema cookie in destination */ - int bDestLocked; /* True once a write-transaction is open on pDest */ - - Pgno iNext; /* Page number of the next source page to copy */ - sqlite3* pSrcDb; /* Source database handle */ - Btree *pSrc; /* Source b-tree file */ - - int rc; /* Backup process error code */ - - /* These two variables are set by every call to backup_step(). They are - ** read by calls to backup_remaining() and backup_pagecount(). - */ - Pgno nRemaining; /* Number of pages left to copy */ - Pgno nPagecount; /* Total number of pages to copy */ - - int isAttached; /* True once backup has been registered with pager */ - sqlite3_backup *pNext; /* Next backup associated with source pager */ -}; - -/* -** THREAD SAFETY NOTES: -** -** Once it has been created using backup_init(), a single sqlite3_backup -** structure may be accessed via two groups of thread-safe entry points: -** -** * Via the sqlite3_backup_XXX() API function backup_step() and -** backup_finish(). Both these functions obtain the source database -** handle mutex and the mutex associated with the source BtShared -** structure, in that order. -** -** * Via the BackupUpdate() and BackupRestart() functions, which are -** invoked by the pager layer to report various state changes in -** the page cache associated with the source database. The mutex -** associated with the source database BtShared structure will always -** be held when either of these functions are invoked. -** -** The other sqlite3_backup_XXX() API functions, backup_remaining() and -** backup_pagecount() are not thread-safe functions. If they are called -** while some other thread is calling backup_step() or backup_finish(), -** the values returned may be invalid. There is no way for a call to -** BackupUpdate() or BackupRestart() to interfere with backup_remaining() -** or backup_pagecount(). -** -** Depending on the SQLite configuration, the database handles and/or -** the Btree objects may have their own mutexes that require locking. -** Non-sharable Btrees (in-memory databases for example), do not have -** associated mutexes. -*/ - -/* -** Return a pointer corresponding to database zDb (i.e. "main", "temp") -** in connection handle pDb. If such a database cannot be found, return -** a NULL pointer and write an error message to pErrorDb. -** -** If the "temp" database is requested, it may need to be opened by this -** function. If an error occurs while doing so, return 0 and write an -** error message to pErrorDb. -*/ -static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ - int i = sqlite3FindDbName(pDb, zDb); - - if( i==1 ){ - Parse sParse; - int rc = 0; - sqlite3ParseObjectInit(&sParse,pDb); - if( sqlite3OpenTempDatabase(&sParse) ){ - sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); - rc = SQLITE_ERROR; - } - sqlite3DbFree(pErrorDb, sParse.zErrMsg); - sqlite3ParseObjectReset(&sParse); - if( rc ){ - return 0; - } - } - - if( i<0 ){ - sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); - return 0; - } - - return pDb->aDb[i].pBt; -} - -/* -** Attempt to set the page size of the destination to match the page size -** of the source. -*/ -static int setDestPgsz(sqlite3_backup *p){ - int rc; - rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0); - return rc; -} - -/* -** Check that there is no open read-transaction on the b-tree passed as the -** second argument. If there is not, return SQLITE_OK. Otherwise, if there -** is an open read-transaction, return SQLITE_ERROR and leave an error -** message in database handle db. -*/ -static int checkReadTransaction(sqlite3 *db, Btree *p){ - if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); - return SQLITE_ERROR; - } - return SQLITE_OK; -} - -/* -** Create an sqlite3_backup process to copy the contents of zSrcDb from -** connection handle pSrcDb to zDestDb in pDestDb. If successful, return -** a pointer to the new sqlite3_backup object. -** -** If an error occurs, NULL is returned and an error code and error message -** stored in database handle pDestDb. -*/ -SQLITE_API sqlite3_backup *sqlite3_backup_init( - sqlite3* pDestDb, /* Database to write to */ - const char *zDestDb, /* Name of database within pDestDb */ - sqlite3* pSrcDb, /* Database connection to read from */ - const char *zSrcDb /* Name of database within pSrcDb */ -){ - sqlite3_backup *p; /* Value to return */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - { - extern int sqlcipher_find_db_index(sqlite3*, const char*); - extern void sqlcipherCodecGetKey(sqlite3*, int, void**, int*); - extern void sqlcipher_free(void*, sqlite3_uint64); - int srcNKey, destNKey; - void *zKey; - - sqlcipherCodecGetKey(pSrcDb, sqlcipher_find_db_index(pSrcDb, zSrcDb), &zKey, &srcNKey); - if(srcNKey) sqlcipher_free(zKey, srcNKey); - sqlcipherCodecGetKey(pDestDb, sqlcipher_find_db_index(pDestDb, zDestDb), &zKey, &destNKey); - if(destNKey) sqlcipher_free(zKey, destNKey); - - /* either both databases must be plaintext, or both must be encrypted */ - if((srcNKey == 0 && destNKey > 0) || (srcNKey > 0 && destNKey == 0)) { - sqlite3ErrorWithMsg(pDestDb, SQLITE_ERROR, "backup is not supported with encrypted databases"); - return NULL; - } - } -#endif -/* END SQLCIPHER */ - - /* Lock the source database handle. The destination database - ** handle is not locked in this routine, but it is locked in - ** sqlite3_backup_step(). The user is required to ensure that no - ** other thread accesses the destination handle for the duration - ** of the backup operation. Any attempt to use the destination - ** database connection while a backup is in progress may cause - ** a malfunction or a deadlock. - */ - sqlite3_mutex_enter(pSrcDb->mutex); - sqlite3_mutex_enter(pDestDb->mutex); - - if( pSrcDb==pDestDb ){ - sqlite3ErrorWithMsg( - pDestDb, SQLITE_ERROR, "source and destination must be distinct" - ); - p = 0; - }else { - /* Allocate space for a new sqlite3_backup object... - ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a - ** call to sqlite3_backup_init() and is destroyed by a call to - ** sqlite3_backup_finish(). */ - p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); - if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); - } - } - - /* If the allocation succeeded, populate the new object. */ - if( p ){ - p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); - p->pDest = findBtree(pDestDb, pDestDb, zDestDb); - p->pDestDb = pDestDb; - p->pSrcDb = pSrcDb; - p->iNext = 1; - p->isAttached = 0; - - if( 0==p->pSrc || 0==p->pDest - || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK - ){ - /* One (or both) of the named databases did not exist or an OOM - ** error was hit. Or there is a transaction open on the destination - ** database. The error has already been written into the pDestDb - ** handle. All that is left to do here is free the sqlite3_backup - ** structure. */ - sqlite3_free(p); - p = 0; - } - } - if( p ){ - p->pSrc->nBackup++; - } - - sqlite3_mutex_leave(pDestDb->mutex); - sqlite3_mutex_leave(pSrcDb->mutex); - return p; -} - -/* -** Argument rc is an SQLite error code. Return true if this error is -** considered fatal if encountered during a backup operation. All errors -** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. -*/ -static int isFatalError(int rc){ - return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); -} - -/* -** Parameter zSrcData points to a buffer containing the data for -** page iSrcPg from the source database. Copy this data into the -** destination database. -*/ -static int backupOnePage( - sqlite3_backup *p, /* Backup handle */ - Pgno iSrcPg, /* Source database page to backup */ - const u8 *zSrcData, /* Source database page data */ - int bUpdate /* True for an update, false otherwise */ -){ - Pager * const pDestPager = sqlite3BtreePager(p->pDest); - const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); - int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); - const int nCopy = MIN(nSrcPgsz, nDestPgsz); - 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. */ - int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); - int nDestReserve = sqlite3BtreeGetRequestedReserve(p->pDest); -#endif -/* END SQLCIPHER */ - int rc = SQLITE_OK; - i64 iOff; - - assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); - assert( p->bDestLocked ); - assert( !isFatalError(p->rc) ); - assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); - assert( zSrcData ); - assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 ); - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - /* Backup is not possible if the page size of the destination is changing - ** and a codec is in use. - */ - if( nSrcPgsz!=nDestPgsz && sqlcipherPagerGetCodec(pDestPager)!=0 ){ - rc = SQLITE_READONLY; - } - - /* Backup is not possible if the number of bytes of reserve space differ - ** between source and destination. If there is a difference, try to - ** fix the destination to agree with the source. If that is not possible, - ** then the backup cannot proceed. - */ - if( nSrcReserve!=nDestReserve ){ - u32 newPgsz = nSrcPgsz; - rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); - if( rc==SQLITE_OK && newPgsz!=(u32)nSrcPgsz ) rc = SQLITE_READONLY; - } -#endif -/* END SQLCIPHER */ - - /* This loop runs once for each destination page spanned by the source - ** page. For each iteration, variable iOff is set to the byte offset - ** of the destination page. - */ - for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOffpDest->pBt) ) continue; - if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0)) - && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) - ){ - const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; - u8 *zDestData = sqlite3PagerGetData(pDestPg); - u8 *zOut = &zDestData[iOff%nDestPgsz]; - - /* Copy the data from the source page into the destination page. - ** Then clear the Btree layer MemPage.isInit flag. Both this module - ** and the pager code use this trick (clearing the first byte - ** of the page 'extra' space to invalidate the Btree layers - ** cached parse of the page). MemPage.isInit is marked - ** "MUST BE FIRST" for this purpose. - */ - memcpy(zOut, zIn, nCopy); - ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; - if( iOff==0 && bUpdate==0 ){ - sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); - } - } - sqlite3PagerUnref(pDestPg); - } - - return rc; -} - -/* -** If pFile is currently larger than iSize bytes, then truncate it to -** exactly iSize bytes. If pFile is not larger than iSize bytes, then -** this function is a no-op. -** -** Return SQLITE_OK if everything is successful, or an SQLite error -** code if an error occurs. -*/ -static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){ - i64 iCurrent; - int rc = sqlite3OsFileSize(pFile, &iCurrent); - if( rc==SQLITE_OK && iCurrent>iSize ){ - rc = sqlite3OsTruncate(pFile, iSize); - } - return rc; -} - -/* -** Register this backup object with the associated source pager for -** callbacks when pages are changed or the cache invalidated. -*/ -static void attachBackupObject(sqlite3_backup *p){ - sqlite3_backup **pp; - assert( sqlite3BtreeHoldsMutex(p->pSrc) ); - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - p->pNext = *pp; - *pp = p; - p->isAttached = 1; -} - -/* -** Copy nPage pages from the source b-tree to the destination. -*/ -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ - int rc; - int destMode; /* Destination journal mode */ - int pgszSrc = 0; /* Source page size */ - int pgszDest = 0; /* Destination page size */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(p->pSrcDb->mutex); - sqlite3BtreeEnter(p->pSrc); - if( p->pDestDb ){ - sqlite3_mutex_enter(p->pDestDb->mutex); - } - - rc = p->rc; - if( !isFatalError(rc) ){ - Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ - Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ - int ii; /* Iterator variable */ - int nSrcPage = -1; /* Size of source db in pages */ - int bCloseTrans = 0; /* True if src db requires unlocking */ - - /* If the source pager is currently in a write-transaction, return - ** SQLITE_BUSY immediately. - */ - if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ - rc = SQLITE_BUSY; - }else{ - rc = SQLITE_OK; - } - - /* If there is no open read-transaction on the source database, open - ** one now. If a transaction is opened here, then it will be closed - ** before this function exits. - */ - if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){ - rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); - bCloseTrans = 1; - } - - /* If the destination database has not yet been locked (i.e. if this - ** is the first call to backup_step() for the current backup operation), - ** try to set its page size to the same as the source database. This - ** is especially important on ZipVFS systems, as in that case it is - ** not possible to create a database file that uses one page size by - ** writing to it with another. */ - if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){ - rc = SQLITE_NOMEM; - } - - /* Lock the destination database, if it is not locked already. */ - if( SQLITE_OK==rc && p->bDestLocked==0 - && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2, - (int*)&p->iDestSchema)) - ){ - p->bDestLocked = 1; - } - - /* Do not allow backup if the destination database is in WAL mode - ** and the page sizes are different between source and destination */ - pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); - pgszDest = sqlite3BtreeGetPageSize(p->pDest); - destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); - if( SQLITE_OK==rc - && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) - && pgszSrc!=pgszDest - ){ - rc = SQLITE_READONLY; - } - - /* Now that there is a read-lock on the source database, query the - ** source pager for the number of pages in the database. - */ - nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); - assert( nSrcPage>=0 ); - for(ii=0; (nPage<0 || iiiNext<=(Pgno)nSrcPage && !rc; ii++){ - const Pgno iSrcPg = p->iNext; /* Source page number */ - if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ - DbPage *pSrcPg; /* Source page object */ - rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); - if( rc==SQLITE_OK ){ - rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); - sqlite3PagerUnref(pSrcPg); - } - } - p->iNext++; - } - if( rc==SQLITE_OK ){ - p->nPagecount = nSrcPage; - p->nRemaining = nSrcPage+1-p->iNext; - if( p->iNext>(Pgno)nSrcPage ){ - rc = SQLITE_DONE; - }else if( !p->isAttached ){ - attachBackupObject(p); - } - } - - /* Update the schema version field in the destination database. This - ** is to make sure that the schema-version really does change in - ** the case where the source and destination databases have the - ** same schema version. - */ - if( rc==SQLITE_DONE ){ - if( nSrcPage==0 ){ - rc = sqlite3BtreeNewDb(p->pDest); - nSrcPage = 1; - } - if( rc==SQLITE_OK || rc==SQLITE_DONE ){ - rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); - } - if( rc==SQLITE_OK ){ - if( p->pDestDb ){ - sqlite3ResetAllSchemasOfConnection(p->pDestDb); - } - if( destMode==PAGER_JOURNALMODE_WAL ){ - rc = sqlite3BtreeSetVersion(p->pDest, 2); - } - } - if( rc==SQLITE_OK ){ - int nDestTruncate; - /* Set nDestTruncate to the final number of pages in the destination - ** database. The complication here is that the destination page - ** size may be different to the source page size. - ** - ** If the source page size is smaller than the destination page size, - ** round up. In this case the call to sqlite3OsTruncate() below will - ** fix the size of the file. However it is important to call - ** sqlite3PagerTruncateImage() here so that any pages in the - ** destination file that lie beyond the nDestTruncate page mark are - ** journalled by PagerCommitPhaseOne() before they are destroyed - ** by the file truncation. - */ - assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); - assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); - if( pgszSrcpDest->pBt) ){ - nDestTruncate--; - } - }else{ - nDestTruncate = nSrcPage * (pgszSrc/pgszDest); - } - assert( nDestTruncate>0 ); - - if( pgszSrc= iSize || ( - nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) - && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest - )); - - /* This block ensures that all data required to recreate the original - ** database has been stored in the journal for pDestPager and the - ** journal synced to disk. So at this point we may safely modify - ** the database file in any way, knowing that if a power failure - ** occurs, the original database will be reconstructed from the - ** journal file. */ - sqlite3PagerPagecount(pDestPager, &nDstPage); - for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ - if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ - DbPage *pPg; - rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pPg); - sqlite3PagerUnref(pPg); - } - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); - } - - /* Write the extra pages and truncate the database file as required */ - iEnd = MIN(PENDING_BYTE + pgszDest, iSize); - for( - iOff=PENDING_BYTE+pgszSrc; - rc==SQLITE_OK && iOffpDest, 0)) - ){ - rc = SQLITE_DONE; - } - } - } - - /* If bCloseTrans is true, then this function opened a read transaction - ** on the source database. Close the read transaction here. There is - ** no need to check the return values of the btree methods here, as - ** "committing" a read-only transaction cannot fail. - */ - if( bCloseTrans ){ - TESTONLY( int rc2 ); - TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); - TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); - assert( rc2==SQLITE_OK ); - } - - if( rc==SQLITE_IOERR_NOMEM ){ - rc = SQLITE_NOMEM_BKPT; - } - p->rc = rc; - } - if( p->pDestDb ){ - sqlite3_mutex_leave(p->pDestDb->mutex); - } - sqlite3BtreeLeave(p->pSrc); - sqlite3_mutex_leave(p->pSrcDb->mutex); - return rc; -} - -/* -** Release all resources associated with an sqlite3_backup* handle. -*/ -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ - sqlite3_backup **pp; /* Ptr to head of pagers backup list */ - sqlite3 *pSrcDb; /* Source database connection */ - int rc; /* Value to return */ - - /* Enter the mutexes */ - if( p==0 ) return SQLITE_OK; - pSrcDb = p->pSrcDb; - sqlite3_mutex_enter(pSrcDb->mutex); - sqlite3BtreeEnter(p->pSrc); - if( p->pDestDb ){ - sqlite3_mutex_enter(p->pDestDb->mutex); - } - - /* Detach this backup from the source pager. */ - if( p->pDestDb ){ - p->pSrc->nBackup--; - } - if( p->isAttached ){ - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - assert( pp!=0 ); - while( *pp!=p ){ - pp = &(*pp)->pNext; - assert( pp!=0 ); - } - *pp = p->pNext; - } - - /* If a transaction is still open on the Btree, roll it back. */ - sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); - - /* Set the error code of the destination database handle. */ - rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; - if( p->pDestDb ){ - sqlite3Error(p->pDestDb, rc); - - /* Exit the mutexes and free the backup context structure. */ - sqlite3LeaveMutexAndCloseZombie(p->pDestDb); - } - sqlite3BtreeLeave(p->pSrc); - if( p->pDestDb ){ - /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a - ** call to sqlite3_backup_init() and is destroyed by a call to - ** sqlite3_backup_finish(). */ - sqlite3_free(p); - } - sqlite3LeaveMutexAndCloseZombie(pSrcDb); - return rc; -} - -/* -** Return the number of pages still to be backed up as of the most recent -** call to sqlite3_backup_step(). -*/ -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return p->nRemaining; -} - -/* -** Return the total number of pages in the source database as of the most -** recent call to sqlite3_backup_step(). -*/ -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return p->nPagecount; -} - -/* -** This function is called after the contents of page iPage of the -** source database have been modified. If page iPage has already been -** copied into the destination database, then the data written to the -** destination is now invalidated. The destination copy of iPage needs -** to be updated with the new data before the backup operation is -** complete. -** -** It is assumed that the mutex associated with the BtShared object -** corresponding to the source database is held when this function is -** called. -*/ -static SQLITE_NOINLINE void backupUpdate( - sqlite3_backup *p, - Pgno iPage, - const u8 *aData -){ - assert( p!=0 ); - do{ - assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); - if( !isFatalError(p->rc) && iPageiNext ){ - /* The backup process p has already copied page iPage. But now it - ** has been modified by a transaction on the source pager. Copy - ** the new data into the backup. - */ - int rc; - assert( p->pDestDb ); - sqlite3_mutex_enter(p->pDestDb->mutex); - rc = backupOnePage(p, iPage, aData, 1); - sqlite3_mutex_leave(p->pDestDb->mutex); - assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); - if( rc!=SQLITE_OK ){ - p->rc = rc; - } - } - }while( (p = p->pNext)!=0 ); -} -SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ - if( pBackup ) backupUpdate(pBackup, iPage, aData); -} - -/* -** Restart the backup process. This is called when the pager layer -** detects that the database has been modified by an external database -** connection. In this case there is no way of knowing which of the -** pages that have been copied into the destination database are still -** valid and which are not, so the entire process needs to be restarted. -** -** It is assumed that the mutex associated with the BtShared object -** corresponding to the source database is held when this function is -** called. -*/ -SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){ - sqlite3_backup *p; /* Iterator variable */ - for(p=pBackup; p; p=p->pNext){ - assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); - p->iNext = 1; - } -} - -#ifndef SQLITE_OMIT_VACUUM -/* -** Copy the complete content of pBtFrom into pBtTo. A transaction -** must be active for both files. -** -** The size of file pTo may be reduced by this operation. If anything -** goes wrong, the transaction on pTo is rolled back. If successful, the -** transaction is committed before returning. -*/ -SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ - int rc; - sqlite3_file *pFd; /* File descriptor for database pTo */ - sqlite3_backup b; - sqlite3BtreeEnter(pTo); - sqlite3BtreeEnter(pFrom); - - assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE ); - pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); - if( pFd->pMethods ){ - i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); - rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - if( rc ) goto copy_finished; - } - - /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set - ** to 0. This is used by the implementations of sqlite3_backup_step() - ** and sqlite3_backup_finish() to detect that they are being called - ** from this function, not directly by the user. - */ - memset(&b, 0, sizeof(b)); - b.pSrcDb = pFrom->db; - b.pSrc = pFrom; - b.pDest = pTo; - b.iNext = 1; - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); -#endif -/* END SQLCIPHER */ - - /* 0x7FFFFFFF is the hard limit for the number of pages in a database - ** file. By passing this as the number of pages to copy to - ** sqlite3_backup_step(), we can guarantee that the copy finishes - ** within a single call (unless an error occurs). The assert() statement - ** checks this assumption - (p->rc) should be set to either SQLITE_DONE - ** or an error code. */ - sqlite3_backup_step(&b, 0x7FFFFFFF); - assert( b.rc!=SQLITE_OK ); - - rc = sqlite3_backup_finish(&b); - if( rc==SQLITE_OK ){ - pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; - }else{ - sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); - } - - assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE ); -copy_finished: - sqlite3BtreeLeave(pFrom); - sqlite3BtreeLeave(pTo); - return rc; -} -#endif /* SQLITE_OMIT_VACUUM */ - -/************** End of backup.c **********************************************/ -/************** Begin file vdbemem.c *****************************************/ -/* -** 2004 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to manipulate "Mem" structure. A "Mem" -** stores a single value in the VDBE. Mem is an opaque structure visible -** only within the VDBE. Interface routines refer to a Mem using the -** name sqlite_value -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -/* True if X is a power of two. 0 is considered a power of two here. -** In other words, return true if X has at most one bit set. -*/ -#define ISPOWEROF2(X) (((X)&((X)-1))==0) - -#ifdef SQLITE_DEBUG -/* -** Check invariants on a Mem object. -** -** This routine is intended for use inside of assert() statements, like -** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); -*/ -SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ - /* If MEM_Dyn is set then Mem.xDel!=0. - ** Mem.xDel might not be initialized if MEM_Dyn is clear. - */ - assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); - - /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we - ** ensure that if Mem.szMalloc>0 then it is safe to do - ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn. - ** That saves a few cycles in inner loops. */ - assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); - - /* Cannot have more than one of MEM_Int, MEM_Real, or MEM_IntReal */ - assert( ISPOWEROF2(p->flags & (MEM_Int|MEM_Real|MEM_IntReal)) ); - - if( p->flags & MEM_Null ){ - /* Cannot be both MEM_Null and some other type */ - assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 ); - - /* If MEM_Null is set, then either the value is a pure NULL (the usual - ** case) or it is a pointer set using sqlite3_bind_pointer() or - ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be - ** set. - */ - if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){ - /* This is a pointer type. There may be a flag to indicate what to - ** do with the pointer. */ - assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + - ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + - ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 ); - - /* No other bits set */ - assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype|MEM_FromBind - |MEM_Dyn|MEM_Ephem|MEM_Static))==0 ); - }else{ - /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn, - ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */ - } - }else{ - /* The MEM_Cleared bit is only allowed on NULLs */ - assert( (p->flags & MEM_Cleared)==0 ); - } - - /* The szMalloc field holds the correct memory allocation size */ - assert( p->szMalloc==0 - || (p->flags==MEM_Undefined - && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc)) - || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc)); - - /* If p holds a string or blob, the Mem.z must point to exactly - ** one of the following: - ** - ** (1) Memory in Mem.zMalloc and managed by the Mem object - ** (2) Memory to be freed using Mem.xDel - ** (3) An ephemeral string or blob - ** (4) A static string or blob - */ - if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){ - assert( - ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) + - ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + - ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + - ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 - ); - } - return 1; -} -#endif - -/* -** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal -** into a buffer. -*/ -static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ - StrAccum acc; - assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) ); - assert( sz>22 ); - if( p->flags & MEM_Int ){ -#if GCC_VERSION>=7000000 - /* Work-around for GCC bug - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */ - i64 x; - assert( (p->flags&MEM_Int)*2==sizeof(x) ); - memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2); - p->n = sqlite3Int64ToText(x, zBuf); -#else - p->n = sqlite3Int64ToText(p->u.i, zBuf); -#endif - }else{ - sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); - sqlite3_str_appendf(&acc, "%!.15g", - (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r); - assert( acc.zText==zBuf && acc.mxAlloc<=0 ); - zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */ - p->n = acc.nChar; - } -} - -#ifdef SQLITE_DEBUG -/* -** Validity checks on pMem. pMem holds a string. -** -** (1) Check that string value of pMem agrees with its integer or real value. -** (2) Check that the string is correctly zero terminated -** -** A single int or real value always converts to the same strings. But -** many different strings can be converted into the same int or real. -** If a table contains a numeric value and an index is based on the -** corresponding string value, then it is important that the string be -** derived from the numeric value, not the other way around, to ensure -** that the index and table are consistent. See ticket -** https://sqlite.org/src/info/343634942dd54ab (2018-01-31) for -** an example. -** -** This routine looks at pMem to verify that if it has both a numeric -** representation and a string representation then the string rep has -** been derived from the numeric and not the other way around. It returns -** true if everything is ok and false if there is a problem. -** -** This routine is for use inside of assert() statements only. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ - Mem tmp; - char zBuf[100]; - char *z; - int i, j, incr; - if( (p->flags & MEM_Str)==0 ) return 1; - if( p->db && p->db->mallocFailed ) return 1; - if( p->flags & MEM_Term ){ - /* Insure that the string is properly zero-terminated. Pay particular - ** attention to the case where p->n is odd */ - if( p->szMalloc>0 && p->z==p->zMalloc ){ - assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 ); - assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 ); - } - assert( p->z[p->n]==0 ); - assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 ); - assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 ); - } - if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1; - memcpy(&tmp, p, sizeof(tmp)); - vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp); - z = p->z; - i = j = 0; - incr = 1; - if( p->enc!=SQLITE_UTF8 ){ - incr = 2; - if( p->enc==SQLITE_UTF16BE ) z++; - } - while( zBuf[j] ){ - if( zBuf[j++]!=z[i] ) return 0; - i += incr; - } - return 1; -} -#endif /* SQLITE_DEBUG */ - -/* -** If pMem is an object with a valid string representation, this routine -** ensures the internal encoding for the string representation is -** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. -** -** If pMem is not a string object, or the encoding of the string -** representation is already stored using the requested encoding, then this -** routine is a no-op. -** -** SQLITE_OK is returned if the conversion is successful (or not required). -** SQLITE_NOMEM may be returned if a malloc() fails during conversion -** between formats. -*/ -SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ -#ifndef SQLITE_OMIT_UTF16 - int rc; -#endif - assert( pMem!=0 ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE - || desiredEnc==SQLITE_UTF16BE ); - if( !(pMem->flags&MEM_Str) ){ - pMem->enc = desiredEnc; - return SQLITE_OK; - } - if( pMem->enc==desiredEnc ){ - return SQLITE_OK; - } - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); -#ifdef SQLITE_OMIT_UTF16 - return SQLITE_ERROR; -#else - - /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, - ** then the encoding of the value may not have changed. - */ - rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc); - assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); - assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); - assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); - return rc; -#endif -} - -/* -** Make sure pMem->z points to a writable allocation of at least n bytes. -** -** If the bPreserve argument is true, then copy of the content of -** pMem->z into the new allocation. pMem must be either a string or -** blob if bPreserve is true. If bPreserve is false, any prior content -** in pMem->z is discarded. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ - assert( sqlite3VdbeCheckMemInvariants(pMem) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - testcase( pMem->db==0 ); - - /* If the bPreserve flag is set to true, then the memory cell must already - ** contain a valid string or blob value. */ - assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); - testcase( bPreserve && pMem->z==0 ); - - assert( pMem->szMalloc==0 - || (pMem->flags==MEM_Undefined - && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc)) - || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc)); - if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ - if( pMem->db ){ - pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - }else{ - pMem->zMalloc = sqlite3Realloc(pMem->z, n); - if( pMem->zMalloc==0 ) sqlite3_free(pMem->z); - pMem->z = pMem->zMalloc; - } - bPreserve = 0; - }else{ - if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); - pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); - } - if( pMem->zMalloc==0 ){ - sqlite3VdbeMemSetNull(pMem); - pMem->z = 0; - pMem->szMalloc = 0; - return SQLITE_NOMEM_BKPT; - }else{ - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); - } - - if( bPreserve && pMem->z ){ - assert( pMem->z!=pMem->zMalloc ); - memcpy(pMem->zMalloc, pMem->z, pMem->n); - } - if( (pMem->flags&MEM_Dyn)!=0 ){ - assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC ); - pMem->xDel((void *)(pMem->z)); - } - - pMem->z = pMem->zMalloc; - pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static); - return SQLITE_OK; -} - -/* -** Change the pMem->zMalloc allocation to be at least szNew bytes. -** If pMem->zMalloc already meets or exceeds the requested size, this -** routine is a no-op. -** -** Any prior string or blob content in the pMem object may be discarded. -** The pMem->xDel destructor is called, if it exists. Though MEM_Str -** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal, -** and MEM_Null values are preserved. -** -** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM) -** if unable to complete the resizing. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ - assert( CORRUPT_DB || szNew>0 ); - assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 ); - if( pMem->szMallocflags & MEM_Dyn)==0 ); - pMem->z = pMem->zMalloc; - pMem->flags &= (MEM_Null|MEM_Int|MEM_Real|MEM_IntReal); - return SQLITE_OK; -} - -/* -** If pMem is already a string, detect if it is a zero-terminated -** string, or make it into one if possible, and mark it as such. -** -** This is an optimization. Correct operation continues even if -** this routine is a no-op. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ - if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ - /* pMem must be a string, and it cannot be an ephemeral or static string */ - return; - } - if( pMem->enc!=SQLITE_UTF8 ) return; - assert( pMem->z!=0 ); - if( pMem->flags & MEM_Dyn ){ - if( pMem->xDel==sqlite3_free - && sqlite3_msize(pMem->z) >= (u64)(pMem->n+1) - ){ - pMem->z[pMem->n] = 0; - pMem->flags |= MEM_Term; - return; - } - if( pMem->xDel==sqlite3RCStrUnref ){ - /* Blindly assume that all RCStr objects are zero-terminated */ - pMem->flags |= MEM_Term; - return; - } - }else if( pMem->szMalloc >= pMem->n+1 ){ - pMem->z[pMem->n] = 0; - pMem->flags |= MEM_Term; - return; - } -} - -/* -** It is already known that pMem contains an unterminated string. -** Add the zero terminator. -** -** Three bytes of zero are added. In this way, there is guaranteed -** to be a double-zero byte at an even byte boundary in order to -** terminate a UTF16 string, even if the initial size of the buffer -** is an odd number of bytes. -*/ -static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ - return SQLITE_NOMEM_BKPT; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->z[pMem->n+2] = 0; - pMem->flags |= MEM_Term; - return SQLITE_OK; -} - -/* -** Change pMem so that its MEM_Str or MEM_Blob value is stored in -** MEM.zMalloc, where it can be safely written. -** -** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ - if( ExpandBlob(pMem) ) return SQLITE_NOMEM; - if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ - int rc = vdbeMemAddTerminator(pMem); - if( rc ) return rc; - } - } - pMem->flags &= ~MEM_Ephem; -#ifdef SQLITE_DEBUG - pMem->pScopyFrom = 0; -#endif - - return SQLITE_OK; -} - -/* -** If the given Mem* has a zero-filled tail, turn it into an ordinary -** blob stored in dynamically allocated space. -*/ -#ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ - int nByte; - assert( pMem!=0 ); - assert( pMem->flags & MEM_Zero ); - assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) ); - testcase( sqlite3_value_nochange(pMem) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - - /* Set nByte to the number of bytes required to store the expanded blob. */ - nByte = pMem->n + pMem->u.nZero; - if( nByte<=0 ){ - if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK; - nByte = 1; - } - if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ - return SQLITE_NOMEM_BKPT; - } - assert( pMem->z!=0 ); - assert( sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte ); - - memset(&pMem->z[pMem->n], 0, pMem->u.nZero); - pMem->n += pMem->u.nZero; - pMem->flags &= ~(MEM_Zero|MEM_Term); - return SQLITE_OK; -} -#endif - -/* -** Make sure the given Mem is \u0000 terminated. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->db==0 || 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 ); - if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){ - return SQLITE_OK; /* Nothing to do */ - }else{ - return vdbeMemAddTerminator(pMem); - } -} - -/* -** Add MEM_Str to the set of representations for the given Mem. This -** routine is only called if pMem is a number of some kind, not a NULL -** or a BLOB. -** -** Existing representations MEM_Int, MEM_Real, or MEM_IntReal are invalidated -** if bForce is true but are retained if bForce is false. -** -** A MEM_Null value will never be passed to this function. This function is -** used for converting values to text for returning to the user (i.e. via -** sqlite3_value_text()), or for ensuring that values to be used as btree -** keys are strings. In the former case a NULL pointer is returned the -** user and the latter is an internal programming error. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ - const int nByte = 32; - - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !(pMem->flags&MEM_Zero) ); - assert( !(pMem->flags&(MEM_Str|MEM_Blob)) ); - assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - - if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ - pMem->enc = 0; - return SQLITE_NOMEM_BKPT; - } - - vdbeMemRenderNum(nByte, pMem->z, pMem); - assert( pMem->z!=0 ); - assert( pMem->n==(int)sqlite3Strlen30NN(pMem->z) ); - pMem->enc = SQLITE_UTF8; - pMem->flags |= MEM_Str|MEM_Term; - if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); - sqlite3VdbeChangeEncoding(pMem, enc); - return SQLITE_OK; -} - -/* -** Memory cell pMem contains the context of an aggregate function. -** This routine calls the finalize method for that function. The -** result of the aggregate is stored back into pMem. -** -** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK -** otherwise. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ - 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( sqlite3_mutex_held(pMem->db->mutex) ); - memset(&ctx, 0, sizeof(ctx)); - memset(&t, 0, sizeof(t)); - t.flags = MEM_Null; - t.db = pMem->db; - 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 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); - memcpy(pMem, &t, sizeof(t)); - return ctx.isError; -} - -/* -** Memory cell pAccum contains the context of an aggregate function. -** This routine calls the xValue method for that function and stores -** the results in memory cell pMem. -** -** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK -** otherwise. -*/ -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ - sqlite3_context ctx; - assert( pFunc!=0 ); - assert( pFunc->xValue!=0 ); - assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); - assert( pAccum->db!=0 ); - assert( sqlite3_mutex_held(pAccum->db->mutex) ); - memset(&ctx, 0, sizeof(ctx)); - sqlite3VdbeMemSetNull(pOut); - ctx.pOut = pOut; - ctx.pMem = pAccum; - ctx.pFunc = pFunc; - ctx.enc = ENC(pAccum->db); - pFunc->xValue(&ctx); - return ctx.isError; -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** If the memory cell contains a value that must be freed by -** invoking the external callback in Mem.xDel, then this routine -** will free that value. It also sets Mem.flags to MEM_Null. -** -** This is a helper routine for sqlite3VdbeMemSetNull() and -** for sqlite3VdbeMemRelease(). Use those other routines as the -** entry point for releasing Mem resources. -*/ -static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){ - assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); - assert( VdbeMemDynamic(p) ); - if( p->flags&MEM_Agg ){ - sqlite3VdbeMemFinalize(p, p->u.pDef); - assert( (p->flags & MEM_Agg)==0 ); - testcase( p->flags & MEM_Dyn ); - } - if( p->flags&MEM_Dyn ){ - assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); - p->xDel((void *)p->z); - } - p->flags = MEM_Null; -} - -/* -** Release memory held by the Mem p, both external memory cleared -** by p->xDel and memory in p->zMalloc. -** -** This is a helper routine invoked by sqlite3VdbeMemRelease() in -** the unusual case where there really is memory in p that needs -** to be freed. -*/ -static SQLITE_NOINLINE void vdbeMemClear(Mem *p){ - if( VdbeMemDynamic(p) ){ - vdbeMemClearExternAndSetNull(p); - } - if( p->szMalloc ){ - sqlite3DbFreeNN(p->db, p->zMalloc); - p->szMalloc = 0; - } - p->z = 0; -} - -/* -** Release any memory resources held by the Mem. Both the memory that is -** free by Mem.xDel and the Mem.zMalloc allocation are freed. -** -** Use this routine prior to clean up prior to abandoning a Mem, or to -** reset a Mem back to its minimum memory utilization. -** -** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space -** prior to inserting new content into the Mem. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ - assert( sqlite3VdbeCheckMemInvariants(p) ); - if( VdbeMemDynamic(p) || p->szMalloc ){ - vdbeMemClear(p); - } -} - -/* Like sqlite3VdbeMemRelease() but faster for cases where we -** know in advance that the Mem is not MEM_Dyn or MEM_Agg. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ - assert( !VdbeMemDynamic(p) ); - if( p->szMalloc ) vdbeMemClear(p); -} - -/* -** Return some kind of integer value which is the best we can do -** at representing the value that *pMem describes as an integer. -** If pMem is an integer, then the value is exact. If pMem is -** a floating-point then the value returned is the integer part. -** If pMem is a string or blob, then we make an attempt to convert -** it into an integer and return that. If pMem represents an -** an SQL-NULL value, return 0. -** -** If pMem represents a string value, its encoding might be changed. -*/ -static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){ - i64 value = 0; - sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); - return value; -} -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ - int flags; - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - flags = pMem->flags; - if( flags & (MEM_Int|MEM_IntReal) ){ - testcase( flags & MEM_IntReal ); - return pMem->u.i; - }else if( flags & MEM_Real ){ - return sqlite3RealToI64(pMem->u.r); - }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){ - return memIntValue(pMem); - }else{ - return 0; - } -} - -/* -** Return the best representation of pMem that we can get into a -** double. If pMem is already a double or an integer, return its -** value. If it is a string or blob, try to convert it to a double. -** If it is a NULL, return 0.0. -*/ -static SQLITE_NOINLINE double memRealValue(Mem *pMem){ - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - double val = (double)0; - sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); - return val; -} -SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - if( pMem->flags & MEM_Real ){ - return pMem->u.r; - }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pMem->flags & MEM_IntReal ); - return (double)pMem->u.i; - }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ - return memRealValue(pMem); - }else{ - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - return (double)0; - } -} - -/* -** Return 1 if pMem represents true, and return 0 if pMem represents false. -** Return the value ifNull if pMem is NULL. -*/ -SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ - testcase( pMem->flags & MEM_IntReal ); - if( pMem->flags & (MEM_Int|MEM_IntReal) ) return pMem->u.i!=0; - if( pMem->flags & MEM_Null ) return ifNull; - return sqlite3VdbeRealValue(pMem)!=0.0; -} - -/* -** The MEM structure is already a MEM_Real or MEM_IntReal. Try to -** make it a MEM_Int if we can. -*/ -SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->flags & (MEM_Real|MEM_IntReal) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - if( pMem->flags & MEM_IntReal ){ - MemSetTypeFlag(pMem, MEM_Int); - }else{ - i64 ix = sqlite3RealToI64(pMem->u.r); - - /* Only mark the value as an integer if - ** - ** (1) the round-trip conversion real->int->real is a no-op, and - ** (2) The integer is neither the largest nor the smallest - ** possible integer (ticket #3922) - ** - ** The second and third terms in the following conditional enforces - ** the second condition under the assumption that addition overflow causes - ** values to wrap around. - */ - if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; - MemSetTypeFlag(pMem, MEM_Int); - } - } -} - -/* -** Convert pMem to type integer. Invalidate any prior representations. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - pMem->u.i = sqlite3VdbeIntValue(pMem); - MemSetTypeFlag(pMem, MEM_Int); - return SQLITE_OK; -} - -/* -** Convert pMem so that it is of type MEM_Real. -** Invalidate any prior representations. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - pMem->u.r = sqlite3VdbeRealValue(pMem); - MemSetTypeFlag(pMem, MEM_Real); - return SQLITE_OK; -} - -/* Compare a floating point value to an integer. Return true if the two -** values are the same within the precision of the floating point value. -** -** This function assumes that i was obtained by assignment from r1. -** -** For some versions of GCC on 32-bit machines, if you do the more obvious -** comparison of "r1==(double)i" you sometimes get an answer of false even -** though the r1 and (double)i values are bit-for-bit the same. -*/ -SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ - double r2 = (double)i; - return r1==0.0 - || (memcmp(&r1, &r2, sizeof(r1))==0 - && i >= -2251799813685248LL && i < 2251799813685248LL); -} - -/* Convert a floating point value to its closest integer. Do so in -** a way that avoids 'outside the range of representable values' warnings -** from UBSAN. -*/ -SQLITE_PRIVATE i64 sqlite3RealToI64(double r){ - if( r<-9223372036854774784.0 ) return SMALLEST_INT64; - if( r>+9223372036854774784.0 ) return LARGEST_INT64; - return (i64)r; -} - -/* -** Convert pMem so that it has type MEM_Real or MEM_Int. -** Invalidate any prior representations. -** -** Every effort is made to force the conversion, even if the input -** is a string that does not look completely like a number. Convert -** as much of the string as we can and ignore the rest. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ - assert( pMem!=0 ); - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_Real ); - testcase( pMem->flags & MEM_IntReal ); - testcase( pMem->flags & MEM_Null ); - if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){ - int rc; - sqlite3_int64 ix; - assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1) - || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) - ){ - pMem->u.i = ix; - MemSetTypeFlag(pMem, MEM_Int); - }else{ - MemSetTypeFlag(pMem, MEM_Real); - } - } - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))!=0 ); - pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero); - return SQLITE_OK; -} - -/* -** Cast the datatype of the value in pMem according to the affinity -** "aff". Casting is different from applying affinity in that a cast -** is forced. In other words, the value is converted into the desired -** affinity even if that results in loss of data. This routine is -** used (for example) to implement the SQL "cast()" operator. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ - if( pMem->flags & MEM_Null ) return SQLITE_OK; - switch( aff ){ - case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ - if( (pMem->flags & MEM_Blob)==0 ){ - sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); - assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); - }else{ - pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); - } - break; - } - case SQLITE_AFF_NUMERIC: { - sqlite3VdbeMemNumerify(pMem); - break; - } - case SQLITE_AFF_INTEGER: { - sqlite3VdbeMemIntegerify(pMem); - break; - } - case SQLITE_AFF_REAL: { - sqlite3VdbeMemRealify(pMem); - break; - } - default: { - int rc; - assert( aff==SQLITE_AFF_TEXT ); - assert( MEM_Str==(MEM_Blob>>3) ); - pMem->flags |= (pMem->flags&MEM_Blob)>>3; - sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); - assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero); - if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1; - rc = sqlite3VdbeChangeEncoding(pMem, encoding); - if( rc ) return rc; - sqlite3VdbeMemZeroTerminateIfAble(pMem); - } - } - return SQLITE_OK; -} - -/* -** Initialize bulk memory to be a consistent Mem object. -** -** The minimum amount of initialization feasible is performed. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){ - assert( (flags & ~MEM_TypeMask)==0 ); - pMem->flags = flags; - pMem->db = db; - pMem->szMalloc = 0; -} - - -/* -** Delete any previous value and set the value stored in *pMem to NULL. -** -** This routine calls the Mem.xDel destructor to dispose of values that -** require the destructor. But it preserves the Mem.zMalloc memory allocation. -** To free all resources, use sqlite3VdbeMemRelease(), which both calls this -** routine to invoke the destructor and deallocates Mem.zMalloc. -** -** Use this routine to reset the Mem prior to insert a new value. -** -** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ - if( VdbeMemDynamic(pMem) ){ - vdbeMemClearExternAndSetNull(pMem); - }else{ - pMem->flags = MEM_Null; - } -} -SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){ - sqlite3VdbeMemSetNull((Mem*)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 sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ - sqlite3VdbeMemRelease(pMem); - pMem->flags = MEM_Blob|MEM_Zero; - pMem->n = 0; - if( n<0 ) n = 0; - pMem->u.nZero = n; - pMem->enc = SQLITE_UTF8; - pMem->z = 0; -} -#else -SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ - int nByte = n>0?n:1; - if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){ - return SQLITE_NOMEM_BKPT; - } - assert( pMem->z!=0 ); - assert( 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 -** to a value change. So invoke the destructor, then set the value to -** a 64-bit integer. -*/ -static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){ - sqlite3VdbeMemSetNull(pMem); - pMem->u.i = val; - pMem->flags = MEM_Int; -} - -/* -** Delete any previous value and set the value stored in *pMem to val, -** manifest type INTEGER. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ - if( VdbeMemDynamic(pMem) ){ - vdbeReleaseAndSetInt64(pMem, val); - }else{ - pMem->u.i = val; - pMem->flags = MEM_Int; - } -} - -/* -** Set the iIdx'th entry of array aMem[] to contain integer value val. -*/ -SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val){ - sqlite3VdbeMemSetInt64(&aMem[iIdx], val); -} - -/* A no-op destructor */ -SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } - -/* -** Set the value stored in *pMem should already be a NULL. -** Also store a pointer to go with it. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetPointer( - Mem *pMem, - void *pPtr, - const char *zPType, - 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; - pMem->eSubtype = 'p'; - pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Delete any previous value and set the value stored in *pMem to val, -** manifest type REAL. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ - sqlite3VdbeMemSetNull(pMem); - if( !sqlite3IsNaN(val) ){ - pMem->u.r = val; - pMem->flags = MEM_Real; - } -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Return true if the Mem holds a RowSet object. This routine is intended -** for use inside of assert() statements. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem *pMem){ - return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn) - && pMem->xDel==sqlite3RowSetDelete; -} -#endif - -/* -** Delete any previous value and set the value of pMem to be an -** empty boolean index. -** -** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation -** error occurs. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem *pMem){ - sqlite3 *db = pMem->db; - RowSet *p; - assert( db!=0 ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - sqlite3VdbeMemRelease(pMem); - p = sqlite3RowSetInit(db); - if( p==0 ) return SQLITE_NOMEM; - pMem->z = (char*)p; - pMem->flags = MEM_Blob|MEM_Dyn; - pMem->xDel = sqlite3RowSetDelete; - return SQLITE_OK; -} - -/* -** Return true if the Mem object contains a TEXT or BLOB that is -** too large - whose size exceeds SQLITE_MAX_LENGTH. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){ - assert( p->db!=0 ); - if( p->flags & (MEM_Str|MEM_Blob) ){ - int n = p->n; - if( p->flags & MEM_Zero ){ - n += p->u.nZero; - } - return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; - } - return 0; -} - -#ifdef SQLITE_DEBUG -/* -** This routine prepares a memory cell for modification by breaking -** its link to a shallow copy and by marking any current shallow -** copies of this cell as invalid. -** -** This is used for testing and debugging only - to help ensure that shallow -** copies (created by OP_SCopy) are not misused. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ - int i; - Mem *pX; - if( pMem->bScopy ){ - for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){ - if( pX->pScopyFrom==pMem ){ - u16 mFlags; - if( pVdbe->db->flags & SQLITE_VdbeTrace ){ - sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n", - (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem)); - } - /* If pX is marked as a shallow copy of pMem, then try to verify that - ** no significant changes have been made to pX since the OP_SCopy. - ** A significant change would indicated a missed call to this - ** function for pX. Minor changes, such as adding or removing a - ** dual type, are allowed, as long as the underlying value is the - ** same. */ - mFlags = pMem->flags & pX->flags & pX->mScopyFlags; - assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i ); - - /* pMem is the register that is changing. But also mark pX as - ** undefined so that we can quickly detect the shallow-copy error */ - pX->flags = MEM_Undefined; - pX->pScopyFrom = 0; - } - } - pMem->bScopy = 0; - } - pMem->pScopyFrom = 0; -} -#endif /* SQLITE_DEBUG */ - -/* -** Make an shallow copy of pFrom into pTo. Prior contents of -** pTo are freed. The pFrom->z field is not duplicated. If -** pFrom->z is used, then pTo->z points to the same thing as pFrom->z -** and flags gets srcType (either MEM_Ephem or MEM_Static). -*/ -static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){ - vdbeMemClearExternAndSetNull(pTo); - assert( !VdbeMemDynamic(pTo) ); - sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); -} -SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ - assert( !sqlite3VdbeMemIsRowSet(pFrom) ); - assert( pTo->db==pFrom->db ); - if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } - memcpy(pTo, pFrom, MEMCELLSIZE); - if( (pFrom->flags&MEM_Static)==0 ){ - pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); - assert( srcType==MEM_Ephem || srcType==MEM_Static ); - pTo->flags |= srcType; - } -} - -/* -** Make a full copy of pFrom into pTo. Prior contents of pTo are -** freed before the copy is made. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ - int rc = SQLITE_OK; - - assert( !sqlite3VdbeMemIsRowSet(pFrom) ); - if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); - memcpy(pTo, pFrom, MEMCELLSIZE); - pTo->flags &= ~MEM_Dyn; - if( pTo->flags&(MEM_Str|MEM_Blob) ){ - if( 0==(pFrom->flags&MEM_Static) ){ - pTo->flags |= MEM_Ephem; - rc = sqlite3VdbeMemMakeWriteable(pTo); - } - } - - return rc; -} - -/* -** Transfer the contents of pFrom to pTo. Any existing value in pTo is -** freed. If pFrom contains ephemeral data, a copy is made. -** -** pFrom contains an SQL NULL when this routine returns. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ - assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); - assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); - assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); - - sqlite3VdbeMemRelease(pTo); - memcpy(pTo, pFrom, sizeof(Mem)); - pFrom->flags = MEM_Null; - pFrom->szMalloc = 0; -} - -/* -** Change the value of a Mem to be a string or a BLOB. -** -** The memory management strategy depends on the value of the xDel -** parameter. If the value passed is SQLITE_TRANSIENT, then the -** string is copied into a (possibly existing) buffer managed by the -** Mem structure. Otherwise, any existing buffer is freed and the -** pointer copied. -** -** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH -** size limit) then no memory allocation occurs. If the string can be -** 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 sqlite3VdbeMemSetStr( - Mem *pMem, /* Memory cell to set to string value */ - const char *z, /* String pointer */ - i64 n, /* Bytes in string, or negative */ - u8 enc, /* Encoding of z. 0 for BLOBs */ - void (*xDel)(void*) /* Destructor function */ -){ - i64 nByte = n; /* New value for pMem->n */ - int iLimit; /* Maximum allowed string or blob size */ - u16 flags; /* New value for pMem->flags */ - - assert( pMem!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( enc!=0 || n>=0 ); - - /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ - if( !z ){ - sqlite3VdbeMemSetNull(pMem); - return SQLITE_OK; - } - - if( pMem->db ){ - iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH]; - }else{ - iLimit = SQLITE_MAX_LENGTH; - } - if( nByte<0 ){ - assert( enc!=0 ); - if( enc==SQLITE_UTF8 ){ - nByte = strlen(z); - }else{ - for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} - } - 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 ){ - sqlite3DbFree(pMem->db, (void*)z); - }else{ - xDel((void*)z); - } - } - sqlite3VdbeMemSetNull(pMem); - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); - } - - /* The following block sets the new values of Mem.z and Mem.xDel. It - ** also sets a flag in local variable "flags" to indicate the memory - ** management (one of MEM_Dyn or MEM_Static). - */ - if( xDel==SQLITE_TRANSIENT ){ - i64 nAlloc = nByte; - if( flags&MEM_Term ){ - nAlloc += (enc==SQLITE_UTF8?1:2); - } - testcase( nAlloc==0 ); - testcase( nAlloc==31 ); - testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ - return SQLITE_NOMEM_BKPT; - } - memcpy(pMem->z, z, nAlloc); - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->z = (char *)z; - if( xDel==SQLITE_DYNAMIC ){ - pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); - }else{ - pMem->xDel = xDel; - flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); - } - } - - pMem->n = (int)(nByte & 0x7fffffff); - pMem->flags = flags; - pMem->enc = enc; - -#ifndef SQLITE_OMIT_UTF16 - if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ - return SQLITE_NOMEM_BKPT; - } -#endif - - - return SQLITE_OK; -} - -/* -** Move data out of a btree key or data field and into a Mem structure. -** The data is payload from the entry that pCur is currently pointing -** to. offset and amt determine what portion of the data or key to retrieve. -** The result is written into the pMem element. -** -** The pMem object must have been initialized. This routine will use -** pMem->zMalloc to hold the content from the btree, if possible. New -** pMem->zMalloc space will be allocated if necessary. The calling routine -** is responsible for making sure that the pMem object is eventually -** destroyed. -** -** If this routine fails for any reason (malloc returns NULL or unable -** to read from the disk) then the pMem is left in an inconsistent state. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( - BtCursor *pCur, /* Cursor pointing at record to retrieve. */ - u32 offset, /* Offset from the start of data to return bytes from. */ - u32 amt, /* Number of bytes to return. */ - Mem *pMem /* OUT: Return data in this Mem structure. */ -){ - int rc; - pMem->flags = MEM_Null; - if( sqlite3BtreeMaxRecordSize(pCur)z); - if( rc==SQLITE_OK ){ - pMem->z[amt] = 0; /* Overrun area used when reading malformed records */ - pMem->flags = MEM_Blob; - pMem->n = (int)amt; - }else{ - sqlite3VdbeMemRelease(pMem); - } - } - return rc; -} -SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset( - BtCursor *pCur, /* Cursor pointing at record to retrieve. */ - u32 amt, /* Number of bytes to return. */ - Mem *pMem /* OUT: Return data in this Mem structure. */ -){ - u32 available = 0; /* Number of bytes available on the local btree page */ - int rc = SQLITE_OK; /* Return code */ - - assert( sqlite3BtreeCursorIsValid(pCur) ); - assert( !VdbeMemDynamic(pMem) ); - - /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() - ** that both the BtShared and database handle mutexes are held. */ - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available); - assert( pMem->z!=0 ); - - if( amt<=available ){ - pMem->flags = MEM_Blob|MEM_Ephem; - pMem->n = (int)amt; - }else{ - rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem); - } - - return rc; -} - -/* -** The pVal argument is known to be a value other than NULL. -** Convert it into a string with encoding enc and return a pointer -** to a zero-terminated version of that string. -*/ -static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ - assert( pVal!=0 ); - assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); - assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( !sqlite3VdbeMemIsRowSet(pVal) ); - assert( (pVal->flags & (MEM_Null))==0 ); - if( pVal->flags & (MEM_Blob|MEM_Str) ){ - if( ExpandBlob(pVal) ) return 0; - pVal->flags |= MEM_Str; - if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ - sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); - } - if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ - assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); - if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ - return 0; - } - } - sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ - }else{ - sqlite3VdbeMemStringify(pVal, enc, 0); - assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); - } - assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 - || pVal->db->mallocFailed ); - if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ - assert( sqlite3VdbeMemValidStrRep(pVal) ); - return pVal->z; - }else{ - return 0; - } -} - -/* This function is only available internally, it is not part of the -** external API. It works in a similar way to sqlite3_value_text(), -** except the data returned is in the encoding specified by the second -** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or -** SQLITE_UTF8. -** -** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED. -** If that is the case, then the result must be aligned on an even byte -** boundary. -*/ -SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ - if( !pVal ) return 0; - assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); - assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( !sqlite3VdbeMemIsRowSet(pVal) ); - if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ - assert( sqlite3VdbeMemValidStrRep(pVal) ); - return pVal->z; - } - if( pVal->flags&MEM_Null ){ - return 0; - } - return valueToText(pVal, enc); -} - -/* Return true if sqlit3_value object pVal is a string or blob value -** that uses the destructor specified in the second argument. -** -** TODO: Maybe someday promote this interface into a published API so -** that third-party extensions can get access to it? -*/ -SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value *pVal, void(*xFree)(void*)){ - if( ALWAYS(pVal!=0) - && ALWAYS((pVal->flags & (MEM_Str|MEM_Blob))!=0) - && (pVal->flags & MEM_Dyn)!=0 - && pVal->xDel==xFree - ){ - return 1; - }else{ - return 0; - } -} - -/* -** Create a new sqlite3_value object. -*/ -SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){ - Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p ){ - p->flags = MEM_Null; - p->db = db; - } - return p; -} - -/* -** Context object passed by sqlite3Stat4ProbeSetValue() through to -** valueNew(). See comments above valueNew() for details. -*/ -struct ValueNewStat4Ctx { - Parse *pParse; - Index *pIdx; - UnpackedRecord **ppRec; - int iVal; -}; - -/* -** Allocate and return a pointer to a new sqlite3_value object. If -** the second argument to this function is NULL, the object is allocated -** by calling sqlite3ValueNew(). -** -** Otherwise, if the second argument is non-zero, then this function is -** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not -** already been allocated, allocate the UnpackedRecord structure that -** that function will return to its caller here. Then return a pointer to -** an sqlite3_value within the UnpackedRecord.a[] array. -*/ -static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ -#ifdef SQLITE_ENABLE_STAT4 - if( p ){ - UnpackedRecord *pRec = p->ppRec[0]; - - if( pRec==0 ){ - Index *pIdx = p->pIdx; /* Index being probed */ - i64 nByte; /* Bytes of space to allocate */ - int i; /* Counter variable */ - int nCol = pIdx->nColumn; /* Number of index columns including rowid */ - - nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord)); - pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte); - if( pRec ){ - pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx); - if( pRec->pKeyInfo ){ - assert( pRec->pKeyInfo->nAllField==nCol ); - assert( pRec->pKeyInfo->enc==ENC(db) ); - pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); - for(i=0; iaMem[i].flags = MEM_Null; - pRec->aMem[i].db = db; - } - }else{ - sqlite3DbFreeNN(db, pRec); - pRec = 0; - } - } - if( pRec==0 ) return 0; - p->ppRec[0] = pRec; - } - - pRec->nField = p->iVal+1; - sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); - return &pRec->aMem[p->iVal]; - } -#else - UNUSED_PARAMETER(p); -#endif /* defined(SQLITE_ENABLE_STAT4) */ - return sqlite3ValueNew(db); -} - -/* -** The expression object indicated by the second argument is guaranteed -** to be a scalar SQL function. If -** -** * all function arguments are SQL literals, -** * one of the SQLITE_FUNC_CONSTANT or _SLOCHNG function flags is set, and -** * the SQLITE_FUNC_NEEDCOLL function flag is not set, -** -** then this routine attempts to invoke the SQL function. Assuming no -** error occurs, output parameter (*ppVal) is set to point to a value -** object containing the result before returning SQLITE_OK. -** -** Affinity aff is applied to the result of the function before returning. -** If the result is a text value, the sqlite3_value object uses encoding -** enc. -** -** If the conditions above are not met, this function returns SQLITE_OK -** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to -** NULL and an SQLite error code returned. -*/ -#ifdef SQLITE_ENABLE_STAT4 -static int valueFromFunction( - sqlite3 *db, /* The database connection */ - const Expr *p, /* The expression to evaluate */ - u8 enc, /* Encoding to use */ - u8 aff, /* Affinity to use */ - sqlite3_value **ppVal, /* Write the new value here */ - struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ -){ - sqlite3_context ctx; /* Context object for function invocation */ - sqlite3_value **apVal = 0; /* Function arguments */ - int nVal = 0; /* Number of function arguments */ - FuncDef *pFunc = 0; /* Function definition */ - sqlite3_value *pVal = 0; /* New value */ - int rc = SQLITE_OK; /* Return code */ - ExprList *pList = 0; /* Function arguments */ - int i; /* Iterator variable */ - - 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 = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pFunc==0 ) return SQLITE_OK; -#endif - assert( pFunc ); - if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 - ){ - return SQLITE_OK; - } - - if( pList ){ - apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); - if( apVal==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto value_from_function_out; - } - for(i=0; ipParse, pList->a[i].pExpr, aff, - &apVal[i]); - if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; - } - } - - pVal = valueNew(db, pCtx); - if( pVal==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto value_from_function_out; - } - - 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; - sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); - }else{ - sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); - assert( rc==SQLITE_OK ); - rc = sqlite3VdbeChangeEncoding(pVal, enc); - if( NEVER(rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal)) ){ - rc = SQLITE_TOOBIG; - pCtx->pParse->nErr++; - } - } - - value_from_function_out: - if( rc!=SQLITE_OK ){ - pVal = 0; - pCtx->pParse->rc = rc; - } - if( apVal ){ - for(i=0; iop)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; - if( op==TK_REGISTER ) op = pExpr->op2; - - /* Compressed expressions only appear when parsing the DEFAULT clause - ** on a table column definition, and hence only when pCtx==0. This - ** check ensures that an EP_TokenOnly expression is never passed down - ** into valueFromFunction(). */ - assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); - - if( op==TK_CAST ){ - u8 aff; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - aff = sqlite3AffinityType(pExpr->u.zToken,0); - rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); - testcase( rc!=SQLITE_OK ); - if( *ppVal ){ -#ifdef SQLITE_ENABLE_STAT4 - rc = ExpandBlob(*ppVal); -#else - /* zero-blobs only come from functions, not literal values. And - ** functions are only processed under STAT4 */ - assert( (ppVal[0][0].flags & MEM_Zero)==0 ); -#endif - sqlite3VdbeMemCast(*ppVal, aff, enc); - sqlite3ValueApplyAffinity(*ppVal, affinity, enc); - } - return rc; - } - - /* Handle negative integers in a single step. This is needed in the - ** case when the value is -9223372036854775808. Except - do not do this - ** for hexadecimal literals. */ - if( op==TK_UMINUS ){ - Expr *pLeft = pExpr->pLeft; - if( (pLeft->op==TK_INTEGER || pLeft->op==TK_FLOAT) ){ - if( ExprHasProperty(pLeft, EP_IntValue) - || pLeft->u.zToken[0]!='0' || (pLeft->u.zToken[1] & ~0x20)!='X' - ){ - pExpr = pLeft; - op = pExpr->op; - negInt = -1; - zNeg = "-"; - } - } - } - - if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - pVal = valueNew(db, pCtx); - if( pVal==0 ) goto no_mem; - if( ExprHasProperty(pExpr, EP_IntValue) ){ - sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); - }else{ - i64 iVal; - if( op==TK_INTEGER && 0==sqlite3DecOrHexToI64(pExpr->u.zToken, &iVal) ){ - sqlite3VdbeMemSetInt64(pVal, iVal*negInt); - }else{ - zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); - if( zVal==0 ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); - } - } - if( affinity==SQLITE_AFF_BLOB ){ - if( op==TK_FLOAT ){ - assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) ); - sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8); - pVal->flags = MEM_Real; - }else if( op==TK_INTEGER ){ - /* This case is required by -9223372036854775808 and other strings - ** that look like integers but cannot be handled by the - ** sqlite3DecOrHexToI64() call above. */ - sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); - } - }else{ - sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); - } - assert( (pVal->flags & MEM_IntReal)==0 ); - if( pVal->flags & (MEM_Int|MEM_IntReal|MEM_Real) ){ - testcase( pVal->flags & MEM_Int ); - testcase( pVal->flags & MEM_Real ); - pVal->flags &= ~MEM_Str; - } - if( enc!=SQLITE_UTF8 ){ - rc = sqlite3VdbeChangeEncoding(pVal, enc); - } - }else if( op==TK_UMINUS ) { - /* This branch happens for multiple negative signs. Ex: -(-5) */ - if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) - && pVal!=0 - ){ - sqlite3VdbeMemNumerify(pVal); - if( pVal->flags & MEM_Real ){ - pVal->u.r = -pVal->u.r; - }else if( pVal->u.i==SMALLEST_INT64 ){ -#ifndef SQLITE_OMIT_FLOATING_POINT - pVal->u.r = -(double)SMALLEST_INT64; -#else - pVal->u.r = LARGEST_INT64; -#endif - MemSetTypeFlag(pVal, MEM_Real); - }else{ - pVal->u.i = -pVal->u.i; - } - sqlite3ValueApplyAffinity(pVal, affinity, enc); - } - }else if( op==TK_NULL ){ - pVal = valueNew(db, pCtx); - if( pVal==0 ) goto no_mem; - sqlite3VdbeMemSetNull(pVal); - } -#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); - if( !pVal ) goto no_mem; - zVal = &pExpr->u.zToken[2]; - nVal = sqlite3Strlen30(zVal)-1; - assert( zVal[nVal]=='\'' ); - sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, - 0, SQLITE_DYNAMIC); - } -#endif -#ifdef SQLITE_ENABLE_STAT4 - else if( op==TK_FUNCTION && pCtx!=0 ){ - rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); - } -#endif - else if( op==TK_TRUEFALSE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pVal = valueNew(db, pCtx); - if( pVal ){ - pVal->flags = MEM_Int; - pVal->u.i = pExpr->u.zToken[4]==0; - sqlite3ValueApplyAffinity(pVal, affinity, enc); - } - } - - *ppVal = pVal; - return rc; - -no_mem: -#ifdef SQLITE_ENABLE_STAT4 - if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) ) -#endif - sqlite3OomFault(db); - sqlite3DbFree(db, zVal); - assert( *ppVal==0 ); -#ifdef SQLITE_ENABLE_STAT4 - if( pCtx==0 ) sqlite3ValueFree(pVal); -#else - assert( pCtx==0 ); sqlite3ValueFree(pVal); -#endif - return SQLITE_NOMEM_BKPT; -} - -/* -** Create a new sqlite3_value object, containing the value of pExpr. -** -** This only works for very simple expressions that consist of one constant -** token (i.e. "5", "5.1", "'a string'"). If the expression can -** be converted directly into a value, then the value is allocated and -** a pointer written to *ppVal. The caller is responsible for deallocating -** the value by passing it to sqlite3ValueFree() later on. If the expression -** cannot be converted to a value, then *ppVal is set to NULL. -*/ -SQLITE_PRIVATE int sqlite3ValueFromExpr( - sqlite3 *db, /* The database connection */ - const Expr *pExpr, /* The expression to evaluate */ - u8 enc, /* Encoding to use */ - u8 affinity, /* Affinity to use */ - sqlite3_value **ppVal /* Write the new value here */ -){ - return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; -} - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Attempt to extract a value from pExpr and use it to construct *ppVal. -** -** If pAlloc is not NULL, then an UnpackedRecord object is created for -** pAlloc if one does not exist and the new value is added to the -** UnpackedRecord object. -** -** A value is extracted in the following cases: -** -** * (pExpr==0). In this case the value is assumed to be an SQL NULL, -** -** * The expression is a bound variable, and this is a reprepare, or -** -** * The expression is a literal value. -** -** On success, *ppVal is made to point to the extracted value. The caller -** is responsible for ensuring that the value is eventually freed. -*/ -static int stat4ValueFromExpr( - Parse *pParse, /* Parse context */ - Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ - struct ValueNewStat4Ctx *pAlloc,/* How to allocate space. Or NULL */ - sqlite3_value **ppVal /* OUT: New value object (or NULL) */ -){ - int rc = SQLITE_OK; - sqlite3_value *pVal = 0; - sqlite3 *db = pParse->db; - - /* Skip over any TK_COLLATE nodes */ - pExpr = sqlite3ExprSkipCollate(pExpr); - - assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE ); - if( !pExpr ){ - pVal = valueNew(db, pAlloc); - if( pVal ){ - sqlite3VdbeMemSetNull((Mem*)pVal); - } - }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ - Vdbe *v; - int iBindVar = pExpr->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); - if( (v = pParse->pReprepare)!=0 ){ - pVal = valueNew(db, pAlloc); - if( pVal ){ - rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); - sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); - pVal->db = pParse->db; - } - } - }else{ - rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc); - } - - assert( pVal==0 || pVal->db==db ); - *ppVal = pVal; - return rc; -} - -/* -** This function is used to allocate and populate UnpackedRecord -** structures intended to be compared against sample index keys stored -** in the sqlite_stat4 table. -** -** A single call to this function populates zero or more fields of the -** record starting with field iVal (fields are numbered from left to -** right starting with 0). A single field is populated if: -** -** * (pExpr==0). In this case the value is assumed to be an SQL NULL, -** -** * The expression is a bound variable, and this is a reprepare, or -** -** * The sqlite3ValueFromExpr() function is able to extract a value -** from the expression (i.e. the expression is a literal value). -** -** Or, if pExpr is a TK_VECTOR, one field is populated for each of the -** vector components that match either of the two latter criteria listed -** above. -** -** Before any value is appended to the record, the affinity of the -** corresponding column within index pIdx is applied to it. Before -** this function returns, output parameter *pnExtract is set to the -** number of values appended to the record. -** -** When this function is called, *ppRec must either point to an object -** allocated by an earlier call to this function, or must be NULL. If it -** is NULL and a value can be successfully extracted, a new UnpackedRecord -** is allocated (and *ppRec set to point to it) before returning. -** -** Unless an error is encountered, SQLITE_OK is returned. It is not an -** error if a value cannot be extracted from pExpr. If an error does -** occur, an SQLite error code is returned. -*/ -SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( - Parse *pParse, /* Parse context */ - Index *pIdx, /* Index being probed */ - UnpackedRecord **ppRec, /* IN/OUT: Probe record */ - Expr *pExpr, /* The expression to extract a value from */ - int nElem, /* Maximum number of values to append */ - int iVal, /* Array element to populate */ - int *pnExtract /* OUT: Values appended to the record */ -){ - int rc = SQLITE_OK; - int nExtract = 0; - - if( pExpr==0 || pExpr->op!=TK_SELECT ){ - int i; - struct ValueNewStat4Ctx alloc; - - alloc.pParse = pParse; - alloc.pIdx = pIdx; - alloc.ppRec = ppRec; - - for(i=0; idb, pIdx, iVal+i); - alloc.iVal = iVal+i; - rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal); - if( !pVal ) break; - nExtract++; - } - } - - *pnExtract = nExtract; - return rc; -} - -/* -** Attempt to extract a value from expression pExpr using the methods -** as described for sqlite3Stat4ProbeSetValue() above. -** -** If successful, set *ppVal to point to a new value object and return -** SQLITE_OK. If no value can be extracted, but no other error occurs -** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error -** does occur, return an SQLite error code. The final value of *ppVal -** is undefined in this case. -*/ -SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr( - Parse *pParse, /* Parse context */ - Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ - sqlite3_value **ppVal /* OUT: New value object (or NULL) */ -){ - return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal); -} - -/* -** Extract the iCol-th column from the nRec-byte record in pRec. Write -** the column value into *ppVal. If *ppVal is initially NULL then a new -** sqlite3_value object is allocated. -** -** If *ppVal is initially NULL then the caller is responsible for -** ensuring that the value written into *ppVal is eventually freed. -*/ -SQLITE_PRIVATE int sqlite3Stat4Column( - sqlite3 *db, /* Database handle */ - const void *pRec, /* Pointer to buffer containing record */ - int nRec, /* Size of buffer pRec in bytes */ - int iCol, /* Column to extract */ - sqlite3_value **ppVal /* OUT: Extracted value */ -){ - u32 t = 0; /* a column type code */ - u32 nHdr; /* Size of the header in the record */ - u32 iHdr; /* Next unread header byte */ - i64 iField; /* Next unread data byte */ - u32 szField = 0; /* Size of the current data field */ - int i; /* Column index */ - u8 *a = (u8*)pRec; /* Typecast byte array */ - Mem *pMem = *ppVal; /* Write result into this Mem object */ - - assert( iCol>0 ); - iHdr = getVarint32(a, nHdr); - if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; - iField = nHdr; - for(i=0; i<=iCol; i++){ - iHdr += getVarint32(&a[iHdr], t); - testcase( iHdr==nHdr ); - testcase( iHdr==nHdr+1 ); - if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT; - szField = sqlite3VdbeSerialTypeLen(t); - iField += szField; - } - testcase( iField==nRec ); - testcase( iField==nRec+1 ); - if( iField>nRec ) return SQLITE_CORRUPT_BKPT; - if( pMem==0 ){ - pMem = *ppVal = sqlite3ValueNew(db); - if( pMem==0 ) return SQLITE_NOMEM_BKPT; - } - sqlite3VdbeSerialGet(&a[iField-szField], t, pMem); - pMem->enc = ENC(db); - return SQLITE_OK; -} - -/* -** Unless it is NULL, the argument must be an UnpackedRecord object returned -** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes -** the object. -*/ -SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ - if( pRec ){ - int i; - int nCol = pRec->pKeyInfo->nAllField; - Mem *aMem = pRec->aMem; - sqlite3 *db = aMem[0].db; - for(i=0; ipKeyInfo); - sqlite3DbFreeNN(db, pRec); - } -} -#endif /* ifdef SQLITE_ENABLE_STAT4 */ - -/* -** Change the string value of an sqlite3_value object -*/ -SQLITE_PRIVATE void sqlite3ValueSetStr( - sqlite3_value *v, /* Value to be set */ - int n, /* Length of string z */ - const void *z, /* Text of the new string */ - u8 enc, /* Encoding to use */ - void (*xDel)(void*) /* Destructor for the string */ -){ - if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); -} - -/* -** Free an sqlite3_value object -*/ -SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){ - if( !v ) return; - sqlite3VdbeMemRelease((Mem *)v); - sqlite3DbFreeNN(((Mem*)v)->db, v); -} - -/* -** The sqlite3ValueBytes() routine returns the number of bytes in the -** sqlite3_value object assuming that it uses the encoding "enc". -** The valueBytes() routine is a helper function. -*/ -static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){ - return valueToText(pVal, enc)!=0 ? pVal->n : 0; -} -SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ - Mem *p = (Mem*)pVal; - assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 ); - if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){ - return p->n; - } - if( (p->flags & MEM_Str)!=0 && enc!=SQLITE_UTF8 && pVal->enc!=SQLITE_UTF8 ){ - return p->n; - } - if( (p->flags & MEM_Blob)!=0 ){ - if( p->flags & MEM_Zero ){ - return p->n + p->u.nZero; - }else{ - return p->n; - } - } - if( p->flags & MEM_Null ) return 0; - return valueBytes(pVal, enc); -} - -/************** End of vdbemem.c *********************************************/ -/************** Begin file vdbeaux.c *****************************************/ -/* -** 2003 September 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used for creating, destroying, and populating -** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -/* Forward references */ -static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef); -static void vdbeFreeOpArray(sqlite3 *, Op *, int); - -/* -** Create a new virtual database engine. -*/ -SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ - sqlite3 *db = pParse->db; - Vdbe *p; - p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); - if( p==0 ) return 0; - memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); - p->db = db; - if( db->pVdbe ){ - db->pVdbe->ppVPrev = &p->pVNext; - } - p->pVNext = db->pVdbe; - p->ppVPrev = &db->pVdbe; - db->pVdbe = p; - assert( p->eVdbeState==VDBE_INIT_STATE ); - p->pParse = pParse; - pParse->pVdbe = p; - assert( pParse->aLabel==0 ); - assert( pParse->nLabel==0 ); - assert( p->nOpAlloc==0 ); - assert( pParse->szOpAlloc==0 ); - sqlite3VdbeAddOp2(p, OP_Init, 0, 1); - return p; -} - -/* -** Return the Parse object that owns a Vdbe object. -*/ -SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe *p){ - return p->pParse; -} - -/* -** Change the error string stored in Vdbe.zErrMsg -*/ -SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){ - va_list ap; - sqlite3DbFree(p->db, p->zErrMsg); - va_start(ap, zFormat); - p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap); - va_end(ap); -} - -/* -** Remember the SQL string for a prepared statement. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){ - if( p==0 ) return; - p->prepFlags = prepFlags; - if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ - p->expmask = 0; - } - assert( p->zSql==0 ); - p->zSql = sqlite3DbStrNDup(p->db, z, n); -} - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Add a new element to the Vdbe->pDblStr list. -*/ -SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){ - if( p ){ - int n = sqlite3Strlen30(z); - DblquoteStr *pStr = sqlite3DbMallocRawNN(db, - sizeof(*pStr)+n+1-sizeof(pStr->z)); - if( pStr ){ - pStr->pNextStr = p->pDblStr; - p->pDblStr = pStr; - memcpy(pStr->z, z, n+1); - } - } -} -#endif - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** zId of length nId is a double-quoted identifier. Check to see if -** that identifier is really used as a string literal. -*/ -SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString( - Vdbe *pVdbe, /* The prepared statement */ - const char *zId /* The double-quoted identifier, already dequoted */ -){ - DblquoteStr *pStr; - assert( zId!=0 ); - if( pVdbe->pDblStr==0 ) return 0; - for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){ - if( strcmp(zId, pStr->z)==0 ) return 1; - } - return 0; -} -#endif - -/* -** Swap byte-code between two VDBE structures. -** -** This happens after pB was previously run and returned -** SQLITE_SCHEMA. The statement was then reprepared in pA. -** This routine transfers the new bytecode in pA over to pB -** so that pB can be run again. The old pB byte code is -** moved back to pA so that it will be cleaned up when pA is -** finalized. -*/ -SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ - Vdbe tmp, *pTmp, **ppTmp; - char *zTmp; - assert( pA->db==pB->db ); - tmp = *pA; - *pA = *pB; - *pB = tmp; - pTmp = pA->pVNext; - pA->pVNext = pB->pVNext; - pB->pVNext = pTmp; - ppTmp = pA->ppVPrev; - pA->ppVPrev = pB->ppVPrev; - pB->ppVPrev = ppTmp; - zTmp = pA->zSql; - pA->zSql = pB->zSql; - pB->zSql = zTmp; -#ifdef SQLITE_ENABLE_NORMALIZE - zTmp = pA->zNormSql; - pA->zNormSql = pB->zNormSql; - pB->zNormSql = zTmp; -#endif - pB->expmask = pA->expmask; - pB->prepFlags = pA->prepFlags; - memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); - pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++; -} - -/* -** Resize the Vdbe.aOp array so that it is at least nOp elements larger -** than its current size. nOp is guaranteed to be less than or equal -** to 1024/sizeof(Op). -** -** If an out-of-memory error occurs while resizing the array, return -** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain -** unchanged (this is so that any opcodes already allocated can be -** correctly deallocated along with the rest of the Vdbe). -*/ -static int growOpArray(Vdbe *v, int nOp){ - VdbeOp *pNew; - Parse *p = v->pParse; - - /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force - ** more frequent reallocs and hence provide more opportunities for - ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used - ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array - ** by the minimum* amount required until the size reaches 512. Normal - ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current - ** size of the op array or add 1KB of space, whichever is smaller. */ -#ifdef SQLITE_TEST_REALLOC_STRESS - sqlite3_int64 nNew = (v->nOpAlloc>=512 ? 2*(sqlite3_int64)v->nOpAlloc - : (sqlite3_int64)v->nOpAlloc+nOp); -#else - sqlite3_int64 nNew = (v->nOpAlloc ? 2*(sqlite3_int64)v->nOpAlloc - : (sqlite3_int64)(1024/sizeof(Op))); - UNUSED_PARAMETER(nOp); -#endif - - /* Ensure that the size of a VDBE does not grow too large */ - if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){ - sqlite3OomFault(p->db); - return SQLITE_NOMEM; - } - - assert( nOp<=(int)(1024/sizeof(Op)) ); - assert( nNew>=(v->nOpAlloc+nOp) ); - pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); - if( pNew ){ - p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); - v->nOpAlloc = p->szOpAlloc/sizeof(Op); - v->aOp = pNew; - } - return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT); -} - -#ifdef SQLITE_DEBUG -/* This routine is just a convenient place to set a breakpoint that will -** fire after each opcode is inserted and displayed using -** "PRAGMA vdbe_addoptrace=on". Parameters "pc" (program counter) and -** pOp are available to make the breakpoint conditional. -** -** Other useful labels for breakpoints include: -** test_trace_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) -** sqlite3MisuseError(lineno) -** sqlite3CantopenError(lineno) -*/ -static void test_addop_breakpoint(int pc, Op *pOp){ - static u64 n = 0; - (void)pc; - (void)pOp; - n++; - if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */ -} -#endif - -/* -** Slow paths for sqlite3VdbeAddOp3() and sqlite3VdbeAddOp4Int() for the -** unusual case when we need to increase the size of the Vdbe.aOp[] array -** before adding the new opcode. -*/ -static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ - assert( p->nOpAlloc<=p->nOp ); - if( growOpArray(p, 1) ) return 1; - assert( p->nOpAlloc>p->nOp ); - return sqlite3VdbeAddOp3(p, op, p1, p2, p3); -} -static SQLITE_NOINLINE int addOp4IntSlow( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - if( p->db->mallocFailed==0 ){ - VdbeOp *pOp = &p->aOp[addr]; - pOp->p4type = P4_INT32; - pOp->p4.i = p4; - } - return addr; -} - - -/* -** Add a new instruction to the list of instructions current in the -** VDBE. Return the address of the new instruction. -** -** Parameters: -** -** p Pointer to the VDBE -** -** op The opcode for this instruction -** -** p1, p2, p3, p4 Operands -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ - return sqlite3VdbeAddOp3(p, op, 0, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ - return sqlite3VdbeAddOp3(p, op, p1, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ - return sqlite3VdbeAddOp3(p, op, p1, p2, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ - int i; - VdbeOp *pOp; - - i = p->nOp; - 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; - pOp->p2 = p2; - pOp->p3 = p3; - pOp->p4.p = 0; - pOp->p4type = P4_NOTUSED; - - /* Replicate this logic in sqlite3VdbeAddOp4Int() - ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOp->zComment = 0; -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - pOp->nExec = 0; - pOp->nCycle = 0; -#endif -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i, &p->aOp[i]); - test_addop_breakpoint(i, &p->aOp[i]); - } -#endif -#ifdef SQLITE_VDBE_COVERAGE - pOp->iSrcLine = 0; -#endif - /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ** Replicate in sqlite3VdbeAddOp4Int() */ - - return i; -} -SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int i; - VdbeOp *pOp; - - i = p->nOp; - if( p->nOpAlloc<=i ){ - return addOp4IntSlow(p, op, p1, p2, p3, p4); - } - p->nOp++; - pOp = &p->aOp[i]; - assert( pOp!=0 ); - pOp->opcode = (u8)op; - pOp->p5 = 0; - pOp->p1 = p1; - pOp->p2 = p2; - pOp->p3 = p3; - pOp->p4.i = p4; - pOp->p4type = P4_INT32; - - /* Replicate this logic in sqlite3VdbeAddOp3() - ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOp->zComment = 0; -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - pOp->nExec = 0; - pOp->nCycle = 0; -#endif -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i, &p->aOp[i]); - test_addop_breakpoint(i, &p->aOp[i]); - } -#endif -#ifdef SQLITE_VDBE_COVERAGE - pOp->iSrcLine = 0; -#endif - /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ** Replicate in sqlite3VdbeAddOp3() */ - - return i; -} - -/* Generate code for an unconditional jump to instruction iDest -*/ -SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe *p, int iDest){ - return sqlite3VdbeAddOp3(p, OP_Goto, 0, iDest, 0); -} - -/* Generate code to cause the string zStr to be loaded into -** register iDest -*/ -SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){ - return sqlite3VdbeAddOp4(p, OP_String8, 0, iDest, 0, zStr, 0); -} - -/* -** Generate code that initializes multiple registers to string or integer -** constants. The registers begin with iDest and increase consecutively. -** One register is initialized for each characgter in zTypes[]. For each -** "s" character in zTypes[], the register is a string if the argument is -** not NULL, or OP_Null if the value is a null pointer. For each "i" character -** in zTypes[], the register is initialized to an integer. -** -** If the input string does not end with "X" then an OP_ResultRow instruction -** is generated for the values inserted. -*/ -SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){ - va_list ap; - int i; - char c; - va_start(ap, zTypes); - for(i=0; (c = zTypes[i])!=0; i++){ - if( c=='s' ){ - const char *z = va_arg(ap, const char*); - sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest+i, 0, z, 0); - }else if( c=='i' ){ - sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest+i); - }else{ - goto skip_op_resultrow; - } - } - sqlite3VdbeAddOp2(p, OP_ResultRow, iDest, i); -skip_op_resultrow: - va_end(ap); -} - -/* -** Add an opcode that includes the p4 value as a pointer. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - const char *zP4, /* The P4 operand */ - int p4type /* P4 operand type */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - sqlite3VdbeChangeP4(p, addr, zP4, p4type); - return addr; -} - -/* -** Add an OP_Function or OP_PureFunc opcode. -** -** The eCallCtx argument is information (typically taken from Expr.op2) -** that describes the calling context of the function. 0 means a general -** function call. NC_IsCheck means called by a check constraint, -** NC_IdxExpr means called as part of an index expression. NC_PartIdx -** means in the WHERE clause of a partial index. NC_GenCol means called -** while computing a generated column value. 0 is the usual case. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall( - Parse *pParse, /* Parsing context */ - int p1, /* Constant argument mask */ - int p2, /* First argument register */ - int p3, /* Register into which results are written */ - int nArg, /* Number of argument */ - const FuncDef *pFunc, /* The function to be invoked */ - int eCallCtx /* Calling context */ -){ - Vdbe *v = pParse->pVdbe; - int addr; - sqlite3_context *pCtx; - assert( v ); - pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg)); - if( pCtx==0 ){ - assert( pParse->db->mallocFailed ); - freeEphemeralFunction(pParse->db, (FuncDef*)pFunc); - return 0; - } - pCtx->pOut = 0; - pCtx->pFunc = (FuncDef*)pFunc; - pCtx->pVdbe = 0; - pCtx->isError = 0; - pCtx->argc = nArg; - pCtx->iOp = sqlite3VdbeCurrentAddr(v); - addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, - p1, p2, p3, (char*)pCtx, P4_FUNCCTX); - sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); - sqlite3MayAbort(pParse); - return addr; -} - -/* -** Add an opcode that includes the p4 value with a P4_INT64 or -** P4_REAL type. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - const u8 *zP4, /* The P4 operand */ - int p4type /* P4 operand type */ -){ - char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); - if( p4copy ) memcpy(p4copy, zP4, 8); - return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Return the address of the current EXPLAIN QUERY PLAN baseline. -** 0 means "none". -*/ -SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){ - VdbeOp *pOp; - if( pParse->addrExplain==0 ) return 0; - pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); - return pOp->p2; -} - -/* -** Set a debugger breakpoint on the following routine in order to -** monitor the EXPLAIN QUERY PLAN code generation. -*/ -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){ - (void)z1; - (void)z2; -} -#endif - -/* -** Add a new OP_Explain opcode. -** -** If the bPush flag is true, then make this opcode the parent for -** subsequent Explains until sqlite3VdbeExplainPop() is called. -*/ -SQLITE_PRIVATE int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ - int addr = 0; -#if !defined(SQLITE_DEBUG) - /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined. - ** But omit them (for performance) during production builds */ - if( pParse->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) -#endif - { - char *zMsg; - Vdbe *v; - va_list ap; - int iThis; - va_start(ap, zFmt); - zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); - va_end(ap); - v = pParse->pVdbe; - iThis = v->nOp; - addr = sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, - zMsg, P4_DYNAMIC); - sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetLastOp(v)->p4.z); - if( bPush){ - pParse->addrExplain = iThis; - } - sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0); - } - return addr; -} - -/* -** Pop the EXPLAIN QUERY PLAN stack one level. -*/ -SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){ - sqlite3ExplainBreakpoint("POP", 0); - pParse->addrExplain = sqlite3VdbeExplainParent(pParse); -} -#endif /* SQLITE_OMIT_EXPLAIN */ - -/* -** Add an OP_ParseSchema opcode. This routine is broken out from -** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees -** as having been used. -** -** The zWhere string must have been obtained from sqlite3_malloc(). -** This routine will take ownership of the allocated memory. -*/ -SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){ - int j; - sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); - sqlite3VdbeChangeP5(p, p5); - for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j); - sqlite3MayAbort(p->pParse); -} - -/* Insert the end of a co-routine -*/ -SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); - - /* Clear the temporary register cache, thereby ensuring that each - ** co-routine has its own independent set of registers, because co-routines - ** might expect their registers to be preserved across an OP_Yield, and - ** that could cause problems if two or more co-routines are using the same - ** temporary register. - */ - v->pParse->nTempReg = 0; - v->pParse->nRangeReg = 0; -} - -/* -** Create a new symbolic label for an instruction that has yet to be -** coded. The symbolic label is really just a negative number. The -** label can be used as the P2 value of an operation. Later, when -** the label is resolved to a specific address, the VDBE will scan -** through its operation list and change all values of P2 which match -** the label into the resolved address. -** -** The VDBE knows that a P2 value is a label because labels are -** always negative and P2 values are suppose to be non-negative. -** Hence, a negative P2 value is a label that has yet to be resolved. -** (Later:) This is only true for opcodes that have the OPFLG_JUMP -** property. -** -** Variable usage notes: -** -** Parse.aLabel[x] Stores the address that the x-th label resolves -** into. For testing (SQLITE_DEBUG), unresolved -** labels stores -1, but that is not required. -** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[] -** Parse.nLabel The *negative* of the number of labels that have -** been issued. The negative is stored because -** that gives a performance improvement over storing -** the equivalent positive value. -*/ -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse *pParse){ - return --pParse->nLabel; -} - -/* -** Resolve label "x" to be the address of the next instruction to -** be inserted. The parameter "x" must have been obtained from -** a prior call to sqlite3VdbeMakeLabel(). -*/ -static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ - int nNewSize = 10 - p->nLabel; - p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, - nNewSize*sizeof(p->aLabel[0])); - if( p->aLabel==0 ){ - p->nLabelAlloc = 0; - }else{ -#ifdef SQLITE_DEBUG - int i; - for(i=p->nLabelAlloc; iaLabel[i] = -1; -#endif - if( nNewSize>=100 && (nNewSize/100)>(p->nLabelAlloc/100) ){ - sqlite3ProgressCheck(p); - } - p->nLabelAlloc = nNewSize; - p->aLabel[j] = v->nOp; - } -} -SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ - Parse *p = v->pParse; - int j = ADDR(x); - assert( v->eVdbeState==VDBE_INIT_STATE ); - assert( j<-p->nLabel ); - assert( j>=0 ); -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - printf("RESOLVE LABEL %d to %d\n", x, v->nOp); - } -#endif - if( p->nLabelAlloc + p->nLabel < 0 ){ - resizeResolveLabel(p,v,j); - }else{ - assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */ - p->aLabel[j] = v->nOp; - } -} - -/* -** Mark the VDBE as one that can only be run one time. -*/ -SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ - sqlite3VdbeAddOp2(p, OP_Expire, 1, 1); -} - -/* -** Mark the VDBE as one that can be run multiple times. -*/ -SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe *p){ - int i; - for(i=1; ALWAYS(inOp); i++){ - if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){ - p->aOp[1].opcode = OP_Noop; - break; - } - } -} - -#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ - -/* -** The following type and function are used to iterate through all opcodes -** in a Vdbe main program and each of the sub-programs (triggers) it may -** invoke directly or indirectly. It should be used as follows: -** -** Op *pOp; -** VdbeOpIter sIter; -** -** memset(&sIter, 0, sizeof(sIter)); -** sIter.v = v; // v is of type Vdbe* -** while( (pOp = opIterNext(&sIter)) ){ -** // Do something with pOp -** } -** sqlite3DbFree(v->db, sIter.apSub); -** -*/ -typedef struct VdbeOpIter VdbeOpIter; -struct VdbeOpIter { - Vdbe *v; /* Vdbe to iterate through the opcodes of */ - SubProgram **apSub; /* Array of subprograms */ - int nSub; /* Number of entries in apSub */ - int iAddr; /* Address of next instruction to return */ - int iSub; /* 0 = main program, 1 = first sub-program etc. */ -}; -static Op *opIterNext(VdbeOpIter *p){ - Vdbe *v = p->v; - Op *pRet = 0; - Op *aOp; - int nOp; - - if( p->iSub<=p->nSub ){ - - if( p->iSub==0 ){ - aOp = v->aOp; - nOp = v->nOp; - }else{ - aOp = p->apSub[p->iSub-1]->aOp; - nOp = p->apSub[p->iSub-1]->nOp; - } - assert( p->iAddriAddr]; - p->iAddr++; - if( p->iAddr==nOp ){ - p->iSub++; - p->iAddr = 0; - } - - if( pRet->p4type==P4_SUBPROGRAM ){ - i64 nByte = (1+(u64)p->nSub)*sizeof(SubProgram*); - int j; - for(j=0; jnSub; j++){ - if( p->apSub[j]==pRet->p4.pProgram ) break; - } - if( j==p->nSub ){ - p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte); - if( !p->apSub ){ - pRet = 0; - }else{ - p->apSub[p->nSub++] = pRet->p4.pProgram; - } - } - } - } - - return pRet; -} - -/* -** Check if the program stored in the VM associated with pParse may -** throw an ABORT exception (causing the statement, but not entire transaction -** to be rolled back). This condition is true if the main program or any -** sub-programs contains any of the following: -** -** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. -** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. -** * OP_Destroy -** * OP_VUpdate -** * OP_VCreate -** * OP_VRename -** * OP_FkCounter with P2==0 (immediate foreign key constraint) -** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine -** (for CREATE TABLE AS SELECT ...) -** -** Then check that the value of Parse.mayAbort is true if an -** ABORT may be thrown, or false otherwise. Return true if it does -** match, or false otherwise. This function is intended to be used as -** part of an assert statement in the compiler. Similar to: -** -** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); -*/ -SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ - int hasAbort = 0; - int hasFkCounter = 0; - int hasCreateTable = 0; - int hasCreateIndex = 0; - int hasInitCoroutine = 0; - Op *pOp; - VdbeOpIter sIter; - - if( v==0 ) return 0; - memset(&sIter, 0, sizeof(sIter)); - sIter.v = v; - - while( (pOp = opIterNext(&sIter))!=0 ){ - int opcode = pOp->opcode; - if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename - || 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)) - ){ - hasAbort = 1; - break; - } - if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; - if( mayAbort ){ - /* hasCreateIndex may also be set for some DELETE statements that use - ** OP_Clear. So this routine may end up returning true in the case - ** where a "DELETE FROM tbl" has a statement-journal but does not - ** require one. This is not so bad - it is an inefficiency, not a bug. */ - if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1; - if( opcode==OP_Clear ) hasCreateIndex = 1; - } - if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ - hasFkCounter = 1; - } -#endif - } - sqlite3DbFree(v->db, sIter.apSub); - - /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. - ** If malloc failed, then the while() loop above may not have iterated - ** through all opcodes and hasAbort may be set incorrectly. Return - ** true for this case to prevent the assert() in the callers frame - ** from failing. */ - return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter - || (hasCreateTable && hasInitCoroutine) || hasCreateIndex - ); -} -#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ - -#ifdef SQLITE_DEBUG -/* -** Increment the nWrite counter in the VDBE if the cursor is not an -** ephemeral cursor, or if the cursor argument is NULL. -*/ -SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){ - if( pC==0 - || (pC->eCurType!=CURTYPE_SORTER - && pC->eCurType!=CURTYPE_PSEUDO - && !pC->isEphemeral) - ){ - p->nWrite++; - } -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Assert if an Abort at this point in time might result in a corrupt -** database. -*/ -SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ - assert( p->nWrite==0 || p->usesStmtJournal ); -} -#endif - -/* -** This routine is called after all opcodes have been inserted. It loops -** through all the opcodes and fixes up some details. -** -** (1) For each jump instruction with a negative P2 value (a label) -** resolve the P2 value to an actual address. -** -** (2) Compute the maximum number of arguments used by the xUpdate/xFilter -** methods of any virtual table and store that value in *pMaxVtabArgs. -** -** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately -** indicate what the prepared statement actually does. -** -** (4) (discontinued) -** -** (5) Reclaim the memory allocated for storing labels. -** -** This routine will only function correctly if the mkopcodeh.tcl generator -** script numbers the opcodes correctly. Changes to this routine must be -** coordinated with changes to mkopcodeh.tcl. -*/ -static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){ - int nMaxVtabArgs = *pMaxVtabArgs; - Op *pOp; - Parse *pParse = p->pParse; - int *aLabel = pParse->aLabel; - - assert( pParse->db->mallocFailed==0 ); /* tag-20230419-1 */ - p->readOnly = 1; - p->bIsReader = 0; - pOp = &p->aOp[p->nOp-1]; - assert( p->aOp[0].opcode==OP_Init ); - while( 1 /* Loop terminates when it reaches the OP_Init opcode */ ){ - /* Only JUMP opcodes and the short list of special opcodes in the switch - ** below need to be considered. The mkopcodeh.tcl generator script groups - ** all these opcodes together near the front of the opcode list. Skip - ** any opcode that does not need processing by virtual of the fact that - ** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization. - */ - if( pOp->opcode<=SQLITE_MX_JUMP_OPCODE ){ - /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing - ** cases from this switch! */ - switch( pOp->opcode ){ - case OP_Transaction: { - if( pOp->p2!=0 ) p->readOnly = 0; - /* no break */ deliberate_fall_through - } - case OP_AutoCommit: - case OP_Savepoint: { - p->bIsReader = 1; - break; - } -#ifndef SQLITE_OMIT_WAL - case OP_Checkpoint: -#endif - case OP_Vacuum: - case OP_JournalMode: { - p->readOnly = 0; - p->bIsReader = 1; - break; - } - case OP_Init: { - assert( pOp->p2>=0 ); - goto resolve_p2_values_loop_exit; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - case OP_VUpdate: { - if( pOp->p2>nMaxVtabArgs ) nMaxVtabArgs = pOp->p2; - break; - } - case OP_VFilter: { - int n; - /* The instruction immediately prior to VFilter will be an - ** OP_Integer that sets the "argc" value for the VFilter. See - ** the code where OP_VFilter is generated at tag-20250207a. */ - assert( (pOp - p->aOp) >= 3 ); - assert( pOp[-1].opcode==OP_Integer ); - assert( pOp[-1].p2==pOp->p3+1 ); - n = pOp[-1].p1; - if( n>nMaxVtabArgs ) nMaxVtabArgs = n; - /* Fall through into the default case */ - /* no break */ deliberate_fall_through - } -#endif - default: { - if( pOp->p2<0 ){ - /* The mkopcodeh.tcl script has so arranged things that the only - ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to - ** have non-negative values for P2. */ - assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); - assert( ADDR(pOp->p2)<-pParse->nLabel ); - assert( aLabel!=0 ); /* True because of tag-20230419-1 */ - pOp->p2 = aLabel[ADDR(pOp->p2)]; - } - - /* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes - ** might */ - assert( pOp->p2>0 - || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP0)!=0 ); - - /* Jumps never go off the end of the bytecode array */ - assert( pOp->p2nOp - || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)==0 ); - break; - } - } - /* The mkopcodeh.tcl script has so arranged things that the only - ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to - ** have non-negative values for P2. */ - assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0); - } - assert( pOp>p->aOp ); - pOp--; - } -resolve_p2_values_loop_exit: - if( aLabel ){ - sqlite3DbNNFreeNN(p->db, pParse->aLabel); - pParse->aLabel = 0; - } - pParse->nLabel = 0; - *pMaxVtabArgs = nMaxVtabArgs; - 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 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; - sqlite3_str *pErr = 0; - assert( v!=0 ); - pParse = v->pParse; - assert( pParse!=0 ); - if( pParse->nErr ) return; - assert( iLast>=iFirst ); - assert( iLastnOp ); - pOp = &v->aOp[iFirst]; - for(i=iFirst; i<=iLast; i++, pOp++){ - if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){ - int iDest = pOp->p2; /* Jump destination */ - if( iDest==0 ) continue; - if( pOp->opcode==OP_Gosub ) continue; - if( pOp->p3==20230325 && pOp->opcode==OP_NotNull ){ - /* This is a deliberately taken illegal branch. tag-20230325-2 */ - 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( iDestiLast ){ - int j = iDest; - for(; jnOp; 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 = sqlite3_str_new(0); - }else{ - sqlite3_str_appendchar(pErr, 1, '\n'); - } - 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 = sqlite3_str_finish(pErr); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0); - sqlite3_free(zErr); - sqlite3MayAbort(pParse); - } -} -#endif /* SQLITE_DEBUG */ - -/* -** Return the address of the next instruction to be inserted. -*/ -SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ - assert( p->eVdbeState==VDBE_INIT_STATE ); - return p->nOp; -} - -/* -** Verify that at least N opcode slots are available in p without -** having to malloc for more space (except when compiled using -** SQLITE_TEST_REALLOC_STRESS). This interface is used during testing -** to verify that certain calls to sqlite3VdbeAddOpList() can never -** fail due to a OOM fault and hence that the return value from -** sqlite3VdbeAddOpList() will always be non-NULL. -*/ -#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) -SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){ - assert( p->nOp + N <= p->nOpAlloc ); -} -#endif - -/* -** Verify that the VM passed as the only argument does not contain -** an OP_ResultRow opcode. Fail an assert() if it does. This is used -** by code in pragma.c to ensure that the implementation of certain -** pragmas comports with the flags specified in the mkpragmatab.tcl -** script. -*/ -#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) -SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){ - int i; - for(i=0; inOp; i++){ - assert( p->aOp[i].opcode!=OP_ResultRow ); - } -} -#endif - -/* -** Generate code (a single OP_Abortable opcode) that will -** verify that the VDBE program can safely call Abort in the current -** context. -*/ -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){ - if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable); -} -#endif - -/* -** This function returns a pointer to the array of opcodes associated with -** the Vdbe passed as the first argument. It is the callers responsibility -** to arrange for the returned array to be eventually freed using the -** vdbeFreeOpArray() function. -** -** Before returning, *pnOp is set to the number of entries in the returned -** array. Also, *pnMaxArg is set to the larger of its current value and -** the number of entries in the Vdbe.apArg[] array required to execute the -** returned program. -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ - VdbeOp *aOp = p->aOp; - assert( aOp && !p->db->mallocFailed ); - - /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ - assert( DbMaskAllZero(p->btreeMask) ); - - resolveP2Values(p, pnMaxArg); - *pnOp = p->nOp; - p->aOp = 0; - return aOp; -} - -/* -** Add a whole list of operations to the operation stack. Return a -** pointer to the first operation inserted. -** -** Non-zero P2 arguments to jump instructions are automatically adjusted -** so that the jump target is relative to the first operation inserted. -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( - Vdbe *p, /* Add opcodes to the prepared statement */ - int nOp, /* Number of opcodes to add */ - VdbeOpList const *aOp, /* The opcodes to be added */ - int iLineno /* Source-file line number of first opcode */ -){ - int i; - VdbeOp *pOut, *pFirst; - assert( nOp>0 ); - assert( p->eVdbeState==VDBE_INIT_STATE ); - if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){ - return 0; - } - pFirst = pOut = &p->aOp[p->nOp]; - for(i=0; iopcode = aOp->opcode; - pOut->p1 = aOp->p1; - pOut->p2 = aOp->p2; - assert( aOp->p2>=0 ); - if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){ - pOut->p2 += p->nOp; - } - pOut->p3 = aOp->p3; - pOut->p4type = P4_NOTUSED; - pOut->p4.p = 0; - pOut->p5 = 0; -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOut->zComment = 0; -#endif -#ifdef SQLITE_VDBE_COVERAGE - pOut->iSrcLine = iLineno+i; -#else - (void)iLineno; -#endif -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i+p->nOp, &p->aOp[i+p->nOp]); - } -#endif - } - p->nOp += nOp; - return pFirst; -} - -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) -/* -** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). -*/ -SQLITE_PRIVATE void sqlite3VdbeScanStatus( - Vdbe *p, /* VM to add scanstatus() to */ - int addrExplain, /* Address of OP_Explain (or 0) */ - int addrLoop, /* Address of loop counter */ - int addrVisit, /* Address of rows visited counter */ - LogEst nEst, /* Estimated number of output rows */ - const char *zName /* Name of table or index being scanned */ -){ - if( IS_STMT_SCANSTATUS(p->db) ){ - i64 nByte = (1+(i64)p->nScan) * sizeof(ScanStatus); - ScanStatus *aNew; - aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); - if( aNew ){ - ScanStatus *pNew = &aNew[p->nScan++]; - memset(pNew, 0, sizeof(ScanStatus)); - pNew->addrExplain = addrExplain; - pNew->addrLoop = addrLoop; - pNew->addrVisit = addrVisit; - pNew->nEst = nEst; - pNew->zName = sqlite3DbStrDup(p->db, zName); - p->aScan = aNew; - } - } -} - -/* -** Add the range of instructions from addrStart to addrEnd (inclusive) to -** the set of those corresponding to the sqlite3_stmt_scanstatus() counters -** associated with the OP_Explain instruction at addrExplain. The -** sum of the sqlite3Hwtime() values for each of these instructions -** will be returned for SQLITE_SCANSTAT_NCYCLE requests. -*/ -SQLITE_PRIVATE void sqlite3VdbeScanStatusRange( - Vdbe *p, - int addrExplain, - int addrStart, - int addrEnd -){ - if( IS_STMT_SCANSTATUS(p->db) ){ - ScanStatus *pScan = 0; - int ii; - for(ii=p->nScan-1; ii>=0; ii--){ - pScan = &p->aScan[ii]; - if( pScan->addrExplain==addrExplain ) break; - pScan = 0; - } - if( pScan ){ - if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1; - for(ii=0; iiaAddrRange); ii+=2){ - if( pScan->aAddrRange[ii]==0 ){ - pScan->aAddrRange[ii] = addrStart; - pScan->aAddrRange[ii+1] = addrEnd; - break; - } - } - } - } -} - -/* -** Set the addresses for the SQLITE_SCANSTAT_NLOOP and SQLITE_SCANSTAT_NROW -** counters for the query element associated with the OP_Explain at -** addrExplain. -*/ -SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters( - Vdbe *p, - int addrExplain, - int addrLoop, - int addrVisit -){ - if( IS_STMT_SCANSTATUS(p->db) ){ - ScanStatus *pScan = 0; - int ii; - for(ii=p->nScan-1; ii>=0; ii--){ - pScan = &p->aScan[ii]; - if( pScan->addrExplain==addrExplain ) break; - pScan = 0; - } - if( pScan ){ - if( addrLoop>0 ) pScan->addrLoop = addrLoop; - if( addrVisit>0 ) pScan->addrVisit = addrVisit; - } - } -} -#endif /* defined(SQLITE_ENABLE_STMT_SCANSTATUS) */ - - -/* -** Change the value of the opcode, or P1, P2, P3, or P5 operands -** for a specific instruction. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){ - assert( addr>=0 ); - sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode; -} -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ - assert( addr>=0 ); - sqlite3VdbeGetOp(p,addr)->p1 = val; -} -SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ - assert( addr>=0 || p->db->mallocFailed ); - sqlite3VdbeGetOp(p,addr)->p2 = val; -} -SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ - assert( addr>=0 ); - sqlite3VdbeGetOp(p,addr)->p3 = val; -} -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ - assert( p->nOp>0 || p->db->mallocFailed ); - if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; -} - -/* -** If the previous opcode is an OP_Column that delivers results -** into register iDest, then add the OPFLAG_TYPEOFARG flag to that -** opcode. -*/ -SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){ - VdbeOp *pOp = sqlite3VdbeGetLastOp(p); -#ifdef SQLITE_DEBUG - while( pOp->opcode==OP_ReleaseReg ) pOp--; -#endif - if( pOp->p3==iDest && pOp->opcode==OP_Column ){ - pOp->p5 |= OPFLAG_TYPEOFARG; - } -} - -/* -** Change the P2 operand of instruction addr so that it points to -** the address of the next instruction to be coded. -*/ -SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - sqlite3VdbeChangeP2(p, addr, p->nOp); -} - -/* -** Change the P2 operand of the jump instruction at addr so that -** the jump lands on the next opcode. Or if the jump instruction was -** the previous opcode (and is thus a no-op) then simply back up -** the next instruction counter by one slot so that the jump is -** overwritten by the next inserted opcode. -** -** This routine is an optimization of sqlite3VdbeJumpHere() that -** strives to omit useless byte-code like this: -** -** 7 Once 0 8 0 -** 8 ... -*/ -SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ - if( addr==p->nOp-1 ){ - assert( p->aOp[addr].opcode==OP_Once - || p->aOp[addr].opcode==OP_If - || p->aOp[addr].opcode==OP_FkIfZero ); - assert( p->aOp[addr].p4type==0 ); -#ifdef SQLITE_VDBE_COVERAGE - sqlite3VdbeGetLastOp(p)->iSrcLine = 0; /* Erase VdbeCoverage() macros */ -#endif - p->nOp--; - }else{ - sqlite3VdbeChangeP2(p, addr, p->nOp); - } -} - - -/* -** If the input FuncDef structure is ephemeral, then free it. If -** the FuncDef is not ephemeral, then do nothing. -*/ -static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - assert( db!=0 ); - if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ - sqlite3DbNNFreeNN(db, pDef); - } -} - -/* -** Delete a P4 value if necessary. -*/ -static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){ - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); - sqlite3DbNNFreeNN(db, p); -} -static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){ - assert( db!=0 ); - freeEphemeralFunction(db, p->pFunc); - sqlite3DbNNFreeNN(db, p); -} -static void freeP4(sqlite3 *db, int p4type, void *p4){ - assert( db ); - switch( p4type ){ - case P4_FUNCCTX: { - freeP4FuncCtx(db, (sqlite3_context*)p4); - break; - } - case P4_REAL: - case P4_INT64: - case P4_DYNAMIC: - case P4_INTARRAY: { - if( p4 ) sqlite3DbNNFreeNN(db, p4); - break; - } - case P4_KEYINFO: { - if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); - break; - } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - case P4_EXPR: { - sqlite3ExprDelete(db, (Expr*)p4); - break; - } -#endif - case P4_FUNCDEF: { - freeEphemeralFunction(db, (FuncDef*)p4); - break; - } - case P4_MEM: { - if( db->pnBytesFreed==0 ){ - sqlite3ValueFree((sqlite3_value*)p4); - }else{ - freeP4Mem(db, (Mem*)p4); - } - break; - } - case P4_VTAB : { - if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); - break; - } - case P4_TABLEREF: { - if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4); - break; - } - case P4_SUBRTNSIG: { - SubrtnSig *pSig = (SubrtnSig*)p4; - sqlite3DbFree(db, pSig->zAff); - sqlite3DbFree(db, pSig); - break; - } - } -} - -/* -** Free the space allocated for aOp and any p4 values allocated for the -** opcodes contained within. If aOp is not NULL it is assumed to contain -** nOp entries. -*/ -static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ - assert( nOp>=0 ); - assert( db!=0 ); - if( aOp ){ - 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 - sqlite3DbFree(db, pOp->zComment); -#endif - if( pOp==aOp ) break; - pOp--; - } - sqlite3DbNNFreeNN(db, aOp); - } -} - -/* -** Link the SubProgram object passed as the second argument into the linked -** list at Vdbe.pSubProgram. This list is used to delete all sub-program -** objects when the VM is no longer required. -*/ -SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ - p->pNext = pVdbe->pProgram; - pVdbe->pProgram = p; -} - -/* -** Return true if the given Vdbe has any SubPrograms. -*/ -SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){ - return pVdbe->pProgram!=0; -} - -/* -** Change the opcode at addr into OP_Noop -*/ -SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ - VdbeOp *pOp; - if( p->db->mallocFailed ) return 0; - assert( addr>=0 && addrnOp ); - pOp = &p->aOp[addr]; - freeP4(p->db, pOp->p4type, pOp->p4.p); - pOp->p4type = P4_NOTUSED; - pOp->p4.z = 0; - pOp->opcode = OP_Noop; - return 1; -} - -/* -** If the last opcode is "op" and it is not a jump destination, -** then remove it. Return true if and only if an opcode was removed. -*/ -SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ - if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){ - return sqlite3VdbeChangeToNoop(p, p->nOp-1); - }else{ - return 0; - } -} - -#ifdef SQLITE_DEBUG -/* -** Generate an OP_ReleaseReg opcode to indicate that a range of -** registers, except any identified by mask, are no longer in use. -*/ -SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( - Parse *pParse, /* Parsing context */ - int iFirst, /* Index of first register to be released */ - int N, /* Number of registers to release */ - u32 mask, /* Mask of registers to NOT release */ - int bUndefine /* If true, mark registers as undefined */ -){ - if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return; - assert( pParse->pVdbe ); - assert( iFirst>=1 ); - assert( iFirst+N-1<=pParse->nMem ); - if( N<=31 && mask!=0 ){ - while( N>0 && (mask&1)!=0 ){ - mask >>= 1; - iFirst++; - N--; - } - while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){ - mask &= ~MASKBIT32(N-1); - N--; - } - } - if( N>0 ){ - sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask); - if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1); - } -} -#endif /* SQLITE_DEBUG */ - -/* -** Change the value of the P4 operand for a specific instruction. -** This routine is useful when a large program is loaded from a -** static array using sqlite3VdbeAddOpList but we want to make a -** few minor changes to the program. -** -** If n>=0 then the P4 operand is dynamic, meaning that a copy of -** the string is made into memory obtained from sqlite3_malloc(). -** A value of n==0 means copy bytes of zP4 up to and including the -** first null byte. If n>0 then copy n+1 bytes of zP4. -** -** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points -** to a string or structure that is guaranteed to exist for the lifetime of -** the Vdbe. In these cases we can just copy the pointer. -** -** If addr<0 then change P4 on the most recently inserted instruction. -*/ -static void SQLITE_NOINLINE vdbeChangeP4Full( - Vdbe *p, - Op *pOp, - const char *zP4, - int n -){ - if( pOp->p4type ){ - assert( pOp->p4type > P4_FREE_IF_LE ); - pOp->p4type = 0; - pOp->p4.p = 0; - } - if( n<0 ){ - sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n); - }else{ - if( n==0 ) n = sqlite3Strlen30(zP4); - pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n); - pOp->p4type = P4_DYNAMIC; - } -} -SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ - Op *pOp; - sqlite3 *db; - assert( p!=0 ); - db = p->db; - 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); - return; - } - assert( p->nOp>0 ); - assert( addrnOp ); - if( addr<0 ){ - addr = p->nOp - 1; - } - pOp = &p->aOp[addr]; - if( n>=0 || pOp->p4type ){ - vdbeChangeP4Full(p, pOp, zP4, n); - return; - } - if( n==P4_INT32 ){ - /* Note: this cast is safe, because the origin data point was an int - ** that was cast to a (const char *). */ - pOp->p4.i = SQLITE_PTR_TO_INT(zP4); - pOp->p4type = P4_INT32; - }else if( zP4!=0 ){ - assert( n<0 ); - pOp->p4.p = (void*)zP4; - pOp->p4type = (signed char)n; - if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4); - } -} - -/* -** Change the P4 operand of the most recently coded instruction -** to the value defined by the arguments. This is a high-speed -** version of sqlite3VdbeChangeP4(). -** -** The P4 operand must not have been previously defined. And the new -** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of -** those cases. -*/ -SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){ - VdbeOp *pOp; - assert( n!=P4_INT32 && n!=P4_VTAB ); - assert( n<=0 ); - if( p->db->mallocFailed ){ - freeP4(p->db, n, pP4); - }else{ - assert( pP4!=0 || n==P4_DYNAMIC ); - assert( p->nOp>0 ); - pOp = &p->aOp[p->nOp-1]; - assert( pOp->p4type==P4_NOTUSED ); - pOp->p4type = n; - pOp->p4.p = pP4; - } -} - -/* -** Set the P4 on the most recently added opcode to the KeyInfo for the -** index given. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){ - Vdbe *v = pParse->pVdbe; - KeyInfo *pKeyInfo; - assert( v!=0 ); - assert( pIdx!=0 ); - pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx); - if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); -} - -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS -/* -** Change the comment on the most recently coded instruction. Or -** insert a No-op and add the comment to that new instruction. This -** makes the code easier to read during debugging. None of this happens -** in a production build. -*/ -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->pParse->nErr>0 ); - if( p->nOp ){ - assert( p->aOp ); - sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); - p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); - } -} -SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ - va_list ap; - if( p ){ - va_start(ap, zFormat); - vdbeVComment(p, zFormat, ap); - va_end(ap); - } -} -SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ - va_list ap; - if( p ){ - sqlite3VdbeAddOp0(p, OP_Noop); - va_start(ap, zFormat); - vdbeVComment(p, zFormat, ap); - va_end(ap); - } -} -#endif /* NDEBUG */ - -#ifdef SQLITE_VDBE_COVERAGE -/* -** Set the value if the iSrcLine field for the previously coded instruction. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ - sqlite3VdbeGetLastOp(v)->iSrcLine = iLine; -} -#endif /* SQLITE_VDBE_COVERAGE */ - -/* -** Return the opcode for a given address. The address must be non-negative. -** See sqlite3VdbeGetLastOp() to get the most recently added opcode. -** -** If a memory allocation error has occurred prior to the calling of this -** routine, then a pointer to a dummy VdbeOp will be returned. That opcode -** is readable but not writable, though it is cast to a writable value. -** The return of a dummy opcode allows the call to continue functioning -** after an OOM fault without having to check to see if the return from -** this routine is a valid pointer. But because the dummy.opcode is 0, -** dummy will never be written to. This is verified by code inspection and -** by running with Valgrind. -*/ -SQLITE_PRIVATE VdbeOp *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->eVdbeState==VDBE_INIT_STATE ); - assert( (addr>=0 && addrnOp) || p->db->mallocFailed ); - if( p->db->mallocFailed ){ - return (VdbeOp*)&dummy; - }else{ - return &p->aOp[addr]; - } -} - -/* Return the most recently added opcode -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe *p){ - return sqlite3VdbeGetOp(p, p->nOp - 1); -} - -#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) -/* -** Return an integer value for one of the parameters to the opcode pOp -** determined by character c. -*/ -static int translateP(char c, const Op *pOp){ - if( c=='1' ) return pOp->p1; - if( c=='2' ) return pOp->p2; - if( c=='3' ) return pOp->p3; - if( c=='4' ) return pOp->p4.i; - return pOp->p5; -} - -/* -** Compute a string for the "comment" field of a VDBE opcode listing. -** -** The Synopsis: field in comments in the vdbe.c source file gets converted -** to an extra string that is appended to the sqlite3OpcodeName(). In the -** absence of other comments, this synopsis becomes the comment on the opcode. -** Some translation occurs: -** -** "PX" -> "r[X]" -** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1 -** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0 -** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x -*/ -SQLITE_PRIVATE char *sqlite3VdbeDisplayComment( - sqlite3 *db, /* Optional - Oom error reporting only */ - const Op *pOp, /* The opcode to be commented */ - const char *zP4 /* Previously obtained value for P4 */ -){ - const char *zOpName; - const char *zSynopsis; - int nOpName; - int ii; - char zAlt[50]; - StrAccum x; - - sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH); - zOpName = sqlite3OpcodeName(pOp->opcode); - nOpName = sqlite3Strlen30(zOpName); - if( zOpName[nOpName+1] ){ - int seenCom = 0; - char c; - zSynopsis = zOpName + nOpName + 1; - if( strncmp(zSynopsis,"IF ",3)==0 ){ - sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3); - zSynopsis = zAlt; - } - for(ii=0; (c = zSynopsis[ii])!=0; ii++){ - if( c=='P' ){ - c = zSynopsis[++ii]; - if( c=='4' ){ - sqlite3_str_appendall(&x, zP4); - }else if( c=='X' ){ - if( pOp->zComment && pOp->zComment[0] ){ - sqlite3_str_appendall(&x, pOp->zComment); - seenCom = 1; - break; - } - }else{ - int v1 = translateP(c, pOp); - int v2; - if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){ - ii += 3; - v2 = translateP(zSynopsis[ii], pOp); - if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){ - ii += 2; - v2++; - } - if( v2<2 ){ - sqlite3_str_appendf(&x, "%d", v1); - }else{ - sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1); - } - }else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){ - sqlite3_context *pCtx = pOp->p4.pCtx; - if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){ - sqlite3_str_appendf(&x, "%d", v1); - }else if( pCtx->argc>1 ){ - sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1); - }else if( x.accError==0 ){ - assert( x.nChar>2 ); - x.nChar -= 2; - ii++; - } - ii += 3; - }else{ - sqlite3_str_appendf(&x, "%d", v1); - if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){ - ii += 4; - } - } - } - }else{ - sqlite3_str_appendchar(&x, 1, c); - } - } - if( !seenCom && pOp->zComment ){ - sqlite3_str_appendf(&x, "; %s", pOp->zComment); - } - }else if( pOp->zComment ){ - sqlite3_str_appendall(&x, pOp->zComment); - } - if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){ - sqlite3OomFault(db); - } - return sqlite3StrAccumFinish(&x); -} -#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */ - -#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) -/* -** Translate the P4.pExpr value for an OP_CursorHint opcode into text -** that can be displayed in the P4 column of EXPLAIN output. -*/ -static void displayP4Expr(StrAccum *p, Expr *pExpr){ - const char *zOp = 0; - switch( pExpr->op ){ - case TK_STRING: - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3_str_appendf(p, "%Q", pExpr->u.zToken); - break; - case TK_INTEGER: - sqlite3_str_appendf(p, "%d", pExpr->u.iValue); - break; - case TK_NULL: - sqlite3_str_appendf(p, "NULL"); - break; - case TK_REGISTER: { - sqlite3_str_appendf(p, "r[%d]", pExpr->iTable); - break; - } - case TK_COLUMN: { - if( pExpr->iColumn<0 ){ - sqlite3_str_appendf(p, "rowid"); - }else{ - sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn); - } - break; - } - case TK_LT: zOp = "LT"; break; - case TK_LE: zOp = "LE"; break; - case TK_GT: zOp = "GT"; break; - case TK_GE: zOp = "GE"; break; - case TK_NE: zOp = "NE"; break; - case TK_EQ: zOp = "EQ"; break; - case TK_IS: zOp = "IS"; break; - case TK_ISNOT: zOp = "ISNOT"; break; - case TK_AND: zOp = "AND"; break; - case TK_OR: zOp = "OR"; break; - case TK_PLUS: zOp = "ADD"; break; - case TK_STAR: zOp = "MUL"; break; - case TK_MINUS: zOp = "SUB"; break; - case TK_REM: zOp = "REM"; break; - case TK_BITAND: zOp = "BITAND"; break; - case TK_BITOR: zOp = "BITOR"; break; - case TK_SLASH: zOp = "DIV"; break; - case TK_LSHIFT: zOp = "LSHIFT"; break; - case TK_RSHIFT: zOp = "RSHIFT"; break; - case TK_CONCAT: zOp = "CONCAT"; break; - case TK_UMINUS: zOp = "MINUS"; break; - case TK_UPLUS: zOp = "PLUS"; break; - case TK_BITNOT: zOp = "BITNOT"; break; - case TK_NOT: zOp = "NOT"; break; - case TK_ISNULL: zOp = "ISNULL"; break; - case TK_NOTNULL: zOp = "NOTNULL"; break; - - default: - sqlite3_str_appendf(p, "%s", "expr"); - break; - } - - if( zOp ){ - sqlite3_str_appendf(p, "%s(", zOp); - displayP4Expr(p, pExpr->pLeft); - if( pExpr->pRight ){ - sqlite3_str_append(p, ",", 1); - displayP4Expr(p, pExpr->pRight); - } - sqlite3_str_append(p, ")", 1); - } -} -#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ - - -#if VDBE_DISPLAY_P4 -/* -** Compute a string that describes the P4 parameter for an opcode. -** Use zTemp for any required temporary buffer space. -*/ -SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){ - char *zP4 = 0; - StrAccum x; - - sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH); - switch( pOp->p4type ){ - case P4_KEYINFO: { - int j; - KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->aSortFlags!=0 ); - sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); - for(j=0; jnKeyField; j++){ - CollSeq *pColl = pKeyInfo->aColl[j]; - const char *zColl = pColl ? pColl->zName : ""; - if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; - sqlite3_str_appendf(&x, ",%s%s%s", - (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "", - (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "", - zColl); - } - sqlite3_str_append(&x, ")", 1); - break; - } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - case P4_EXPR: { - displayP4Expr(&x, pOp->p4.pExpr); - break; - } -#endif - case P4_COLLSEQ: { - static const char *const encnames[] = {"?", "8", "16LE", "16BE"}; - CollSeq *pColl = pOp->p4.pColl; - assert( pColl->enc<4 ); - sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName, - encnames[pColl->enc]); - break; - } - case P4_FUNCDEF: { - FuncDef *pDef = pOp->p4.pFunc; - sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); - break; - } - case P4_FUNCCTX: { - FuncDef *pDef = pOp->p4.pCtx->pFunc; - sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); - break; - } - case P4_INT64: { - sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64); - break; - } - case P4_INT32: { - sqlite3_str_appendf(&x, "%d", pOp->p4.i); - break; - } - case P4_REAL: { - sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal); - break; - } - case P4_MEM: { - Mem *pMem = pOp->p4.pMem; - if( pMem->flags & MEM_Str ){ - zP4 = pMem->z; - }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - sqlite3_str_appendf(&x, "%lld", pMem->u.i); - }else if( pMem->flags & MEM_Real ){ - sqlite3_str_appendf(&x, "%.16g", pMem->u.r); - }else if( pMem->flags & MEM_Null ){ - zP4 = "NULL"; - }else{ - assert( pMem->flags & MEM_Blob ); - zP4 = "(blob)"; - } - break; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - case P4_VTAB: { - sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_str_appendf(&x, "vtab:%p", pVtab); - break; - } -#endif - case P4_INTARRAY: { - u32 i; - u32 *ai = pOp->p4.ai; - u32 n = ai[0]; /* The first element of an INTARRAY is always the - ** count of the number of elements to follow */ - for(i=1; i<=n; i++){ - sqlite3_str_appendf(&x, "%c%u", (i==1 ? '[' : ','), ai[i]); - } - sqlite3_str_append(&x, "]", 1); - break; - } - case P4_SUBPROGRAM: { - zP4 = "program"; - break; - } - case P4_TABLE: { - zP4 = pOp->p4.pTab->zName; - break; - } - case P4_SUBRTNSIG: { - SubrtnSig *pSig = pOp->p4.pSubrtnSig; - sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff); - break; - } - default: { - zP4 = pOp->p4.z; - } - } - if( zP4 ) sqlite3_str_appendall(&x, zP4); - if( (x.accError & SQLITE_NOMEM)!=0 ){ - sqlite3OomFault(db); - } - return sqlite3StrAccumFinish(&x); -} -#endif /* VDBE_DISPLAY_P4 */ - -/* -** Declare to the Vdbe that the BTree object at db->aDb[i] is used. -** -** The prepared statements need to know in advance the complete set of -** attached databases that will be use. A mask of these databases -** is maintained in p->btreeMask. The p->lockMask value is the subset of -** p->btreeMask of databases that will require a lock. -*/ -SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - assert( i>=0 && idb->nDb && i<(int)sizeof(yDbMask)*8 ); - assert( i<(int)sizeof(p->btreeMask)*8 ); - DbMaskSet(p->btreeMask, i); - if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){ - DbMaskSet(p->lockMask, i); - } -} - -#if !defined(SQLITE_OMIT_SHARED_CACHE) -/* -** If SQLite is compiled to support shared-cache mode and to be threadsafe, -** this routine obtains the mutex associated with each BtShared structure -** that may be accessed by the VM passed as an argument. In doing so it also -** sets the BtShared.db member of each of the BtShared structures, ensuring -** that the correct busy-handler callback is invoked if required. -** -** If SQLite is not threadsafe but does support shared-cache mode, then -** sqlite3BtreeEnter() is invoked to set the BtShared.db variables -** of all of BtShared structures accessible via the database handle -** associated with the VM. -** -** If SQLite is not threadsafe and does not support shared-cache mode, this -** function is a no-op. -** -** The p->btreeMask field is a bitmask of all btrees that the prepared -** statement p will ever use. Let N be the number of bits in p->btreeMask -** corresponding to btrees that use shared cache. Then the runtime of -** this routine is N*N. But as N is rarely more than 1, this should not -** be a problem. -*/ -SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){ - int i; - sqlite3 *db; - Db *aDb; - int nDb; - if( DbMaskAllZero(p->lockMask) ) return; /* The common case */ - db = p->db; - aDb = db->aDb; - nDb = db->nDb; - for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ - sqlite3BtreeEnter(aDb[i].pBt); - } - } -} -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 -/* -** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). -*/ -static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){ - int i; - sqlite3 *db; - Db *aDb; - int nDb; - db = p->db; - aDb = db->aDb; - nDb = db->nDb; - for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ - sqlite3BtreeLeave(aDb[i].pBt); - } - } -} -SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){ - if( DbMaskAllZero(p->lockMask) ) return; /* The common case */ - vdbeLeave(p); -} -#endif - -#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) -/* -** Print a single opcode. This routine is used for debugging only. -*/ -SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ - char *zP4; - char *zCom; - sqlite3 dummyDb; - static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n"; - if( pOut==0 ) pOut = stdout; - sqlite3BeginBenignMalloc(); - dummyDb.mallocFailed = 1; - zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp); -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - zCom = sqlite3VdbeDisplayComment(0, pOp, zP4); -#else - zCom = 0; -#endif - /* NB: The sqlite3OpcodeName() function is implemented by code created - ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the - ** information from the vdbe.c source text */ - fprintf(pOut, zFormat1, pc, - sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, - zP4 ? zP4 : "", pOp->p5, - zCom ? zCom : "" - ); - fflush(pOut); - sqlite3_free(zP4); - sqlite3_free(zCom); - sqlite3EndBenignMalloc(); -} -#endif - -/* -** 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, sqlite3 *db, u16 flags){ - assert( db!=0 ); - if( N>0 ){ - do{ - p->flags = flags; - p->db = db; - p->szMalloc = 0; -#ifdef SQLITE_DEBUG - p->pScopyFrom = 0; - p->bScopy = 0; -#endif - p++; - }while( (--N)>0 ); - } -} - -/* -** 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 ){ - Mem *pEnd = &p[N]; - sqlite3 *db = p->db; - assert( db!=0 ); - if( db->pnBytesFreed ){ - do{ - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); - }while( (++p)flags & MEM_Agg ); - testcase( p->flags & MEM_Dyn ); - if( p->flags&(MEM_Agg|MEM_Dyn) ){ - testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlite3VdbeFrameMemDel ); - sqlite3VdbeMemRelease(p); - p->flags = MEM_Undefined; - }else if( p->szMalloc ){ - sqlite3DbNNFreeNN(db, p->zMalloc); - p->szMalloc = 0; - p->flags = MEM_Undefined; - } -#ifdef SQLITE_DEBUG - else{ - p->flags = MEM_Undefined; - } -#endif - }while( (++p)iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0; - return 1; -} -#endif - - -/* -** This is a destructor on a Mem object (which is really an sqlite3_value) -** that deletes the Frame object that is attached to it as a blob. -** -** This routine does not delete the Frame right away. It merely adds the -** frame to a list of frames to be deleted when the Vdbe halts. -*/ -SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){ - VdbeFrame *pFrame = (VdbeFrame*)pArg; - assert( sqlite3VdbeFrameIsValid(pFrame) ); - pFrame->pParent = pFrame->v->pDelFrame; - pFrame->v->pDelFrame = pFrame; -} - -#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN) -/* -** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN -** QUERY PLAN output. -** -** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no -** more opcodes to be displayed. -*/ -SQLITE_PRIVATE int sqlite3VdbeNextOpcode( - Vdbe *p, /* The statement being explained */ - Mem *pSub, /* Storage for keeping track of subprogram nesting */ - int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */ - int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */ - int *piAddr, /* OUT: Write index into (*paOp)[] here */ - Op **paOp /* OUT: Write the opcode array here */ -){ - int nRow; /* Stop when row count reaches this */ - int nSub = 0; /* Number of sub-vdbes seen so far */ - SubProgram **apSub = 0; /* Array of sub-vdbes */ - int i; /* Next instruction address */ - int rc = SQLITE_OK; /* Result code */ - Op *aOp = 0; /* Opcode array */ - int iPc; /* Rowid. Copy of value in *piPc */ - - /* When the number of output rows reaches nRow, that means the - ** listing has finished and sqlite3_step() should return SQLITE_DONE. - ** nRow is the sum of the number of rows in the main program, plus - ** the sum of the number of rows in all trigger subprograms encountered - ** so far. The nRow value will increase as new trigger subprograms are - ** encountered, but p->pc will eventually catch up to nRow. - */ - nRow = p->nOp; - if( pSub!=0 ){ - if( pSub->flags&MEM_Blob ){ - /* pSub is initiallly NULL. It is initialized to a BLOB by - ** the P4_SUBPROGRAM processing logic below */ - nSub = pSub->n/sizeof(Vdbe*); - apSub = (SubProgram **)pSub->z; - } - for(i=0; inOp; - } - } - iPc = *piPc; - while(1){ /* Loop exits via break */ - i = iPc++; - if( i>=nRow ){ - p->rc = SQLITE_OK; - rc = SQLITE_DONE; - break; - } - if( inOp ){ - /* The rowid is small enough that we are still in the - ** main program. */ - aOp = p->aOp; - }else{ - /* We are currently listing subprograms. Figure out which one and - ** pick up the appropriate opcode. */ - int j; - i -= p->nOp; - assert( apSub!=0 ); - assert( nSub>0 ); - for(j=0; i>=apSub[j]->nOp; j++){ - i -= apSub[j]->nOp; - assert( inOp || j+1aOp; - } - - /* When an OP_Program opcode is encounter (the only opcode that has - ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms - ** kept in p->aMem[9].z to hold the new program - assuming this subprogram - ** has not already been seen. - */ - if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){ - int nByte = (nSub+1)*sizeof(SubProgram*); - int j; - for(j=0; jrc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0); - if( p->rc!=SQLITE_OK ){ - rc = SQLITE_ERROR; - break; - } - apSub = (SubProgram **)pSub->z; - apSub[nSub++] = aOp[i].p4.pProgram; - MemSetTypeFlag(pSub, MEM_Blob); - pSub->n = nSub*sizeof(SubProgram*); - nRow += aOp[i].p4.pProgram->nOp; - } - } - if( eMode==0 ) break; -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - if( eMode==2 ){ - Op *pOp = aOp + i; - if( pOp->opcode==OP_OpenRead ) break; - if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break; - if( pOp->opcode==OP_ReopenIdx ) break; - }else -#endif - { - assert( eMode==1 ); - if( aOp[i].opcode==OP_Explain ) break; - if( aOp[i].opcode==OP_Init && iPc>1 ) break; - } - } - *piPc = iPc; - *piAddr = i; - *paOp = aOp; - return rc; -} -#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */ - - -/* -** Delete a VdbeFrame object and its contents. VdbeFrame objects are -** allocated by the OP_Program opcode in sqlite3VdbeExec(). -*/ -SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ - int i; - Mem *aMem = VdbeFrameMem(p); - VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; - assert( sqlite3VdbeFrameIsValid(p) ); - for(i=0; inChildCsr; i++){ - if( apCsr[i] ) sqlite3VdbeFreeCursorNN(p->v, apCsr[i]); - } - releaseMemArray(aMem, p->nChildMem); - sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0); - sqlite3DbFree(p->v->db, p); -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Give a listing of the program in the virtual machine. -** -** The interface is the same as sqlite3VdbeExec(). But instead of -** running the code, it invokes the callback once for each instruction. -** This feature is used to implement "EXPLAIN". -** -** When p->explain==1, each instruction is listed. When -** p->explain==2, only OP_Explain instructions are listed and these -** are shown in a different format. p->explain==2 is used to implement -** EXPLAIN QUERY PLAN. -** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers -** are also shown, so that the boundaries between the main program and -** each trigger are clear. -** -** When p->explain==1, first the main program is listed, then each of -** the trigger subprograms are listed one by one. -*/ -SQLITE_PRIVATE int sqlite3VdbeList( - Vdbe *p /* The VDBE */ -){ - Mem *pSub = 0; /* Memory cell hold array of subprogs */ - sqlite3 *db = p->db; /* The database connection */ - int i; /* Loop counter */ - int rc = SQLITE_OK; /* Return code */ - Mem *pMem = &p->aMem[1]; /* First Mem of result set */ - int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); - Op *aOp; /* Array of opcodes */ - Op *pOp; /* Current opcode */ - - assert( p->explain ); - 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 - ** the result, result columns may become dynamic if the user calls - ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. - */ - releaseMemArray(pMem, 8); - - if( p->rc==SQLITE_NOMEM ){ - /* This happens if a malloc() inside a call to sqlite3_column_text() or - ** sqlite3_column_text16() failed. */ - sqlite3OomFault(db); - return SQLITE_ERROR; - } - - if( bListSubprogs ){ - /* The first 8 memory cells are used for the result set. So we will - ** commandeer the 9th cell to use as storage for an array of pointers - ** to trigger subprograms. The VDBE is guaranteed to have at least 9 - ** cells. */ - assert( p->nMem>9 ); - pSub = &p->aMem[9]; - }else{ - pSub = 0; - } - - /* Figure out which opcode is next to display */ - rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp); - - if( rc==SQLITE_OK ){ - pOp = aOp + i; - if( AtomicLoad(&db->u1.isInterrupted) ){ - p->rc = SQLITE_INTERRUPT; - rc = SQLITE_ERROR; - sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); - }else{ - char *zP4 = sqlite3VdbeDisplayP4(db, pOp); - if( p->explain==2 ){ - sqlite3VdbeMemSetInt64(pMem, pOp->p1); - sqlite3VdbeMemSetInt64(pMem+1, pOp->p2); - sqlite3VdbeMemSetInt64(pMem+2, pOp->p3); - sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free); - assert( p->nResColumn==4 ); - }else{ - sqlite3VdbeMemSetInt64(pMem+0, i); - sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode), - -1, SQLITE_UTF8, SQLITE_STATIC); - sqlite3VdbeMemSetInt64(pMem+2, pOp->p1); - sqlite3VdbeMemSetInt64(pMem+3, pOp->p2); - sqlite3VdbeMemSetInt64(pMem+4, pOp->p3); - /* pMem+5 for p4 is done last */ - sqlite3VdbeMemSetInt64(pMem+6, pOp->p5); -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - { - char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4); - sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free); - } -#else - sqlite3VdbeMemSetNull(pMem+7); -#endif - sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free); - assert( p->nResColumn==8 ); - } - p->pResultRow = pMem; - if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - rc = SQLITE_ERROR; - }else{ - p->rc = SQLITE_OK; - rc = SQLITE_ROW; - } - } - } - return rc; -} -#endif /* SQLITE_OMIT_EXPLAIN */ - -#ifdef SQLITE_DEBUG -/* -** Print the SQL that was used to generate a VDBE program. -*/ -SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){ - const char *z = 0; - if( p->zSql ){ - z = p->zSql; - }else if( p->nOp>=1 ){ - const VdbeOp *pOp = &p->aOp[0]; - if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ - z = pOp->p4.z; - while( sqlite3Isspace(*z) ) z++; - } - } - if( z ) printf("SQL: [%s]\n", z); -} -#endif - -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) -/* -** Print an IOTRACE message showing SQL content. -*/ -SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ - int nOp = p->nOp; - VdbeOp *pOp; - if( sqlite3IoTrace==0 ) return; - if( nOp<1 ) return; - pOp = &p->aOp[0]; - if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ - int i, j; - char z[1000]; - sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); - for(i=0; sqlite3Isspace(z[i]); i++){} - for(j=0; z[i]; i++){ - if( sqlite3Isspace(z[i]) ){ - if( z[i-1]!=' ' ){ - z[j++] = ' '; - } - }else{ - z[j++] = z[i]; - } - } - z[j] = 0; - sqlite3IoTrace("SQL %s\n", z); - } -} -#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ - -/* An instance of this object describes bulk memory available for use -** by subcomponents of a prepared statement. Space is allocated out -** of a ReusableSpace object by the allocSpace() routine below. -*/ -struct ReusableSpace { - u8 *pSpace; /* Available memory */ - sqlite3_int64 nFree; /* Bytes of available memory */ - sqlite3_int64 nNeeded; /* Total bytes that could not be allocated */ -}; - -/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf -** from the ReusableSpace object. Return a pointer to the allocated -** memory on success. If insufficient memory is available in the -** ReusableSpace object, increase the ReusableSpace.nNeeded -** value by the amount needed and return NULL. -** -** If pBuf is not initially NULL, that means that the memory has already -** been allocated by a prior call to this routine, so just return a copy -** of pBuf and leave ReusableSpace unchanged. -** -** This allocator is employed to repurpose unused slots at the end of the -** opcode array of prepared state for other memory needs of the prepared -** statement. -*/ -static void *allocSpace( - struct ReusableSpace *p, /* Bulk memory available for allocation */ - void *pBuf, /* Pointer to a prior allocation */ - sqlite3_int64 nByte /* Bytes of memory needed. */ -){ - assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); - if( pBuf==0 ){ - nByte = ROUND8P(nByte); - if( nByte <= p->nFree ){ - p->nFree -= nByte; - pBuf = &p->pSpace[p->nFree]; - }else{ - p->nNeeded += nByte; - } - } - assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); - return pBuf; -} - -/* -** Rewind the VDBE back to the beginning in preparation for -** running it. -*/ -SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ -#if defined(SQLITE_DEBUG) - int i; -#endif - assert( p!=0 ); - 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 ); - - p->eVdbeState = VDBE_READY_STATE; - -#ifdef SQLITE_DEBUG - for(i=0; inMem; i++){ - assert( p->aMem[i].db==p->db ); - } -#endif - p->pc = -1; - p->rc = SQLITE_OK; - p->errorAction = OE_Abort; - p->nChange = 0; - p->cacheCtr = 1; - p->minWriteFileFormat = 255; - p->iStatement = 0; - p->nFkConstraint = 0; -#ifdef VDBE_PROFILE - for(i=0; inOp; i++){ - p->aOp[i].nExec = 0; - p->aOp[i].nCycle = 0; - } -#endif -} - -/* -** Prepare a virtual machine for execution for the first time after -** creating the virtual machine. This involves things such -** as allocating registers and initializing the program counter. -** After the VDBE has be prepped, it can be executed by one or more -** calls to sqlite3VdbeExec(). -** -** This function may be called exactly once on each virtual machine. -** After this routine is called the VM has been "packaged" and is ready -** to run. After this routine is called, further calls to -** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects -** the Vdbe from the Parse object that helped generate it so that the -** the Vdbe becomes an independent entity and the Parse object can be -** destroyed. -** -** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back -** to its initial state after it has been run. -*/ -SQLITE_PRIVATE void sqlite3VdbeMakeReady( - Vdbe *p, /* The VDBE */ - Parse *pParse /* Parsing context */ -){ - sqlite3 *db; /* The database connection */ - int nVar; /* Number of parameters */ - int nMem; /* Number of VM memory registers */ - int nCursor; /* Number of cursors required */ - int nArg; /* Max number args to xFilter or xUpdate */ - int n; /* Loop counter */ - struct ReusableSpace x; /* Reusable bulk memory */ - - assert( p!=0 ); - assert( p->nOp>0 ); - assert( pParse!=0 ); - assert( p->eVdbeState==VDBE_INIT_STATE ); - assert( pParse==p->pParse ); - assert( pParse->db==p->db ); - p->pVList = pParse->pVList; - pParse->pVList = 0; - db = p->db; - assert( db->mallocFailed==0 ); - nVar = pParse->nVar; - nMem = pParse->nMem; - nCursor = pParse->nTab; - nArg = pParse->nMaxArg; - - /* Each cursor uses a memory cell. The first cursor (cursor 0) can - ** use aMem[0] which is not otherwise used by the VDBE program. Allocate - ** space at the end of aMem[] for cursors 1 and greater. - ** See also: allocateCursor(). - */ - nMem += nCursor; - if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */ - - /* Figure out how much reusable memory is available at the end of the - ** opcode array. This extra memory will be reallocated for other elements - ** of the prepared statement. - */ - 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 */ - assert( x.nFree>=0 ); - assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); - - resolveP2Values(p, &nArg); - p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); - if( pParse->explain ){ - if( nMem<10 ) nMem = 10; - p->explain = pParse->explain; - p->nResColumn = 12 - 4*p->explain; - } - p->expired = 0; - - /* Memory for registers, parameters, cursor, etc, is allocated in one or two - ** passes. On the first pass, we try to reuse unused memory at the - ** end of the opcode array. If we are unable to satisfy all memory - ** requirements by reusing the opcode array tail, then the second - ** pass will fill in the remainder using a fresh memory allocation. - ** - ** This two-pass approach that reuses as much memory as possible from - ** the leftover memory at the end of the opcode array. This can significantly - ** reduce the amount of memory held by a prepared statement. - */ - x.nNeeded = 0; - p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem)); - p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem)); - p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*)); - p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*)); - if( x.nNeeded ){ - x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); - x.nFree = x.nNeeded; - if( !db->mallocFailed ){ - p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); - p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); - p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); - p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); - } - } -#ifdef SQLITE_DEBUG - p->napArg = nArg; -#endif - - if( db->mallocFailed ){ - p->nVar = 0; - p->nCursor = 0; - p->nMem = 0; - }else{ - p->nCursor = nCursor; - p->nVar = (ynVar)nVar; - initMemArray(p->aVar, nVar, db, MEM_Null); - p->nMem = nMem; - initMemArray(p->aMem, nMem, db, MEM_Undefined); - memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); - } - sqlite3VdbeRewind(p); -} - -/* -** Close a VDBE cursor and release all the resources that cursor -** happens to hold. -*/ -SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ - if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx); -} -static SQLITE_NOINLINE void freeCursorWithCache(Vdbe *p, VdbeCursor *pCx){ - VdbeTxtBlbCache *pCache = pCx->pCache; - assert( pCx->colCache ); - pCx->colCache = 0; - pCx->pCache = 0; - if( pCache->pCValue ){ - sqlite3RCStrUnref(pCache->pCValue); - pCache->pCValue = 0; - } - sqlite3DbFree(p->db, pCache); - sqlite3VdbeFreeCursorNN(p, pCx); -} -SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){ - if( pCx->colCache ){ - freeCursorWithCache(p, pCx); - return; - } - switch( pCx->eCurType ){ - case CURTYPE_SORTER: { - sqlite3VdbeSorterClose(p->db, pCx); - break; - } - case CURTYPE_BTREE: { - assert( pCx->uc.pCursor!=0 ); - sqlite3BtreeCloseCursor(pCx->uc.pCursor); - break; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - case CURTYPE_VTAB: { - sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur; - const sqlite3_module *pModule = pVCur->pVtab->pModule; - assert( pVCur->pVtab->nRef>0 ); - pVCur->pVtab->nRef--; - pModule->xClose(pVCur); - break; - } -#endif - } -} - -/* -** Close all cursors in the current frame. -*/ -static void closeCursorsInFrame(Vdbe *p){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursorNN(p, pC); - p->apCsr[i] = 0; - } - } -} - -/* -** Copy the values stored in the VdbeFrame structure to its Vdbe. This -** is used, for example, when a trigger sub-program is halted to restore -** control to the main program. -*/ -SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ - Vdbe *v = pFrame->v; - closeCursorsInFrame(v); - v->aOp = pFrame->aOp; - v->nOp = pFrame->nOp; - v->aMem = pFrame->aMem; - v->nMem = pFrame->nMem; - v->apCsr = pFrame->apCsr; - v->nCursor = pFrame->nCursor; - v->db->lastRowid = pFrame->lastRowid; - v->nChange = pFrame->nChange; - v->db->nChange = pFrame->nDbChange; - sqlite3VdbeDeleteAuxData(v->db, &v->pAuxData, -1, 0); - v->pAuxData = pFrame->pAuxData; - pFrame->pAuxData = 0; - return pFrame->pc; -} - -/* -** Close all cursors. -** -** Also release any dynamic memory held by the VM in the Vdbe.aMem memory -** cell array. This is necessary as the memory cell array may contain -** pointers to VdbeFrame objects, which may in turn contain pointers to -** open cursors. -*/ -static void closeAllCursors(Vdbe *p){ - if( p->pFrame ){ - VdbeFrame *pFrame; - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - sqlite3VdbeFrameRestore(pFrame); - p->pFrame = 0; - p->nFrame = 0; - } - assert( p->nFrame==0 ); - closeCursorsInFrame(p); - releaseMemArray(p->aMem, p->nMem); - while( p->pDelFrame ){ - VdbeFrame *pDel = p->pDelFrame; - p->pDelFrame = pDel->pParent; - sqlite3VdbeFrameDelete(pDel); - } - - /* Delete any auxdata allocations made by the VM */ - if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0); - assert( p->pAuxData==0 ); -} - -/* -** Set the number of result columns that will be returned by this SQL -** statement. This is now set at compile time, rather than during -** execution of the vdbe program so that sqlite3_column_count() can -** be called on an SQL statement before sqlite3_step(). -*/ -SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ - int n; - sqlite3 *db = p->db; - - if( p->nResAlloc ){ - releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); - sqlite3DbFree(db, p->aColName); - } - n = nResColumn*COLNAME_N; - p->nResColumn = p->nResAlloc = (u16)nResColumn; - p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); - if( p->aColName==0 ) return; - initMemArray(p->aColName, n, db, MEM_Null); -} - -/* -** Set the name of the idx'th column to be returned by the SQL statement. -** zName must be a pointer to a nul terminated string. -** -** This call must be made after a call to sqlite3VdbeSetNumCols(). -** -** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC -** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed -** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed. -*/ -SQLITE_PRIVATE int sqlite3VdbeSetColName( - Vdbe *p, /* Vdbe being configured */ - int idx, /* Index of column zName applies to */ - int var, /* One of the COLNAME_* constants */ - const char *zName, /* Pointer to buffer containing name */ - void (*xDel)(void*) /* Memory management strategy for zName */ -){ - int rc; - Mem *pColName; - assert( idxnResAlloc ); - assert( vardb->mallocFailed ){ - assert( !zName || xDel!=SQLITE_DYNAMIC ); - return SQLITE_NOMEM_BKPT; - } - assert( p->aColName!=0 ); - pColName = &(p->aColName[idx+var*p->nResAlloc]); - rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); - assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); - return rc; -} - -/* -** A read or write transaction may or may not be active on database handle -** db. If a transaction is active, commit it. If there is a -** write-transaction spanning more than one database file, this routine -** takes care of the super-journal trickery. -*/ -static int vdbeCommit(sqlite3 *db, Vdbe *p){ - int i; - int nTrans = 0; /* Number of databases with an active write-transaction - ** that are candidates for a two-phase commit using a - ** super-journal */ - int rc = SQLITE_OK; - int needXcommit = 0; - -#ifdef SQLITE_OMIT_VIRTUALTABLE - /* With this option, sqlite3VtabSync() is defined to be simply - ** SQLITE_OK so p is not used. - */ - UNUSED_PARAMETER(p); -#endif - - /* Before doing anything else, call the xSync() callback for any - ** virtual module tables written in this transaction. This has to - ** be done before determining whether a super-journal file is - ** required, as an xSync() callback may add an attached database - ** to the transaction. - */ - rc = sqlite3VtabSync(db, p); - - /* This loop determines (a) if the commit hook should be invoked and - ** (b) how many database files have open write transactions, not - ** including the temp database. (b) is important because if more than - ** one database file has an open write transaction, a super-journal - ** file is required for an atomic commit. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ - /* Whether or not a database might need a super-journal depends upon - ** its journal mode (among other things). This matrix determines which - ** journal modes use a super-journal and which do not */ - static const u8 aMJNeeded[] = { - /* DELETE */ 1, - /* PERSIST */ 1, - /* OFF */ 0, - /* TRUNCATE */ 1, - /* MEMORY */ 0, - /* WAL */ 0 - }; - Pager *pPager; /* Pager associated with pBt */ - needXcommit = 1; - sqlite3BtreeEnter(pBt); - pPager = sqlite3BtreePager(pBt); - if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF - && aMJNeeded[sqlite3PagerGetJournalMode(pPager)] - && sqlite3PagerIsMemdb(pPager)==0 - ){ - assert( i!=1 ); - nTrans++; - } - rc = sqlite3PagerExclusiveLock(pPager); - sqlite3BtreeLeave(pBt); - } - } - if( rc!=SQLITE_OK ){ - return rc; - } - - /* If there are any write-transactions at all, invoke the commit hook */ - if( needXcommit && db->xCommitCallback ){ - rc = db->xCommitCallback(db->pCommitArg); - if( rc ){ - return SQLITE_CONSTRAINT_COMMITHOOK; - } - } - - /* The simple case - no more than one database file (not counting the - ** TEMP database) has a transaction active. There is no need for the - ** super-journal. - ** - ** If the return value of sqlite3BtreeGetFilename() is a zero length - ** string, it means the main database is :memory: or a temp file. In - ** that case we do not support atomic multi-file commits, so use the - ** simple case then too. - */ - if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt)) - || nTrans<=1 - ){ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, 0); - } - } - - /* Do the commit only if all databases successfully complete phase 1. - ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an - ** IO error while deleting or truncating a journal file. It is unlikely, - ** but could happen. In this case abandon processing and return the error. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseTwo(pBt, 0); - } - } - if( rc==SQLITE_OK ){ - sqlite3VtabCommit(db); - } - } - - /* The complex case - There is a multi-file write-transaction active. - ** This requires a super-journal file to ensure the transaction is - ** committed atomically. - */ -#ifndef SQLITE_OMIT_DISKIO - else{ - sqlite3_vfs *pVfs = db->pVfs; - char *zSuper = 0; /* File-name for the super-journal */ - char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); - sqlite3_file *pSuperJrnl = 0; - i64 offset = 0; - int res; - int retryCount = 0; - int nMainFile; - - /* Select a super-journal file name */ - nMainFile = sqlite3Strlen30(zMainFile); - zSuper = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0); - if( zSuper==0 ) return SQLITE_NOMEM_BKPT; - zSuper += 4; - do { - u32 iRandom; - if( retryCount ){ - if( retryCount>100 ){ - sqlite3_log(SQLITE_FULL, "MJ delete: %s", zSuper); - sqlite3OsDelete(pVfs, zSuper, 0); - break; - }else if( retryCount==1 ){ - sqlite3_log(SQLITE_FULL, "MJ collide: %s", zSuper); - } - } - retryCount++; - sqlite3_randomness(sizeof(iRandom), &iRandom); - sqlite3_snprintf(13, &zSuper[nMainFile], "-mj%06X9%02X", - (iRandom>>8)&0xffffff, iRandom&0xff); - /* The antipenultimate character of the super-journal name must - ** be "9" to avoid name collisions when using 8+3 filenames. */ - assert( zSuper[sqlite3Strlen30(zSuper)-3]=='9' ); - sqlite3FileSuffix3(zMainFile, zSuper); - rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res); - }while( rc==SQLITE_OK && res ); - if( rc==SQLITE_OK ){ - /* Open the super-journal. */ - rc = sqlite3OsOpenMalloc(pVfs, zSuper, &pSuperJrnl, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_SUPER_JOURNAL, 0 - ); - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zSuper-4); - return rc; - } - - /* Write the name of each database file in the transaction into the new - ** super-journal file. If an error occurs at this point close - ** and delete the super-journal file. All the individual journal files - ** still have 'null' as the super-journal pointer, so they will roll - ** back independently if a failure occurs. - */ - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ - char const *zFile = sqlite3BtreeGetJournalname(pBt); - if( zFile==0 ){ - continue; /* Ignore TEMP and :memory: databases */ - } - assert( zFile[0]!=0 ); - rc = sqlite3OsWrite(pSuperJrnl, zFile, sqlite3Strlen30(zFile)+1,offset); - offset += sqlite3Strlen30(zFile)+1; - if( rc!=SQLITE_OK ){ - sqlite3OsCloseFree(pSuperJrnl); - sqlite3OsDelete(pVfs, zSuper, 0); - sqlite3DbFree(db, zSuper-4); - return rc; - } - } - } - - /* Sync the super-journal file. If the IOCAP_SEQUENTIAL device - ** flag is set this is not required. - */ - if( 0==(sqlite3OsDeviceCharacteristics(pSuperJrnl)&SQLITE_IOCAP_SEQUENTIAL) - && SQLITE_OK!=(rc = sqlite3OsSync(pSuperJrnl, SQLITE_SYNC_NORMAL)) - ){ - sqlite3OsCloseFree(pSuperJrnl); - sqlite3OsDelete(pVfs, zSuper, 0); - sqlite3DbFree(db, zSuper-4); - return rc; - } - - /* Sync all the db files involved in the transaction. The same call - ** sets the super-journal pointer in each individual journal. If - ** an error occurs here, do not delete the super-journal file. - ** - ** If the error occurs during the first call to - ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the - ** super-journal file will be orphaned. But we cannot delete it, - ** in case the super-journal file name was written into the journal - ** file before the failure occurred. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, zSuper); - } - } - sqlite3OsCloseFree(pSuperJrnl); - assert( rc!=SQLITE_BUSY ); - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zSuper-4); - return rc; - } - - /* Delete the super-journal file. This commits the transaction. After - ** doing this the directory is synced again before any individual - ** transaction files are deleted. - */ - rc = sqlite3OsDelete(pVfs, zSuper, 1); - sqlite3DbFree(db, zSuper-4); - zSuper = 0; - if( rc ){ - return rc; - } - - /* All files and directories have already been synced, so the following - ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and - ** deleting or truncating journals. If something goes wrong while - ** this is happening we don't really care. The integrity of the - ** transaction is already guaranteed, but some stray 'cold' journals - ** may be lying around. Returning an error code won't help matters. - */ - disable_simulated_io_errors(); - sqlite3BeginBenignMalloc(); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - sqlite3BtreeCommitPhaseTwo(pBt, 1); - } - } - sqlite3EndBenignMalloc(); - enable_simulated_io_errors(); - - sqlite3VtabCommit(db); - } -#endif - - return rc; -} - -/* -** This routine checks that the sqlite3.nVdbeActive count variable -** matches the number of vdbe's in the list sqlite3.pVdbe that are -** currently active. An assertion fails if the two counts do not match. -** This is an internal self-check only - it is not an essential processing -** step. -** -** This is a no-op if NDEBUG is defined. -*/ -#ifndef NDEBUG -static void checkActiveVdbeCnt(sqlite3 *db){ - Vdbe *p; - int cnt = 0; - int nWrite = 0; - int nRead = 0; - p = db->pVdbe; - while( p ){ - if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){ - cnt++; - if( p->readOnly==0 ) nWrite++; - if( p->bIsReader ) nRead++; - } - p = p->pVNext; - } - assert( cnt==db->nVdbeActive ); - assert( nWrite==db->nVdbeWrite ); - assert( nRead==db->nVdbeRead ); -} -#else -#define checkActiveVdbeCnt(x) -#endif - -/* -** If the Vdbe passed as the first argument opened a statement-transaction, -** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or -** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement -** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the -** statement transaction is committed. -** -** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. -** Otherwise SQLITE_OK. -*/ -static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){ - sqlite3 *const db = p->db; - int rc = SQLITE_OK; - int i; - const int iSavepoint = p->iStatement-1; - - assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); - assert( db->nStatement>0 ); - assert( p->iStatement==(db->nStatement+db->nSavepoint) ); - - for(i=0; inDb; i++){ - int rc2 = SQLITE_OK; - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc2==SQLITE_OK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - db->nStatement--; - p->iStatement = 0; - - if( rc==SQLITE_OK ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint); - } - } - - /* If the statement transaction is being rolled back, also restore the - ** database handles deferred constraint counter to the value it had when - ** the statement transaction was opened. */ - if( eOp==SAVEPOINT_ROLLBACK ){ - db->nDeferredCons = p->nStmtDefCons; - db->nDeferredImmCons = p->nStmtDefImmCons; - } - return rc; -} -SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ - if( p->db->nStatement && p->iStatement ){ - return vdbeCloseStatement(p, eOp); - } - return SQLITE_OK; -} - - -/* -** This function is called when a transaction opened by the database -** handle associated with the VM passed as an argument is about to be -** committed. If there are outstanding deferred foreign key constraint -** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. -** -** If there are outstanding FK violations and this function returns -** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY -** and write an error message to it. Then return SQLITE_ERROR. -*/ -#ifndef SQLITE_OMIT_FOREIGN_KEY -SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ - sqlite3 *db = p->db; - if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) - || (!deferred && p->nFkConstraint>0) - ){ - p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; - p->errorAction = OE_Abort; - sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR; - return SQLITE_CONSTRAINT_FOREIGNKEY; - } - return SQLITE_OK; -} -#endif - -/* -** This routine is called the when a VDBE tries to halt. If the VDBE -** 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 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 -** means the close did not happen and needs to be repeated. -*/ -SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ - int rc; /* Used to store transient return codes */ - sqlite3 *db = p->db; - - /* This function contains the logic that determines if a statement or - ** transaction will be committed or rolled back as a result of the - ** execution of this virtual machine. - ** - ** If any of the following errors occur: - ** - ** SQLITE_NOMEM - ** SQLITE_IOERR - ** SQLITE_FULL - ** SQLITE_INTERRUPT - ** - ** Then the internal cache might have been left in an inconsistent - ** state. We need to rollback the statement transaction, if there is - ** one, or the complete transaction if there is no statement transaction. - */ - - assert( p->eVdbeState==VDBE_RUN_STATE ); - if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM_BKPT; - } - closeAllCursors(p); - checkActiveVdbeCnt(db); - - /* 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->bIsReader ){ - int mrc; /* Primary error code from p->rc */ - int eStatementOp = 0; - int isSpecialError; /* Set to true if a 'special' error */ - - /* Lock all btrees used by the statement */ - sqlite3VdbeEnter(p); - - /* Check for one of the special errors */ - 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 - ** transaction must be rolled back to restore the database to a - ** consistent state. - ** - ** Even if the statement is read-only, it is important to perform - ** a statement or transaction rollback operation. If the error - ** occurred while writing to the journal, sub-journal or database - ** file as part of an effort to free up cache space (see function - ** pagerStress() in pager.c), the rollback is required to restore - ** the pager to a consistent state. - */ - if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ - if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ - eStatementOp = SAVEPOINT_ROLLBACK; - }else{ - /* We are forced to roll back the active transaction. Before doing - ** so, abort any other statements this handle currently has active. - */ - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - p->nChange = 0; - } - } - } - - /* Check for immediate foreign key violations. */ - if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - (void)sqlite3VdbeCheckFk(p, 0); - } - - /* If the auto-commit flag is set and this is the only active writer - ** VM, then we do either a commit or rollback of the current transaction. - ** - ** Note: This block also runs if one of the special errors handled - ** above has occurred. - */ - if( !sqlite3VtabInSync(db) - && db->autoCommit - && db->nVdbeWrite==(p->readOnly==0) - ){ - if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - rc = sqlite3VdbeCheckFk(p, 1); - if( rc!=SQLITE_OK ){ - if( NEVER(p->readOnly) ){ - sqlite3VdbeLeave(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 - ** key constraints to hold up the transaction. This means a commit - ** is required. */ - rc = vdbeCommit(db, p); - } - if( rc==SQLITE_BUSY && p->readOnly ){ - sqlite3VdbeLeave(p); - return SQLITE_BUSY; - }else if( rc!=SQLITE_OK ){ - sqlite3SystemError(db, rc); - p->rc = rc; - sqlite3RollbackAll(db, SQLITE_OK); - p->nChange = 0; - }else{ - db->nDeferredCons = 0; - db->nDeferredImmCons = 0; - db->flags &= ~(u64)SQLITE_DeferFKs; - sqlite3CommitInternalChanges(db); - } - }else if( p->rc==SQLITE_SCHEMA && db->nVdbeActive>1 ){ - p->nChange = 0; - }else{ - sqlite3RollbackAll(db, SQLITE_OK); - p->nChange = 0; - } - db->nStatement = 0; - }else if( eStatementOp==0 ){ - if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ - eStatementOp = SAVEPOINT_RELEASE; - }else if( p->errorAction==OE_Abort ){ - eStatementOp = SAVEPOINT_ROLLBACK; - }else{ - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - p->nChange = 0; - } - } - - /* If eStatementOp is non-zero, then a statement transaction needs to - ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to - ** do so. If this operation returns an error, and the current statement - ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the - ** current statement error code. - */ - if( eStatementOp ){ - rc = sqlite3VdbeCloseStatement(p, eStatementOp); - if( rc ){ - if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){ - p->rc = rc; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - } - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - p->nChange = 0; - } - } - - /* If this was an INSERT, UPDATE or DELETE and no statement transaction - ** has been rolled back, update the database connection change-counter. - */ - if( p->changeCntOn ){ - if( eStatementOp!=SAVEPOINT_ROLLBACK ){ - sqlite3VdbeSetChanges(db, p->nChange); - }else{ - sqlite3VdbeSetChanges(db, 0); - } - p->nChange = 0; - } - - /* Release the locks */ - sqlite3VdbeLeave(p); - } - - /* We have successfully halted and closed the VM. Record this fact. */ - 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; - } - - /* If the auto-commit flag is set to true, then any locks that were held - ** by connection db have now been released. Call sqlite3ConnectionUnlocked() - ** to invoke any required unlock-notify callbacks. - */ - if( db->autoCommit ){ - sqlite3ConnectionUnlocked(db); - } - - assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 ); - return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); -} - - -/* -** Each VDBE holds the result of the most recent sqlite3_step() call -** in p->rc. This routine sets that result back to SQLITE_OK. -*/ -SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){ - p->rc = SQLITE_OK; -} - -/* -** Copy the error code and error message belonging to the VDBE passed -** as the first argument to its database handle (so that they will be -** returned by calls to sqlite3_errcode() and sqlite3_errmsg()). -** -** This function does not clear the VDBE error code or message, just -** copies them to the database handle. -*/ -SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ - sqlite3 *db = p->db; - int rc = p->rc; - if( p->zErrMsg ){ - db->bBenignMalloc++; - sqlite3BeginBenignMalloc(); - if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); - sqlite3EndBenignMalloc(); - db->bBenignMalloc--; - }else if( db->pErr ){ - sqlite3ValueSetNull(db->pErr); - } - db->errCode = rc; - db->errByteOffset = -1; - return rc; -} - -#ifdef SQLITE_ENABLE_SQLLOG -/* -** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, -** invoke it. -*/ -static void vdbeInvokeSqllog(Vdbe *v){ - if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ - char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); - assert( v->db->init.busy==0 ); - if( zExpanded ){ - sqlite3GlobalConfig.xSqllog( - sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1 - ); - sqlite3DbFree(v->db, zExpanded); - } - } -} -#else -# define vdbeInvokeSqllog(x) -#endif - -/* -** Clean up a VDBE after execution but do not delete the VDBE just yet. -** Write any error messages into *pzErrMsg. Return the result code. -** -** After this routine is run, the VDBE should be ready to be executed -** again. -** -** To look at it another way, this routine resets the state of the -** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to -** VDBE_READY_STATE. -*/ -SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) - int i; -#endif - - sqlite3 *db; - db = p->db; - - /* If the VM did not run to completion or if it encountered an - ** error, then it might not have been halted properly. So halt - ** it now. - */ - if( p->eVdbeState==VDBE_RUN_STATE ) 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 - ** if the VDBE has just been set to run but has not actually executed any - ** instructions yet, leave the main database error information unchanged. - */ - if( p->pc>=0 ){ - vdbeInvokeSqllog(p); - if( db->pErr || p->zErrMsg ){ - sqlite3VdbeTransferError(p); - }else{ - db->errCode = p->rc; - } - } - - /* Reset register contents and reclaim error message memory. - */ -#ifdef SQLITE_DEBUG - /* Execute assert() statements to ensure that the Vdbe.apCsr[] and - ** Vdbe.aMem[] arrays have already been cleaned up. */ - if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); - if( p->aMem ){ - for(i=0; inMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); - } -#endif - if( p->zErrMsg ){ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - } - p->pResultRow = 0; -#ifdef SQLITE_DEBUG - p->nWrite = 0; -#endif - - /* Save profiling information from this VDBE run. - */ -#ifdef VDBE_PROFILE - { - FILE *out = fopen("vdbe_profile.out", "a"); - if( out ){ - fprintf(out, "---- "); - for(i=0; inOp; i++){ - fprintf(out, "%02x", p->aOp[i].opcode); - } - fprintf(out, "\n"); - if( p->zSql ){ - char c, pc = 0; - fprintf(out, "-- "); - for(i=0; (c = p->zSql[i])!=0; i++){ - if( pc=='\n' ) fprintf(out, "-- "); - putc(c, out); - pc = c; - } - if( pc!='\n' ) fprintf(out, "\n"); - } - for(i=0; inOp; i++){ - char zHdr[100]; - i64 cnt = p->aOp[i].nExec; - i64 cycles = p->aOp[i].nCycle; - sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", - cnt, - cycles, - cnt>0 ? cycles/cnt : 0 - ); - fprintf(out, "%s", zHdr); - sqlite3VdbePrintOp(out, i, &p->aOp[i]); - } - fclose(out); - } - } -#endif - return p->rc & db->errMask; -} - -/* -** Clean up and delete a VDBE after execution. Return an integer which is -** the result code. Write any error message text into *pzErrMsg. -*/ -SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ - int rc = SQLITE_OK; - assert( VDBE_RUN_STATE>VDBE_READY_STATE ); - assert( VDBE_HALT_STATE>VDBE_READY_STATE ); - assert( VDBE_INIT_STATEeVdbeState>=VDBE_READY_STATE ){ - rc = sqlite3VdbeReset(p); - assert( (rc & p->db->errMask)==rc ); - } - sqlite3VdbeDelete(p); - return rc; -} - -/* -** If parameter iOp is less than zero, then invoke the destructor for -** all auxiliary data pointers currently cached by the VM passed as -** the first argument. -** -** Or, if iOp is greater than or equal to zero, then the destructor is -** only invoked for those auxiliary data pointers created by the user -** function invoked by the OP_Function opcode at instruction iOp of -** VM pVdbe, and only then if: -** -** * the associated function parameter is the 32nd or later (counting -** from left to right), or -** -** * the corresponding bit in argument mask is clear (where the first -** function parameter corresponds to bit 0 etc.). -*/ -SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, int mask){ - while( *pp ){ - AuxData *pAux = *pp; - if( (iOp<0) - || (pAux->iAuxOp==iOp - && pAux->iAuxArg>=0 - && (pAux->iAuxArg>31 || !(mask & MASKBIT32(pAux->iAuxArg)))) - ){ - testcase( pAux->iAuxArg==31 ); - if( pAux->xDeleteAux ){ - pAux->xDeleteAux(pAux->pAux); - } - *pp = pAux->pNextAux; - sqlite3DbFree(db, pAux); - }else{ - pp= &pAux->pNextAux; - } - } -} - -/* -** Free all memory associated with the Vdbe passed as the second argument, -** except for object itself, which is preserved. -** -** The difference between this function and sqlite3VdbeDelete() is that -** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with -** the database connection and frees the object itself. -*/ -static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ - SubProgram *pSub, *pNext; - assert( db!=0 ); - assert( p->db==0 || p->db==db ); - if( p->aColName ){ - releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); - sqlite3DbNNFreeNN(db, p->aColName); - } - for(pSub=p->pProgram; pSub; pSub=pNext){ - pNext = pSub->pNext; - vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); - sqlite3DbFree(db, pSub); - } - if( p->eVdbeState!=VDBE_INIT_STATE ){ - releaseMemArray(p->aVar, p->nVar); - if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList); - if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree); - } - vdbeFreeOpArray(db, p->aOp, p->nOp); - if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql); -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3DbFree(db, p->zNormSql); - { - DblquoteStr *pThis, *pNxt; - for(pThis=p->pDblStr; pThis; pThis=pNxt){ - pNxt = pThis->pNextStr; - sqlite3DbFree(db, pThis); - } - } -#endif -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - { - int i; - for(i=0; inScan; i++){ - sqlite3DbFree(db, p->aScan[i].zName); - } - sqlite3DbFree(db, p->aScan); - } -#endif -} - -/* -** Delete an entire VDBE. -*/ -SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ - sqlite3 *db; - - assert( p!=0 ); - db = p->db; - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - sqlite3VdbeClearObject(db, p); - if( db->pnBytesFreed==0 ){ - assert( p->ppVPrev!=0 ); - *p->ppVPrev = p->pVNext; - if( p->pVNext ){ - p->pVNext->ppVPrev = p->ppVPrev; - } - } - sqlite3DbNNFreeNN(db, p); -} - -/* -** The cursor "p" has a pending seek operation that has not yet been -** carried out. Seek the cursor now. If an error occurs, return -** the appropriate error code. -*/ -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){ - int res, rc; -#ifdef SQLITE_TEST - extern int sqlite3_search_count; -#endif - assert( p->deferredMoveto ); - assert( p->isTable ); - assert( p->eCurType==CURTYPE_BTREE ); - rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res); - if( rc ) return rc; - if( res!=0 ) return SQLITE_CORRUPT_BKPT; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - p->deferredMoveto = 0; - p->cacheStatus = CACHE_STALE; - return SQLITE_OK; -} - -/* -** Something has moved cursor "p" out of place. Maybe the row it was -** pointed to was deleted out from under it. Or maybe the btree was -** rebalanced. Whatever the cause, try to restore "p" to the place it -** is supposed to be pointing. If the row was deleted out from under the -** cursor, set the cursor to point to a NULL row. -*/ -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p){ - int isDifferentRow, rc; - assert( p->eCurType==CURTYPE_BTREE ); - assert( p->uc.pCursor!=0 ); - assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ); - rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow); - p->cacheStatus = CACHE_STALE; - if( isDifferentRow ) p->nullRow = 1; - return rc; -} - -/* -** Check to ensure that the cursor is valid. Restore the cursor -** if need be. Return any I/O error from the restore operation. -*/ -SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ - assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) ); - if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return sqlite3VdbeHandleMovedCursor(p); - } - return SQLITE_OK; -} - -/* -** The following functions: -** -** sqlite3VdbeSerialType() -** sqlite3VdbeSerialTypeLen() -** sqlite3VdbeSerialLen() -** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02 -** sqlite3VdbeSerialGet() -** -** encapsulate the code that serializes values for storage in SQLite -** data and index records. Each serialized value consists of a -** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned -** integer, stored as a varint. -** -** In an SQLite index record, the serial type is stored directly before -** the blob of data that it corresponds to. In a table record, all serial -** types are stored at the start of the record, and the blobs of data at -** the end. Hence these functions allow the caller to handle the -** serial-type and data blob separately. -** -** The following table describes the various storage classes for data: -** -** serial type bytes of data type -** -------------- --------------- --------------- -** 0 0 NULL -** 1 1 signed integer -** 2 2 signed integer -** 3 3 signed integer -** 4 4 signed integer -** 5 6 signed integer -** 6 8 signed integer -** 7 8 IEEE float -** 8 0 Integer constant 0 -** 9 0 Integer constant 1 -** 10,11 reserved for expansion -** N>=12 and even (N-12)/2 BLOB -** N>=13 and odd (N-13)/2 text -** -** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions -** of SQLite will not understand those serial types. -*/ - -#if 0 /* Inlined into the OP_MakeRecord opcode */ -/* -** Return the serial-type for the value stored in pMem. -** -** This routine might convert a large MEM_IntReal value into MEM_Real. -** -** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord -** opcode in the byte-code engine. But by moving this routine in-line, we -** can omit some redundant tests and make that opcode a lot faster. So -** this routine is now only used by the STAT3 logic and STAT3 support has -** ended. The code is kept here for historical reference only. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ - int flags = pMem->flags; - u32 n; - - assert( pLen!=0 ); - if( flags&MEM_Null ){ - *pLen = 0; - return 0; - } - if( flags&(MEM_Int|MEM_IntReal) ){ - /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ -# define MAX_6BYTE ((((i64)0x00008000)<<32)-1) - i64 i = pMem->u.i; - u64 u; - testcase( flags & MEM_Int ); - testcase( flags & MEM_IntReal ); - if( i<0 ){ - u = ~i; - }else{ - u = i; - } - if( u<=127 ){ - if( (i&1)==i && file_format>=4 ){ - *pLen = 0; - return 8+(u32)u; - }else{ - *pLen = 1; - return 1; - } - } - if( u<=32767 ){ *pLen = 2; return 2; } - if( u<=8388607 ){ *pLen = 3; return 3; } - if( u<=2147483647 ){ *pLen = 4; return 4; } - if( u<=MAX_6BYTE ){ *pLen = 6; return 5; } - *pLen = 8; - if( flags&MEM_IntReal ){ - /* If the value is IntReal and is going to take up 8 bytes to store - ** as an integer, then we might as well make it an 8-byte floating - ** point value */ - pMem->u.r = (double)pMem->u.i; - pMem->flags &= ~MEM_IntReal; - pMem->flags |= MEM_Real; - return 7; - } - return 6; - } - if( flags&MEM_Real ){ - *pLen = 8; - return 7; - } - assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); - assert( pMem->n>=0 ); - n = (u32)pMem->n; - if( flags & MEM_Zero ){ - n += pMem->u.nZero; - } - *pLen = n; - return ((n*2) + 12 + ((flags&MEM_Str)!=0)); -} -#endif /* inlined into OP_MakeRecord */ - -/* -** The sizes for serial types less than 128 -*/ -SQLITE_PRIVATE const u8 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, -/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, -/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, -/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, -/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, -/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, -/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, -/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, -/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, -/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, -/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, -/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57 -}; - -/* -** Return the length of the data corresponding to the supplied serial-type. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ - if( serial_type>=128 ){ - return (serial_type-12)/2; - }else{ - assert( serial_type<12 - || sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 ); - return sqlite3SmallTypeSizes[serial_type]; - } -} -SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){ - assert( serial_type<128 ); - return sqlite3SmallTypeSizes[serial_type]; -} - -/* -** If we are on an architecture with mixed-endian floating -** points (ex: ARM7) then swap the lower 4 bytes with the -** upper 4 bytes. Return the result. -** -** For most architectures, this is a no-op. -** -** (later): It is reported to me that the mixed-endian problem -** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems -** that early versions of GCC stored the two words of a 64-bit -** float in the wrong order. And that error has been propagated -** ever since. The blame is not necessarily with GCC, though. -** GCC might have just copying the problem from a prior compiler. -** I am also told that newer versions of GCC that follow a different -** ABI get the byte order right. -** -** Developers using SQLite on an ARM7 should compile and run their -** application using -DSQLITE_DEBUG=1 at least once. With DEBUG -** enabled, some asserts below will ensure that the byte order of -** floating point values is correct. -** -** (2007-08-30) Frank van Vugt has studied this problem closely -** and has send his findings to the SQLite developers. Frank -** writes that some Linux kernels offer floating point hardware -** emulation that uses only 32-bit mantissas instead of a full -** 48-bits as required by the IEEE standard. (This is the -** CONFIG_FPE_FASTFPE option.) On such systems, floating point -** byte swapping becomes very complicated. To avoid problems, -** the necessary byte swapping is carried out using a 64-bit integer -** rather than a 64-bit float. Frank assures us that the code here -** works for him. We, the developers, have no way to independently -** verify this, but Frank seems to know what he is talking about -** so we trust him. -*/ -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in){ - union { - u64 r; - u32 i[2]; - } u; - u32 t; - - u.r = in; - t = u.i[0]; - u.i[0] = u.i[1]; - u.i[1] = t; - return u.r; -} -#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */ - - -/* Input "x" is a sequence of unsigned characters that represent a -** big-endian integer. Return the equivalent native integer -*/ -#define ONE_BYTE_INT(x) ((i8)(x)[0]) -#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) -#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) -#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) -#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) - -/* -** Deserialize the data blob pointed to by buf as serial type serial_type -** and store the result in pMem. -** -** 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 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 */ -){ - u64 x = FOUR_BYTE_UINT(buf); - u32 y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) + y; - if( serial_type==6 ){ - /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit - ** twos-complement integer. */ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - }else{ - /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit - ** floating point number. */ -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->u.r, &x, sizeof(x)); - pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; - } -} -static int serialGet7( - const unsigned char *buf, /* Buffer to deserialize from */ - Mem *pMem /* Memory cell to write value into */ -){ - u64 x = FOUR_BYTE_UINT(buf); - u32 y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) + y; - assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->u.r, &x, sizeof(x)); - if( IsNaN(x) ){ - pMem->flags = MEM_Null; - return 1; - } - pMem->flags = MEM_Real; - return 0; -} -SQLITE_PRIVATE void sqlite3VdbeSerialGet( - const unsigned char *buf, /* Buffer to deserialize from */ - u32 serial_type, /* Serial type to deserialize */ - Mem *pMem /* Memory cell to write value into */ -){ - switch( serial_type ){ - case 10: { /* Internal use only: NULL with virtual table - ** UPDATE no-change flag set */ - pMem->flags = MEM_Null|MEM_Zero; - pMem->n = 0; - pMem->u.nZero = 0; - return; - } - case 11: /* Reserved for future use */ - case 0: { /* Null */ - /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ - pMem->flags = MEM_Null; - return; - } - case 1: { - /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement - ** integer. */ - pMem->u.i = ONE_BYTE_INT(buf); - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return; - } - case 2: { /* 2-byte signed integer */ - /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit - ** twos-complement integer. */ - pMem->u.i = TWO_BYTE_INT(buf); - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return; - } - case 3: { /* 3-byte signed integer */ - /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit - ** twos-complement integer. */ - pMem->u.i = THREE_BYTE_INT(buf); - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return; - } - case 4: { /* 4-byte signed integer */ - /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit - ** twos-complement integer. */ - pMem->u.i = FOUR_BYTE_INT(buf); -#ifdef __HP_cc - /* Work around a sign-extension bug in the HP compiler for HP/UX */ - if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL; -#endif - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return; - } - case 5: { /* 6-byte signed integer */ - /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit - ** twos-complement integer. */ - 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; - } - 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 */ - serialGet(buf,serial_type,pMem); - return; - } - case 8: /* Integer 0 */ - case 9: { /* Integer 1 */ - /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */ - /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ - pMem->u.i = serial_type-8; - pMem->flags = MEM_Int; - return; - } - default: { - /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in - ** length. - ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and - ** (N-13)/2 bytes in length. */ - static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; - pMem->z = (char *)buf; - pMem->n = (serial_type-12)/2; - pMem->flags = aFlag[serial_type&1]; - return; - } - } - return; -} -/* -** This routine is used to allocate sufficient space for an UnpackedRecord -** structure large enough to be used with sqlite3VdbeRecordUnpack() if -** the first argument is a pointer to KeyInfo structure pKeyInfo. -** -** The space is either allocated using sqlite3DbMallocRaw() or from within -** the unaligned buffer passed via the second and third arguments (presumably -** stack space). If the former, then *ppFree is set to a pointer that should -** be eventually freed by the caller using sqlite3DbFree(). Or, if the -** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL -** before returning. -** -** If an OOM error occurs, NULL is returned. -*/ -SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( - KeyInfo *pKeyInfo /* Description of the record */ -){ - UnpackedRecord *p; /* Unpacked record to return */ - int nByte; /* Number of bytes required for *p */ - assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff ); - nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); - p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); - if( !p ) return 0; - p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))]; - assert( pKeyInfo->aSortFlags!=0 ); - p->pKeyInfo = pKeyInfo; - p->nField = pKeyInfo->nKeyField + 1; - return p; -} - -/* -** Given the nKey-byte encoding of a record in pKey[], populate the -** UnpackedRecord structure indicated by the fourth argument with the -** contents of the decoded record. -*/ -SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( - KeyInfo *pKeyInfo, /* Information about the record format */ - int nKey, /* Size of the binary record */ - const void *pKey, /* The binary record */ - UnpackedRecord *p /* Populate this structure before returning. */ -){ - const unsigned char *aKey = (const unsigned char *)pKey; - u32 d; - u32 idx; /* Offset in aKey[] to read from */ - u16 u; /* Unsigned loop counter */ - u32 szHdr; - Mem *pMem = p->aMem; - - p->default_rc = 0; - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - idx = getVarint32(aKey, szHdr); - d = szHdr; - u = 0; - while( idxenc = pKeyInfo->enc; - pMem->db = pKeyInfo->db; - /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ - pMem->szMalloc = 0; - pMem->z = 0; - sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); - d += sqlite3VdbeSerialTypeLen(serial_type); - pMem++; - if( (++u)>=p->nField ) break; - } - if( d>(u32)nKey && u ){ - assert( CORRUPT_DB ); - /* In a corrupt record entry, the last pMem might have been set up using - ** uninitialized memory. Overwrite its value with NULL, to prevent - ** warnings from MSAN. */ - sqlite3VdbeMemSetNull(pMem-1); - } - assert( u<=pKeyInfo->nKeyField + 1 ); - p->nField = u; -} - -#ifdef SQLITE_DEBUG -/* -** This function compares two index or table record keys in the same way -** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), -** this function deserializes and compares values using the -** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used -** in assert() statements to ensure that the optimized code in -** sqlite3VdbeRecordCompare() returns results with these two primitives. -** -** Return true if the result of comparison is equivalent to desiredResult. -** Return false if there is a disagreement. -*/ -static int vdbeRecordCompareDebug( - int nKey1, const void *pKey1, /* Left key */ - const UnpackedRecord *pPKey2, /* Right key */ - int desiredResult /* Correct answer */ -){ - u32 d1; /* Offset into aKey[] of next data element */ - u32 idx1; /* Offset into aKey[] of next header element */ - u32 szHdr1; /* Number of bytes in header */ - int i = 0; - int rc = 0; - const unsigned char *aKey1 = (const unsigned char *)pKey1; - KeyInfo *pKeyInfo; - Mem mem1; - - pKeyInfo = pPKey2->pKeyInfo; - if( pKeyInfo->db==0 ) return 1; - mem1.enc = pKeyInfo->enc; - mem1.db = pKeyInfo->db; - /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ - VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ - - /* Compilers may complain that mem1.u.i is potentially uninitialized. - ** We could initialize it, as shown here, to silence those complaints. - ** But in fact, mem1.u.i will never actually be used uninitialized, and doing - ** the unnecessary initialization has a measurable negative performance - ** impact, since this routine is a very high runner. And so, we choose - ** to ignore the compiler warnings and leave this variable uninitialized. - */ - /* mem1.u.i = 0; // not needed, here to silence compiler warning */ - - idx1 = getVarint32(aKey1, szHdr1); - if( szHdr1>98307 ) return SQLITE_CORRUPT; - d1 = szHdr1; - assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pKeyInfo->aSortFlags!=0 ); - assert( pKeyInfo->nKeyField>0 ); - assert( idx1<=szHdr1 || CORRUPT_DB ); - do{ - u32 serial_type1; - - /* Read the serial types for the next element in each key. */ - idx1 += getVarint32( aKey1+idx1, serial_type1 ); - - /* Verify that there is enough key space remaining to avoid - ** a buffer overread. The "d1+serial_type1+2" subexpression will - ** always be greater than or equal to the amount of required key space. - ** Use that approximation to avoid the more expensive call to - ** sqlite3VdbeSerialTypeLen() in the common case. - */ - if( d1+(u64)serial_type1+2>(u64)nKey1 - && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 - ){ - if( serial_type1>=1 - && serial_type1<=7 - && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)<=(u64)nKey1+8 - && CORRUPT_DB - ){ - return 1; /* corrupt record not detected by - ** sqlite3VdbeRecordCompareWithSkip(). Return true - ** to avoid firing the assert() */ - } - break; - } - - /* Extract the values to be compared. - */ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - d1 += sqlite3VdbeSerialTypeLen(serial_type1); - - /* Do the comparison - */ - rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], - pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0); - if( rc!=0 ){ - assert( mem1.szMalloc==0 ); /* See comment below */ - if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) - && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null)) - ){ - rc = -rc; - } - if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){ - rc = -rc; /* Invert the result for DESC sort order. */ - } - goto debugCompareEnd; - } - i++; - }while( idx1nField ); - - /* No memory allocation is ever used on mem1. Prove this using - ** the following assert(). If the assert() fails, it indicates a - ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). - */ - assert( mem1.szMalloc==0 ); - - /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. Return the default_rc - ** value. */ - rc = pPKey2->default_rc; - -debugCompareEnd: - if( desiredResult==0 && rc==0 ) return 1; - if( desiredResult<0 && rc<0 ) return 1; - if( desiredResult>0 && rc>0 ) return 1; - if( CORRUPT_DB ) return 1; - if( pKeyInfo->db->mallocFailed ) return 1; - return 0; -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Count the number of fields (a.k.a. columns) in the record given by -** pKey,nKey. The verify that this count is less than or equal to the -** limit given by pKeyInfo->nAllField. -** -** If this constraint is not satisfied, it means that the high-speed -** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will -** not work correctly. If this assert() ever fires, it probably means -** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed -** incorrectly. -*/ -static void vdbeAssertFieldCountWithinLimits( - int nKey, const void *pKey, /* The record to verify */ - const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ -){ - int nField = 0; - u32 szHdr; - u32 idx; - u32 notUsed; - const unsigned char *aKey = (const unsigned char*)pKey; - - if( CORRUPT_DB ) return; - idx = getVarint32(aKey, szHdr); - assert( nKey>=0 ); - assert( szHdr<=(u32)nKey ); - while( idxnAllField ); -} -#else -# define vdbeAssertFieldCountWithinLimits(A,B,C) -#endif - -/* -** Both *pMem1 and *pMem2 contain string values. Compare the two values -** using the collation sequence pColl. As usual, return a negative , zero -** or positive value if *pMem1 is less than, equal to or greater than -** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". -*/ -static int vdbeCompareMemString( - const Mem *pMem1, - const Mem *pMem2, - const CollSeq *pColl, - u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */ -){ - if( pMem1->enc==pColl->enc ){ - /* The strings are already in the correct encoding. Call the - ** comparison function directly */ - return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); - }else{ - int rc; - const void *v1, *v2; - Mem c1; - Mem c2; - sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); - sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); - sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); - sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); - v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - if( (v1==0 || v2==0) ){ - if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT; - rc = 0; - }else{ - rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); - } - sqlite3VdbeMemReleaseMalloc(&c1); - sqlite3VdbeMemReleaseMalloc(&c2); - return rc; - } -} - -/* -** The input pBlob is guaranteed to be a Blob that is not marked -** with MEM_Zero. Return true if it could be a zero-blob. -*/ -static int isAllZero(const char *z, int n){ - int i; - for(i=0; in; - int n2 = pB2->n; - - /* It is possible to have a Blob value that has some non-zero content - ** followed by zero content. But that only comes up for Blobs formed - ** by the OP_MakeRecord opcode, and such Blobs never get passed into - ** sqlite3MemCompare(). */ - assert( (pB1->flags & MEM_Zero)==0 || n1==0 ); - assert( (pB2->flags & MEM_Zero)==0 || n2==0 ); - - if( (pB1->flags|pB2->flags) & MEM_Zero ){ - if( pB1->flags & pB2->flags & MEM_Zero ){ - return pB1->u.nZero - pB2->u.nZero; - }else if( pB1->flags & MEM_Zero ){ - if( !isAllZero(pB2->z, pB2->n) ) return -1; - return pB1->u.nZero - n2; - }else{ - if( !isAllZero(pB1->z, pB1->n) ) return +1; - return n1 - pB2->u.nZero; - } - } - c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1); - if( c ) return c; - return n1 - n2; -} - -/* The following two functions are used only within testcase() to prove -** test coverage. These functions do no exist for production builds. -** We must use separate SQLITE_NOINLINE functions here, since otherwise -** optimizer code movement causes gcov to become very confused. -*/ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) -static int SQLITE_NOINLINE doubleLt(double a, double b){ return a=9223372036854775808.0 ) return -1; - y = (i64)r; - if( iy ) return +1; - testcase( doubleLt(((double)i),r) ); - testcase( doubleLt(r,((double)i)) ); - testcase( doubleEq(r,((double)i)) ); - return (((double)i)r); - } -} - -/* -** Compare the values contained by the two memory cells, returning -** negative, zero or positive if pMem1 is less than, equal to, or greater -** than pMem2. Sorting order is NULL's first, followed by numbers (integers -** and reals) sorted numerically, followed by text ordered by the collating -** sequence pColl and finally blob's ordered by memcmp(). -** -** Two NULL values are considered equal by this function. -*/ -SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ - int f1, f2; - int combined_flags; - - f1 = pMem1->flags; - f2 = pMem2->flags; - combined_flags = f1|f2; - assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) ); - - /* If one value is NULL, it is less than the other. If both values - ** are NULL, return 0. - */ - if( combined_flags&MEM_Null ){ - return (f2&MEM_Null) - (f1&MEM_Null); - } - - /* At least one of the two values is a number - */ - if( combined_flags&(MEM_Int|MEM_Real|MEM_IntReal) ){ - testcase( combined_flags & MEM_Int ); - testcase( combined_flags & MEM_Real ); - testcase( combined_flags & MEM_IntReal ); - if( (f1 & f2 & (MEM_Int|MEM_IntReal))!=0 ){ - testcase( f1 & f2 & MEM_Int ); - testcase( f1 & f2 & MEM_IntReal ); - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return +1; - return 0; - } - if( (f1 & f2 & MEM_Real)!=0 ){ - if( pMem1->u.r < pMem2->u.r ) return -1; - if( pMem1->u.r > pMem2->u.r ) return +1; - return 0; - } - if( (f1&(MEM_Int|MEM_IntReal))!=0 ){ - testcase( f1 & MEM_Int ); - testcase( f1 & MEM_IntReal ); - if( (f2&MEM_Real)!=0 ){ - return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r); - }else if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return +1; - return 0; - }else{ - return -1; - } - } - if( (f1&MEM_Real)!=0 ){ - if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ - testcase( f2 & MEM_Int ); - testcase( f2 & MEM_IntReal ); - return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r); - }else{ - return -1; - } - } - return +1; - } - - /* If one value is a string and the other is a blob, the string is less. - ** If both are strings, compare using the collating functions. - */ - if( combined_flags&MEM_Str ){ - if( (f1 & MEM_Str)==0 ){ - return 1; - } - if( (f2 & MEM_Str)==0 ){ - return -1; - } - - assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed ); - assert( pMem1->enc==SQLITE_UTF8 || - pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); - - /* The collation sequence must be defined at this point, even if - ** the user deletes the collation sequence after the vdbe program is - ** compiled (this was not always the case). - */ - assert( !pColl || pColl->xCmp ); - - if( pColl ){ - return vdbeCompareMemString(pMem1, pMem2, pColl, 0); - } - /* If a NULL pointer was passed as the collate function, fall through - ** to the blob case and use memcmp(). */ - } - - /* Both values must be blobs. Compare using memcmp(). */ - return sqlite3BlobCompare(pMem1, pMem2); -} - - -/* -** The first argument passed to this function is a serial-type that -** corresponds to an integer - all values between 1 and 9 inclusive -** except 7. The second points to a buffer containing an integer value -** serialized according to serial_type. This function deserializes -** and returns the value. -*/ -static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ - u32 y; - assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); - switch( serial_type ){ - case 0: - case 1: - testcase( aKey[0]&0x80 ); - return ONE_BYTE_INT(aKey); - case 2: - testcase( aKey[0]&0x80 ); - return TWO_BYTE_INT(aKey); - case 3: - testcase( aKey[0]&0x80 ); - return THREE_BYTE_INT(aKey); - case 4: { - testcase( aKey[0]&0x80 ); - y = FOUR_BYTE_UINT(aKey); - return (i64)*(int*)&y; - } - case 5: { - testcase( aKey[0]&0x80 ); - return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); - } - case 6: { - u64 x = FOUR_BYTE_UINT(aKey); - testcase( aKey[0]&0x80 ); - x = (x<<32) | FOUR_BYTE_UINT(aKey+4); - return (i64)*(i64*)&x; - } - } - - return (serial_type - 8); -} - -/* -** This function compares the two table rows or index records -** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or -** greater than key2. The {nKey1, pKey1} key must be a blob -** created by the OP_MakeRecord opcode of the VDBE. The pPKey2 -** key must be a parsed key such as obtained from -** sqlite3VdbeParseRecord. -** -** If argument bSkip is non-zero, it is assumed that the caller has already -** determined that the first fields of the keys are equal. -** -** Key1 and Key2 do not have to contain the same number of fields. If all -** fields that appear in both keys are equal, then pPKey2->default_rc is -** returned. -** -** If database corruption is discovered, set pPKey2->errCode to -** SQLITE_CORRUPT and return 0. If an OOM error is encountered, -** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the -** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). -*/ -SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2, /* Right key */ - int bSkip /* If true, skip the first field */ -){ - u32 d1; /* Offset into aKey[] of next data element */ - int i; /* Index of next field to compare */ - u32 szHdr1; /* Size of record header in bytes */ - u32 idx1; /* Offset of first type in header */ - int rc = 0; /* Return value */ - Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ - KeyInfo *pKeyInfo; - const unsigned char *aKey1 = (const unsigned char *)pKey1; - Mem mem1; - - /* If bSkip is true, then the caller has already determined that the first - ** two elements in the keys are equal. Fix the various stack variables so - ** that this routine begins comparing at the second field. */ - if( bSkip ){ - u32 s1 = aKey1[1]; - if( s1<0x80 ){ - idx1 = 2; - }else{ - idx1 = 1 + sqlite3GetVarint32(&aKey1[1], &s1); - } - szHdr1 = aKey1[0]; - d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); - i = 1; - pRhs++; - }else{ - if( (szHdr1 = aKey1[0])<0x80 ){ - idx1 = 1; - }else{ - idx1 = sqlite3GetVarint32(aKey1, &szHdr1); - } - d1 = szHdr1; - i = 0; - } - if( d1>(unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corruption */ - } - - VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ - assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField - || CORRUPT_DB ); - assert( pPKey2->pKeyInfo->aSortFlags!=0 ); - assert( pPKey2->pKeyInfo->nKeyField>0 ); - assert( idx1<=szHdr1 || CORRUPT_DB ); - while( 1 /*exit-by-break*/ ){ - u32 serial_type; - - /* RHS is an integer */ - if( pRhs->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pRhs->flags & MEM_Int ); - testcase( pRhs->flags & MEM_IntReal ); - serial_type = aKey1[idx1]; - testcase( serial_type==12 ); - if( serial_type>=10 ){ - rc = serial_type==10 ? -1 : +1; - }else if( serial_type==0 ){ - rc = -1; - }else if( serial_type==7 ){ - serialGet7(&aKey1[d1], &mem1); - rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); - }else{ - i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); - i64 rhs = pRhs->u.i; - if( lhsrhs ){ - rc = +1; - } - } - } - - /* RHS is real */ - else if( pRhs->flags & MEM_Real ){ - serial_type = aKey1[idx1]; - if( serial_type>=10 ){ - /* Serial types 12 or greater are strings and blobs (greater than - ** numbers). Types 10 and 11 are currently "reserved for future - ** use", so it doesn't really matter what the results of comparing - ** them to numeric values are. */ - rc = serial_type==10 ? -1 : +1; - }else if( serial_type==0 ){ - rc = -1; - }else{ - if( serial_type==7 ){ - if( serialGet7(&aKey1[d1], &mem1) ){ - rc = -1; /* mem1 is a NaN */ - }else if( mem1.u.ru.r ){ - rc = -1; - }else if( mem1.u.r>pRhs->u.r ){ - rc = +1; - }else{ - assert( rc==0 ); - } - }else{ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); - rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); - } - } - } - - /* RHS is a string */ - else if( pRhs->flags & MEM_Str ){ - getVarint32NR(&aKey1[idx1], serial_type); - testcase( serial_type==12 ); - if( serial_type<12 ){ - rc = -1; - }else if( !(serial_type & 0x01) ){ - rc = +1; - }else{ - mem1.n = (serial_type - 12) / 2; - testcase( (d1+mem1.n)==(unsigned)nKey1 ); - testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); - if( (d1+mem1.n) > (unsigned)nKey1 - || (pKeyInfo = pPKey2->pKeyInfo)->nAllField<=i - ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corruption */ - }else if( pKeyInfo->aColl[i] ){ - mem1.enc = pKeyInfo->enc; - mem1.db = pKeyInfo->db; - mem1.flags = MEM_Str; - mem1.z = (char*)&aKey1[d1]; - rc = vdbeCompareMemString( - &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode - ); - }else{ - int nCmp = MIN(mem1.n, pRhs->n); - rc = memcmp(&aKey1[d1], pRhs->z, nCmp); - if( rc==0 ) rc = mem1.n - pRhs->n; - } - } - } - - /* RHS is a blob */ - else if( pRhs->flags & MEM_Blob ){ - assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 ); - getVarint32NR(&aKey1[idx1], serial_type); - testcase( serial_type==12 ); - if( serial_type<12 || (serial_type & 0x01) ){ - rc = -1; - }else{ - int nStr = (serial_type - 12) / 2; - testcase( (d1+nStr)==(unsigned)nKey1 ); - testcase( (d1+nStr+1)==(unsigned)nKey1 ); - if( (d1+nStr) > (unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corruption */ - }else if( pRhs->flags & MEM_Zero ){ - if( !isAllZero((const char*)&aKey1[d1],nStr) ){ - rc = 1; - }else{ - rc = nStr - pRhs->u.nZero; - } - }else{ - int nCmp = MIN(nStr, pRhs->n); - rc = memcmp(&aKey1[d1], pRhs->z, nCmp); - if( rc==0 ) rc = nStr - pRhs->n; - } - } - } - - /* RHS is null */ - else{ - serial_type = aKey1[idx1]; - if( serial_type==0 - || serial_type==10 - || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0) - ){ - assert( rc==0 ); - }else{ - rc = 1; - } - } - - if( rc!=0 ){ - int sortFlags = pPKey2->pKeyInfo->aSortFlags[i]; - if( sortFlags ){ - if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0 - || ((sortFlags & KEYINFO_ORDER_DESC) - !=(serial_type==0 || (pRhs->flags&MEM_Null))) - ){ - rc = -rc; - } - } - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); - assert( mem1.szMalloc==0 ); /* See comment below */ - return rc; - } - - i++; - if( i==pPKey2->nField ) break; - pRhs++; - d1 += sqlite3VdbeSerialTypeLen(serial_type); - if( d1>(unsigned)nKey1 ) break; - idx1 += sqlite3VarintLen(serial_type); - if( idx1>=(unsigned)szHdr1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corrupt index */ - } - } - - /* No memory allocation is ever used on mem1. Prove this using - ** the following assert(). If the assert() fails, it indicates a - ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ - assert( mem1.szMalloc==0 ); - - /* rc==0 here means that one or both of the keys ran out of fields and - ** all the fields up to that point were equal. Return the default_rc - ** value. */ - assert( CORRUPT_DB - || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) - || pPKey2->pKeyInfo->db->mallocFailed - ); - pPKey2->eqSeen = 1; - return pPKey2->default_rc; -} -SQLITE_PRIVATE int sqlite3VdbeRecordCompare( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); -} - - -/* -** This function is an optimized version of sqlite3VdbeRecordCompare() -** that (a) the first field of pPKey2 is an integer, and (b) the -** size-of-header varint at the start of (pKey1/nKey1) fits in a single -** byte (i.e. is less than 128). -** -** To avoid concerns about buffer overreads, this routine is only used -** on schemas where the maximum valid header size is 63 bytes or less. -*/ -static int vdbeRecordCompareInt( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; - int serial_type = ((const u8*)pKey1)[1]; - int res; - u32 y; - u64 x; - i64 v; - i64 lhs; - - vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); - assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); - switch( serial_type ){ - case 1: { /* 1-byte signed integer */ - lhs = ONE_BYTE_INT(aKey); - testcase( lhs<0 ); - break; - } - case 2: { /* 2-byte signed integer */ - lhs = TWO_BYTE_INT(aKey); - testcase( lhs<0 ); - break; - } - case 3: { /* 3-byte signed integer */ - lhs = THREE_BYTE_INT(aKey); - testcase( lhs<0 ); - break; - } - case 4: { /* 4-byte signed integer */ - y = FOUR_BYTE_UINT(aKey); - lhs = (i64)*(int*)&y; - testcase( lhs<0 ); - break; - } - case 5: { /* 6-byte signed integer */ - lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); - testcase( lhs<0 ); - break; - } - case 6: { /* 8-byte signed integer */ - x = FOUR_BYTE_UINT(aKey); - x = (x<<32) | FOUR_BYTE_UINT(aKey+4); - lhs = *(i64*)&x; - testcase( lhs<0 ); - break; - } - case 8: - lhs = 0; - break; - case 9: - lhs = 1; - break; - - /* This case could be removed without changing the results of running - ** this code. Including it causes gcc to generate a faster switch - ** statement (since the range of switch targets now starts at zero and - ** is contiguous) but does not cause any duplicate code to be generated - ** (as gcc is clever enough to combine the two like cases). Other - ** compilers might be similar. */ - case 0: case 7: - return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); - - default: - return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); - } - - assert( pPKey2->u.i == pPKey2->aMem[0].u.i ); - v = pPKey2->u.i; - if( v>lhs ){ - res = pPKey2->r1; - }else if( vr2; - }else if( pPKey2->nField>1 ){ - /* The first fields of the two keys are equal. Compare the trailing - ** fields. */ - res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); - }else{ - /* The first fields of the two keys are equal and there are no trailing - ** fields. Return pPKey2->default_rc in this case. */ - res = pPKey2->default_rc; - pPKey2->eqSeen = 1; - } - - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) ); - return res; -} - -/* -** This function is an optimized version of sqlite3VdbeRecordCompare() -** that (a) the first field of pPKey2 is a string, that (b) the first field -** uses the collation sequence BINARY and (c) that the size-of-header varint -** at the start of (pKey1/nKey1) fits in a single byte. -*/ -static int vdbeRecordCompareString( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - const u8 *aKey1 = (const u8*)pKey1; - int serial_type; - 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 = (signed char)(aKey1[1]); - -vrcs_restart: - if( serial_type<12 ){ - if( serial_type<0 ){ - 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 */ - }else{ - int nCmp; - int nStr; - int szHdr = aKey1[0]; - - nStr = (serial_type-12) / 2; - if( (szHdr + nStr) > nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corruption */ - } - 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->n; - if( res==0 ){ - if( pPKey2->nField>1 ){ - res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); - }else{ - res = pPKey2->default_rc; - pPKey2->eqSeen = 1; - } - }else if( res>0 ){ - res = pPKey2->r2; - }else{ - res = pPKey2->r1; - } - } - } - - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) - || CORRUPT_DB - || pPKey2->pKeyInfo->db->mallocFailed - ); - return res; -} - -/* -** Return a pointer to an sqlite3VdbeRecordCompare() compatible function -** suitable for comparing serialized records to the unpacked record passed -** as the only argument. -*/ -SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ - /* varintRecordCompareInt() and varintRecordCompareString() both assume - ** that the size-of-header varint that occurs at the start of each record - ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() - ** also assumes that it is safe to overread a buffer by at least the - ** maximum possible legal header size plus 8 bytes. Because there is - ** guaranteed to be at least 74 (but not 136) bytes of padding following each - ** buffer passed to varintRecordCompareInt() this makes it convenient to - ** limit the size of the header to 64 bytes in cases where the first field - ** is an integer. - ** - ** The easiest way to enforce this limit is to consider only records with - ** 13 fields or less. If the first field is an integer, the maximum legal - ** header size is (12*5 + 1 + 1) bytes. */ - if( p->pKeyInfo->nAllField<=13 ){ - int flags = p->aMem[0].flags; - if( p->pKeyInfo->aSortFlags[0] ){ - if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ - return sqlite3VdbeRecordCompare; - } - p->r1 = 1; - p->r2 = -1; - }else{ - p->r1 = -1; - p->r2 = 1; - } - if( (flags & MEM_Int) ){ - p->u.i = p->aMem[0].u.i; - return vdbeRecordCompareInt; - } - testcase( flags & MEM_Real ); - testcase( flags & MEM_Null ); - testcase( flags & MEM_Blob ); - if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0 - && p->pKeyInfo->aColl[0]==0 - ){ - assert( flags & MEM_Str ); - p->u.z = p->aMem[0].z; - p->n = p->aMem[0].n; - return vdbeRecordCompareString; - } - } - - return sqlite3VdbeRecordCompare; -} - -/* -** pCur points at an index entry created using the OP_MakeRecord opcode. -** Read the rowid (the last field in the record) and store it in *rowid. -** Return SQLITE_OK if everything works, or an error code otherwise. -** -** pCur might be pointing to text obtained from a corrupt database file. -** So the content cannot be trusted. Do appropriate checks on the content. -*/ -SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ - i64 nCellKey = 0; - int rc; - u32 szHdr; /* Size of the header */ - u32 typeRowid; /* Serial type of the rowid */ - u32 lenRowid; /* Size of the rowid */ - Mem m, v; - - /* Get the size of the index entry. Only indices entries of less - ** than 2GiB are support - anything large must be database corruption. - ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so - ** this code can safely assume that nCellKey is 32-bits - */ - assert( sqlite3BtreeCursorIsValid(pCur) ); - nCellKey = sqlite3BtreePayloadSize(pCur); - assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); - - /* Read in the complete content of the index entry */ - sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); - if( rc ){ - return rc; - } - - /* The index entry must begin with a header size */ - getVarint32NR((u8*)m.z, szHdr); - testcase( szHdr==3 ); - testcase( szHdr==(u32)m.n ); - testcase( szHdr>0x7fffffff ); - assert( m.n>=0 ); - if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ - goto idx_rowid_corruption; - } - - /* The last field of the index should be an integer - the ROWID. - ** Verify that the last entry really is an integer. */ - getVarint32NR((u8*)&m.z[szHdr-1], typeRowid); - testcase( typeRowid==1 ); - testcase( typeRowid==2 ); - testcase( typeRowid==3 ); - testcase( typeRowid==4 ); - testcase( typeRowid==5 ); - testcase( typeRowid==6 ); - testcase( typeRowid==8 ); - testcase( typeRowid==9 ); - if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ - goto idx_rowid_corruption; - } - lenRowid = sqlite3SmallTypeSizes[typeRowid]; - testcase( (u32)m.n==szHdr+lenRowid ); - if( unlikely((u32)m.neCurType==CURTYPE_BTREE ); - pCur = pC->uc.pCursor; - assert( sqlite3BtreeCursorIsValid(pCur) ); - nCellKey = sqlite3BtreePayloadSize(pCur); - /* nCellKey will always be between 0 and 0xffffffff because of the way - ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ - if( nCellKey<=0 || nCellKey>0x7fffffff ){ - *res = 0; - return SQLITE_CORRUPT_BKPT; - } - sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); - if( rc ){ - return rc; - } - *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0); - sqlite3VdbeMemReleaseMalloc(&m); - return SQLITE_OK; -} - -/* -** This routine sets the value to be returned by subsequent calls to -** sqlite3_changes() on the database handle 'db'. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){ - assert( sqlite3_mutex_held(db->mutex) ); - db->nChange = nChange; - db->nTotalChange += nChange; -} - -/* -** Set a flag in the vdbe to update the change counter when it is finalised -** or reset. -*/ -SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){ - v->changeCntOn = 1; -} - -/* -** Mark every prepared statement associated with a database connection -** as expired. -** -** An expired statement means that recompilation of the statement is -** recommend. Statements expire when things happen that make their -** programs obsolete. Removing user-defined functions or collating -** sequences, or changing an authorization function are the types of -** things that make prepared statements obsolete. -** -** If iCode is 1, then expiration is advisory. The statement should -** be reprepared before being restarted, but if it is already running -** it is allowed to run to completion. -** -** Internally, this function just sets the Vdbe.expired flag on all -** prepared statements. The flag is set to 1 for an immediate expiration -** and set to 2 for an advisory expiration. -*/ -SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ - Vdbe *p; - for(p = db->pVdbe; p; p=p->pVNext){ - p->expired = iCode+1; - } -} - -/* -** Return the database associated with the Vdbe. -*/ -SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ - return v->db; -} - -/* -** Return the SQLITE_PREPARE flags for a Vdbe. -*/ -SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe *v){ - return v->prepFlags; -} - -/* -** Return a pointer to an sqlite3_value structure containing the value bound -** parameter iVar of VM v. Except, if the value is an SQL NULL, return -** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* -** constants) to the value before returning it. -** -** The returned value must be freed by the caller using sqlite3ValueFree(). -*/ -SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){ - assert( iVar>0 ); - if( v ){ - Mem *pMem = &v->aVar[iVar-1]; - assert( (v->db->flags & SQLITE_EnableQPSG)==0 - || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); - if( 0==(pMem->flags & MEM_Null) ){ - sqlite3_value *pRet = sqlite3ValueNew(v->db); - if( pRet ){ - sqlite3VdbeMemCopy((Mem *)pRet, pMem); - sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8); - } - return pRet; - } - } - return 0; -} - -/* -** Configure SQL variable iVar so that binding a new value to it signals -** to sqlite3_reoptimize() that re-preparing the statement may result -** in a better query plan. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ - assert( iVar>0 ); - assert( (v->db->flags & SQLITE_EnableQPSG)==0 - || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); - if( iVar>=32 ){ - v->expmask |= 0x80000000; - }else{ - v->expmask |= ((u32)1 << (iVar-1)); - } -} - -/* -** Cause a function to throw an error if it was call from OP_PureFunc -** rather than OP_Function. -** -** OP_PureFunc means that the function must be deterministic, and should -** throw an error if it is given inputs that would make it non-deterministic. -** This routine is invoked by date/time functions that use non-deterministic -** features such as 'now'. -*/ -SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){ - const VdbeOp *pOp; -#ifdef SQLITE_ENABLE_STAT4 - if( pCtx->pVdbe==0 ) return 1; -#endif - pOp = pCtx->pVdbe->aOp + pCtx->iOp; - if( pOp->opcode==OP_PureFunc ){ - const char *zContext; - char *zMsg; - if( pOp->p5 & NC_IsCheck ){ - zContext = "a CHECK constraint"; - }else if( pOp->p5 & NC_GenCol ){ - zContext = "a generated column"; - }else{ - zContext = "an index"; - } - zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s", - pCtx->pFunc->zName, zContext); - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); - return 0; - } - return 1; -} - -#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) -/* -** This Walker callback is used to help verify that calls to -** sqlite3BtreeCursorHint() with opcode BTREE_HINT_RANGE have -** byte-code register values correctly initialized. -*/ -SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_REGISTER ){ - assert( (pWalker->u.aMem[pExpr->iTable].flags & MEM_Undefined)==0 ); - } - return WRC_Continue; -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS && SQLITE_DEBUG */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored -** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored -** in memory obtained from sqlite3DbMalloc). -*/ -SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ - if( pVtab->zErrMsg ){ - sqlite3 *db = p->db; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; - } -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - -/* -** If the second argument is not NULL, release any allocations associated -** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord -** structure itself, using sqlite3DbFree(). -** -** This function is used to free UnpackedRecord structures allocated by -** the vdbeUnpackRecord() function found in vdbeapi.c. -*/ -static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){ - assert( db!=0 ); - if( p ){ - int i; - for(i=0; iaMem[i]; - if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem); - } - sqlite3DbNNFreeNN(db, p); - } -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, -** then cursor passed as the second argument should point to the row about -** to be update or deleted. If the application calls sqlite3_preupdate_old(), -** the required value will be read from the row the cursor points to. -*/ -SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( - Vdbe *v, /* Vdbe pre-update hook is invoked by */ - VdbeCursor *pCsr, /* Cursor to grab old.* values from */ - int op, /* SQLITE_INSERT, UPDATE or DELETE */ - const char *zDb, /* Database name */ - Table *pTab, /* Modified table */ - i64 iKey1, /* Initial key value */ - int iReg, /* Register for new.* record */ - int iBlobWrite -){ - sqlite3 *db = v->db; - i64 iKey2; - PreUpdate preupdate; - const char *zTbl = pTab->zName; - static const u8 fakeSortOrder = 0; -#ifdef SQLITE_DEBUG - int nRealCol; - if( pTab->tabFlags & TF_WithoutRowid ){ - nRealCol = sqlite3PrimaryKeyIndex(pTab)->nColumn; - }else if( pTab->tabFlags & TF_HasVirtual ){ - nRealCol = pTab->nNVCol; - }else{ - nRealCol = pTab->nCol; - } -#endif - - assert( db->pPreUpdate==0 ); - memset(&preupdate, 0, sizeof(PreUpdate)); - if( HasRowid(pTab)==0 ){ - iKey1 = iKey2 = 0; - preupdate.pPk = sqlite3PrimaryKeyIndex(pTab); - }else{ - if( op==SQLITE_UPDATE ){ - iKey2 = v->aMem[iReg].u.i; - }else{ - iKey2 = iKey1; - } - } - - assert( pCsr!=0 ); - assert( pCsr->eCurType==CURTYPE_BTREE ); - assert( pCsr->nField==nRealCol - || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) - ); - - preupdate.v = v; - preupdate.pCsr = pCsr; - preupdate.op = op; - preupdate.iNewReg = iReg; - preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; - preupdate.pKeyinfo->db = db; - preupdate.pKeyinfo->enc = ENC(db); - preupdate.pKeyinfo->nKeyField = pTab->nCol; - preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder; - 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); - db->pPreUpdate = 0; - sqlite3DbFree(db, preupdate.aRecord); - vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked); - vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked); - sqlite3VdbeMemRelease(&preupdate.oldipk); - if( preupdate.aNew ){ - int i; - for(i=0; inField; i++){ - sqlite3VdbeMemRelease(&preupdate.aNew[i]); - } - sqlite3DbNNFreeNN(db, preupdate.aNew); - } - if( preupdate.apDflt ){ - int i; - for(i=0; inCol; i++){ - sqlite3ValueFree(preupdate.apDflt[i]); - } - sqlite3DbFree(db, preupdate.apDflt); - } -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -/************** End of vdbeaux.c *********************************************/ -/************** Begin file vdbeapi.c *****************************************/ -/* -** 2004 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to implement APIs that are part of the -** VDBE. -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ -/* #include "opcodes.h" */ - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Return TRUE (non-zero) of the statement supplied as an argument needs -** to be recompiled. A statement needs to be recompiled whenever the -** execution environment changes in a way that would alter the program -** that sqlite3_prepare() generates. For example, if new functions or -** collating sequences are registered or if an authorizer function is -** added or changed. -*/ -SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - return p==0 || p->expired; -} -#endif - -/* -** Check on a Vdbe to make sure it has not been finalized. Log -** an error and return true if it has been finalized (or is otherwise -** invalid). Return false if it is ok. -*/ -static int vdbeSafety(Vdbe *p){ - if( p->db==0 ){ - sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); - return 1; - }else{ - return 0; - } -} -static int vdbeSafetyNotNull(Vdbe *p){ - if( p==0 ){ - sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); - return 1; - }else{ - return vdbeSafety(p); - } -} - -#ifndef SQLITE_OMIT_TRACE -/* -** Invoke the profile callback. This routine is only called if we already -** know that the profile callback is defined and needs to be invoked. -*/ -static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ - sqlite3_int64 iNow; - sqlite3_int64 iElapse; - assert( p->startTime>0 ); - assert( db->init.busy==0 ); - assert( p->zSql!=0 ); - sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); - iElapse = (iNow - p->startTime)*1000000; -#ifndef SQLITE_OMIT_DEPRECATED - if( db->xProfile ){ - db->xProfile(db->pProfileArg, p->zSql, iElapse); - } -#endif - if( db->mTrace & SQLITE_TRACE_PROFILE ){ - db->trace.xV2(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse); - } - p->startTime = 0; -} -/* -** The checkProfileCallback(DB,P) macro checks to see if a profile callback -** is needed, and it invokes the callback if it is needed. -*/ -# define checkProfileCallback(DB,P) \ - if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); } -#else -# define checkProfileCallback(DB,P) /*no-op*/ -#endif - -/* -** The following routine destroys a virtual machine that is created by -** the sqlite3_compile() routine. The integer returned is an SQLITE_ -** success/failure code that describes the result of executing the virtual -** machine. -** -** This routine sets the error code and string returned by -** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). -*/ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ - int rc; - if( pStmt==0 ){ - /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL - ** pointer is a harmless no-op. */ - rc = SQLITE_OK; - }else{ - Vdbe *v = (Vdbe*)pStmt; - sqlite3 *db = v->db; - if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; - sqlite3_mutex_enter(db->mutex); - checkProfileCallback(db, v); - assert( v->eVdbeState>=VDBE_READY_STATE ); - rc = sqlite3VdbeReset(v); - sqlite3VdbeDelete(v); - rc = sqlite3ApiExit(db, rc); - sqlite3LeaveMutexAndCloseZombie(db); - } - return rc; -} - -/* -** Terminate the current execution of an SQL statement and reset it -** back to its starting state so that it can be reused. A success code from -** the prior execution is returned. -** -** This routine sets the error code and string returned by -** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). -*/ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ - int rc; - if( pStmt==0 ){ - rc = SQLITE_OK; - }else{ - Vdbe *v = (Vdbe*)pStmt; - sqlite3 *db = v->db; - sqlite3_mutex_enter(db->mutex); - checkProfileCallback(db, v); - rc = sqlite3VdbeReset(v); - sqlite3VdbeRewind(v); - assert( (rc & (db->errMask))==rc ); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - } - return rc; -} - -/* -** Set all the parameters in the compiled SQL statement to NULL. -*/ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ - int i; - int rc = SQLITE_OK; - Vdbe *p = (Vdbe*)pStmt; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex; -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif -#if SQLITE_THREADSAFE - mutex = p->db->mutex; -#endif - sqlite3_mutex_enter(mutex); - for(i=0; inVar; i++){ - sqlite3VdbeMemRelease(&p->aVar[i]); - p->aVar[i].flags = MEM_Null; - } - assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); - if( p->expmask ){ - p->expired = 1; - } - sqlite3_mutex_leave(mutex); - return rc; -} - - -/**************************** sqlite3_value_ ******************************* -** The following routines extract information from a Mem or sqlite3_value -** structure. -*/ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ - Mem *p = (Mem*)pVal; - if( p->flags & (MEM_Blob|MEM_Str) ){ - if( ExpandBlob(p)!=SQLITE_OK ){ - assert( p->flags==MEM_Null && p->z==0 ); - return 0; - } - p->flags |= MEM_Blob; - return p->n ? p->z : 0; - }else{ - return sqlite3_value_text(pVal); - } -} -SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ - return sqlite3ValueBytes(pVal, SQLITE_UTF8); -} -SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ - return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); -} -SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ - return sqlite3VdbeRealValue((Mem*)pVal); -} -SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ - return (int)sqlite3VdbeIntValue((Mem*)pVal); -} -SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ - return sqlite3VdbeIntValue((Mem*)pVal); -} -SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ - Mem *pMem = (Mem*)pVal; - return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); -} -SQLITE_API void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){ - Mem *p = (Mem*)pVal; - if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == - (MEM_Null|MEM_Term|MEM_Subtype) - && zPType!=0 - && p->eSubtype=='p' - && strcmp(p->u.zPType, zPType)==0 - ){ - return (void*)p->z; - }else{ - return 0; - } -} -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ - return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); -} -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16BE); -} -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16LE); -} -#endif /* SQLITE_OMIT_UTF16 */ -/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five -** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating -** point number string BLOB NULL -*/ -SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ - static const u8 aType[] = { - SQLITE_BLOB, /* 0x00 (not possible) */ - SQLITE_NULL, /* 0x01 NULL */ - SQLITE_TEXT, /* 0x02 TEXT */ - SQLITE_NULL, /* 0x03 (not possible) */ - SQLITE_INTEGER, /* 0x04 INTEGER */ - SQLITE_NULL, /* 0x05 (not possible) */ - SQLITE_INTEGER, /* 0x06 INTEGER + TEXT */ - SQLITE_NULL, /* 0x07 (not possible) */ - SQLITE_FLOAT, /* 0x08 FLOAT */ - SQLITE_NULL, /* 0x09 (not possible) */ - SQLITE_FLOAT, /* 0x0a FLOAT + TEXT */ - SQLITE_NULL, /* 0x0b (not possible) */ - SQLITE_INTEGER, /* 0x0c (not possible) */ - SQLITE_NULL, /* 0x0d (not possible) */ - SQLITE_INTEGER, /* 0x0e (not possible) */ - SQLITE_NULL, /* 0x0f (not possible) */ - SQLITE_BLOB, /* 0x10 BLOB */ - SQLITE_NULL, /* 0x11 (not possible) */ - SQLITE_TEXT, /* 0x12 (not possible) */ - SQLITE_NULL, /* 0x13 (not possible) */ - SQLITE_INTEGER, /* 0x14 INTEGER + BLOB */ - SQLITE_NULL, /* 0x15 (not possible) */ - SQLITE_INTEGER, /* 0x16 (not possible) */ - SQLITE_NULL, /* 0x17 (not possible) */ - SQLITE_FLOAT, /* 0x18 FLOAT + BLOB */ - SQLITE_NULL, /* 0x19 (not possible) */ - SQLITE_FLOAT, /* 0x1a (not possible) */ - SQLITE_NULL, /* 0x1b (not possible) */ - SQLITE_INTEGER, /* 0x1c (not possible) */ - SQLITE_NULL, /* 0x1d (not possible) */ - SQLITE_INTEGER, /* 0x1e (not possible) */ - SQLITE_NULL, /* 0x1f (not possible) */ - SQLITE_FLOAT, /* 0x20 INTREAL */ - SQLITE_NULL, /* 0x21 (not possible) */ - SQLITE_FLOAT, /* 0x22 INTREAL + TEXT */ - SQLITE_NULL, /* 0x23 (not possible) */ - SQLITE_FLOAT, /* 0x24 (not possible) */ - SQLITE_NULL, /* 0x25 (not possible) */ - SQLITE_FLOAT, /* 0x26 (not possible) */ - SQLITE_NULL, /* 0x27 (not possible) */ - SQLITE_FLOAT, /* 0x28 (not possible) */ - SQLITE_NULL, /* 0x29 (not possible) */ - SQLITE_FLOAT, /* 0x2a (not possible) */ - SQLITE_NULL, /* 0x2b (not possible) */ - SQLITE_FLOAT, /* 0x2c (not possible) */ - SQLITE_NULL, /* 0x2d (not possible) */ - SQLITE_FLOAT, /* 0x2e (not possible) */ - SQLITE_NULL, /* 0x2f (not possible) */ - SQLITE_BLOB, /* 0x30 (not possible) */ - SQLITE_NULL, /* 0x31 (not possible) */ - SQLITE_TEXT, /* 0x32 (not possible) */ - SQLITE_NULL, /* 0x33 (not possible) */ - SQLITE_FLOAT, /* 0x34 (not possible) */ - SQLITE_NULL, /* 0x35 (not possible) */ - SQLITE_FLOAT, /* 0x36 (not possible) */ - SQLITE_NULL, /* 0x37 (not possible) */ - SQLITE_FLOAT, /* 0x38 (not possible) */ - SQLITE_NULL, /* 0x39 (not possible) */ - SQLITE_FLOAT, /* 0x3a (not possible) */ - SQLITE_NULL, /* 0x3b (not possible) */ - SQLITE_FLOAT, /* 0x3c (not possible) */ - SQLITE_NULL, /* 0x3d (not possible) */ - SQLITE_FLOAT, /* 0x3e (not possible) */ - SQLITE_NULL, /* 0x3f (not possible) */ - }; -#ifdef SQLITE_DEBUG - { - int eType = SQLITE_BLOB; - if( pVal->flags & MEM_Null ){ - eType = SQLITE_NULL; - }else if( pVal->flags & (MEM_Real|MEM_IntReal) ){ - eType = SQLITE_FLOAT; - }else if( pVal->flags & MEM_Int ){ - eType = SQLITE_INTEGER; - }else if( pVal->flags & MEM_Str ){ - eType = SQLITE_TEXT; - } - assert( eType == aType[pVal->flags&MEM_AffMask] ); - } -#endif - return aType[pVal->flags&MEM_AffMask]; -} -SQLITE_API int sqlite3_value_encoding(sqlite3_value *pVal){ - return pVal->enc; -} - -/* Return true if a parameter to xUpdate represents an unchanged column */ -SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){ - return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero); -} - -/* Return true if a parameter value originated from an sqlite3_bind() */ -SQLITE_API int sqlite3_value_frombind(sqlite3_value *pVal){ - return (pVal->flags&MEM_FromBind)!=0; -} - -/* Make a copy of an sqlite3_value object -*/ -SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ - sqlite3_value *pNew; - if( pOrig==0 ) return 0; - pNew = sqlite3_malloc( sizeof(*pNew) ); - if( pNew==0 ) return 0; - memset(pNew, 0, sizeof(*pNew)); - memcpy(pNew, pOrig, MEMCELLSIZE); - pNew->flags &= ~MEM_Dyn; - pNew->db = 0; - if( pNew->flags&(MEM_Str|MEM_Blob) ){ - pNew->flags &= ~(MEM_Static|MEM_Dyn); - pNew->flags |= MEM_Ephem; - if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){ - sqlite3ValueFree(pNew); - pNew = 0; - } - }else if( pNew->flags & MEM_Null ){ - /* Do not duplicate pointer values */ - pNew->flags &= ~(MEM_Term|MEM_Subtype); - } - return pNew; -} - -/* Destroy an sqlite3_value object previously obtained from -** sqlite3_value_dup(). -*/ -SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ - sqlite3ValueFree(pOld); -} - - -/**************************** sqlite3_result_ ******************************* -** The following routines are used by user-defined functions to specify -** the function result. -** -** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the -** 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 if P is not going to be used and need to be destroyed. -*/ -static void setResultStrOrError( - sqlite3_context *pCtx, /* Function context */ - const char *z, /* String pointer */ - int n, /* Bytes in string, or negative */ - u8 enc, /* Encoding of z. 0 for BLOBs */ - void (*xDel)(void*) /* Destructor function */ -){ - Mem *pOut = pCtx->pOut; - int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); - if( rc ){ - if( rc==SQLITE_TOOBIG ){ - sqlite3_result_error_toobig(pCtx); - }else{ - /* The only errors possible from sqlite3VdbeMemSetStr are - ** SQLITE_TOOBIG and SQLITE_NOMEM */ - assert( rc==SQLITE_NOMEM ); - sqlite3_result_error_nomem(pCtx); - } - return; - } - sqlite3VdbeChangeEncoding(pOut, pCtx->enc); - if( sqlite3VdbeMemTooBig(pOut) ){ - sqlite3_result_error_toobig(pCtx); - } -} -static int invokeValueDestructor( - const void *p, /* Value to destroy */ - void (*xDel)(void*), /* The destructor */ - sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if not NULL */ -){ - assert( xDel!=SQLITE_DYNAMIC ); - if( xDel==0 ){ - /* noop */ - }else if( xDel==SQLITE_TRANSIENT ){ - /* noop */ - }else{ - xDel((void*)p); - } -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx!=0 ){ - sqlite3_result_error_toobig(pCtx); - } -#else - assert( pCtx!=0 ); - sqlite3_result_error_toobig(pCtx); -#endif - return SQLITE_TOOBIG; -} -SQLITE_API void sqlite3_result_blob( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 || n<0 ){ - invokeValueDestructor(z, xDel, pCtx); - return; - } -#endif - assert( n>=0 ); - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n, 0, xDel); -} -SQLITE_API void sqlite3_result_blob64( - sqlite3_context *pCtx, - const void *z, - sqlite3_uint64 n, - void (*xDel)(void *) -){ - assert( xDel!=SQLITE_DYNAMIC ); -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - if( n>0x7fffffff ){ - (void)invokeValueDestructor(z, xDel, pCtx); - }else{ - setResultStrOrError(pCtx, z, (int)n, 0, xDel); - } -} -SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); -} -SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - pCtx->isError = SQLITE_ERROR; - sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - pCtx->isError = SQLITE_ERROR; - sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); -} -#endif -SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); -} -SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); -} -SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetNull(pCtx->pOut); -} -SQLITE_API void sqlite3_result_pointer( - sqlite3_context *pCtx, - void *pPtr, - const char *zPType, - void (*xDestructor)(void*) -){ - Mem *pOut; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(pPtr, xDestructor, 0); - return; - } -#endif - pOut = pCtx->pOut; - assert( sqlite3_mutex_held(pOut->db->mutex) ); - sqlite3VdbeMemRelease(pOut); - pOut->flags = MEM_Null; - sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor); -} -SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - Mem *pOut; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif -#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0 - if( pCtx->pFunc!=0 - && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0 - ){ - char zErr[200]; - sqlite3_snprintf(sizeof(zErr), zErr, - "misuse of sqlite3_result_subtype() by %s()", - pCtx->pFunc->zName); - sqlite3_result_error(pCtx, zErr, -1); - return; - } -#endif /* SQLITE_STRICT_SUBTYPE */ - pOut = pCtx->pOut; - assert( sqlite3_mutex_held(pOut->db->mutex) ); - pOut->eSubtype = eSubtype & 0xff; - pOut->flags |= MEM_Subtype; -} -SQLITE_API void sqlite3_result_text( - sqlite3_context *pCtx, - const char *z, - int n, - void (*xDel)(void *) -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); -} -SQLITE_API void sqlite3_result_text64( - sqlite3_context *pCtx, - const char *z, - sqlite3_uint64 n, - void (*xDel)(void *), - unsigned char enc -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 ){ - if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - n &= ~(u64)1; - } - if( n>0x7fffffff ){ - (void)invokeValueDestructor(z, xDel, pCtx); - }else{ - setResultStrOrError(pCtx, z, (int)n, enc, xDel); - sqlite3VdbeMemZeroTerminateIfAble(pCtx->pOut); - } -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_text16( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16NATIVE, xDel); -} -SQLITE_API void sqlite3_result_text16be( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16BE, xDel); -} -SQLITE_API void sqlite3_result_text16le( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16LE, xDel); -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - Mem *pOut; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; - if( pValue==0 ){ - sqlite3_result_null(pCtx); - return; - } -#endif - pOut = pCtx->pOut; - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemCopy(pOut, pValue); - sqlite3VdbeChangeEncoding(pOut, pCtx->enc); - if( sqlite3VdbeMemTooBig(pOut) ){ - sqlite3_result_error_toobig(pCtx); - } -} -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ - sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0); -} -SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ - Mem *pOut; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return SQLITE_MISUSE_BKPT; -#endif - pOut = pCtx->pOut; - assert( sqlite3_mutex_held(pOut->db->mutex) ); - if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(pCtx); - return SQLITE_TOOBIG; - } -#ifndef SQLITE_OMIT_INCRBLOB - sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); - return SQLITE_OK; -#else - return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); -#endif -} -SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - pCtx->isError = errCode ? errCode : -1; -#ifdef SQLITE_DEBUG - if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; -#endif - if( pCtx->pOut->flags & MEM_Null ){ - setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, - SQLITE_STATIC); - } -} - -/* Force an SQLITE_TOOBIG error. */ -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - pCtx->isError = SQLITE_TOOBIG; - sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, - SQLITE_UTF8, SQLITE_STATIC); -} - -/* An SQLITE_NOMEM error. */ -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetNull(pCtx->pOut); - pCtx->isError = SQLITE_NOMEM_BKPT; - sqlite3OomFault(pCtx->pOut->db); -} - -#ifndef SQLITE_UNTESTABLE -/* Force the INT64 value currently stored as the result to be -** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL -** test-control. -*/ -SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - if( pCtx->pOut->flags & MEM_Int ){ - pCtx->pOut->flags &= ~MEM_Int; - pCtx->pOut->flags |= MEM_IntReal; - } -} -#endif - - -/* -** This function is called after a transaction has been committed. It -** invokes callbacks registered with sqlite3_wal_hook() as required. -*/ -static int doWalCallbacks(sqlite3 *db){ - int rc = SQLITE_OK; -#ifndef SQLITE_OMIT_WAL - int i; - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - int nEntry; - sqlite3BtreeEnter(pBt); - nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); - sqlite3BtreeLeave(pBt); - if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){ - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); - } - } - } -#endif - return rc; -} - - -/* -** Execute the statement pStmt, either until a row of data is ready, the -** statement is completely executed or an error occurs. -** -** This routine implements the bulk of the logic behind the sqlite_step() -** API. The only thing omitted is the automatic recompile if a -** schema change has occurred. That detail is handled by the -** outer sqlite3_step() wrapper procedure. -*/ -static int sqlite3Step(Vdbe *p){ - sqlite3 *db; - int rc; - - assert(p); - db = p->db; - 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 = sqlite3VdbeTransferError(p); - } - goto end_of_step; - } - - /* If there are no other statements currently running, then - ** reset the interrupt flag. This prevents a call to sqlite3_interrupt - ** from interrupting a statement that has not yet started. - */ - if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); - } - - assert( db->nVdbeWrite>0 || db->autoCommit==0 - || ((db->nDeferredCons + db->nDeferredImmCons)==0) - ); - -#ifndef SQLITE_OMIT_TRACE - if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 - && !db->init.busy && p->zSql ){ - 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; - p->eVdbeState = VDBE_RUN_STATE; - }else - - if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){ - /* We used to require that sqlite3_reset() be called before retrying - ** sqlite3_step() after any error or after SQLITE_DONE. But beginning - ** with version 3.7.0, we changed this so that 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 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 ){ - sqlite3_reset((sqlite3_stmt*)p); - }else{ - return SQLITE_MISUSE_BKPT; - } -#else - sqlite3_reset((sqlite3_stmt*)p); -#endif - assert( p->eVdbeState==VDBE_READY_STATE ); - goto restart_step; - } - } - -#ifdef SQLITE_DEBUG - p->rcApp = SQLITE_OK; -#endif -#ifndef SQLITE_OMIT_EXPLAIN - if( p->explain ){ - rc = sqlite3VdbeList(p); - }else -#endif /* SQLITE_OMIT_EXPLAIN */ - { - db->nVdbeExec++; - rc = sqlite3VdbeExec(p); - db->nVdbeExec--; - } - - 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); -#endif - p->pResultRow = 0; - if( rc==SQLITE_DONE && db->autoCommit ){ - assert( p->rc==SQLITE_OK ); - p->rc = doWalCallbacks(db); - if( p->rc!=SQLITE_OK ){ - rc = SQLITE_ERROR; - } - }else if( rc!=SQLITE_DONE && (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 = sqlite3VdbeTransferError(p); - } - } - - db->errCode = rc; - if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){ - p->rc = SQLITE_NOMEM_BKPT; - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ) rc = p->rc; - } -end_of_step: - /* There are only a limited number of result codes allowed from the - ** statements prepared using the legacy sqlite3_prepare() interface */ - assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 - || rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR - || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE - ); - return (rc&db->errMask); -} - -/* -** This is the top-level implementation of sqlite3_step(). Call -** sqlite3Step() to do most of the work. If a schema error occurs, -** call sqlite3Reprepare() and try again. -*/ -SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ - int rc = SQLITE_OK; /* Result from sqlite3Step() */ - Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ - int cnt = 0; /* Counter to prevent infinite loop of reprepares */ - sqlite3 *db; /* The database connection */ - - if( vdbeSafetyNotNull(v) ){ - return SQLITE_MISUSE_BKPT; - } - db = v->db; - sqlite3_mutex_enter(db->mutex); - while( (rc = sqlite3Step(v))==SQLITE_SCHEMA - && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ - int savedPc = v->pc; - rc = sqlite3Reprepare(v); - if( rc!=SQLITE_OK ){ - /* This case occurs after failing to recompile an sql statement. - ** The error message from the SQL compiler has already been loaded - ** into the database handle. This block copies the error message - ** from the database handle into the statement and sets the statement - ** program counter to 0 to ensure that when the statement is - ** finalized or reset the parser error message is available via - ** sqlite3_errmsg() and sqlite3_errcode(). - */ - const char *zErr = (const char *)sqlite3_value_text(db->pErr); - sqlite3DbFree(db, v->zErrMsg); - if( !db->mallocFailed ){ - v->zErrMsg = sqlite3DbStrDup(db, zErr); - v->rc = rc = sqlite3ApiExit(db, rc); - } else { - v->zErrMsg = 0; - v->rc = rc = SQLITE_NOMEM_BKPT; - } - break; - } - sqlite3_reset(pStmt); - 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 ); - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - - -/* -** Extract the user data from a sqlite3_context structure and return a -** pointer to it. -*/ -SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#endif - assert( p && p->pFunc ); - return p->pFunc->pUserData; -} - -/* -** Extract the user data from a sqlite3_context structure and return a -** pointer to it. -** -** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface -** returns a copy of the pointer to the database connection (the 1st -** parameter) of the sqlite3_create_function() and -** sqlite3_create_function16() routines that originally registered the -** application defined function. -*/ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#else - assert( p && p->pOut ); -#endif - return p->pOut->db; -} - -/* -** If this routine is invoked from within an xColumn method of a virtual -** table, then it returns true if and only if the the call is during an -** UPDATE operation and the value of the column will not be modified -** by the UPDATE. -** -** If this routine is called from any context other than within the -** xColumn method of a virtual table, then the return value is meaningless -** and arbitrary. -** -** Virtual table implements might use this routine to optimize their -** performance by substituting a NULL result, or some other light-weight -** value, as a signal to the xUpdate routine that the column is unchanged. -*/ -SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#else - assert( p ); -#endif - return sqlite3_value_nochange(p->pOut); -} - -/* -** The destructor function for a ValueList object. This needs to be -** a separate function, unknowable to the application, to ensure that -** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not -** preceded by activation of IN processing via sqlite3_vtab_int() do not -** try to access a fake ValueList object inserted by a hostile extension. -*/ -SQLITE_PRIVATE void sqlite3VdbeValueListFree(void *pToDelete){ - sqlite3_free(pToDelete); -} - -/* -** Implementation of sqlite3_vtab_in_first() (if bNext==0) and -** sqlite3_vtab_in_next() (if bNext!=0). -*/ -static int valueFromValueList( - sqlite3_value *pVal, /* Pointer to the ValueList object */ - 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_BKPT; - if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ - return SQLITE_ERROR; - }else{ - assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == - (MEM_Null|MEM_Term|MEM_Subtype) ); - assert( pVal->eSubtype=='p' ); - assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 ); - pRhs = (ValueList*)pVal->z; - } - if( bNext ){ - rc = sqlite3BtreeNext(pRhs->pCsr, 0); - }else{ - int dummy = 0; - rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy); - assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) ); - if( 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 = sqlite3BtreePayloadSize(pRhs->pCsr); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); - if( rc==SQLITE_OK ){ - u8 *zBuf = (u8*)sMem.z; - u32 iSerial; - sqlite3_value *pOut = pRhs->pOut; - int iOff = 1 + getVarint32(&zBuf[1], iSerial); - sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut); - pOut->enc = ENC(pOut->db); - if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){ - rc = SQLITE_NOMEM; - }else{ - *ppOut = pOut; - } - } - 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 sqlite3_vtab_in_first(sqlite3_value *pVal, 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 sqlite3_vtab_in_next(sqlite3_value *pVal, 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 -** of the amount of time that elapses between invocations. In other words, -** the time returned is always the time of the first call. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ - int rc; -#ifndef SQLITE_ENABLE_STAT4 - sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; - assert( p->pVdbe!=0 ); -#else - sqlite3_int64 iTime = 0; - sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; -#endif - if( *piTime==0 ){ - rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); - if( rc ) *piTime = 0; - } - return *piTime; -} - -/* -** Create a new aggregate context for p and return a pointer to -** its pMem->z element. -*/ -static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ - Mem *pMem = p->pMem; - assert( (pMem->flags & MEM_Agg)==0 ); - if( nByte<=0 ){ - sqlite3VdbeMemSetNull(pMem); - pMem->z = 0; - }else{ - sqlite3VdbeMemClearAndResize(pMem, nByte); - pMem->flags = MEM_Agg; - pMem->u.pDef = p->pFunc; - if( pMem->z ){ - memset(pMem->z, 0, nByte); - } - } - return (void*)pMem->z; -} - -/* -** Allocate or return the aggregate context for a user function. A new -** context is allocated on the first call. Subsequent calls return the -** same context that was returned on prior calls. -*/ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - assert( p && p->pFunc && p->pFunc->xFinalize ); - assert( sqlite3_mutex_held(p->pOut->db->mutex) ); - testcase( nByte<0 ); - if( (p->pMem->flags & MEM_Agg)==0 ){ - return createAggContext(p, nByte); - }else{ - return (void*)p->pMem->z; - } -} - -/* -** Return the auxiliary data pointer, if any, for the iArg'th argument to -** the user-function defined by pCtx. -** -** The left-most argument is 0. -** -** Undocumented behavior: If iArg is negative then access a cache of -** auxiliary data pointers that is available to all functions within a -** single prepared statement. The iArg values must match. -*/ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ - AuxData *pAuxData; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return 0; -#endif - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#if SQLITE_ENABLE_STAT4 - if( pCtx->pVdbe==0 ) return 0; -#else - assert( pCtx->pVdbe!=0 ); -#endif - for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){ - if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){ - return pAuxData->pAux; - } - } - return 0; -} - -/* -** Set the auxiliary data pointer and delete function, for the iArg'th -** argument to the user-function defined by pCtx. Any previous value is -** deleted by calling the delete function specified when it was set. -** -** The left-most argument is 0. -** -** Undocumented behavior: If iArg is negative then make the data available -** to all functions within the current prepared statement using iArg as an -** access code. -*/ -SQLITE_API void sqlite3_set_auxdata( - sqlite3_context *pCtx, - int iArg, - void *pAux, - void (*xDelete)(void*) -){ - AuxData *pAuxData; - Vdbe *pVdbe; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - pVdbe= pCtx->pVdbe; - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#ifdef SQLITE_ENABLE_STAT4 - if( pVdbe==0 ) goto failed; -#else - assert( pVdbe!=0 ); -#endif - - for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){ - if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){ - break; - } - } - if( pAuxData==0 ){ - pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData)); - if( !pAuxData ) goto failed; - pAuxData->iAuxOp = pCtx->iOp; - pAuxData->iAuxArg = iArg; - pAuxData->pNextAux = pVdbe->pAuxData; - pVdbe->pAuxData = pAuxData; - if( pCtx->isError==0 ) pCtx->isError = -1; - }else if( pAuxData->xDeleteAux ){ - pAuxData->xDeleteAux(pAuxData->pAux); - } - - pAuxData->pAux = pAux; - pAuxData->xDeleteAux = xDelete; - return; - -failed: - if( xDelete ){ - xDelete(pAux); - } -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Return the number of times the Step function of an aggregate has been -** called. -** -** This function is deprecated. Do not use it for new code. It is -** provide only to avoid breaking legacy code. New aggregate function -** implementations should keep their own counts within their aggregate -** context. -*/ -SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ - assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize ); - return p->pMem->n; -} -#endif - -/* -** Return the number of columns in the result set for the statement pStmt. -*/ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 ) return 0; - return pVm->nResColumn; -} - -/* -** Return the number of values available from the current row of the -** currently executing statement pStmt. -*/ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 || pVm->pResultRow==0 ) return 0; - return pVm->nResColumn; -} - -/* -** Return a pointer to static memory containing an SQL NULL value. -*/ -static const Mem *columnNullValue(void){ - /* Even though the Mem structure contains an element - ** of type i64, on certain architectures (x86) with certain compiler - ** switches (-Os), gcc may align this Mem object on a 4-byte boundary - ** instead of an 8-byte one. This all works fine, except that when - ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s - ** that a Mem structure is located on an 8-byte boundary. To prevent - ** these assert()s from failing, when building with SQLITE_DEBUG defined - ** using gcc, we force nullMem to be 8-byte aligned using the magical - ** __attribute__((aligned(8))) macro. */ - static const Mem nullMem -#if defined(SQLITE_DEBUG) && defined(__GNUC__) - __attribute__((aligned(8))) -#endif - = { - /* .u = */ {0}, - /* .z = */ (char*)0, - /* .n = */ (int)0, - /* .flags = */ (u16)MEM_Null, - /* .enc = */ (u8)0, - /* .eSubtype = */ (u8)0, - /* .db = */ (sqlite3*)0, - /* .szMalloc = */ (int)0, - /* .uTemp = */ (u32)0, - /* .zMalloc = */ (char*)0, - /* .xDel = */ (void(*)(void*))0, -#ifdef SQLITE_DEBUG - /* .pScopyFrom = */ (Mem*)0, - /* .mScopyFlags= */ 0, - /* .bScopy = */ 0, -#endif - }; - return &nullMem; -} - -/* -** Check to see if column iCol of the given statement is valid. If -** it is, return a pointer to the Mem for the value of that column. -** If iCol is not valid, return a pointer to a Mem which has a value -** of NULL. -*/ -static Mem *columnMem(sqlite3_stmt *pStmt, int i){ - Vdbe *pVm; - Mem *pOut; - - pVm = (Vdbe *)pStmt; - if( pVm==0 ) return (Mem*)columnNullValue(); - assert( pVm->db ); - sqlite3_mutex_enter(pVm->db->mutex); - if( pVm->pResultRow!=0 && inResColumn && i>=0 ){ - pOut = &pVm->pResultRow[i]; - }else{ - sqlite3Error(pVm->db, SQLITE_RANGE); - pOut = (Mem*)columnNullValue(); - } - return pOut; -} - -/* -** This function is called after invoking an sqlite3_value_XXX function on a -** column value (i.e. a value returned by evaluating an SQL expression in the -** select list of a SELECT statement) that may cause a malloc() failure. If -** malloc() has failed, the threads mallocFailed flag is cleared and the result -** code of statement pStmt set to SQLITE_NOMEM. -** -** Specifically, this is called from within: -** -** sqlite3_column_int() -** sqlite3_column_int64() -** sqlite3_column_text() -** sqlite3_column_text16() -** sqlite3_column_double() -** sqlite3_column_bytes() -** sqlite3_column_bytes16() -** sqlite3_column_blob() -*/ -static void columnMallocFailure(sqlite3_stmt *pStmt) -{ - /* If malloc() failed during an encoding conversion within an - ** sqlite3_column_XXX API, then set the return code of the statement to - ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR - ** and _finalize() will return NOMEM. - */ - Vdbe *p = (Vdbe *)pStmt; - if( p ){ - assert( p->db!=0 ); - assert( sqlite3_mutex_held(p->db->mutex) ); - p->rc = sqlite3ApiExit(p->db, p->rc); - sqlite3_mutex_leave(p->db->mutex); - } -} - -/**************************** sqlite3_column_ ******************************* -** The following routines are used to access elements of the current row -** in the result set. -*/ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ - const void *val; - val = sqlite3_value_blob( columnMem(pStmt,i) ); - /* Even though there is no encoding conversion, value_blob() might - ** need to call malloc() to expand the result of a zeroblob() - ** expression. - */ - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_bytes( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ - double val = sqlite3_value_double( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_int( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ - sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ - const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ - Mem *pOut = columnMem(pStmt, i); - if( pOut->flags&MEM_Static ){ - pOut->flags &= ~MEM_Static; - pOut->flags |= MEM_Ephem; - } - columnMallocFailure(pStmt); - return (sqlite3_value *)pOut; -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ - const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ - int iType = sqlite3_value_type( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return iType; -} - -/* -** Column names appropriate for EXPLAIN or EXPLAIN QUERY PLAN. -*/ -static const char * const azExplainColNames8[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", /* EXPLAIN */ - "id", "parent", "notused", "detail" /* EQP */ -}; -static const u16 azExplainColNames16data[] = { - /* 0 */ 'a', 'd', 'd', 'r', 0, - /* 5 */ 'o', 'p', 'c', 'o', 'd', 'e', 0, - /* 12 */ 'p', '1', 0, - /* 15 */ 'p', '2', 0, - /* 18 */ 'p', '3', 0, - /* 21 */ 'p', '4', 0, - /* 24 */ 'p', '5', 0, - /* 27 */ 'c', 'o', 'm', 'm', 'e', 'n', 't', 0, - /* 35 */ 'i', 'd', 0, - /* 38 */ 'p', 'a', 'r', 'e', 'n', 't', 0, - /* 45 */ 'n', 'o', 't', 'u', 's', 'e', 'd', 0, - /* 53 */ 'd', 'e', 't', 'a', 'i', 'l', 0 -}; -static const u8 iExplainColNames16[] = { - 0, 5, 12, 15, 18, 21, 24, 27, - 35, 38, 45, 53 -}; - -/* -** Convert the N-th element of pStmt->pColName[] into a string using -** xFunc() then return that string. If N is out of range, return 0. -** -** There are up to 5 names for each column. useType determines which -** name is returned. Here are the names: -** -** 0 The column name as it should be displayed for output -** 1 The datatype name for the column -** 2 The name of the database that the column derives from -** 3 The name of the table that the column derives from -** 4 The name of the table column that the result column derives from -** -** If the result is not a simple column reference (if it is an expression -** or a constant) then useTypes 2, 3, and 4 return NULL. -*/ -static const void *columnName( - sqlite3_stmt *pStmt, /* The statement */ - int N, /* Which column to get the name for */ - int useUtf16, /* True to return the name as UTF16 */ - int useType /* What type of name */ -){ - const void *ret; - Vdbe *p; - int n; - sqlite3 *db; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - if( N<0 ) return 0; - ret = 0; - p = (Vdbe *)pStmt; - db = p->db; - assert( db!=0 ); - sqlite3_mutex_enter(db->mutex); - - if( p->explain ){ - if( useType>0 ) goto columnName_end; - n = p->explain==1 ? 8 : 4; - if( N>=n ) goto columnName_end; - if( useUtf16 ){ - int i = iExplainColNames16[N + 8*p->explain - 8]; - ret = (void*)&azExplainColNames16data[i]; - }else{ - ret = (void*)azExplainColNames8[N + 8*p->explain - 8]; - } - goto columnName_end; - } - n = p->nResColumn; - if( NmallocFailed; - N += useType*n; -#ifndef SQLITE_OMIT_UTF16 - if( useUtf16 ){ - ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); - }else -#endif - { - ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]); - } - /* A malloc may have failed inside of the _text() call. If this - ** is the case, clear the mallocFailed flag and return NULL. - */ - assert( db->mallocFailed==0 || db->mallocFailed==1 ); - if( db->mallocFailed > prior_mallocFailed ){ - sqlite3OomClear(db); - ret = 0; - } - } -columnName_end: - sqlite3_mutex_leave(db->mutex); - return ret; -} - -/* -** Return the name of the Nth column of the result set returned by SQL -** statement pStmt. -*/ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_NAME); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_NAME); -} -#endif - -/* -** Constraint: If you have ENABLE_COLUMN_METADATA then you must -** not define OMIT_DECLTYPE. -*/ -#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA) -# error "Must not define both SQLITE_OMIT_DECLTYPE \ - and SQLITE_ENABLE_COLUMN_METADATA" -#endif - -#ifndef SQLITE_OMIT_DECLTYPE -/* -** Return the column declaration type (if applicable) of the 'i'th column -** of the result set of SQL statement pStmt. -*/ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_DECLTYPE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_DECLTYPE); -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_OMIT_DECLTYPE */ - -#ifdef SQLITE_ENABLE_COLUMN_METADATA -/* -** Return the name of the database from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_DATABASE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_DATABASE); -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the name of the table from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_TABLE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_TABLE); -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the name of the table column from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_COLUMN); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_COLUMN); -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_ENABLE_COLUMN_METADATA */ - - -/******************************* sqlite3_bind_ *************************** -** -** Routines used to attach values to wildcards in a compiled SQL statement. -*/ -/* -** Unbind the value bound to variable i in virtual machine p. This is the -** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK. -** -** A successful evaluation of this routine acquires the mutex on p. -** the mutex is released if any kind of error occurs. -** -** The error code stored in database p->db is overwritten with the return -** value in any case. -** -** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK, -** that means all of the the following will be true: -** -** p!=0 -** p->pVar!=0 -** i>0 -** i<=p->nVar -** -** An assert() is normally added after vdbeUnbind() to help static analyzers -** realize this. -*/ -static int vdbeUnbind(Vdbe *p, unsigned int i){ - Mem *pVar; - if( vdbeSafetyNotNull(p) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(p->db->mutex); - if( p->eVdbeState!=VDBE_READY_STATE ){ - sqlite3Error(p->db, SQLITE_MISUSE_BKPT); - sqlite3_mutex_leave(p->db->mutex); - sqlite3_log(SQLITE_MISUSE, - "bind on a busy prepared statement: [%s]", p->zSql); - return SQLITE_MISUSE_BKPT; - } - if( i>=(unsigned int)p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE); - sqlite3_mutex_leave(p->db->mutex); - return SQLITE_RANGE; - } - pVar = &p->aVar[i]; - sqlite3VdbeMemRelease(pVar); - pVar->flags = MEM_Null; - p->db->errCode = SQLITE_OK; - - /* If the bit corresponding to this variable in Vdbe.expmask is set, then - ** binding a new value to this variable invalidates the current query plan. - ** - ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host - ** parameter in the WHERE clause might influence the choice of query plan - ** for a statement, then the statement will be automatically recompiled, - ** as if there had been a schema change, on the first sqlite3_step() call - ** following any change to the bindings of that parameter. - */ - assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); - if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<expired = 1; - } - return SQLITE_OK; -} - -/* -** Bind a text or BLOB value. -*/ -static int bindText( - 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 */ - i64 nData, /* Number of bytes of data to be bound */ - void (*xDel)(void*), /* Destructor for the data */ - u8 encoding /* Encoding for the data */ -){ - Vdbe *p = (Vdbe *)pStmt; - Mem *pVar; - int rc; - - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - if( zData!=0 ){ - pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); - } - if( rc ){ - sqlite3Error(p->db, rc); - rc = sqlite3ApiExit(p->db, rc); - } - } - sqlite3_mutex_leave(p->db->mutex); - }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){ - xDel((void*)zData); - } - return rc; -} - - -/* -** Bind a blob value to an SQL statement variable. -*/ -SQLITE_API int sqlite3_bind_blob( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - void (*xDel)(void*) -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( nData<0 ) return SQLITE_MISUSE_BKPT; -#endif - return bindText(pStmt, i, zData, nData, xDel, 0); -} -SQLITE_API int sqlite3_bind_blob64( - sqlite3_stmt *pStmt, - int i, - const void *zData, - sqlite3_uint64 nData, - void (*xDel)(void*) -){ - assert( xDel!=SQLITE_DYNAMIC ); - return bindText(pStmt, i, zData, nData, xDel, 0); -} -SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ - return sqlite3_bind_int64(p, i, (i64)iValue); -} -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ - int rc; - Vdbe *p = (Vdbe*)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_pointer( - sqlite3_stmt *pStmt, - int i, - void *pPtr, - const char *zPTtype, - void (*xDestructor)(void*) -){ - int rc; - Vdbe *p = (Vdbe*)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor); - sqlite3_mutex_leave(p->db->mutex); - }else if( xDestructor ){ - xDestructor(pPtr); - } - return rc; -} -SQLITE_API int sqlite3_bind_text( - sqlite3_stmt *pStmt, - int i, - const char *zData, - int nData, - void (*xDel)(void*) -){ - return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); -} -SQLITE_API int sqlite3_bind_text64( - sqlite3_stmt *pStmt, - int i, - const char *zData, - sqlite3_uint64 nData, - void (*xDel)(void*), - unsigned char enc -){ - assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 ){ - if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - nData &= ~(u64)1; - } - return bindText(pStmt, i, zData, nData, xDel, enc); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_bind_text16( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int n, - void (*xDel)(void*) -){ - return bindText(pStmt, i, zData, n & ~(u64)1, xDel, SQLITE_UTF16NATIVE); -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ - int rc; - switch( sqlite3_value_type((sqlite3_value*)pValue) ){ - case SQLITE_INTEGER: { - rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); - break; - } - case SQLITE_FLOAT: { - assert( pValue->flags & (MEM_Real|MEM_IntReal) ); - rc = sqlite3_bind_double(pStmt, i, - (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i - ); - break; - } - case SQLITE_BLOB: { - if( pValue->flags & MEM_Zero ){ - rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); - }else{ - rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); - } - break; - } - case SQLITE_TEXT: { - rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, - pValue->enc); - break; - } - default: { - rc = sqlite3_bind_null(pStmt, i); - break; - } - } - return rc; -} -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ -#ifndef SQLITE_OMIT_INCRBLOB - sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); -#else - rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); -#endif - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ - int rc; - Vdbe *p = (Vdbe *)pStmt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(p->db->mutex); - if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - rc = SQLITE_TOOBIG; - }else{ - assert( (n & 0x7FFFFFFF)==n ); - rc = sqlite3_bind_zeroblob(pStmt, i, n); - } - rc = sqlite3ApiExit(p->db, rc); - sqlite3_mutex_leave(p->db->mutex); - return rc; -} - -/* -** Return the number of wildcards that can be potentially bound to. -** This routine is added to support DBD::SQLite. -*/ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - return p ? p->nVar : 0; -} - -/* -** Return the name of a wildcard parameter. Return NULL if the index -** is out of range or if the wildcard is unnamed. -** -** The result is always UTF-8. -*/ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ - Vdbe *p = (Vdbe*)pStmt; - if( p==0 ) return 0; - return sqlite3VListNumToName(p->pVList, i); -} - -/* -** Given a wildcard parameter name, return the index of the variable -** with that name. If there is no variable with the given name, -** return 0. -*/ -SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ - if( p==0 || zName==0 ) return 0; - return sqlite3VListNameToNum(p->pVList, zName, nName); -} -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ - return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); -} - -/* -** Transfer all bindings from the first statement over to the second. -*/ -SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ - Vdbe *pFrom = (Vdbe*)pFromStmt; - Vdbe *pTo = (Vdbe*)pToStmt; - int i; - assert( pTo->db==pFrom->db ); - assert( pTo->nVar==pFrom->nVar ); - sqlite3_mutex_enter(pTo->db->mutex); - for(i=0; inVar; i++){ - sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); - } - sqlite3_mutex_leave(pTo->db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Deprecated external interface. Internal/core SQLite code -** should call sqlite3TransferBindings. -** -** It is misuse to call this routine with statements from different -** database connections. But as this is a deprecated interface, we -** will not bother to check for that condition. -** -** If the two statements contain a different number of bindings, then -** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise -** SQLITE_OK is returned. -*/ -SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ - Vdbe *pFrom = (Vdbe*)pFromStmt; - Vdbe *pTo = (Vdbe*)pToStmt; - if( pFrom->nVar!=pTo->nVar ){ - return SQLITE_ERROR; - } - assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 ); - if( pTo->expmask ){ - pTo->expired = 1; - } - assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 ); - if( pFrom->expmask ){ - pFrom->expired = 1; - } - return sqlite3TransferBindings(pFromStmt, pToStmt); -} -#endif - -/* -** Return the sqlite3* database handle to which the prepared statement given -** in the argument belongs. This is the same database handle that was -** the first argument to the sqlite3_prepare() that was used to create -** the statement in the first place. -*/ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->db : 0; -} - -/* -** Return true if the prepared statement is guaranteed to not modify the -** database. -*/ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; -} - -/* -** Return 1 if the statement is an EXPLAIN and return 2 if the -** statement is an EXPLAIN QUERY PLAN -*/ -SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->explain : 0; -} - -/* -** Set the explain mode for a statement. -*/ -SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){ - Vdbe *v = (Vdbe*)pStmt; - int rc; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(v->db->mutex); - if( ((int)v->explain)==eMode ){ - rc = SQLITE_OK; - }else if( eMode<0 || eMode>2 ){ - rc = SQLITE_ERROR; - }else if( (v->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ - rc = SQLITE_ERROR; - }else if( v->eVdbeState!=VDBE_READY_STATE ){ - rc = SQLITE_BUSY; - }else if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){ - /* No reprepare necessary */ - v->explain = eMode; - rc = SQLITE_OK; - }else{ - v->explain = eMode; - rc = sqlite3Reprepare(v); - v->haveEqpOps = eMode==2; - } - if( v->explain ){ - v->nResColumn = 12 - 4*v->explain; - }else{ - v->nResColumn = v->nResAlloc; - } - sqlite3_mutex_leave(v->db->mutex); - return rc; -} - -/* -** Return true if the prepared statement is in need of being reset. -*/ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ - Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->eVdbeState==VDBE_RUN_STATE; -} - -/* -** Return a pointer to the next prepared statement after pStmt associated -** with database connection pDb. If pStmt is NULL, return the first -** prepared statement for the database connection. Return NULL if there -** are no more. -*/ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ - sqlite3_stmt *pNext; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(pDb) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(pDb->mutex); - if( pStmt==0 ){ - pNext = (sqlite3_stmt*)pDb->pVdbe; - }else{ - pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext; - } - sqlite3_mutex_leave(pDb->mutex); - return pNext; -} - -/* -** Return the value of a status counter for a prepared statement -*/ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ - Vdbe *pVdbe = (Vdbe*)pStmt; - u32 v; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !pStmt - || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) - ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - if( op==SQLITE_STMTSTATUS_MEMUSED ){ - sqlite3 *db = pVdbe->db; - sqlite3_mutex_enter(db->mutex); - v = 0; - db->pnBytesFreed = (int*)&v; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; - sqlite3VdbeDelete(pVdbe); - db->pnBytesFreed = 0; - db->lookaside.pEnd = db->lookaside.pTrueEnd; - sqlite3_mutex_leave(db->mutex); - }else{ - v = pVdbe->aCounter[op]; - if( resetFlag ) pVdbe->aCounter[op] = 0; - } - return (int)v; -} - -/* -** Return the SQL associated with a prepared statement -*/ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe *)pStmt; - return p ? p->zSql : 0; -} - -/* -** Return the SQL associated with a prepared statement with -** bound parameters expanded. Space to hold the returned string is -** obtained from sqlite3_malloc(). The caller is responsible for -** freeing the returned string by passing it to sqlite3_free(). -** -** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of -** expanded bound parameters. -*/ -SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){ -#ifdef SQLITE_OMIT_TRACE - return 0; -#else - char *z = 0; - const char *zSql = sqlite3_sql(pStmt); - if( zSql ){ - Vdbe *p = (Vdbe *)pStmt; - sqlite3_mutex_enter(p->db->mutex); - z = sqlite3VdbeExpandSql(p, zSql); - sqlite3_mutex_leave(p->db->mutex); - } - return z; -#endif -} - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Return the normalized SQL associated with a prepared statement. -*/ -SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe *)pStmt; - if( p==0 ) return 0; - if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){ - sqlite3_mutex_enter(p->db->mutex); - p->zNormSql = sqlite3Normalize(p, p->zSql); - sqlite3_mutex_leave(p->db->mutex); - } - return p->zNormSql; -} -#endif /* SQLITE_ENABLE_NORMALIZE */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** Allocate and populate an UnpackedRecord structure based on the serialized -** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure -** if successful, or a NULL pointer if an OOM error is encountered. -*/ -static UnpackedRecord *vdbeUnpackRecord( - KeyInfo *pKeyInfo, - int nKey, - const void *pKey -){ - UnpackedRecord *pRet; /* Return value */ - - pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); - if( pRet ){ - memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); - sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); - } - return pRet; -} - -/* -** This function is called from within a pre-update callback to retrieve -** a field of the row currently being updated or deleted. -*/ -SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p; - Mem *pMem; - int rc = SQLITE_OK; - int iStore = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 || ppValue==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - p = db->pPreUpdate; - /* Test that this call is being made from within an SQLITE_DELETE or - ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ - if( !p || p->op==SQLITE_INSERT ){ - rc = SQLITE_MISUSE_BKPT; - goto preupdate_old_out; - } - if( p->pPk ){ - iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else{ - iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); - } - if( iStore>=p->pCsr->nField || iStore<0 ){ - rc = SQLITE_RANGE; - goto preupdate_old_out; - } - - if( iIdx==p->pTab->iPKey ){ - *ppValue = pMem = &p->oldipk; - sqlite3VdbeMemSetInt64(pMem, p->iKey1); - }else{ - - /* If the old.* record has not yet been loaded into memory, do so now. */ - if( p->pUnpacked==0 ){ - u32 nRec; - u8 *aRec; - - assert( p->pCsr->eCurType==CURTYPE_BTREE ); - nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); - aRec = sqlite3DbMallocRaw(db, nRec); - if( !aRec ) goto preupdate_old_out; - rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); - if( rc==SQLITE_OK ){ - p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec); - if( !p->pUnpacked ) rc = SQLITE_NOMEM; - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, aRec); - goto preupdate_old_out; - } - p->aRecord = aRec; - } - - pMem = *ppValue = &p->pUnpacked->aMem[iStore]; - if( iStore>=p->pUnpacked->nField ){ - /* This occurs when the table has been extended using ALTER TABLE - ** ADD COLUMN. The value to return is the default value of the column. */ - Column *pCol = &p->pTab->aCol[iIdx]; - if( pCol->iDflt>0 ){ - if( p->apDflt==0 ){ - int nByte; - assert( sizeof(sqlite3_value*)*UMXV(p->pTab->nCol) < 0x7fffffff ); - nByte = sizeof(sqlite3_value*)*p->pTab->nCol; - p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte); - if( p->apDflt==0 ) goto preupdate_old_out; - } - if( p->apDflt[iIdx]==0 ){ - sqlite3_value *pVal = 0; - Expr *pDflt; - assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) ); - pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; - rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal); - if( rc==SQLITE_OK && pVal==0 ){ - rc = SQLITE_CORRUPT_BKPT; - } - p->apDflt[iIdx] = pVal; - } - *ppValue = p->apDflt[iIdx]; - }else{ - *ppValue = (sqlite3_value *)columnNullValue(); - } - }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ - if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_IntReal ); - sqlite3VdbeMemRealify(pMem); - } - } - } - - preupdate_old_out: - sqlite3Error(db, rc); - return sqlite3ApiExit(db, rc); -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** This function is called from within a pre-update callback to retrieve -** the number of columns in the row being updated, deleted or inserted. -*/ -SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif - return (p ? p->pKeyinfo->nKeyField : 0); -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** This function is designed to be called from within a pre-update callback -** only. It returns zero if the change that caused the callback was made -** immediately by a user SQL statement. Or, if the change was made by a -** trigger program, it returns the number of trigger programs currently -** on the stack (1 for a top-level trigger, 2 for a trigger fired by a -** top-level trigger etc.). -** -** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL -** or SET DEFAULT action is considered a trigger. -*/ -SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif - return (p ? p->v->nFrame : 0); -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** This function is designed to be called from within a pre-update callback -** only. -*/ -SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif - 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. -*/ -SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p; - int rc = SQLITE_OK; - Mem *pMem; - int iStore = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 || ppValue==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - p = db->pPreUpdate; - if( !p || p->op==SQLITE_DELETE ){ - rc = SQLITE_MISUSE_BKPT; - goto preupdate_new_out; - } - if( p->pPk && p->op!=SQLITE_UPDATE ){ - iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else{ - iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); - } - - if( iStore>=p->pCsr->nField || iStore<0 ){ - rc = SQLITE_RANGE; - goto preupdate_new_out; - } - - if( p->op==SQLITE_INSERT ){ - /* For an INSERT, memory cell p->iNewReg contains the serialized record - ** that is being inserted. Deserialize it. */ - UnpackedRecord *pUnpack = p->pNewUnpacked; - if( !pUnpack ){ - Mem *pData = &p->v->aMem[p->iNewReg]; - rc = ExpandBlob(pData); - if( rc!=SQLITE_OK ) goto preupdate_new_out; - pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z); - if( !pUnpack ){ - rc = SQLITE_NOMEM; - goto preupdate_new_out; - } - p->pNewUnpacked = pUnpack; - } - pMem = &pUnpack->aMem[iStore]; - if( iIdx==p->pTab->iPKey ){ - sqlite3VdbeMemSetInt64(pMem, p->iKey2); - }else if( iStore>=pUnpack->nField ){ - pMem = (sqlite3_value *)columnNullValue(); - } - }else{ - /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required - ** value. Make a copy of the cell contents and return a pointer to it. - ** It is not safe to return a pointer to the memory cell itself as the - ** caller may modify the value text encoding. - */ - assert( p->op==SQLITE_UPDATE ); - if( !p->aNew ){ - assert( sizeof(Mem)*UMXV(p->pCsr->nField) < 0x7fffffff ); - p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem)*p->pCsr->nField); - if( !p->aNew ){ - rc = SQLITE_NOMEM; - goto preupdate_new_out; - } - } - assert( iStore>=0 && iStorepCsr->nField ); - pMem = &p->aNew[iStore]; - if( pMem->flags==0 ){ - if( iIdx==p->pTab->iPKey ){ - sqlite3VdbeMemSetInt64(pMem, p->iKey2); - }else{ - rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]); - if( rc!=SQLITE_OK ) goto preupdate_new_out; - } - } - } - *ppValue = pMem; - - preupdate_new_out: - sqlite3Error(db, rc); - return sqlite3ApiExit(db, rc); -} -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Return status data for a single loop within query pStmt. -*/ -SQLITE_API int sqlite3_stmt_scanstatus_v2( - sqlite3_stmt *pStmt, /* Prepared statement being queried */ - int iScan, /* Index of loop to report on */ - int iScanStatusOp, /* Which metric to return */ - int flags, - void *pOut /* OUT: Write the answer here */ -){ - Vdbe *p = (Vdbe*)pStmt; - VdbeOp *aOp; - int nOp; - ScanStatus *pScan = 0; - int idx; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 || pOut==0 - || iScanStatusOpSQLITE_SCANSTAT_NCYCLE ){ - return 1; - } -#endif - aOp = p->aOp; - nOp = p->nOp; - if( p->pFrame ){ - VdbeFrame *pFrame; - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - aOp = pFrame->aOp; - nOp = pFrame->nOp; - } - - if( iScan<0 ){ - int ii; - if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){ - i64 res = 0; - for(ii=0; iinScan; idx++){ - pScan = &p->aScan[idx]; - if( pScan->zName ){ - iScan--; - if( iScan<0 ) break; - } - } - } - if( idx>=p->nScan ) return 1; - assert( pScan==0 || pScan==&p->aScan[idx] ); - pScan = &p->aScan[idx]; - - switch( iScanStatusOp ){ - case SQLITE_SCANSTAT_NLOOP: { - if( pScan->addrLoop>0 ){ - *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec; - }else{ - *(sqlite3_int64*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_NVISIT: { - if( pScan->addrVisit>0 ){ - *(sqlite3_int64*)pOut = aOp[pScan->addrVisit].nExec; - }else{ - *(sqlite3_int64*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_EST: { - double r = 1.0; - LogEst x = pScan->nEst; - while( x<100 ){ - x += 10; - r *= 0.5; - } - *(double*)pOut = r*sqlite3LogEstToInt(x); - break; - } - case SQLITE_SCANSTAT_NAME: { - *(const char**)pOut = pScan->zName; - break; - } - case SQLITE_SCANSTAT_EXPLAIN: { - if( pScan->addrExplain ){ - *(const char**)pOut = aOp[ pScan->addrExplain ].p4.z; - }else{ - *(const char**)pOut = 0; - } - break; - } - case SQLITE_SCANSTAT_SELECTID: { - if( pScan->addrExplain ){ - *(int*)pOut = aOp[ pScan->addrExplain ].p1; - }else{ - *(int*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_PARENTID: { - if( pScan->addrExplain ){ - *(int*)pOut = aOp[ pScan->addrExplain ].p2; - }else{ - *(int*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_NCYCLE: { - i64 res = 0; - if( pScan->aAddrRange[0]==0 ){ - res = -1; - }else{ - int ii; - for(ii=0; iiaAddrRange); ii+=2){ - int iIns = pScan->aAddrRange[ii]; - int iEnd = pScan->aAddrRange[ii+1]; - if( iIns==0 ) break; - if( iIns>0 ){ - while( iIns<=iEnd ){ - res += aOp[iIns].nCycle; - iIns++; - } - }else{ - int iOp; - for(iOp=0; iOpp1!=iEnd ) continue; - if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){ - continue; - } - res += aOp[iOp].nCycle; - } - } - } - } - *(i64*)pOut = res; - break; - } - default: { - return 1; - } - } - return 0; -} - -/* -** Return status data for a single loop within query pStmt. -*/ -SQLITE_API int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement being queried */ - int iScan, /* Index of loop to report on */ - int iScanStatusOp, /* Which metric to return */ - void *pOut /* OUT: Write the answer here */ -){ - return sqlite3_stmt_scanstatus_v2(pStmt, iScan, iScanStatusOp, 0, pOut); -} - -/* -** Zero all counters associated with the sqlite3_stmt_scanstatus() data. -*/ -SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - int ii; - for(ii=0; p!=0 && iinOp; ii++){ - Op *pOp = &p->aOp[ii]; - pOp->nExec = 0; - pOp->nCycle = 0; - } -} -#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ - -/************** End of vdbeapi.c *********************************************/ -/************** Begin file vdbetrace.c ***************************************/ -/* -** 2009 November 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to insert the values of host parameters -** (aka "wildcards") into the SQL text output by sqlite3_trace(). -** -** The Vdbe parse-tree explainer is also found here. -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -#ifndef SQLITE_OMIT_TRACE - -/* -** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of -** bytes in this text up to but excluding the first character in -** a host parameter. If the text contains no host parameters, return -** the total number of bytes in the text. -*/ -static int findNextHostParameter(const char *zSql, int *pnToken){ - int tokenType; - int nTotal = 0; - int n; - - *pnToken = 0; - while( zSql[0] ){ - n = sqlite3GetToken((u8*)zSql, &tokenType); - assert( n>0 && tokenType!=TK_ILLEGAL ); - if( tokenType==TK_VARIABLE ){ - *pnToken = n; - break; - } - nTotal += n; - zSql += n; - } - return nTotal; -} - -/* -** This function returns a pointer to a nul-terminated string in memory -** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the -** string contains a copy of zRawSql but with host parameters expanded to -** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, -** then the returned string holds a copy of zRawSql with "-- " prepended -** to each line of text. -** -** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then -** then long strings and blobs are truncated to that many bytes. This -** can be used to prevent unreasonably large trace strings when dealing -** with large (multi-megabyte) strings and blobs. -** -** The calling function is responsible for making sure the memory returned -** is eventually freed. -** -** ALGORITHM: Scan the input string looking for host parameters in any of -** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within -** string literals, quoted identifier names, and comments. For text forms, -** the host parameter index is found by scanning the prepared -** statement for the corresponding OP_Variable opcode. Once the host -** parameter index is known, locate the value in p->aVar[]. Then render -** the value as a literal in place of the host parameter name. -*/ -SQLITE_PRIVATE char *sqlite3VdbeExpandSql( - Vdbe *p, /* The prepared statement being evaluated */ - const char *zRawSql /* Raw text of the SQL statement */ -){ - sqlite3 *db; /* The database connection */ - int idx = 0; /* Index of a host parameter */ - int nextIndex = 1; /* Index of next ? host parameter */ - int n; /* Length of a token prefix */ - int nToken; /* Length of the parameter token */ - int i; /* Loop counter */ - Mem *pVar; /* Value of a host parameter */ - StrAccum out; /* Accumulate the output here */ -#ifndef SQLITE_OMIT_UTF16 - Mem utf8; /* Used to convert UTF16 into UTF8 for display */ -#endif - - db = p->db; - sqlite3StrAccumInit(&out, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - if( db->nVdbeExec>1 ){ - while( *zRawSql ){ - const char *zStart = zRawSql; - while( *(zRawSql++)!='\n' && *zRawSql ); - sqlite3_str_append(&out, "-- ", 3); - assert( (zRawSql - zStart) > 0 ); - sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart)); - } - }else if( p->nVar==0 ){ - sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql)); - }else{ - while( zRawSql[0] ){ - n = findNextHostParameter(zRawSql, &nToken); - assert( n>0 ); - sqlite3_str_append(&out, zRawSql, n); - zRawSql += n; - assert( zRawSql[0] || nToken==0 ); - if( nToken==0 ) break; - if( zRawSql[0]=='?' ){ - if( nToken>1 ){ - assert( sqlite3Isdigit(zRawSql[1]) ); - sqlite3GetInt32(&zRawSql[1], &idx); - }else{ - idx = nextIndex; - } - }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || - zRawSql[0]=='@' || zRawSql[0]=='#' ); - testcase( zRawSql[0]==':' ); - testcase( zRawSql[0]=='$' ); - testcase( zRawSql[0]=='@' ); - testcase( zRawSql[0]=='#' ); - idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); - assert( idx>0 ); - } - zRawSql += nToken; - nextIndex = MAX(idx + 1, nextIndex); - assert( idx>0 && idx<=p->nVar ); - pVar = &p->aVar[idx-1]; - if( pVar->flags & MEM_Null ){ - sqlite3_str_append(&out, "NULL", 4); - }else if( pVar->flags & (MEM_Int|MEM_IntReal) ){ - sqlite3_str_appendf(&out, "%lld", pVar->u.i); - }else if( pVar->flags & MEM_Real ){ - sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); - }else if( pVar->flags & MEM_Str ){ - int nOut; /* Number of bytes of the string text to include in output */ -#ifndef SQLITE_OMIT_UTF16 - u8 enc = ENC(db); - if( enc!=SQLITE_UTF8 ){ - memset(&utf8, 0, sizeof(utf8)); - utf8.db = db; - sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); - if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ - out.accError = SQLITE_NOMEM; - out.nAlloc = 0; - } - pVar = &utf8; - } -#endif - nOut = pVar->n; -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ - nOut = SQLITE_TRACE_SIZE_LIMIT; - while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } - } -#endif - sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z); -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ){ - sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); - } -#endif -#ifndef SQLITE_OMIT_UTF16 - if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); -#endif - }else if( pVar->flags & MEM_Zero ){ - sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero); - }else{ - int nOut; /* Number of bytes of the blob to include in output */ - assert( pVar->flags & MEM_Blob ); - sqlite3_str_append(&out, "x'", 2); - nOut = pVar->n; -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; -#endif - for(i=0; iz[i]&0xff); - } - sqlite3_str_append(&out, "'", 1); -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ){ - sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); - } -#endif - } - } - } - if( out.accError ) sqlite3_str_reset(&out); - return sqlite3StrAccumFinish(&out); -} - -#endif /* #ifndef SQLITE_OMIT_TRACE */ - -/************** End of vdbetrace.c *******************************************/ -/************** Begin file vdbe.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** The code in this file implements the function that runs the -** bytecode of a prepared statement. -** -** Various scripts scan this source file in order to generate HTML -** documentation, headers files, or other derived files. The formatting -** of the code in this file is, therefore, important. See other comments -** in this file for details. If in doubt, do not deviate from existing -** commenting and indentation practices when changing or adding code. -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -/* -** High-resolution hardware timer used for debugging and testing only. -*/ -#if defined(VDBE_PROFILE) \ - || defined(SQLITE_PERFORMANCE_TRACE) \ - || defined(SQLITE_ENABLE_STMT_SCANSTATUS) -/************** 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 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - - #elif defined(_MSC_VER) - - __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ - __asm { - rdtsc - ret ; return value at EDX:EAX - } - } - - #endif - -#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - -#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long long retval; - unsigned long junk; - __asm__ __volatile__ ("\n\ - 1: mftbu %1\n\ - mftb %L0\n\ - mftbu %0\n\ - cmpw %0,%1\n\ - bne 1b" - : "=r" (retval), "=r" (junk)); - return retval; - } - -#else - - /* - ** asm() is needed for hardware timing support. Without asm(), - ** disable the sqlite3Hwtime() routine. - ** - ** 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 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } - -#endif - -#endif /* !defined(SQLITE_HWTIME_H) */ - -/************** End of hwtime.h **********************************************/ -/************** Continuing where we left off in vdbe.c ***********************/ -#endif - -/* -** Invoke this macro on memory cells just prior to changing the -** value of the cell. This macro verifies that shallow copies are -** not misused. A shallow copy of a string or blob just copies a -** pointer to the string or blob, not the content. If the original -** is changed while the copy is still in use, the string or blob might -** be changed out from under the copy. This macro verifies that nothing -** like that ever happens. -*/ -#ifdef SQLITE_DEBUG -# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) -#else -# define memAboutToChange(P,M) -#endif - -/* -** The following global variable is incremented every time a cursor -** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test -** procedures use this information to make sure that indices are -** working correctly. This variable has no function other than to -** help verify the correct operation of the library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_search_count = 0; -#endif - -/* -** When this global variable is positive, it gets decremented once before -** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted -** field of the sqlite3 structure is set in order to simulate an interrupt. -** -** This facility is used for testing purposes only. It does not function -** in an ordinary build. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_interrupt_count = 0; -#endif - -/* -** The next global variable is incremented each type the OP_Sort opcode -** is executed. The test procedures use this information to make sure that -** sorting is occurring or not occurring at appropriate times. This variable -** has no function other than to help verify the correct operation of the -** library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_sort_count = 0; -#endif - -/* -** The next global variable records the size of the largest MEM_Blob -** or MEM_Str that has been used by a VDBE opcode. The test procedures -** use this information to make sure that the zero-blob functionality -** is working correctly. This variable has no function other than to -** help verify the correct operation of the library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_max_blobsize = 0; -static void updateMaxBlobsize(Mem *p){ - if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){ - sqlite3_max_blobsize = p->n; - } -} -#endif - -/* -** This macro evaluates to true if either the update hook or the preupdate -** hook are enabled for database connect DB. -*/ -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) -#else -# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) -#endif - -/* -** The next global variable is incremented each time the OP_Found opcode -** is executed. This is used to test whether or not the foreign key -** operation implemented using OP_FkIsZero is working. This variable -** has no function other than to help verify the correct operation of the -** library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_found_count = 0; -#endif - -/* -** Test a register to see if it exceeds the current maximum blob size. -** If it does, record the new maximum blob size. -*/ -#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE) -# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) -#else -# define UPDATE_MAX_BLOBSIZE(P) -#endif - -#ifdef SQLITE_DEBUG -/* This routine provides a convenient place to set a breakpoint during -** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after -** each opcode is printed. Variables "pc" (program counter) and pOp are -** available to add conditionals to the breakpoint. GDB example: -** -** break test_trace_breakpoint if pc=22 -** -** Other useful labels for breakpoints include: -** test_addop_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) -** sqlite3MisuseError(lineno) -** sqlite3CantopenError(lineno) -*/ -static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ - static u64 n = 0; - (void)pc; - (void)pOp; - (void)v; - n++; - if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */ -} -#endif - -/* -** Invoke the VDBE coverage callback, if that callback is defined. This -** feature is used for test suite validation only and does not appear an -** production builds. -** -** M is the type of branch. I is the direction taken for this instance of -** the branch. -** -** M: 2 - two-way branch (I=0: fall-thru 1: jump ) -** 3 - two-way + NULL (I=0: fall-thru 1: jump 2: NULL ) -** 4 - OP_Jump (I=0: jump p1 1: jump p2 2: jump p3) -** -** In other words, if M is 2, then I is either 0 (for fall-through) or -** 1 (for when the branch is taken). If M is 3, the I is 0 for an -** ordinary fall-through, I is 1 if the branch was taken, and I is 2 -** if the result of comparison is NULL. For M=3, I=2 the jump may or -** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5. -** When M is 4, that means that an OP_Jump is being run. I is 0, 1, or 2 -** depending on if the operands are less than, equal, or greater than. -** -** iSrcLine is the source code line (from the __LINE__ macro) that -** generated the VDBE instruction combined with flag bits. The source -** code line number is in the lower 24 bits of iSrcLine and the upper -** 8 bytes are flags. The lower three bits of the flags indicate -** values for I that should never occur. For example, if the branch is -** always taken, the flags should be 0x05 since the fall-through and -** alternate branch are never taken. If a branch is never taken then -** flags should be 0x06 since only the fall-through approach is allowed. -** -** Bit 0x08 of the flags indicates an OP_Jump opcode that is only -** interested in equal or not-equal. In other words, I==0 and I==2 -** should be treated as equivalent -** -** Since only a line number is retained, not the filename, this macro -** only works for amalgamation builds. But that is ok, since these macros -** should be no-ops except for special builds used to measure test coverage. -*/ -#if !defined(SQLITE_VDBE_COVERAGE) -# define VdbeBranchTaken(I,M) -#else -# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) - static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){ - u8 mNever; - assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */ - assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */ - assert( I> 24; - assert( (I & mNever)==0 ); - if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ - /* Invoke the branch coverage callback with three arguments: - ** iSrcLine - the line number of the VdbeCoverage() macro, with - ** flags removed. - ** I - Mask of bits 0x07 indicating which cases are are - ** fulfilled by this instance of the jump. 0x01 means - ** fall-thru, 0x02 means taken, 0x04 means NULL. Any - ** impossible cases (ex: if the comparison is never NULL) - ** are filled in automatically so that the coverage - ** measurement logic does not flag those impossible cases - ** as missed coverage. - ** M - Type of jump. Same as M argument above - */ - I |= mNever; - if( M==2 ) I |= 0x04; - if( M==4 ){ - I |= 0x08; - if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/ - } - sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, - iSrcLine&0xffffff, I, M); - } -#endif - -/* -** An ephemeral string value (signified by the MEM_Ephem flag) contains -** a pointer to a dynamically allocated string where some other entity -** is responsible for deallocating that string. Because the register -** does not control the string, it might be deleted without the register -** knowing it. -** -** This routine converts an ephemeral string into a dynamically allocated -** string that the register itself controls. In other words, it -** converts an MEM_Ephem string into a string with P.z==P.zMalloc. -*/ -#define Deephemeralize(P) \ - if( ((P)->flags&MEM_Ephem)!=0 \ - && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} - -/* Return true if the cursor was opened using the OP_OpenSorter opcode. */ -#define isSorter(x) ((x)->eCurType==CURTYPE_SORTER) - -/* -** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL -** if we run out of memory. -*/ -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 */ - u8 eCurType /* Type of the new cursor */ -){ - /* Find the memory cell that will be used to store the blob of memory - ** required for this VdbeCursor structure. It is convenient to use a - ** vdbe memory cell to manage the memory allocation required for a - ** VdbeCursor structure for the following reasons: - ** - ** * Sometimes cursor numbers are used for a couple of different - ** purposes in a vdbe program. The different uses might require - ** different sized allocations. Memory cells provide growable - ** allocations. - ** - ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can - ** be freed lazily via the sqlite3_release_memory() API. This - ** minimizes the number of malloc calls made by the system. - ** - ** The memory cell for cursor 0 is aMem[0]. The rest are allocated from - ** the top of the register space. Cursor 1 is at Mem[p->nMem-1]. - ** Cursor 2 is at Mem[p->nMem-2]. And so forth. - */ - Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; - - i64 nByte; - VdbeCursor *pCx = 0; - nByte = SZ_VDBECURSOR(nField); - assert( ROUND8(nByte)==nByte ); - if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize(); - - assert( iCur>=0 && iCurnCursor ); - if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/ - sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]); - p->apCsr[iCur] = 0; - } - - /* There used to be a call to 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->szMallocszMalloc>0 ){ - sqlite3DbFreeNN(pMem->db, pMem->zMalloc); - } - pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte); - if( pMem->zMalloc==0 ){ - pMem->szMalloc = 0; - return 0; - } - pMem->szMalloc = (int)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 ){ - assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) ); - pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)]; - sqlite3BtreeCursorZero(pCx->uc.pCursor); - } - return pCx; -} - -/* -** The string in pRec is known to look like an integer and to have a -** floating point value of rValue. Return true and set *piValue to the -** integer value if the string is in range to be an integer. Otherwise, -** return false. -*/ -static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ - i64 iValue; - iValue = sqlite3RealToI64(rValue); - if( sqlite3RealSameAsInt(rValue,iValue) ){ - *piValue = iValue; - return 1; - } - return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc); -} - -/* -** Try to convert a value into a numeric representation if we can -** do so without loss of information. In other words, if the string -** looks like a number, convert it into a number. If it does not -** look like a number, leave it alone. -** -** If the bTryForInt flag is true, then extra effort is made to give -** an integer representation. Strings that look like floating point -** values but which have no fractional component (example: '48.00') -** will have a MEM_Int representation when bTryForInt is true. -** -** If bTryForInt is false, then if the input string contains a decimal -** point or exponential notation, the result is only MEM_Real, even -** if there is an exact integer representation of the quantity. -*/ -static void applyNumericAffinity(Mem *pRec, int bTryForInt){ - double rValue; - u8 enc = pRec->enc; - int rc; - assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); - rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc); - if( rc<=0 ) return; - if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ - pRec->flags |= MEM_Int; - }else{ - pRec->u.r = rValue; - pRec->flags |= MEM_Real; - if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); - } - /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the - ** string representation after computing a numeric equivalent, because the - ** string representation might not be the canonical representation for the - ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */ - pRec->flags &= ~MEM_Str; -} - -/* -** Processing is determine by the affinity parameter: -** -** SQLITE_AFF_INTEGER: -** SQLITE_AFF_REAL: -** SQLITE_AFF_NUMERIC: -** Try to convert pRec to an integer representation or a -** floating-point representation if an integer representation -** is not possible. Note that the integer representation is -** always preferred, even if the affinity is REAL, because -** an integer representation is more space efficient on disk. -** -** SQLITE_AFF_FLEXNUM: -** If the value is text, then try to convert it into a number of -** some kind (integer or real) but do not make any other changes. -** -** SQLITE_AFF_TEXT: -** Convert pRec to a text representation. -** -** SQLITE_AFF_BLOB: -** SQLITE_AFF_NONE: -** No-op. pRec is unchanged. -*/ -static void applyAffinity( - Mem *pRec, /* The value to apply affinity to */ - char affinity, /* The affinity to be applied */ - u8 enc /* Use this text encoding */ -){ - if( affinity>=SQLITE_AFF_NUMERIC ){ - assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL - || affinity==SQLITE_AFF_NUMERIC || affinity==SQLITE_AFF_FLEXNUM ); - if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){ - if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); - }else if( affinity<=SQLITE_AFF_REAL ){ - sqlite3VdbeIntegerAffinity(pRec); - } - } - }else if( affinity==SQLITE_AFF_TEXT ){ - /* Only attempt the conversion to TEXT if there is an integer or real - ** representation (blob and NULL do not get converted) but no string - ** representation. It would be harmless to repeat the conversion if - ** there is already a string rep, but it is pointless to waste those - ** CPU cycles. */ - if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/ - if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){ - testcase( pRec->flags & MEM_Int ); - testcase( pRec->flags & MEM_Real ); - testcase( pRec->flags & MEM_IntReal ); - sqlite3VdbeMemStringify(pRec, enc, 1); - } - } - pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal); - } -} - -/* -** Try to convert the type of a function argument or a result column -** into a numeric representation. Use either INTEGER or REAL whichever -** is appropriate. But only do the conversion if it is possible without -** loss of information and return the revised type of the argument. -*/ -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ - int eType = sqlite3_value_type(pVal); - if( eType==SQLITE_TEXT ){ - Mem *pMem = (Mem*)pVal; - applyNumericAffinity(pMem, 0); - eType = sqlite3_value_type(pVal); - } - return eType; -} - -/* -** Exported version of applyAffinity(). This one works on sqlite3_value*, -** not the internal Mem* type. -*/ -SQLITE_PRIVATE void sqlite3ValueApplyAffinity( - sqlite3_value *pVal, - u8 affinity, - u8 enc -){ - applyAffinity((Mem *)pVal, affinity, enc); -} - -/* -** pMem currently only holds a string type (or maybe a BLOB that we can -** interpret as a string if we want to). Compute its corresponding -** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields -** accordingly. -*/ -static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ - int rc; - sqlite3_int64 ix; - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ); - assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); - if( ExpandBlob(pMem) ){ - pMem->u.i = 0; - return MEM_Int; - } - rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( rc<=0 ){ - if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ - pMem->u.i = ix; - return MEM_Int; - }else{ - return MEM_Real; - } - }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){ - pMem->u.i = ix; - return MEM_Int; - } - return MEM_Real; -} - -/* -** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or -** none. -** -** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. -** But it does set pMem->u.r and pMem->u.i appropriately. -*/ -static u16 numericType(Mem *pMem){ - assert( (pMem->flags & MEM_Null)==0 - || pMem->db==0 || pMem->db->mallocFailed ); - if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null) ){ - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_Real ); - testcase( pMem->flags & MEM_IntReal ); - return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null); - } - assert( pMem->flags & (MEM_Str|MEM_Blob) ); - testcase( pMem->flags & MEM_Str ); - testcase( pMem->flags & MEM_Blob ); - return computeNumericType(pMem); - return 0; -} - -#ifdef SQLITE_DEBUG -/* -** Write a nice string representation of the contents of cell pMem -** into buffer zBuf, length nBuf. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){ - int f = pMem->flags; - static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; - if( f&MEM_Blob ){ - int i; - char c; - if( f & MEM_Dyn ){ - c = 'z'; - assert( (f & (MEM_Static|MEM_Ephem))==0 ); - }else if( f & MEM_Static ){ - c = 't'; - assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); - }else if( f & MEM_Ephem ){ - c = 'e'; - assert( (f & (MEM_Static|MEM_Dyn))==0 ); - }else{ - c = 's'; - } - sqlite3_str_appendf(pStr, "%cx[", c); - for(i=0; i<25 && in; i++){ - sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF)); - } - sqlite3_str_appendf(pStr, "|"); - for(i=0; i<25 && in; i++){ - char z = pMem->z[i]; - sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z); - } - sqlite3_str_appendf(pStr,"]"); - if( f & MEM_Zero ){ - sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero); - } - }else if( f & MEM_Str ){ - int j; - u8 c; - if( f & MEM_Dyn ){ - c = 'z'; - assert( (f & (MEM_Static|MEM_Ephem))==0 ); - }else if( f & MEM_Static ){ - c = 't'; - assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); - }else if( f & MEM_Ephem ){ - c = 'e'; - assert( (f & (MEM_Static|MEM_Dyn))==0 ); - }else{ - c = 's'; - } - sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n); - for(j=0; j<25 && jn; j++){ - c = pMem->z[j]; - sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.'); - } - sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]); - if( f & MEM_Term ){ - sqlite3_str_appendf(pStr, "(0-term)"); - } - } -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Print the value of a register for tracing purposes: -*/ -static void memTracePrint(Mem *p){ - if( p->flags & MEM_Undefined ){ - printf(" undefined"); - }else if( p->flags & MEM_Null ){ - printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); - }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - printf(" si:%lld", p->u.i); - }else if( (p->flags & (MEM_IntReal))!=0 ){ - printf(" ir:%lld", p->u.i); - }else if( p->flags & MEM_Int ){ - printf(" i:%lld", p->u.i); -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( p->flags & MEM_Real ){ - printf(" r:%.17g", p->u.r); -#endif - }else if( sqlite3VdbeMemIsRowSet(p) ){ - printf(" (rowset)"); - }else{ - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(p, &acc); - printf(" %s", sqlite3StrAccumFinish(&acc)); - } - if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); -} -static void registerTrace(int iReg, Mem *p){ - printf("R[%d] = ", iReg); - memTracePrint(p); - if( p->pScopyFrom ){ - assert( p->pScopyFrom->bScopy ); - printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg])); - } - printf("\n"); - sqlite3VdbeCheckMemInvariants(p); -} -/**/ void sqlite3PrintMem(Mem *pMem){ - memTracePrint(pMem); - printf("\n"); - fflush(stdout); -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Show the values of all registers in the virtual machine. Used for -** interactive debugging. -*/ -SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){ - int i; - for(i=1; inMem; i++) registerTrace(i, v->aMem+i); -} -#endif /* SQLITE_DEBUG */ - - -#ifdef SQLITE_DEBUG -# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M) -#else -# define REGISTER_TRACE(R,M) -#endif - -#ifndef NDEBUG -/* -** This function is only called from within an assert() expression. It -** checks that the sqlite3.nTransaction variable is correctly set to -** the number of non-transaction savepoints currently in the -** linked list starting at sqlite3.pSavepoint. -** -** Usage: -** -** assert( checkSavepointCount(db) ); -*/ -static int checkSavepointCount(sqlite3 *db){ - int n = 0; - Savepoint *p; - for(p=db->pSavepoint; p; p=p->pNext) n++; - assert( n==(db->nSavepoint + db->isTransactionSavepoint) ); - return 1; -} -#endif - -/* -** Return the register of pOp->p2 after first preparing it to be -** overwritten with an integer value. -*/ -static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){ - sqlite3VdbeMemSetNull(pOut); - pOut->flags = MEM_Int; - return pOut; -} -static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ - Mem *pOut; - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - pOut = &p->aMem[pOp->p2]; - memAboutToChange(p, pOut); - if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/ - return out2PrereleaseWithClear(pOut); - }else{ - pOut->flags = MEM_Int; - return pOut; - } -} - -/* -** 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; iflags & (MEM_Int|MEM_IntReal) ){ - h += p->u.i; - }else if( p->flags & MEM_Real ){ - h += sqlite3VdbeIntValue(p); - }else if( p->flags & (MEM_Str|MEM_Blob) ){ - /* All strings have the same hash and all blobs have the same hash, - ** though, at least, those hashes are different from each other and - ** from NULL. */ - h += 4093 + (p->flags & (MEM_Str|MEM_Blob)); - } - } - return h; -} - - -/* -** For OP_Column, factor out the case where content is loaded from -** overflow pages, so that the code to implement this case is separate -** the common case where all content fits on the page. Factoring out -** the code reduces register pressure and helps the common case -** to run faster. -*/ -static SQLITE_NOINLINE int vdbeColumnFromOverflow( - VdbeCursor *pC, /* The BTree cursor from which we are reading */ - int iCol, /* The column to read */ - int t, /* The serial-type code for the column value */ - i64 iOffset, /* Offset to the start of the content value */ - u32 cacheStatus, /* Current Vdbe.cacheCtr value */ - u32 colCacheCtr, /* Current value of the column cache counter */ - Mem *pDest /* Store the value into this register. */ -){ - int rc; - sqlite3 *db = pDest->db; - int encoding = pDest->enc; - int len = sqlite3VdbeSerialTypeLen(t); - assert( pC->eCurType==CURTYPE_BTREE ); - if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG; - if( len > 4000 && pC->pKeyInfo==0 ){ - /* Cache large column values that are on overflow pages using - ** an RCStr (reference counted string) so that if they are reloaded, - ** that do not have to be copied a second time. The overhead of - ** creating and managing the cache is such that this is only - ** profitable for larger TEXT and BLOB values. - ** - ** Only do this on table-btrees so that writes to index-btrees do not - ** need to clear the cache. This buys performance in the common case - ** in exchange for generality. - */ - VdbeTxtBlbCache *pCache; - char *pBuf; - if( pC->colCache==0 ){ - pC->pCache = sqlite3DbMallocZero(db, sizeof(VdbeTxtBlbCache) ); - if( pC->pCache==0 ) return SQLITE_NOMEM; - pC->colCache = 1; - } - pCache = pC->pCache; - if( pCache->pCValue==0 - || pCache->iCol!=iCol - || pCache->cacheStatus!=cacheStatus - || pCache->colCacheCtr!=colCacheCtr - || pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor) - ){ - if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue); - pBuf = pCache->pCValue = sqlite3RCStrNew( len+3 ); - if( pBuf==0 ) return SQLITE_NOMEM; - rc = sqlite3BtreePayload(pC->uc.pCursor, iOffset, len, pBuf); - if( rc ) return rc; - pBuf[len] = 0; - pBuf[len+1] = 0; - pBuf[len+2] = 0; - pCache->iCol = iCol; - pCache->cacheStatus = cacheStatus; - pCache->colCacheCtr = colCacheCtr; - pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor); - }else{ - pBuf = pCache->pCValue; - } - assert( t>=12 ); - sqlite3RCStrRef(pBuf); - if( t&1 ){ - rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding, - sqlite3RCStrUnref); - pDest->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0, - sqlite3RCStrUnref); - } - }else{ - rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest); - if( rc ) return rc; - sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); - if( (t&1)!=0 && encoding==SQLITE_UTF8 ){ - pDest->z[len] = 0; - pDest->flags |= MEM_Term; - } - } - pDest->flags &= ~MEM_Ephem; - return rc; -} - - -/* -** 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[sqlite3_value_type(pMem)-1]; -} - -/* -** Execute as much of a VDBE program as we can. -** This is the core of sqlite3_step(). -*/ -SQLITE_PRIVATE int sqlite3VdbeExec( - Vdbe *p /* The VDBE */ -){ - Op *aOp = p->aOp; /* Copy of p->aOp */ - Op *pOp = aOp; /* Current operation */ -#ifdef SQLITE_DEBUG - Op *pOrigOp; /* Value of pOp at the top of the loop */ - int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ - u8 iCompareIsInit = 0; /* iCompare is initialized */ -#endif - int rc = SQLITE_OK; /* Value to return */ - sqlite3 *db = p->db; /* The database */ - u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ - u8 encoding = ENC(db); /* The database encoding */ - int iCompare = 0; /* Result of last comparison */ - u64 nVmStep = 0; /* Number of virtual machine steps */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u64 nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */ -#endif - Mem *aMem = p->aMem; /* Copy of p->aMem */ - Mem *pIn1 = 0; /* 1st input operand */ - Mem *pIn2 = 0; /* 2nd input operand */ - Mem *pIn3 = 0; /* 3rd input operand */ - Mem *pOut = 0; /* Output operand */ - u32 colCacheCtr = 0; /* Column cache counter */ -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - u64 *pnCycle = 0; - int bStmtScanStatus = IS_STMT_SCANSTATUS(db)!=0; -#endif - /*** INSERT STACK UNION HERE ***/ - - assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlite3_step() verifies this */ - if( DbMaskNonZero(p->lockMask) ){ - sqlite3VdbeEnter(p); - } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; - assert( 0 < db->nProgressOps ); - nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); - }else{ - nProgressLimit = LARGEST_UINT64; - } -#endif - if( p->rc==SQLITE_NOMEM ){ - /* This happens if a malloc() inside a call to sqlite3_column_text() or - ** sqlite3_column_text16() failed. */ - goto no_mem; - } - assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY ); - testcase( p->rc!=SQLITE_OK ); - p->rc = SQLITE_OK; - assert( p->bIsReader || p->readOnly!=0 ); - p->iCurrentTime = 0; - assert( p->explain==0 ); - db->busyHandler.nBusy = 0; - if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; - sqlite3VdbeIOTraceSql(p); -#ifdef SQLITE_DEBUG - sqlite3BeginBenignMalloc(); - if( p->pc==0 - && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0 - ){ - int i; - int once = 1; - sqlite3VdbePrintSql(p); - if( p->db->flags & SQLITE_VdbeListing ){ - printf("VDBE Program Listing:\n"); - for(i=0; inOp; i++){ - sqlite3VdbePrintOp(stdout, i, &aOp[i]); - } - } - if( p->db->flags & SQLITE_VdbeEQP ){ - for(i=0; inOp; i++){ - if( aOp[i].opcode==OP_Explain ){ - if( once ) printf("VDBE Query Plan:\n"); - printf("%s\n", aOp[i].p4.z); - once = 0; - } - } - } - if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n"); - } - sqlite3EndBenignMalloc(); -#endif - for(pOp=&aOp[p->pc]; 1; pOp++){ - /* Errors are detected by individual opcodes, with an immediate - ** jumps to abort_due_to_error. */ - assert( rc==SQLITE_OK ); - - assert( pOp>=aOp && pOp<&aOp[p->nOp]); - nVmStep++; - -#if defined(VDBE_PROFILE) - pOp->nExec++; - pnCycle = &pOp->nCycle; - if( sqlite3NProfileCnt==0 ) *pnCycle -= sqlite3Hwtime(); -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( bStmtScanStatus ){ - pOp->nExec++; - pnCycle = &pOp->nCycle; - *pnCycle -= sqlite3Hwtime(); - } -#endif - - /* Only allow tracing if SQLITE_DEBUG is defined. - */ -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeTrace ){ - sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); - test_trace_breakpoint((int)(pOp - aOp),pOp,p); - } -#endif - - - /* Check to see if we need to simulate an interrupt. This only happens - ** if we have a special test build. - */ -#ifdef SQLITE_TEST - if( sqlite3_interrupt_count>0 ){ - sqlite3_interrupt_count--; - if( sqlite3_interrupt_count==0 ){ - sqlite3_interrupt(db); - } - } -#endif - - /* Sanity checking on other operands */ -#ifdef SQLITE_DEBUG - { - u8 opProperty = sqlite3OpcodeProperty[pOp->opcode]; - if( (opProperty & OPFLG_IN1)!=0 ){ - assert( pOp->p1>0 ); - assert( pOp->p1<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p1]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); - REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); - } - if( (opProperty & OPFLG_IN2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p2]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); - REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); - } - if( (opProperty & OPFLG_IN3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p3]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); - REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); - } - if( (opProperty & OPFLG_OUT2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - memAboutToChange(p, &aMem[pOp->p2]); - } - if( (opProperty & OPFLG_OUT3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - memAboutToChange(p, &aMem[pOp->p3]); - } - } -#endif -#ifdef SQLITE_DEBUG - pOrigOp = pOp; -#endif - - switch( pOp->opcode ){ - -/***************************************************************************** -** What follows is a massive switch statement where each case implements a -** separate instruction in the virtual machine. If we follow the usual -** indentation conventions, each case should be indented by 6 spaces. But -** that is a lot of wasted space on the left margin. So the code within -** the switch statement will break with convention and be flush-left. Another -** big comment (similar to this one) will mark the point in the code where -** we transition back to normal indentation. -** -** The formatting of each case is important. The makefile for SQLite -** generates two C files "opcodes.h" and "opcodes.c" by scanning this -** file looking for lines that begin with "case OP_". The opcodes.h files -** will be filled with #defines that give unique integer values to each -** opcode and the opcodes.c file is filled with an array of strings where -** each string is the symbolic name for the corresponding opcode. If the -** case statement is followed by a comment of the form "/# same as ... #/" -** that comment is used to determine the particular value of the opcode. -** -** Other keywords in the comment that follows each case are used to -** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. -** Keywords include: in1, in2, in3, out2, out3. See -** the mkopcodeh.awk script for additional information. -** -** Documentation about VDBE opcodes is generated by scanning this file -** for lines of that contain "Opcode:". That line and all subsequent -** comment lines are used in the generation of the opcode.html documentation -** file. -** -** SUMMARY: -** -** Formatting is important to scripts that scan this file. -** Do not deviate from the formatting style currently in use. -** -*****************************************************************************/ - -/* Opcode: Goto * P2 * * * -** -** An unconditional jump to address P2. -** The next instruction executed will be -** the one at index P2 from the beginning of -** the program. -** -** The P1 parameter is not actually used by this opcode. However, it -** is sometimes set to 1 instead of 0 as a hint to the command-line shell -** that this Goto is the bottom of a loop and that the lines from P2 down -** to the current line should be indented for EXPLAIN output. -*/ -case OP_Goto: { /* jump */ - -#ifdef SQLITE_DEBUG - /* In debugging mode, when the p5 flags is set on an OP_Goto, that - ** means we should really jump back to the preceding OP_ReleaseReg - ** instruction. */ - if( pOp->p5 ){ - assert( pOp->p2 < (int)(pOp - aOp) ); - assert( pOp->p2 > 1 ); - pOp = &aOp[pOp->p2 - 2]; - assert( pOp[1].opcode==OP_ReleaseReg ); - goto check_for_interrupt; - } -#endif - -jump_to_p2_and_check_for_interrupt: - pOp = &aOp[pOp->p2 - 1]; - - /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, - ** OP_VNext, or OP_SorterNext) all jump here upon - ** completion. Check to see if sqlite3_interrupt() has been called - ** or if the progress callback needs to be invoked. - ** - ** This code uses unstructured "goto" statements and does not look clean. - ** But that is not due to sloppy coding habits. The code is written this - ** way for performance, to avoid having to run the interrupt and progress - ** checks on every opcode. This helps sqlite3_step() to run about 1.5% - ** faster according to "valgrind --tool=cachegrind" */ -check_for_interrupt: - if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Call the progress callback if it is configured and the required number - ** of VDBE ops have been executed (either since this invocation of - ** sqlite3VdbeExec() or since last time the progress callback was called). - ** If the progress callback returns non-zero, exit the virtual machine with - ** a return code SQLITE_ABORT. - */ - while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ - assert( db->nProgressOps!=0 ); - nProgressLimit += db->nProgressOps; - if( db->xProgress(db->pProgressArg) ){ - nProgressLimit = LARGEST_UINT64; - rc = SQLITE_INTERRUPT; - goto abort_due_to_error; - } - } -#endif - - break; -} - -/* Opcode: Gosub P1 P2 * * * -** -** Write the current address onto register P1 -** and then jump to address P2. -*/ -case OP_Gosub: { /* jump */ - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - pIn1 = &aMem[pOp->p1]; - assert( VdbeMemDynamic(pIn1)==0 ); - memAboutToChange(p, pIn1); - pIn1->flags = MEM_Int; - pIn1->u.i = (int)(pOp-aOp); - REGISTER_TRACE(pOp->p1, pIn1); - goto jump_to_p2_and_check_for_interrupt; -} - -/* Opcode: Return P1 P2 P3 * * -** -** 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]; - 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; -} - -/* Opcode: InitCoroutine P1 P2 P3 * * -** -** Set up register P1 so that it will Yield to the coroutine -** located at address P3. -** -** If P2!=0 then the coroutine implementation immediately follows -** this opcode. So jump over the coroutine implementation to -** address P2. -** -** See also: EndCoroutine -*/ -case OP_InitCoroutine: { /* jump0 */ - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - assert( pOp->p2>=0 && pOp->p2nOp ); - assert( pOp->p3>=0 && pOp->p3nOp ); - pOut = &aMem[pOp->p1]; - assert( !VdbeMemDynamic(pOut) ); - pOut->u.i = pOp->p3 - 1; - pOut->flags = MEM_Int; - 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->p2nOp ); /* Jumps must be in range */ - pOp = &aOp[pOp->p2 - 1]; - break; -} - -/* Opcode: EndCoroutine P1 * * * * -** -** The instruction at the address in register P1 is a Yield. -** Jump to the P2 parameter of that Yield. -** After the jump, the value register P1 is left with a value -** such that subsequent OP_Yields go back to the this same -** OP_EndCoroutine instruction. -** -** See also: InitCoroutine -*/ -case OP_EndCoroutine: { /* in1 */ - VdbeOp *pCaller; - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags==MEM_Int ); - assert( pIn1->u.i>=0 && pIn1->u.inOp ); - pCaller = &aOp[pIn1->u.i]; - assert( pCaller->opcode==OP_Yield ); - assert( pCaller->p2>=0 && pCaller->p2nOp ); - pIn1->u.i = (int)(pOp - p->aOp) - 1; - pOp = &aOp[pCaller->p2 - 1]; - break; -} - -/* Opcode: Yield P1 P2 * * * -** -** Swap the program counter with the value in register P1. This -** has the effect of yielding to a coroutine. -** -** If the coroutine that is launched by this instruction ends with -** Yield or Return then continue to the next instruction. But if -** the coroutine launched by this instruction ends with -** EndCoroutine, then jump to P2 rather than continuing with the -** next instruction. -** -** See also: InitCoroutine -*/ -case OP_Yield: { /* in1, jump0 */ - int pcDest; - pIn1 = &aMem[pOp->p1]; - assert( VdbeMemDynamic(pIn1)==0 ); - pIn1->flags = MEM_Int; - pcDest = (int)pIn1->u.i; - pIn1->u.i = (int)(pOp - aOp); - REGISTER_TRACE(pOp->p1, pIn1); - pOp = &aOp[pcDest]; - break; -} - -/* Opcode: HaltIfNull P1 P2 P3 P4 P5 -** Synopsis: if r[P3]=null halt -** -** Check the value in register P3. If it is NULL then Halt using -** parameter P1, P2, and P4 as if this were a Halt instruction. If the -** value in register P3 is not NULL, then this routine is a no-op. -** The P5 parameter should be 1. -*/ -case OP_HaltIfNull: { /* in3 */ - pIn3 = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } -#endif - if( (pIn3->flags & MEM_Null)==0 ) break; - /* Fall through into OP_Halt */ - /* no break */ deliberate_fall_through -} - -/* Opcode: Halt P1 P2 P3 P4 P5 -** -** Exit immediately. All open cursors, etc are closed -** automatically. -** -** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), -** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). -** For errors, it can be some other value. If P1!=0 then P2 will determine -** whether or not to rollback the current transaction. Do not rollback -** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, -** then back out all changes that have occurred during this execution of the -** VDBE, but do not rollback the transaction. -** -** If P3 is not zero and P4 is NULL, then P3 is a register that holds the -** text of an error message. -** -** If P3 is zero and P4 is not null then the error message string is held -** in P4. -** -** P5 is a value between 1 and 4, inclusive, then the P4 error message -** string is modified as follows: -** -** 1: NOT NULL constraint failed: P4 -** 2: UNIQUE constraint failed: P4 -** 3: CHECK constraint failed: P4 -** 4: FOREIGN KEY constraint failed: P4 -** -** If P3 is zero and P5 is not zero and P4 is NULL, then everything after -** the ":" is omitted. -** -** There is an implied "Halt 0 0 0" instruction inserted at the very end of -** every program. So a jump past the last instruction of the program -** is the same as executing Halt. -*/ -case OP_Halt: { - VdbeFrame *pFrame; - int pcx; - -#ifdef SQLITE_DEBUG - if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } -#endif - assert( pOp->p4type==P4_NOTUSED - || pOp->p4type==P4_STATIC - || pOp->p4type==P4_DYNAMIC ); - - /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates - ** something is wrong with the code generator. Raise an assertion in order - ** to bring this to the attention of fuzzers and other testing tools. */ - assert( pOp->p1!=SQLITE_INTERNAL ); - - if( p->pFrame && pOp->p1==SQLITE_OK ){ - /* Halt the sub-program. Return control to the parent frame. */ - pFrame = p->pFrame; - p->pFrame = pFrame->pParent; - p->nFrame--; - sqlite3VdbeSetChanges(db, p->nChange); - pcx = sqlite3VdbeFrameRestore(pFrame); - if( pOp->p2==OE_Ignore ){ - /* Instruction pcx is the OP_Program that invoked the sub-program - ** currently being halted. If the p2 instruction of this OP_Halt - ** instruction is set to OE_Ignore, then the sub-program is throwing - ** an IGNORE exception. In this case jump to the address specified - ** as the p2 of the calling OP_Program. */ - pcx = p->aOp[pcx].p2-1; - } - aOp = p->aOp; - aMem = p->aMem; - pOp = &aOp[pcx]; - break; - } - p->rc = pOp->p1; - p->errorAction = (u8)pOp->p2; - assert( pOp->p5<=4 ); - if( p->rc ){ - if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){ - const char *zErr; - assert( pOp->p3<=(p->nMem + 1 - p->nCursor) ); - zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8); - sqlite3VdbeError(p, "%s", zErr); - }else if( pOp->p5 ){ - static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", - "FOREIGN KEY" }; - testcase( pOp->p5==1 ); - testcase( pOp->p5==2 ); - testcase( pOp->p5==3 ); - testcase( pOp->p5==4 ); - sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]); - if( pOp->p4.z ){ - p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z); - } - }else{ - sqlite3VdbeError(p, "%s", pOp->p4.z); - } - pcx = (int)(pOp - aOp); - sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql); - } - rc = sqlite3VdbeHalt(p); - assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); - if( rc==SQLITE_BUSY ){ - p->rc = SQLITE_BUSY; - }else{ - assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); - rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; - } - goto vdbe_return; -} - -/* Opcode: Integer P1 P2 * * * -** Synopsis: r[P2]=P1 -** -** The 32-bit integer value P1 is written into register P2. -*/ -case OP_Integer: { /* out2 */ - pOut = out2Prerelease(p, pOp); - pOut->u.i = pOp->p1; - break; -} - -/* Opcode: Int64 * P2 * P4 * -** Synopsis: r[P2]=P4 -** -** P4 is a pointer to a 64-bit integer value. -** Write that value into register P2. -*/ -case OP_Int64: { /* out2 */ - pOut = out2Prerelease(p, pOp); - assert( pOp->p4.pI64!=0 ); - pOut->u.i = *pOp->p4.pI64; - break; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* Opcode: Real * P2 * P4 * -** Synopsis: r[P2]=P4 -** -** P4 is a pointer to a 64-bit floating point value. -** Write that value into register P2. -*/ -case OP_Real: { /* same as TK_FLOAT, out2 */ - pOut = out2Prerelease(p, pOp); - pOut->flags = MEM_Real; - assert( !sqlite3IsNaN(*pOp->p4.pReal) ); - pOut->u.r = *pOp->p4.pReal; - break; -} -#endif - -/* Opcode: String8 * P2 * P4 * -** Synopsis: r[P2]='P4' -** -** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into a String opcode before it is executed for the first time. During -** this transformation, the length of string P4 is computed and stored -** as the P1 parameter. -*/ -case OP_String8: { /* same as TK_STRING, out2 */ - assert( pOp->p4.z!=0 ); - pOut = out2Prerelease(p, pOp); - pOp->p1 = sqlite3Strlen30(pOp->p4.z); - -#ifndef SQLITE_OMIT_UTF16 - if( encoding!=SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); - assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG ); - if( rc ) goto too_big; - if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; - assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); - assert( VdbeMemDynamic(pOut)==0 ); - pOut->szMalloc = 0; - pOut->flags |= MEM_Static; - if( pOp->p4type==P4_DYNAMIC ){ - sqlite3DbFree(db, pOp->p4.z); - } - pOp->p4type = P4_DYNAMIC; - pOp->p4.z = pOut->z; - pOp->p1 = pOut->n; - } -#endif - if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - pOp->opcode = OP_String; - assert( rc==SQLITE_OK ); - /* Fall through to the next case, OP_String */ - /* no break */ deliberate_fall_through -} - -/* Opcode: String P1 P2 P3 P4 P5 -** Synopsis: r[P2]='P4' (len=P1) -** -** The string value P4 of length P1 (bytes) is stored in register P2. -** -** If P3 is not zero and the content of register P3 is equal to P5, then -** the datatype of the register P2 is converted to BLOB. The content is -** the same sequence of bytes, it is merely interpreted as a BLOB instead -** of a string, as if it had been CAST. In other words: -** -** if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB) -*/ -case OP_String: { /* out2 */ - assert( pOp->p4.z!=0 ); - pOut = out2Prerelease(p, pOp); - pOut->flags = MEM_Str|MEM_Static|MEM_Term; - pOut->z = pOp->p4.z; - pOut->n = pOp->p1; - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pOp->p3>0 ){ - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - pIn3 = &aMem[pOp->p3]; - assert( pIn3->flags & MEM_Int ); - if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; - } -#endif - 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 -** -** Write a NULL into registers P2. If P3 greater than P2, then also write -** NULL into register P3 and every register in between P2 and P3. If P3 -** is less than P2 (typically P3 is zero) then only register P2 is -** set to NULL. -** -** If the P1 value is non-zero, then also set the MEM_Cleared flag so that -** 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; - pOut = out2Prerelease(p, pOp); - cnt = pOp->p3-pOp->p2; - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; - pOut->n = 0; -#ifdef SQLITE_DEBUG - pOut->uTemp = 0; -#endif - while( cnt>0 ){ - pOut++; - memAboutToChange(p, pOut); - sqlite3VdbeMemSetNull(pOut); - pOut->flags = nullFlag; - pOut->n = 0; - cnt--; - } - break; -} - -/* Opcode: SoftNull P1 * * * * -** Synopsis: r[P1]=NULL -** -** Set register P1 to have the value NULL as seen by the OP_MakeRecord -** instruction, but do not free any string or blob memory associated with -** the register, so that if the value was a string or blob that was -** previously copied using OP_SCopy, the copies will continue to be valid. -*/ -case OP_SoftNull: { - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - pOut = &aMem[pOp->p1]; - pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null; - break; -} - -/* Opcode: Blob P1 P2 * P4 * -** Synopsis: r[P2]=P4 (len=P1) -** -** P4 points to a blob of data P1 bytes long. Store this -** blob in register P2. 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); - if( pOp->p4.z==0 ){ - sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1); - if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem; - }else{ - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); - } - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Variable P1 P2 * * * -** Synopsis: r[P2]=parameter(P1) -** -** Transfer the values of bound parameter P1 into register P2 -*/ -case OP_Variable: { /* out2 */ - Mem *pVar; /* Value being transferred */ - - assert( pOp->p1>0 && pOp->p1<=p->nVar ); - pVar = &p->aVar[pOp->p1 - 1]; - if( sqlite3VdbeMemTooBig(pVar) ){ - goto too_big; - } - pOut = &aMem[pOp->p2]; - if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); - memcpy(pOut, pVar, MEMCELLSIZE); - pOut->flags &= ~(MEM_Dyn|MEM_Ephem); - pOut->flags |= MEM_Static|MEM_FromBind; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Move P1 P2 P3 * * -** Synopsis: r[P2@P3]=r[P1@P3] -** -** Move the P3 values in register P1..P1+P3-1 over into -** registers P2..P2+P3-1. Registers P1..P1+P3-1 are -** left holding a NULL. It is an error for register ranges -** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error -** for P3 to be less than 1. -*/ -case OP_Move: { - int n; /* Number of registers left to copy */ - int p1; /* Register to copy from */ - int p2; /* Register to copy to */ - - n = pOp->p3; - p1 = pOp->p1; - p2 = pOp->p2; - assert( n>0 && p1>0 && p2>0 ); - assert( p1+n<=p2 || p2+n<=p1 ); - - pIn1 = &aMem[p1]; - pOut = &aMem[p2]; - do{ - assert( pOut<=&aMem[(p->nMem+1 - p->nCursor)] ); - assert( pIn1<=&aMem[(p->nMem+1 - p->nCursor)] ); - assert( memIsValid(pIn1) ); - memAboutToChange(p, pOut); - sqlite3VdbeMemMove(pOut, pIn1); -#ifdef SQLITE_DEBUG - pIn1->pScopyFrom = 0; - { int i; - for(i=1; inMem; i++){ - if( aMem[i].pScopyFrom==pIn1 ){ - assert( aMem[i].bScopy ); - aMem[i].pScopyFrom = pOut; - } - } - } -#endif - Deephemeralize(pOut); - REGISTER_TRACE(p2++, pOut); - pIn1++; - pOut++; - }while( --n ); - break; -} - -/* 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. -*/ -case OP_Copy: { - int n; - - n = pOp->p3; - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - assert( pOut!=pIn1 ); - while( 1 ){ - memAboutToChange(p, pOut); - 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 - REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); - if( (n--)==0 ) break; - pOut++; - pIn1++; - } - break; -} - -/* Opcode: SCopy P1 P2 * * * -** Synopsis: r[P2]=r[P1] -** -** Make a shallow copy of register P1 into register P2. -** -** This instruction makes a shallow copy of the value. If the value -** is a string or blob, then the copy is only a pointer to the -** original and hence if the original changes so will the copy. -** Worse, if the original is deallocated, the copy becomes invalid. -** Thus the program must guarantee that the original will not change -** during the lifetime of the copy. Use OP_Copy to make a complete -** copy. -*/ -case OP_SCopy: { /* out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - assert( pOut!=pIn1 ); - sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); -#ifdef SQLITE_DEBUG - pOut->pScopyFrom = pIn1; - pOut->mScopyFlags = pIn1->flags; - pIn1->bScopy = 1; -#endif - break; -} - -/* Opcode: IntCopy P1 P2 * * * -** Synopsis: r[P2]=r[P1] -** -** Transfer the integer value held in register P1 into register P2. -** -** This is an optimized version of SCopy that works only for integer -** values. -*/ -case OP_IntCopy: { /* out2 */ - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Int)!=0 ); - pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetInt64(pOut, pIn1->u.i); - 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 = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){ - goto abort_due_to_error; - } - break; -} - -/* Opcode: ResultRow P1 P2 * * * -** Synopsis: output=r[P1@P2] -** -** The registers P1 through P1+P2-1 contain a single row of -** results. This opcode causes the sqlite3_step() call to terminate -** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the r(P1)..r(P1+P2-1) values as -** the result row. -*/ -case OP_ResultRow: { - assert( p->nResColumn==pOp->p2 ); - assert( pOp->p1>0 || CORRUPT_DB ); - assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); - - p->cacheCtr = (p->cacheCtr + 2)|1; - p->pResultRow = &aMem[pOp->p1]; -#ifdef SQLITE_DEBUG - { - Mem *pMem = p->pResultRow; - int i; - for(i=0; ip2; 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 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); - } - p->pc = (int)(pOp - aOp) + 1; - rc = SQLITE_ROW; - goto vdbe_return; -} - -/* Opcode: Concat P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]+r[P1] -** -** Add the text in register P1 onto the end of the text in -** register P2 and store the result in register P3. -** If either the P1 or P2 text are NULL then store NULL in P3. -** -** P3 = P2 || P1 -** -** It is illegal for P1 and P3 to be the same register. Sometimes, -** if P3 is the same register as P2, the implementation is able -** to avoid a memcpy(). -*/ -case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ - i64 nByte; /* Total size of the output string or blob */ - u16 flags1; /* Initial flags for P1 */ - u16 flags2; /* Initial flags for P2 */ - - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - pOut = &aMem[pOp->p3]; - testcase( pOut==pIn2 ); - assert( pIn1!=pOut ); - flags1 = pIn1->flags; - testcase( flags1 & MEM_Null ); - testcase( pIn2->flags & MEM_Null ); - if( (flags1 | pIn2->flags) & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - break; - } - if( (flags1 & (MEM_Str|MEM_Blob))==0 ){ - if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem; - flags1 = pIn1->flags & ~MEM_Str; - }else if( (flags1 & MEM_Zero)!=0 ){ - if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; - flags1 = pIn1->flags & ~MEM_Str; - } - flags2 = pIn2->flags; - if( (flags2 & (MEM_Str|MEM_Blob))==0 ){ - if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem; - flags2 = pIn2->flags & ~MEM_Str; - }else if( (flags2 & MEM_Zero)!=0 ){ - if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem; - flags2 = pIn2->flags & ~MEM_Str; - } - nByte = pIn1->n + pIn2->n; - if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ - goto no_mem; - } - MemSetTypeFlag(pOut, MEM_Str); - if( pOut!=pIn2 ){ - memcpy(pOut->z, pIn2->z, pIn2->n); - assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) ); - pIn2->flags = flags2; - } - 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->flags |= MEM_Term; - pOut->n = (int)nByte; - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Add P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]+r[P2] -** -** Add the value in register P1 to the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Multiply P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]*r[P2] -** -** -** Multiply the value in register P1 by the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Subtract P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]-r[P1] -** -** Subtract the value in register P1 from the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Divide P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]/r[P1] -** -** Divide the value in register P1 by the value in register P2 -** and store the result in register P3 (P3=P2/P1). If the value in -** register P1 is zero, then the result is NULL. If either input is -** NULL, the result is NULL. -*/ -/* Opcode: Remainder P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]%r[P1] -** -** Compute the remainder after integer register P2 is divided by -** register P1 and store the result in register P3. -** If the value in register P1 is zero the result is NULL. -** If either operand is NULL, the result is NULL. -*/ -case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ -case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ -case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ -case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ -case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ - u16 type1; /* Numeric type of left operand */ - u16 type2; /* Numeric type of right operand */ - i64 iA; /* Integer value of left operand */ - i64 iB; /* Integer value of right operand */ - double rA; /* Real value of left operand */ - double rB; /* Real value of right operand */ - - pIn1 = &aMem[pOp->p1]; - type1 = pIn1->flags; - pIn2 = &aMem[pOp->p2]; - type2 = pIn2->flags; - pOut = &aMem[pOp->p3]; - if( (type1 & type2 & MEM_Int)!=0 ){ -int_math: - iA = pIn1->u.i; - iB = pIn2->u.i; - switch( pOp->opcode ){ - case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; - case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; - case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; - case OP_Divide: { - if( iA==0 ) goto arithmetic_result_is_null; - if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; - iB /= iA; - break; - } - default: { - if( iA==0 ) goto arithmetic_result_is_null; - if( iA==-1 ) iA = 1; - iB %= iA; - break; - } - } - pOut->u.i = iB; - MemSetTypeFlag(pOut, MEM_Int); - }else if( ((type1 | type2) & MEM_Null)!=0 ){ - goto arithmetic_result_is_null; - }else{ - type1 = numericType(pIn1); - type2 = numericType(pIn2); - if( (type1 & type2 & MEM_Int)!=0 ) goto int_math; -fp_math: - rA = sqlite3VdbeRealValue(pIn1); - rB = sqlite3VdbeRealValue(pIn2); - switch( pOp->opcode ){ - case OP_Add: rB += rA; break; - case OP_Subtract: rB -= rA; break; - case OP_Multiply: rB *= rA; break; - case OP_Divide: { - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( rA==(double)0 ) goto arithmetic_result_is_null; - rB /= rA; - break; - } - default: { - iA = sqlite3VdbeIntValue(pIn1); - iB = sqlite3VdbeIntValue(pIn2); - if( iA==0 ) goto arithmetic_result_is_null; - if( iA==-1 ) iA = 1; - rB = (double)(iB % iA); - break; - } - } -#ifdef SQLITE_OMIT_FLOATING_POINT - pOut->u.i = rB; - MemSetTypeFlag(pOut, MEM_Int); -#else - if( sqlite3IsNaN(rB) ){ - goto arithmetic_result_is_null; - } - pOut->u.r = rB; - MemSetTypeFlag(pOut, MEM_Real); -#endif - } - break; - -arithmetic_result_is_null: - sqlite3VdbeMemSetNull(pOut); - break; -} - -/* Opcode: CollSeq P1 * * P4 -** -** P4 is a pointer to a CollSeq object. If the next call to a user function -** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will -** be returned. This is used by the built-in min(), max() and nullif() -** functions. -** -** If P1 is not zero, then it is a register that a subsequent min() or -** max() aggregate will set to 1 if the current row is not the minimum or -** maximum. The P1 register is initialized to 0 by this instruction. -** -** The interface used by the implementation of the aforementioned functions -** to retrieve the collation sequence set by this opcode is not available -** publicly. Only built-in functions have access to this feature. -*/ -case OP_CollSeq: { - assert( pOp->p4type==P4_COLLSEQ ); - if( pOp->p1 ){ - sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); - } - break; -} - -/* Opcode: BitAnd P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]&r[P2] -** -** Take the bit-wise AND of the values in register P1 and P2 and -** store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: BitOr P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]|r[P2] -** -** Take the bit-wise OR of the values in register P1 and P2 and -** store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: ShiftLeft P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]<>r[P1] -** -** Shift the integer value in register P2 to the right by the -** number of bits specified by the integer in register P1. -** Store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ -case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ -case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ -case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ - i64 iA; - u64 uA; - i64 iB; - u8 op; - - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - pOut = &aMem[pOp->p3]; - if( (pIn1->flags | pIn2->flags) & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - break; - } - iA = sqlite3VdbeIntValue(pIn2); - iB = sqlite3VdbeIntValue(pIn1); - op = pOp->opcode; - if( op==OP_BitAnd ){ - iA &= iB; - }else if( op==OP_BitOr ){ - iA |= iB; - }else if( iB!=0 ){ - assert( op==OP_ShiftRight || op==OP_ShiftLeft ); - - /* If shifting by a negative amount, shift in the other direction */ - if( iB<0 ){ - assert( OP_ShiftRight==OP_ShiftLeft+1 ); - op = 2*OP_ShiftLeft + 1 - op; - iB = iB>(-64) ? -iB : 64; - } - - if( iB>=64 ){ - iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1; - }else{ - memcpy(&uA, &iA, sizeof(uA)); - if( op==OP_ShiftLeft ){ - uA <<= iB; - }else{ - uA >>= iB; - /* Sign-extend on a right shift of a negative number */ - if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB); - } - memcpy(&iA, &uA, sizeof(iA)); - } - } - pOut->u.i = iA; - MemSetTypeFlag(pOut, MEM_Int); - break; -} - -/* Opcode: AddImm P1 P2 * * * -** Synopsis: r[P1]=r[P1]+P2 -** -** Add the constant P2 to the value in register P1. -** The result is always an integer. -** -** To force any register to be an integer, just add 0. -*/ -case OP_AddImm: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - sqlite3VdbeMemIntegerify(pIn1); - *(u64*)&pIn1->u.i += (u64)pOp->p2; - break; -} - -/* Opcode: MustBeInt P1 P2 * * * -** -** Force the value in register P1 to be an integer. If the value -** in P1 is not an integer and cannot be converted into an integer -** without data loss, then jump immediately to P2, or if P2==0 -** raise an SQLITE_MISMATCH exception. -*/ -case OP_MustBeInt: { /* jump0, in1 */ - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Int)==0 ){ - applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); - if( (pIn1->flags & MEM_Int)==0 ){ - VdbeBranchTaken(1, 2); - if( pOp->p2==0 ){ - rc = SQLITE_MISMATCH; - goto abort_due_to_error; - }else{ - goto jump_to_p2; - } - } - } - VdbeBranchTaken(0, 2); - MemSetTypeFlag(pIn1, MEM_Int); - break; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* Opcode: RealAffinity P1 * * * * -** -** If register P1 holds an integer convert it to a real value. -** -** This opcode is used when extracting information from a column that -** has REAL affinity. Such column values may still be stored as -** integers, for space efficiency, but after extraction we want them -** to have only a real value. -*/ -case OP_RealAffinity: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pIn1->flags & MEM_Int ); - testcase( pIn1->flags & MEM_IntReal ); - sqlite3VdbeMemRealify(pIn1); - REGISTER_TRACE(pOp->p1, pIn1); - } - break; -} -#endif - -#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE) -/* Opcode: Cast P1 P2 * * * -** Synopsis: affinity(r[P1]) -** -** Force the value in register P1 to be the type defined by P2. -** -**
      -**
    • P2=='A' → BLOB -**
    • P2=='B' → TEXT -**
    • P2=='C' → NUMERIC -**
    • P2=='D' → INTEGER -**
    • P2=='E' → REAL -**
    -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_Cast: { /* in1 */ - assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL ); - testcase( pOp->p2==SQLITE_AFF_TEXT ); - testcase( pOp->p2==SQLITE_AFF_BLOB ); - testcase( pOp->p2==SQLITE_AFF_NUMERIC ); - testcase( pOp->p2==SQLITE_AFF_INTEGER ); - testcase( pOp->p2==SQLITE_AFF_REAL ); - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - rc = ExpandBlob(pIn1); - if( rc ) goto abort_due_to_error; - rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); - if( rc ) goto abort_due_to_error; - UPDATE_MAX_BLOBSIZE(pIn1); - REGISTER_TRACE(pOp->p1, pIn1); - break; -} -#endif /* SQLITE_OMIT_CAST */ - -/* Opcode: Eq 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. -** -** 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 -** to coerce both inputs according to this affinity before the -** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric -** affinity is used. Note that the affinity conversions are stored -** back into the input registers P1 and P3. So this opcode can cause -** persistent changes to registers P1 and P3. -** -** Once any conversions have taken place, and neither value is NULL, -** the values are compared. If both values are blobs then memcmp() is -** used to determine the results of the comparison. If both values -** are text, then the appropriate collating function specified in -** P4 is used to do the comparison. If P4 is not specified then -** memcmp() is used to compare text string. If both values are -** 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. -** -** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either -** true or false and is never NULL. If both operands are NULL then the result -** of comparison is true. If either operand is NULL then the result is false. -** If neither operand is NULL the result is the same as it would be if -** the SQLITE_NULLEQ flag were omitted from P5. -** -** 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] -** -** 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. -*/ -/* Opcode: Lt P1 P2 P3 P4 P5 -** Synopsis: IF r[P3]r[P1] -** -** This works just like the Lt opcode except that the jump is taken if -** the content of register P3 is greater than the content of -** register P1. See the Lt opcode for additional information. -*/ -/* Opcode: Ge P1 P2 P3 P4 P5 -** Synopsis: IF r[P3]>=r[P1] -** -** This works just like the Lt opcode except that the jump is taken if -** the content of register P3 is greater than or equal to the content of -** register P1. See the Lt opcode for additional information. -*/ -case OP_Eq: /* same as TK_EQ, jump, in1, in3 */ -case OP_Ne: /* same as TK_NE, jump, in1, in3 */ -case OP_Lt: /* same as TK_LT, jump, in1, in3 */ -case OP_Le: /* same as TK_LE, jump, in1, in3 */ -case OP_Gt: /* same as TK_GT, jump, in1, in3 */ -case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ - int res, res2; /* Result of the comparison of pIn1 against pIn3 */ - char affinity; /* Affinity to use for comparison */ - u16 flags1; /* Copy of initial value of pIn1->flags */ - u16 flags3; /* Copy of initial value of pIn3->flags */ - - pIn1 = &aMem[pOp->p1]; - pIn3 = &aMem[pOp->p3]; - flags1 = pIn1->flags; - flags3 = pIn3->flags; - if( (flags1 & flags3 & MEM_Int)!=0 ){ - /* Common case of comparison of two integers */ - if( pIn3->u.i > pIn1->u.i ){ - if( sqlite3aGTb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = +1; - VVA_ONLY( iCompareIsInit = 1; ) - }else if( pIn3->u.i < pIn1->u.i ){ - if( sqlite3aLTb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = -1; - VVA_ONLY( iCompareIsInit = 1; ) - }else{ - if( sqlite3aEQb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = 0; - VVA_ONLY( iCompareIsInit = 1; ) - } - 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 ){ - /* If SQLITE_NULLEQ is set (which will only happen if the operator is - ** OP_Eq or OP_Ne) then take the jump or not depending on whether - ** or not both operands are null. - */ - assert( (flags1 & MEM_Cleared)==0 ); - assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB ); - testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 ); - if( (flags1&flags3&MEM_Null)!=0 - && (flags3&MEM_Cleared)==0 - ){ - res = 0; /* Operands are equal */ - }else{ - res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */ - } - }else{ - /* SQLITE_NULLEQ is clear and at least one operand is NULL, - ** then the result is always NULL. - ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. - */ - VdbeBranchTaken(2,3); - if( pOp->p5 & SQLITE_JUMPIFNULL ){ - goto jump_to_p2; - } - iCompare = 1; /* Operands are not equal */ - VVA_ONLY( iCompareIsInit = 1; ) - break; - } - }else{ - /* 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 ){ - if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn1,0); - assert( flags3==pIn3->flags || CORRUPT_DB ); - flags3 = pIn3->flags; - } - if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3,0); - } - } - }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){ - if( (flags1 & MEM_Str)!=0 ){ - pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); - }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ - testcase( pIn1->flags & MEM_Int ); - testcase( pIn1->flags & MEM_Real ); - testcase( pIn1->flags & MEM_IntReal ); - 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( (flags3 & MEM_Str)!=0 ){ - pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); - }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ - testcase( pIn3->flags & MEM_Int ); - testcase( pIn3->flags & MEM_Real ); - testcase( pIn3->flags & MEM_IntReal ); - sqlite3VdbeMemStringify(pIn3, encoding, 1); - testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); - flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); - } - } - assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); - } - - /* 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 - ** operator actually is. The next block of code depends on the fact - ** that the 6 comparison operators are consecutive integers in this - ** 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 ){ - res2 = sqlite3aLTb[pOp->opcode]; - }else if( res==0 ){ - res2 = sqlite3aEQb[pOp->opcode]; - }else{ - res2 = sqlite3aGTb[pOp->opcode]; - } - iCompare = res; - VVA_ONLY( iCompareIsInit = 1; ) - - /* Undo any changes made by applyAffinity() to the input registers. */ - assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); - pIn3->flags = flags3; - assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); - pIn1->flags = flags1; - - VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); - if( res2 ){ - goto jump_to_p2; - } - break; -} - -/* 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. -** -** If the result of an OP_Eq comparison on the same two operands as -** the 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_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 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 ); - break; - } -#endif /* SQLITE_DEBUG */ - assert( iCompareIsInit ); - VdbeBranchTaken(iCompare==0, 2); - if( iCompare==0 ) goto jump_to_p2; - break; -} - - -/* Opcode: Permutation * * * P4 * -** -** 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 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. -*/ -case OP_Permutation: { - assert( pOp->p4type==P4_INTARRAY ); - assert( pOp->p4.ai ); - assert( pOp[1].opcode==OP_Compare ); - assert( pOp[1].p5 & OPFLAG_PERMUTE ); - break; -} - -/* Opcode: Compare P1 P2 P3 P4 P5 -** Synopsis: r[P1@P3] <-> r[P2@P3] -** -** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this -** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of -** the comparison for use by the next OP_Jump instruct. -** -** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is -** determined by the most recent OP_Permutation operator. If the -** OPFLAG_PERMUTE bit is clear, then register are compared in sequential -** order. -** -** P4 is a KeyInfo structure that defines collating sequences and sort -** orders for the comparison. The permutation applies to registers -** only. The KeyInfo elements are used sequentially. -** -** 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; - int i; - int p1; - int p2; - const KeyInfo *pKeyInfo; - u32 idx; - CollSeq *pColl; /* Collating sequence to use on this term */ - int bRev; /* True for DESCENDING sort order */ - u32 *aPermute; /* The permutation */ - - if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){ - aPermute = 0; - }else{ - assert( pOp>aOp ); - assert( pOp[-1].opcode==OP_Permutation ); - assert( pOp[-1].p4type==P4_INTARRAY ); - aPermute = pOp[-1].p4.ai + 1; - assert( aPermute!=0 ); - } - n = pOp->p3; - pKeyInfo = pOp->p4.pKeyInfo; - assert( n>0 ); - assert( pKeyInfo!=0 ); - p1 = pOp->p1; - p2 = pOp->p2; -#ifdef SQLITE_DEBUG - if( aPermute ){ - int k, mx = 0; - for(k=0; k(u32)mx ) mx = aPermute[k]; - assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); - assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); - }else{ - assert( p1>0 && p1+n<=(p->nMem+1 - p->nCursor)+1 ); - assert( p2>0 && p2+n<=(p->nMem+1 - p->nCursor)+1 ); - } -#endif /* SQLITE_DEBUG */ - for(i=0; inKeyField ); - pColl = pKeyInfo->aColl[i]; - bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC); - iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); - VVA_ONLY( iCompareIsInit = 1; ) - if( iCompare ){ - if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) - && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null)) - ){ - iCompare = -iCompare; - } - if( bRev ) iCompare = -iCompare; - break; - } - } - assert( pOp[1].opcode==OP_Jump ); - break; -} - -/* Opcode: Jump P1 P2 P3 * * -** -** 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 ); - assert( iCompareIsInit ); - if( iCompare<0 ){ - VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1]; - }else if( iCompare==0 ){ - VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1]; - }else{ - VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1]; - } - break; -} - -/* Opcode: And P1 P2 P3 * * -** Synopsis: r[P3]=(r[P1] && r[P2]) -** -** Take the logical AND of the values in registers P1 and P2 and -** write the result into register P3. -** -** If either P1 or P2 is 0 (false) then the result is 0 even if -** the other input is NULL. A NULL and true or two NULLs give -** a NULL output. -*/ -/* Opcode: Or P1 P2 P3 * * -** Synopsis: r[P3]=(r[P1] || r[P2]) -** -** Take the logical OR of the values in register P1 and P2 and -** store the answer in register P3. -** -** If either P1 or P2 is nonzero (true) then the result is 1 (true) -** even if the other input is NULL. A NULL and false or two NULLs -** give a NULL output. -*/ -case OP_And: /* same as TK_AND, in1, in2, out3 */ -case OP_Or: { /* same as TK_OR, in1, in2, out3 */ - int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - - v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2); - v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2); - if( pOp->opcode==OP_And ){ - static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; - v1 = and_logic[v1*3+v2]; - }else{ - static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; - v1 = or_logic[v1*3+v2]; - } - pOut = &aMem[pOp->p3]; - if( v1==2 ){ - MemSetTypeFlag(pOut, MEM_Null); - }else{ - pOut->u.i = v1; - MemSetTypeFlag(pOut, MEM_Int); - } - break; -} - -/* Opcode: IsTrue P1 P2 P3 P4 * -** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 -** -** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and -** IS NOT FALSE operators. -** -** Interpret the value in register P1 as a boolean value. Store that -** boolean (a 0 or 1) in register P2. Or if the value in register P1 is -** NULL, then the P3 is stored in register P2. Invert the answer if P4 -** is 1. -** -** The logic is summarized like this: -** -**
      -**
    • If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE -**
    • If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE -**
    • If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE -**
    • If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE -**
    -*/ -case OP_IsTrue: { /* in1, out2 */ - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p4.i==0 || pOp->p4.i==1 ); - assert( pOp->p3==0 || pOp->p3==1 ); - sqlite3VdbeMemSetInt64(&aMem[pOp->p2], - sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); - break; -} - -/* Opcode: Not P1 P2 * * * -** Synopsis: r[P2]= !r[P1] -** -** Interpret the value in register P1 as a boolean value. Store the -** boolean complement in register P2. If the value in register P1 is -** NULL, then a NULL is stored in P2. -*/ -case OP_Not: { /* same as TK_NOT, in1, out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0)); - }else{ - sqlite3VdbeMemSetNull(pOut); - } - break; -} - -/* Opcode: BitNot P1 P2 * * * -** Synopsis: r[P2]= ~r[P1] -** -** Interpret the content of register P1 as an integer. Store the -** ones-complement of the P1 value into register P2. If P1 holds -** a NULL then store a NULL in P2. -*/ -case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); - if( (pIn1->flags & MEM_Null)==0 ){ - pOut->flags = MEM_Int; - pOut->u.i = ~sqlite3VdbeIntValue(pIn1); - } - break; -} - -/* Opcode: Once P1 P2 P3 * * -** -** Fall through to the next instruction the first time this opcode is -** encountered on each invocation of the byte-code program. Jump to P2 -** on the second and all subsequent encounters during the same invocation. -** -** Top-level programs determine first invocation by comparing the P1 -** operand against the P1 operand on the OP_Init opcode at the beginning -** of the program. If the P1 values differ, then fall through and make -** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are -** the same then take the jump. -** -** For subprograms, there is a bitmask in the VdbeFrame that determines -** whether or not the jump should be taken. The bitmask is necessary -** because the self-altering code trick does not work for recursive -** triggers. -** -** The P3 operand is not used directly by this opcode. However P3 is -** used by the code generator as follows: If this opcode is the start -** of a subroutine and that subroutine uses a Bloom filter, then P3 will -** be the register that holds that Bloom filter. See tag-202407032019 -** in the source code for implementation details. -*/ -case OP_Once: { /* jump */ - u32 iAddr; /* Address of this instruction */ - assert( p->aOp[0].opcode==OP_Init ); - if( p->pFrame ){ - iAddr = (int)(pOp - p->aOp); - if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){ - VdbeBranchTaken(1, 2); - goto jump_to_p2; - } - p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7); - }else{ - if( p->aOp[0].p1==pOp->p1 ){ - VdbeBranchTaken(1, 2); - goto jump_to_p2; - } - } - VdbeBranchTaken(0, 2); - pOp->p1 = p->aOp[0].p1; - break; -} - -/* Opcode: If P1 P2 P3 * * -** -** Jump to P2 if the value in register P1 is true. The value -** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if and only if P3 is non-zero. -*/ -case OP_If: { /* jump, in1 */ - int c; - c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3); - VdbeBranchTaken(c!=0, 2); - if( c ) goto jump_to_p2; - break; -} - -/* Opcode: IfNot P1 P2 P3 * * -** -** Jump to P2 if the value in register P1 is False. The value -** is considered false if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if and only if P3 is non-zero. -*/ -case OP_IfNot: { /* jump, in1 */ - int c; - c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3); - VdbeBranchTaken(c!=0, 2); - if( c ) goto jump_to_p2; - break; -} - -/* Opcode: IsNull P1 P2 * * * -** Synopsis: if r[P1]==NULL goto P2 -** -** Jump to P2 if the value in register P1 is NULL. -*/ -case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ - pIn1 = &aMem[pOp->p1]; - VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); - if( (pIn1->flags & MEM_Null)!=0 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: IsType P1 P2 P3 P4 P5 -** Synopsis: if typeof(P1.P3) in P5 goto P2 -** -** Jump to P2 if the type of a column in a btree is one of the types specified -** by the P5 bitmask. -** -** P1 is normally a cursor on a btree for which the row decode cache is -** valid through at least column P3. In other words, there should have been -** a prior OP_Column for column P3 or greater. If the cursor is not valid, -** then this opcode might give spurious results. -** The the btree row has fewer than P3 columns, then use P4 as the -** datatype. -** -** If P1 is -1, then P3 is a register number and the datatype is taken -** from the value in that register. -** -** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant -** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04. -** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10. -** -** WARNING: This opcode does not reliably distinguish between NULL and REAL -** when P1>=0. If the database contains a NaN value, this opcode will think -** that the datatype is REAL when it should be NULL. When P1<0 and the value -** is already stored in register P3, then this opcode does reliably -** distinguish between NULL and REAL. The problem only arises then P1>=0. -** -** Take the jump to address P2 if and only if the datatype of the -** value determined by P1 and P3 corresponds to one of the bits in the -** P5 bitmask. -** -*/ -case OP_IsType: { /* jump */ - VdbeCursor *pC; - u16 typeMask; - u32 serialType; - - assert( pOp->p1>=(-1) && pOp->p1nCursor ); - assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) ); - if( pOp->p1>=0 ){ - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pOp->p3>=0 ); - if( pOp->p3nHdrParsed ){ - serialType = pC->aType[pOp->p3]; - if( serialType>=12 ){ - if( serialType&1 ){ - typeMask = 0x04; /* SQLITE_TEXT */ - }else{ - typeMask = 0x08; /* SQLITE_BLOB */ - } - }else{ - static const unsigned char aMask[] = { - 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2, - 0x01, 0x01, 0x10, 0x10 - }; - testcase( serialType==0 ); - testcase( serialType==1 ); - testcase( serialType==2 ); - testcase( serialType==3 ); - testcase( serialType==4 ); - testcase( serialType==5 ); - testcase( serialType==6 ); - testcase( serialType==7 ); - testcase( serialType==8 ); - testcase( serialType==9 ); - testcase( serialType==10 ); - testcase( serialType==11 ); - typeMask = aMask[serialType]; - } - }else{ - typeMask = 1 << (pOp->p4.i - 1); - testcase( typeMask==0x01 ); - testcase( typeMask==0x02 ); - testcase( typeMask==0x04 ); - testcase( typeMask==0x08 ); - testcase( typeMask==0x10 ); - } - }else{ - assert( memIsValid(&aMem[pOp->p3]) ); - typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1); - testcase( typeMask==0x01 ); - testcase( typeMask==0x02 ); - testcase( typeMask==0x04 ); - testcase( typeMask==0x08 ); - testcase( typeMask==0x10 ); - } - VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2); - if( typeMask & pOp->p5 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: ZeroOrNull P1 P2 P3 * * -** Synopsis: r[P2] = 0 OR NULL -** -** If 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 - ){ - sqlite3VdbeMemSetNull(aMem + pOp->p2); - }else{ - sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0); - } - break; -} - -/* Opcode: NotNull P1 P2 * * * -** Synopsis: if r[P1]!=NULL goto P2 -** -** Jump to P2 if the value in register P1 is not NULL. -*/ -case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ - pIn1 = &aMem[pOp->p1]; - VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); - if( (pIn1->flags & MEM_Null)==0 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: IfNullRow P1 P2 P3 * * -** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2 -** -** Check the cursor P1 to see if it is currently pointing at a NULL row. -** If it is, then set register P3 to NULL and jump immediately to P2. -** If P1 is not on a NULL row, then fall through without making any -** changes. -** -** If P1 is not an open cursor, then this opcode is a no-op. -*/ -case OP_IfNullRow: { /* jump */ - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - if( pC && pC->nullRow ){ - sqlite3VdbeMemSetNull(aMem + pOp->p3); - goto jump_to_p2; - } - break; -} - -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC -/* Opcode: Offset P1 P2 P3 * * -** Synopsis: r[P3] = sqlite_offset(P1) -** -** Store in register r[P3] the byte offset into the database file that is the -** start of the payload for the record at which that cursor P1 is currently -** pointing. -** -** P2 is the column number for the argument to the sqlite_offset() function. -** This opcode does not use P2 itself, but the P2 value is used by the -** code generator. The P1, P2, and P3 operands to this opcode are the -** same as for OP_Column. -** -** This opcode is only available if SQLite is compiled with the -** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. -*/ -case OP_Offset: { /* out3 */ - VdbeCursor *pC; /* The VDBE cursor */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - pOut = &p->aMem[pOp->p3]; - if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ - sqlite3VdbeMemSetNull(pOut); - }else{ - if( pC->deferredMoveto ){ - rc = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - } - if( sqlite3BtreeEof(pC->uc.pCursor) ){ - sqlite3VdbeMemSetNull(pOut); - }else{ - sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); - } - } - break; -} -#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ - -/* Opcode: Column P1 P2 P3 P4 P5 -** 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 -** information about the format of the data.) Extract the P2-th column -** from this record. If there are less than (P2+1) -** values in the record, extract a NULL. -** -** The value extracted is stored in register P3. -** -** If the record contains fewer than P2 fields, then extract a NULL. Or, -** if the P4 argument is a P4_MEM use the value of the P4 argument as -** the result. -** -** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed -** to only be used by the length() function or the equivalent. The content -** of large blobs is not loaded, thus saving CPU cycles. If the -** OPFLAG_TYPEOFARG bit is set then the result will only be used by the -** typeof() function or the IS NULL or IS NOT NULL operators or the -** equivalent. In this case, all content loading can be omitted. -*/ -case OP_Column: { /* ncycle */ - u32 p2; /* column number to retrieve */ - VdbeCursor *pC; /* The VDBE 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 */ - Mem *pDest; /* Where to write the extracted value */ - Mem sMem; /* For storing the record being decoded */ - const u8 *zData; /* Part of the record being decoded */ - const u8 *zHdr; /* Next unparsed byte of the header */ - const u8 *zEndHdr; /* Pointer to first byte after the header */ - u64 offset64; /* 64-bit offset */ - u32 t; /* A type code from the record header */ - Mem *pReg; /* PseudoTable input register */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - pC = p->apCsr[pOp->p1]; - p2 = (u32)pOp->p2; - -op_column_restart: - assert( pC!=0 ); - 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 && pC->seekResult>0 ){ - /* For the special case of as pseudo-cursor, the seekResult field - ** identifies the register that holds the record */ - 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); - 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 = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - }else if( sqlite3BtreeCursorHasMoved(pCrsr) ){ - rc = sqlite3VdbeHandleMovedCursor(pC); - if( rc ) goto abort_due_to_error; - goto op_column_restart; - } - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pCrsr ); - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); - pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow); - assert( pC->szRow<=pC->payloadSize ); - assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */ - } - pC->cacheStatus = p->cacheCtr; - if( (aOffset[0] = pC->aRow[0])<0x80 ){ - pC->iHdrOffset = 1; - }else{ - pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset); - } - pC->nHdrParsed = 0; - - if( pC->szRowaRow does not have to hold the entire row, but it does at least - ** need to cover the header of the record. If pC->aRow does not contain - ** the complete header, then set it to zero, forcing the header to be - ** dynamically allocated. */ - pC->aRow = 0; - pC->szRow = 0; - - /* Make sure a corrupt database has not given us an oversize header. - ** Do this now to avoid an oversize memory allocation. - ** - ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte - ** types use so much data space that there can only be 4096 and 32 of - ** them, respectively. So the maximum header length results from a - ** 3-byte type for each of the maximum of 32768 columns plus three - ** extra bytes for the header length itself. 32768*3 + 3 = 98307. - */ - if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){ - goto op_column_corrupt; - } - }else{ - /* This is an optimization. By skipping over the first few tests - ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a - ** measurable performance gain. - ** - ** This branch is taken even if aOffset[0]==0. Such a record is never - ** generated by SQLite, and could be considered corruption, but we - ** accept it for historical reasons. When aOffset[0]==0, the code this - ** branch jumps to reads past the end of the record, but never more - ** than a few bytes. Even if the record occurs at the end of the page - ** content area, the "page header" comes after the page content and so - ** this overread is harmless. Similar overreads can occur for a corrupt - ** database file. - */ - zData = pC->aRow; - assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ - testcase( aOffset[0]==0 ); - goto op_column_read_header; - } - }else if( sqlite3BtreeCursorHasMoved(pC->uc.pCursor) ){ - rc = 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 - ** parsed and valid information is in aOffset[] and pC->aType[]. - */ - if( pC->nHdrParsed<=p2 ){ - /* If there is more header available for parsing in the record, try - ** to extract additional fields up through the p2+1-th field - */ - if( pC->iHdrOffsetaRow==0 ){ - memset(&sMem, 0, sizeof(sMem)); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pC->uc.pCursor,aOffset[0],&sMem); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - zData = (u8*)sMem.z; - }else{ - zData = pC->aRow; - } - - /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ - op_column_read_header: - i = pC->nHdrParsed; - offset64 = aOffset[i]; - zHdr = zData + pC->iHdrOffset; - zEndHdr = zData + aOffset[0]; - testcase( zHdr>=zEndHdr ); - do{ - if( (pC->aType[i] = t = zHdr[0])<0x80 ){ - zHdr++; - offset64 += sqlite3VdbeOneByteSerialTypeLen(t); - }else{ - zHdr += sqlite3GetVarint32(zHdr, &t); - pC->aType[i] = t; - offset64 += sqlite3VdbeSerialTypeLen(t); - } - aOffset[++i] = (u32)(offset64 & 0xffffffff); - }while( (u32)i<=p2 && zHdr=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) - || (offset64 > pC->payloadSize) - ){ - if( aOffset[0]==0 ){ - i = 0; - zHdr = zEndHdr; - }else{ - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); - goto op_column_corrupt; - } - } - - pC->nHdrParsed = i; - pC->iHdrOffset = (u32)(zHdr - zData); - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); - }else{ - t = 0; - } - - /* If after trying to extract new entries from the header, nHdrParsed is - ** still not up to p2, that means that the record has fewer than p2 - ** columns. So the result will be either the default value or a NULL. - */ - if( pC->nHdrParsed<=p2 ){ - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); - if( pOp->p4type==P4_MEM ){ - sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); - }else{ - sqlite3VdbeMemSetNull(pDest); - } - goto op_column_out; - } - }else{ - t = pC->aType[p2]; - } - - /* Extract the content for the p2+1-th column. Control can only - ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are - ** all valid. - */ - assert( p2nHdrParsed ); - assert( rc==SQLITE_OK ); - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); - assert( sqlite3VdbeCheckMemInvariants(pDest) ); - if( VdbeMemDynamic(pDest) ){ - sqlite3VdbeMemSetNull(pDest); - } - assert( t==pC->aType[p2] ); - if( pC->szRow>=aOffset[p2+1] ){ - /* This is the common case where the desired content fits on the original - ** page - where the content is not on an overflow page */ - zData = pC->aRow + aOffset[p2]; - if( t<12 ){ - sqlite3VdbeSerialGet(zData, t, pDest); - }else{ - /* If the column value is a string, we need a persistent value, not - ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent - ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize(). - */ - static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term }; - 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( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem; - }else{ - pDest->z = pDest->zMalloc; - } - memcpy(pDest->z, zData, len); - pDest->z[len] = 0; - pDest->z[len+1] = 0; - pDest->flags = aFlag[t&1]; - } - }else{ - u8 p5; - pDest->enc = encoding; - assert( pDest->db==db ); - /* This branch happens only when content is on overflow pages */ - if( ((p5 = (pOp->p5 & OPFLAG_BYTELENARG))!=0 - && (p5==OPFLAG_TYPEOFARG - || (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG)) - ) - ) - || sqlite3VdbeSerialTypeLen(t)==0 - ){ - /* Content is irrelevant for - ** 1. the typeof() function, - ** 2. the length(X) function if X is a blob, and - ** 3. if the content length is zero. - ** So we might as well use bogus content rather than reading - ** content from disk. - ** - ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the - ** buffer passed to it, debugging function VdbeMemPrettyPrint() may - ** read more. Use the global constant sqlite3CtypeMap[] as the array, - ** as that array is 256 bytes long (plenty for VdbeMemPrettyPrint()) - ** and it begins with a bunch of zeros. - */ - sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); - }else{ - rc = vdbeColumnFromOverflow(pC, p2, t, aOffset[p2], - p->cacheCtr, colCacheCtr, pDest); - if( rc ){ - if( rc==SQLITE_NOMEM ) goto no_mem; - if( rc==SQLITE_TOOBIG ) goto too_big; - goto abort_due_to_error; - } - } - } - -op_column_out: - UPDATE_MAX_BLOBSIZE(pDest); - REGISTER_TRACE(pOp->p3, pDest); - break; - -op_column_corrupt: - if( aOp[0].p3>0 ){ - pOp = &aOp[aOp[0].p3-1]; - break; - }else{ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } -} - -/* 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: -** -**
      -**
    • P2 should be the number of non-virtual columns in the -** table of P4. -**
    • Table P4 should be a STRICT table. -**
    -** -** 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; inCol; 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 ); - assert( (pIn1->flags & MEM_IntReal)==0 ); - 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: - sqlite3VdbeError(p, "cannot store %s value in %s column %s.%s", - vdbeMemTypeName(pIn1), 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]) -** -** Apply affinities to a range of P2 registers starting with P1. -** -** P4 is a string that is P2 characters long. The N-th character of the -** string indicates the column affinity that should be used for the N-th -** memory cell in the range. -*/ -case OP_Affinity: { - const char *zAffinity; /* The affinity to be applied */ - - zAffinity = pOp->p4.z; - assert( zAffinity!=0 ); - assert( pOp->p2>0 ); - assert( zAffinity[pOp->p2]==0 ); - pIn1 = &aMem[pOp->p1]; - while( 1 /*exit-by-break*/ ){ - assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] ); - assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) ); - applyAffinity(pIn1, zAffinity[0], encoding); - if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){ - /* 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|MEM_Str); - } - } - REGISTER_TRACE((int)(pIn1-aMem), pIn1); - zAffinity++; - if( zAffinity[0]==0 ) break; - pIn1++; - } - break; -} - -/* Opcode: MakeRecord P1 P2 P3 P4 * -** Synopsis: r[P3]=mkrec(r[P1@P2]) -** -** Convert P2 registers beginning with P1 into the [record format] -** use as a data record in a database table or as a key -** in an index. The OP_Column opcode can decode the record later. -** -** P4 may be a string that is P2 characters long. The N-th character of the -** string indicates the column affinity that should be used for the N-th -** field of the index key. -** -** The mapping from character to affinity is given by the SQLITE_AFF_ -** macros defined in sqliteInt.h. -** -** If P4 is NULL then all index fields have the affinity BLOB. -** -** The meaning of P5 depends on whether or not the SQLITE_ENABLE_NULL_TRIM -** compile-time option is enabled: -** -** * If SQLITE_ENABLE_NULL_TRIM is enabled, then the P5 is the index -** of the right-most table that can be null-trimmed. -** -** * If SQLITE_ENABLE_NULL_TRIM is omitted, then P5 has the value -** OPFLAG_NOCHNG_MAGIC if the OP_MakeRecord opcode is allowed to -** accept no-change records with serial_type 10. This value is -** only used inside an assert() and does not affect the end result. -*/ -case OP_MakeRecord: { - Mem *pRec; /* The new record */ - u64 nData; /* Number of bytes of data space */ - int nHdr; /* Number of bytes of header space */ - i64 nByte; /* Data space required for this record */ - i64 nZero; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - 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 */ - - /* Assuming the record contains N fields, the record format looks - ** like this: - ** - ** ------------------------------------------------------------------------ - ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | - ** ------------------------------------------------------------------------ - ** - ** Data(0) is taken from register P1. Data(1) comes from register P1+1 - ** and so forth. - ** - ** Each type field is a varint representing the serial type of the - ** corresponding data element (see sqlite3VdbeSerialType()). The - ** hdr-size field is also a varint which is the offset from the beginning - ** of the record to data0. - */ - nData = 0; /* Number of bytes of data space */ - nHdr = 0; /* Number of bytes of header space */ - nZero = 0; /* Number of zero bytes at the end of the record */ - nField = pOp->p1; - zAffinity = pOp->p4.z; - assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1 ); - pData0 = &aMem[nField]; - nField = pOp->p2; - pLast = &pData0[nField-1]; - - /* Identify the output register */ - assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); - pOut = &aMem[pOp->p3]; - memAboutToChange(p, pOut); - - /* Apply the requested affinity to all inputs - */ - assert( pData0<=pLast ); - if( zAffinity ){ - pRec = pData0; - do{ - applyAffinity(pRec, zAffinity[0], encoding); - if( zAffinity[0]==SQLITE_AFF_REAL && (pRec->flags & MEM_Int) ){ - pRec->flags |= MEM_IntReal; - pRec->flags &= ~(MEM_Int); - } - REGISTER_TRACE((int)(pRec-aMem), pRec); - zAffinity++; - pRec++; - assert( zAffinity[0]==0 || pRec<=pLast ); - }while( zAffinity[0] ); - } - -#ifdef SQLITE_ENABLE_NULL_TRIM - /* NULLs can be safely trimmed from the end of the record, as long as - ** as the schema format is 2 or more and none of the omitted columns - ** have a non-NULL default value. Also, the record must be left with - ** at least one field. If P5>0 then it will be one more than the - ** index of the right-most column with a non-NULL default value */ - if( pOp->p5 ){ - while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){ - pLast--; - nField--; - } - } -#endif - - /* Loop through the elements that will make up the record to figure - ** out how much space is required for the new record. After this loop, - ** the Mem.uTemp field of each term should hold the serial-type that will - ** be used for that term in the generated record: - ** - ** Mem.uTemp value type - ** --------------- --------------- - ** 0 NULL - ** 1 1-byte signed integer - ** 2 2-byte signed integer - ** 3 3-byte signed integer - ** 4 4-byte signed integer - ** 5 6-byte signed integer - ** 6 8-byte signed integer - ** 7 IEEE float - ** 8 Integer constant 0 - ** 9 Integer constant 1 - ** 10,11 reserved for expansion - ** N>=12 and even BLOB - ** N>=13 and odd text - ** - ** The following additional values are computed: - ** nHdr Number of bytes needed for the record header - ** nData Number of bytes of data space needed for the record - ** nZero Zero bytes at the end of the record - */ - pRec = pLast; - do{ - assert( memIsValid(pRec) ); - if( pRec->flags & MEM_Null ){ - if( pRec->flags & MEM_Zero ){ - /* Values with MEM_Null and MEM_Zero are created by xColumn virtual - ** table methods that never invoke sqlite3_result_xxxxx() while - ** computing an unchanging column value in an UPDATE statement. - ** Give such values a special internal-use-only serial-type of 10 - ** so that they can be passed through to xUpdate and have - ** a true sqlite3_value_nochange(). */ -#ifndef SQLITE_ENABLE_NULL_TRIM - assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); -#endif - pRec->uTemp = 10; - }else{ - pRec->uTemp = 0; - } - nHdr++; - }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){ - /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ - i64 i = pRec->u.i; - u64 uu; - testcase( pRec->flags & MEM_Int ); - testcase( pRec->flags & MEM_IntReal ); - if( i<0 ){ - uu = ~i; - }else{ - uu = i; - } - nHdr++; - testcase( uu==127 ); testcase( uu==128 ); - testcase( uu==32767 ); testcase( uu==32768 ); - testcase( uu==8388607 ); testcase( uu==8388608 ); - testcase( uu==2147483647 ); testcase( uu==2147483648LL ); - testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL ); - if( uu<=127 ){ - if( (i&1)==i && p->minWriteFileFormat>=4 ){ - pRec->uTemp = 8+(u32)uu; - }else{ - nData++; - pRec->uTemp = 1; - } - }else if( uu<=32767 ){ - nData += 2; - pRec->uTemp = 2; - }else if( uu<=8388607 ){ - nData += 3; - pRec->uTemp = 3; - }else if( uu<=2147483647 ){ - nData += 4; - pRec->uTemp = 4; - }else if( uu<=140737488355327LL ){ - nData += 6; - pRec->uTemp = 5; - }else{ - nData += 8; - if( pRec->flags & MEM_IntReal ){ - /* If the value is IntReal and is going to take up 8 bytes to store - ** as an integer, then we might as well make it an 8-byte floating - ** point value */ - pRec->u.r = (double)pRec->u.i; - pRec->flags &= ~MEM_IntReal; - pRec->flags |= MEM_Real; - pRec->uTemp = 7; - }else{ - pRec->uTemp = 6; - } - } - }else if( pRec->flags & MEM_Real ){ - nHdr++; - nData += 8; - pRec->uTemp = 7; - }else{ - assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) ); - assert( pRec->n>=0 ); - len = (u32)pRec->n; - serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0); - if( pRec->flags & MEM_Zero ){ - serial_type += pRec->u.nZero*2; - if( nData ){ - if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; - len += pRec->u.nZero; - }else{ - nZero += pRec->u.nZero; - } - } - nData += len; - nHdr += sqlite3VarintLen(serial_type); - pRec->uTemp = serial_type; - } - if( pRec==pData0 ) break; - pRec--; - }while(1); - - /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint - ** which determines the total number of bytes in the header. The varint - ** value is the size of the header in bytes including the size varint - ** itself. */ - testcase( nHdr==126 ); - testcase( nHdr==127 ); - if( nHdr<=126 ){ - /* The common case */ - nHdr += 1; - }else{ - /* Rare case of a really large header */ - nVarint = sqlite3VarintLen(nHdr); - nHdr += nVarint; - if( nVarintp3) is not allowed to - ** be one of the input registers (because the following call to - ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). - */ - if( nByte+nZero<=pOut->szMalloc ){ - /* The output register is already large enough to hold the record. - ** No error checks or buffer enlargement is required */ - pOut->z = pOut->zMalloc; - }else{ - /* Need to make sure that the output is not too big and then enlarge - ** the output register to hold the full result */ - if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ - goto no_mem; - } - } - pOut->n = (int)nByte; - pOut->flags = MEM_Blob; - if( nZero ){ - pOut->u.nZero = nZero; - pOut->flags |= MEM_Zero; - } - UPDATE_MAX_BLOBSIZE(pOut); - zHdr = (u8 *)pOut->z; - zPayload = zHdr + nHdr; - - /* Write the record */ - if( nHdr<0x80 ){ - *(zHdr++) = nHdr; - }else{ - zHdr += sqlite3PutVarint(zHdr,nHdr); - } - assert( pData0<=pLast ); - pRec = pData0; - 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. - ** EVIDENCE-OF: R-64536-51728 The values for each column in the record - ** immediately follow the header. */ - if( serial_type<=7 ){ - *(zHdr++) = serial_type; - if( serial_type==0 ){ - /* NULL value. No change in zPayload */ - }else{ - u64 v; - 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 = sqlite3SmallTypeSizes[serial_type]; - assert( len>=1 && len<=8 && len!=5 && len!=7 ); - switch( len ){ - default: zPayload[7] = (u8)(v&0xff); v >>= 8; - zPayload[6] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 6: zPayload[5] = (u8)(v&0xff); v >>= 8; - zPayload[4] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 4: zPayload[3] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 3: zPayload[2] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 2: zPayload[1] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 1: zPayload[0] = (u8)(v&0xff); - } - 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 += sqlite3PutVarint(zHdr, serial_type); - if( pRec->n ){ - assert( pRec->z!=0 ); - assert( pRec->z!=(const char*)sqlite3CtypeMap ); - 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) ); - - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - REGISTER_TRACE(pOp->p3, pOut); - break; -} - -/* Opcode: Count P1 P2 P3 * * -** Synopsis: r[P2]=count() -** -** Store the number of entries (an integer value) in the table or index -** opened by cursor P1 in register P2. -** -** If P3==0, then an exact count is obtained, which involves visiting -** every btree page of the table. But if P3 is non-zero, an estimate -** is returned based on the current cursor position. -*/ -case OP_Count: { /* out2 */ - i64 nEntry; - BtCursor *pCrsr; - - assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE ); - pCrsr = p->apCsr[pOp->p1]->uc.pCursor; - assert( pCrsr ); - if( pOp->p3 ){ - nEntry = sqlite3BtreeRowCountEst(pCrsr); - }else{ - nEntry = 0; /* Not needed. Only used to silence a warning. */ - rc = sqlite3BtreeCount(db, pCrsr, &nEntry); - if( rc ) goto abort_due_to_error; - } - pOut = out2Prerelease(p, pOp); - pOut->u.i = nEntry; - goto check_for_interrupt; -} - -/* Opcode: Savepoint P1 * * P4 * -** -** Open, release or rollback the savepoint named by parameter P4, depending -** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN). -** To release (commit) an existing savepoint set P1==1 (SAVEPOINT_RELEASE). -** To rollback an existing savepoint set P1==2 (SAVEPOINT_ROLLBACK). -*/ -case OP_Savepoint: { - int p1; /* Value of P1 operand */ - char *zName; /* Name of savepoint */ - int nName; - Savepoint *pNew; - Savepoint *pSavepoint; - Savepoint *pTmp; - int iSavepoint; - int ii; - - p1 = pOp->p1; - zName = pOp->p4.z; - - /* Assert that the p1 parameter is valid. Also that if there is no open - ** transaction, then there cannot be any savepoints. - */ - assert( db->pSavepoint==0 || db->autoCommit==0 ); - assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); - assert( db->pSavepoint || db->isTransactionSavepoint==0 ); - assert( checkSavepointCount(db) ); - assert( p->bIsReader ); - - if( p1==SAVEPOINT_BEGIN ){ - if( db->nVdbeWrite>0 ){ - /* A new savepoint cannot be created if there are active write - ** statements (i.e. open read/write incremental blob handles). - */ - sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress"); - rc = SQLITE_BUSY; - }else{ - nName = sqlite3Strlen30(zName); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* This call is Ok even if this savepoint is actually a transaction - ** savepoint (and therefore should not prompt xSavepoint()) callbacks. - ** If this is a transaction savepoint being opened, it is guaranteed - ** that the db->aVTrans[] array is empty. */ - assert( db->autoCommit==0 || db->nVTrans==0 ); - rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, - db->nStatement+db->nSavepoint); - if( rc!=SQLITE_OK ) goto abort_due_to_error; -#endif - - /* Create a new savepoint structure. */ - pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); - if( pNew ){ - pNew->zName = (char *)&pNew[1]; - memcpy(pNew->zName, zName, nName+1); - - /* If there is no open transaction, then mark this as a special - ** "transaction savepoint". */ - if( db->autoCommit ){ - db->autoCommit = 0; - db->isTransactionSavepoint = 1; - }else{ - db->nSavepoint++; - } - - /* Link the new savepoint into the database handle's list. */ - pNew->pNext = db->pSavepoint; - db->pSavepoint = pNew; - pNew->nDeferredCons = db->nDeferredCons; - pNew->nDeferredImmCons = db->nDeferredImmCons; - } - } - }else{ - assert( p1==SAVEPOINT_RELEASE || p1==SAVEPOINT_ROLLBACK ); - iSavepoint = 0; - - /* Find the named savepoint. If there is no such savepoint, then an - ** an error is returned to the user. */ - for( - pSavepoint = db->pSavepoint; - pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); - pSavepoint = pSavepoint->pNext - ){ - iSavepoint++; - } - if( !pSavepoint ){ - sqlite3VdbeError(p, "no such savepoint: %s", zName); - rc = SQLITE_ERROR; - }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ - /* It is not possible to release (commit) a savepoint if there are - ** active write statements. - */ - sqlite3VdbeError(p, "cannot release savepoint - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - }else{ - - /* Determine whether or not this is a transaction savepoint. If so, - ** and this is a RELEASE command, then the current transaction - ** is committed. - */ - int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; - if( isTransaction && p1==SAVEPOINT_RELEASE ){ - if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ - goto vdbe_return; - } - db->autoCommit = 1; - if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - db->autoCommit = 0; - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - rc = p->rc; - if( rc ){ - db->autoCommit = 0; - }else{ - db->isTransactionSavepoint = 0; - } - }else{ - int isSchemaChange; - iSavepoint = db->nSavepoint - iSavepoint - 1; - if( p1==SAVEPOINT_ROLLBACK ){ - isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0; - for(ii=0; iinDb; ii++){ - rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, - SQLITE_ABORT_ROLLBACK, - isSchemaChange==0); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - }else{ - assert( p1==SAVEPOINT_RELEASE ); - isSchemaChange = 0; - } - for(ii=0; iinDb; ii++){ - rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - } - if( isSchemaChange ){ - sqlite3ExpirePreparedStatements(db, 0); - sqlite3ResetAllSchemasOfConnection(db); - db->mDbFlags |= DBFLAG_SchemaChange; - } - } - if( rc ) goto abort_due_to_error; - - /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all - ** savepoints nested inside of the savepoint being operated on. */ - while( db->pSavepoint!=pSavepoint ){ - pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; - sqlite3DbFree(db, pTmp); - db->nSavepoint--; - } - - /* If it is a RELEASE, then destroy the savepoint being operated on - ** too. If it is a ROLLBACK TO, then set the number of deferred - ** constraint violations present in the database to the value stored - ** when the savepoint was created. */ - if( p1==SAVEPOINT_RELEASE ){ - assert( pSavepoint==db->pSavepoint ); - db->pSavepoint = pSavepoint->pNext; - sqlite3DbFree(db, pSavepoint); - if( !isTransaction ){ - db->nSavepoint--; - } - }else{ - assert( p1==SAVEPOINT_ROLLBACK ); - db->nDeferredCons = pSavepoint->nDeferredCons; - db->nDeferredImmCons = pSavepoint->nDeferredImmCons; - } - - if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ - rc = sqlite3VtabSavepoint(db, p1, iSavepoint); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - } - } - if( rc ) goto abort_due_to_error; - if( p->eVdbeState==VDBE_HALT_STATE ){ - rc = SQLITE_DONE; - goto vdbe_return; - } - break; -} - -/* Opcode: AutoCommit P1 P2 * * * -** -** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll -** back any currently active btree transactions. If there are any active -** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if -** there are active writing VMs or active VMs that use shared cache. -** -** This instruction causes the VM to halt. -*/ -case OP_AutoCommit: { - int desiredAutoCommit; - int iRollback; - - desiredAutoCommit = pOp->p1; - iRollback = pOp->p2; - assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); - assert( desiredAutoCommit==1 || iRollback==0 ); - assert( db->nVdbeActive>0 ); /* At least this one VM is active */ - assert( p->bIsReader ); - - if( desiredAutoCommit!=db->autoCommit ){ - if( iRollback ){ - assert( desiredAutoCommit==1 ); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - db->autoCommit = 1; - }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ - /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. - */ - sqlite3VdbeError(p, "cannot commit transaction - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - goto abort_due_to_error; - }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ - goto vdbe_return; - }else{ - db->autoCommit = (u8)desiredAutoCommit; - } - if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - db->autoCommit = (u8)(1-desiredAutoCommit); - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - sqlite3CloseSavepoints(db); - if( p->rc==SQLITE_OK ){ - rc = SQLITE_DONE; - }else{ - rc = SQLITE_ERROR; - } - goto vdbe_return; - }else{ - sqlite3VdbeError(p, - (!desiredAutoCommit)?"cannot start a transaction within a transaction":( - (iRollback)?"cannot rollback - no transaction is active": - "cannot commit - no transaction is active")); - - rc = SQLITE_ERROR; - goto abort_due_to_error; - } - /*NOTREACHED*/ assert(0); -} - -/* Opcode: Transaction P1 P2 P3 P4 P5 -** -** Begin a transaction on database P1 if a transaction is not already -** active. -** If P2 is non-zero, then a write-transaction is started, or if a -** read-transaction is already active, it is upgraded to a write-transaction. -** If P2 is zero, then a read-transaction is started. If P2 is 2 or more -** then an exclusive transaction is started. -** -** P1 is the index of the database file on which the transaction is -** started. Index 0 is the main database file and index 1 is the -** file used for temporary tables. Indices of 2 or more are used for -** attached databases. -** -** If a write-transaction is started and the Vdbe.usesStmtJournal flag is -** true (this flag is set if the Vdbe may modify more than one row and may -** throw an ABORT exception), a statement transaction may also be opened. -** More specifically, a statement transaction is opened iff the database -** connection is currently not in autocommit mode, or if there are other -** active statements. A statement transaction allows the changes made by this -** VDBE to be rolled back after an error without having to roll back the -** entire transaction. If no error is encountered, the statement transaction -** will automatically commit when the VDBE halts. -** -** If P5!=0 then this opcode also checks the schema cookie against P3 -** and the schema generation counter against P4. -** The cookie changes its value whenever the database schema changes. -** This operation is used to detect when that the cookie has changed -** and that the current process needs to reread the schema. If the schema -** cookie in P3 differs from the schema cookie in the database header or -** if the schema generation counter in P4 differs from the current -** generation counter, then an SQLITE_SCHEMA error is raised and execution -** halts. The sqlite3_step() wrapper function might then reprepare the -** statement and rerun it from the beginning. -*/ -case OP_Transaction: { - Btree *pBt; - Db *pDb; - int iMeta = 0; - - assert( p->bIsReader ); - assert( p->readOnly==0 || pOp->p2==0 ); - assert( pOp->p2>=0 && pOp->p2<=2 ); - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); - 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; - } - pDb = &db->aDb[pOp->p1]; - pBt = pDb->pBt; - - if( pBt ){ - rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta); - testcase( rc==SQLITE_BUSY_SNAPSHOT ); - testcase( rc==SQLITE_BUSY_RECOVERY ); - if( rc!=SQLITE_OK ){ - if( (rc&0xff)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - p->rc = rc; - goto vdbe_return; - } - goto abort_due_to_error; - } - - if( p->usesStmtJournal - && pOp->p2 - && (db->autoCommit==0 || db->nVdbeRead>1) - ){ - assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ); - if( p->iStatement==0 ){ - assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; - p->iStatement = db->nSavepoint + db->nStatement; - } - - rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); - } - - /* Store the current value of the database handles deferred constraint - ** counter. If the statement transaction needs to be rolled back, - ** the value of this counter needs to be restored too. */ - p->nStmtDefCons = db->nDeferredCons; - p->nStmtDefImmCons = db->nDeferredImmCons; - } - } - assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); - 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 - ** version is checked to ensure that the schema has not changed since the - ** SQL statement was prepared. - */ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie - ** stored with the in-memory representation of the schema, do - ** not reload the schema from the database file. - ** - ** If virtual-tables are in use, this is not just an optimization. - ** Often, v-tables store their data in other SQLite tables, which - ** are queried from within xNext() and other v-table methods using - ** prepared queries. If such a query is out-of-date, we do not want to - ** discard the database schema, as the user code implementing the - ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within - ** a v-table method. - */ - if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ - sqlite3ResetOneSchema(db, pOp->p1); - } - p->expired = 1; - rc = SQLITE_SCHEMA; - - /* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes() - ** from being modified in sqlite3VdbeHalt(). If this statement is - ** reprepared, changeCntOn will be set again. */ - p->changeCntOn = 0; - } - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: ReadCookie P1 P2 P3 * * -** -** Read cookie number P3 from database P1 and write it into register P2. -** P3==1 is the schema version. P3==2 is the database format. -** P3==3 is the recommended pager cache size, and so forth. P1==0 is -** the main database file and P1==1 is the database file used to store -** temporary tables. -** -** There must be a read-lock on the database (either a transaction -** must be started or there must be an open cursor) before -** executing this instruction. -*/ -case OP_ReadCookie: { /* out2 */ - int iMeta; - int iDb; - int iCookie; - - assert( p->bIsReader ); - iDb = pOp->p1; - iCookie = pOp->p3; - assert( pOp->p3=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 ); - assert( DbMaskTest(p->btreeMask, iDb) ); - - sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); - pOut = out2Prerelease(p, pOp); - pOut->u.i = iMeta; - break; -} - -/* Opcode: SetCookie P1 P2 P3 * P5 -** -** Write the integer value P3 into cookie number P2 of database P1. -** P2==1 is the schema version. P2==2 is the database format. -** P2==3 is the recommended pager cache -** size, and so forth. P1==0 is the main database file and P1==1 is the -** database file used to store temporary tables. -** -** A transaction must be started before executing this opcode. -** -** If P2 is the SCHEMA_VERSION cookie (cookie number 1) then the internal -** schema version is set to P3-P5. The "PRAGMA schema_version=N" statement -** has P5 set to 1, so that the internal schema version will be different -** from the database schema version, resulting in a schema reset. -*/ -case OP_SetCookie: { - Db *pDb; - - sqlite3VdbeIncrWriteCounter(p, 0); - assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); - assert( p->readOnly==0 ); - pDb = &db->aDb[pOp->p1]; - assert( pDb->pBt!=0 ); - assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); - if( pOp->p2==BTREE_SCHEMA_VERSION ){ - /* When the schema cookie changes, record the new cookie internally */ - *(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5; - db->mDbFlags |= DBFLAG_SchemaChange; - sqlite3FkClearTriggerCache(db, pOp->p1); - }else if( pOp->p2==BTREE_FILE_FORMAT ){ - /* Record changes in the file format */ - pDb->pSchema->file_format = pOp->p3; - } - if( pOp->p1==1 ){ - /* Invalidate all prepared statements whenever the TEMP database - ** schema is changed. Ticket #1644 */ - sqlite3ExpirePreparedStatements(db, 0); - p->expired = 0; - } - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: OpenRead P1 P2 P3 P4 P5 -** Synopsis: root=P2 iDb=P3 -** -** Open a read-only cursor for the database table whose root page is -** P2 in a database file. The database file is determined by P3. -** P3==0 means the main database, P3==1 means the database used for -** temporary tables, and P3>1 means used the corresponding attached -** database. Give the new cursor an identifier of P1. The P1 -** values need not be contiguous but all P1 values should be small integers. -** It is an error for P1 to be negative. -** -** Allowed P5 bits: -**
      -**
    • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
    -** -** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** object, then table being opened must be an [index b-tree] where the -** KeyInfo object defines the content and collating -** sequence of that index b-tree. Otherwise, if P4 is an integer -** value, then the table being opened must be a [table b-tree] with a -** number of columns no less than the value of P4. -** -** See also: OpenWrite, ReopenIdx -*/ -/* Opcode: ReopenIdx P1 P2 P3 P4 P5 -** Synopsis: root=P2 iDb=P3 -** -** The ReopenIdx opcode works like OP_OpenRead except that it first -** checks to see if the cursor on P1 is already open on the same -** b-tree and if it is this opcode becomes a no-op. In other words, -** if the cursor is already open, do not reopen it. -** -** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ -** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must -** be the same as every other ReopenIdx or OpenRead for the same cursor -** number. -** -** Allowed P5 bits: -**
      -**
    • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
    -** -** See also: OP_OpenRead, OP_OpenWrite -*/ -/* Opcode: OpenWrite P1 P2 P3 P4 P5 -** Synopsis: root=P2 iDb=P3 -** -** Open a read/write cursor named P1 on the table or index whose root -** page is P2 (or whose root page is held in register P2 if the -** OPFLAG_P2ISREG bit is set in P5 - see below). -** -** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** object, then table being opened must be an [index b-tree] where the -** KeyInfo object defines the content and collating -** sequence of that index b-tree. Otherwise, if P4 is an integer -** value, then the table being opened must be a [table b-tree] with a -** number of columns no less than the value of P4. -** -** Allowed P5 bits: -**
      -**
    • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
    • 0x08 OPFLAG_FORDELETE: This cursor is used only to seek -** and subsequently delete entries in an index btree. This is a -** hint to the storage engine that the storage engine is allowed to -** ignore. The hint is not used by the official SQLite b*tree storage -** engine, but is used by COMDB2. -**
    • 0x10 OPFLAG_P2ISREG: Use the content of register P2 -** as the root page, not the value of P2 itself. -**
    -** -** This instruction works like OpenRead except that it opens the cursor -** in read/write mode. -** -** See also: OP_OpenRead, OP_ReopenIdx -*/ -case OP_ReopenIdx: { /* ncycle */ - int nField; - KeyInfo *pKeyInfo; - u32 p2; - int iDb; - int wrFlag; - Btree *pX; - VdbeCursor *pCur; - Db *pDb; - - assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); - assert( pOp->p4type==P4_KEYINFO ); - pCur = p->apCsr[pOp->p1]; - if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ - assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ - assert( pCur->eCurType==CURTYPE_BTREE ); - sqlite3BtreeClearCursor(pCur->uc.pCursor); - goto open_cursor_set_hints; - } - /* If the cursor is not currently open or is open on a different - ** index, then fall through into OP_OpenRead to force a reopen */ -case OP_OpenRead: /* ncycle */ -case OP_OpenWrite: - - assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); - assert( p->bIsReader ); - assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx - || p->readOnly==0 ); - - if( p->expired==1 ){ - rc = SQLITE_ABORT_ROLLBACK; - goto abort_due_to_error; - } - - nField = 0; - pKeyInfo = 0; - p2 = (u32)pOp->p2; - iDb = pOp->p3; - assert( iDb>=0 && iDbnDb ); - assert( DbMaskTest(p->btreeMask, iDb) ); - pDb = &db->aDb[iDb]; - pX = pDb->pBt; - assert( pX!=0 ); - if( pOp->opcode==OP_OpenWrite ){ - assert( OPFLAG_FORDELETE==BTREE_FORDELETE ); - wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( pDb->pSchema->file_format < p->minWriteFileFormat ){ - p->minWriteFileFormat = pDb->pSchema->file_format; - } - if( pOp->p5 & OPFLAG_P2ISREG ){ - assert( p2>0 ); - assert( p2<=(u32)(p->nMem+1 - p->nCursor) ); - pIn2 = &aMem[p2]; - assert( memIsValid(pIn2) ); - assert( (pIn2->flags & MEM_Int)!=0 ); - sqlite3VdbeMemIntegerify(pIn2); - p2 = (int)pIn2->u.i; - /* The p2 value always comes from a prior OP_CreateBtree opcode and - ** that opcode will always set the p2 value to 2 or more or else fail. - ** If there were a failure, the prepared statement would have halted - ** before reaching this instruction. */ - assert( p2>=2 ); - } - }else{ - wrFlag = 0; - assert( (pOp->p5 & OPFLAG_P2ISREG)==0 ); - } - if( pOp->p4type==P4_KEYINFO ){ - pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->enc==ENC(db) ); - assert( pKeyInfo->db==db ); - nField = pKeyInfo->nAllField; - }else if( pOp->p4type==P4_INT32 ){ - nField = pOp->p4.i; - } - assert( pOp->p1>=0 ); - assert( nField>=0 ); - testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - 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; -#ifdef SQLITE_DEBUG - pCur->wrFlag = wrFlag; -#endif - rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); - pCur->pKeyInfo = pKeyInfo; - /* Set the VdbeCursor.isTable variable. Previous versions of - ** SQLite used to check if the root-page flags were sane at this point - ** and report database corruption if they were not, but this check has - ** since moved into the btree layer. */ - pCur->isTable = pOp->p4type!=P4_KEYINFO; - -open_cursor_set_hints: - assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); - testcase( pOp->p5 & OPFLAG_BULKCSR ); - testcase( pOp->p2 & OPFLAG_SEEKEQ ); - sqlite3BtreeCursorHintFlags(pCur->uc.pCursor, - (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: OpenDup P1 P2 * * * -** -** Open a new cursor P1 that points to the same ephemeral table as -** cursor P2. The P2 cursor must have been opened by a prior OP_OpenEphemeral -** opcode. Only ephemeral cursors may be duplicated. -** -** Duplicate ephemeral cursors are used for self-joins of materialized views. -*/ -case OP_OpenDup: { /* ncycle */ - VdbeCursor *pOrig; /* The original cursor to be duplicated */ - VdbeCursor *pCx; /* The new cursor */ - - pOrig = p->apCsr[pOp->p2]; - assert( pOrig ); - assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */ - - pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE); - if( pCx==0 ) goto no_mem; - pCx->nullRow = 1; - pCx->isEphemeral = 1; - pCx->pKeyInfo = pOrig->pKeyInfo; - pCx->isTable = pOrig->isTable; - pCx->pgnoRoot = pOrig->pgnoRoot; - pCx->isOrdered = pOrig->isOrdered; - pCx->ub.pBtx = pOrig->ub.pBtx; - pCx->noReuse = 1; - pOrig->noReuse = 1; - rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, - pCx->pKeyInfo, pCx->uc.pCursor); - /* The sqlite3BtreeCursor() routine can only fail for the first cursor - ** opened for a database. Since there is already an open cursor when this - ** opcode is run, the sqlite3BtreeCursor() cannot fail */ - assert( rc==SQLITE_OK ); - break; -} - - -/* Opcode: OpenEphemeral P1 P2 P3 P4 P5 -** Synopsis: nColumn=P2 -** -** Open a new cursor P1 to a transient table. -** The cursor is always opened read/write even if -** the main database is read-only. The ephemeral -** table is deleted automatically when the cursor is closed. -** -** If the cursor P1 is already opened on an ephemeral table, the table -** is cleared (all content is erased). -** -** P2 is the number of columns in the ephemeral table. -** The cursor points to a BTree table if P4==0 and to a BTree index -** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure -** that defines the format of keys in the index. -** -** The P5 parameter can be a mask of the BTREE_* flags defined -** in btree.h. These flags control aspects of the operation of -** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are -** added automatically. -** -** If P3 is positive, then reg[P3] is modified slightly so that it -** can be used as zero-length data for OP_Insert. This is an optimization -** that avoids an extra OP_Blob opcode to initialize that register. -*/ -/* Opcode: OpenAutoindex P1 P2 * P4 * -** Synopsis: nColumn=P2 -** -** This opcode works the same as OP_OpenEphemeral. It has a -** different name to distinguish its use. Tables created using -** by this opcode will be used for automatically created transient -** indices in joins. -*/ -case OP_OpenAutoindex: /* ncycle */ -case OP_OpenEphemeral: { /* ncycle */ - VdbeCursor *pCx; - KeyInfo *pKeyInfo; - - static const int vfsFlags = - SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | - SQLITE_OPEN_DELETEONCLOSE | - SQLITE_OPEN_TRANSIENT_DB; - assert( pOp->p1>=0 ); - assert( pOp->p2>=0 ); - if( pOp->p3>0 ){ - /* Make register reg[P3] into a value that can be used as the data - ** form sqlite3BtreeInsert() where the length of the data is zero. */ - assert( pOp->p2==0 ); /* Only used when number of columns is zero */ - assert( pOp->opcode==OP_OpenEphemeral ); - assert( aMem[pOp->p3].flags & MEM_Null ); - aMem[pOp->p3].n = 0; - aMem[pOp->p3].z = ""; - } - pCx = p->apCsr[pOp->p1]; - if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ - /* If the ephemeral 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 = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0); - }else{ - pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); - if( pCx==0 ) goto no_mem; - pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, - BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, - vfsFlags); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); - if( rc==SQLITE_OK ){ - /* If a transient index is required, create it by calling - ** 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 = 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 = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, - pKeyInfo, pCx->uc.pCursor); - } - pCx->isTable = 0; - }else{ - pCx->pgnoRoot = SCHEMA_ROOT; - rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR, - 0, pCx->uc.pCursor); - pCx->isTable = 1; - } - } - pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); - assert( p->apCsr[pOp->p1]==pCx ); - if( rc ){ - assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); - sqlite3BtreeClose(pCx->ub.pBtx); - p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */ - }else{ - assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); - } - } - } - if( rc ) goto abort_due_to_error; - pCx->nullRow = 1; - break; -} - -/* Opcode: SorterOpen P1 P2 P3 P4 * -** -** This opcode works like OP_OpenEphemeral except that it opens -** a transient index that is specifically designed to sort large -** tables using an external merge-sort algorithm. -** -** If argument P3 is non-zero, then it indicates that the sorter may -** assume that a stable sort considering the first P3 fields of each -** key is sufficient to produce the required results. -*/ -case OP_SorterOpen: { - VdbeCursor *pCx; - - assert( pOp->p1>=0 ); - assert( pOp->p2>=0 ); - 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 ); - assert( pCx->pKeyInfo->enc==ENC(db) ); - rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: SequenceTest P1 P2 * * * -** Synopsis: if( cursor[P1].ctr++ ) pc = P2 -** -** P1 is a sorter cursor. If the sequence counter is currently zero, jump -** to P2. Regardless of whether or not the jump is taken, increment the -** the sequence value. -*/ -case OP_SequenceTest: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( isSorter(pC) ); - if( (pC->seqCount++)==0 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: OpenPseudo P1 P2 P3 * * -** Synopsis: P3 columns in r[P2] -** -** Open a new cursor that points to a fake table that contains a single -** row of data. The content of that one row is the content of memory -** register P2. In other words, cursor P1 becomes an alias for the -** MEM_Blob content contained in register P2. -** -** A pseudo-table created by this opcode is used to hold a single -** row output from the sorter so that the row can be decomposed into -** individual columns using the OP_Column opcode. The OP_Column opcode -** is the only cursor opcode that works with a pseudo-table. -** -** P3 is the number of fields in the records that will be stored by -** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor -** will return NULL for every column. -*/ -case OP_OpenPseudo: { - VdbeCursor *pCx; - - assert( pOp->p1>=0 ); - assert( pOp->p3>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO); - if( pCx==0 ) goto no_mem; - pCx->nullRow = 1; - pCx->seekResult = pOp->p2; - pCx->isTable = 1; - /* Give this pseudo-cursor a fake BtCursor pointer so that pCx - ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test - ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto() - ** which is a performance optimization */ - pCx->uc.pCursor = sqlite3BtreeFakeValidCursor(); - assert( pOp->p5==0 ); - break; -} - -/* Opcode: Close P1 * * * * -** -** Close a cursor previously opened as P1. If P1 is not -** currently open, this instruction is a no-op. -*/ -case OP_Close: { /* ncycle */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); - p->apCsr[pOp->p1] = 0; - break; -} - -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK -/* Opcode: ColumnsUsed P1 * * P4 * -** -** This opcode (which only exists if SQLite was compiled with -** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the -** table or index for cursor P1 are used. P4 is a 64-bit integer -** (P4_INT64) in which the first 63 bits are one for each of the -** first 63 columns of the table or index that are actually used -** by the cursor. The high-order bit is set if any column after -** the 64th is used. -*/ -case OP_ColumnsUsed: { - VdbeCursor *pC; - pC = p->apCsr[pOp->p1]; - assert( pC->eCurType==CURTYPE_BTREE ); - pC->maskUsed = *(u64*)pOp->p4.pI64; - break; -} -#endif - -/* Opcode: SeekGE P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as the key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than or equal to the key value. If there are no records -** greater than or equal to the key and P2 is not zero, then jump to P2. -** -** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will either land on a record that exactly matches the key, or -** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, -** this opcode must be followed by an IdxLE opcode with the same arguments. -** The IdxGT opcode will be skipped if this opcode succeeds, but the -** IdxGT opcode will be used on subsequent loop iterations. The -** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this -** is an equality search. -** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. -** -** See also: Found, NotFound, SeekLt, SeekGt, SeekLe -*/ -/* Opcode: SeekGT P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than the key value. If there are no records greater than -** the key and P2 is not zero, then jump to P2. -** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. -** -** See also: Found, NotFound, SeekLt, SeekGe, SeekLe -*/ -/* Opcode: SeekLT P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the largest entry that -** is less than the key value. If there are no records less than -** the key and P2 is not zero, then jump to P2. -** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. -** -** See also: Found, NotFound, SeekGt, SeekGe, SeekLe -*/ -/* Opcode: SeekLE P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the largest entry that -** is less than or equal to the key value. If there are no records -** less than or equal to the key and P2 is not zero, then jump to P2. -** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. -** -** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will either land on a record that exactly matches the key, or -** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, -** this opcode must be followed by an IdxLE opcode with the same arguments. -** The IdxGE opcode will be skipped if this opcode succeeds, but the -** IdxGE opcode will be used on subsequent loop iterations. The -** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this -** is an equality search. -** -** See also: Found, NotFound, SeekGt, SeekGe, SeekLt -*/ -case OP_SeekLT: /* jump0, in3, group, ncycle */ -case OP_SeekLE: /* jump0, in3, group, ncycle */ -case OP_SeekGE: /* jump0, in3, group, ncycle */ -case OP_SeekGT: { /* jump0, in3, group, ncycle */ - int res; /* Comparison result */ - int oc; /* Opcode */ - VdbeCursor *pC; /* The cursor to seek */ - UnpackedRecord r; /* The key to seek for */ - int nField; /* Number of columns or fields in the key */ - i64 iKey; /* The rowid we are to seek to */ - int eqOnly; /* Only interested in == results */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p2!=0 ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( OP_SeekLE == OP_SeekLT+1 ); - assert( OP_SeekGE == OP_SeekLT+2 ); - assert( OP_SeekGT == OP_SeekLT+3 ); - assert( pC->isOrdered ); - assert( pC->uc.pCursor!=0 ); - oc = pOp->opcode; - eqOnly = 0; - pC->nullRow = 0; -#ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; -#endif - - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( pC->isTable ){ - u16 flags3, newType; - /* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */ - assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 - || CORRUPT_DB ); - - /* The input value in P3 might be of any type: integer, real, string, - ** blob, or NULL. But it needs to be an integer before we can do - ** the seek, so convert it. */ - pIn3 = &aMem[pOp->p3]; - flags3 = pIn3->flags; - if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3, 0); - } - iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ - newType = pIn3->flags; /* Record the type after applying numeric affinity */ - pIn3->flags = flags3; /* But convert the type back to its original */ - - /* 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); - goto jump_to_p2; - }else{ - rc = sqlite3BtreeLast(pC->uc.pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - goto seek_not_found; - } - } - c = 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 - ** is 4.9 and the integer approximation 5: - ** - ** (x > 4.9) -> (x >= 5) - ** (x <= 4.9) -> (x < 5) - */ - if( c>0 ){ - assert( OP_SeekGE==(OP_SeekGT-1) ); - assert( OP_SeekLT==(OP_SeekLE-1) ); - assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); - if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; - } - - /* If the approximation iKey is smaller than the actual real search - ** term, substitute <= for < and > for >=. */ - 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 = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res); - pC->movetoTarget = iKey; /* Used by OP_Delete */ - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - }else{ - /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the - ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be - ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively, - ** with the same key. - */ - if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){ - eqOnly = 1; - assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); - assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT ); - assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT ); - assert( pOp[1].p1==pOp[0].p1 ); - assert( pOp[1].p2==pOp[0].p2 ); - assert( pOp[1].p3==pOp[0].p3 ); - assert( pOp[1].p4.i==pOp[0].p4.i ); - } - - nField = pOp->p4.i; - assert( pOp->p4type==P4_INT32 ); - assert( nField>0 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)nField; - - /* The next line of code computes as follows, only faster: - ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ - ** r.default_rc = -1; - ** }else{ - ** r.default_rc = +1; - ** } - */ - r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); - assert( oc!=OP_SeekGT || r.default_rc==-1 ); - assert( oc!=OP_SeekLE || r.default_rc==-1 ); - assert( oc!=OP_SeekGE || r.default_rc==+1 ); - assert( oc!=OP_SeekLT || r.default_rc==+1 ); - - r.aMem = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; i0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]); - } - } -#endif - r.eqSeen = 0; - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( eqOnly && r.eqSeen==0 ){ - assert( res!=0 ); - goto seek_not_found; - } - } -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); - if( res<0 || (res==0 && oc==OP_SeekGT) ){ - res = 0; - rc = sqlite3BtreeNext(pC->uc.pCursor, 0); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - res = 1; - }else{ - goto abort_due_to_error; - } - } - }else{ - res = 0; - } - }else{ - assert( oc==OP_SeekLT || oc==OP_SeekLE ); - if( res>0 || (res==0 && oc==OP_SeekLT) ){ - res = 0; - rc = sqlite3BtreePrevious(pC->uc.pCursor, 0); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - res = 1; - }else{ - goto abort_due_to_error; - } - } - }else{ - /* res might be negative because the table is empty. Check to - ** see if this is the case. - */ - res = sqlite3BtreeEof(pC->uc.pCursor); - } - } -seek_not_found: - assert( pOp->p2>0 ); - VdbeBranchTaken(res!=0,2); - if( res ){ - goto jump_to_p2; - }else if( eqOnly ){ - assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ - } - break; -} - - -/* Opcode: SeekScan P1 P2 * * P5 -** Synopsis: Scan-ahead up to P1 rows -** -** This opcode is a prefix opcode to OP_SeekGE. In other words, this -** opcode must be immediately followed by OP_SeekGE. This constraint is -** checked by assert() statements. -** -** This opcode uses the P1 through P4 operands of the subsequent -** OP_SeekGE. In the text that follows, the operands of the subsequent -** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only -** the P1, P2 and P5 operands of this opcode are also used, and are called -** This.P1, This.P2 and This.P5. -** -** This opcode helps to optimize IN operators on a multi-column index -** where the IN operator is on the later terms of the index by avoiding -** unnecessary seeks on the btree, substituting steps to the next row -** of the b-tree instead. A correct answer is obtained if this opcode -** is omitted or is a no-op. -** -** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which -** is the desired entry that we want the cursor SeekGE.P1 to be pointing -** to. Call this SeekGE.P3/P4 row the "target". -** -** If the SeekGE.P1 cursor is not currently pointing to a valid row, -** then this opcode is a no-op and control passes through into the OP_SeekGE. -** -** If the SeekGE.P1 cursor is pointing to a valid row, then that row -** might be the target row, or it might be near and slightly before the -** target row, or it might be after the target row. If the cursor is -** currently before the target row, then this opcode attempts to position -** the cursor on or after the target row by invoking sqlite3BtreeStep() -** on the cursor between 1 and This.P1 times. -** -** The This.P5 parameter is a flag that indicates what to do if the -** cursor ends up pointing at a valid row that is past the target -** row. If This.P5 is false (0) then a jump is made to SeekGE.P2. If -** This.P5 is true (non-zero) then a jump is made to This.P2. The P5==0 -** case occurs when there are no inequality constraints to the right of -** the IN constraint. The jump to SeekGE.P2 ends the loop. The P5!=0 case -** occurs when there are inequality constraints to the right of the IN -** operator. In that case, the This.P2 will point either directly to or -** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for -** loop terminate. -** -** Possible outcomes from this opcode:
      -** -**
    1. If the cursor is initially not pointed to any valid row, then -** fall through into the subsequent OP_SeekGE opcode. -** -**
    2. If the cursor is left pointing to a row that is before the target -** row, even after making as many as This.P1 calls to -** sqlite3BtreeNext(), then also fall through into OP_SeekGE. -** -**
    3. If the cursor is left pointing at the target row, either because it -** was at the target row to begin with or because one or more -** sqlite3BtreeNext() calls moved the cursor to the target row, -** then jump to This.P2.., -** -**
    4. If the cursor started out before the target row and a call to -** to sqlite3BtreeNext() moved the cursor off the end of the index -** (indicating that the target row definitely does not exist in the -** btree) then jump to SeekGE.P2, ending the loop. -** -**
    5. If the cursor ends up on a valid row that is past the target row -** (indicating that the target row does not exist in the btree) then -** jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0. -**
    -*/ -case OP_SeekScan: { /* ncycle */ - VdbeCursor *pC; - int res; - int nStep; - UnpackedRecord r; - - assert( pOp[1].opcode==OP_SeekGE ); - - /* If pOp->p5 is clear, then pOp->p2 points to the first instruction past the - ** OP_IdxGT that follows the OP_SeekGE. Otherwise, it points to the first - ** opcode past the OP_SeekGE itself. */ - assert( pOp->p2>=(int)(pOp-aOp)+2 ); -#ifdef SQLITE_DEBUG - if( pOp->p5==0 ){ - /* There are no inequality constraints following the IN constraint. */ - 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 ); - assert( aOp[pOp->p2-1].opcode==OP_IdxGT - || aOp[pOp->p2-1].opcode==OP_IdxGE ); - testcase( aOp[pOp->p2-1].opcode==OP_IdxGE ); - }else{ - /* There are inequality constraints. */ - assert( pOp->p2==(int)(pOp-aOp)+2 ); - assert( aOp[pOp->p2-1].opcode==OP_SeekGE ); - } -#endif - - assert( pOp->p1>0 ); - pC = p->apCsr[pOp[1].p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( !pC->isTable ); - if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... cursor not valid - fall through\n"); - } -#endif - break; - } - nStep = pOp->p1; - assert( nStep>=1 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp[1].p4.i; - r.default_rc = 0; - r.aMem = &aMem[pOp[1].p3]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; i0 && pOp->p5==0 ){ - seekscan_search_fail: - /* Jump to SeekGE.P2, ending the loop */ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... %d steps and then skip\n", pOp->p1 - nStep); - } -#endif - VdbeBranchTaken(1,3); - pOp++; - goto jump_to_p2; - } - if( res>=0 ){ - /* Jump to This.P2, bypassing the OP_SeekGE opcode */ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... %d steps and then success\n", pOp->p1 - nStep); - } -#endif - VdbeBranchTaken(2,3); - goto jump_to_p2; - break; - } - if( nStep<=0 ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... fall through after %d steps\n", pOp->p1); - } -#endif - VdbeBranchTaken(0,3); - break; - } - nStep--; - pC->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeNext(pC->uc.pCursor, 0); - if( rc ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - goto seekscan_search_fail; - }else{ - goto abort_due_to_error; - } - } - } - - break; -} - - -/* Opcode: SeekHit P1 P2 P3 * * -** Synopsis: set P2<=seekHit<=P3 -** -** Increase or decrease the seekHit value for cursor P1, if necessary, -** so that it is no less than P2 and no greater than P3. -** -** The seekHit integer represents the maximum of terms in an index for which -** there is known to be at least one match. If the seekHit value is smaller -** than the total number of equality terms in an index lookup, then the -** OP_IfNoHope opcode might run to see if the IN loop can be abandoned -** early, thus saving work. This is part of the IN-early-out optimization. -** -** P1 must be a valid b-tree cursor. -*/ -case OP_SeekHit: { /* ncycle */ - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pOp->p3>=pOp->p2 ); - if( pC->seekHitp2 ){ -#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; -} - -/* Opcode: IfNotOpen P1 P2 * * * -** Synopsis: if( !csr[P1] ) goto P2 -** -** If cursor P1 is not open or if P1 is set to a NULL row using the -** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through. -*/ -case OP_IfNotOpen: { /* jump */ - VdbeCursor *pCur; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pCur = p->apCsr[pOp->p1]; - VdbeBranchTaken(pCur==0 || pCur->nullRow, 2); - if( pCur==0 || pCur->nullRow ){ - goto jump_to_p2_and_check_for_interrupt; - } - break; -} - -/* Opcode: Found P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If P4==0 then register P3 holds a blob constructed by MakeRecord. If -** P4>0 then register P3 is the first of P4 registers that form an unpacked -** record. -** -** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is a prefix of any entry in P1 then a jump is made to P2 and -** P1 is left pointing at the matching entry. -** -** This operation leaves the cursor in a state where it can be -** advanced in the forward direction. The Next instruction will work, -** but not the Prev instruction. -** -** See also: NotFound, NoConflict, NotExists. SeekGe -*/ -/* Opcode: NotFound P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If P4==0 then register P3 holds a blob constructed by MakeRecord. If -** P4>0 then register P3 is the first of P4 registers that form an unpacked -** record. -** -** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is not the prefix of any entry in P1 then a jump is made to P2. If P1 -** does contain an entry whose prefix matches the P3/P4 record then control -** falls through to the next instruction and P1 is left pointing at the -** matching entry. -** -** This operation leaves the cursor in a state where it cannot be -** advanced in either direction. In other words, the Next and Prev -** opcodes do not work after this operation. -** -** See also: Found, NotExists, NoConflict, IfNoHope -*/ -/* Opcode: IfNoHope P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** Register P3 is the first of P4 registers that form an unpacked -** record. Cursor P1 is an index btree. P2 is a jump destination. -** In other words, the operands to this opcode are the same as the -** operands to OP_NotFound and OP_IdxGT. -** -** This opcode is an optimization attempt only. If this opcode always -** falls through, the correct answer is still obtained, but extra work -** is performed. -** -** A value of N in the seekHit flag of cursor P1 means that there exists -** a key P3:N that will match some record in the index. We want to know -** if it is possible for a record P3:P4 to match some record in the -** index. If it is not possible, we can skip some work. So if seekHit -** is less than P4, attempt to find out if a match is possible by running -** OP_NotFound. -** -** This opcode is used in IN clause processing for a multi-column key. -** If an IN clause is attached to an element of the key other than the -** left-most element, and if there are no matches on the most recent -** seek over the whole key, then it might be that one of the key element -** to the left is prohibiting a match, and hence there is "no hope" of -** any match regardless of how many IN clause elements are checked. -** In such a case, we abandon the IN clause search early, using this -** opcode. The opcode name comes from the fact that the -** jump is taken if there is "no hope" of achieving a match. -** -** See also: NotFound, SeekHit -*/ -/* Opcode: NoConflict P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** If P4==0 then register P3 holds a blob constructed by MakeRecord. If -** P4>0 then register P3 is the first of P4 registers that form an unpacked -** record. -** -** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** contains any NULL value, jump immediately to P2. If all terms of the -** record are not-NULL then a check is done to determine if any row in the -** P1 index btree has a matching key prefix. If there are no matches, jump -** immediately to P2. If there is a match, fall through and leave the P1 -** cursor pointing to the matching row. -** -** This opcode is similar to OP_NotFound with the exceptions that the -** branch is always taken if any part of the search key input is NULL. -** -** This operation leaves the cursor in a state where it cannot be -** advanced in either direction. In other words, the Next and Prev -** opcodes do not work after this operation. -** -** See also: NotFound, Found, NotExists -*/ -case OP_IfNoHope: { /* jump, in3, ncycle */ - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - 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 -} -case OP_NoConflict: /* jump, in3, ncycle */ -case OP_NotFound: /* jump, in3, ncycle */ -case OP_Found: { /* jump, in3, ncycle */ - int alreadyExists; - int ii; - VdbeCursor *pC; - UnpackedRecord *pIdxKey; - UnpackedRecord r; - -#ifdef SQLITE_TEST - if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; -#endif - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p4type==P4_INT32 ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); -#ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; -#endif - r.aMem = &aMem[pOp->p3]; - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - assert( pC->isTable==0 ); - r.nField = (u16)pOp->p4.i; - if( r.nField>0 ){ - /* Key values in an array of registers */ - r.pKeyInfo = pC->pKeyInfo; - r.default_rc = 0; -#ifdef SQLITE_DEBUG - (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */ - for(ii=0; iip3+ii, &r.aMem[ii]); - } -#endif - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult); - }else{ - /* 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; - pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); - if( pIdxKey==0 ) goto no_mem; - sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey); - pIdxKey->default_rc = 0; - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult); - sqlite3DbFreeNN(db, pIdxKey); - } - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - alreadyExists = (pC->seekResult==0); - pC->nullRow = 1-alreadyExists; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( pOp->opcode==OP_Found ){ - VdbeBranchTaken(alreadyExists!=0,2); - if( alreadyExists ) goto jump_to_p2; - }else{ - 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; iiopcode==OP_IfNoHope ){ - pC->seekHit = pOp->p4.i; - } - } - break; -} - -/* Opcode: SeekRowid P1 P2 P3 * * -** Synopsis: intkey=r[P3] -** -** P1 is the index of a cursor open on an SQL table btree (with integer -** keys). If register P3 does not contain an integer or if P1 does not -** contain a record with rowid P3 then jump immediately to P2. -** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain -** a record with rowid P3 then -** leave the cursor pointing at that record and fall through to the next -** instruction. -** -** The OP_NotExists opcode performs the same operation, but with OP_NotExists -** the P3 register must be guaranteed to contain an integer value. With this -** opcode, register P3 might not contain an integer. -** -** The OP_NotFound opcode performs the same operation on index btrees -** (with arbitrary multi-value keys). -** -** This opcode leaves the cursor in a state where it cannot be advanced -** in either direction. In other words, the Next and Prev opcodes will -** not work following this opcode. -** -** See also: Found, NotFound, NoConflict, SeekRowid -*/ -/* Opcode: NotExists P1 P2 P3 * * -** Synopsis: intkey=r[P3] -** -** P1 is the index of a cursor open on an SQL table btree (with integer -** keys). P3 is an integer rowid. If P1 does not contain a record with -** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an -** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then -** leave the cursor pointing at that record and fall through to the next -** instruction. -** -** The OP_SeekRowid opcode performs the same operation but also allows the -** P3 register to contain a non-integer value, in which case the jump is -** always taken. This opcode requires that P3 always contain an integer. -** -** The OP_NotFound opcode performs the same operation on index btrees -** (with arbitrary multi-value keys). -** -** This opcode leaves the cursor in a state where it cannot be advanced -** in either direction. In other words, the Next and Prev opcodes will -** not work following this opcode. -** -** See also: Found, NotFound, NoConflict, SeekRowid -*/ -case OP_SeekRowid: { /* jump0, in3, ncycle */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - u64 iKey; - - pIn3 = &aMem[pOp->p3]; - testcase( pIn3->flags & MEM_Int ); - testcase( pIn3->flags & MEM_IntReal ); - testcase( pIn3->flags & MEM_Real ); - testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str ); - if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - /* If pIn3->u.i does not contain an integer, compute iKey as the - ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted - ** into an integer without loss of information. Take care to avoid - ** changing the datatype of pIn3, however, as it is used by other - ** parts of the prepared statement. */ - Mem x = pIn3[0]; - applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding); - if( (x.flags & MEM_Int)==0 ) goto jump_to_p2; - iKey = x.u.i; - goto notExistsWithKey; - } - /* Fall through into OP_NotExists */ - /* no break */ deliberate_fall_through -case OP_NotExists: /* jump, in3, ncycle */ - pIn3 = &aMem[pOp->p3]; - assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - iKey = pIn3->u.i; -notExistsWithKey: - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); -#ifdef SQLITE_DEBUG - if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid; -#endif - assert( pC->isTable ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; - assert( pCrsr!=0 ); - res = 0; - rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res); - assert( rc==SQLITE_OK || res==0 ); - pC->movetoTarget = iKey; /* Used by OP_Delete */ - pC->nullRow = 0; - pC->cacheStatus = CACHE_STALE; - pC->deferredMoveto = 0; - VdbeBranchTaken(res!=0,2); - pC->seekResult = res; - if( res!=0 ){ - assert( rc==SQLITE_OK ); - if( pOp->p2==0 ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - goto jump_to_p2; - } - } - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: Sequence P1 P2 * * * -** Synopsis: r[P2]=cursor[P1].ctr++ -** -** Find the next available sequence number for cursor P1. -** Write the sequence number into register P2. -** The sequence number on the cursor is incremented after this -** instruction. -*/ -case OP_Sequence: { /* out2 */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( p->apCsr[pOp->p1]!=0 ); - assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB ); - pOut = out2Prerelease(p, pOp); - pOut->u.i = p->apCsr[pOp->p1]->seqCount++; - break; -} - - -/* Opcode: NewRowid P1 P2 P3 * * -** Synopsis: r[P2]=rowid -** -** Get a new integer record number (a.k.a "rowid") used as the key to a table. -** The record number is not previously used as a key in the database -** table that cursor P1 points to. The new record number is written -** written to register P2. -** -** If P3>0 then P3 is a register in the root frame of this VDBE that holds -** the largest previously generated record number. No new record numbers are -** allowed to be less than this value. When this value reaches its maximum, -** an SQLITE_FULL error is generated. The P3 register is updated with the ' -** generated record number. This P3 mechanism is used to help implement the -** AUTOINCREMENT feature. -*/ -case OP_NewRowid: { /* out2 */ - i64 v; /* The new rowid */ - VdbeCursor *pC; /* Cursor of table to get the new rowid */ - int res; /* Result of an sqlite3BtreeLast() */ - int cnt; /* Counter to limit the number of searches */ -#ifndef SQLITE_OMIT_AUTOINCREMENT - Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ - VdbeFrame *pFrame; /* Root frame of VDBE */ -#endif - - v = 0; - res = 0; - pOut = out2Prerelease(p, pOp); - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->isTable ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - { - /* The next rowid or record number (different terms for the same - ** thing) is obtained in a two-step algorithm. - ** - ** First we attempt to find the largest existing rowid and add one - ** to that. But if the largest existing rowid is already the maximum - ** positive integer, we have to fall through to the second - ** probabilistic algorithm - ** - ** The second algorithm is to select a rowid at random and see if - ** it already exists in the table. If it does not exist, we have - ** succeeded. If the random rowid does exist, we select a new one - ** and try again, up to 100 times. - */ - assert( pC->isTable ); - -#ifdef SQLITE_32BIT_ROWID -# define MAX_ROWID 0x7fffffff -#else - /* Some compilers complain about constants of the form 0x7fffffffffffffff. - ** Others complain about 0x7ffffffffffffffffLL. The following macro seems - ** to provide the constant while making all compilers happy. - */ -# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) -#endif - - if( !pC->useRandomRowid ){ - rc = sqlite3BtreeLast(pC->uc.pCursor, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( res ){ - v = 1; /* IMP: R-61914-48074 */ - }else{ - assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) ); - v = sqlite3BtreeIntegerKey(pC->uc.pCursor); - if( v>=MAX_ROWID ){ - pC->useRandomRowid = 1; - }else{ - v++; /* IMP: R-29538-34987 */ - } - } - } - -#ifndef SQLITE_OMIT_AUTOINCREMENT - if( pOp->p3 ){ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3>0 ); - if( p->pFrame ){ - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=pFrame->nMem ); - pMem = &pFrame->aMem[pOp->p3]; - }else{ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - pMem = &aMem[pOp->p3]; - memAboutToChange(p, pMem); - } - assert( memIsValid(pMem) ); - - REGISTER_TRACE(pOp->p3, pMem); - sqlite3VdbeMemIntegerify(pMem); - assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-17817-00630 */ - goto abort_due_to_error; - } - if( vu.i+1 ){ - v = pMem->u.i + 1; - } - pMem->u.i = v; - } -#endif - if( pC->useRandomRowid ){ - /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the - ** largest possible integer (9223372036854775807) then the database - ** engine starts picking positive candidate ROWIDs at random until - ** it finds one that is not previously used. */ - assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is - ** an AUTOINCREMENT table. */ - cnt = 0; - do{ - sqlite3_randomness(sizeof(v), &v); - v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ - }while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v, - 0, &res))==SQLITE_OK) - && (res==0) - && (++cnt<100)); - if( rc ) goto abort_due_to_error; - if( res==0 ){ - rc = SQLITE_FULL; /* IMP: R-38219-53002 */ - goto abort_due_to_error; - } - assert( v>0 ); /* EV: R-40812-03570 */ - } - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - } - pOut->u.i = v; - break; -} - -/* Opcode: Insert P1 P2 P3 P4 P5 -** Synopsis: intkey=r[P3] data=r[P2] -** -** Write an entry into the table of cursor P1. A new entry is -** created if it doesn't already exist or the data for an existing -** entry is overwritten. The data is the value MEM_Blob stored in register -** number P2. The key is stored in register P3. The key must -** be a MEM_Int. -** -** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is -** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, -** then rowid is stored for subsequent return by the -** sqlite3_last_insert_rowid() function (otherwise it is unmodified). -** -** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might -** run faster by avoiding an unnecessary seek on cursor P1. However, -** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior -** seeks on the cursor or if the most recent seek used a key equal to P3. -** -** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an -** UPDATE operation. Otherwise (if the flag is clear) then this opcode -** is part of an INSERT operation. The difference is only important to -** the update hook. -** -** Parameter P4 may point to a Table structure, or may be NULL. If it is -** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked -** following a successful insert. -** -** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically -** allocated, then ownership of P2 is transferred to the pseudo-cursor -** and register P2 becomes ephemeral. If the cursor is changed, the -** value of register P2 will then change. Make sure this does not -** cause any problems.) -** -** This instruction only works on tables. The equivalent instruction -** for indices is OP_IdxInsert. -*/ -case OP_Insert: { - Mem *pData; /* MEM cell holding data for the record to be inserted */ - Mem *pKey; /* MEM cell holding key for the record */ - VdbeCursor *pC; /* Cursor to table into which insert is written */ - int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ - const char *zDb; /* database name - used by the update hook */ - Table *pTab; /* Table structure - used by update and pre-update hooks */ - BtreePayload x; /* Payload to be inserted */ - - pData = &aMem[pOp->p2]; - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( memIsValid(pData) ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->deferredMoveto==0 ); - assert( pC->uc.pCursor!=0 ); - assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); - assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); - REGISTER_TRACE(pOp->p2, pData); - sqlite3VdbeIncrWriteCounter(p, pC); - - pKey = &aMem[pOp->p3]; - assert( pKey->flags & MEM_Int ); - assert( memIsValid(pKey) ); - REGISTER_TRACE(pOp->p3, pKey); - x.nKey = pKey->u.i; - - if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ - assert( pC->iDb>=0 ); - zDb = db->aDb[pC->iDb].zDbSName; - pTab = pOp->p4.pTab; - assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) ); - }else{ - pTab = 0; - zDb = 0; - } - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - /* Invoke the pre-update hook, if any */ - if( pTab ){ - if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){ - 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 */ - pTab = 0; - } - } - if( pOp->p5 & OPFLAG_ISNOOP ) break; -#endif - - assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 ); - if( pOp->p5 & OPFLAG_NCHANGE ){ - p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; - } - assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 ); - x.pData = pData->z; - x.nData = pData->n; - seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); - if( pData->flags & MEM_Zero ){ - x.nZero = pData->u.nZero; - }else{ - x.nZero = 0; - } - x.pKey = 0; - assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); - rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), - seekResult - ); - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - colCacheCtr++; - - /* Invoke the update-hook if required. */ - if( rc ) goto abort_due_to_error; - if( pTab ){ - assert( db->xUpdateCallback!=0 ); - assert( pTab->aCol!=0 ); - db->xUpdateCallback(db->pUpdateArg, - (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT, - zDb, pTab->zName, x.nKey); - } - 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 = 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. -** -** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then -** the cursor will be left pointing at either the next or the previous -** record in the table. If it is left pointing at the next record, then -** the next Next instruction will be a no-op. As a result, in this case -** it is ok to delete a record from within a Next loop. If -** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be -** left in an undefined state. -** -** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this -** delete is one of several associated with deleting a table row and -** all its associated index entries. Exactly one of those deletes is -** the "primary" delete. The others are all on OPFLAG_FORDELETE -** cursors or else are marked with the AUXDELETE flag. -** -** If the OPFLAG_NCHANGE (0x01) flag of P2 (NB: P2 not P5) is set, then -** the row change count is incremented (otherwise not). -** -** If the OPFLAG_ISNOOP (0x40) flag of P2 (not P5!) is set, then the -** pre-update-hook for deletes is run, but the btree is otherwise unchanged. -** This happens when the OP_Delete is to be shortly followed by an OP_Insert -** with the same key, causing the btree entry to be overwritten. -** -** P1 must not be pseudo-table. It has to be a real table with -** multiple rows. -** -** If P4 is not NULL then it points to a Table object. In this case either -** the update or pre-update hook, or both, may be invoked. The P1 cursor must -** have been positioned using OP_NotFound prior to invoking this opcode in -** this case. Specifically, if one is configured, the pre-update hook is -** invoked if P4 is not NULL. The update-hook is invoked if one is configured, -** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. -** -** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address -** of the memory cell that contains the value that the rowid of the row will -** be set to by the update. -*/ -case OP_Delete: { - VdbeCursor *pC; - const char *zDb; - Table *pTab; - int opflags; - - opflags = pOp->p2; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - assert( pC->deferredMoveto==0 ); - sqlite3VdbeIncrWriteCounter(p, pC); - -#ifdef SQLITE_DEBUG - if( pOp->p4type==P4_TABLE - && HasRowid(pOp->p4.pTab) - && pOp->p5==0 - && sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) - ){ - /* If p5 is zero, the seek operation that positioned the cursor prior to - ** OP_Delete will have also set the pC->movetoTarget field to the rowid of - ** the row that is being deleted */ - i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor); - assert( CORRUPT_DB || pC->movetoTarget==iKey ); - } -#endif - - /* If the update-hook or pre-update-hook will be invoked, set zDb to - ** the name of the db to pass as to it. Also set local pTab to a copy - ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was - ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set - ** VdbeCursor.movetoTarget to the current rowid. */ - if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ - assert( pC->iDb>=0 ); - assert( pOp->p4.pTab!=0 ); - zDb = db->aDb[pC->iDb].zDbSName; - pTab = pOp->p4.pTab; - if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ - pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); - } - }else{ - zDb = 0; - pTab = 0; - } - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - /* Invoke the pre-update-hook if required. */ - 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) - ); - sqlite3VdbePreUpdateHook(p, pC, - (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, - zDb, pTab, pC->movetoTarget, - pOp->p3, -1 - ); - } - if( opflags & OPFLAG_ISNOOP ) break; -#endif - - /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ - assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); - assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); - assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); - -#ifdef SQLITE_DEBUG - if( p->pFrame==0 ){ - if( pC->isEphemeral==0 - && (pOp->p5 & OPFLAG_AUXDELETE)==0 - && (pC->wrFlag & OPFLAG_FORDELETE)==0 - ){ - nExtraDelete++; - } - if( pOp->p2 & OPFLAG_NCHANGE ){ - nExtraDelete--; - } - } -#endif - - rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); - pC->cacheStatus = CACHE_STALE; - colCacheCtr++; - pC->seekResult = 0; - if( rc ) goto abort_due_to_error; - - /* Invoke the update-hook if required. */ - if( opflags & OPFLAG_NCHANGE ){ - p->nChange++; - if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){ - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, - pC->movetoTarget); - assert( pC->iDb>=0 ); - } - } - - break; -} -/* Opcode: ResetCount * * * * * -** -** The value of the change counter is copied to the database handle -** change counter (returned by subsequent calls to sqlite3_changes()). -** Then the VMs internal change counter resets to 0. -** This is used by trigger programs. -*/ -case OP_ResetCount: { - sqlite3VdbeSetChanges(db, p->nChange); - p->nChange = 0; - break; -} - -/* Opcode: SorterCompare P1 P2 P3 P4 -** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 -** -** P1 is a sorter cursor. This instruction compares a prefix of the -** record blob in register P3 against a prefix of the entry that -** the sorter cursor currently points to. Only the first P4 fields -** of r[P3] and the sorter record are compared. -** -** If either P3 or the sorter contains a NULL in one of their significant -** fields (not counting the P4 fields at the end which are ignored) then -** the comparison is assumed to be equal. -** -** Fall through to next instruction if the two records compare equal to -** each other. Jump to P2 if they are different. -*/ -case OP_SorterCompare: { - VdbeCursor *pC; - int res; - int nKeyCol; - - pC = p->apCsr[pOp->p1]; - assert( isSorter(pC) ); - assert( pOp->p4type==P4_INT32 ); - pIn3 = &aMem[pOp->p3]; - nKeyCol = pOp->p4.i; - res = 0; - rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); - VdbeBranchTaken(res!=0,2); - if( rc ) goto abort_due_to_error; - if( res ) goto jump_to_p2; - break; -}; - -/* Opcode: SorterData P1 P2 P3 * * -** Synopsis: r[P2]=data -** -** Write into register P2 the current sorter data for sorter cursor P1. -** Then clear the column header cache on cursor P3. -** -** This opcode is normally used to move a record out of the sorter and into -** a register that is the source for a pseudo-table cursor created using -** OpenPseudo. That pseudo-table cursor is the one that is identified by -** parameter P3. Clearing the P3 column cache as part of this opcode saves -** us from having to issue a separate NullRow instruction to clear that cache. -*/ -case OP_SorterData: { /* ncycle */ - VdbeCursor *pC; - - pOut = &aMem[pOp->p2]; - pC = p->apCsr[pOp->p1]; - assert( isSorter(pC) ); - rc = sqlite3VdbeSorterRowkey(pC, pOut); - assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - if( rc ) goto abort_due_to_error; - p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; - break; -} - -/* Opcode: RowData P1 P2 P3 * * -** Synopsis: r[P2]=data -** -** Write into register P2 the complete row content for the row at -** which cursor P1 is currently pointing. -** There is no interpretation of the data. -** It is just copied onto the P2 register exactly as -** it is found in the database file. -** -** If cursor P1 is an index, then the content is the key of the row. -** If cursor P2 is a table, then the content extracted is the data. -** -** If the P1 cursor must be pointing to a valid row (not a NULL row) -** of a real table, not a pseudo-table. -** -** If P3!=0 then this opcode is allowed to make an ephemeral pointer -** into the database page. That means that the content of the output -** register will be invalidated as soon as the cursor moves - including -** moves caused by other cursors that "save" the current cursors -** position in order that they can write to the same table. If P3==0 -** then a copy of the data is made into memory. P3!=0 is faster, but -** P3==0 is safer. -** -** If P3!=0 then the content of the P2 register is unsuitable for use -** in OP_Result and any OP_Result will invalidate the P2 register content. -** The P2 register content is invalidated by opcodes like OP_Function or -** by any use of another cursor pointing to the same table. -*/ -case OP_RowData: { - VdbeCursor *pC; - BtCursor *pCrsr; - u32 n; - - pOut = out2Prerelease(p, pOp); - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( isSorter(pC)==0 ); - assert( pC->nullRow==0 ); - assert( pC->uc.pCursor!=0 ); - pCrsr = pC->uc.pCursor; - - /* The OP_RowData opcodes always follow OP_NotExists or - ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions - ** that might invalidate the cursor. - ** If this were not the case, one of the following assert()s - ** would fail. Should this ever change (because of changes in the code - ** generator) then the fix would be to insert a call to - ** sqlite3VdbeCursorMoveto(). - */ - assert( pC->deferredMoveto==0 ); - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - - n = sqlite3BtreePayloadSize(pCrsr); - if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - testcase( n==0 ); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut); - if( rc ) goto abort_due_to_error; - if( !pOp->p3 ) Deephemeralize(pOut); - UPDATE_MAX_BLOBSIZE(pOut); - REGISTER_TRACE(pOp->p2, pOut); - break; -} - -/* Opcode: Rowid P1 P2 * * * -** 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. -** -** P1 can be either an ordinary table or a virtual table. There used to -** be a separate OP_VRowid opcode for use with virtual tables, but this -** one opcode now works for both table types. -*/ -case OP_Rowid: { /* out2, ncycle */ - VdbeCursor *pC; - i64 v; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - - pOut = out2Prerelease(p, pOp); - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); - if( pC->nullRow ){ - pOut->flags = MEM_Null; - break; - }else if( pC->deferredMoveto ){ - v = pC->movetoTarget; -#ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( pC->eCurType==CURTYPE_VTAB ){ - assert( pC->uc.pVCur!=0 ); - pVtab = pC->uc.pVCur->pVtab; - pModule = pVtab->pModule; - assert( pModule->xRowid ); - rc = pModule->xRowid(pC->uc.pVCur, &v); - sqlite3VtabImportErrmsg(p, pVtab); - if( rc ) goto abort_due_to_error; -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - }else{ - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - rc = sqlite3VdbeCursorRestore(pC); - if( rc ) goto abort_due_to_error; - if( pC->nullRow ){ - pOut->flags = MEM_Null; - break; - } - v = sqlite3BtreeIntegerKey(pC->uc.pCursor); - } - pOut->u.i = v; - break; -} - -/* Opcode: NullRow P1 * * * * -** -** 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->p1nCursor ); - pC = p->apCsr[pOp->p1]; - 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 = sqlite3BtreeFakeValidCursor(); - } - pC->nullRow = 1; - pC->cacheStatus = CACHE_STALE; - if( pC->eCurType==CURTYPE_BTREE ){ - assert( pC->uc.pCursor!=0 ); - sqlite3BtreeClearCursor(pC->uc.pCursor); - } -#ifdef SQLITE_DEBUG - if( pC->seekOp==0 ) pC->seekOp = OP_NullRow; -#endif - break; -} - -/* Opcode: SeekEnd P1 * * * * -** -** Position cursor P1 at the end of the btree for the purpose of -** appending a new entry onto the btree. -** -** It is assumed that the cursor is used only for appending and so -** if the cursor is valid, then the cursor must already be pointing -** at the end of the btree and so no changes are made to -** the cursor. -*/ -/* Opcode: Last P1 P2 * * * -** -** The next use of the Rowid or Column or Prev instruction for P1 -** will refer to the last entry in the database table or index. -** If the table or index is empty and P2>0, then jump immediately to P2. -** If P2 is 0 or if the table or index is not empty, fall through -** to the following instruction. -** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. -*/ -case OP_SeekEnd: /* ncycle */ -case OP_Last: { /* jump0, ncycle */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; - res = 0; - assert( pCrsr!=0 ); -#ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; -#endif - if( pOp->opcode==OP_SeekEnd ){ - assert( pOp->p2==0 ); - pC->seekResult = -1; - if( sqlite3BtreeCursorIsValidNN(pCrsr) ){ - break; - } - } - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } - break; -} - -/* Opcode: IfSizeBetween P1 P2 P3 P4 * -** -** Let N be the approximate number of rows in the table or index -** with cursor P1 and let X be 10*log2(N) if N is positive or -1 -** if N is zero. -** -** Jump to P2 if X is in between P3 and P4, inclusive. -*/ -case OP_IfSizeBetween: { /* jump */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - i64 sz; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p3>=-1 && pOp->p3<=640*2 ); - assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - pCrsr = pC->uc.pCursor; - assert( pCrsr ); - rc = sqlite3BtreeFirst(pCrsr, &res); - if( rc ) goto abort_due_to_error; - if( res!=0 ){ - sz = -1; /* -Infinity encoding */ - }else{ - sz = sqlite3BtreeRowCountEst(pCrsr); - assert( sz>0 ); - sz = sqlite3LogEst((u64)sz); - } - res = sz>=pOp->p3 && sz<=pOp->p4.i; - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - break; -} - - -/* Opcode: SorterSort P1 P2 * * * -** -** After all records have been inserted into the Sorter object -** identified by P1, invoke this opcode to actually do the sorting. -** Jump to P2 if there are no records to be sorted. -** -** This opcode is an alias for OP_Sort and OP_Rewind that is used -** for Sorter objects. -*/ -/* Opcode: Sort P1 P2 * * * -** -** This opcode does exactly the same thing as OP_Rewind except that -** it increments an undocumented global variable used for testing. -** -** Sorting is accomplished by writing records into a sorting index, -** then rewinding that index and playing it back from beginning to -** end. We use the OP_Sort opcode instead of OP_Rewind to do the -** rewinding so that the global variable will be incremented and -** regression tests can determine whether or not the optimizer is -** correctly optimizing out sorts. -*/ -case OP_SorterSort: /* jump ncycle */ -case OP_Sort: { /* jump ncycle */ -#ifdef SQLITE_TEST - sqlite3_sort_count++; - sqlite3_search_count--; -#endif - p->aCounter[SQLITE_STMTSTATUS_SORT]++; - /* Fall through into OP_Rewind */ - /* no break */ deliberate_fall_through -} -/* Opcode: Rewind P1 P2 * * * -** -** The next use of the Rowid or Column or Next instruction for P1 -** will refer to the first entry in the database table or index. -** If the table or index is empty, jump immediately to P2. -** If the table or index is not empty, fall through to the following -** instruction. -** -** If P2 is zero, that is an assertion that the P1 table is never -** empty and hence the jump will never be taken. -** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. -*/ -case OP_Rewind: { /* jump0, ncycle */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 ); - assert( pOp->p2>=0 && pOp->p2nOp ); - - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); - res = 1; -#ifdef SQLITE_DEBUG - pC->seekOp = OP_Rewind; -#endif - if( isSorter(pC) ){ - rc = sqlite3VdbeSorterRewind(pC, &res); - }else{ - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; - assert( pCrsr ); - rc = sqlite3BtreeFirst(pCrsr, &res); - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - } - if( rc ) goto abort_due_to_error; - pC->nullRow = (u8)res; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } - break; -} - -/* 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 -** to the following instruction. But if the cursor advance was successful, -** jump immediately to P2. -** -** The Next opcode is only valid following an SeekGT, SeekGE, or -** OP_Rewind opcode used to position the cursor. Next is not allowed -** to follow SeekLT, SeekLE, or OP_Last. -** -** The P1 cursor must be for a real table, not a pseudo-table. P1 must have -** been opened prior to this opcode or the program will segfault. -** -** The P3 value is a hint to the btree implementation. If P3==1, that -** means P1 is an SQL index and that this instruction could have been -** omitted if that index had been unique. P3 is usually 0. P3 is -** always either 0 or 1. -** -** 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 * P5 -** -** Back up cursor P1 so that it points to the previous key/data pair in its -** table or index. If there is no previous key/value pairs then fall through -** to the following instruction. But if the cursor backup was successful, -** jump immediately to P2. -** -** -** The Prev opcode is only valid following an SeekLT, SeekLE, or -** OP_Last opcode used to position the cursor. Prev is not allowed -** to follow SeekGT, SeekGE, or OP_Rewind. -** -** The P1 cursor must be for a real table, not a pseudo-table. If P1 is -** not open then the behavior is undefined. -** -** The P3 value is a hint to the btree implementation. If P3==1, that -** means P1 is an SQL index and that this instruction could have been -** omitted if that index had been unique. P3 is usually 0. P3 is -** always either 0 or 1. -** -** If P5 is positive and the jump is taken, then event counter -** number P5-1 in the prepared statement is incremented. -*/ -/* Opcode: SorterNext P1 P2 * * P5 -** -** This opcode works just like OP_Next except that P1 must be a -** sorter object for which the OP_SorterSort opcode has been -** invoked. This opcode advances the cursor to the next sorted -** record, or jumps to P2 if there are no more sorted records. -*/ -case OP_SorterNext: { /* jump */ - VdbeCursor *pC; - - pC = p->apCsr[pOp->p1]; - assert( isSorter(pC) ); - rc = sqlite3VdbeSorterNext(db, pC); - goto next_tail; - -case OP_Prev: /* jump, ncycle */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 - || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP - || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->deferredMoveto==0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope - || pC->seekOp==OP_NullRow); - rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3); - goto next_tail; - -case OP_Next: /* jump, ncycle */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 - || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP - || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX); - 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); - rc = sqlite3BtreeNext(pC->uc.pCursor, pOp->p3); - -next_tail: - pC->cacheStatus = CACHE_STALE; - VdbeBranchTaken(rc==SQLITE_OK,2); - if( rc==SQLITE_OK ){ - pC->nullRow = 0; - p->aCounter[pOp->p5]++; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - goto jump_to_p2_and_check_for_interrupt; - } - if( rc!=SQLITE_DONE ) goto abort_due_to_error; - rc = SQLITE_OK; - pC->nullRow = 1; - goto check_for_interrupt; -} - -/* Opcode: IdxInsert P1 P2 P3 P4 P5 -** Synopsis: key=r[P2] -** -** Register P2 holds an SQL index key made using the -** MakeRecord instructions. This opcode writes that key -** into the index P1. Data for the entry is nil. -** -** If P4 is not zero, then it is the number of values in the unpacked -** key of reg(P2). In that case, P3 is the index of the first register -** for the unpacked key. The availability of the unpacked key can sometimes -** be an optimization. -** -** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer -** that this insert is likely to be an append. -** -** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is -** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, -** then the change counter is unchanged. -** -** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might -** run faster by avoiding an unnecessary seek on cursor P1. However, -** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior -** seeks on the cursor or if the most recent seek used a key equivalent -** to P2. -** -** This instruction only works for indices. The equivalent instruction -** for tables is OP_Insert. -*/ -case OP_IdxInsert: { /* in2 */ - VdbeCursor *pC; - BtreePayload x; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - sqlite3VdbeIncrWriteCounter(p, pC); - assert( pC!=0 ); - assert( !isSorter(pC) ); - pIn2 = &aMem[pOp->p2]; - 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 ); - rc = ExpandBlob(pIn2); - if( rc ) goto abort_due_to_error; - x.nKey = pIn2->n; - x.pKey = pIn2->z; - x.aMem = aMem + pOp->p3; - x.nMem = (u16)pOp->p4.i; - rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) - ); - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; - if( rc) goto abort_due_to_error; - break; -} - -/* Opcode: SorterInsert P1 P2 * * * -** Synopsis: key=r[P2] -** -** Register P2 holds an SQL index key made using the -** MakeRecord instructions. This opcode writes that key -** into the sorter P1. Data for the entry is nil. -*/ -case OP_SorterInsert: { /* in2 */ - VdbeCursor *pC; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - sqlite3VdbeIncrWriteCounter(p, pC); - assert( pC!=0 ); - assert( isSorter(pC) ); - pIn2 = &aMem[pOp->p2]; - assert( pIn2->flags & MEM_Blob ); - assert( pC->isTable==0 ); - rc = ExpandBlob(pIn2); - if( rc ) goto abort_due_to_error; - rc = sqlite3VdbeSorterWrite(pC, pIn2); - if( rc) goto abort_due_to_error; - break; -} - -/* Opcode: IdxDelete P1 P2 P3 * P5 -** Synopsis: key=r[P2@P3] -** -** The content of P3 registers starting at register P2 form -** an unpacked index key. This opcode removes that entry from the -** index opened by cursor P1. -** -** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error -** if no matching index entry is found. This happens when running -** 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. Also, do not raise -** this (self-correcting and non-critical) error if in writable_schema mode. -*/ -case OP_IdxDelete: { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - UnpackedRecord r; - - assert( pOp->p3>0 ); - assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3VdbeIncrWriteCounter(p, pC); - pCrsr = pC->uc.pCursor; - assert( pCrsr!=0 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p3; - r.default_rc = 0; - r.aMem = &aMem[pOp->p2]; - rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res); - if( rc ) goto abort_due_to_error; - if( res==0 ){ - rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); - if( rc ) goto abort_due_to_error; - }else if( pOp->p5 && !sqlite3WritableSchema(db) ){ - rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); - goto abort_due_to_error; - } - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; - pC->seekResult = 0; - break; -} - -/* Opcode: DeferredSeek P1 * P3 P4 * -** Synopsis: Move P3 to P1.rowid if needed -** -** P1 is an open index cursor and P3 is a cursor on the corresponding -** table. This opcode does a deferred seek of the P3 table cursor -** to the row that corresponds to the current row of P1. -** -** This is a deferred seek. Nothing actually happens until -** the cursor is used to read a record. That way, if no reads -** occur, no unnecessary I/O happens. -** -** P4 may be an array of integers (type P4_INTARRAY) containing -** one entry for each column in the P3 table. If array entry a(i) -** is non-zero, then reading column a(i)-1 from cursor P3 is -** equivalent to performing the deferred seek and then reading column i -** from P1. This information is stored in P3 and used to redirect -** reads against P3 over to P1, thus possibly avoiding the need to -** seek and read cursor P3. -*/ -/* Opcode: IdxRowid P1 P2 * * * -** Synopsis: r[P2]=rowid -** -** Write into register P2 an integer which is the last entry in the record at -** the end of the index key pointed to by cursor P1. This integer should be -** the rowid of the table entry to which this index entry points. -** -** See also: Rowid, MakeRecord. -*/ -case OP_DeferredSeek: /* ncycle */ -case OP_IdxRowid: { /* out2, ncycle */ - VdbeCursor *pC; /* The P1 index cursor */ - VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */ - i64 rowid; /* Rowid that P1 current points to */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) ); - assert( pC->uc.pCursor!=0 ); - assert( pC->isTable==0 || IsNullCursor(pC) ); - assert( pC->deferredMoveto==0 ); - assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); - - /* The IdxRowid and Seek opcodes are combined because of the commonality - ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ - rc = sqlite3VdbeCursorRestore(pC); - - /* sqlite3VdbeCursorRestore() may fail if the cursor has been disturbed - ** since it was last positioned and an error (e.g. OOM or an IO error) - ** occurs while trying to reposition it. */ - if( rc!=SQLITE_OK ) goto abort_due_to_error; - - if( !pC->nullRow ){ - rowid = 0; /* Not needed. Only used to silence a warning. */ - rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( pOp->opcode==OP_DeferredSeek ){ - assert( pOp->p3>=0 && pOp->p3nCursor ); - pTabCur = p->apCsr[pOp->p3]; - assert( pTabCur!=0 ); - assert( pTabCur->eCurType==CURTYPE_BTREE ); - assert( pTabCur->uc.pCursor!=0 ); - assert( pTabCur->isTable ); - pTabCur->nullRow = 0; - pTabCur->movetoTarget = rowid; - pTabCur->deferredMoveto = 1; - pTabCur->cacheStatus = CACHE_STALE; - assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); - assert( !pTabCur->isEphemeral ); - pTabCur->ub.aAltMap = pOp->p4.ai; - assert( !pC->isEphemeral ); - pTabCur->pAltCursor = pC; - }else{ - pOut = out2Prerelease(p, pOp); - pOut->u.i = rowid; - } - }else{ - assert( pOp->opcode==OP_IdxRowid ); - sqlite3VdbeMemSetNull(&aMem[pOp->p2]); - } - break; -} - -/* Opcode: FinishSeek P1 * * * * -** -** If cursor P1 was previously moved via OP_DeferredSeek, complete that -** seek operation now, without further delay. If the cursor seek has -** already occurred, this instruction is a no-op. -*/ -case OP_FinishSeek: { /* ncycle */ - VdbeCursor *pC; /* The P1 index cursor */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - if( pC->deferredMoveto ){ - rc = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - } - break; -} - -/* Opcode: IdxGE P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID -** fields at the end. -** -** If the P1 index entry is greater than or equal to the key value -** then jump to P2. Otherwise fall through to the next instruction. -*/ -/* Opcode: IdxGT P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID -** fields at the end. -** -** If the P1 index entry is greater than the key value -** then jump to P2. Otherwise fall through to the next instruction. -*/ -/* Opcode: IdxLT P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY or ROWID. Compare this key value against -** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or -** ROWID on the P1 index. -** -** If the P1 index entry is less than the key value then jump to P2. -** Otherwise fall through to the next instruction. -*/ -/* Opcode: IdxLE P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY or ROWID. Compare this key value against -** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or -** ROWID on the P1 index. -** -** If the P1 index entry is less than or equal to the key value then jump -** to P2. Otherwise fall through to the next instruction. -*/ -case OP_IdxLE: /* jump, ncycle */ -case OP_IdxGT: /* jump, ncycle */ -case OP_IdxLT: /* jump, ncycle */ -case OP_IdxGE: { /* jump, ncycle */ - VdbeCursor *pC; - int res; - UnpackedRecord r; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->isOrdered ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0); - assert( pC->deferredMoveto==0 ); - assert( pOp->p4type==P4_INT32 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p4.i; - if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); - r.default_rc = -1; - }else{ - assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); - r.default_rc = 0; - } - r.aMem = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; ip3+i, &aMem[pOp->p3+i]); - } - } -#endif - - /* Inlined version of sqlite3VdbeIdxKeyCompare() */ - { - i64 nCellKey = 0; - BtCursor *pCur; - Mem m; - - assert( pC->eCurType==CURTYPE_BTREE ); - pCur = pC->uc.pCursor; - assert( sqlite3BtreeCursorIsValid(pCur) ); - nCellKey = sqlite3BtreePayloadSize(pCur); - /* nCellKey will always be between 0 and 0xffffffff because of the way - ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ - if( nCellKey<=0 || nCellKey>0x7fffffff ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); - if( rc ) goto abort_due_to_error; - res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0); - sqlite3VdbeMemReleaseMalloc(&m); - } - /* End of inlined sqlite3VdbeIdxKeyCompare() */ - - assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); - if( (pOp->opcode&1)==(OP_IdxLT&1) ){ - assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); - res = -res; - }else{ - assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); - res++; - } - VdbeBranchTaken(res>0,2); - assert( rc==SQLITE_OK ); - if( res>0 ) goto jump_to_p2; - break; -} - -/* Opcode: Destroy P1 P2 P3 * * -** -** Delete an entire database table or index whose root page in the database -** file is given by P1. -** -** The table being destroyed is in the main database file if P3==0. If -** P3==1 then the table to be destroyed is in the auxiliary database file -** that is used to store tables create using CREATE TEMPORARY TABLE. -** -** If AUTOVACUUM is enabled then it is possible that another root page -** might be moved into the newly deleted root page in order to keep all -** root pages contiguous at the beginning of the database. The former -** value of the root page that moved - its value before the move occurred - -** is stored in register P2. If no page movement was required (because the -** table being dropped was already the last one in the database) then a -** zero is stored in register P2. If AUTOVACUUM is disabled then a zero -** is stored in register P2. -** -** This opcode throws an error if there are any active reader VMs when -** it is invoked. This is done to avoid the difficulty associated with -** updating existing cursors when a root page is moved in an AUTOVACUUM -** database. This error is thrown even if the database is not an AUTOVACUUM -** db in order to avoid introducing an incompatibility between autovacuum -** and non-autovacuum modes. -** -** See also: Clear -*/ -case OP_Destroy: { /* out2 */ - int iMoved; - int iDb; - - sqlite3VdbeIncrWriteCounter(p, 0); - assert( p->readOnly==0 ); - assert( pOp->p1>1 ); - pOut = out2Prerelease(p, pOp); - pOut->flags = MEM_Null; - if( db->nVdbeRead > db->nVDestroy+1 ){ - rc = SQLITE_LOCKED; - p->errorAction = OE_Abort; - goto abort_due_to_error; - }else{ - iDb = pOp->p3; - assert( DbMaskTest(p->btreeMask, iDb) ); - iMoved = 0; /* Not needed. Only to silence a warning. */ - rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); - pOut->flags = MEM_Int; - pOut->u.i = iMoved; - if( rc ) goto abort_due_to_error; -#ifndef SQLITE_OMIT_AUTOVACUUM - if( iMoved!=0 ){ - sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1); - /* All OP_Destroy operations occur on the same btree */ - assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 ); - resetSchemaOnFault = iDb+1; - } -#endif - } - break; -} - -/* Opcode: Clear P1 P2 P3 -** -** Delete all contents of the database table or index whose root page -** in the database file is given by P1. But, unlike Destroy, do not -** remove the table or index from the database file. -** -** The table being cleared is in the main database file if P2==0. If -** P2==1 then the table to be cleared 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 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: { - i64 nChange; - - sqlite3VdbeIncrWriteCounter(p, 0); - nChange = 0; - assert( p->readOnly==0 ); - assert( DbMaskTest(p->btreeMask, pOp->p2) ); - rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange); - if( pOp->p3 ){ - p->nChange += nChange; - if( pOp->p3>0 ){ - assert( memIsValid(&aMem[pOp->p3]) ); - memAboutToChange(p, &aMem[pOp->p3]); - aMem[pOp->p3].u.i += nChange; - } - } - if( rc ) goto abort_due_to_error; - break; -} - -/* Opcode: ResetSorter P1 * * * * -** -** Delete all contents from the ephemeral table or sorter -** that is open on cursor P1. -** -** This opcode only works for cursors used for sorting and -** opened with OP_OpenEphemeral or OP_SorterOpen. -*/ -case OP_ResetSorter: { - VdbeCursor *pC; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - if( isSorter(pC) ){ - sqlite3VdbeSorterReset(db, pC->uc.pSorter); - }else{ - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->isEphemeral ); - rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor); - if( rc ) goto abort_due_to_error; - } - break; -} - -/* Opcode: CreateBtree P1 P2 P3 * * -** Synopsis: r[P2]=root iDb=P1 flags=P3 -** -** Allocate a new b-tree in the main database file if P1==0 or in the -** TEMP database file if P1==1 or in an attached database if -** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table -** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table. -** The root page number of the new b-tree is stored in register P2. -*/ -case OP_CreateBtree: { /* out2 */ - Pgno pgno; - Db *pDb; - - sqlite3VdbeIncrWriteCounter(p, 0); - pOut = out2Prerelease(p, pOp); - pgno = 0; - assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY ); - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); - assert( p->readOnly==0 ); - pDb = &db->aDb[pOp->p1]; - assert( pDb->pBt!=0 ); - rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3); - if( rc ) goto abort_due_to_error; - pOut->u.i = pgno; - break; -} - -/* Opcode: SqlExec P1 P2 * P4 * -** -** Run the SQL statement or statements specified in the P4 string. -** -** The P1 parameter is a bitmask of options: -** -** 0x0001 Disable Auth and Trace callbacks while the statements -** in P4 are running. -** -** 0x0002 Set db->nAnalysisLimit to P2 while the statements in -** P4 are running. -** -*/ -case OP_SqlExec: { - char *zErr; -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth; -#endif - u8 mTrace; - int savedAnalysisLimit; - - sqlite3VdbeIncrWriteCounter(p, 0); - db->nSqlExec++; - zErr = 0; -#ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; -#endif - mTrace = db->mTrace; - savedAnalysisLimit = db->nAnalysisLimit; - if( pOp->p1 & 0x0001 ){ -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = 0; -#endif - db->mTrace = 0; - } - if( pOp->p1 & 0x0002 ){ - db->nAnalysisLimit = pOp->p2; - } - rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); - db->nSqlExec--; -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - db->mTrace = mTrace; - db->nAnalysisLimit = savedAnalysisLimit; - if( zErr || rc ){ - sqlite3VdbeError(p, "%s", zErr); - sqlite3_free(zErr); - if( rc==SQLITE_NOMEM ) goto no_mem; - goto abort_due_to_error; - } - break; -} - -/* Opcode: ParseSchema P1 * * P4 * -** -** Read and parse all entries from the schema table of database P1 -** that match the WHERE clause P4. If P4 is a NULL pointer, then the -** entire schema for P1 is reparsed. -** -** This opcode invokes the parser to create a new virtual machine, -** then runs the new virtual machine. It is thus a re-entrant opcode. -*/ -case OP_ParseSchema: { - int iDb; - const char *zSchema; - char *zSql; - InitData initData; - - /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking - ** sqlite3InitCallback(). - */ -#ifdef SQLITE_DEBUG - for(iDb=0; iDbnDb; iDb++){ - assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); - } -#endif - - iDb = pOp->p1; - assert( iDb>=0 && iDbnDb ); - assert( DbHasProperty(db, iDb, DB_SchemaLoaded) - || db->mallocFailed - || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) ); - -#ifndef SQLITE_OMIT_ALTERTABLE - if( pOp->p4.z==0 ){ - sqlite3SchemaClear(db->aDb[iDb].pSchema); - db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5); - db->mDbFlags |= DBFLAG_SchemaChange; - p->expired = 0; - }else -#endif - { - zSchema = LEGACY_SCHEMA_TABLE; - initData.db = db; - initData.iDb = iDb; - initData.pzErrMsg = &p->zErrMsg; - initData.mInitFlags = 0; - initData.mxPage = sqlite3BtreeLastPage(db->aDb[iDb].pBt); - zSql = sqlite3MPrintf(db, - "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zDbSName, zSchema, pOp->p4.z); - if( zSql==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - assert( db->init.busy==0 ); - db->init.busy = 1; - initData.rc = SQLITE_OK; - initData.nInitRow = 0; - assert( !db->mallocFailed ); - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); - if( rc==SQLITE_OK ) rc = initData.rc; - if( rc==SQLITE_OK && initData.nInitRow==0 ){ - /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse - ** at least one SQL statement. Any less than that indicates that - ** the sqlite_schema table is corrupt. */ - rc = SQLITE_CORRUPT_BKPT; - } - sqlite3DbFreeNN(db, zSql); - db->init.busy = 0; - } - } - if( rc ){ - sqlite3ResetAllSchemasOfConnection(db); - if( rc==SQLITE_NOMEM ){ - goto no_mem; - } - goto abort_due_to_error; - } - break; -} - -#if !defined(SQLITE_OMIT_ANALYZE) -/* Opcode: LoadAnalysis P1 * * * * -** -** Read the sqlite_stat1 table for database P1 and load the content -** of that table into the internal index hash table. This will cause -** the analysis to be used when preparing all subsequent queries. -*/ -case OP_LoadAnalysis: { - assert( pOp->p1>=0 && pOp->p1nDb ); - rc = sqlite3AnalysisLoad(db, pOp->p1); - if( rc ) goto abort_due_to_error; - break; -} -#endif /* !defined(SQLITE_OMIT_ANALYZE) */ - -/* Opcode: DropTable P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the table named P4 in database P1. This is called after a table -** is dropped from disk (using the Destroy opcode) in order to keep -** the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropTable: { - sqlite3VdbeIncrWriteCounter(p, 0); - sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); - break; -} - -/* Opcode: DropIndex P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the index named P4 in database P1. This is called after an index -** is dropped from disk (using the Destroy opcode) -** in order to keep the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropIndex: { - sqlite3VdbeIncrWriteCounter(p, 0); - sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); - break; -} - -/* Opcode: DropTrigger P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the trigger named P4 in database P1. This is called after a trigger -** is dropped from disk (using the Destroy opcode) in order to keep -** the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropTrigger: { - sqlite3VdbeIncrWriteCounter(p, 0); - sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); - break; -} - - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* Opcode: IntegrityCk P1 P2 P3 P4 P5 -** -** Do an analysis of the currently open database. Store in -** register (P1+1) the text of an error message describing any problems. -** If no problems are found, store a NULL in register (P1+1). -** -** The register (P1) contains one less than the maximum number of allowed -** errors. At most reg(P1) errors will be reported. -** In other words, the analysis stops as soon as reg(P1) errors are -** seen. Reg(P1) is updated with the number of errors remaining. -** -** The root page numbers of all tables in the database are integers -** stored in P4_INTARRAY argument. -** -** If P5 is not zero, the check is done on the auxiliary database -** file, not the main database file. -** -** This opcode is used to implement the integrity_check pragma. -*/ -case OP_IntegrityCk: { - int nRoot; /* Number of tables to check. (Number of root pages.) */ - Pgno *aRoot; /* Array of rootpage numbers for tables to be checked */ - int nErr; /* Number of errors reported */ - char *z; /* Text of the error report */ - Mem *pnErr; /* Register keeping track of errors remaining */ - - assert( p->bIsReader ); - assert( pOp->p4type==P4_INTARRAY ); - nRoot = pOp->p2; - aRoot = pOp->p4.ai; - assert( nRoot>0 ); - assert( aRoot!=0 ); - assert( aRoot[0]==(Pgno)nRoot ); - assert( pOp->p1>0 && (pOp->p1+1)<=(p->nMem+1 - p->nCursor) ); - pnErr = &aMem[pOp->p1]; - assert( (pnErr->flags & MEM_Int)!=0 ); - assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); - pIn1 = &aMem[pOp->p1+1]; - assert( pOp->p5nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p5) ); - rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], - &aMem[pOp->p3], nRoot, (int)pnErr->u.i+1, &nErr, &z); - sqlite3VdbeMemSetNull(pIn1); - if( nErr==0 ){ - assert( z==0 ); - }else if( rc ){ - sqlite3_free(z); - goto abort_due_to_error; - }else{ - pnErr->u.i -= nErr-1; - sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); - } - UPDATE_MAX_BLOBSIZE(pIn1); - sqlite3VdbeChangeEncoding(pIn1, encoding); - goto check_for_interrupt; -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -/* Opcode: RowSetAdd P1 P2 * * * -** Synopsis: rowset(P1)=r[P2] -** -** Insert the integer value held by register P2 into a RowSet object -** held in register P1. -** -** An assertion fails if P2 is not an integer. -*/ -case OP_RowSetAdd: { /* in1, in2 */ - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - assert( (pIn2->flags & MEM_Int)!=0 ); - if( (pIn1->flags & MEM_Blob)==0 ){ - if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; - } - assert( sqlite3VdbeMemIsRowSet(pIn1) ); - sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i); - break; -} - -/* Opcode: RowSetRead P1 P2 P3 * * -** Synopsis: r[P3]=rowset(P1) -** -** Extract the smallest value from the RowSet object in P1 -** and put that value into register P3. -** Or, if RowSet object P1 is initially empty, leave P3 -** unchanged and jump to instruction P2. -*/ -case OP_RowSetRead: { /* jump, in1, out3 */ - i64 val; - - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) ); - if( (pIn1->flags & MEM_Blob)==0 - || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0 - ){ - /* The boolean index is empty */ - sqlite3VdbeMemSetNull(pIn1); - VdbeBranchTaken(1,2); - goto jump_to_p2_and_check_for_interrupt; - }else{ - /* A value was pulled from the index */ - VdbeBranchTaken(0,2); - sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); - } - goto check_for_interrupt; -} - -/* Opcode: RowSetTest P1 P2 P3 P4 -** Synopsis: if r[P3] in rowset(P1) goto P2 -** -** Register P3 is assumed to hold a 64-bit integer value. If register P1 -** contains a RowSet object and that RowSet object contains -** the value held in P3, jump to register P2. Otherwise, insert the -** integer in P3 into the RowSet and continue on to the -** next opcode. -** -** The RowSet object is optimized for the case where sets of integers -** are inserted in distinct phases, which each set contains no duplicates. -** Each set is identified by a unique P4 value. The first set -** must have P4==0, the final set must have P4==-1, and for all other sets -** must have P4>0. -** -** This allows optimizations: (a) when P4==0 there is no need to test -** the RowSet object for P3, as it is guaranteed not to contain it, -** (b) when P4==-1 there is no need to insert the value, as it will -** never be tested for, and (c) when a value that is part of set X is -** inserted, there is no need to search to see if the same value was -** previously inserted as part of set X (only if it was previously -** inserted as part of some other set). -*/ -case OP_RowSetTest: { /* jump, in1, in3 */ - int iSet; - int exists; - - pIn1 = &aMem[pOp->p1]; - pIn3 = &aMem[pOp->p3]; - iSet = pOp->p4.i; - assert( pIn3->flags&MEM_Int ); - - /* If there is anything other than a rowset object in memory cell P1, - ** delete it now and initialize P1 with an empty rowset - */ - if( (pIn1->flags & MEM_Blob)==0 ){ - if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; - } - assert( sqlite3VdbeMemIsRowSet(pIn1) ); - assert( pOp->p4type==P4_INT32 ); - assert( iSet==-1 || iSet>=0 ); - if( iSet ){ - exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i); - VdbeBranchTaken(exists!=0,2); - if( exists ) goto jump_to_p2; - } - if( iSet>=0 ){ - sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i); - } - break; -} - - -#ifndef SQLITE_OMIT_TRIGGER - -/* Opcode: Program P1 P2 P3 P4 P5 -** -** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). -** -** P1 contains the address of the memory cell that contains the first memory -** cell in an array of values used as arguments to the sub-program. P2 -** contains the address to jump to if the sub-program throws an IGNORE -** exception using the RAISE() function. P2 might be zero, if there is -** no possibility that an IGNORE exception will be raised. -** Register P3 contains the address -** of a memory cell in this (the parent) VM that is used to allocate the -** memory required by the sub-vdbe at runtime. -** -** P4 is a pointer to the VM containing the trigger program. -** -** If P5 is non-zero, then recursive program invocation is enabled. -*/ -case OP_Program: { /* jump0 */ - int nMem; /* Number of memory registers for sub-program */ - i64 nByte; /* Bytes of runtime space required for sub-program */ - Mem *pRt; /* Register to allocate runtime space */ - Mem *pMem; /* Used to iterate through memory cells */ - Mem *pEnd; /* Last memory cell in new array */ - VdbeFrame *pFrame; /* New vdbe frame to execute in */ - SubProgram *pProgram; /* Sub-program to execute */ - void *t; /* Token identifying trigger */ - - pProgram = pOp->p4.pProgram; - pRt = &aMem[pOp->p3]; - assert( pProgram->nOp>0 ); - - /* If the p5 flag is clear, then recursive invocation of triggers is - ** disabled for backwards compatibility (p5 is set if this sub-program - ** is really a trigger, not a foreign key action, and the flag set - ** and cleared by the "PRAGMA recursive_triggers" command is clear). - ** - ** It is recursive invocation of triggers, at the SQL level, that is - ** disabled. In some cases a single trigger may generate more than one - ** SubProgram (if the trigger may be executed with more than one different - ** ON CONFLICT algorithm). SubProgram structures associated with a - ** single trigger all have the same value for the SubProgram.token - ** variable. */ - if( pOp->p5 ){ - t = pProgram->token; - for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent); - if( pFrame ) break; - } - - if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ - rc = SQLITE_ERROR; - sqlite3VdbeError(p, "too many levels of trigger recursion"); - goto abort_due_to_error; - } - - /* Register pRt is used to store the memory required to save the state - ** of the current program, and the memory required at runtime to execute - ** the trigger program. If this trigger has been fired before, then pRt - ** is already allocated. Otherwise, it must be initialized. */ - if( (pRt->flags&MEM_Blob)==0 ){ - /* SubProgram.nMem is set to the number of memory cells used by the - ** program stored in SubProgram.aOp. As well as these, one memory - ** cell is required for each cursor used by the program. Set local - ** variable nMem (and later, VdbeFrame.nChildMem) to this value. - */ - nMem = pProgram->nMem + pProgram->nCsr; - assert( nMem>0 ); - if( pProgram->nCsr==0 ) nMem++; - nByte = ROUND8(sizeof(VdbeFrame)) - + nMem * sizeof(Mem) - + pProgram->nCsr * sizeof(VdbeCursor*) - + (7 + (i64)pProgram->nOp)/8; - pFrame = sqlite3DbMallocZero(db, nByte); - if( !pFrame ){ - goto no_mem; - } - sqlite3VdbeMemRelease(pRt); - pRt->flags = MEM_Blob|MEM_Dyn; - pRt->z = (char*)pFrame; - pRt->n = (int)nByte; - pRt->xDel = sqlite3VdbeFrameMemDel; - - pFrame->v = p; - pFrame->nChildMem = nMem; - pFrame->nChildCsr = pProgram->nCsr; - pFrame->pc = (int)(pOp - aOp); - pFrame->aMem = p->aMem; - pFrame->nMem = p->nMem; - pFrame->apCsr = p->apCsr; - pFrame->nCursor = p->nCursor; - pFrame->aOp = p->aOp; - pFrame->nOp = p->nOp; - pFrame->token = pProgram->token; -#ifdef SQLITE_DEBUG - pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; -#endif - - pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; - for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ - pMem->flags = MEM_Undefined; - pMem->db = db; - } - }else{ - pFrame = (VdbeFrame*)pRt->z; - assert( pRt->xDel==sqlite3VdbeFrameMemDel ); - assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem - || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); - assert( pProgram->nCsr==pFrame->nChildCsr ); - assert( (int)(pOp - aOp)==pFrame->pc ); - } - - p->nFrame++; - pFrame->pParent = p->pFrame; - pFrame->lastRowid = db->lastRowid; - pFrame->nChange = p->nChange; - pFrame->nDbChange = p->db->nChange; - assert( pFrame->pAuxData==0 ); - pFrame->pAuxData = p->pAuxData; - p->pAuxData = 0; - p->nChange = 0; - p->pFrame = pFrame; - p->aMem = aMem = VdbeFrameMem(pFrame); - p->nMem = pFrame->nChildMem; - p->nCursor = (u16)pFrame->nChildCsr; - p->apCsr = (VdbeCursor **)&aMem[p->nMem]; - pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr]; - memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8); - p->aOp = aOp = pProgram->aOp; - p->nOp = pProgram->nOp; -#ifdef SQLITE_DEBUG - /* Verify that second and subsequent executions of the same trigger do not - ** try to reuse register values from the first use. */ - { - int i; - for(i=0; inMem; i++){ - aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */ - MemSetTypeFlag(&aMem[i], MEM_Undefined); /* Fault if this reg is reused */ - } - } -#endif - pOp = &aOp[-1]; - goto check_for_interrupt; -} - -/* Opcode: Param P1 P2 * * * -** -** This opcode is only ever present in sub-programs called via the -** OP_Program instruction. Copy a value currently stored in a memory -** cell of the calling (parent) frame to cell P2 in the current frames -** address space. This is used by trigger programs to access the new.* -** and old.* values. -** -** The address of the cell in the parent frame is determined by adding -** the value of the P1 argument to the value of the P1 argument to the -** calling OP_Program instruction. -*/ -case OP_Param: { /* out2 */ - VdbeFrame *pFrame; - Mem *pIn; - pOut = out2Prerelease(p, pOp); - pFrame = p->pFrame; - pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; - sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); - break; -} - -#endif /* #ifndef SQLITE_OMIT_TRIGGER */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY -/* Opcode: FkCounter P1 P2 * * * -** Synopsis: fkctr[P1]+=P2 -** -** Increment a "constraint counter" by P2 (P2 may be negative or positive). -** If P1 is non-zero, the database constraint counter is incremented -** (deferred foreign key constraints). Otherwise, if P1 is zero, the -** statement counter is incremented (immediate foreign key constraints). -*/ -case OP_FkCounter: { - if( pOp->p1 ){ - db->nDeferredCons += pOp->p2; - }else{ - if( db->flags & SQLITE_DeferFKs ){ - db->nDeferredImmCons += pOp->p2; - }else{ - p->nFkConstraint += pOp->p2; - } - } - break; -} - -/* Opcode: FkIfZero P1 P2 * * * -** Synopsis: if fkctr[P1]==0 goto P2 -** -** This opcode tests if a foreign key constraint-counter is currently zero. -** If so, jump to instruction P2. Otherwise, fall through to the next -** instruction. -** -** If P1 is non-zero, then the jump is taken if the database constraint-counter -** is zero (the one that counts deferred constraint violations). If P1 is -** zero, the jump is taken if the statement constraint-counter is zero -** (immediate foreign key constraint violations). -*/ -case OP_FkIfZero: { /* jump */ - if( pOp->p1 ){ - VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); - if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; - }else{ - VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); - if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; - } - break; -} -#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ - -#ifndef SQLITE_OMIT_AUTOINCREMENT -/* Opcode: MemMax P1 P2 * * * -** Synopsis: r[P1]=max(r[P1],r[P2]) -** -** P1 is a register in the root frame of this VM (the root frame is -** different from the current frame if this instruction is being executed -** within a sub-program). Set the value of register P1 to the maximum of -** its current value and the value in register P2. -** -** This instruction throws an error if the memory cell is not initially -** an integer. -*/ -case OP_MemMax: { /* in2 */ - VdbeFrame *pFrame; - if( p->pFrame ){ - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - pIn1 = &pFrame->aMem[pOp->p1]; - }else{ - pIn1 = &aMem[pOp->p1]; - } - assert( memIsValid(pIn1) ); - sqlite3VdbeMemIntegerify(pIn1); - pIn2 = &aMem[pOp->p2]; - sqlite3VdbeMemIntegerify(pIn2); - if( pIn1->u.iu.i){ - pIn1->u.i = pIn2->u.i; - } - break; -} -#endif /* SQLITE_OMIT_AUTOINCREMENT */ - -/* Opcode: IfPos P1 P2 P3 * * -** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 -** -** Register P1 must contain an integer. -** If the value of register P1 is 1 or greater, subtract P3 from the -** value in P1 and jump to P2. -** -** If the initial value of register P1 is less than 1, then the -** value is unchanged and control passes through to the next instruction. -*/ -case OP_IfPos: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - VdbeBranchTaken( pIn1->u.i>0, 2); - if( pIn1->u.i>0 ){ - pIn1->u.i -= pOp->p3; - goto jump_to_p2; - } - break; -} - -/* Opcode: OffsetLimit P1 P2 P3 * * -** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) -** -** This opcode performs a commonly used computation associated with -** LIMIT and OFFSET processing. r[P1] holds the limit counter. r[P3] -** holds the offset counter. The opcode computes the combined value -** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] -** value computed is the total number of rows that will need to be -** visited in order to complete the query. -** -** If r[P3] is zero or negative, that means there is no OFFSET -** and r[P2] is set to be the value of the LIMIT, r[P1]. -** -** if r[P1] is zero or negative, that means there is no LIMIT -** and r[P2] is set to -1. -** -** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. -*/ -case OP_OffsetLimit: { /* in1, out2, in3 */ - i64 x; - pIn1 = &aMem[pOp->p1]; - pIn3 = &aMem[pOp->p3]; - pOut = out2Prerelease(p, pOp); - assert( pIn1->flags & MEM_Int ); - assert( pIn3->flags & MEM_Int ); - x = pIn1->u.i; - if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){ - /* If the LIMIT is less than or equal to zero, loop forever. This - ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then - ** also loop forever. This is undocumented. In fact, one could argue - ** that the loop should terminate. But assuming 1 billion iterations - ** per second (far exceeding the capabilities of any current hardware) - ** it would take nearly 300 years to actually reach the limit. So - ** looping forever is a reasonable approximation. */ - pOut->u.i = -1; - }else{ - pOut->u.i = x; - } - break; -} - -/* Opcode: IfNotZero P1 P2 * * * -** Synopsis: if r[P1]!=0 then r[P1]--, goto P2 -** -** Register P1 must contain an integer. If the content of register P1 is -** initially greater than zero, then decrement the value in register P1. -** If it is non-zero (negative or positive) and then also jump to P2. -** If register P1 is initially zero, leave it unchanged and fall through. -*/ -case OP_IfNotZero: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - VdbeBranchTaken(pIn1->u.i<0, 2); - if( pIn1->u.i ){ - if( pIn1->u.i>0 ) pIn1->u.i--; - goto jump_to_p2; - } - break; -} - -/* Opcode: DecrJumpZero P1 P2 * * * -** Synopsis: if (--r[P1])==0 goto P2 -** -** Register P1 must hold an integer. Decrement the value in P1 -** and jump to P2 if the new value is exactly zero. -*/ -case OP_DecrJumpZero: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--; - VdbeBranchTaken(pIn1->u.i==0, 2); - if( pIn1->u.i==0 ) goto jump_to_p2; - break; -} - - -/* Opcode: AggStep * P2 P3 P4 P5 -** Synopsis: accum=r[P3] step(r[P2@P5]) -** -** Execute the xStep function for an aggregate. -** The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the -** accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -*/ -/* Opcode: AggInverse * P2 P3 P4 P5 -** Synopsis: accum=r[P3] inverse(r[P2@P5]) -** -** Execute the xInverse function for an aggregate. -** The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the -** accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -*/ -/* Opcode: AggStep1 P1 P2 P3 P4 P5 -** Synopsis: accum=r[P3] step(r[P2@P5]) -** -** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an -** aggregate. The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the -** accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -** -** This opcode is initially coded as OP_AggStep0. On first evaluation, -** the FuncDef stored in P4 is converted into an sqlite3_context and -** the opcode is changed. In this way, the initialization of the -** sqlite3_context only happens once, instead of on each call to the -** step function. -*/ -case OP_AggInverse: -case OP_AggStep: { - int n; - sqlite3_context *pCtx; - u64 nAlloc; - - assert( pOp->p4type==P4_FUNCDEF ); - n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - - /* Allocate space for (a) the context object and (n-1) extra pointers - ** to append to the sqlite3_context.argv[1] array, and (b) a memory - ** cell in which to store the accumulation. Be careful that the memory - ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits. - ** - ** Note: We could avoid this by using a regular memory cell from aMem[] for - ** the accumulator, instead of allocating one here. */ - nAlloc = ROUND8P( SZ_CONTEXT(n) ); - pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem)); - if( pCtx==0 ) goto no_mem; - pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc); - assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) ); - - sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); - pCtx->pMem = 0; - pCtx->pFunc = pOp->p4.pFunc; - pCtx->iOp = (int)(pOp - aOp); - pCtx->pVdbe = p; - pCtx->skipFlag = 0; - pCtx->isError = 0; - pCtx->enc = encoding; - pCtx->argc = n; - pOp->p4type = P4_FUNCCTX; - pOp->p4.pCtx = pCtx; - - /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ - assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); - - pOp->opcode = OP_AggStep1; - /* Fall through into OP_AggStep */ - /* no break */ deliberate_fall_through -} -case OP_AggStep1: { - int i; - sqlite3_context *pCtx; - Mem *pMem; - - assert( pOp->p4type==P4_FUNCCTX ); - pCtx = pOp->p4.pCtx; - pMem = &aMem[pOp->p3]; - -#ifdef SQLITE_DEBUG - if( pOp->p1 ){ - /* This is an OP_AggInverse call. Verify that xStep has always - ** been called at least once prior to any xInverse call. */ - assert( pMem->uTemp==0x1122e0e3 ); - }else{ - /* This is an OP_AggStep call. Mark it as such. */ - pMem->uTemp = 0x1122e0e3; - } -#endif - - /* If this function is inside of a trigger, the register array in aMem[] - ** might change from one evaluation to the next. The next block of code - ** checks to see if the register array has changed, and if so it - ** reinitializes the relevant parts of the sqlite3_context object */ - if( pCtx->pMem != pMem ){ - pCtx->pMem = pMem; - for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; - } - -#ifdef SQLITE_DEBUG - for(i=0; iargc; i++){ - assert( memIsValid(pCtx->argv[i]) ); - REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); - } -#endif - - pMem->n++; - assert( pCtx->pOut->flags==MEM_Null ); - assert( pCtx->isError==0 ); - assert( pCtx->skipFlag==0 ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pOp->p1 ){ - (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv); - }else -#endif - (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ - - if( pCtx->isError ){ - if( pCtx->isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); - rc = pCtx->isError; - } - if( pCtx->skipFlag ){ - assert( pOp[-1].opcode==OP_CollSeq ); - i = pOp[-1].p1; - if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); - pCtx->skipFlag = 0; - } - sqlite3VdbeMemRelease(pCtx->pOut); - pCtx->pOut->flags = MEM_Null; - pCtx->isError = 0; - if( rc ) goto abort_due_to_error; - } - assert( pCtx->pOut->flags==MEM_Null ); - assert( pCtx->skipFlag==0 ); - break; -} - -/* Opcode: AggFinal P1 P2 * P4 * -** Synopsis: accum=r[P1] N=P2 -** -** P1 is the memory location that is the accumulator for an aggregate -** or window function. Execute the finalizer function -** for an aggregate and store the result in P1. -** -** P2 is the number of arguments that the step function takes and -** P4 is a pointer to the FuncDef for this function. The P2 -** argument is not used by this opcode. It is only there to disambiguate -** functions that can take varying numbers of arguments. The -** P4 argument is only needed for the case where -** the step function was not previously called. -*/ -/* Opcode: AggValue * P2 P3 P4 * -** Synopsis: r[P3]=value N=P2 -** -** Invoke the xValue() function and store the result in register P3. -** -** P2 is the number of arguments that the step function takes and -** P4 is a pointer to the FuncDef for this function. The P2 -** argument is not used by this opcode. It is only there to disambiguate -** functions that can take varying numbers of arguments. The -** P4 argument is only needed for the case where -** the step function was not previously called. -*/ -case OP_AggValue: -case OP_AggFinal: { - Mem *pMem; - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - assert( pOp->p3==0 || pOp->opcode==OP_AggValue ); - pMem = &aMem[pOp->p1]; - assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pOp->p3 ){ - memAboutToChange(p, &aMem[pOp->p3]); - rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); - pMem = &aMem[pOp->p3]; - }else -#endif - { - rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); - } - - if( rc ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); - goto abort_due_to_error; - } - sqlite3VdbeChangeEncoding(pMem, encoding); - UPDATE_MAX_BLOBSIZE(pMem); - REGISTER_TRACE((int)(pMem-aMem), pMem); - break; -} - -#ifndef SQLITE_OMIT_WAL -/* Opcode: Checkpoint P1 P2 P3 * * -** -** Checkpoint database P1. This is a no-op if P1 is not currently in -** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, -** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns -** SQLITE_BUSY or not, respectively. Write the number of pages in the -** WAL after the checkpoint into mem[P3+1] and the number of pages -** in the WAL that have been checkpointed after the checkpoint -** completes into mem[P3+2]. However on an error, mem[P3+1] and -** mem[P3+2] are initialized to -1. -*/ -case OP_Checkpoint: { - int i; /* Loop counter */ - int aRes[3]; /* Results */ - Mem *pMem; /* Write results here */ - - assert( p->readOnly==0 ); - aRes[0] = 0; - aRes[1] = aRes[2] = -1; - assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE - || pOp->p2==SQLITE_CHECKPOINT_FULL - || pOp->p2==SQLITE_CHECKPOINT_RESTART - || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE - ); - rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); - if( rc ){ - if( rc!=SQLITE_BUSY ) goto abort_due_to_error; - rc = SQLITE_OK; - aRes[0] = 1; - } - for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){ - sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]); - } - break; -}; -#endif - -#ifndef SQLITE_OMIT_PRAGMA -/* Opcode: JournalMode P1 P2 P3 * * -** -** Change the journal mode of database P1 to P3. P3 must be one of the -** PAGER_JOURNALMODE_XXX values. If changing between the various rollback -** modes (delete, truncate, persist, off and memory), this is a simple -** operation. No IO is required. -** -** If changing into or out of WAL mode the procedure is more complicated. -** -** Write a string containing the final journal-mode to register P2. -*/ -case OP_JournalMode: { /* out2 */ - Btree *pBt; /* Btree to change journal mode of */ - Pager *pPager; /* Pager associated with pBt */ - int eNew; /* New journal mode */ - int eOld; /* The old journal mode */ -#ifndef SQLITE_OMIT_WAL - const char *zFilename; /* Name of database file for pPager */ -#endif - - pOut = out2Prerelease(p, pOp); - eNew = pOp->p3; - assert( eNew==PAGER_JOURNALMODE_DELETE - || eNew==PAGER_JOURNALMODE_TRUNCATE - || eNew==PAGER_JOURNALMODE_PERSIST - || eNew==PAGER_JOURNALMODE_OFF - || eNew==PAGER_JOURNALMODE_MEMORY - || eNew==PAGER_JOURNALMODE_WAL - || eNew==PAGER_JOURNALMODE_QUERY - ); - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( p->readOnly==0 ); - - pBt = db->aDb[pOp->p1].pBt; - pPager = sqlite3BtreePager(pBt); - eOld = sqlite3PagerGetJournalMode(pPager); - if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; - assert( sqlite3BtreeHoldsMutex(pBt) ); - if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; - -#ifndef SQLITE_OMIT_WAL - zFilename = sqlite3PagerFilename(pPager, 1); - - /* Do not allow a transition to journal_mode=WAL for a database - ** in temporary storage or if the VFS does not support shared memory - */ - if( eNew==PAGER_JOURNALMODE_WAL - && (sqlite3Strlen30(zFilename)==0 /* Temp file */ - || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */ - ){ - eNew = eOld; - } - - if( (eNew!=eOld) - && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) - ){ - if( !db->autoCommit || db->nVdbeRead>1 ){ - rc = SQLITE_ERROR; - sqlite3VdbeError(p, - "cannot change %s wal mode from within a transaction", - (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") - ); - goto abort_due_to_error; - }else{ - - if( eOld==PAGER_JOURNALMODE_WAL ){ - /* If leaving WAL mode, close the log file. If successful, the call - ** to PagerCloseWal() checkpoints and deletes the write-ahead-log - ** file. An EXCLUSIVE lock may still be held on the database file - ** after a successful return. - */ - rc = sqlite3PagerCloseWal(pPager, db); - if( rc==SQLITE_OK ){ - sqlite3PagerSetJournalMode(pPager, eNew); - } - }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ - /* Cannot transition directly from MEMORY to WAL. Use mode OFF - ** as an intermediate */ - sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF); - } - - /* Open a transaction on the database file. Regardless of the journal - ** mode, this transaction always uses a rollback journal. - */ - assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); - } - } - } -#endif /* ifndef SQLITE_OMIT_WAL */ - - if( rc ) eNew = eOld; - eNew = sqlite3PagerSetJournalMode(pPager, eNew); - - pOut->flags = MEM_Str|MEM_Static|MEM_Term; - pOut->z = (char *)sqlite3JournalModename(eNew); - pOut->n = sqlite3Strlen30(pOut->z); - pOut->enc = SQLITE_UTF8; - sqlite3VdbeChangeEncoding(pOut, encoding); - if( rc ) goto abort_due_to_error; - break; -}; -#endif /* SQLITE_OMIT_PRAGMA */ - -#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* Opcode: Vacuum P1 P2 * * * -** -** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more -** for an attached database. The "temp" database may not be vacuumed. -** -** If P2 is not zero, then it is a register holding a string which is -** the file into which the result of vacuum should be written. When -** P2 is zero, the vacuum overwrites the original database. -*/ -case OP_Vacuum: { - assert( p->readOnly==0 ); - rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1, - pOp->p2 ? &aMem[pOp->p2] : 0); - if( rc ) goto abort_due_to_error; - break; -} -#endif - -#if !defined(SQLITE_OMIT_AUTOVACUUM) -/* Opcode: IncrVacuum P1 P2 * * * -** -** Perform a single step of the incremental vacuum procedure on -** the P1 database. If the vacuum has finished, jump to instruction -** P2. Otherwise, fall through to the next instruction. -*/ -case OP_IncrVacuum: { /* jump */ - Btree *pBt; - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); - assert( p->readOnly==0 ); - pBt = db->aDb[pOp->p1].pBt; - rc = sqlite3BtreeIncrVacuum(pBt); - VdbeBranchTaken(rc==SQLITE_DONE,2); - if( rc ){ - if( rc!=SQLITE_DONE ) goto abort_due_to_error; - rc = SQLITE_OK; - goto jump_to_p2; - } - break; -} -#endif - -/* Opcode: Expire P1 P2 * * * -** -** Cause precompiled statements to expire. When an expired statement -** is executed using sqlite3_step() it will either automatically -** reprepare itself (if it was originally created using sqlite3_prepare_v2()) -** or it will fail with SQLITE_SCHEMA. -** -** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, -** then only the currently executing statement is expired. -** -** If P2 is 0, then SQL statements are expired immediately. If P2 is 1, -** then running SQL statements are allowed to continue to run to completion. -** The P2==1 case occurs when a CREATE INDEX or similar schema change happens -** that might help the statement run faster but which does not affect the -** correctness of operation. -*/ -case OP_Expire: { - assert( pOp->p2==0 || pOp->p2==1 ); - if( !pOp->p1 ){ - sqlite3ExpirePreparedStatements(db, pOp->p2); - }else{ - p->expired = pOp->p2+1; - } - break; -} - -/* Opcode: CursorLock P1 * * * * -** -** Lock the btree to which cursor P1 is pointing so that the btree cannot be -** written by an other cursor. -*/ -case OP_CursorLock: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorPin(pC->uc.pCursor); - break; -} - -/* Opcode: CursorUnlock P1 * * * * -** -** Unlock the btree to which cursor P1 is pointing so that it can be -** written by other cursors. -*/ -case OP_CursorUnlock: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorUnpin(pC->uc.pCursor); - break; -} - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* Opcode: TableLock P1 P2 P3 P4 * -** Synopsis: iDb=P1 root=P2 write=P3 -** -** Obtain a lock on a particular table. This instruction is only used when -** the shared-cache feature is enabled. -** -** P1 is the index of the database in sqlite3.aDb[] of the database -** on which the lock is acquired. A readlock is obtained if P3==0 or -** a write lock if P3==1. -** -** P2 contains the root-page of the table to lock. -** -** P4 contains a pointer to the name of the table being locked. This is only -** used to generate an error message if the lock cannot be obtained. -*/ -case OP_TableLock: { - u8 isWriteLock = (u8)pOp->p3; - if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){ - int p1 = pOp->p1; - assert( p1>=0 && p1nDb ); - assert( DbMaskTest(p->btreeMask, p1) ); - assert( isWriteLock==0 || isWriteLock==1 ); - rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); - if( rc ){ - if( (rc&0xFF)==SQLITE_LOCKED ){ - const char *z = pOp->p4.z; - sqlite3VdbeError(p, "database table is locked: %s", z); - } - goto abort_due_to_error; - } - } - break; -} -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VBegin * * * P4 * -** -** P4 may be a pointer to an sqlite3_vtab structure. If so, call the -** xBegin method for that table. -** -** Also, whether or not P4 is set, check that this is not being called from -** within a callback to a virtual table xSync() method. If it is, the error -** code will be set to SQLITE_LOCKED. -*/ -case OP_VBegin: { - VTable *pVTab; - pVTab = pOp->p4.pVtab; - rc = sqlite3VtabBegin(db, pVTab); - if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); - if( rc ) goto abort_due_to_error; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCreate P1 P2 * * * -** -** P2 is a register that holds the name of a virtual table in database -** P1. Call the xCreate method for that table. -*/ -case OP_VCreate: { - Mem sMem; /* For storing the record being decoded */ - const char *zTab; /* Name of the virtual table */ - - memset(&sMem, 0, sizeof(sMem)); - sMem.db = db; - /* Because P2 is always a static string, it is impossible for the - ** sqlite3VdbeMemCopy() to fail */ - assert( (aMem[pOp->p2].flags & MEM_Str)!=0 ); - assert( (aMem[pOp->p2].flags & MEM_Static)!=0 ); - rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]); - assert( rc==SQLITE_OK ); - zTab = (const char*)sqlite3_value_text(&sMem); - assert( zTab || db->mallocFailed ); - if( zTab ){ - rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); - } - sqlite3VdbeMemRelease(&sMem); - if( rc ) goto abort_due_to_error; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VDestroy P1 * * P4 * -** -** P4 is the name of a virtual table in database P1. Call the xDestroy method -** of that table. -*/ -case OP_VDestroy: { - db->nVDestroy++; - rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); - db->nVDestroy--; - assert( p->errorAction==OE_Abort && p->usesStmtJournal ); - if( rc ) goto abort_due_to_error; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VOpen P1 * * P4 * -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** P1 is a cursor number. This opcode opens a cursor to the virtual -** table and stores that cursor in P1. -*/ -case OP_VOpen: { /* ncycle */ - VdbeCursor *pCur; - sqlite3_vtab_cursor *pVCur; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - - assert( p->bIsReader ); - pCur = 0; - pVCur = 0; - pVtab = pOp->p4.pVtab->pVtab; - if( pVtab==0 || NEVER(pVtab->pModule==0) ){ - rc = SQLITE_LOCKED; - goto abort_due_to_error; - } - pModule = pVtab->pModule; - rc = pModule->xOpen(pVtab, &pVCur); - sqlite3VtabImportErrmsg(p, pVtab); - if( rc ) goto abort_due_to_error; - - /* Initialize sqlite3_vtab_cursor base class */ - pVCur->pVtab = pVtab; - - /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB); - if( pCur ){ - pCur->uc.pVCur = pVCur; - pVtab->nRef++; - }else{ - assert( db->mallocFailed ); - pModule->xClose(pVCur); - goto no_mem; - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCheck P1 P2 P3 P4 * -** -** P4 is a pointer to a Table object that is a virtual table in schema P1 -** that supports the xIntegrity() method. This opcode runs the xIntegrity() -** method for that virtual table, using P3 as the integer argument. If -** an error is reported back, the table name is prepended to the error -** message and that message is stored in P2. If no errors are seen, -** register P2 is set to NULL. -*/ -case OP_VCheck: { /* out2 */ - Table *pTab; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - char *zErr = 0; - - pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */ - assert( pOp->p4type==P4_TABLEREF ); - pTab = pOp->p4.pTab; - assert( pTab!=0 ); - assert( pTab->nTabRef>0 ); - assert( IsVirtual(pTab) ); - if( pTab->u.vtab.p==0 ) break; - pVtab = pTab->u.vtab.p->pVtab; - assert( pVtab!=0 ); - pModule = pVtab->pModule; - assert( pModule!=0 ); - assert( pModule->iVersion>=4 ); - assert( pModule->xIntegrity!=0 ); - sqlite3VtabLock(pTab->u.vtab.p); - assert( pOp->p1>=0 && pOp->p1nDb ); - rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName, - pOp->p3, &zErr); - sqlite3VtabUnlock(pTab->u.vtab.p); - if( rc ){ - sqlite3_free(zErr); - goto abort_due_to_error; - } - if( zErr ){ - sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free); - } - break; -} -#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 sqlite3_vtab_in_first() and -** 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 -** sqlite3_vtab_in_first() and sqlite3_vtab_in_next(). -*/ -case OP_VInitIn: { /* out2, ncycle */ - VdbeCursor *pC; /* The cursor containing the RHS values */ - ValueList *pRhs; /* New ValueList object to put in reg[P2] */ - - pC = p->apCsr[pOp->p1]; - pRhs = 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; - sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree); - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VFilter P1 P2 P3 P4 * -** Synopsis: iplan=r[P3] zplan='P4' -** -** P1 is a cursor opened using VOpen. P2 is an address to jump to if -** the filtered result set is empty. -** -** P4 is either NULL or a string that was generated by the xBestIndex -** method of the module. The interpretation of the P4 string is left -** to the module implementation. -** -** This opcode invokes the xFilter method on the virtual table specified -** by P1. The integer query plan parameter to xFilter is stored in register -** P3. Register P3+1 stores the argc parameter to be passed to the -** xFilter method. Registers P3+2..P3+1+argc are the argc -** additional parameters which are passed to -** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. -** -** A jump is made to P2 if the result set after filtering would be empty. -*/ -case OP_VFilter: { /* jump, ncycle */ - int nArg; - int iQuery; - const sqlite3_module *pModule; - Mem *pQuery; - Mem *pArgc; - sqlite3_vtab_cursor *pVCur; - sqlite3_vtab *pVtab; - VdbeCursor *pCur; - int res; - int i; - Mem **apArg; - - pQuery = &aMem[pOp->p3]; - pArgc = &pQuery[1]; - 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; - pModule = pVtab->pModule; - - /* Grab the index number and argc parameters */ - assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); - nArg = (int)pArgc->u.i; - iQuery = (int)pQuery->u.i; - - /* Invoke the xFilter method */ - apArg = p->apArg; - assert( nArg<=p->napArg ); - for(i = 0; ixFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg); - sqlite3VtabImportErrmsg(p, pVtab); - if( rc ) goto abort_due_to_error; - res = pModule->xEof(pVCur); - pCur->nullRow = 0; - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VColumn P1 P2 P3 * P5 -** Synopsis: r[P3]=vcolumn(P2) -** -** Store in register P3 the value of the P2-th column of -** the current row of the virtual-table of cursor P1. -** -** If the VColumn opcode is being used to fetch the value of -** an unchanging column during an UPDATE operation, then the P5 -** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange() -** function to return true inside the xColumn method of the virtual -** table implementation. The P5 column might also contain other -** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are -** unused by OP_VColumn. -*/ -case OP_VColumn: { /* ncycle */ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - Mem *pDest; - sqlite3_context sContext; - FuncDef nullFunc; - - VdbeCursor *pCur = p->apCsr[pOp->p1]; - assert( pCur!=0 ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); - if( pCur->nullRow ){ - 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; - nullFunc.pUserData = 0; - nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE; - sContext.pFunc = &nullFunc; - assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 ); - if( pOp->p5 & OPFLAG_NOCHNG ){ - sqlite3VdbeMemSetNull(pDest); - pDest->flags = MEM_Null|MEM_Zero; - pDest->u.nZero = 0; - }else{ - MemSetTypeFlag(pDest, MEM_Null); - } - rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); - sqlite3VtabImportErrmsg(p, pVtab); - if( sContext.isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest)); - rc = sContext.isError; - } - sqlite3VdbeChangeEncoding(pDest, encoding); - REGISTER_TRACE(pOp->p3, pDest); - UPDATE_MAX_BLOBSIZE(pDest); - - if( rc ) goto abort_due_to_error; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VNext P1 P2 * * * -** -** Advance virtual table P1 to the next row in its result set and -** jump to instruction P2. Or, if the virtual table has reached -** the end of its result set, then fall through to the next instruction. -*/ -case OP_VNext: { /* jump, ncycle */ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - int res; - VdbeCursor *pCur; - - pCur = p->apCsr[pOp->p1]; - assert( pCur!=0 ); - assert( pCur->eCurType==CURTYPE_VTAB ); - if( pCur->nullRow ){ - break; - } - pVtab = pCur->uc.pVCur->pVtab; - pModule = pVtab->pModule; - assert( pModule->xNext ); - - /* Invoke the xNext() method of the module. There is no way for the - ** underlying implementation to return an error if one occurs during - ** xNext(). Instead, if an error occurs, true is returned (indicating that - ** data is available) and the error code returned when xColumn or - ** some other method is next invoked on the save virtual table cursor. - */ - rc = pModule->xNext(pCur->uc.pVCur); - sqlite3VtabImportErrmsg(p, pVtab); - if( rc ) goto abort_due_to_error; - res = pModule->xEof(pCur->uc.pVCur); - VdbeBranchTaken(!res,2); - if( !res ){ - /* If there is data, jump to P2 */ - goto jump_to_p2_and_check_for_interrupt; - } - goto check_for_interrupt; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VRename P1 * * P4 * -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** This opcode invokes the corresponding xRename method. The value -** in register P1 is passed as the zName argument to the xRename method. -*/ -case OP_VRename: { - sqlite3_vtab *pVtab; - Mem *pName; - int isLegacy; - - isLegacy = (db->flags & SQLITE_LegacyAlter); - db->flags |= SQLITE_LegacyAlter; - pVtab = pOp->p4.pVtab->pVtab; - pName = &aMem[pOp->p1]; - assert( pVtab->pModule->xRename ); - assert( memIsValid(pName) ); - assert( p->readOnly==0 ); - REGISTER_TRACE(pOp->p1, pName); - assert( pName->flags & MEM_Str ); - testcase( pName->enc==SQLITE_UTF8 ); - testcase( pName->enc==SQLITE_UTF16BE ); - testcase( pName->enc==SQLITE_UTF16LE ); - rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); - if( rc ) goto abort_due_to_error; - rc = pVtab->pModule->xRename(pVtab, pName->z); - if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter; - sqlite3VtabImportErrmsg(p, pVtab); - p->expired = 0; - if( rc ) goto abort_due_to_error; - break; -} -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VUpdate P1 P2 P3 P4 P5 -** Synopsis: data=r[P3@P2] -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** This opcode invokes the corresponding xUpdate method. P2 values -** are contiguous memory cells starting at P3 to pass to the xUpdate -** invocation. The value in register (P3+P2-1) corresponds to the -** p2th element of the argv array passed to xUpdate. -** -** The xUpdate method will do a DELETE or an INSERT or both. -** The argv[0] element (which corresponds to memory cell P3) -** is the rowid of a row to delete. If argv[0] is NULL then no -** deletion occurs. The argv[1] element is the rowid of the new -** row. This can be NULL to have the virtual table select the new -** rowid for itself. The subsequent elements in the array are -** the values of columns in the new row. -** -** If P2==1 then no insert is performed. argv[0] is the rowid of -** a row to delete. -** -** P1 is a boolean flag. If it is set to true and the xUpdate call -** is successful, then the value returned by sqlite3_last_insert_rowid() -** is set to the value of the rowid for the row just inserted. -** -** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to -** apply in the case of a constraint failure on an insert or update. -*/ -case OP_VUpdate: { - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - int nArg; - int i; - sqlite_int64 rowid = 0; - Mem **apArg; - Mem *pX; - - assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback - || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace - ); - assert( p->readOnly==0 ); - if( db->mallocFailed ) goto no_mem; - sqlite3VdbeIncrWriteCounter(p, 0); - pVtab = pOp->p4.pVtab->pVtab; - if( pVtab==0 || NEVER(pVtab->pModule==0) ){ - rc = SQLITE_LOCKED; - goto abort_due_to_error; - } - pModule = pVtab->pModule; - nArg = pOp->p2; - assert( pOp->p4type==P4_VTAB ); - if( ALWAYS(pModule->xUpdate) ){ - u8 vtabOnConflict = db->vtabOnConflict; - apArg = p->apArg; - pX = &aMem[pOp->p3]; - assert( nArg<=p->napArg ); - for(i=0; ivtabOnConflict = pOp->p5; - rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); - db->vtabOnConflict = vtabOnConflict; - sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK && pOp->p1 ){ - assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); - db->lastRowid = rowid; - } - if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ - if( pOp->p5==OE_Ignore ){ - rc = SQLITE_OK; - }else{ - p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); - } - }else{ - p->nChange++; - } - if( rc ) goto abort_due_to_error; - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* Opcode: Pagecount P1 P2 * * * -** -** Write the current number of pages in database P1 to memory cell P2. -*/ -case OP_Pagecount: { /* out2 */ - pOut = out2Prerelease(p, pOp); - pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); - break; -} -#endif - - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* Opcode: MaxPgcnt P1 P2 P3 * * -** -** Try to set the maximum page count for database P1 to the value in P3. -** Do not let the maximum page count fall below the current page count and -** do not change the maximum page count value if P3==0. -** -** Store the maximum page count after the change in register P2. -*/ -case OP_MaxPgcnt: { /* out2 */ - unsigned int newMax; - Btree *pBt; - - pOut = out2Prerelease(p, pOp); - pBt = db->aDb[pOp->p1].pBt; - newMax = 0; - if( pOp->p3 ){ - newMax = sqlite3BtreeLastPage(pBt); - if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3; - } - pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); - break; -} -#endif - -/* Opcode: Function P1 P2 P3 P4 * -** Synopsis: r[P3]=func(r[P2@NP]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with arguments taken -** from register P2 and successors. The number of arguments is in -** the sqlite3_context object that P4 points to. -** The result of the function is stored -** in register P3. Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** See also: AggStep, AggFinal, PureFunc -*/ -/* Opcode: PureFunc P1 P2 P3 P4 * -** Synopsis: r[P3]=func(r[P2@NP]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with arguments taken -** from register P2 and successors. The number of arguments is in -** the sqlite3_context object that P4 points to. -** The result of the function is stored -** in register P3. Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** This opcode works exactly like OP_Function. The only difference is in -** its name. This opcode is used in places where the function must be -** purely non-deterministic. Some built-in date/time functions can be -** either deterministic of non-deterministic, depending on their arguments. -** When those function are used in a non-deterministic way, they will check -** to see if they were called using OP_PureFunc instead of OP_Function, and -** if they were, they throw an error. -** -** See also: AggStep, AggFinal, Function -*/ -case OP_PureFunc: /* group */ -case OP_Function: { /* group */ - int i; - sqlite3_context *pCtx; - - assert( pOp->p4type==P4_FUNCCTX ); - pCtx = pOp->p4.pCtx; - - /* If this function is inside of a trigger, the register array in aMem[] - ** might change from one evaluation to the next. The next block of code - ** checks to see if the register array has changed, and if so it - ** reinitializes the relevant parts of the sqlite3_context object */ - pOut = &aMem[pOp->p3]; - 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 ); - - memAboutToChange(p, pOut); -#ifdef SQLITE_DEBUG - for(i=0; iargc; i++){ - assert( memIsValid(pCtx->argv[i]) ); - REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); - } -#endif - MemSetTypeFlag(pOut, MEM_Null); - assert( pCtx->isError==0 ); - (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ - - /* If the function returned an error, throw an exception */ - if( pCtx->isError ){ - if( pCtx->isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); - rc = pCtx->isError; - } - sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); - pCtx->isError = 0; - if( rc ) goto abort_due_to_error; - } - - assert( (pOut->flags&MEM_Str)==0 - || pOut->enc==encoding - || db->mallocFailed ); - assert( !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: GetSubtype P1 P2 * * * -** Synopsis: r[P2] = r[P1].subtype -** -** Extract the subtype value from register P1 and write that subtype -** into register P2. If P1 has no subtype, then P1 gets a NULL. -*/ -case OP_GetSubtype: { /* in1 out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Subtype ){ - sqlite3VdbeMemSetInt64(pOut, pIn1->eSubtype); - }else{ - sqlite3VdbeMemSetNull(pOut); - } - break; -} - -/* Opcode: SetSubtype P1 P2 * * * -** Synopsis: r[P2].subtype = r[P1] -** -** Set the subtype value of register P2 to the integer from register P1. -** If P1 is NULL, clear the subtype from p2. -*/ -case OP_SetSubtype: { /* in1 out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Null ){ - pOut->flags &= ~MEM_Subtype; - }else{ - assert( pIn1->flags & MEM_Int ); - pOut->flags |= MEM_Subtype; - pOut->eSubtype = (u8)(pIn1->u.i & 0xff); - } - 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; iip3+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*8); - 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; iip3+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*8); - 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 -** enabled. -** -** Operand P1 must be 0x7fffffff and P2 must positive. -*/ -/* Opcode: Init P1 P2 P3 P4 * -** Synopsis: Start at P2 -** -** Programs contain a single instance of this opcode as the very first -** opcode. -** -** If tracing is enabled (by the sqlite3_trace()) interface, then -** the UTF-8 string contained in P4 is emitted on the trace callback. -** Or if P4 is blank, use the string returned by sqlite3_sql(). -** -** If P2 is not zero, jump to instruction P2. -** -** Increment the value of P1 so that OP_Once opcodes will jump the -** first time they are evaluated for this run. -** -** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT -** error is encountered. -*/ -case OP_Trace: -case OP_Init: { /* jump0 */ - int i; -#ifndef SQLITE_OMIT_TRACE - char *zTrace; -#endif - - /* If the P4 argument is not NULL, then it must be an SQL comment string. - ** The "--" string is broken up to prevent false-positives with srcck1.c. - ** - ** This assert() provides evidence for: - ** EVIDENCE-OF: R-50676-09860 The callback can compute the same text that - ** would have been returned by the legacy sqlite3_trace() interface by - ** using the X argument when X begins with "--" and invoking - ** sqlite3_expanded_sql(P) otherwise. - */ - assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); - - /* OP_Init is always instruction 0 */ - assert( pOp==p->aOp || pOp->opcode==OP_Trace ); - -#ifndef SQLITE_OMIT_TRACE - if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 - && p->minWriteFileFormat!=254 /* tag-20220401a */ - && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 - ){ -#ifndef SQLITE_OMIT_DEPRECATED - if( db->mTrace & SQLITE_TRACE_LEGACY ){ - char *z = sqlite3VdbeExpandSql(p, zTrace); - db->trace.xLegacy(db->pTraceArg, z); - sqlite3_free(z); - }else -#endif - if( db->nVdbeExec>1 ){ - char *z = sqlite3MPrintf(db, "-- %s", zTrace); - (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, z); - sqlite3DbFree(db, z); - }else{ - (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); - } - } -#ifdef SQLITE_USE_FCNTL_TRACE - zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); - if( zTrace ){ - int j; - for(j=0; jnDb; j++){ - if( DbMaskTest(p->btreeMask, j)==0 ) continue; - sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace); - } - } -#endif /* SQLITE_USE_FCNTL_TRACE */ -#ifdef SQLITE_DEBUG - if( (db->flags & SQLITE_SqlTrace)!=0 - && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 - ){ - sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); - } -#endif /* SQLITE_DEBUG */ -#endif /* SQLITE_OMIT_TRACE */ - assert( pOp->p2>0 ); - if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ - if( pOp->opcode==OP_Trace ) break; - for(i=1; inOp; i++){ - if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; - } - pOp->p1 = 0; - } - pOp->p1++; - p->aCounter[SQLITE_STMTSTATUS_RUN]++; - goto jump_to_p2; -} - -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* Opcode: CursorHint P1 * * P4 * -** -** Provide a hint to cursor P1 that it only needs to return rows that -** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer -** to values currently held in registers. TK_COLUMN terms in the P4 -** expression refer to columns in the b-tree to which cursor P1 is pointing. -*/ -case OP_CursorHint: { - VdbeCursor *pC; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p4type==P4_EXPR ); - pC = p->apCsr[pOp->p1]; - if( pC ){ - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE, - pOp->p4.pExpr, aMem); - } - break; -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ - -#ifdef SQLITE_DEBUG -/* Opcode: Abortable * * * * * -** -** Verify that an Abort can happen. Assert if an Abort at this point -** might cause database corruption. This opcode only appears in debugging -** builds. -** -** An Abort is safe if either there have been no writes, or if there is -** an active statement journal. -*/ -case OP_Abortable: { - sqlite3VdbeAssertAbortable(p); - break; -} -#endif - -#ifdef SQLITE_DEBUG -/* Opcode: ReleaseReg P1 P2 P3 * P5 -** Synopsis: release r[P1@P2] mask P3 -** -** Release registers from service. Any content that was in the -** the registers is unreliable after this opcode completes. -** -** The registers released will be the P2 registers starting at P1, -** except if bit ii of P3 set, then do not release register P1+ii. -** In other words, P3 is a mask of registers to preserve. -** -** Releasing a register clears the Mem.pScopyFrom pointer. That means -** that if the content of the released register was set using OP_SCopy, -** a change to the value of the source register for the OP_SCopy will no longer -** generate an assertion fault in sqlite3VdbeMemAboutToChange(). -** -** If P5 is set, then all released registers have their type set -** to MEM_Undefined so that any subsequent attempt to read the released -** register (before it is reinitialized) will generate an assertion fault. -** -** P5 ought to be set on every call to this opcode. -** However, there are places in the code generator will release registers -** before their are used, under the (valid) assumption that the registers -** will not be reallocated for some other purpose before they are used and -** hence are safe to release. -** -** This opcode is only available in testing and debugging builds. It is -** not generated for release builds. The purpose of this opcode is to help -** validate the generated bytecode. This opcode does not actually contribute -** to computing an answer. -*/ -case OP_ReleaseReg: { - Mem *pMem; - int i; - u32 constMask; - assert( pOp->p1>0 ); - assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); - pMem = &aMem[pOp->p1]; - constMask = pOp->p3; - for(i=0; ip2; i++, pMem++){ - if( i>=32 || (constMask & MASKBIT32(i))==0 ){ - pMem->pScopyFrom = 0; - if( i<32 && pOp->p5 ) MemSetTypeFlag(pMem, MEM_Undefined); - } - } - break; -} -#endif - -/* Opcode: Noop * * * * * -** -** Do nothing. Continue downward to the next opcode. -*/ -/* Opcode: Explain P1 P2 P3 P4 * -** -** This is the same as OP_Noop during normal query execution. The -** purpose of this opcode is to hold information about the query -** plan for the purpose of EXPLAIN QUERY PLAN output. -** -** The P4 value is human-readable text that describes the query plan -** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1". -** -** The P1 value is the ID of the current element and P2 is the parent -** element for the case of nested query plan elements. If P2 is zero -** then this element is a top-level element. -** -** For loop elements, P3 is the estimated code of each invocation of this -** element. -** -** As with all opcodes, the meanings of the parameters for OP_Explain -** are subject to change from one release to the next. Applications -** should not attempt to interpret or use any of the information -** contained in the OP_Explain opcode. The information provided by this -** opcode is intended for testing and debugging use only. -*/ -default: { /* This is really OP_Noop, OP_Explain */ - assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); - - break; -} - -/***************************************************************************** -** The cases of the switch statement above this line should all be indented -** by 6 spaces. But the left-most 6 spaces have been removed to improve the -** readability. From this point on down, the normal indentation rules are -** restored. -*****************************************************************************/ - } - -#if defined(VDBE_PROFILE) - *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); - pnCycle = 0; -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pnCycle ){ - *pnCycle += sqlite3Hwtime(); - pnCycle = 0; - } -#endif - - /* The following code adds nothing to the actual functionality - ** of the program. It is only here for testing and debugging. - ** On the other hand, it does burn CPU cycles every time through - ** the evaluator loop. So we can leave it out when NDEBUG is defined. - */ -#ifndef NDEBUG - assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] ); - -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeTrace ){ - u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode]; - if( rc!=0 ) printf("rc=%d\n",rc); - if( opProperty & (OPFLG_OUT2) ){ - registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); - } - if( opProperty & OPFLG_OUT3 ){ - registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); - } - if( opProperty==0xff ){ - /* Never happens. This code exists to avoid a harmless linkage - ** warning about sqlite3VdbeRegisterDump() being defined but not - ** used. */ - sqlite3VdbeRegisterDump(p); - } - } -#endif /* SQLITE_DEBUG */ -#endif /* NDEBUG */ - } /* The end of the for(;;) loop the loops through opcodes */ - - /* If we reach this point, it means that execution is finished with - ** an error of some kind. - */ -abort_due_to_error: - if( db->mallocFailed ){ - rc = SQLITE_NOMEM_BKPT; - }else if( rc==SQLITE_IOERR_CORRUPTFS ){ - 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 ){ - sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); - } - p->rc = rc; - sqlite3SystemError(db, rc); - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(rc, "statement aborts at %d: %s; [%s]", - (int)(pOp - aOp), p->zErrMsg, p->zSql); - if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); - if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); - if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ - db->flags |= SQLITE_CorruptRdOnly; - } - rc = SQLITE_ERROR; - if( resetSchemaOnFault>0 ){ - sqlite3ResetOneSchema(db, resetSchemaOnFault-1); - } - - /* This is the only way out of this procedure. We have to - ** release the mutexes on btrees that were acquired at the - ** top. */ -vdbe_return: -#if defined(VDBE_PROFILE) - if( pnCycle ){ - *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); - pnCycle = 0; - } -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pnCycle ){ - *pnCycle += sqlite3Hwtime(); - pnCycle = 0; - } -#endif - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ - nProgressLimit += db->nProgressOps; - if( db->xProgress(db->pProgressArg) ){ - nProgressLimit = LARGEST_UINT64; - rc = SQLITE_INTERRUPT; - goto abort_due_to_error; - } - } -#endif - p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; - if( DbMaskNonZero(p->lockMask) ){ - sqlite3VdbeLeave(p); - } - assert( rc!=SQLITE_OK || nExtraDelete==0 - || sqlite3_strlike("DELETE%",p->zSql,0)!=0 - ); - return rc; - - /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH - ** is encountered. - */ -too_big: - sqlite3VdbeError(p, "string or blob too big"); - rc = SQLITE_TOOBIG; - goto abort_due_to_error; - - /* Jump to here if a malloc() fails. - */ -no_mem: - sqlite3OomFault(db); - sqlite3VdbeError(p, "out of memory"); - rc = SQLITE_NOMEM_BKPT; - goto abort_due_to_error; - - /* Jump to here if the sqlite3_interrupt() API sets the interrupt - ** flag. - */ -abort_due_to_interrupt: - assert( AtomicLoad(&db->u1.isInterrupted) ); - rc = SQLITE_INTERRUPT; - goto abort_due_to_error; -} - - -/************** End of vdbe.c ************************************************/ -/************** Begin file vdbeblob.c ****************************************/ -/* -** 2007 May 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to implement incremental BLOB I/O. -*/ - -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -#ifndef SQLITE_OMIT_INCRBLOB - -/* -** Valid sqlite3_blob* handles point to Incrblob structures. -*/ -typedef struct Incrblob Incrblob; -struct Incrblob { - int nByte; /* Size of open blob, in bytes */ - int iOffset; /* Byte offset of blob in cursor data */ - u16 iCol; /* Table column this handle is open on */ - BtCursor *pCsr; /* Cursor pointing at blob row */ - sqlite3_stmt *pStmt; /* Statement holding cursor open */ - sqlite3 *db; /* The associated database */ - char *zDb; /* Database name */ - Table *pTab; /* Table object */ -}; - - -/* -** This function is used by both blob_open() and blob_reopen(). It seeks -** the b-tree cursor associated with blob handle p to point to row iRow. -** If successful, SQLITE_OK is returned and subsequent calls to -** sqlite3_blob_read() or sqlite3_blob_write() access the specified row. -** -** If an error occurs, or if the specified row does not exist or does not -** contain a value of type TEXT or BLOB in the column nominated when the -** blob handle was opened, then an error code is returned and *pzErr may -** be set to point to a buffer containing an error message. It is the -** responsibility of the caller to free the error message buffer using -** sqlite3DbFree(). -** -** If an error does occur, then the b-tree cursor is closed. All subsequent -** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will -** immediately return SQLITE_ABORT. -*/ -static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ - int rc; /* Error code */ - char *zErr = 0; /* Error message */ - Vdbe *v = (Vdbe *)p->pStmt; - - /* Set the value of register r[1] in the SQL statement to integer iRow. - ** This is done directly as a performance optimization - */ - sqlite3VdbeMemSetInt64(&v->aMem[1], iRow); - - /* If the statement has been run before (and is paused at the OP_ResultRow) - ** then back it up to the point where it does the OP_NotExists. This could - ** have been down with an extra OP_Goto, but simply setting the program - ** counter is faster. */ - if( v->pc>4 ){ - v->pc = 4; - assert( v->aOp[v->pc].opcode==OP_NotExists ); - rc = sqlite3VdbeExec(v); - }else{ - rc = sqlite3_step(p->pStmt); - } - if( rc==SQLITE_ROW ){ - VdbeCursor *pC = v->apCsr[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 ){ - zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", - type==0?"null": type==7?"real": "integer" - ); - rc = SQLITE_ERROR; - sqlite3_finalize(p->pStmt); - p->pStmt = 0; - }else{ - p->iOffset = pC->aType[p->iCol + pC->nField]; - p->nByte = sqlite3VdbeSerialTypeLen(type); - p->pCsr = pC->uc.pCursor; - sqlite3BtreeIncrblobCursor(p->pCsr); - } - } - - if( rc==SQLITE_ROW ){ - rc = SQLITE_OK; - }else if( p->pStmt ){ - rc = sqlite3_finalize(p->pStmt); - p->pStmt = 0; - if( rc==SQLITE_OK ){ - zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow); - rc = SQLITE_ERROR; - }else{ - zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db)); - } - } - - assert( rc!=SQLITE_OK || zErr==0 ); - assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE ); - - *pzErr = zErr; - return rc; -} - -/* -** Open a blob handle. -*/ -SQLITE_API int sqlite3_blob_open( - sqlite3* db, /* The database connection */ - const char *zDb, /* The attached database containing the blob */ - const char *zTable, /* The table containing the blob */ - const char *zColumn, /* The column containing the blob */ - sqlite_int64 iRow, /* The row containing the glob */ - int wrFlag, /* True -> read/write access, false -> read-only */ - sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */ -){ - int nAttempt = 0; - int iCol; /* Index of zColumn in row-record */ - int rc = SQLITE_OK; - char *zErr = 0; - Table *pTab; - Incrblob *pBlob = 0; - int iDb; - Parse sParse; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppBlob==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - *ppBlob = 0; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTable==0 || zColumn==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ - - sqlite3_mutex_enter(db->mutex); - - pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); - while(1){ - sqlite3ParseObjectInit(&sParse,db); - if( !pBlob ) goto blob_open_out; - sqlite3DbFree(db, zErr); - zErr = 0; - - sqlite3BtreeEnterAll(db); - pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); - if( pTab && IsVirtual(pTab) ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); - } - if( pTab && !HasRowid(pTab) ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); - } - if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s", - zTable); - } -#ifndef SQLITE_OMIT_VIEW - if( pTab && IsView(pTab) ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); - } -#endif - if( pTab==0 - || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 && - sqlite3OpenTempDatabase(&sParse)) - ){ - if( sParse.zErrMsg ){ - sqlite3DbFree(db, zErr); - zErr = sParse.zErrMsg; - sParse.zErrMsg = 0; - } - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - pBlob->pTab = pTab; - pBlob->zDb = db->aDb[iDb].zDbSName; - - /* Now search pTab for the exact column. */ - iCol = sqlite3ColumnIndex(pTab, zColumn); - if( iCol<0 ){ - sqlite3DbFree(db, zErr); - zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - - /* If the value is being opened for writing, check that the - ** column is not indexed, and that it is not part of a foreign key. - */ - if( wrFlag ){ - const char *zFault = 0; - Index *pIdx; -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( db->flags&SQLITE_ForeignKeys ){ - /* Check that the column is not part of an FK child key definition. It - ** is not necessary to check if it is part of a parent key, as parent - ** key columns must be indexed. The check below will pick up this - ** case. */ - FKey *pFKey; - assert( IsOrdinaryTable(pTab) ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - int j; - for(j=0; jnCol; j++){ - if( pFKey->aCol[j].iFrom==iCol ){ - zFault = "foreign key"; - } - } - } - } -#endif - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int j; - for(j=0; jnKeyCol; j++){ - /* FIXME: Be smarter about indexes that use expressions */ - if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){ - zFault = "indexed"; - } - } - } - if( zFault ){ - sqlite3DbFree(db, zErr); - zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - } - - pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse); - assert( pBlob->pStmt || db->mallocFailed ); - if( pBlob->pStmt ){ - - /* This VDBE program seeks a btree cursor to the identified - ** db/table/row entry. The reason for using a vdbe program instead - ** of writing code to use the b-tree layer directly is that the - ** vdbe program will take advantage of the various transaction, - ** locking and error handling infrastructure built into the vdbe. - ** - ** After seeking the cursor, the vdbe executes an OP_ResultRow. - ** Code external to the Vdbe then "borrows" the b-tree cursor and - ** uses it to implement the blob_read(), blob_write() and - ** blob_bytes() functions. - ** - ** The sqlite3_blob_close() function finalizes the vdbe program, - ** which closes the b-tree cursor and (possibly) commits the - ** transaction. - */ - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList openBlob[] = { - {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ - {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ - /* blobSeekToRow() will initialize r[1] to the desired rowid */ - {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ - {OP_Column, 0, 0, 1}, /* 3 */ - {OP_ResultRow, 1, 0, 0}, /* 4 */ - {OP_Halt, 0, 0, 0}, /* 5 */ - }; - Vdbe *v = (Vdbe *)pBlob->pStmt; - VdbeOp *aOp; - - sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, - pTab->pSchema->schema_cookie, - pTab->pSchema->iGeneration); - sqlite3VdbeChangeP5(v, 1); - assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); - aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); - - /* Make sure a mutex is held on the table to be accessed */ - sqlite3VdbeUsesBtree(v, iDb); - - if( db->mallocFailed==0 ){ - assert( aOp!=0 ); - /* Configure the OP_TableLock instruction */ -#ifdef SQLITE_OMIT_SHARED_CACHE - aOp[0].opcode = OP_Noop; -#else - aOp[0].p1 = iDb; - aOp[0].p2 = pTab->tnum; - aOp[0].p3 = wrFlag; - sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); - } - if( db->mallocFailed==0 ){ -#endif - - /* Remove either the OP_OpenWrite or OpenRead. Set the P2 - ** parameter of the other to pTab->tnum. */ - if( wrFlag ) aOp[1].opcode = OP_OpenWrite; - aOp[1].p2 = pTab->tnum; - aOp[1].p3 = iDb; - - /* Configure the number of columns. Configure the cursor to - ** think that the table has one more column than it really - ** does. An OP_Column to retrieve this imaginary column will - ** always return an SQL NULL. This is useful because it means - ** we can invoke OP_Column to fill in the vdbe cursors type - ** and offset cache without causing any IO. - */ - aOp[1].p4type = P4_INT32; - aOp[1].p4.i = pTab->nCol+1; - aOp[3].p2 = pTab->nCol; - - sParse.nVar = 0; - sParse.nMem = 1; - sParse.nTab = 1; - sqlite3VdbeMakeReady(v, &sParse); - } - } - - pBlob->iCol = iCol; - pBlob->db = db; - sqlite3BtreeLeaveAll(db); - if( db->mallocFailed ){ - goto blob_open_out; - } - rc = blobSeekToRow(pBlob, iRow, &zErr); - if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break; - sqlite3ParseObjectReset(&sParse); - } - -blob_open_out: - if( rc==SQLITE_OK && db->mallocFailed==0 ){ - *ppBlob = (sqlite3_blob *)pBlob; - }else{ - if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); - sqlite3DbFree(db, pBlob); - } - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); - sqlite3DbFree(db, zErr); - sqlite3ParseObjectReset(&sParse); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Close a blob handle that was previously created using -** sqlite3_blob_open(). -*/ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ - Incrblob *p = (Incrblob *)pBlob; - int rc; - sqlite3 *db; - - if( p ){ - sqlite3_stmt *pStmt = p->pStmt; - db = p->db; - sqlite3_mutex_enter(db->mutex); - sqlite3DbFree(db, p); - sqlite3_mutex_leave(db->mutex); - rc = sqlite3_finalize(pStmt); - }else{ - rc = SQLITE_OK; - } - return rc; -} - -/* -** Perform a read or write operation on a blob -*/ -static int blobReadWrite( - sqlite3_blob *pBlob, - void *z, - int n, - int iOffset, - int (*xCall)(BtCursor*, u32, u32, void*) -){ - int rc; - Incrblob *p = (Incrblob *)pBlob; - Vdbe *v; - sqlite3 *db; - - if( p==0 ) return SQLITE_MISUSE_BKPT; - db = p->db; - sqlite3_mutex_enter(db->mutex); - v = (Vdbe*)p->pStmt; - - if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ - /* Request is out of range. Return a transient error. */ - rc = SQLITE_ERROR; - }else if( v==0 ){ - /* If there is no statement handle, then the blob-handle has - ** already been invalidated. Return SQLITE_ABORT in this case. - */ - rc = SQLITE_ABORT; - }else{ - /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is - ** returned, clean-up the statement handle. - */ - assert( db == v->db ); - sqlite3BtreeEnterCursor(p->pCsr); - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){ - /* If a pre-update hook is registered and this is a write cursor, - ** invoke it here. - ** - ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this - ** operation should really be an SQLITE_UPDATE. This is probably - ** incorrect, but is convenient because at this point the new.* values - ** are not easily obtainable. And for the sessions module, an - ** SQLITE_UPDATE where the PK columns do not change is handled in the - ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually - ** slightly more efficient). Since you cannot write to a PK column - ** using the incremental-blob API, this works. For the sessions module - ** anyhow. - */ - sqlite3_int64 iKey; - iKey = sqlite3BtreeIntegerKey(p->pCsr); - assert( v->apCsr[0]!=0 ); - assert( v->apCsr[0]->eCurType==CURTYPE_BTREE ); - sqlite3VdbePreUpdateHook( - v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol - ); - } -#endif - - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); - sqlite3BtreeLeaveCursor(p->pCsr); - if( rc==SQLITE_ABORT ){ - sqlite3VdbeFinalize(v); - p->pStmt = 0; - }else{ - v->rc = rc; - } - } - sqlite3Error(db, rc); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Read data from a blob handle. -*/ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ - return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked); -} - -/* -** Write data to a blob handle. -*/ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ - return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); -} - -/* -** Query a blob handle for the size of the data. -** -** The Incrblob.nByte field is fixed for the lifetime of the Incrblob -** so no mutex is required for access. -*/ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ - Incrblob *p = (Incrblob *)pBlob; - return (p && p->pStmt) ? p->nByte : 0; -} - -/* -** Move an existing blob handle to point to a different row of the same -** database table. -** -** If an error occurs, or if the specified row does not exist or does not -** contain a blob or text value, then an error code is returned and the -** database handle error code and message set. If this happens, then all -** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) -** immediately return SQLITE_ABORT. -*/ -SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ - int rc; - Incrblob *p = (Incrblob *)pBlob; - sqlite3 *db; - - if( p==0 ) return SQLITE_MISUSE_BKPT; - db = p->db; - sqlite3_mutex_enter(db->mutex); - - if( p->pStmt==0 ){ - /* If there is no statement handle, then the blob-handle has - ** already been invalidated. Return SQLITE_ABORT in this case. - */ - rc = SQLITE_ABORT; - }else{ - char *zErr; - ((Vdbe*)p->pStmt)->rc = SQLITE_OK; - rc = blobSeekToRow(p, iRow, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); - sqlite3DbFree(db, zErr); - } - assert( rc!=SQLITE_SCHEMA ); - } - - rc = sqlite3ApiExit(db, rc); - assert( rc==SQLITE_OK || p->pStmt==0 ); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#endif /* #ifndef SQLITE_OMIT_INCRBLOB */ - -/************** End of vdbeblob.c ********************************************/ -/************** Begin file vdbesort.c ****************************************/ -/* -** 2011-07-09 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code for the VdbeSorter object, used in concert with -** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements -** or by SELECT statements with ORDER BY clauses that cannot be satisfied -** using indexes and without LIMIT clauses. -** -** The VdbeSorter object implements a multi-threaded external merge sort -** algorithm that is efficient even if the number of elements being sorted -** exceeds the available memory. -** -** Here is the (internal, non-API) interface between this module and the -** rest of the SQLite system: -** -** sqlite3VdbeSorterInit() Create a new VdbeSorter object. -** -** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter -** object. The row is a binary blob in the -** OP_MakeRecord format that contains both -** the ORDER BY key columns and result columns -** in the case of a SELECT w/ ORDER BY, or -** the complete record for an index entry -** in the case of a CREATE INDEX. -** -** sqlite3VdbeSorterRewind() Sort all content previously added. -** Position the read cursor on the -** first sorted element. -** -** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted -** element. -** -** sqlite3VdbeSorterRowkey() Return the complete binary blob for the -** row currently under the read cursor. -** -** sqlite3VdbeSorterCompare() Compare the binary blob for the row -** currently under the read cursor against -** another binary blob X and report if -** X is strictly less than the read cursor. -** Used to enforce uniqueness in a -** CREATE UNIQUE INDEX statement. -** -** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim -** all resources. -** -** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This -** is like Close() followed by Init() only -** much faster. -** -** The interfaces above must be called in a particular order. Write() can -** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and -** Compare() can only occur in between Rewind() and Close()/Reset(). i.e. -** -** Init() -** for each record: Write() -** Rewind() -** Rowkey()/Compare() -** Next() -** Close() -** -** Algorithm: -** -** Records passed to the sorter via calls to Write() are initially held -** unsorted in main memory. Assuming the amount of memory used never exceeds -** a threshold, when Rewind() is called the set of records is sorted using -** an in-memory merge sort. In this case, no temporary files are required -** and subsequent calls to Rowkey(), Next() and Compare() read records -** directly from main memory. -** -** If the amount of space used to store records in main memory exceeds the -** threshold, then the set of records currently in memory are sorted and -** written to a temporary file in "Packed Memory Array" (PMA) format. -** A PMA created at this point is known as a "level-0 PMA". Higher levels -** of PMAs may be created by merging existing PMAs together - for example -** merging two or more level-0 PMAs together creates a level-1 PMA. -** -** The threshold for the amount of main memory to use before flushing -** records to a PMA is roughly the same as the limit configured for the -** page-cache of the main database. Specifically, the threshold is set to -** the value returned by "PRAGMA main.page_size" multiplied by -** that returned by "PRAGMA main.cache_size", in bytes. -** -** If the sorter is running in single-threaded mode, then all PMAs generated -** are appended to a single temporary file. Or, if the sorter is running in -** multi-threaded mode then up to (N+1) temporary files may be opened, where -** N is the configured number of worker threads. In this case, instead of -** sorting the records and writing the PMA to a temporary file itself, the -** calling thread usually launches a worker thread to do so. Except, if -** there are already N worker threads running, the main thread does the work -** itself. -** -** The sorter is running in multi-threaded mode if (a) the library was built -** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater -** than zero, and (b) worker threads have been enabled at runtime by calling -** "PRAGMA threads=N" with some value of N greater than 0. -** -** When Rewind() is called, any data remaining in memory is flushed to a -** final PMA. So at this point the data is stored in some number of sorted -** PMAs within temporary files on disk. -** -** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the -** sorter is running in single-threaded mode, then these PMAs are merged -** incrementally as keys are retrieved from the sorter by the VDBE. The -** MergeEngine object, described in further detail below, performs this -** merge. -** -** Or, if running in multi-threaded mode, then a background thread is -** launched to merge the existing PMAs. Once the background thread has -** merged T bytes of data into a single sorted PMA, the main thread -** begins reading keys from that PMA while the background thread proceeds -** with merging the next T bytes of data. And so on. -** -** Parameter T is set to half the value of the memory threshold used -** by Write() above to determine when to create a new PMA. -** -** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when -** Rewind() is called, then a hierarchy of incremental-merges is used. -** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on -** disk are merged together. Then T bytes of data from the second set, and -** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT -** PMAs at a time. This done is to improve locality. -** -** If running in multi-threaded mode and there are more than -** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more -** than one background thread may be created. Specifically, there may be -** one background thread for each temporary file on disk, and one background -** thread to merge the output of each of the others to a single PMA for -** the main thread to read from. -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -/* -** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various -** messages to stderr that may be helpful in understanding the performance -** characteristics of the sorter in multi-threaded mode. -*/ -#if 0 -# define SQLITE_DEBUG_SORTER_THREADS 1 -#endif - -/* -** Hard-coded maximum amount of data to accumulate in memory before flushing -** to a level 0 PMA. The purpose of this limit is to prevent various integer -** overflows. 512MiB. -*/ -#define SQLITE_MAX_PMASZ (1<<29) - -/* -** Private objects used by the sorter -*/ -typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ -typedef struct PmaReader PmaReader; /* Incrementally read one PMA */ -typedef struct PmaWriter PmaWriter; /* Incrementally write one PMA */ -typedef struct SorterRecord SorterRecord; /* A record being sorted */ -typedef struct SortSubtask SortSubtask; /* A sub-task in the sort process */ -typedef struct SorterFile SorterFile; /* Temporary file object wrapper */ -typedef struct SorterList SorterList; /* In-memory list of records */ -typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */ - -/* -** A container for a temp file handle and the current amount of data -** stored in the file. -*/ -struct SorterFile { - sqlite3_file *pFd; /* File handle */ - i64 iEof; /* Bytes of data stored in pFd */ -}; - -/* -** An in-memory list of objects to be sorted. -** -** If aMemory==0 then each object is allocated separately and the objects -** are connected using SorterRecord.u.pNext. If aMemory!=0 then all objects -** are stored in the aMemory[] bulk memory, one right after the other, and -** are connected using SorterRecord.u.iNext. -*/ -struct SorterList { - SorterRecord *pList; /* Linked list of records */ - u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ - i64 szPMA; /* Size of pList as PMA in bytes */ -}; - -/* -** The MergeEngine object is used to combine two or more smaller PMAs into -** one big PMA using a merge operation. Separate PMAs all need to be -** combined into one big PMA in order to be able to step through the sorted -** records in order. -** -** The aReadr[] array contains a PmaReader object for each of the PMAs being -** merged. An aReadr[] object either points to a valid key or else is at EOF. -** ("EOF" means "End Of File". When aReadr[] is at EOF there is no more data.) -** For the purposes of the paragraphs below, we assume that the array is -** actually N elements in size, where N is the smallest power of 2 greater -** to or equal to the number of PMAs being merged. The extra aReadr[] elements -** are treated as if they are empty (always at EOF). -** -** The aTree[] array is also N elements in size. The value of N is stored in -** the MergeEngine.nTree variable. -** -** The final (N/2) elements of aTree[] contain the results of comparing -** pairs of PMA keys together. Element i contains the result of -** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the -** aTree element is set to the index of it. -** -** For the purposes of this comparison, EOF is considered greater than any -** other key value. If the keys are equal (only possible with two EOF -** values), it doesn't matter which index is stored. -** -** The (N/4) elements of aTree[] that precede the final (N/2) described -** above contains the index of the smallest of each block of 4 PmaReaders -** And so on. So that aTree[1] contains the index of the PmaReader that -** currently points to the smallest key value. aTree[0] is unused. -** -** Example: -** -** aReadr[0] -> Banana -** aReadr[1] -> Feijoa -** aReadr[2] -> Elderberry -** aReadr[3] -> Currant -** aReadr[4] -> Grapefruit -** aReadr[5] -> Apple -** aReadr[6] -> Durian -** aReadr[7] -> EOF -** -** aTree[] = { X, 5 0, 5 0, 3, 5, 6 } -** -** The current element is "Apple" (the value of the key indicated by -** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will -** be advanced to the next key in its segment. Say the next key is -** "Eggplant": -** -** aReadr[5] -> Eggplant -** -** The contents of aTree[] are updated first by comparing the new PmaReader -** 5 key to the current key of PmaReader 4 (still "Grapefruit"). The PmaReader -** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree. -** The value of PmaReader 6 - "Durian" - is now smaller than that of PmaReader -** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Bananafile2. And instead of using a -** background thread to prepare data for the PmaReader, with a single -** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with -** keys from pMerger by the calling thread whenever the PmaReader runs out -** of data. -*/ -struct IncrMerger { - SortSubtask *pTask; /* Task that owns this merger */ - MergeEngine *pMerger; /* Merge engine thread reads data from */ - i64 iStartOff; /* Offset to start writing file at */ - int mxSz; /* Maximum bytes of data to store */ - int bEof; /* Set to true when merge is finished */ - int bUseThread; /* True to use a bg thread for this object */ - SorterFile aFile[2]; /* aFile[0] for reading, [1] for writing */ -}; - -/* -** An instance of this object is used for writing a PMA. -** -** The PMA is written one record at a time. Each record is of an arbitrary -** size. But I/O is more efficient if it occurs in page-sized blocks where -** each block is aligned on a page boundary. This object caches writes to -** the PMA so that aligned, page-size blocks are written. -*/ -struct PmaWriter { - int eFWErr; /* Non-zero if in an error state */ - u8 *aBuffer; /* Pointer to write buffer */ - int nBuffer; /* Size of write buffer in bytes */ - int iBufStart; /* First byte of buffer to write */ - int iBufEnd; /* Last byte of buffer to write */ - i64 iWriteOff; /* Offset of start of buffer in file */ - sqlite3_file *pFd; /* File handle to write to */ -}; - -/* -** This object is the header on a single record while that record is being -** held in memory and prior to being written out as part of a PMA. -** -** How the linked list is connected depends on how memory is being managed -** by this module. If using a separate allocation for each in-memory record -** (VdbeSorter.list.aMemory==0), then the list is always connected using the -** SorterRecord.u.pNext pointers. -** -** Or, if using the single large allocation method (VdbeSorter.list.aMemory!=0), -** then while records are being accumulated the list is linked using the -** SorterRecord.u.iNext offset. This is because the aMemory[] array may -** be sqlite3Realloc()ed while records are being accumulated. Once the VM -** has finished passing records to the sorter, or when the in-memory buffer -** is full, the list is sorted. As part of the sorting process, it is -** converted to use the SorterRecord.u.pNext pointers. See function -** vdbeSorterSort() for details. -*/ -struct SorterRecord { - int nVal; /* Size of the record in bytes */ - union { - SorterRecord *pNext; /* Pointer to next record in list */ - int iNext; /* Offset within aMemory of next record */ - } u; - /* The data for the record immediately follows this header */ -}; - -/* Return a pointer to the buffer containing the record data for SorterRecord -** object p. Should be used as if: -** -** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } -*/ -#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) - - -/* Maximum number of PMAs that a single MergeEngine can merge */ -#define SORTER_MAX_MERGE_COUNT 16 - -static int vdbeIncrSwap(IncrMerger*); -static void vdbeIncrFree(IncrMerger *); - -/* -** Free all memory belonging to the PmaReader object passed as the -** argument. All structure fields are set to zero before returning. -*/ -static void vdbePmaReaderClear(PmaReader *pReadr){ - sqlite3_free(pReadr->aAlloc); - sqlite3_free(pReadr->aBuffer); - if( pReadr->aMap ) sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); - vdbeIncrFree(pReadr->pIncr); - memset(pReadr, 0, sizeof(PmaReader)); -} - -/* -** Read the next nByte bytes of data from the PMA p. -** If successful, set *ppOut to point to a buffer containing the data -** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite -** error code. -** -** The buffer returned in *ppOut is only valid until the -** next call to this function. -*/ -static int vdbePmaReadBlob( - PmaReader *p, /* PmaReader from which to take the blob */ - int nByte, /* Bytes of data to read */ - u8 **ppOut /* OUT: Pointer to buffer containing data */ -){ - int iBuf; /* Offset within buffer to read from */ - int nAvail; /* Bytes of data available in buffer */ - - if( p->aMap ){ - *ppOut = &p->aMap[p->iReadOff]; - p->iReadOff += nByte; - return SQLITE_OK; - } - - assert( p->aBuffer ); - - /* If there is no more data to be read from the buffer, read the next - ** p->nBuffer bytes of data from the file into it. Or, if there are less - ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ - iBuf = p->iReadOff % p->nBuffer; - if( iBuf==0 ){ - int nRead; /* Bytes to read from disk */ - int rc; /* sqlite3OsRead() return code */ - - /* Determine how many bytes of data to read. */ - if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){ - nRead = p->nBuffer; - }else{ - nRead = (int)(p->iEof - p->iReadOff); - } - assert( nRead>0 ); - - /* Readr data from the file. Return early if an error occurs. */ - rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff); - assert( rc!=SQLITE_IOERR_SHORT_READ ); - if( rc!=SQLITE_OK ) return rc; - } - nAvail = p->nBuffer - iBuf; - - if( nByte<=nAvail ){ - /* The requested data is available in the in-memory buffer. In this - ** case there is no need to make a copy of the data, just return a - ** pointer into the buffer to the caller. */ - *ppOut = &p->aBuffer[iBuf]; - p->iReadOff += nByte; - }else{ - /* The requested data is not all available in the in-memory buffer. - ** In this case, allocate space at p->aAlloc[] to copy the requested - ** range into. Then return a copy of pointer p->aAlloc to the caller. */ - int nRem; /* Bytes remaining to copy */ - - /* Extend the p->aAlloc[] allocation if required. */ - if( p->nAllocnAlloc); - while( nByte>nNew ) nNew = nNew*2; - aNew = sqlite3Realloc(p->aAlloc, nNew); - if( !aNew ) return SQLITE_NOMEM_BKPT; - p->nAlloc = nNew; - p->aAlloc = aNew; - } - - /* Copy as much data as is available in the buffer into the start of - ** p->aAlloc[]. */ - memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail); - p->iReadOff += nAvail; - nRem = nByte - nAvail; - - /* The following loop copies up to p->nBuffer bytes per iteration into - ** the p->aAlloc[] buffer. */ - while( nRem>0 ){ - int rc; /* vdbePmaReadBlob() return code */ - int nCopy; /* Number of bytes to copy */ - u8 *aNext = 0; /* Pointer to buffer to copy data from */ - - nCopy = nRem; - if( nRem>p->nBuffer ) nCopy = p->nBuffer; - rc = vdbePmaReadBlob(p, nCopy, &aNext); - if( rc!=SQLITE_OK ) return rc; - assert( aNext!=p->aAlloc ); - assert( aNext!=0 ); - memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); - nRem -= nCopy; - } - - *ppOut = p->aAlloc; - } - - return SQLITE_OK; -} - -/* -** Read a varint from the stream of data accessed by p. Set *pnOut to -** the value read. -*/ -static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){ - int iBuf; - - if( p->aMap ){ - p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut); - }else{ - iBuf = p->iReadOff % p->nBuffer; - if( iBuf && (p->nBuffer-iBuf)>=9 ){ - p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); - }else{ - u8 aVarint[16], *a; - int i = 0, rc; - do{ - rc = vdbePmaReadBlob(p, 1, &a); - if( rc ) return rc; - aVarint[(i++)&0xf] = a[0]; - }while( (a[0]&0x80)!=0 ); - sqlite3GetVarint(aVarint, pnOut); - } - } - - return SQLITE_OK; -} - -/* -** Attempt to memory map file pFile. If successful, set *pp to point to the -** new mapping and return SQLITE_OK. If the mapping is not attempted -** (because the file is too large or the VFS layer is configured not to use -** mmap), return SQLITE_OK and set *pp to NULL. -** -** Or, if an error occurs, return an SQLite error code. The final value of -** *pp is undefined in this case. -*/ -static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){ - int rc = SQLITE_OK; - if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){ - sqlite3_file *pFd = pFile->pFd; - if( pFd->pMethods->iVersion>=3 ){ - rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp); - testcase( rc!=SQLITE_OK ); - } - } - return rc; -} - -/* -** Attach PmaReader pReadr to file pFile (if it is not already attached to -** that file) and seek it to offset iOff within the file. Return SQLITE_OK -** if successful, or an SQLite error code if an error occurs. -*/ -static int vdbePmaReaderSeek( - SortSubtask *pTask, /* Task context */ - PmaReader *pReadr, /* Reader whose cursor is to be moved */ - SorterFile *pFile, /* Sorter file to read from */ - i64 iOff /* Offset in pFile */ -){ - int rc = SQLITE_OK; - - assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 ); - - if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ; - if( pReadr->aMap ){ - sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); - pReadr->aMap = 0; - } - pReadr->iReadOff = iOff; - pReadr->iEof = pFile->iEof; - pReadr->pFd = pFile->pFd; - - rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap); - if( rc==SQLITE_OK && pReadr->aMap==0 ){ - int pgsz = pTask->pSorter->pgsz; - int iBuf = pReadr->iReadOff % pgsz; - if( pReadr->aBuffer==0 ){ - pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz); - if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM_BKPT; - pReadr->nBuffer = pgsz; - } - if( rc==SQLITE_OK && iBuf ){ - int nRead = pgsz - iBuf; - if( (pReadr->iReadOff + nRead) > pReadr->iEof ){ - nRead = (int)(pReadr->iEof - pReadr->iReadOff); - } - rc = sqlite3OsRead( - pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff - ); - testcase( rc!=SQLITE_OK ); - } - } - - return rc; -} - -/* -** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if -** no error occurs, or an SQLite error code if one does. -*/ -static int vdbePmaReaderNext(PmaReader *pReadr){ - int rc = SQLITE_OK; /* Return Code */ - u64 nRec = 0; /* Size of record in bytes */ - - - if( pReadr->iReadOff>=pReadr->iEof ){ - IncrMerger *pIncr = pReadr->pIncr; - int bEof = 1; - if( pIncr ){ - rc = vdbeIncrSwap(pIncr); - if( rc==SQLITE_OK && pIncr->bEof==0 ){ - rc = vdbePmaReaderSeek( - pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff - ); - bEof = 0; - } - } - - if( bEof ){ - /* This is an EOF condition */ - vdbePmaReaderClear(pReadr); - testcase( rc!=SQLITE_OK ); - return rc; - } - } - - if( rc==SQLITE_OK ){ - rc = vdbePmaReadVarint(pReadr, &nRec); - } - if( rc==SQLITE_OK ){ - pReadr->nKey = (int)nRec; - rc = vdbePmaReadBlob(pReadr, (int)nRec, &pReadr->aKey); - testcase( rc!=SQLITE_OK ); - } - - return rc; -} - -/* -** Initialize PmaReader pReadr to scan through the PMA stored in file pFile -** starting at offset iStart and ending at offset iEof-1. This function -** leaves the PmaReader pointing to the first key in the PMA (or EOF if the -** PMA is empty). -** -** If the pnByte parameter is NULL, then it is assumed that the file -** contains a single PMA, and that that PMA omits the initial length varint. -*/ -static int vdbePmaReaderInit( - SortSubtask *pTask, /* Task context */ - SorterFile *pFile, /* Sorter file to read from */ - i64 iStart, /* Start offset in pFile */ - PmaReader *pReadr, /* PmaReader to populate */ - i64 *pnByte /* IN/OUT: Increment this value by PMA size */ -){ - int rc; - - assert( pFile->iEof>iStart ); - assert( pReadr->aAlloc==0 && pReadr->nAlloc==0 ); - assert( pReadr->aBuffer==0 ); - assert( pReadr->aMap==0 ); - - rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart); - if( rc==SQLITE_OK ){ - u64 nByte = 0; /* Size of PMA in bytes */ - rc = vdbePmaReadVarint(pReadr, &nByte); - pReadr->iEof = pReadr->iReadOff + nByte; - *pnByte += nByte; - } - - if( rc==SQLITE_OK ){ - rc = vdbePmaReaderNext(pReadr); - } - return rc; -} - -/* -** A version of vdbeSorterCompare() that assumes that it has already been -** determined that the first field of key1 is equal to the first field of -** key2. -*/ -static int vdbeSorterCompareTail( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - UnpackedRecord *r2 = pTask->pUnpacked; - if( *pbKey2Cached==0 ){ - sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); - *pbKey2Cached = 1; - } - return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); -} - -/* -** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, -** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences -** used by the comparison. Return the result of the comparison. -** -** If IN/OUT parameter *pbKey2Cached is true when this function is called, -** it is assumed that (pTask->pUnpacked) contains the unpacked version -** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked -** version of key2 and *pbKey2Cached set to true before returning. -** -** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set -** to SQLITE_NOMEM. -*/ -static int vdbeSorterCompare( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - UnpackedRecord *r2 = pTask->pUnpacked; - if( !*pbKey2Cached ){ - sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); - *pbKey2Cached = 1; - } - return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); -} - -/* -** A specially optimized version of vdbeSorterCompare() that assumes that -** the first field of each key is a TEXT value and that the collation -** sequence to compare them with is BINARY. -*/ -static int vdbeSorterCompareText( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - const u8 * const p1 = (const u8 * const)pKey1; - const u8 * const p2 = (const u8 * const)pKey2; - const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ - const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ - - int n1; - int n2; - int res; - - getVarint32NR(&p1[1], n1); - getVarint32NR(&p2[1], n2); - res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2); - if( res==0 ){ - res = n1 - n2; - } - - if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ - res = vdbeSorterCompareTail( - pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 - ); - } - }else{ - assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); - if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ - res = res * -1; - } - } - - return res; -} - -/* -** A specially optimized version of vdbeSorterCompare() that assumes that -** the first field of each key is an INTEGER value. -*/ -static int vdbeSorterCompareInt( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - const u8 * const p1 = (const u8 * const)pKey1; - const u8 * const p2 = (const u8 * const)pKey2; - const int s1 = p1[1]; /* Left hand serial type */ - const int s2 = p2[1]; /* Right hand serial type */ - const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ - const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ - int res; /* Return value */ - - assert( (s1>0 && s1<7) || s1==8 || s1==9 ); - assert( (s2>0 && s2<7) || s2==8 || s2==9 ); - - if( s1==s2 ){ - /* The two values have the same sign. Compare using memcmp(). */ - static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8, 0, 0, 0 }; - const u8 n = aLen[s1]; - int i; - res = 0; - for(i=0; i7 && s2>7 ){ - res = s1 - s2; - }else{ - if( s2>7 ){ - res = +1; - }else if( s1>7 ){ - res = -1; - }else{ - res = s1 - s2; - } - assert( res!=0 ); - - if( res>0 ){ - if( *v1 & 0x80 ) res = -1; - }else{ - if( *v2 & 0x80 ) res = +1; - } - } - - if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ - res = vdbeSorterCompareTail( - pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 - ); - } - }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ - assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); - res = res * -1; - } - - return res; -} - -/* -** Initialize the temporary index cursor just opened as a sorter cursor. -** -** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField) -** to determine the number of fields that should be compared from the -** records being sorted. However, if the value passed as argument nField -** is non-zero and the sorter is able to guarantee a stable sort, nField -** is used instead. This is used when sorting records for a CREATE INDEX -** statement. In this case, keys are always delivered to the sorter in -** order of the primary key, which happens to be make up the final part -** of the records being sorted. So if the sort is stable, there is never -** any reason to compare PK fields and they can be ignored for a small -** performance boost. -** -** The sorter can guarantee a stable sort when running in single-threaded -** mode, but not in multi-threaded mode. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterInit( - sqlite3 *db, /* Database connection (for malloc()) */ - int nField, /* Number of key fields in each record */ - VdbeCursor *pCsr /* Cursor that holds the new sorter */ -){ - int pgsz; /* Page size of main database */ - int i; /* Used to iterate through aTask[] */ - VdbeSorter *pSorter; /* The new sorter */ - KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */ - int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */ - i64 sz; /* Size of pSorter in bytes */ - int rc = SQLITE_OK; -#if SQLITE_MAX_WORKER_THREADS==0 -# define nWorker 0 -#else - int nWorker; -#endif - - /* Initialize the upper limit on the number of worker threads */ -#if SQLITE_MAX_WORKER_THREADS>0 - if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){ - nWorker = 0; - }else{ - nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS]; - } -#endif - - /* Do not allow the total number of threads (main thread + all workers) - ** to exceed the maximum merge count */ -#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT - if( nWorker>=SORTER_MAX_MERGE_COUNT ){ - nWorker = SORTER_MAX_MERGE_COUNT-1; - } -#endif - - assert( pCsr->pKeyInfo ); - assert( !pCsr->isEphemeral ); - assert( pCsr->eCurType==CURTYPE_SORTER ); - assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) - < 0x7fffffff ); - szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField); - sz = SZ_VDBESORTER(nWorker+1); - - pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); - pCsr->uc.pSorter = pSorter; - if( pSorter==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - Btree *pBt = db->aDb[0].pBt; - pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); - memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); - pKeyInfo->db = 0; - if( nField && nWorker==0 ){ - pKeyInfo->nKeyField = nField; - } - sqlite3BtreeEnter(pBt); - pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt); - sqlite3BtreeLeave(pBt); - pSorter->nTask = nWorker + 1; - pSorter->iPrev = (u8)(nWorker - 1); - pSorter->bUseThreads = (pSorter->nTask>1); - pSorter->db = db; - for(i=0; inTask; i++){ - SortSubtask *pTask = &pSorter->aTask[i]; - pTask->pSorter = pSorter; - } - - if( !sqlite3TempInMemory(db) ){ - i64 mxCache; /* Cache size in bytes*/ - u32 szPma = sqlite3GlobalConfig.szPma; - pSorter->mnPmaSize = szPma * pgsz; - - mxCache = db->aDb[0].pSchema->cache_size; - if( mxCache<0 ){ - /* A negative cache-size value C indicates that the cache is abs(C) - ** KiB in size. */ - mxCache = mxCache * -1024; - }else{ - mxCache = mxCache * pgsz; - } - mxCache = MIN(mxCache, SQLITE_MAX_PMASZ); - pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache); - - /* Avoid large memory allocations if the application has requested - ** SQLITE_CONFIG_SMALL_MALLOC. */ - if( sqlite3GlobalConfig.bSmallMalloc==0 ){ - assert( pSorter->iMemory==0 ); - pSorter->nMemory = pgsz; - pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); - if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM_BKPT; - } - } - - if( pKeyInfo->nAllField<13 - && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) - && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0 - ){ - pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; - } - } - - return rc; -} -#undef nWorker /* Defined at the top of this function */ - -/* -** Free the list of sorted records starting at pRecord. -*/ -static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ - SorterRecord *p; - SorterRecord *pNext; - for(p=pRecord; p; p=pNext){ - pNext = p->u.pNext; - sqlite3DbFree(db, p); - } -} - -/* -** Free all resources owned by the object indicated by argument pTask. All -** fields of *pTask are zeroed before returning. -*/ -static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ - sqlite3DbFree(db, pTask->pUnpacked); -#if SQLITE_MAX_WORKER_THREADS>0 - /* pTask->list.aMemory can only be non-zero if it was handed memory - ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ - if( pTask->list.aMemory ){ - sqlite3_free(pTask->list.aMemory); - }else -#endif - { - assert( pTask->list.aMemory==0 ); - vdbeSorterRecordFree(0, pTask->list.pList); - } - if( pTask->file.pFd ){ - sqlite3OsCloseFree(pTask->file.pFd); - } - if( pTask->file2.pFd ){ - sqlite3OsCloseFree(pTask->file2.pFd); - } - memset(pTask, 0, sizeof(SortSubtask)); -} - -#ifdef SQLITE_DEBUG_SORTER_THREADS -static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ - i64 t; - int iTask = (pTask - pTask->pSorter->aTask); - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); -} -static void vdbeSorterRewindDebug(const char *zEvent){ - i64 t = 0; - sqlite3_vfs *pVfs = sqlite3_vfs_find(0); - if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t); - fprintf(stderr, "%lld:X %s\n", t, zEvent); -} -static void vdbeSorterPopulateDebug( - SortSubtask *pTask, - const char *zEvent -){ - i64 t; - int iTask = (pTask - pTask->pSorter->aTask); - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent); -} -static void vdbeSorterBlockDebug( - SortSubtask *pTask, - int bBlocked, - const char *zEvent -){ - if( bBlocked ){ - i64 t; - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:main %s\n", t, zEvent); - } -} -#else -# define vdbeSorterWorkDebug(x,y) -# define vdbeSorterRewindDebug(y) -# define vdbeSorterPopulateDebug(x,y) -# define vdbeSorterBlockDebug(x,y,z) -#endif - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** Join thread pTask->thread. -*/ -static int vdbeSorterJoinThread(SortSubtask *pTask){ - int rc = SQLITE_OK; - if( pTask->pThread ){ -#ifdef SQLITE_DEBUG_SORTER_THREADS - int bDone = pTask->bDone; -#endif - void *pRet = SQLITE_INT_TO_PTR(SQLITE_ERROR); - vdbeSorterBlockDebug(pTask, !bDone, "enter"); - (void)sqlite3ThreadJoin(pTask->pThread, &pRet); - vdbeSorterBlockDebug(pTask, !bDone, "exit"); - rc = SQLITE_PTR_TO_INT(pRet); - assert( pTask->bDone==1 ); - pTask->bDone = 0; - pTask->pThread = 0; - } - return rc; -} - -/* -** Launch a background thread to run xTask(pIn). -*/ -static int vdbeSorterCreateThread( - SortSubtask *pTask, /* Thread will use this task object */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - assert( pTask->pThread==0 && pTask->bDone==0 ); - return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn); -} - -/* -** Join all outstanding threads launched by SorterWrite() to create -** level-0 PMAs. -*/ -static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){ - int rc = rcin; - int i; - - /* This function is always called by the main user thread. - ** - ** If this function is being called after SorterRewind() has been called, - ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread - ** is currently attempt to join one of the other threads. To avoid a race - ** condition where this thread also attempts to join the same object, join - ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */ - for(i=pSorter->nTask-1; i>=0; i--){ - SortSubtask *pTask = &pSorter->aTask[i]; - int rc2 = vdbeSorterJoinThread(pTask); - if( rc==SQLITE_OK ) rc = rc2; - } - return rc; -} -#else -# define vdbeSorterJoinAll(x,rcin) (rcin) -# define vdbeSorterJoinThread(pTask) SQLITE_OK -#endif - -/* -** Allocate a new MergeEngine object capable of handling up to -** nReader PmaReader inputs. -** -** nReader is automatically rounded up to the next power of two. -** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up. -*/ -static MergeEngine *vdbeMergeEngineNew(int nReader){ - int N = 2; /* Smallest power of two >= nReader */ - i64 nByte; /* Total bytes of space to allocate */ - MergeEngine *pNew; /* Pointer to allocated object to return */ - - assert( nReader<=SORTER_MAX_MERGE_COUNT ); - - while( NnTree = N; - pNew->pTask = 0; - pNew->aReadr = (PmaReader*)&pNew[1]; - pNew->aTree = (int*)&pNew->aReadr[N]; - } - return pNew; -} - -/* -** Free the MergeEngine object passed as the only argument. -*/ -static void vdbeMergeEngineFree(MergeEngine *pMerger){ - int i; - if( pMerger ){ - for(i=0; inTree; i++){ - vdbePmaReaderClear(&pMerger->aReadr[i]); - } - } - sqlite3_free(pMerger); -} - -/* -** Free all resources associated with the IncrMerger object indicated by -** the first argument. -*/ -static void vdbeIncrFree(IncrMerger *pIncr){ - if( pIncr ){ -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - vdbeSorterJoinThread(pIncr->pTask); - if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd); - if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd); - } -#endif - vdbeMergeEngineFree(pIncr->pMerger); - sqlite3_free(pIncr); - } -} - -/* -** Reset a sorting cursor back to its original empty state. -*/ -SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ - int i; - (void)vdbeSorterJoinAll(pSorter, SQLITE_OK); - assert( pSorter->bUseThreads || pSorter->pReader==0 ); -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->pReader ){ - vdbePmaReaderClear(pSorter->pReader); - sqlite3DbFree(db, pSorter->pReader); - pSorter->pReader = 0; - } -#endif - vdbeMergeEngineFree(pSorter->pMerger); - pSorter->pMerger = 0; - for(i=0; inTask; i++){ - SortSubtask *pTask = &pSorter->aTask[i]; - vdbeSortSubtaskCleanup(db, pTask); - pTask->pSorter = pSorter; - } - if( pSorter->list.aMemory==0 ){ - vdbeSorterRecordFree(0, pSorter->list.pList); - } - pSorter->list.pList = 0; - pSorter->list.szPMA = 0; - pSorter->bUsePMA = 0; - pSorter->iMemory = 0; - pSorter->mxKeysize = 0; - sqlite3DbFree(db, pSorter->pUnpacked); - pSorter->pUnpacked = 0; -} - -/* -** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. -*/ -SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ - VdbeSorter *pSorter; - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - if( pSorter ){ - sqlite3VdbeSorterReset(db, pSorter); - sqlite3_free(pSorter->list.aMemory); - sqlite3DbFree(db, pSorter); - pCsr->uc.pSorter = 0; - } -} - -#if SQLITE_MAX_MMAP_SIZE>0 -/* -** The first argument is a file-handle open on a temporary file. The file -** is guaranteed to be nByte bytes or smaller in size. This function -** attempts to extend the file to nByte bytes in size and to ensure that -** the VFS has memory mapped it. -** -** Whether or not the file does end up memory mapped of course depends on -** the specific VFS implementation. -*/ -static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ - if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ - void *p = 0; - int chunksize = 4*1024; - sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); - sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); - sqlite3OsFetch(pFd, 0, (int)nByte, &p); - if( p ) sqlite3OsUnfetch(pFd, 0, p); - } -} -#else -# define vdbeSorterExtendFile(x,y,z) -#endif - -/* -** Allocate space for a file-handle and open a temporary file. If successful, -** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK. -** Otherwise, set *ppFd to 0 and return an SQLite error code. -*/ -static int vdbeSorterOpenTempFile( - sqlite3 *db, /* Database handle doing sort */ - i64 nExtend, /* Attempt to extend file to this size */ - sqlite3_file **ppFd -){ - int rc; - if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS; - rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd, - SQLITE_OPEN_TEMP_JOURNAL | - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc - ); - if( rc==SQLITE_OK ){ - i64 max = SQLITE_MAX_MMAP_SIZE; - sqlite3OsFileControlHint(*ppFd, SQLITE_FCNTL_MMAP_SIZE, (void*)&max); - if( nExtend>0 ){ - vdbeSorterExtendFile(db, *ppFd, nExtend); - } - } - return rc; -} - -/* -** If it has not already been allocated, allocate the UnpackedRecord -** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or -** if no allocation was required), or SQLITE_NOMEM otherwise. -*/ -static int vdbeSortAllocUnpacked(SortSubtask *pTask){ - if( pTask->pUnpacked==0 ){ - pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); - if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; - pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField; - pTask->pUnpacked->errCode = 0; - } - return SQLITE_OK; -} - - -/* -** Merge the two sorted lists p1 and p2 into a single list. -*/ -static SorterRecord *vdbeSorterMerge( - SortSubtask *pTask, /* Calling thread context */ - SorterRecord *p1, /* First list to merge */ - SorterRecord *p2 /* Second list to merge */ -){ - SorterRecord *pFinal = 0; - SorterRecord **pp = &pFinal; - int bCached = 0; - - assert( p1!=0 && p2!=0 ); - for(;;){ - int res; - res = pTask->xCompare( - pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal - ); - - if( res<=0 ){ - *pp = p1; - pp = &p1->u.pNext; - p1 = p1->u.pNext; - if( p1==0 ){ - *pp = p2; - break; - } - }else{ - *pp = p2; - pp = &p2->u.pNext; - p2 = p2->u.pNext; - bCached = 0; - if( p2==0 ){ - *pp = p1; - break; - } - } - } - return pFinal; -} - -/* -** Return the SorterCompare function to compare values collected by the -** sorter object passed as the only argument. -*/ -static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ - if( p->typeMask==SORTER_TYPE_INTEGER ){ - return vdbeSorterCompareInt; - }else if( p->typeMask==SORTER_TYPE_TEXT ){ - return vdbeSorterCompareText; - } - return vdbeSorterCompare; -} - -/* -** Sort the linked list of records headed at pTask->pList. Return -** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if -** an error occurs. -*/ -static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ - int i; - SorterRecord *p; - int rc; - SorterRecord *aSlot[64]; - - rc = vdbeSortAllocUnpacked(pTask); - if( rc!=SQLITE_OK ) return rc; - - p = pList->pList; - pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); - memset(aSlot, 0, sizeof(aSlot)); - - while( p ){ - SorterRecord *pNext; - if( pList->aMemory ){ - if( (u8*)p==pList->aMemory ){ - pNext = 0; - }else{ - assert( p->u.iNextaMemory) ); - pNext = (SorterRecord*)&pList->aMemory[p->u.iNext]; - } - }else{ - pNext = p->u.pNext; - } - - p->u.pNext = 0; - for(i=0; aSlot[i]; i++){ - p = vdbeSorterMerge(pTask, p, aSlot[i]); - /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use - ** | up all 64 aSlots[] with only a 64-bit address space. - ** v */ - assert( ipList = p; - - assert( pTask->pUnpacked->errCode==SQLITE_OK - || pTask->pUnpacked->errCode==SQLITE_NOMEM - ); - return pTask->pUnpacked->errCode; -} - -/* -** Initialize a PMA-writer object. -*/ -static void vdbePmaWriterInit( - sqlite3_file *pFd, /* File handle to write to */ - PmaWriter *p, /* Object to populate */ - int nBuf, /* Buffer size */ - i64 iStart /* Offset of pFd to begin writing at */ -){ - memset(p, 0, sizeof(PmaWriter)); - p->aBuffer = (u8*)sqlite3Malloc(nBuf); - if( !p->aBuffer ){ - p->eFWErr = SQLITE_NOMEM_BKPT; - }else{ - p->iBufEnd = p->iBufStart = (iStart % nBuf); - p->iWriteOff = iStart - p->iBufStart; - p->nBuffer = nBuf; - p->pFd = pFd; - } -} - -/* -** Write nData bytes of data to the PMA. Return SQLITE_OK -** if successful, or an SQLite error code if an error occurs. -*/ -static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ - int nRem = nData; - while( nRem>0 && p->eFWErr==0 ){ - int nCopy = nRem; - if( nCopy>(p->nBuffer - p->iBufEnd) ){ - nCopy = p->nBuffer - p->iBufEnd; - } - - memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); - p->iBufEnd += nCopy; - if( p->iBufEnd==p->nBuffer ){ - p->eFWErr = sqlite3OsWrite(p->pFd, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, - p->iWriteOff + p->iBufStart - ); - p->iBufStart = p->iBufEnd = 0; - p->iWriteOff += p->nBuffer; - } - assert( p->iBufEndnBuffer ); - - nRem -= nCopy; - } -} - -/* -** Flush any buffered data to disk and clean up the PMA-writer object. -** The results of using the PMA-writer after this call are undefined. -** Return SQLITE_OK if flushing the buffered data succeeds or is not -** required. Otherwise, return an SQLite error code. -** -** Before returning, set *piEof to the offset immediately following the -** last byte written to the file. -*/ -static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){ - int rc; - if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ - p->eFWErr = sqlite3OsWrite(p->pFd, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, - p->iWriteOff + p->iBufStart - ); - } - *piEof = (p->iWriteOff + p->iBufEnd); - sqlite3_free(p->aBuffer); - rc = p->eFWErr; - memset(p, 0, sizeof(PmaWriter)); - return rc; -} - -/* -** Write value iVal encoded as a varint to the PMA. Return -** SQLITE_OK if successful, or an SQLite error code if an error occurs. -*/ -static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){ - int nByte; - u8 aByte[10]; - nByte = sqlite3PutVarint(aByte, iVal); - vdbePmaWriteBlob(p, aByte, nByte); -} - -/* -** Write the current contents of in-memory linked-list pList to a level-0 -** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if -** successful, or an SQLite error code otherwise. -** -** The format of a PMA is: -** -** * A varint. This varint contains the total number of bytes of content -** in the PMA (not including the varint itself). -** -** * One or more records packed end-to-end in order of ascending keys. -** Each record consists of a varint followed by a blob of data (the -** key). The varint is the number of bytes in the blob of data. -*/ -static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){ - sqlite3 *db = pTask->pSorter->db; - int rc = SQLITE_OK; /* Return code */ - PmaWriter writer; /* Object used to write to the file */ - -#ifdef SQLITE_DEBUG - /* Set iSz to the expected size of file pTask->file after writing the PMA. - ** This is used by an assert() statement at the end of this function. */ - i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof; -#endif - - vdbeSorterWorkDebug(pTask, "enter"); - memset(&writer, 0, sizeof(PmaWriter)); - assert( pList->szPMA>0 ); - - /* If the first temporary PMA file has not been opened, open it now. */ - if( pTask->file.pFd==0 ){ - rc = vdbeSorterOpenTempFile(db, 0, &pTask->file.pFd); - assert( rc!=SQLITE_OK || pTask->file.pFd ); - assert( pTask->file.iEof==0 ); - assert( pTask->nPMA==0 ); - } - - /* Try to get the file to memory map */ - if( rc==SQLITE_OK ){ - vdbeSorterExtendFile(db, pTask->file.pFd, pTask->file.iEof+pList->szPMA+9); - } - - /* Sort the list */ - if( rc==SQLITE_OK ){ - rc = vdbeSorterSort(pTask, pList); - } - - if( rc==SQLITE_OK ){ - SorterRecord *p; - SorterRecord *pNext = 0; - - vdbePmaWriterInit(pTask->file.pFd, &writer, pTask->pSorter->pgsz, - pTask->file.iEof); - pTask->nPMA++; - vdbePmaWriteVarint(&writer, pList->szPMA); - for(p=pList->pList; p; p=pNext){ - pNext = p->u.pNext; - vdbePmaWriteVarint(&writer, p->nVal); - vdbePmaWriteBlob(&writer, SRVAL(p), p->nVal); - if( pList->aMemory==0 ) sqlite3_free(p); - } - pList->pList = p; - rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof); - } - - vdbeSorterWorkDebug(pTask, "exit"); - assert( rc!=SQLITE_OK || pList->pList==0 ); - assert( rc!=SQLITE_OK || pTask->file.iEof==iSz ); - return rc; -} - -/* -** Advance the MergeEngine to its next entry. -** Set *pbEof to true there is no next entry because -** the MergeEngine has reached the end of all its inputs. -** -** Return SQLITE_OK if successful or an error code if an error occurs. -*/ -static int vdbeMergeEngineStep( - MergeEngine *pMerger, /* The merge engine to advance to the next row */ - int *pbEof /* Set TRUE at EOF. Set false for more content */ -){ - int rc; - int iPrev = pMerger->aTree[1];/* Index of PmaReader to advance */ - SortSubtask *pTask = pMerger->pTask; - - /* Advance the current PmaReader */ - rc = vdbePmaReaderNext(&pMerger->aReadr[iPrev]); - - /* Update contents of aTree[] */ - if( rc==SQLITE_OK ){ - int i; /* Index of aTree[] to recalculate */ - PmaReader *pReadr1; /* First PmaReader to compare */ - PmaReader *pReadr2; /* Second PmaReader to compare */ - int bCached = 0; - - /* Find the first two PmaReaders to compare. The one that was just - ** advanced (iPrev) and the one next to it in the array. */ - pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; - pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; - - for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ - /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ - int iRes; - if( pReadr1->pFd==0 ){ - iRes = +1; - }else if( pReadr2->pFd==0 ){ - iRes = -1; - }else{ - iRes = pTask->xCompare(pTask, &bCached, - pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey - ); - } - - /* If pReadr1 contained the smaller value, set aTree[i] to its index. - ** Then set pReadr2 to the next PmaReader to compare to pReadr1. In this - ** case there is no cache of pReadr2 in pTask->pUnpacked, so set - ** pKey2 to point to the record belonging to pReadr2. - ** - ** Alternatively, if pReadr2 contains the smaller of the two values, - ** set aTree[i] to its index and update pReadr1. If vdbeSorterCompare() - ** was actually called above, then pTask->pUnpacked now contains - ** a value equivalent to pReadr2. So set pKey2 to NULL to prevent - ** vdbeSorterCompare() from decoding pReadr2 again. - ** - ** If the two values were equal, then the value from the oldest - ** PMA should be considered smaller. The VdbeSorter.aReadr[] array - ** is sorted from oldest to newest, so pReadr1 contains older values - ** than pReadr2 iff (pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); - pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - bCached = 0; - }else{ - if( pReadr1->pFd ) bCached = 0; - pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); - pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - } - } - *pbEof = (pMerger->aReadr[pMerger->aTree[1]].pFd==0); - } - - return (rc==SQLITE_OK ? pTask->pUnpacked->errCode : rc); -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for background threads that write level-0 PMAs. -*/ -static void *vdbeSorterFlushThread(void *pCtx){ - SortSubtask *pTask = (SortSubtask*)pCtx; - int rc; /* Return code */ - assert( pTask->bDone==0 ); - rc = vdbeSorterListToPMA(pTask, &pTask->list); - pTask->bDone = 1; - return SQLITE_INT_TO_PTR(rc); -} -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - -/* -** Flush the current contents of VdbeSorter.list to a new PMA, possibly -** using a background thread. -*/ -static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ -#if SQLITE_MAX_WORKER_THREADS==0 - pSorter->bUsePMA = 1; - return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list); -#else - int rc = SQLITE_OK; - int i; - SortSubtask *pTask = 0; /* Thread context used to create new PMA */ - int nWorker = (pSorter->nTask-1); - - /* Set the flag to indicate that at least one PMA has been written. - ** Or will be, anyhow. */ - pSorter->bUsePMA = 1; - - /* Select a sub-task to sort and flush the current list of in-memory - ** records to disk. If the sorter is running in multi-threaded mode, - ** round-robin between the first (pSorter->nTask-1) tasks. Except, if - ** the background thread from a sub-tasks previous turn is still running, - ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy, - ** fall back to using the final sub-task. The first (pSorter->nTask-1) - ** sub-tasks are preferred as they use background threads - the final - ** sub-task uses the main thread. */ - for(i=0; iiPrev + i + 1) % nWorker; - pTask = &pSorter->aTask[iTest]; - if( pTask->bDone ){ - rc = vdbeSorterJoinThread(pTask); - } - if( rc!=SQLITE_OK || pTask->pThread==0 ) break; - } - - if( rc==SQLITE_OK ){ - if( i==nWorker ){ - /* Use the foreground thread for this operation */ - rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list); - }else{ - /* Launch a background thread for this operation */ - u8 *aMem; - void *pCtx; - - assert( pTask!=0 ); - assert( pTask->pThread==0 && pTask->bDone==0 ); - assert( pTask->list.pList==0 ); - assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 ); - - aMem = pTask->list.aMemory; - pCtx = (void*)pTask; - pSorter->iPrev = (u8)(pTask - pSorter->aTask); - pTask->list = pSorter->list; - pSorter->list.pList = 0; - pSorter->list.szPMA = 0; - if( aMem ){ - pSorter->list.aMemory = aMem; - pSorter->nMemory = sqlite3MallocSize(aMem); - }else if( pSorter->list.aMemory ){ - pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory); - if( !pSorter->list.aMemory ) return SQLITE_NOMEM_BKPT; - } - - rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx); - } - } - - return rc; -#endif /* SQLITE_MAX_WORKER_THREADS!=0 */ -} - -/* -** Add a record to the sorter. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterWrite( - const VdbeCursor *pCsr, /* Sorter cursor */ - Mem *pVal /* Memory cell containing record */ -){ - VdbeSorter *pSorter; - int rc = SQLITE_OK; /* Return Code */ - SorterRecord *pNew; /* New list element */ - int bFlush; /* True to flush contents of memory to PMA */ - i64 nReq; /* Bytes of memory required */ - i64 nPMA; /* Bytes of PMA space required */ - int t; /* serial type of first record field */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - getVarint32NR((const u8*)&pVal->z[1], t); - if( t>0 && t<10 && t!=7 ){ - pSorter->typeMask &= SORTER_TYPE_INTEGER; - }else if( t>10 && (t & 0x01) ){ - pSorter->typeMask &= SORTER_TYPE_TEXT; - }else{ - pSorter->typeMask = 0; - } - - assert( pSorter ); - - /* Figure out whether or not the current contents of memory should be - ** flushed to a PMA before continuing. If so, do so. - ** - ** If using the single large allocation mode (pSorter->aMemory!=0), then - ** flush the contents of memory to a new PMA if (a) at least one value is - ** already in memory and (b) the new value will not fit in memory. - ** - ** Or, if using separate allocations for each record, flush the contents - ** of memory to a PMA if either of the following are true: - ** - ** * The total memory allocated for the in-memory list is greater - ** than (page-size * cache-size), or - ** - ** * The total memory allocated for the in-memory list is greater - ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. - */ - nReq = pVal->n + sizeof(SorterRecord); - nPMA = pVal->n + sqlite3VarintLen(pVal->n); - if( pSorter->mxPmaSize ){ - if( pSorter->list.aMemory ){ - bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize; - }else{ - bFlush = ( - (pSorter->list.szPMA > pSorter->mxPmaSize) - || (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull()) - ); - } - if( bFlush ){ - rc = vdbeSorterFlushPMA(pSorter); - pSorter->list.szPMA = 0; - pSorter->iMemory = 0; - assert( rc!=SQLITE_OK || pSorter->list.pList==0 ); - } - } - - pSorter->list.szPMA += nPMA; - if( nPMA>pSorter->mxKeysize ){ - pSorter->mxKeysize = nPMA; - } - - if( pSorter->list.aMemory ){ - int nMin = pSorter->iMemory + nReq; - - if( nMin>pSorter->nMemory ){ - u8 *aNew; - sqlite3_int64 nNew = 2 * (sqlite3_int64)pSorter->nMemory; - int iListOff = -1; - if( pSorter->list.pList ){ - iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; - } - while( nNew < nMin ) nNew = nNew*2; - if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; - if( nNew < nMin ) nNew = nMin; - aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); - if( !aNew ) return SQLITE_NOMEM_BKPT; - if( iListOff>=0 ){ - pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; - } - pSorter->list.aMemory = aNew; - pSorter->nMemory = nNew; - } - - pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; - pSorter->iMemory += ROUND8(nReq); - if( pSorter->list.pList ){ - pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); - } - }else{ - pNew = (SorterRecord *)sqlite3Malloc(nReq); - if( pNew==0 ){ - return SQLITE_NOMEM_BKPT; - } - pNew->u.pNext = pSorter->list.pList; - } - - memcpy(SRVAL(pNew), pVal->z, pVal->n); - pNew->nVal = pVal->n; - pSorter->list.pList = pNew; - - return rc; -} - -/* -** Read keys from pIncr->pMerger and populate pIncr->aFile[1]. The format -** of the data stored in aFile[1] is the same as that used by regular PMAs, -** except that the number-of-bytes varint is omitted from the start. -*/ -static int vdbeIncrPopulate(IncrMerger *pIncr){ - int rc = SQLITE_OK; - int rc2; - i64 iStart = pIncr->iStartOff; - SorterFile *pOut = &pIncr->aFile[1]; - SortSubtask *pTask = pIncr->pTask; - MergeEngine *pMerger = pIncr->pMerger; - PmaWriter writer; - assert( pIncr->bEof==0 ); - - vdbeSorterPopulateDebug(pTask, "enter"); - - vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart); - while( rc==SQLITE_OK ){ - int dummy; - PmaReader *pReader = &pMerger->aReadr[ pMerger->aTree[1] ]; - int nKey = pReader->nKey; - i64 iEof = writer.iWriteOff + writer.iBufEnd; - - /* Check if the output file is full or if the input has been exhausted. - ** In either case exit the loop. */ - if( pReader->pFd==0 ) break; - if( (iEof + nKey + sqlite3VarintLen(nKey))>(iStart + pIncr->mxSz) ) break; - - /* Write the next key to the output. */ - vdbePmaWriteVarint(&writer, nKey); - vdbePmaWriteBlob(&writer, pReader->aKey, nKey); - assert( pIncr->pMerger->pTask==pTask ); - rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy); - } - - rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof); - if( rc==SQLITE_OK ) rc = rc2; - vdbeSorterPopulateDebug(pTask, "exit"); - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for background threads that populate aFile[1] of -** multi-threaded IncrMerger objects. -*/ -static void *vdbeIncrPopulateThread(void *pCtx){ - IncrMerger *pIncr = (IncrMerger*)pCtx; - void *pRet = SQLITE_INT_TO_PTR( vdbeIncrPopulate(pIncr) ); - pIncr->pTask->bDone = 1; - return pRet; -} - -/* -** Launch a background thread to populate aFile[1] of pIncr. -*/ -static int vdbeIncrBgPopulate(IncrMerger *pIncr){ - void *p = (void*)pIncr; - assert( pIncr->bUseThread ); - return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p); -} -#endif - -/* -** This function is called when the PmaReader corresponding to pIncr has -** finished reading the contents of aFile[0]. Its purpose is to "refill" -** aFile[0] such that the PmaReader should start rereading it from the -** beginning. -** -** For single-threaded objects, this is accomplished by literally reading -** keys from pIncr->pMerger and repopulating aFile[0]. -** -** For multi-threaded objects, all that is required is to wait until the -** background thread is finished (if it is not already) and then swap -** aFile[0] and aFile[1] in place. If the contents of pMerger have not -** been exhausted, this function also launches a new background thread -** to populate the new aFile[1]. -** -** SQLITE_OK is returned on success, or an SQLite error code otherwise. -*/ -static int vdbeIncrSwap(IncrMerger *pIncr){ - int rc = SQLITE_OK; - -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterJoinThread(pIncr->pTask); - - if( rc==SQLITE_OK ){ - SorterFile f0 = pIncr->aFile[0]; - pIncr->aFile[0] = pIncr->aFile[1]; - pIncr->aFile[1] = f0; - } - - if( rc==SQLITE_OK ){ - if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ - pIncr->bEof = 1; - }else{ - rc = vdbeIncrBgPopulate(pIncr); - } - } - }else -#endif - { - rc = vdbeIncrPopulate(pIncr); - pIncr->aFile[0] = pIncr->aFile[1]; - if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ - pIncr->bEof = 1; - } - } - - return rc; -} - -/* -** Allocate and return a new IncrMerger object to read data from pMerger. -** -** If an OOM condition is encountered, return NULL. In this case free the -** pMerger argument before returning. -*/ -static int vdbeIncrMergerNew( - SortSubtask *pTask, /* The thread that will be using the new IncrMerger */ - MergeEngine *pMerger, /* The MergeEngine that the IncrMerger will control */ - IncrMerger **ppOut /* Write the new IncrMerger here */ -){ - int rc = SQLITE_OK; - IncrMerger *pIncr = *ppOut = (IncrMerger*) - (sqlite3FaultSim(100) ? 0 : sqlite3MallocZero(sizeof(*pIncr))); - if( pIncr ){ - pIncr->pMerger = pMerger; - pIncr->pTask = pTask; - pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2); - pTask->file2.iEof += pIncr->mxSz; - }else{ - vdbeMergeEngineFree(pMerger); - rc = SQLITE_NOMEM_BKPT; - } - assert( *ppOut!=0 || rc!=SQLITE_OK ); - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** Set the "use-threads" flag on object pIncr. -*/ -static void vdbeIncrMergerSetThreads(IncrMerger *pIncr){ - pIncr->bUseThread = 1; - pIncr->pTask->file2.iEof -= pIncr->mxSz; -} -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - - - -/* -** Recompute pMerger->aTree[iOut] by comparing the next keys on the -** two PmaReaders that feed that entry. Neither of the PmaReaders -** are advanced. This routine merely does the comparison. -*/ -static void vdbeMergeEngineCompare( - MergeEngine *pMerger, /* Merge engine containing PmaReaders to compare */ - int iOut /* Store the result in pMerger->aTree[iOut] */ -){ - int i1; - int i2; - int iRes; - PmaReader *p1; - PmaReader *p2; - - assert( iOutnTree && iOut>0 ); - - if( iOut>=(pMerger->nTree/2) ){ - i1 = (iOut - pMerger->nTree/2) * 2; - i2 = i1 + 1; - }else{ - i1 = pMerger->aTree[iOut*2]; - i2 = pMerger->aTree[iOut*2+1]; - } - - p1 = &pMerger->aReadr[i1]; - p2 = &pMerger->aReadr[i2]; - - if( p1->pFd==0 ){ - iRes = i2; - }else if( p2->pFd==0 ){ - iRes = i1; - }else{ - SortSubtask *pTask = pMerger->pTask; - int bCached = 0; - int res; - assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ - res = pTask->xCompare( - pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey - ); - if( res<=0 ){ - iRes = i1; - }else{ - iRes = i2; - } - } - - pMerger->aTree[iOut] = iRes; -} - -/* -** Allowed values for the eMode parameter to vdbeMergeEngineInit() -** and vdbePmaReaderIncrMergeInit(). -** -** Only INCRINIT_NORMAL is valid in single-threaded builds (when -** SQLITE_MAX_WORKER_THREADS==0). The other values are only used -** when there exists one or more separate worker threads. -*/ -#define INCRINIT_NORMAL 0 -#define INCRINIT_TASK 1 -#define INCRINIT_ROOT 2 - -/* -** Forward reference required as the vdbeIncrMergeInit() and -** vdbePmaReaderIncrInit() routines are called mutually recursively when -** building a merge tree. -*/ -static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); - -/* -** Initialize the MergeEngine object passed as the second argument. Once this -** function returns, the first key of merged data may be read from the -** MergeEngine object in the usual fashion. -** -** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge -** objects attached to the PmaReader objects that the merger reads from have -** already been populated, but that they have not yet populated aFile[0] and -** set the PmaReader objects up to read from it. In this case all that is -** required is to call vdbePmaReaderNext() on each PmaReader to point it at -** its first key. -** -** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use -** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data -** to pMerger. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbeMergeEngineInit( - SortSubtask *pTask, /* Thread that will run pMerger */ - MergeEngine *pMerger, /* MergeEngine to initialize */ - int eMode /* One of the INCRINIT_XXX constants */ -){ - int rc = SQLITE_OK; /* Return code */ - int i; /* For looping over PmaReader objects */ - int nTree; /* Number of subtrees to merge */ - - /* Failure to allocate the merge would have been detected prior to - ** invoking this routine */ - assert( pMerger!=0 ); - - /* eMode is always INCRINIT_NORMAL in single-threaded mode */ - assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - - /* Verify that the MergeEngine is assigned to a single thread */ - assert( pMerger->pTask==0 ); - pMerger->pTask = pTask; - - nTree = pMerger->nTree; - for(i=0; i0 && eMode==INCRINIT_ROOT ){ - /* PmaReaders should be normally initialized in order, as if they are - ** reading from the same temp file this makes for more linear file IO. - ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is - ** in use it will block the vdbePmaReaderNext() call while it uses - ** the main thread to fill its buffer. So calling PmaReaderNext() - ** on this PmaReader before any of the multi-threaded PmaReaders takes - ** better advantage of multi-processor hardware. */ - rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]); - }else{ - rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL); - } - if( rc!=SQLITE_OK ) return rc; - } - - for(i=pMerger->nTree-1; i>0; i--){ - vdbeMergeEngineCompare(pMerger, i); - } - return pTask->pUnpacked->errCode; -} - -/* -** The PmaReader passed as the first argument is guaranteed to be an -** incremental-reader (pReadr->pIncr!=0). This function serves to open -** and/or initialize the temp file related fields of the IncrMerge -** object at (pReadr->pIncr). -** -** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders -** in the sub-tree headed by pReadr are also initialized. Data is then -** loaded into the buffers belonging to pReadr and it is set to point to -** the first key in its range. -** -** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed -** to be a multi-threaded PmaReader and this function is being called in a -** background thread. In this case all PmaReaders in the sub-tree are -** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to -** pReadr is populated. However, pReadr itself is not set up to point -** to its first key. A call to vdbePmaReaderNext() is still required to do -** that. -** -** The reason this function does not call vdbePmaReaderNext() immediately -** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has -** to block on thread (pTask->thread) before accessing aFile[1]. But, since -** this entire function is being run by thread (pTask->thread), that will -** lead to the current background thread attempting to join itself. -** -** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed -** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all -** child-trees have already been initialized using IncrInit(INCRINIT_TASK). -** In this case vdbePmaReaderNext() is called on all child PmaReaders and -** the current PmaReader set to point to the first key in its range. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ - int rc = SQLITE_OK; - IncrMerger *pIncr = pReadr->pIncr; - SortSubtask *pTask = pIncr->pTask; - sqlite3 *db = pTask->pSorter->db; - - /* eMode is always INCRINIT_NORMAL in single-threaded mode */ - assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - - rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - - /* Set up the required files for pIncr. A multi-threaded IncrMerge object - ** requires two temp files to itself, whereas a single-threaded object - ** only requires a region of pTask->file2. */ - if( rc==SQLITE_OK ){ - int mxSz = pIncr->mxSz; -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); - if( rc==SQLITE_OK ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); - } - }else -#endif - /*if( !pIncr->bUseThread )*/{ - if( pTask->file2.pFd==0 ){ - assert( pTask->file2.iEof>0 ); - rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); - pTask->file2.iEof = 0; - } - if( rc==SQLITE_OK ){ - pIncr->aFile[1].pFd = pTask->file2.pFd; - pIncr->iStartOff = pTask->file2.iEof; - pTask->file2.iEof += mxSz; - } - } - } - -#if SQLITE_MAX_WORKER_THREADS>0 - if( rc==SQLITE_OK && pIncr->bUseThread ){ - /* Use the current thread to populate aFile[1], even though this - ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, - ** then this function is already running in background thread - ** pIncr->pTask->thread. - ** - ** If this is the INCRINIT_ROOT object, then it is running in the - ** main VDBE thread. But that is Ok, as that thread cannot return - ** control to the VDBE or proceed with anything useful until the - ** first results are ready from this merger object anyway. - */ - assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); - rc = vdbeIncrPopulate(pIncr); - } -#endif - - if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){ - rc = vdbePmaReaderNext(pReadr); - } - - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for vdbePmaReaderIncrMergeInit() operations run in -** background threads. -*/ -static void *vdbePmaReaderBgIncrInit(void *pCtx){ - PmaReader *pReader = (PmaReader*)pCtx; - void *pRet = SQLITE_INT_TO_PTR( - vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK) - ); - pReader->pIncr->pTask->bDone = 1; - return pRet; -} -#endif - -/* -** If the PmaReader passed as the first argument is not an incremental-reader -** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes -** the vdbePmaReaderIncrMergeInit() function with the parameters passed to -** this routine to initialize the incremental merge. -** -** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), -** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). -** Or, if the IncrMerger is single threaded, the same function is called -** using the current thread. -*/ -static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ - IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */ - int rc = SQLITE_OK; /* Return code */ - if( pIncr ){ -#if SQLITE_MAX_WORKER_THREADS>0 - assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK ); - if( pIncr->bUseThread ){ - void *pCtx = (void*)pReadr; - rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx); - }else -#endif - { - rc = vdbePmaReaderIncrMergeInit(pReadr, eMode); - } - } - return rc; -} - -/* -** Allocate a new MergeEngine object to merge the contents of nPMA level-0 -** PMAs from pTask->file. If no error occurs, set *ppOut to point to -** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut -** to NULL and return an SQLite error code. -** -** When this function is called, *piOffset is set to the offset of the -** first PMA to read from pTask->file. Assuming no error occurs, it is -** set to the offset immediately following the last byte of the last -** PMA before returning. If an error does occur, then the final value of -** *piOffset is undefined. -*/ -static int vdbeMergeEngineLevel0( - SortSubtask *pTask, /* Sorter task to read from */ - int nPMA, /* Number of PMAs to read */ - i64 *piOffset, /* IN/OUT: Readr offset in pTask->file */ - MergeEngine **ppOut /* OUT: New merge-engine */ -){ - MergeEngine *pNew; /* Merge engine to return */ - i64 iOff = *piOffset; - int i; - int rc = SQLITE_OK; - - *ppOut = pNew = vdbeMergeEngineNew(nPMA); - if( pNew==0 ) rc = SQLITE_NOMEM_BKPT; - - for(i=0; iaReadr[i]; - rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy); - iOff = pReadr->iEof; - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pNew); - *ppOut = 0; - } - *piOffset = iOff; - return rc; -} - -/* -** Return the depth of a tree comprising nPMA PMAs, assuming a fanout of -** SORTER_MAX_MERGE_COUNT. The returned value does not include leaf nodes. -** -** i.e. -** -** nPMA<=16 -> TreeDepth() == 0 -** nPMA<=256 -> TreeDepth() == 1 -** nPMA<=65536 -> TreeDepth() == 2 -*/ -static int vdbeSorterTreeDepth(int nPMA){ - int nDepth = 0; - i64 nDiv = SORTER_MAX_MERGE_COUNT; - while( nDiv < (i64)nPMA ){ - nDiv = nDiv * SORTER_MAX_MERGE_COUNT; - nDepth++; - } - return nDepth; -} - -/* -** pRoot is the root of an incremental merge-tree with depth nDepth (according -** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the -** tree, counting from zero. This function adds pLeaf to the tree. -** -** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error -** code is returned and pLeaf is freed. -*/ -static int vdbeSorterAddToTree( - SortSubtask *pTask, /* Task context */ - int nDepth, /* Depth of tree according to TreeDepth() */ - int iSeq, /* Sequence number of leaf within tree */ - MergeEngine *pRoot, /* Root of tree */ - MergeEngine *pLeaf /* Leaf to add to tree */ -){ - int rc = SQLITE_OK; - int nDiv = 1; - int i; - MergeEngine *p = pRoot; - IncrMerger *pIncr; - - rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr); - - for(i=1; iaReadr[iIter]; - - if( pReadr->pIncr==0 ){ - MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); - if( pNew==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr); - } - } - if( rc==SQLITE_OK ){ - p = pReadr->pIncr->pMerger; - nDiv = nDiv / SORTER_MAX_MERGE_COUNT; - } - } - - if( rc==SQLITE_OK ){ - p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr; - }else{ - vdbeIncrFree(pIncr); - } - return rc; -} - -/* -** This function is called as part of a SorterRewind() operation on a sorter -** that has already written two or more level-0 PMAs to one or more temp -** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that -** can be used to incrementally merge all PMAs on disk. -** -** If successful, SQLITE_OK is returned and *ppOut set to point to the -** MergeEngine object at the root of the tree before returning. Or, if an -** error occurs, an SQLite error code is returned and the final value -** of *ppOut is undefined. -*/ -static int vdbeSorterMergeTreeBuild( - VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */ - MergeEngine **ppOut /* Write the MergeEngine here */ -){ - MergeEngine *pMain = 0; - int rc = SQLITE_OK; - int iTask; - -#if SQLITE_MAX_WORKER_THREADS>0 - /* If the sorter uses more than one task, then create the top-level - ** MergeEngine here. This MergeEngine will read data from exactly - ** one PmaReader per sub-task. */ - assert( pSorter->bUseThreads || pSorter->nTask==1 ); - if( pSorter->nTask>1 ){ - pMain = vdbeMergeEngineNew(pSorter->nTask); - if( pMain==0 ) rc = SQLITE_NOMEM_BKPT; - } -#endif - - for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ - SortSubtask *pTask = &pSorter->aTask[iTask]; - assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 ); - if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){ - MergeEngine *pRoot = 0; /* Root node of tree for this task */ - int nDepth = vdbeSorterTreeDepth(pTask->nPMA); - i64 iReadOff = 0; - - if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){ - rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot); - }else{ - int i; - int iSeq = 0; - pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); - if( pRoot==0 ) rc = SQLITE_NOMEM_BKPT; - for(i=0; inPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){ - MergeEngine *pMerger = 0; /* New level-0 PMA merger */ - int nReader; /* Number of level-0 PMAs to merge */ - - nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT); - rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger); - if( rc==SQLITE_OK ){ - rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger); - } - } - } - - if( rc==SQLITE_OK ){ -#if SQLITE_MAX_WORKER_THREADS>0 - if( pMain!=0 ){ - rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr); - }else -#endif - { - assert( pMain==0 ); - pMain = pRoot; - } - }else{ - vdbeMergeEngineFree(pRoot); - } - } - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pMain); - pMain = 0; - } - *ppOut = pMain; - return rc; -} - -/* -** This function is called as part of an sqlite3VdbeSorterRewind() operation -** on a sorter that has written two or more PMAs to temporary files. It sets -** up either VdbeSorter.pMerger (for single threaded sorters) or pReader -** (for multi-threaded sorters) so that it can be used to iterate through -** all records stored in the sorter. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ - int rc; /* Return code */ - SortSubtask *pTask0 = &pSorter->aTask[0]; - MergeEngine *pMain = 0; -#if SQLITE_MAX_WORKER_THREADS - sqlite3 *db = pTask0->pSorter->db; - int i; - SorterCompare xCompare = vdbeSorterGetCompare(pSorter); - for(i=0; inTask; i++){ - pSorter->aTask[i].xCompare = xCompare; - } -#endif - - rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); - if( rc==SQLITE_OK ){ -#if SQLITE_MAX_WORKER_THREADS - assert( pSorter->bUseThreads==0 || pSorter->nTask>1 ); - if( pSorter->bUseThreads ){ - int iTask; - PmaReader *pReadr = 0; - SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1]; - rc = vdbeSortAllocUnpacked(pLast); - if( rc==SQLITE_OK ){ - pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader)); - pSorter->pReader = pReadr; - if( pReadr==0 ) rc = SQLITE_NOMEM_BKPT; - } - if( rc==SQLITE_OK ){ - rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr); - if( rc==SQLITE_OK ){ - vdbeIncrMergerSetThreads(pReadr->pIncr); - for(iTask=0; iTask<(pSorter->nTask-1); iTask++){ - IncrMerger *pIncr; - if( (pIncr = pMain->aReadr[iTask].pIncr) ){ - vdbeIncrMergerSetThreads(pIncr); - assert( pIncr->pTask!=pLast ); - } - } - for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ - /* Check that: - ** - ** a) The incremental merge object is configured to use the - ** right task, and - ** b) If it is using task (nTask-1), it is configured to run - ** in single-threaded mode. This is important, as the - ** root merge (INCRINIT_ROOT) will be using the same task - ** object. - */ - PmaReader *p = &pMain->aReadr[iTask]; - assert( p->pIncr==0 || ( - (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */ - && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */ - )); - rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK); - } - } - pMain = 0; - } - if( rc==SQLITE_OK ){ - rc = vdbePmaReaderIncrMergeInit(pReadr, INCRINIT_ROOT); - } - }else -#endif - { - rc = vdbeMergeEngineInit(pTask0, pMain, INCRINIT_NORMAL); - pSorter->pMerger = pMain; - pMain = 0; - } - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pMain); - } - return rc; -} - - -/* -** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite, -** this function is called to prepare for iterating through the records -** in sorted order. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ - VdbeSorter *pSorter; - int rc = SQLITE_OK; /* Return code */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - assert( pSorter ); - - /* If no data has been written to disk, then do not do so now. Instead, - ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly - ** from the in-memory list. */ - if( pSorter->bUsePMA==0 ){ - if( pSorter->list.pList ){ - *pbEof = 0; - rc = vdbeSorterSort(&pSorter->aTask[0], &pSorter->list); - }else{ - *pbEof = 1; - } - return rc; - } - - /* Write the current in-memory list to a PMA. When the VdbeSorterWrite() - ** function flushes the contents of memory to disk, it immediately always - ** creates a new list consisting of a single key immediately afterwards. - ** So the list is never empty at this point. */ - assert( pSorter->list.pList ); - rc = vdbeSorterFlushPMA(pSorter); - - /* Join all threads */ - rc = vdbeSorterJoinAll(pSorter, rc); - - vdbeSorterRewindDebug("rewind"); - - /* Assuming no errors have occurred, set up a merger structure to - ** incrementally read and merge all remaining PMAs. */ - assert( pSorter->pReader==0 ); - if( rc==SQLITE_OK ){ - rc = vdbeSorterSetupMerge(pSorter); - *pbEof = 0; - } - - vdbeSorterRewindDebug("rewinddone"); - return rc; -} - -/* -** Advance to the next element in the sorter. Return value: -** -** SQLITE_OK success -** SQLITE_DONE end of data -** otherwise some kind of error. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){ - VdbeSorter *pSorter; - int rc; /* Return code */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) ); - if( pSorter->bUsePMA ){ - assert( pSorter->pReader==0 || pSorter->pMerger==0 ); - assert( pSorter->bUseThreads==0 || pSorter->pReader ); - assert( pSorter->bUseThreads==1 || pSorter->pMerger ); -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->bUseThreads ){ - rc = vdbePmaReaderNext(pSorter->pReader); - if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE; - }else -#endif - /*if( !pSorter->bUseThreads )*/ { - int res = 0; - assert( pSorter->pMerger!=0 ); - assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) ); - rc = vdbeMergeEngineStep(pSorter->pMerger, &res); - if( rc==SQLITE_OK && res ) rc = SQLITE_DONE; - } - }else{ - SorterRecord *pFree = pSorter->list.pList; - pSorter->list.pList = pFree->u.pNext; - pFree->u.pNext = 0; - if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree); - rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE; - } - return rc; -} - -/* -** Return a pointer to a buffer owned by the sorter that contains the -** current key. -*/ -static void *vdbeSorterRowkey( - const VdbeSorter *pSorter, /* Sorter object */ - int *pnKey /* OUT: Size of current key in bytes */ -){ - void *pKey; - if( pSorter->bUsePMA ){ - PmaReader *pReader; -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->bUseThreads ){ - pReader = pSorter->pReader; - }else -#endif - /*if( !pSorter->bUseThreads )*/{ - pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]]; - } - *pnKey = pReader->nKey; - pKey = pReader->aKey; - }else{ - *pnKey = pSorter->list.pList->nVal; - pKey = SRVAL(pSorter->list.pList); - } - return pKey; -} - -/* -** Copy the current sorter key into the memory cell pOut. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ - VdbeSorter *pSorter; - void *pKey; int nKey; /* Sorter key to copy into pOut */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - pKey = vdbeSorterRowkey(pSorter, &nKey); - if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){ - return SQLITE_NOMEM_BKPT; - } - pOut->n = nKey; - MemSetTypeFlag(pOut, MEM_Blob); - memcpy(pOut->z, pKey, nKey); - - return SQLITE_OK; -} - -/* -** Compare the key in memory cell pVal with the key that the sorter cursor -** passed as the first argument currently points to. For the purposes of -** the comparison, ignore the rowid field at the end of each record. -** -** If the sorter cursor key contains any NULL values, consider it to be -** less than pVal. Even if pVal also contains NULL values. -** -** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). -** Otherwise, set *pRes to a negative, zero or positive value if the -** key in pVal is smaller than, equal to or larger than the current sorter -** key. -** -** This routine forms the core of the OP_SorterCompare opcode, which in -** turn is used to verify uniqueness when constructing a UNIQUE INDEX. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterCompare( - const VdbeCursor *pCsr, /* Sorter cursor */ - Mem *pVal, /* Value to compare to current sorter key */ - int nKeyCol, /* Compare this many columns */ - int *pRes /* OUT: Result of comparison */ -){ - VdbeSorter *pSorter; - UnpackedRecord *r2; - KeyInfo *pKeyInfo; - int i; - void *pKey; int nKey; /* Sorter key to compare pVal with */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - r2 = pSorter->pUnpacked; - pKeyInfo = pCsr->pKeyInfo; - if( r2==0 ){ - r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); - if( r2==0 ) return SQLITE_NOMEM_BKPT; - r2->nField = nKeyCol; - } - assert( r2->nField==nKeyCol ); - - pKey = vdbeSorterRowkey(pSorter, &nKey); - sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2); - for(i=0; iaMem[i].flags & MEM_Null ){ - *pRes = -1; - return SQLITE_OK; - } - } - - *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2); - return SQLITE_OK; -} - -/************** End of vdbesort.c ********************************************/ -/************** Begin file vdbevtab.c ****************************************/ -/* -** 2020-03-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 virtual-tables for examining the bytecode content -** of a prepared statement. -*/ -/* #include "sqliteInt.h" */ -#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE) -/* #include "vdbeInt.h" */ - -/* An instance of the bytecode() table-valued function. -*/ -typedef struct bytecodevtab bytecodevtab; -struct bytecodevtab { - sqlite3_vtab base; /* Base class - must be first */ - sqlite3 *db; /* Database connection */ - int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */ -}; - -/* A cursor for scanning through the bytecode -*/ -typedef struct bytecodevtab_cursor bytecodevtab_cursor; -struct bytecodevtab_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */ - int iRowid; /* The rowid of the output table */ - int iAddr; /* Address */ - int needFinalize; /* Cursors owns pStmt and must finalize it */ - int showSubprograms; /* Provide a listing of subprograms */ - Op *aOp; /* Operand array */ - char *zP4; /* Rendered P4 value */ - const char *zType; /* tables_used.type */ - const char *zSchema; /* tables_used.schema */ - const char *zName; /* tables_used.name */ - Mem sub; /* Subprograms */ -}; - -/* -** Create a new bytecode() table-valued function. -*/ -static int bytecodevtabConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - bytecodevtab *pNew; - int rc; - int isTabUsed = pAux!=0; - const char *azSchema[2] = { - /* bytecode() schema */ - "CREATE TABLE x(" - "addr INT," - "opcode TEXT," - "p1 INT," - "p2 INT," - "p3 INT," - "p4 TEXT," - "p5 INT," - "comment TEXT," - "subprog TEXT," - "nexec INT," - "ncycle INT," - "stmt HIDDEN" - ");", - - /* Tables_used() schema */ - "CREATE TABLE x(" - "type TEXT," - "schema TEXT," - "name TEXT," - "wr INT," - "subprog TEXT," - "stmt HIDDEN" - ");" - }; - - (void)argc; - (void)argv; - (void)pzErr; - rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]); - if( rc==SQLITE_OK ){ - pNew = sqlite3_malloc( sizeof(*pNew) ); - *ppVtab = (sqlite3_vtab*)pNew; - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - pNew->db = db; - pNew->bTablesUsed = isTabUsed*2; - } - return rc; -} - -/* -** This method is the destructor for bytecodevtab objects. -*/ -static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){ - bytecodevtab *p = (bytecodevtab*)pVtab; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Constructor for a new bytecodevtab_cursor object. -*/ -static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - bytecodevtab *pVTab = (bytecodevtab*)p; - bytecodevtab_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Clear all internal content from a bytecodevtab cursor. -*/ -static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){ - sqlite3_free(pCur->zP4); - pCur->zP4 = 0; - sqlite3VdbeMemRelease(&pCur->sub); - sqlite3VdbeMemSetNull(&pCur->sub); - if( pCur->needFinalize ){ - sqlite3_finalize(pCur->pStmt); - } - pCur->pStmt = 0; - pCur->needFinalize = 0; - pCur->zType = 0; - pCur->zSchema = 0; - pCur->zName = 0; -} - -/* -** Destructor for a bytecodevtab_cursor. -*/ -static int bytecodevtabClose(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtabCursorClear(pCur); - sqlite3_free(pCur); - return SQLITE_OK; -} - - -/* -** Advance a bytecodevtab_cursor to its next row of output. -*/ -static int bytecodevtabNext(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtab *pTab = (bytecodevtab*)cur->pVtab; - int rc; - if( pCur->zP4 ){ - sqlite3_free(pCur->zP4); - pCur->zP4 = 0; - } - if( pCur->zName ){ - pCur->zName = 0; - pCur->zType = 0; - pCur->zSchema = 0; - } - rc = sqlite3VdbeNextOpcode( - (Vdbe*)pCur->pStmt, - pCur->showSubprograms ? &pCur->sub : 0, - pTab->bTablesUsed, - &pCur->iRowid, - &pCur->iAddr, - &pCur->aOp); - if( rc!=SQLITE_OK ){ - sqlite3VdbeMemSetNull(&pCur->sub); - pCur->aOp = 0; - } - return SQLITE_OK; -} - -/* -** Return TRUE if the cursor has been moved off of the last -** row of output. -*/ -static int bytecodevtabEof(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - return pCur->aOp==0; -} - -/* -** Return values of columns for the row at which the bytecodevtab_cursor -** is currently pointing. -*/ -static int bytecodevtabColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ -){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab; - Op *pOp = pCur->aOp + pCur->iAddr; - if( pVTab->bTablesUsed ){ - if( i==4 ){ - i = 8; - }else{ - if( i<=2 && pCur->zType==0 ){ - Schema *pSchema; - HashElem *k; - int iDb = pOp->p3; - Pgno iRoot = (Pgno)pOp->p2; - sqlite3 *db = pVTab->db; - pSchema = db->aDb[iDb].pSchema; - pCur->zSchema = db->aDb[iDb].zDbSName; - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pTab = (Table*)sqliteHashData(k); - if( !IsVirtual(pTab) && pTab->tnum==iRoot ){ - pCur->zName = pTab->zName; - pCur->zType = "table"; - break; - } - } - if( pCur->zName==0 ){ - for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){ - Index *pIdx = (Index*)sqliteHashData(k); - if( pIdx->tnum==iRoot ){ - pCur->zName = pIdx->zName; - pCur->zType = "index"; - } - } - } - } - i += 20; - } - } - switch( i ){ - case 0: /* addr */ - sqlite3_result_int(ctx, pCur->iAddr); - break; - case 1: /* opcode */ - sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode), - -1, SQLITE_STATIC); - break; - case 2: /* p1 */ - sqlite3_result_int(ctx, pOp->p1); - break; - case 3: /* p2 */ - sqlite3_result_int(ctx, pOp->p2); - break; - case 4: /* p3 */ - sqlite3_result_int(ctx, pOp->p3); - break; - case 5: /* p4 */ - case 7: /* comment */ - if( pCur->zP4==0 ){ - pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp); - } - if( i==5 ){ - sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC); - }else{ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4); - sqlite3_result_text(ctx, zCom, -1, sqlite3_free); -#endif - } - break; - case 6: /* p5 */ - sqlite3_result_int(ctx, pOp->p5); - break; - case 8: { /* subprog */ - Op *aOp = pCur->aOp; - assert( aOp[0].opcode==OP_Init ); - assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 ); - if( pCur->iRowid==pCur->iAddr+1 ){ - break; /* Result is NULL for the main program */ - }else if( aOp[0].p4.z!=0 ){ - sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC); - }else{ - sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC); - } - break; - } - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - case 9: /* nexec */ - sqlite3_result_int64(ctx, pOp->nExec); - break; - case 10: /* ncycle */ - sqlite3_result_int64(ctx, pOp->nCycle); - break; -#else - case 9: /* nexec */ - case 10: /* ncycle */ - sqlite3_result_int(ctx, 0); - break; -#endif - - case 20: /* tables_used.type */ - sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC); - break; - case 21: /* tables_used.schema */ - sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC); - break; - case 22: /* tables_used.name */ - sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC); - break; - case 23: /* tables_used.wr */ - sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite); - break; - } - return SQLITE_OK; -} - -/* -** Return the rowid for the current row. In this implementation, the -** rowid is the same as the output value. -*/ -static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; -} - -/* -** Initialize a cursor. -** -** idxNum==0 means show all subprograms -** idxNum==1 means show only the main bytecode and omit subprograms. -*/ -static int bytecodevtabFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor; - bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab; - int rc = SQLITE_OK; - (void)idxStr; - - bytecodevtabCursorClear(pCur); - pCur->iRowid = 0; - pCur->iAddr = 0; - pCur->showSubprograms = idxNum==0; - assert( argc==1 ); - if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0); - pCur->needFinalize = 1; - } - }else{ - pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer"); - } - if( pCur->pStmt==0 ){ - pVTab->base.zErrMsg = sqlite3_mprintf( - "argument to %s() is not a valid SQL statement", - pVTab->bTablesUsed ? "tables_used" : "bytecode" - ); - rc = SQLITE_ERROR; - }else{ - bytecodevtabNext(pVtabCursor); - } - return rc; -} - -/* -** We must have a single stmt=? constraint that will be passed through -** into the xFilter method. If there is no valid stmt=? constraint, -** then return an SQLITE_CONSTRAINT error. -*/ -static int bytecodevtabBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; - int rc = SQLITE_CONSTRAINT; - struct sqlite3_index_constraint *p; - bytecodevtab *pVTab = (bytecodevtab*)tab; - int iBaseCol = pVTab->bTablesUsed ? 4 : 10; - pIdxInfo->estimatedCost = (double)100; - pIdxInfo->estimatedRows = 100; - pIdxInfo->idxNum = 0; - for(i=0, p=pIdxInfo->aConstraint; inConstraint; i++, p++){ - if( p->usable==0 ) continue; - if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){ - rc = SQLITE_OK; - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - } - if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){ - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->idxNum = 1; - } - } - return rc; -} - -/* -** This following structure defines all the methods for the -** virtual table. -*/ -static sqlite3_module bytecodevtabModule = { - /* iVersion */ 0, - /* xCreate */ 0, - /* xConnect */ bytecodevtabConnect, - /* xBestIndex */ bytecodevtabBestIndex, - /* xDisconnect */ bytecodevtabDisconnect, - /* xDestroy */ 0, - /* xOpen */ bytecodevtabOpen, - /* xClose */ bytecodevtabClose, - /* xFilter */ bytecodevtabFilter, - /* xNext */ bytecodevtabNext, - /* xEof */ bytecodevtabEof, - /* xColumn */ bytecodevtabColumn, - /* xRowid */ bytecodevtabRowid, - /* xUpdate */ 0, - /* xBegin */ 0, - /* xSync */ 0, - /* xCommit */ 0, - /* xRollback */ 0, - /* xFindMethod */ 0, - /* xRename */ 0, - /* xSavepoint */ 0, - /* xRelease */ 0, - /* xRollbackTo */ 0, - /* xShadowName */ 0, - /* xIntegrity */ 0 -}; - - -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ - int rc; - rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db); - } - return rc; -} -#elif defined(SQLITE_ENABLE_BYTECODE_VTAB) -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; } -#endif /* SQLITE_ENABLE_BYTECODE_VTAB */ - -/************** End of vdbevtab.c ********************************************/ -/************** Begin file memjournal.c **************************************/ -/* -** 2008 October 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to implement an in-memory rollback journal. -** The in-memory rollback journal is used to journal transactions for -** ":memory:" databases and when the journal_mode=MEMORY pragma is used. -** -** Update: The in-memory journal is also used to temporarily cache -** smaller journals that are not critical for power-loss recovery. -** For example, statement journals that are not too big will be held -** entirely in memory, thus reducing the number of file I/O calls, and -** more importantly, reducing temporary file creation events. If these -** journals become too large for memory, they are spilled to disk. But -** in the common case, they are usually small and no file I/O needs to -** occur. -*/ -/* #include "sqliteInt.h" */ - -/* Forward references to internal structures */ -typedef struct MemJournal MemJournal; -typedef struct FilePoint FilePoint; -typedef struct FileChunk FileChunk; - -/* -** The rollback journal is composed of a linked list of these structures. -** -** The zChunk array is always at least 8 bytes in size - usually much more. -** Its actual size is stored in the MemJournal.nChunkSize variable. -*/ -struct FileChunk { - FileChunk *pNext; /* Next chunk in the journal */ - u8 zChunk[8]; /* Content of this chunk */ -}; - -/* -** By default, allocate this many bytes of memory for each FileChunk object. -*/ -#define MEMJOURNAL_DFLT_FILECHUNKSIZE 1024 - -/* -** For chunk size nChunkSize, return the number of bytes that should -** be allocated for each FileChunk structure. -*/ -#define fileChunkSize(nChunkSize) (sizeof(FileChunk) + ((nChunkSize)-8)) - -/* -** An instance of this object serves as a cursor into the rollback journal. -** The cursor can be either for reading or writing. -*/ -struct FilePoint { - sqlite3_int64 iOffset; /* Offset from the beginning of the file */ - FileChunk *pChunk; /* Specific chunk into which cursor points */ -}; - -/* -** This structure is a subclass of sqlite3_file. Each open memory-journal -** is an instance of this class. -*/ -struct MemJournal { - const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ - int nChunkSize; /* In-memory chunk-size */ - - int nSpill; /* Bytes of data before flushing */ - 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() */ - - int flags; /* xOpen flags */ - sqlite3_vfs *pVfs; /* The "real" underlying VFS */ - const char *zJournal; /* Name of the journal file */ -}; - -/* -** Read data from the in-memory journal file. This is the implementation -** of the sqlite3_vfs.xRead method. -*/ -static int memjrnlRead( - sqlite3_file *pJfd, /* The journal file from which to read */ - void *zBuf, /* Put the results here */ - int iAmt, /* Number of bytes to read */ - sqlite_int64 iOfst /* Begin reading at this offset */ -){ - MemJournal *p = (MemJournal *)pJfd; - u8 *zOut = zBuf; - int nRead = iAmt; - int iChunkOffset; - FileChunk *pChunk; - - if( (iAmt+iOfst)>p->endpoint.iOffset ){ - return SQLITE_IOERR_SHORT_READ; - } - assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 ); - if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ - sqlite3_int64 iOff = 0; - for(pChunk=p->pFirst; - ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; - pChunk=pChunk->pNext - ){ - iOff += p->nChunkSize; - } - }else{ - pChunk = p->readpoint.pChunk; - assert( pChunk!=0 ); - } - - iChunkOffset = (int)(iOfst%p->nChunkSize); - do { - int iSpace = p->nChunkSize - iChunkOffset; - int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset)); - memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy); - zOut += nCopy; - nRead -= iSpace; - iChunkOffset = 0; - } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); - p->readpoint.iOffset = pChunk ? iOfst+iAmt : 0; - p->readpoint.pChunk = pChunk; - - return SQLITE_OK; -} - -/* -** Free the list of FileChunk structures headed at MemJournal.pFirst. -*/ -static void memjrnlFreeChunks(FileChunk *pFirst){ - FileChunk *pIter; - FileChunk *pNext; - for(pIter=pFirst; pIter; pIter=pNext){ - pNext = pIter->pNext; - sqlite3_free(pIter); - } -} - -/* -** Flush the contents of memory to a real file on disk. -*/ -static int memjrnlCreateFile(MemJournal *p){ - int rc; - sqlite3_file *pReal = (sqlite3_file*)p; - MemJournal copy = *p; - - memset(p, 0, sizeof(MemJournal)); - rc = sqlite3OsOpen(copy.pVfs, copy.zJournal, pReal, copy.flags, 0); - if( rc==SQLITE_OK ){ - int nChunk = copy.nChunkSize; - i64 iOff = 0; - FileChunk *pIter; - for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){ - if( iOff + nChunk > copy.endpoint.iOffset ){ - nChunk = copy.endpoint.iOffset - iOff; - } - rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff); - if( rc ) break; - iOff += nChunk; - } - if( rc==SQLITE_OK ){ - /* No error has occurred. Free the in-memory buffers. */ - memjrnlFreeChunks(copy.pFirst); - } - } - if( rc!=SQLITE_OK ){ - /* If an error occurred while creating or writing to the file, restore - ** the original before returning. This way, SQLite uses the in-memory - ** journal data to roll back changes made to the internal page-cache - ** before this function was called. */ - sqlite3OsClose(pReal); - *p = copy; - } - return rc; -} - - -/* Forward reference */ -static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size); - -/* -** Write data to the file. -*/ -static int memjrnlWrite( - sqlite3_file *pJfd, /* The journal file into which to write */ - const void *zBuf, /* Take data to be written from here */ - int iAmt, /* Number of bytes to write */ - sqlite_int64 iOfst /* Begin writing at this offset into the file */ -){ - MemJournal *p = (MemJournal *)pJfd; - int nWrite = iAmt; - u8 *zWrite = (u8 *)zBuf; - - /* If the file should be created now, create it and write the new data - ** into the file on disk. */ - if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){ - int rc = memjrnlCreateFile(p); - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pJfd, zBuf, iAmt, iOfst); - } - return rc; - } - - /* If the contents of this write should be stored in memory */ - else{ - /* An in-memory journal file should only ever be appended to. Random - ** access writes are not required. The only exception to this is when - ** 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 ); - 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{ - 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 = sqlite3_malloc(fileChunkSize(p->nChunkSize)); - if( !pNew ){ - return SQLITE_IOERR_NOMEM_BKPT; - } - pNew->pNext = 0; - if( pChunk ){ - assert( p->pFirst ); - pChunk->pNext = pNew; - }else{ - assert( !p->pFirst ); - p->pFirst = pNew; - } - pChunk = p->endpoint.pChunk = pNew; - } - - assert( pChunk!=0 ); - memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace); - zWrite += iSpace; - nWrite -= iSpace; - p->endpoint.iOffset += iSpace; - } - } - } - - return SQLITE_OK; -} - -/* -** Truncate the in-memory file. -*/ -static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ - MemJournal *p = (MemJournal *)pJfd; - assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 ); - if( sizeendpoint.iOffset ){ - FileChunk *pIter = 0; - if( size==0 ){ - memjrnlFreeChunks(p->pFirst); - p->pFirst = 0; - }else{ - i64 iOff = p->nChunkSize; - for(pIter=p->pFirst; ALWAYS(pIter) && iOffpNext){ - 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; - } - return SQLITE_OK; -} - -/* -** Close the file. -*/ -static int memjrnlClose(sqlite3_file *pJfd){ - MemJournal *p = (MemJournal *)pJfd; - memjrnlFreeChunks(p->pFirst); - return SQLITE_OK; -} - -/* -** Sync the file. -** -** If the real file has been created, call its xSync method. Otherwise, -** syncing an in-memory journal is a no-op. -*/ -static int memjrnlSync(sqlite3_file *pJfd, int flags){ - UNUSED_PARAMETER2(pJfd, flags); - return SQLITE_OK; -} - -/* -** Query the size of the file in bytes. -*/ -static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ - MemJournal *p = (MemJournal *)pJfd; - *pSize = (sqlite_int64) p->endpoint.iOffset; - return SQLITE_OK; -} - -/* -** Table of methods for MemJournal sqlite3_file object. -*/ -static const struct sqlite3_io_methods MemJournalMethods = { - 1, /* iVersion */ - memjrnlClose, /* xClose */ - memjrnlRead, /* xRead */ - memjrnlWrite, /* xWrite */ - memjrnlTruncate, /* xTruncate */ - memjrnlSync, /* xSync */ - memjrnlFileSize, /* xFileSize */ - 0, /* xLock */ - 0, /* xUnlock */ - 0, /* xCheckReservedLock */ - 0, /* xFileControl */ - 0, /* xSectorSize */ - 0, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/* -** Open a journal file. -** -** The behaviour of the journal file depends on the value of parameter -** nSpill. If nSpill is 0, then the journal file is always create and -** accessed using the underlying VFS. If nSpill is less than zero, then -** all content is always stored in main-memory. Finally, if nSpill is a -** positive value, then the journal file is initially created in-memory -** but may be flushed to disk later on. In this case the journal file is -** flushed to disk either when it grows larger than nSpill bytes in size, -** or when sqlite3JournalCreate() is called. -*/ -SQLITE_PRIVATE int sqlite3JournalOpen( - sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ - const char *zName, /* Name of the journal file */ - sqlite3_file *pJfd, /* Preallocated, blank file handle */ - int flags, /* Opening flags */ - int nSpill /* Bytes buffered before opening the file */ -){ - MemJournal *p = (MemJournal*)pJfd; - - assert( zName || nSpill<0 || (flags & SQLITE_OPEN_EXCLUSIVE) ); - - /* Zero the file-handle object. If nSpill was passed zero, initialize - ** it using the sqlite3OsOpen() function of the underlying VFS. In this - ** case none of the code in this module is executed as a result of calls - ** made on the journal file-handle. */ - memset(p, 0, sizeof(MemJournal)); - if( nSpill==0 ){ - return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); - } - - if( nSpill>0 ){ - p->nChunkSize = nSpill; - }else{ - p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk); - assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) ); - } - - pJfd->pMethods = (const sqlite3_io_methods*)&MemJournalMethods; - p->nSpill = nSpill; - p->flags = flags; - p->zJournal = zName; - p->pVfs = pVfs; - return SQLITE_OK; -} - -/* -** Open an in-memory journal file. -*/ -SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ - sqlite3JournalOpen(0, 0, pJfd, 0, -1); -} - -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) -/* -** If the argument p points to a MemJournal structure that is not an -** in-memory-only journal file (i.e. is one that was opened with a +ve -** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying -** file has not yet been created, create it now. -*/ -SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *pJfd){ - int rc = SQLITE_OK; - MemJournal *p = (MemJournal*)pJfd; - if( pJfd->pMethods==&MemJournalMethods && ( -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - p->nSpill>0 -#else - /* While this appears to not be possible without ATOMIC_WRITE, the - ** paths are complex, so it seems prudent to leave the test in as - ** a NEVER(), in case our analysis is subtly flawed. */ - NEVER(p->nSpill>0) -#endif -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - || (p->flags & SQLITE_OPEN_MAIN_JOURNAL) -#endif - )){ - rc = memjrnlCreateFile(p); - } - return rc; -} -#endif - -/* -** The file-handle passed as the only argument is open on a journal file. -** Return true if this "journal file" is currently stored in heap memory, -** or false otherwise. -*/ -SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p){ - return p->pMethods==&MemJournalMethods; -} - -/* -** Return the number of bytes required to store a JournalFile that uses vfs -** pVfs to create the underlying on-disk files. -*/ -SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ - return MAX(pVfs->szOsFile, (int)sizeof(MemJournal)); -} - -/************** End of memjournal.c ******************************************/ -/************** Begin file sqlcipher.c ***************************************/ -/* -** SQLCipher -** http://zetetic.net -** -** Copyright (c) 2008-2024, 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 - -#if !defined(SQLCIPHER_OMIT_LOG_DEVICE) -#if defined(__ANDROID__) -#include -#elif defined(__APPLE__) -/* #include */ -#include -#endif -#endif - -/* #include */ - -#if defined(_WIN32) || defined(SQLITE_OS_WINRT) -/* #include ** amalgamator: dontcache ** */ -#else -/* #include ** amalgamator: dontcache ** */ -#endif - -#ifndef OMIT_MEMLOCK -#if defined(__unix__) || defined(__APPLE__) || defined(_AIX) -/* #include ** amalgamator: dontcache ** */ -/* #include ** amalgamator: dontcache ** */ -#include /* amalgamator: dontcache */ -/* #include ** amalgamator: dontcache ** */ -#endif -#endif - -/* #include */ -/************** Include sqlcipher.h in the middle of sqlcipher.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 "sqlite3.h" */ -/* #include "sqliteInt.h" */ - -#define SQLCIPHER_DECRYPT 0 -#define SQLCIPHER_ENCRYPT 1 - -#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 sqlcipher_provider sqlcipher_provider; -struct sqlcipher_provider { - int (*init)(void); - void (*shutdown)(void); - const char* (*get_provider_name)(void *ctx); - int (*add_random)(void *ctx, const void *buffer, int length); - int (*random)(void *ctx, void *buffer, int length); - int (*hmac)(void *ctx, int algorithm, - const unsigned char *hmac_key, int key_sz, - const unsigned char *in, int in_sz, - const unsigned char *in2, int in2_sz, - unsigned char *out); - int (*kdf)(void *ctx, int algorithm, - const unsigned char *pass, int pass_sz, - const unsigned char* salt, int salt_sz, - int workfactor, - int key_sz, unsigned char *key); - int (*cipher)(void *ctx, int mode, - const unsigned char *key, int key_sz, - const unsigned char *iv, - const 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 *next; -}; - -/* public interfaces called externally */ -int sqlcipher_extra_init(const char*); -void sqlcipher_extra_shutdown(void); -void sqlcipher_init_memmethods(void); -int sqlcipher_codec_pragma(sqlite3*, int, Parse*, const char *, const char*); -int sqlcipherCodecAttach(sqlite3*, int, const void *, int); -void sqlcipherCodecGetKey(sqlite3*, int, void**, int*); -int sqlcipher_find_db_index(sqlite3 *, const char *); - -/* utility functions */ -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_malloc(sqlite_uint64); -void sqlcipher_free(void *, sqlite_uint64); -char* sqlcipher_version(void); - -/* 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_MEM 6 -#define SQLCIPHER_MUTEX_SHAREDCACHE 7 -#define SQLCIPHER_MUTEX_COUNT 8 - -sqlite3_mutex* sqlcipher_mutex(int); - -#define SQLCIPHER_LOG_NONE 0 -#define SQLCIPHER_LOG_ANY 0xffffffff - -#define SQLCIPHER_LOG_ERROR (1<<0) -#define SQLCIPHER_LOG_WARN (1<<1) -#define SQLCIPHER_LOG_INFO (1<<2) -#define SQLCIPHER_LOG_DEBUG (1<<3) -#define SQLCIPHER_LOG_TRACE (1<<4) - -#define SQLCIPHER_LOG_CORE (1<<0) -#define SQLCIPHER_LOG_MEMORY (1<<1) -#define SQLCIPHER_LOG_MUTEX (1<<2) -#define SQLCIPHER_LOG_PROVIDER (1<<3) - -#ifdef SQLCIPHER_OMIT_LOG -#define sqlcipher_log(level, source, message, ...) -#else -void sqlcipher_log(unsigned int level, unsigned int source, const char *message, ...); -#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) -#endif - -#endif -#endif -/* END SQLCIPHER */ - - -/************** End of sqlcipher.h *******************************************/ -/************** Continuing where we left off in sqlcipher.c ******************/ -/* #include "btreeInt.h" */ -/* #include "pager.h" */ -/* #include "vdbeInt.h" */ - -#if !defined(SQLITE_EXTRA_INIT) || !defined(SQLITE_EXTRA_SHUTDOWN) -#error "SQLCipher must be compiled with -DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown" -#endif - -#if !defined(SQLITE_THREADSAFE) || !(SQLITE_THREADSAFE == 1 || SQLITE_THREADSAFE == 2) -#error "SQLCipher must be compiled with -DSQLITE_THREADSAFE=<1 or 2>" -#endif - -#if !defined(SQLITE_TEMP_STORE) || SQLITE_TEMP_STORE == 0 || SQLITE_TEMP_STORE == 1 -#error "SQLCipher must be compiled with -DSQLITE_TEMP_STORE=<2 or 3>" -#endif - -/* 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 sqlite3pager_is_sj_pgno(Pager*, Pgno); -SQLITE_API void sqlite3pager_error(Pager*, int); -SQLITE_API void 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) \ - && !defined (SQLCIPHER_CRYPTO_CUSTOM) -#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.11.0 -#endif - -#ifndef CIPHER_VERSION_BUILD -#define CIPHER_VERSION_BUILD community -#endif - -#define CIPHER_READ_CTX 0 -#define CIPHER_WRITE_CTX 1 -#define CIPHER_READWRITE_CTX 2 - -#ifndef PBKDF2_ITER -#define PBKDF2_ITER 256000 -#endif - -#define SQLCIPHER_FLAG_GET(FLAG,BIT) ((FLAG & BIT) != 0) -#define SQLCIPHER_FLAG_SET(FLAG,BIT) FLAG |= BIT -#define SQLCIPHER_FLAG_UNSET(FLAG,BIT) FLAG &= ~BIT - -/* possible flags for codec_ctx->flags */ -#define CIPHER_FLAG_HMAC (1 << 0) -#define CIPHER_FLAG_LE_PGNO (1 << 1) -#define CIPHER_FLAG_BE_PGNO (1 << 2) -#define CIPHER_FLAG_KEY_USED (1 << 3) -#define CIPHER_FLAG_HAS_KDF_SALT (1 << 4) - - -#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 - - -/* 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; -} 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 reserve_sz; - int hmac_sz; - int plaintext_header_sz; - int hmac_algorithm; - int kdf_algorithm; - int error; - 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 ; - -typedef struct private_block private_block; -struct private_block { - private_block *next; - u32 size; - u32 is_used; -}; - -/* implementation of simple, fast PSRNG function using xoshiro256++ (XOR/shift/rotate) - * https://prng.di.unimi.it/ under the public domain via https://prng.di.unimi.it/xoshiro256plusplus.c - * xoshiro is NEVER used for any cryptographic functions as CSPRNG. It is solely used for - * generating random data for testing, debugging, and forensic purposes (overwriting memory segments) */ -static volatile uint64_t xoshiro_s[4]; - -static inline uint64_t xoshiro_rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); -} - -uint64_t xoshiro_next(void) { - volatile uint64_t result = xoshiro_rotl(xoshiro_s[0] + xoshiro_s[3], 23) + xoshiro_s[0]; - volatile uint64_t t = xoshiro_s[1] << 17; - - xoshiro_s[2] ^= xoshiro_s[0]; - xoshiro_s[3] ^= xoshiro_s[1]; - xoshiro_s[1] ^= xoshiro_s[2]; - xoshiro_s[0] ^= xoshiro_s[3]; - - xoshiro_s[2] ^= t; - - xoshiro_s[3] = xoshiro_rotl(xoshiro_s[3], 45); - - return result; -} - -static void xoshiro_randomness(unsigned char *ptr, int sz) { - volatile uint64_t val; - volatile int to_copy; - while (sz > 0) { - val = xoshiro_next(); - to_copy = (sz >= sizeof(val)) ? sizeof(val) : sz; - memcpy(ptr, (void *) &val, to_copy); - ptr += to_copy; - sz -= to_copy; - } -} - -#ifdef SQLCIPHER_TEST -/* possible flags for simulating specific test conditions */ -#define TEST_FAIL_ENCRYPT 0x01 -#define TEST_FAIL_DECRYPT 0x02 -#define TEST_FAIL_MIGRATE 0x04 - -static volatile unsigned int cipher_test_flags = 0; -static volatile int cipher_test_rand = 0; - -static 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; - - xoshiro_randomness((unsigned char *) &x, sizeof(x)); - return ((x % cipher_test_rand) == 0); -} -#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_size = 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 sqlite3_mem_methods default_mem_methods; -static sqlcipher_provider *default_provider = NULL; - -static sqlite3_mutex* sqlcipher_static_mutex[SQLCIPHER_MUTEX_COUNT]; - -#ifndef SQLCIPHER_LOG_LEVEL_DEFAULT -#define SQLCIPHER_LOG_LEVEL_DEFAULT SQLCIPHER_LOG_WARN -#endif -static FILE* sqlcipher_log_file = NULL; -static volatile int sqlcipher_log_device = 0; -static volatile unsigned int sqlcipher_log_level = SQLCIPHER_LOG_NONE; -static volatile unsigned int sqlcipher_log_source = SQLCIPHER_LOG_ANY; -static volatile int sqlcipher_log_set = 0; - -static size_t sqlcipher_shield_mask_sz = 32; -static u8* sqlcipher_shield_mask = NULL; - -/* Establish the default size of the private heap. This can be overriden - * at compile time by setting -DSQLCIPHER_PRIVATE_HEAP_SIZE_DEFAULT=X */ -#ifndef SQLCIPHER_PRIVATE_HEAP_SIZE_DEFAULT -/* On android, the maximim amount of memory that can be memlocked in 64k. This also - * seems to be a popular ulimit on linux distributions, containsers, etc. Therefore - * the default heap size is chosen as 48K, which is either 4 (with 4k page size) - * or 1 (with 16k page size) page less than the max. We choose to allocate slightly - * less than the max just in case the app has locked some other page(s). This - * initial allocation should be enough to support at least 10 concurrent - * sqlcipher-enabled database connections at the same time without requiring any - * overflow allocations */ -#define SQLCIPHER_PRIVATE_HEAP_SIZE_DEFAULT 49152 -#endif -/* if default allocation fails, we'll reduce the size by this amount - * and try again. This is also the minimium of the private heap. The minimum - * size will be 4 4K pages or 1 16K page (possible with latest android)*/ -#define SQLCIPHER_PRIVATE_HEAP_SIZE_STEP 16384 - -static volatile size_t private_heap_sz = SQLCIPHER_PRIVATE_HEAP_SIZE_DEFAULT; -static u8* private_heap = NULL; -static volatile size_t private_heap_used = 0; /* bytes currently used on private heap */ -static volatile size_t private_heap_hwm = 0; /* larged number of bytes used on the private heap at one time */ -static volatile size_t private_heap_alloc = 0; /* total bytes allocated on private heap over time */ -static volatile u32 private_heap_allocs = 0; /* total number of allocations on private heap over time */ -static volatile size_t private_heap_overflow = 0; /* total bytes overflowing private heap over time */ -static volatile u32 private_heap_overflows = 0; /* number of overlow allocations over time */ - -/* to prevent excessive fragmentation blocks will - * only be split if there are at least this many - * bytes available after the split. This should allow for at - * least two addtional small allocations */ -#define SQLCIPHER_PRIVATE_HEAP_MIN_SPLIT_SIZE 32 - -/* requested sizes will be rounded up to the nearest 8 bytes for alignment */ -#define SQLCIPHER_PRIVATE_HEAP_ALIGNMENT 8 -#define SQLCIPHER_PRIVATE_HEAP_ROUNDUP(x) ((x % SQLCIPHER_PRIVATE_HEAP_ALIGNMENT) ? \ - ((x / SQLCIPHER_PRIVATE_HEAP_ALIGNMENT) + 1) * SQLCIPHER_PRIVATE_HEAP_ALIGNMENT : x) - -static volatile int sqlcipher_init = 0; -static volatile int sqlcipher_shutdown = 0; -static volatile int sqlcipher_cleanup = 0; -static int sqlcipher_init_error = SQLITE_ERROR; - -static void sqlcipher_internal_free(void *, sqlite_uint64); -static void *sqlcipher_internal_malloc(sqlite_uint64); - - -/* -** 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++) { - 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; -} - -sqlite3_mutex* sqlcipher_mutex(int mutex) { - if(mutex < 0 || mutex >= SQLCIPHER_MUTEX_COUNT) return NULL; - return sqlcipher_static_mutex[mutex]; -} - -static void sqlcipher_atexit(void) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: calling sqlcipher_extra_shutdown()", __func__); - sqlcipher_extra_shutdown(); -} - -static void sqlcipher_fini(void) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: calling sqlcipher_extra_shutdown()", __func__); - sqlcipher_extra_shutdown(); -} - -#if defined(_WIN32) - #ifndef SQLCIPHER_OMIT_DLLMAIN - BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - switch (fdwReason) { - case DLL_PROCESS_DETACH: - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: calling sqlcipher_extra_shutdown()", __func__); - sqlcipher_extra_shutdown(); - break; - default: - break; - } - return TRUE; - } - #endif -#elif defined(__APPLE__) - #if defined(__has_feature) && __has_feature(address_sanitizer) - static void sqlcipher_cleanup_destructor(void) __attribute__((destructor)); - static void sqlcipher_cleanup_destructor(void) { sqlcipher_fini(); } - #else - static void (*const sqlcipher_fini_func)(void) __attribute__((used, section("__DATA,__mod_term_func"))) = sqlcipher_fini; - #endif -#else -static void (*const sqlcipher_fini_func)(void) __attribute__((used, section(".fini_array"))) = sqlcipher_fini; -#endif - -static void sqlcipher_exportFunc(sqlite3_context*, int, sqlite3_value**); - -static int sqlcipher_export_init(sqlite3* db, const char** errmsg, const struct sqlite3_api_routines* api) { - sqlite3_create_function_v2(db, "sqlcipher_export", -1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0); - return SQLITE_OK; -} - -/* The extra_init function is called by sqlite3_init automaticay by virtue of - * being defined with SQLITE_EXTRA_INIT. This function sets up - * static mutexes used internally by SQLCipher and initializes - * the internal private heap */ -int sqlcipher_extra_init(const char* arg) { - int rc = SQLITE_OK, i=0; - void* provider_ctx = NULL; - - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - - if(sqlcipher_init) { - /* if this init routine already completed successfully return immediately */ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - return SQLITE_OK; - } - - /* only register cleanup handlers once per process */ - if(!sqlcipher_cleanup) { - atexit(sqlcipher_atexit); - sqlcipher_cleanup = 1; - } - -#ifndef SQLCIPHER_OMIT_DEFAULT_LOGGING - /* when sqlcipher is first activated, set a default log target and level of WARN if the - logging settings have not yet been initialized. Use the "device log" for - android (logcat) or apple (console). Use stderr on all other platforms. */ - if(!sqlcipher_log_set) { - - /* set log level if it is different than the uninitalized default value of NONE */ - if(sqlcipher_log_level == SQLCIPHER_LOG_NONE) { - sqlcipher_log_level = SQLCIPHER_LOG_LEVEL_DEFAULT; - } - - /* set the default file or device if neither is already set */ - if(sqlcipher_log_device == 0 && sqlcipher_log_file == NULL) { -#if defined(__ANDROID__) || defined(__APPLE__) - sqlcipher_log_device = 1; -#else - sqlcipher_log_file = stderr; -#endif - } - sqlcipher_log_set = 1; - } -#endif - - /* allocate static mutexe, and return error if any fail to allocate */ - for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) { - if(sqlcipher_static_mutex[i] == NULL) { - if((sqlcipher_static_mutex[i] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST)) == NULL) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to allocate static mutex %d", __func__, i); - rc = SQLITE_NOMEM; - goto error; - } - } - } - - /* initialize the private heap for use in internal SQLCipher memory allocations */ - if(private_heap == NULL) { - while(private_heap_sz >= SQLCIPHER_PRIVATE_HEAP_SIZE_STEP) { - /* attempt to allocate the private heap. If allocation fails, reduce the size and try again */ - if((private_heap = sqlcipher_internal_malloc(private_heap_sz))) { - xoshiro_randomness(private_heap, (int) private_heap_sz); - /* initialize the head block of the linked list at the start of the heap */ - private_block *head = (private_block *) private_heap; - head->is_used = 0; - head->size = (u32) private_heap_sz - sizeof(private_block); - head->next = NULL; - break; - } - - /* allocation failed, reduce the requested size of the heap */ - private_heap_sz -= SQLCIPHER_PRIVATE_HEAP_SIZE_STEP; - } - } - if(!private_heap) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to allocate private heap", __func__); - rc = SQLITE_NOMEM; - goto error; - } - - /* 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); -#elif defined (SQLCIPHER_CRYPTO_OSSL3) - extern int sqlcipher_ossl3_setup(sqlcipher_provider *p); - sqlcipher_ossl3_setup(p); -#elif defined (SQLCIPHER_CRYPTO_CUSTOM) - extern int SQLCIPHER_CRYPTO_CUSTOM(sqlcipher_provider *p); - SQLCIPHER_CRYPTO_CUSTOM(p); -#else -#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED" -#endif - if((rc = sqlcipher_register_provider(p)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_PROVIDER, "%s: failed to register provider %p %d", __func__, p, rc); - goto error; - } - } - - /* required random data */ - if((rc = default_provider->ctx_init(&provider_ctx)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to initilize provider context %d", __func__, rc); - goto error; - } - - if((rc = default_provider->random(provider_ctx, (void *)xoshiro_s, sizeof(xoshiro_s))) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to generate xoshiro seed %d", __func__, rc); - goto error; - } - - if(!sqlcipher_shield_mask) { - if(!(sqlcipher_shield_mask = sqlcipher_internal_malloc(sqlcipher_shield_mask_sz))) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to allocate shield mask", __func__); - goto error; - } - if((rc = default_provider->random(provider_ctx, sqlcipher_shield_mask, (int) sqlcipher_shield_mask_sz)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, "%s: failed to generate requisite random mask data %d", __func__, rc); - goto error; - } - } - - default_provider->ctx_free(&provider_ctx); - - sqlcipher_init = 1; - sqlcipher_shutdown = 0; - - /* leave the master mutex so we can proceed with auto extension registration */ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - - /* finally, extension registration occurs outside of the mutex because it is - * uses SQLITE_MUTEX_STATIC_MASTER itself */ - sqlite3_auto_extension((void (*)(void))sqlcipher_export_init); - - return SQLITE_OK; - -error: - /* if an error occurs during initialization, tear down everything that was setup */ - if(private_heap) { - sqlcipher_internal_free(private_heap, private_heap_sz); - private_heap = NULL; - } - if(sqlcipher_shield_mask) { - sqlcipher_internal_free(sqlcipher_shield_mask, sqlcipher_shield_mask_sz); - sqlcipher_shield_mask = NULL; - } - for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) { - if(sqlcipher_static_mutex[i]) { - sqlite3_mutex_free(sqlcipher_static_mutex[i]); - sqlcipher_static_mutex[i] = NULL; - } - } - - /* post cleanup return the error code back up to sqlite3_init() */ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - sqlcipher_init_error = rc; - return rc; -} - -/* The extra_shutdown function is called by sqlite3_shutdown() - * because it is defined with SQLITE_EXTRA_SHUTDOWN. In addition it will - * be called via atexit(), finalizer, and DllMain. The function will - * cleanup resources allocated by SQLCipher including mutexes, - * the private heap, and default provider. */ -void sqlcipher_extra_shutdown(void) { - int i = 0; - sqlcipher_provider *provider = NULL; - - /* if sqlcipher hasn't been initialized or the shutdown already completed exit early */ - if(!sqlcipher_init || sqlcipher_shutdown) { - goto cleanup; - } - - if(sqlcipher_shield_mask) { - sqlcipher_internal_free(sqlcipher_shield_mask, sqlcipher_shield_mask_sz); - sqlcipher_shield_mask = NULL; - } - - /* free the provider list. start at the default provider and move through the list - * freeing each one. If a provider has a shutdown function, call it before freeing. - * finally NULL out the default_provider */ - provider = default_provider; - while(provider) { - sqlcipher_provider *next = provider->next; - if(provider->shutdown) { - provider->shutdown(); - } - sqlcipher_free(provider, sizeof(sqlcipher_provider)); - provider = next; - } - default_provider = NULL; - - /* free private heap. If SQLCipher is compiled in test mode, it will deliberately - not free the heap (leaking it) if the heap is not empty. This will allow tooling - to detect memory issues like unfreed private heap memory */ - if(private_heap) { -#ifdef SQLCIPHER_TEST - size_t used = 0; - private_block *block = NULL; - block = (private_block *) private_heap; - while (block != NULL) { - if(block->is_used) { - used+= block->size; - i++; - } - block = block->next; - } - if(used > 0) { - /* don't free the heap so that sqlite treats this as unfreed memory */ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_MEMORY, - "%s: SQLCipher private heap unfreed memory %u bytes in %d allocations", __func__, used, i); - } else { - sqlcipher_internal_free(private_heap, private_heap_sz); - private_heap = NULL; - } -#else - sqlcipher_internal_free(private_heap, private_heap_sz); - private_heap = NULL; -#endif - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, - "%s: SQLCipher private heap stats: size=%u, hwm=%u, alloc=%u, allocs=%u, overflow=%u, overflows=%u", __func__, - private_heap_sz, private_heap_hwm, private_heap_alloc, private_heap_allocs, private_heap_overflow, private_heap_overflows - ); - } - - /* free all of sqlcipher's static mutexes */ - for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) { - if(sqlcipher_static_mutex[i]) { - sqlite3_mutex_free(sqlcipher_static_mutex[i]); - sqlcipher_static_mutex[i] = NULL; - } - } - -cleanup: - sqlcipher_init = 0; - sqlcipher_init_error = SQLITE_ERROR; - sqlcipher_shutdown = 1; -} - -static void sqlcipher_shield(unsigned char *in, int sz) { - int i = 0; - for(i = 0; i < sz; i++) { - in[i] ^= sqlcipher_shield_mask[i % sqlcipher_shield_mask_sz]; - } -} - -/* 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) { - volatile sqlite_uint64 i = 0; - volatile unsigned char *a = v; - - if (v == NULL) return v; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MEMORY, "sqlcipher_memset: setting %p[0-%u]=%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 volatile unsigned char *a = v; - volatile 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 volatile unsigned char *a0 = v0, *a1 = v1; - volatile int i = 0, result = 0; - - for(i = 0; i < len; i++) { - result |= a0[i] ^ a1[i]; - } - - return (result != 0); -} - -static 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_LOG_MEMORY, "sqlcipher_mlock: 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_WARN, SQLCIPHER_LOG_MEMORY, "sqlcipher_mlock: mlock() returned %d errno=%d", rc, errno); - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "sqlcipher_mlock: 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_PC_APP)) - int rc; - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MEMORY, "sqlcipher_mlock: calling VirtualLock(%p,%d)", ptr, sz); - rc = VirtualLock(ptr, sz); - if(rc==0) { - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_MEMORY, "sqlcipher_mlock: VirtualLock() returned %d LastError=%d", rc, GetLastError()); - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "sqlcipher_mlock: VirtualLock(%p,%d) returned %d LastError=%d", ptr, sz, rc, GetLastError()); - } -#endif -#endif -#endif -} - -static 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_LOG_MEMORY, "sqlcipher_munlock: calling munlock(%p,%lu)", ptr - offset, sz + offset); - rc = munlock(ptr - offset, sz + offset); - if(rc!=0) { - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "sqlcipher_munlock: 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_PC_APP)) - int rc; - - if(ptr == NULL || sz == 0) return; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MEMORY, "sqlcipher_munlock: calling VirtualUnlock(%p,%d)", ptr, sz); - rc = VirtualUnlock(ptr, sz); - - /* because memory allocations may be made from the same individual page, it is possible for VirtualUnlock to be called - * multiple times for the same page. Subsequent calls will return an error, but this can be safely ignored (i.e. because - * the previous call for that page unlocked the memory already). Log an info level event only in that case. */ - if(!rc) { - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "sqlcipher_munlock: VirtualUnlock(%p,%d) returned %d LastError=%d", ptr, sz, rc, GetLastError()); - } -#endif -#endif -#endif -} - -/** sqlcipher wraps the default memory subsystem so it can optionally provide the - * memory security feature which will lock and sanitize ALL memory used by - * the sqlite library internally. Memory security feature is disabled by default - * but but the wrapper is used regardless, it just forwards to the default - * memory management implementation when disabled - */ -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_LOG_MEMORY, "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_LOG_MEMORY, "%s: calling xoshiro_randomness(%p,%d) and sqlcipher_munlock(%p, %d)", __func__, p, sz, p, sz); - xoshiro_randomness(p, 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 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(sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_mem_methods) != SQLITE_OK || - 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; - } -} - -/** - * Free and wipe memory. Uses SQLites internal 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 - */ -static void sqlcipher_internal_free(void *ptr, sqlite_uint64 sz) { - xoshiro_randomness(ptr, sz); - sqlcipher_munlock(ptr, sz); - 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 - */ -static void* sqlcipher_internal_malloc(sqlite_uint64 sz) { - void *ptr; - ptr = sqlite3_malloc(sz); - sqlcipher_memset(ptr, 0, sz); - sqlcipher_mlock(ptr, sz); - return ptr; -} - -void *sqlcipher_malloc(sqlite3_uint64 size) { - void *alloc = NULL; - private_block *block = NULL, *split = NULL; - - if(size < 1) return NULL; - - size = SQLCIPHER_PRIVATE_HEAP_ROUNDUP(size); - - block = (private_block *) private_heap; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering SQLCIPHER_MUTEX_MEM", __func__); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_MEM)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered SQLCIPHER_MUTEX_MEM", __func__); - - /* iterate through the blocks in the heap to find one which is big enough to hold - the requested allocation. Stop when one is found. */ - while(block != NULL && alloc == NULL) { - if(!block->is_used && block->size >= size) { - /* mark the block as in use and set the return pointer to the start - of the block free space */ - block->is_used = 1; - alloc = ((u8*)block) + sizeof(private_block); - sqlcipher_memset(alloc, 0, size); - - /* if there is at least the minimim amount of required space left after allocation, - split off a new free block and insert it after the in-use block */ - if(block->size >= size + sizeof(private_block) + SQLCIPHER_PRIVATE_HEAP_MIN_SPLIT_SIZE) { - split = (private_block*) (((u8*) block) + size + sizeof(private_block)); - split->is_used = 0; - split->size = block->size - size - sizeof(private_block); - - /* insert inbetween current block and next */ - split->next = block->next; - block->next = split; - - /* only set the size of the current block to the requested amount - if the block was split. otherwise, size will be the full amount - of the block, which will actually be larger than the requested amount */ - block->size = size; - } - } - block = block->next; - } - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving SQLCIPHER_MUTEX_MEM", __func__); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_MEM)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left SQLCIPHER_MUTEX_MEM", __func__); - - /* If we were unable to locate a free block large enough to service the request, the fallback - behavior will simply attempt to allocate additional memory using malloc. */ - if(alloc == NULL) { - private_heap_overflow += size; - private_heap_overflows++; - alloc = sqlcipher_internal_malloc(size); - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "%s: unable to allocate %u bytes on private heap, allocated %p using sqlcipher_internal_malloc fallback", __func__, size, alloc); - } else { - private_heap_used += size; - if(private_heap_used > private_heap_hwm) { - /* if the current bytes allocated on the private heap are greater than the high water mark, set the HWM to the new amount */ - private_heap_hwm = private_heap_used; - } - private_heap_alloc += size; - private_heap_allocs++; - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MEMORY, "%s allocated %u bytes on private heap at %p", __func__, size, alloc); - } - - return alloc; -} - -void sqlcipher_free(void *mem, sqlite3_uint64 sz) { - private_block *block = NULL, *prev = NULL; - void *alloc = NULL; - u32 block_size = 0; - block = (private_block *) private_heap; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering SQLCIPHER_MUTEX_MEM", __func__); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_MEM)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered SQLCIPHER_MUTEX_MEM", __func__); - - /* search the heap for the block that contains this address */ - while(block != NULL) { - alloc = ((u8*)block)+sizeof(private_block); - /* if the memory address to be freed corresponds to this block's - allocation, mark it as unused. If they don't match, move - on to the next block */ - if(mem == alloc) { - block->is_used = 0; - block_size = block->size; /* retain the acual size of the block in use for stats adjustment */ - xoshiro_randomness(alloc, block->size); - - /* check whether the previous block is free, if so merge*/ - if(prev && !prev->is_used) { - prev->size = prev->size + sizeof(private_block) + block->size; - prev->next = block->next; - block = prev; - } - - /* check to see whether the next block is free, if so merge */ - if(block->next && !block->next->is_used) { - block->size = block->size + sizeof(private_block) + block->next->size; - block->next = block->next->next; - } - - /* once the block has been identified, marked free, and optionally - consolidated with it's neighbors, exit the loop, but leave - the block pointer intact so we know we found it in the heap */ - break; - } - - prev = block; - block = block->next; - } - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving SQLCIPHER_MUTEX_MEM", __func__); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_MEM)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left SQLCIPHER_MUTEX_MEM", __func__); - - /* If the memory address couldn't be found in the private heap - then it was allocated by the fallback mechanism and should - be deallocated with free() */ - if(!block) { - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_MEMORY, "%s: unable to find %p with %u bytes on private heap, calling sqlcipher_internal_free fallback", __func__, mem, sz); - sqlcipher_internal_free(mem, sz); - } else { - private_heap_used -= block_size; - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MEMORY, "%s freed %u bytes (%u total) on private heap at %p", __func__, sz, block_size, mem); - } -} - -int sqlcipher_register_provider(sqlcipher_provider *p) { - int preexisting = 0, rc = SQLITE_OK; - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering SQLCIPHER_MUTEX_PROVIDER", __func__); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered SQLCIPHER_MUTEX_PROVIDER", __func__); - - if(!p || default_provider == p) { - goto cleanup; - } - - if(!default_provider) { - /* initial provider registration, NULL out previous pointer*/ - p->next = NULL; - } else { - /* one or more previous provider has already been registered, search through - * the list to see if the new provider has already been registered and handle - * appropriately */ - sqlcipher_provider *previous = default_provider; - sqlcipher_provider *current = default_provider->next; - while(current) { - if(current == p) { - /* this is a duplicate provider registration, and the provider in question - * already exists on the list. In that case, pop it out so it can be moved up to default. - * note that if we found an existing match we should avoid re-initializing the provider */ - previous->next = current->next; - preexisting = 1; - break; - } - previous = current; - current = current->next; - } - /* the current default_provider gets tacked on the list */ - p->next = default_provider; - } - - /* the new provider is elevated to default. if the provider was not preexisting and it has an initializer, call it */ - if(!preexisting && p->init) { - rc = p->init(); - } - - if(rc == SQLITE_OK) { - default_provider = p; - } -cleanup: - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving SQLCIPHER_MUTEX_PROVIDER", __func__); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left SQLCIPHER_MUTEX_PROVIDER", __func__); - - return rc; -} - -/* 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; -} - -char* sqlcipher_version(void) { -#ifdef CIPHER_VERSION_QUALIFIER - char *version = sqlite3_mprintf("%s %s %s", CIPHER_XSTR(CIPHER_VERSION_NUMBER), CIPHER_XSTR(CIPHER_VERSION_QUALIFIER), CIPHER_XSTR(CIPHER_VERSION_BUILD)); -#else - char *version = 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_LOG_MEMORY, "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_LOG_MEMORY, "sqlcipher_cipher_ctx_init: allocating key"); - c_ctx->key = (unsigned char *) sqlcipher_malloc(ctx->key_sz); - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_MEMORY, "sqlcipher_cipher_ctx_init: allocating hmac_key"); - c_ctx->hmac_key = (unsigned char *) sqlcipher_malloc(ctx->key_sz); - - if(!c_ctx->key || !c_ctx->hmac_key) 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, SQLCIPHER_LOG_MEMORY, "cipher_ctx_free: iCtx=%p", iCtx); - if(c_ctx->key) sqlcipher_free(c_ctx->key, ctx->key_sz); - if(c_ctx->hmac_key) sqlcipher_free(c_ctx->hmac_key, ctx->key_sz); - if(c_ctx->pass) sqlcipher_free(c_ctx->pass, c_ctx->pass_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_FLAG_GET(ctx->flags, CIPHER_FLAG_HMAC)) - 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 */ - if(ctx->block_sz > 0) { - reserve = ((reserve % ctx->block_sz) == 0) ? reserve : - ((reserve / ctx->block_sz) + 1) * ctx->block_sz; - } - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "sqlcipher_cipher_ctx_copy: target=%p, source=%p", target, source); - if(target->pass) sqlcipher_free(target->pass, target->pass_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); - } - return SQLITE_OK; -} - -/** - * Get 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_get_keyspec(codec_ctx *ctx, cipher_ctx *c_ctx, char **keyspec_ptr, int *keyspec_sz) { - int sz = 0; - char *keyspec = NULL, *out = NULL; - - if(keyspec_ptr == NULL) return SQLITE_NOMEM; - - /* establish the size for a hex-formated key specification, containing the - * raw encryption key, optional hmac key, and the salt used to generate it. - * The format will be either: - * x'hex(key)...hex(hmac_key)...hex(salt)' - * or - * x'hex(key)...hex(salt)' - *. The contents are SQLite BLOB formatted, so oversize by 3 bytes for the leading - * x' and trailing ' characters required by the spec*/ - if(ctx->flags & CIPHER_FLAG_HMAC) { /* if HMAC is enabled, encode key, hmac key, and salt */ - sz = ((ctx->key_sz + ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3; - } else { /* otherwise encode key and salt */ - sz = ((ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3; - } - - *keyspec_ptr = sqlcipher_malloc(sz); - keyspec = *keyspec_ptr; - - if(keyspec == NULL) return SQLITE_NOMEM; - - keyspec[0] = 'x'; - keyspec[1] = '\''; - - out = keyspec + 2; - - /* start with the encryption key */ - sqlcipher_shield(c_ctx->key, ctx->key_sz); - cipher_bin2hex(c_ctx->key, ctx->key_sz, out); - sqlcipher_shield(c_ctx->key, ctx->key_sz); - out += ctx->key_sz * 2; - - if(ctx->flags & CIPHER_FLAG_HMAC) { - /* add the hmac key after the encryption key if HMAC is in use*/ - sqlcipher_shield(c_ctx->hmac_key, ctx->key_sz); - cipher_bin2hex(c_ctx->hmac_key, ctx->key_sz, out); - sqlcipher_shield(c_ctx->hmac_key, ctx->key_sz); - out += ctx->key_sz * 2; - } - - /* finally encode the salt last */ - cipher_bin2hex(ctx->kdf_salt, ctx->kdf_salt_sz, out); - - keyspec[sz - 1] = '\''; - *keyspec_sz = sz; - - return SQLITE_OK; -} - -static void sqlcipher_set_derive_key(codec_ctx *ctx, int derive) { - if(ctx->read_ctx != NULL) ctx->read_ctx->derive_key = derive; - if(ctx->write_ctx != NULL) ctx->write_ctx->derive_key = derive; -} - -/** - * 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 */ - if(ctx->pass) 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; -} - -static 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_LOG_CORE, "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_LOG_CORE, "sqlcipher_codec_ctx_set_pass: error %d from sqlcipher_cipher_ctx_copy", rc); - return rc; - } - } - - return SQLITE_OK; -} - -static int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - ctx->kdf_iter = kdf_iter; - sqlcipher_set_derive_key(ctx, 1); - return SQLITE_OK; -} - -static int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - ctx->fast_kdf_iter = fast_kdf_iter; - sqlcipher_set_derive_key(ctx, 1); - return SQLITE_OK; -} - -/* set the global default flag for HMAC */ -static void sqlcipher_set_default_use_hmac(int use) { - if(use) SQLCIPHER_FLAG_SET(default_flags, CIPHER_FLAG_HMAC); - else SQLCIPHER_FLAG_UNSET(default_flags,CIPHER_FLAG_HMAC); -} - -/* set the codec flag for whether this individual database should be using hmac */ -static int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - if(use) { - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_HMAC); - } else { - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_HMAC); - } - - return sqlcipher_codec_ctx_reserve_setup(ctx); -} - -/* 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 or equal to the non-reserve size of the first database page - * - * Note: it is possible to leave the entire first page in plaintext. This is discouraged since it will - * likely leak some small amount of schema data, but it's required to support use of the recovery VFS. - * see comment in sqlcipher_page_cipher for more details. - */ -static int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size) { - if(size >= 0 && ctx->block_sz > 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_LOG_CORE, "%s: attempt to set invalid plantext_header_size %d", __func__, size); - return SQLITE_ERROR; -} - -static int sqlcipher_codec_ctx_set_hmac_algorithm(codec_ctx *ctx, int algorithm) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - ctx->hmac_algorithm = algorithm; - return sqlcipher_codec_ctx_reserve_setup(ctx); -} - -static int sqlcipher_codec_ctx_set_kdf_algorithm(codec_ctx *ctx, int algorithm) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - ctx->kdf_algorithm = algorithm; - return SQLITE_OK; -} - -static void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_set_error %d", error); - sqlite3pager_error(sqlite3BtreePager(ctx->pBt), error); - ctx->pBt->pBt->db->errCode = error; - ctx->error = error; -} - -static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx) { - sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(ctx->pBt)); - - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_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_LOG_CORE, "sqlcipher_codec_ctx_init_kdf_salt: obtaining salt"); - if(fd == NULL || fd->pMethods == 0 || sqlite3OsRead(fd, ctx->kdf_salt, ctx->kdf_salt_sz, 0) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "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_LOG_CORE, "sqlcipher_codec_ctx_init_kdf_salt: error retrieving random bytes from provider"); - return SQLITE_ERROR; - } - } - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT); - return SQLITE_OK; -} - -static int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int size) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - if(size >= ctx->kdf_salt_sz) { - memcpy(ctx->kdf_salt, salt, ctx->kdf_salt_sz); - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT); - return SQLITE_OK; - } - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_set_kdf_salt: attempt to set salt of incorrect size %d", size); - return SQLITE_ERROR; -} - -static int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void** salt) { - int rc = SQLITE_OK; - if(!SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT)) { - if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_get_kdf_salt: error %d from sqlcipher_codec_ctx_init_kdf_salt", rc); - } - } - *salt = ctx->kdf_salt; - - return rc; -} - -static int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) return SQLITE_OK; - - if(!((size != 0) && ((size & (size - 1)) == 0)) || size < 512 || size > 65536) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "cipher_page_size not a power of 2 and between 512 and 65536 inclusive"); - return SQLITE_ERROR; - } - /* attempt to free the existing page buffer */ - if(ctx->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; -} - -static 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_LOG_MEMORY, "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_LOG_MEMORY, "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_LOG_MEMORY, "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; - - /* the context will use the current default crypto provider */ - ctx->provider = default_provider; - - if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "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); - - /* - 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_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "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, SQLCIPHER_FLAG_GET(default_flags, CIPHER_FLAG_HMAC))) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_init: error %d setting use_hmac %d", rc, SQLCIPHER_FLAG_GET(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_LOG_CORE, "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_size)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_init: error %d setting sqlcipher_codec_ctx_set_plaintext_header_size with %d", rc, default_plaintext_header_size); - 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_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "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. - */ -static void sqlcipher_codec_ctx_free(codec_ctx **iCtx) { - codec_ctx *ctx = *iCtx; - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_MEMORY, "codec_ctx_free: iCtx=%p", iCtx); - if(ctx->kdf_salt) sqlcipher_free(ctx->kdf_salt, ctx->kdf_salt_sz); - if(ctx->hmac_kdf_salt) sqlcipher_free(ctx->hmac_kdf_salt, ctx->kdf_salt_sz); - if(ctx->buffer) sqlcipher_free(ctx->buffer, ctx->page_sz); - if(ctx->provider) ctx->provider->ctx_free(&ctx->provider_ctx); - - 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)]; - int rc; - /* 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(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_LE_PGNO)) { /* compute hmac using little endian pgno*/ - sqlcipher_put4byte_le(pgno_raw, pgno); - } else if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_BE_PGNO)) { /* compute hmac using big endian pgno */ - sqlite3Put4byte(pgno_raw, pgno); /* 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 */ - sqlcipher_shield(c_ctx->hmac_key, ctx->key_sz); - rc = 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); - sqlcipher_shield(c_ctx->hmac_key, ctx->key_sz); - - return rc; -} - -/* - * 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 - */ -static 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, rc; - - /* 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; - - /* if the full amount of the first page (excluding reserve size), e.g. 4016 bytes for a 4096 byte page size with HMAC_SHA512, - * is used as a plaintext header, then the entire first page will be completely plaintext, and this function should just return early. - * This should almost never occur during normal usage, so we will log at WARN level, but it is required in the special case that - * a user wants to attempt recovery on an encrypted database. In that case, the database header must be completely plaintext so that - * the recovery VFS can be used with it's special 1st page logic */ - if(pgno == 1 && size == 0) { - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_CORE, "%s: skipping encryption/decryption for fully plaintext header", __func__); - return SQLITE_OK; - } - - /* 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_LOG_CORE, "%s: pgno=%d, mode=%d, size=%d", __func__, 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_LOG_CORE, "%s: error possible context corruption, key_sz is zero for pgno=%d", __func__, pgno); - goto error; - } - - if(mode == SQLCIPHER_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 { /* SQLCIPHER_DECRYPT */ - memcpy(iv_out, iv_in, ctx->iv_sz); /* copy the iv from the input to output buffer */ - } - - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HMAC) && (mode == SQLCIPHER_DECRYPT)) { - if(sqlcipher_page_hmac(ctx, c_ctx, pgno, in, size + ctx->iv_sz, hmac_out) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: hmac operation on decrypt failed for pgno=%d", __func__, pgno); - goto error; - } - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: comparing hmac on in=%p out=%p hmac_sz=%d", __func__, hmac_in, hmac_out, ctx->hmac_sz); - if(sqlcipher_memcmp(hmac_in, hmac_out, ctx->hmac_sz) != 0) { /* the hmac check failed */ - if(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_INFO, SQLCIPHER_LOG_CORE, "%s: zeroed page (short read) for pgno %d with autovacuum enabled", __func__, 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_LOG_CORE, "%s: hmac check failed for pgno=%d", __func__, pgno); - goto error; - } - } - } - - sqlcipher_shield(c_ctx->key, ctx->key_sz); - rc = ctx->provider->cipher(ctx->provider_ctx, mode, c_ctx->key, ctx->key_sz, iv_out, in, size, out); - sqlcipher_shield(c_ctx->key, ctx->key_sz); - - if(rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: cipher operation mode=%d failed for pgno=%d", __func__, mode, pgno); - goto error; - }; - - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HMAC) && (mode == SQLCIPHER_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_LOG_CORE, "%s: hmac operation on encrypt failed for pgno=%d", __func__, 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, raw_key_sz = 0, raw_salt_sz = 0, blob_format = 0, derive_hmac_key = 1; - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: ctx->kdf_salt_sz=%d ctx->kdf_iter=%d ctx->fast_kdf_iter=%d ctx->key_sz=%d", - __func__, ctx->kdf_salt_sz, ctx->kdf_iter, ctx->fast_kdf_iter, ctx->key_sz); - - /* if key material is present on the context for derivation */ - if(!c_ctx->pass || !c_ctx->pass_sz) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_cipher_ctx_key_derive: key material is not present on the context for key derivation"); - return SQLITE_ERROR; - } - - /* if necessary, initialize the salt from the header or random source */ - if(!SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT)) { - if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: error %d from sqlcipher_codec_ctx_init_kdf_salt", __func__, rc); - goto error; - } - } - - /* raw hey hex encoded is 2x long */ - raw_key_sz = ctx->key_sz * 2; - raw_salt_sz = ctx->kdf_salt_sz *2; - - /* raw key must be BLOB formatted: - * 1. greater than or equal to 5 characters long - * 2. starting with x' - * 3. ending with ' - * 4. length of contents between the x' and ' must be a power of 2 - * 5. contents must be hex */ - blob_format = - c_ctx->pass_sz >= 5 - && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 - && c_ctx->pass[c_ctx->pass_sz - 1] == '\'' - && (c_ctx->pass_sz - 3) % 2 == 0 - && cipher_isHex(c_ctx->pass + 2, c_ctx->pass_sz - 3); - - if(blob_format && c_ctx->pass_sz == raw_key_sz + 3) { - /* option 1 - raw key consisting of only the encryption key */ - const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: using raw key only", __func__); - cipher_hex2bin(z, raw_key_sz, c_ctx->key); - } else if(blob_format && c_ctx->pass_sz == raw_key_sz + raw_salt_sz + 3) { - /* option 2 - raw key consisting of the encryption key and salt */ - const unsigned char *z = c_ctx->pass + 2; - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: using raw key and salt", __func__); - cipher_hex2bin(z, raw_key_sz, c_ctx->key); - cipher_hex2bin(z + raw_key_sz, raw_salt_sz, ctx->kdf_salt); - } else if(blob_format && c_ctx->pass_sz == raw_key_sz + raw_key_sz + raw_salt_sz + 3) { - /* option 3 - raw key consisting of the encryption key, then hmac key, then salt */ - const unsigned char *z = c_ctx->pass + 2; - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: using raw key, hmac key, and salt", __func__); - cipher_hex2bin(z, raw_key_sz, c_ctx->key); - cipher_hex2bin(z + raw_key_sz, raw_key_sz, c_ctx->hmac_key); - cipher_hex2bin(z + raw_key_sz + raw_key_sz, raw_salt_sz, ctx->kdf_salt); - derive_hmac_key = 0; - } else { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: deriving key using PBKDF2 with %d iterations", __func__, ctx->kdf_iter); - if((rc = 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, SQLCIPHER_LOG_CORE, "%s: error %d occurred from provider kdf generating encryption key", __func__, rc); - goto error; - } - } - - /* if this context is setup to use hmac checks, and we didn't already get an hmac - * key inbound via keyspec / raw key, then generate a seperate - * 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 && derive_hmac_key) { - 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, SQLCIPHER_LOG_CORE, "%s: deriving hmac key from encryption key using PBKDF2 with %d iterations", - __func__, ctx->fast_kdf_iter); - - if((rc = 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, SQLCIPHER_LOG_CORE, "%s: error occurred from provider kdf generating HMAC key", __func__, rc); - goto error; - } - } - - sqlcipher_shield(c_ctx->key, ctx->key_sz); - sqlcipher_shield(c_ctx->hmac_key, ctx->key_sz); - c_ctx->derive_key = 0; - return SQLITE_OK; - -error: - /* if an error occurred, overwrite any derived key material */ - xoshiro_randomness(c_ctx->key, ctx->key_sz); - xoshiro_randomness(c_ctx->hmac_key, ctx->key_sz); - return SQLITE_ERROR; -} - -static 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_LOG_CORE, "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_LOG_CORE, "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_LOG_CORE, "sqlcipher_codec_key_derive: error occurred deriving write_ctx key"); - return SQLITE_ERROR; - } - } - } - - /* 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; -} - -static 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); - } -} - -static int sqlcipher_check_connection(const char *filename, char *key, int key_sz, char *sql, int *user_version, char** journal_mode) { - int rc; - sqlite3 *db = NULL; - sqlite3_stmt *statement = NULL; - char *query_journal_mode = "PRAGMA journal_mode;"; - char *query_user_version = "PRAGMA user_version;"; - - rc = sqlite3_open(filename, &db); - if(rc != SQLITE_OK) goto cleanup; - - rc = sqlite3_key(db, key, key_sz); - if(rc != SQLITE_OK) goto cleanup; - - rc = 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 = sqlite3_prepare(db, query_user_version, -1, &statement, NULL); - if(rc != SQLITE_OK) goto cleanup; - - rc = sqlite3_step(statement); - if(rc == SQLITE_ROW) { - *user_version = sqlite3_column_int(statement, 0); - } else { - goto cleanup; - } - sqlite3_finalize(statement); - - rc = sqlite3_prepare(db, query_journal_mode, -1, &statement, NULL); - if(rc != SQLITE_OK) goto cleanup; - - rc = sqlite3_step(statement); - if(rc == SQLITE_ROW) { - *journal_mode = sqlite3_mprintf("%s", sqlite3_column_text(statement, 0)); - } else { - goto cleanup; - } - rc = SQLITE_OK; - /* cleanup will finalize open statement */ - -cleanup: - if(statement) sqlite3_finalize(statement); - if(db) sqlite3_close(db); - return rc; -} - -static 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; - sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(ctx->pBt)); - i64 file_sz; - - Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, column, SQLITE_STATIC); - - if(fd == NULL || fd->pMethods == 0) { - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "database file is undefined", P4_TRANSIENT); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - goto cleanup; - } - - if(!(ctx->flags & CIPHER_FLAG_HMAC)) { - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "HMAC is not enabled, unable to integrity check", P4_TRANSIENT); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - goto cleanup; - } - - if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) { - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "unable to derive keys", P4_TRANSIENT); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - goto cleanup; - } - - 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(sqlite3pager_is_sj_pgno(sqlite3BtreePager(ctx->pBt), 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(sqlite3OsRead(fd, ctx->buffer, read_sz, offset) != SQLITE_OK) { - result = sqlite3_mprintf("error reading %d bytes from file page %d at offset %d", read_sz, page, offset); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC); - 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 = sqlite3_mprintf("HMAC operation failed for page %d", page); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } else if(sqlcipher_memcmp(ctx->buffer + payload_sz, hmac_out, ctx->hmac_sz) != 0) { - result = sqlite3_mprintf("HMAC verification failed for page %d", page); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - } - - if(file_sz % ctx->page_sz != 0) { - result = sqlite3_mprintf("page %d has an invalid size of %lld bytes (expected %d bytes)", page, file_sz - ((file_sz / ctx->page_sz) * ctx->page_sz), ctx->page_sz); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - -cleanup: - if(hmac_out != NULL) sqlcipher_free(hmac_out, ctx->hmac_sz); - return SQLITE_OK; -} - -static int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { - int i, pass_sz, keyspec_sz, nRes, user_version, rc, rc_cleanup, oflags; - Db *pDb = 0; - sqlite3 *db = ctx->pBt->db; - const char *db_filename = 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; - 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 || 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_INFO, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: no upgrade required - exiting"); - goto cleanup; - } - - for(i = 3; i > 0; i--) { - pragma_compat = 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, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: version %d format found", i); - goto migrate; - } - if(pragma_compat) sqlcipher_free(pragma_compat, 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, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: unable to determine format version for upgrade: this may indicate custom settings were used "); - goto handle_error; - -migrate: - - temp = sqlite3_mprintf("%s-migrated", db_filename); - /* overallocate migrated_db_filename, because sqlite3OsOpen will read past the null terminator - * to determine whether the filename was URI formatted */ - migrated_db_filename = sqlcipher_malloc(sqlite3Strlen30(temp)+2); - memcpy(migrated_db_filename, temp, sqlite3Strlen30(temp)); - sqlcipher_free(temp, sqlite3Strlen30(temp)); - - attach_command = sqlite3_mprintf("ATTACH DATABASE '%s' as migrate;", migrated_db_filename, pass); - set_user_version = sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version); - - rc = sqlite3_exec(db, pragma_compat, NULL, NULL, NULL); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: 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 = sqlite3_exec(db, "PRAGMA journal_mode = delete;", NULL, NULL, NULL); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: force journal mode DELETE failed, error code %d", rc); - goto handle_error; - } - - rc = sqlite3_exec(db, attach_command, NULL, NULL, NULL); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: attach failed, error code %d", rc); - goto handle_error; - } - - rc = sqlite3_key_v2(db, "migrate", pass, pass_sz); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: keying attached database failed, error code %d", rc); - goto handle_error; - } - - rc = sqlite3_exec(db, "SELECT sqlcipher_export('migrate');", NULL, NULL, NULL); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: sqlcipher_export failed, error code %d", rc); - goto handle_error; - } - -#ifdef SQLCIPHER_TEST - if((cipher_test_flags & TEST_FAIL_MIGRATE) > 0) { - rc = SQLITE_ERROR; - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: simulated migrate failure, error code %d", rc); - goto handle_error; - } -#endif - - rc = sqlite3_exec(db, set_user_version, NULL, NULL, NULL); - if(rc != SQLITE_OK){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: set user version failed, error code %d", rc); - goto handle_error; - } - - if( !db->autoCommit ){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: cannot migrate from within a transaction"); - goto handle_error; - } - if( db->nVdbeActive>1 ){ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: cannot migrate - SQL statements in progress"); - goto handle_error; - } - - pDest = db->aDb[0].pBt; - pDb = &(db->aDb[db->nDb-1]); - pSrc = pDb->pBt; - - nRes = sqlite3BtreeGetRequestedReserve(pSrc); - /* unset the BTS_PAGESIZE_FIXED flag to avoid SQLITE_READONLY */ - pDest->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; - rc = sqlite3BtreeSetPageSize(pDest, default_page_size, nRes, 0); - if(rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: failed to set btree page size to %d res %d rc %d", default_page_size, nRes, rc); - goto handle_error; - } - - sqlcipherCodecGetKey(db, db->nDb - 1, (void**)&keyspec, &keyspec_sz); - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_KEY_USED); - sqlcipherCodecAttach(db, 0, keyspec, keyspec_sz); - - srcfile = sqlite3PagerFile(sqlite3BtreePager(pSrc)); - destfile = sqlite3PagerFile(sqlite3BtreePager(pDest)); - - sqlite3OsClose(srcfile); - sqlite3OsClose(destfile); - -#if defined(_WIN32) || defined(SQLITE_OS_WINRT) - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: 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, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: error occurred while renaming migration files %d", rc); - goto handle_error; - } -#else - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: performing POSIX rename"); - if ((rc = rename(migrated_db_filename, db_filename)) != 0) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: error occurred while renaming migration files %s to %s: %d", migrated_db_filename, db_filename, rc); - goto handle_error; - } -#endif - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: renamed migration database %s to main database %s: %d", migrated_db_filename, db_filename, rc); - - rc = sqlite3OsOpen(db->pVfs, migrated_db_filename, srcfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags); - if(rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: failed to reopen migration database %s: %d", migrated_db_filename, rc); - goto handle_error; - } - - rc = sqlite3OsOpen(db->pVfs, db_filename, destfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags); - if(rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: failed to reopen main database %s: %d", db_filename, rc); - goto handle_error; - } - - sqlite3pager_reset(sqlite3BtreePager(pDest)); - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: reset pager"); - -handle_error: - rc_cleanup = sqlite3_exec(db, "DETACH DATABASE migrate;", NULL, NULL, NULL); - if(rc_cleanup != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: DETACH DATABASE migrate failed: %d", rc_cleanup); - /* only overwrite the rc in the cleanup stage if it is currently not an error. This will prevent overwriting a previous error that occured earlier in migration */ - if(rc == SQLITE_OK) { - rc = rc_cleanup; - } - } - - sqlite3ResetAllSchemasOfConnection(db); - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: reset all schemas"); - - if(journal_mode) { - set_journal_mode = sqlite3_mprintf("PRAGMA journal_mode = %s;", journal_mode); - rc_cleanup = sqlite3_exec(db, set_journal_mode, NULL, NULL, NULL); - if(rc_cleanup != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: failed to re-set journal mode via %s: %d", set_journal_mode, rc_cleanup); - if(rc == SQLITE_OK) { - rc = rc_cleanup; - } - } - } - - if(migrated_db_filename) { - int del_rc = sqlite3OsDelete(db->pVfs, migrated_db_filename, 0); - if(del_rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: failed to delete migration database %s: %d", migrated_db_filename, del_rc); - } - } - - if(rc != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_migrate: an error occurred attempting to migrate the database - last error %d", rc); - sqlite3pager_reset(sqlite3BtreePager(ctx->pBt)); - ctx->error = rc; /* set flag for deferred error */ - } - -cleanup: - if(pass) sqlcipher_free(pass, pass_sz); - if(keyspec) sqlcipher_free(keyspec, keyspec_sz); - if(attach_command) sqlcipher_free(attach_command, sqlite3Strlen30(attach_command)); - if(migrated_db_filename) sqlcipher_free(migrated_db_filename, sqlite3Strlen30(migrated_db_filename)); - if(set_user_version) sqlcipher_free(set_user_version, sqlite3Strlen30(set_user_version)); - if(set_journal_mode) sqlcipher_free(set_journal_mode, sqlite3Strlen30(set_journal_mode)); - if(journal_mode) sqlcipher_free(journal_mode, sqlite3Strlen30(journal_mode)); - if(pragma_compat) sqlcipher_free(pragma_compat, 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; -} - -static 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 && - sqlite3StrNICmp((const char *)zRight ,"x'", 2) == 0 && - 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_LOG_CORE, "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_LOG_CORE, "sqlcipher_codec_add_random: attemt to add random with invalid format"); - return SQLITE_ERROR; -} - -#if defined(_WIN32) -/* On windows convert to utf-16 when writing to stderr or stdout to avoid - * a potential exception when writing mixed context to those streams - * when using the shell. */ -static int sqlcipher_fprintf(FILE* stream, const char* format, ...) { - int sz; - va_list ap; - - if (stream == stderr || stream == stdout) { - char* buffer = NULL; - wchar_t* wbuffer = NULL; - - va_start(ap, format); - buffer = sqlite3_vmprintf(format, ap); - va_end(ap); - sz = (int)strlen(buffer); - - wbuffer = sqlite3_malloc((sz + 1) * sizeof(wchar_t)); - if (wbuffer == NULL) return -1; - - sz = MultiByteToWideChar(CP_UTF8, 0, buffer, sz, wbuffer, sz); - wbuffer[sz] = (wchar_t) 0; - fputws(wbuffer, stream); - - sqlite3_free(wbuffer); - sqlite3_free(buffer); - } else { - va_start(ap, format); - sz = vfprintf(stream, format, ap); - va_end(ap); - } - return sz; -} -#else -#define sqlcipher_fprintf fprintf -#endif - -#if !defined(SQLITE_OMIT_TRACE) - -#define SQLCIPHER_PROFILE_FMT "Elapsed time:%.3f ms - %s\n" -#define SQLCIPHER_PROFILE_FMT_OSLOG "Elapsed time:%{public}.3f ms - %{public}s\n" - -static int sqlcipher_profile_callback(unsigned int trace, void *file, void *stmt, void *run_time){ - FILE *f = (FILE*) file; - double elapsed = (*((sqlite3_uint64*)run_time))/1000000.0; - if(f == NULL) { -#if !defined(SQLCIPHER_OMIT_LOG_DEVICE) -#if defined(__ANDROID__) - __android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", SQLCIPHER_PROFILE_FMT, elapsed, sqlite3_sql((sqlite3_stmt*)stmt)); -#elif defined(__APPLE__) - os_log(OS_LOG_DEFAULT, SQLCIPHER_PROFILE_FMT_OSLOG, elapsed, sqlite3_sql((sqlite3_stmt*)stmt)); -#endif -#endif - } else { - sqlcipher_fprintf(f, SQLCIPHER_PROFILE_FMT, elapsed, sqlite3_sql((sqlite3_stmt*)stmt)); - } - return SQLITE_OK; -} -#endif - -static int sqlcipher_cipher_profile(sqlite3 *db, const char *destination){ -#if defined(SQLITE_OMIT_TRACE) - return SQLITE_ERROR; -#else - FILE *f = NULL; - if(sqlite3_stricmp(destination, "off") == 0){ - sqlite3_trace_v2(db, 0, NULL, NULL); /* disable tracing */ - } else { - if(sqlite3_stricmp(destination, "stdout") == 0){ - f = stdout; - }else if(sqlite3_stricmp(destination, "stderr") == 0){ - f = stderr; - }else if(sqlite3_stricmp(destination, "logcat") == 0 || sqlite3_stricmp(destination, "device") == 0){ - f = NULL; /* file pointer will be NULL indicating the device target (i.e. logcat or oslog). We will accept logcat for backwards compatibility */ - }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 - } - sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, sqlcipher_profile_callback, f); - } - return SQLITE_OK; -#endif -} - -static char *sqlcipher_get_log_level_str(unsigned int level) { - switch(level) { - case SQLCIPHER_LOG_ERROR: - return "ERROR"; - case SQLCIPHER_LOG_WARN: - return "WARN"; - case SQLCIPHER_LOG_INFO: - return "INFO"; - case SQLCIPHER_LOG_DEBUG: - return "DEBUG"; - case SQLCIPHER_LOG_TRACE: - return "TRACE"; - case SQLCIPHER_LOG_ANY: - return "ANY"; - } - return "NONE"; -} - -static char *sqlcipher_get_log_source_str(unsigned int source) { - switch(source) { - case SQLCIPHER_LOG_NONE: - return "NONE"; - case SQLCIPHER_LOG_CORE: - return "CORE"; - case SQLCIPHER_LOG_MEMORY: - return "MEMORY"; - case SQLCIPHER_LOG_MUTEX: - return "MUTEX"; - case SQLCIPHER_LOG_PROVIDER: - return "PROVIDER"; - } - return "ANY"; -} - -static char *sqlcipher_get_log_sources_str(unsigned int source) { - if(source == SQLCIPHER_LOG_NONE) { - return sqlite3_mprintf("%s", "NONE"); - } else if (source == SQLCIPHER_LOG_ANY) { - return sqlite3_mprintf("%s", "ANY"); - } else { - char *sources = NULL; - unsigned int flag; - for(flag = SQLCIPHER_LOG_CORE; flag != 0; flag = flag << 1) { - if(SQLCIPHER_FLAG_GET(source, flag)) { - char *src = sqlcipher_get_log_source_str(flag); - if(sources) { - char *tmp = sqlite3_mprintf("%s %s", sources, src); - sqlite3_free(sources); - sources = tmp; - } else { - sources = sqlite3_mprintf("%s", src); - } - } - } - return sources; - } -} - -#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 -#define MAX_LOG_LEN 8192 -void sqlcipher_log(unsigned int level, unsigned int source, const char *message, ...) { - va_list params; - va_start(params, message); - char formatted[MAX_LOG_LEN]; - size_t len = 0; - -#ifdef CODEC_DEBUG -#if defined(SQLCIPHER_OMIT_LOG_DEVICE) || (!defined(__ANDROID__) && !defined(__APPLE__)) - sqlite3_vsnprintf(MAX_LOG_LEN, formatted, message, params); - sqlcipher_fprintf(stderr, formatted); - sqlcipher_fprintf(stderr, "\n"); - goto end; -#else -#if defined(__ANDROID__) - __android_log_vprint(ANDROID_LOG_DEBUG, "sqlcipher", message, params); - goto end; -#elif defined(__APPLE__) - sqlite3_vsnprintf(MAX_LOG_LEN, formatted, message, params); - os_log(OS_LOG_DEFAULT, "%{public}s", formatted); - goto end; -#endif -#endif -#endif - if( - level > sqlcipher_log_level /* log level is higher, e.g. level filter is at ERROR but this message is DEBUG */ - || !SQLCIPHER_FLAG_GET(sqlcipher_log_source, source) /* source filter doesn't match this message source */ - || (sqlcipher_log_device == 0 && sqlcipher_log_file == NULL) /* no configured log target */ - ) { - /* skip logging this message */ - goto end; - } - - sqlite3_snprintf(MAX_LOG_LEN, formatted, "%s %s ", sqlcipher_get_log_level_str(level), sqlcipher_get_log_source_str(source)); - len = strlen(formatted); - sqlite3_vsnprintf(MAX_LOG_LEN - (int) len, formatted + (int) len, message, params); - -#if !defined(SQLCIPHER_OMIT_LOG_DEVICE) - if(sqlcipher_log_device) { -#if defined(__ANDROID__) - __android_log_write(ANDROID_LOG_DEBUG, "sqlcipher", formatted); - goto end; -#elif defined(__APPLE__) - os_log(OS_LOG_DEFAULT, "%{public}s", formatted); - goto end; -#endif - } -#endif - - 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)) { - sqlcipher_fprintf((FILE*)sqlcipher_log_file, "%s.%03d: %s\n", buffer, ms, formatted); - goto end; - } - } - -end: - va_end(params); -} -#endif - -static 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_device = 0; - - if(sqlite3_stricmp(destination, "logcat") == 0 || sqlite3_stricmp(destination, "device") == 0){ - /* use the appropriate device log. accept logcat for backwards compatibility */ - sqlcipher_log_device = 1; - } else if(sqlite3_stricmp(destination, "stdout") == 0){ - sqlcipher_log_file = stdout; - }else if(sqlite3_stricmp(destination, "stderr") == 0){ - sqlcipher_log_file = stderr; - }else if(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_LOG_CORE, "sqlcipher_set_log: set log to %s", destination); - return SQLITE_OK; -#endif -} - -static void sqlcipher_vdbe_return_string(Parse *pParse, const char *zLabel, const char *value, int value_type){ - Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, value, value_type); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); -} - -static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ctx) { - int rc; - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d", ctx->page_sz, ctx->reserve_sz); - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "codec_set_btree_to_codec_pagesize: entering database mutex %p", db->mutex); - sqlite3_mutex_enter(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "codec_set_btree_to_codec_pagesize: entered database mutex %p", db->mutex); - db->nextPagesize = ctx->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 = sqlite3BtreeSetPageSize(pDb->pBt, ctx->page_sz, ctx->reserve_sz, 0); - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize returned %d", rc); - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "codec_set_btree_to_codec_pagesize: leaving database mutex %p", db->mutex); - sqlite3_mutex_leave(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "codec_set_btree_to_codec_pagesize: left database mutex %p", db->mutex); - - return rc; -} - -static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) { - struct Db *pDb = &db->aDb[nDb]; - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "codec_set_pass_key: db=%p nDb=%d for_ctx=%d", db, nDb, for_ctx); - if(pDb->pBt) { - codec_ctx *ctx = (codec_ctx*) sqlcipherPagerGetCodec(sqlite3BtreePager(pDb->pBt)); - - if(ctx) { - return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx); - } else { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "codec_set_pass_key: error ocurred fetching codec from pager on db %d", nDb); - return SQLITE_ERROR; - } - } - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "codec_set_pass_key: no btree present on db %d", nDb); - return SQLITE_ERROR; -} - -int sqlcipher_codec_pragma(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(sqlite3BtreePager(pDb->pBt)); - } - - if(sqlite3_stricmp(zLeft, "key") !=0 && sqlite3_stricmp(zLeft, "rekey") != 0) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_pragma: db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p", db, iDb, pParse, zLeft, zRight, ctx); - } - -#ifdef SQLCIPHER_TEST - if( sqlite3_stricmp(zLeft,"cipher_test_on")==0 ){ - if( zRight ) { - if(sqlite3_stricmp(zRight, "fail_encrypt")==0) { - SQLCIPHER_FLAG_SET(cipher_test_flags,TEST_FAIL_ENCRYPT); - } else - if(sqlite3_stricmp(zRight, "fail_decrypt")==0) { - SQLCIPHER_FLAG_SET(cipher_test_flags,TEST_FAIL_DECRYPT); - } else - if(sqlite3_stricmp(zRight, "fail_migrate")==0) { - SQLCIPHER_FLAG_SET(cipher_test_flags,TEST_FAIL_MIGRATE); - } - } - } else - if( sqlite3_stricmp(zLeft,"cipher_test_off")==0 ){ - if( zRight ) { - if(sqlite3_stricmp(zRight, "fail_encrypt")==0) { - SQLCIPHER_FLAG_UNSET(cipher_test_flags,TEST_FAIL_ENCRYPT); - } else - if(sqlite3_stricmp(zRight, "fail_decrypt")==0) { - SQLCIPHER_FLAG_UNSET(cipher_test_flags,TEST_FAIL_DECRYPT); - } else - if(sqlite3_stricmp(zRight, "fail_migrate")==0) { - SQLCIPHER_FLAG_UNSET(cipher_test_flags,TEST_FAIL_MIGRATE); - } - } - } else - if( sqlite3_stricmp(zLeft,"cipher_test")==0 ){ - char *flags = sqlite3_mprintf("%u", cipher_test_flags); - sqlcipher_vdbe_return_string(pParse, "cipher_test", flags, P4_DYNAMIC); - }else - if( sqlite3_stricmp(zLeft,"cipher_test_rand")==0 ){ - if( zRight ) { - int rand = atoi(zRight); - cipher_test_rand = rand; - } else { - char *rand = sqlite3_mprintf("%d", cipher_test_rand); - sqlcipher_vdbe_return_string(pParse, "cipher_test_rand", rand, P4_DYNAMIC); - } - } else -#endif - if( sqlite3_stricmp(zLeft, "cipher_fips_status")== 0 && !zRight ){ - if(ctx) { - char *fips_mode_status = sqlite3_mprintf("%d", ctx->provider->fips_status(ctx->provider_ctx)); - sqlcipher_vdbe_return_string(pParse, "cipher_fips_status", fips_mode_status, P4_DYNAMIC); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_store_pass")==0 && zRight ) { - if(ctx) { - char *deprecation = "PRAGMA cipher_store_pass is deprecated, please remove from use"; - ctx->store_pass = sqlite3GetBoolean(zRight, 1); - sqlcipher_vdbe_return_string(pParse, "cipher_store_pass", deprecation, P4_TRANSIENT); - sqlite3_log(SQLITE_WARNING, deprecation); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_store_pass")==0 && !zRight ) { - if(ctx){ - char *store_pass_value = sqlite3_mprintf("%d", ctx->store_pass); - sqlcipher_vdbe_return_string(pParse, "cipher_store_pass", store_pass_value, P4_DYNAMIC); - } - } - if( sqlite3_stricmp(zLeft, "cipher_profile")== 0 && zRight ){ - char *profile_status = sqlite3_mprintf("%d", sqlcipher_cipher_profile(db, zRight)); - sqlcipher_vdbe_return_string(pParse, "cipher_profile", profile_status, P4_DYNAMIC); - } else - if( sqlite3_stricmp(zLeft, "cipher_add_random")==0 && zRight ){ - if(ctx) { - char *add_random_status = sqlite3_mprintf("%d", sqlcipher_codec_add_random(ctx, zRight, sqlite3Strlen30(zRight))); - sqlcipher_vdbe_return_string(pParse, "cipher_add_random", add_random_status, P4_DYNAMIC); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_migrate")==0 && !zRight ){ - if(ctx){ - int status = sqlcipher_codec_ctx_migrate(ctx); - char *migrate_status = 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_LOG_CORE, "sqlcipher_codec_pragma: error occurred during cipher_migrate: %d", status); - } - } - } else - if( sqlite3_stricmp(zLeft, "cipher_provider")==0 && !zRight ){ - if(ctx) { - sqlcipher_vdbe_return_string(pParse, "cipher_provider", - ctx->provider->get_provider_name(ctx->provider_ctx), P4_TRANSIENT); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_provider_version")==0 && !zRight){ - if(ctx) { - sqlcipher_vdbe_return_string(pParse, "cipher_provider_version", - ctx->provider->get_provider_version(ctx->provider_ctx), P4_TRANSIENT); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_version")==0 && !zRight ){ - sqlcipher_vdbe_return_string(pParse, "cipher_version", sqlcipher_version(), P4_DYNAMIC); - }else - if( 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); - sqlite3_log(SQLITE_WARNING, message); - }else { - sqlcipher_vdbe_return_string(pParse, "cipher", - ctx->provider->get_cipher(ctx->provider_ctx), P4_TRANSIENT); - } - } - }else - if( 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); - sqlite3_log(SQLITE_WARNING, message); - }else - if( sqlite3_stricmp(zLeft,"cipher_default_kdf_iter")==0 ){ - if( zRight ) { - default_kdf_iter = atoi(zRight); /* change default KDF iterations */ - } else { - char *kdf_iter = sqlite3_mprintf("%d", default_kdf_iter); - sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_iter", kdf_iter, P4_DYNAMIC); - } - }else - if( 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 = sqlite3_mprintf("%d", ctx->kdf_iter); - sqlcipher_vdbe_return_string(pParse, "kdf_iter", kdf_iter, P4_DYNAMIC); - } - } - }else - if( 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); - sqlite3_log(SQLITE_WARNING, deprecation); - } else { - char *fast_kdf_iter = sqlite3_mprintf("%d", ctx->fast_kdf_iter); - sqlcipher_vdbe_return_string(pParse, "fast_kdf_iter", fast_kdf_iter, P4_DYNAMIC); - } - } - }else - if( 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); - sqlite3_log(SQLITE_WARNING, message); - }else - if( sqlite3_stricmp(zLeft,"page_size")==0 || sqlite3_stricmp(zLeft,"cipher_page_size")==0 ){ - /* PRAGMA cipher_page_size will alter the size of the database pages while ensuring that the - required reserve space is allocated at the end of each page. This will also override the - standard SQLite PRAGMA page_size behavior if a codec context is attached to the database handle. - If PRAGMA page_size is invoked but a codec context is not attached (i.e. dealing with a standard - unencrypted database) then return early and allow the standard PRAGMA page_size logic to apply. */ - 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 = sqlite3_mprintf("%d", ctx->page_sz); - sqlcipher_vdbe_return_string(pParse, "cipher_page_size", page_size, P4_DYNAMIC); - } - } else { - return 0; /* return early so that the PragTyp_PAGE_SIZE case logic in pragma.c will take effect */ - } - }else - if( sqlite3_stricmp(zLeft,"cipher_default_page_size")==0 ){ - if( zRight ) { - default_page_size = atoi(zRight); - } else { - char *page_size = sqlite3_mprintf("%d", default_page_size); - sqlcipher_vdbe_return_string(pParse, "cipher_default_page_size", page_size, P4_DYNAMIC); - } - }else - if( sqlite3_stricmp(zLeft,"cipher_default_use_hmac")==0 ){ - if( zRight ) { - sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1)); - } else { - char *default_use_hmac = sqlite3_mprintf("%d", SQLCIPHER_FLAG_GET(default_flags, CIPHER_FLAG_HMAC)); - sqlcipher_vdbe_return_string(pParse, "cipher_default_use_hmac", default_use_hmac, P4_DYNAMIC); - } - }else - if( sqlite3_stricmp(zLeft,"cipher_use_hmac")==0 ){ - if(ctx) { - if( zRight ) { - rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 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 = sqlite3_mprintf("%d", SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HMAC)); - sqlcipher_vdbe_return_string(pParse, "cipher_use_hmac", hmac_flag, P4_DYNAMIC); - } - } - }else - if( 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(sqlite3_stricmp(zRight, "le") == 0) { - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_BE_PGNO); - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_LE_PGNO); - } else if(sqlite3_stricmp(zRight, "be") == 0) { - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_LE_PGNO); - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_BE_PGNO); - } else if(sqlite3_stricmp(zRight, "native") == 0) { - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_LE_PGNO); - SQLCIPHER_FLAG_UNSET(ctx->flags, CIPHER_FLAG_BE_PGNO); - } - sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", deprecation, P4_TRANSIENT); - sqlite3_log(SQLITE_WARNING, deprecation); - - } else { - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_LE_PGNO)) { - sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", "le", P4_TRANSIENT); - } else if(SQLCIPHER_FLAG_GET(ctx->flags, 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( 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 (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) { - unsigned char mask = 0; - const unsigned char *hex = (const unsigned char *)zRight+2; - cipher_hex2bin(hex,2,&mask); - hmac_salt_mask = mask; - } - sqlcipher_vdbe_return_string(pParse, "cipher_hmac_salt_mask", deprecation, P4_TRANSIENT); - sqlite3_log(SQLITE_WARNING, deprecation); - } else { - char *mask = sqlite3_mprintf("%02x", hmac_salt_mask); - sqlcipher_vdbe_return_string(pParse, "cipher_hmac_salt_mask", mask, P4_DYNAMIC); - } - } - }else - if( 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 = sqlite3_mprintf("%d", ctx->plaintext_header_sz); - sqlcipher_vdbe_return_string(pParse, "cipher_plaintext_header_size", size, P4_DYNAMIC); - } - } - }else - if( sqlite3_stricmp(zLeft,"cipher_default_plaintext_header_size")==0 ){ - if( zRight ) { - default_plaintext_header_size = atoi(zRight); - } else { - char *size = sqlite3_mprintf("%d", default_plaintext_header_size); - sqlcipher_vdbe_return_string(pParse, "cipher_default_plaintext_header_size", size, P4_DYNAMIC); - } - }else - if( sqlite3_stricmp(zLeft,"cipher_salt")==0 ){ - if(ctx) { - if(zRight) { - if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == (FILE_HEADER_SZ*2)+3) { - unsigned char *salt = (unsigned char*) 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); - sqlite3_free(salt); - } - } else { - void *salt; - char *hexsalt = (char*) 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 { - sqlite3_free(hexsalt); - sqlcipher_codec_ctx_set_error(ctx, rc); - } - } - } - }else - if( sqlite3_stricmp(zLeft,"cipher_hmac_algorithm")==0 ){ - if(ctx) { - if(zRight) { - rc = SQLITE_ERROR; - if(sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) { - rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1); - } else if(sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) { - rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA256); - } else if(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 = ctx->hmac_algorithm; - if(ctx->hmac_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( sqlite3_stricmp(zLeft,"cipher_default_hmac_algorithm")==0 ){ - if(zRight) { - rc = SQLITE_OK; - if(sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) { - default_hmac_algorithm = SQLCIPHER_HMAC_SHA1; - } else if(sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) { - default_hmac_algorithm = SQLCIPHER_HMAC_SHA256; - } else if(sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) { - default_hmac_algorithm = SQLCIPHER_HMAC_SHA512; - } - } else { - if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA1) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA1_LABEL, P4_TRANSIENT); - } else if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA256) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA256_LABEL, P4_TRANSIENT); - } else if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA512) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA512_LABEL, P4_TRANSIENT); - } - } - }else - if( sqlite3_stricmp(zLeft,"cipher_kdf_algorithm")==0 ){ - if(ctx) { - if(zRight) { - rc = SQLITE_ERROR; - if(sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) { - rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1); - } else if(sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) { - rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA256); - } else if(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 { - if(ctx->kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) { - sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT); - } else if(ctx->kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) { - sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT); - } else if(ctx->kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) { - sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT); - } - } - } - }else - if( sqlite3_stricmp(zLeft,"cipher_default_kdf_algorithm")==0 ){ - if(zRight) { - rc = SQLITE_OK; - if(sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) { - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA1; - } else if(sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) { - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA256; - } else if(sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) { - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA512; - } - } else { - if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT); - } else if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT); - } else if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) { - sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT); - } - } - }else - if( 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( sqlite3_stricmp(zLeft,"cipher_default_compatibility")==0 ){ - if(zRight) { - int version = atoi(zRight); - switch(version) { - case 1: - default_page_size = 1024; - default_hmac_algorithm = SQLCIPHER_HMAC_SHA1; - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA1; - default_kdf_iter = 4000; - sqlcipher_set_default_use_hmac(0); - break; - - case 2: - default_page_size = 1024; - default_hmac_algorithm = SQLCIPHER_HMAC_SHA1; - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA1; - default_kdf_iter = 4000; - sqlcipher_set_default_use_hmac(1); - break; - - case 3: - default_page_size = 1024; - default_hmac_algorithm = SQLCIPHER_HMAC_SHA1; - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA1; - default_kdf_iter = 64000; - sqlcipher_set_default_use_hmac(1); - break; - - default: - default_page_size = 4096; - default_hmac_algorithm = SQLCIPHER_HMAC_SHA512; - default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA512; - default_kdf_iter = 256000; - sqlcipher_set_default_use_hmac(1); - break; - } - } - }else - if( sqlite3_stricmp(zLeft,"cipher_memory_security")==0 ){ - if( zRight ) { - if(sqlite3GetBoolean(zRight,1)) { - /* memory security can only be enabled, not disabled */ - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_set_mem_security: on"); - sqlcipher_mem_security_on = 1; - } - } else { - /* only report that memory security is enabled if pragma cipher_memory_security is ON and - SQLCipher's allocator/deallocator was run at least one time */ - int state = sqlcipher_mem_security_on && sqlcipher_mem_executed; - char *on = sqlite3_mprintf("%d", state); - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, - "sqlcipher_get_mem_security: sqlcipher_mem_security_on = %d, sqlcipher_mem_executed = %d", - sqlcipher_mem_security_on, sqlcipher_mem_executed); - sqlcipher_vdbe_return_string(pParse, "cipher_memory_security", on, P4_DYNAMIC); - } - }else - if( sqlite3_stricmp(zLeft,"cipher_settings")==0 ){ - if(ctx) { - int algorithm; - char *pragma; - - pragma = sqlite3_mprintf("PRAGMA kdf_iter = %d;", ctx->kdf_iter); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_page_size = %d;", ctx->page_sz); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_use_hmac = %d;", SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HMAC)); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_plaintext_header_size = %d;", ctx->plaintext_header_sz); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - algorithm = ctx->hmac_algorithm; - pragma = NULL; - if(algorithm == SQLCIPHER_HMAC_SHA1) { - pragma = sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL); - } else if(algorithm == SQLCIPHER_HMAC_SHA256) { - pragma = sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL); - } else if(algorithm == SQLCIPHER_HMAC_SHA512) { - pragma = sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL); - } - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - algorithm = ctx->kdf_algorithm; - pragma = NULL; - if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) { - pragma = sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL); - } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) { - pragma = sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL); - } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) { - pragma = sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL); - } - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - } - }else - if( sqlite3_stricmp(zLeft,"cipher_default_settings")==0 ){ - char *pragma; - - pragma = sqlite3_mprintf("PRAGMA cipher_default_kdf_iter = %d;", default_kdf_iter); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_default_page_size = %d;", default_page_size); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_default_use_hmac = %d;", SQLCIPHER_FLAG_GET(default_flags, CIPHER_FLAG_HMAC)); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = sqlite3_mprintf("PRAGMA cipher_default_plaintext_header_size = %d;", default_plaintext_header_size); - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = NULL; - if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA1) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL); - } else if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA256) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL); - } else if(default_hmac_algorithm == SQLCIPHER_HMAC_SHA512) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL); - } - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - - pragma = NULL; - if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL); - } else if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL); - } else if(default_kdf_algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) { - pragma = sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL); - } - sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC); - }else - if( sqlite3_stricmp(zLeft,"cipher_integrity_check")==0 ){ - if(ctx) { - sqlcipher_codec_ctx_integrity_check(ctx, pParse, "cipher_integrity_check"); - } - } else - if( sqlite3_stricmp(zLeft, "cipher_log_level")==0 ){ - if(zRight) { - sqlcipher_log_level = SQLCIPHER_LOG_NONE; - if(sqlite3_stricmp(zRight, "ERROR")==0) sqlcipher_log_level = SQLCIPHER_LOG_ERROR; - else if(sqlite3_stricmp(zRight, "WARN" )==0) sqlcipher_log_level = SQLCIPHER_LOG_WARN; - else if(sqlite3_stricmp(zRight, "INFO" )==0) sqlcipher_log_level = SQLCIPHER_LOG_INFO; - else if(sqlite3_stricmp(zRight, "DEBUG")==0) sqlcipher_log_level = SQLCIPHER_LOG_DEBUG; - else if(sqlite3_stricmp(zRight, "TRACE")==0) sqlcipher_log_level = SQLCIPHER_LOG_TRACE; - } - sqlcipher_vdbe_return_string(pParse, "cipher_log_level", sqlcipher_get_log_level_str(sqlcipher_log_level), P4_TRANSIENT); - } else - if( sqlite3_stricmp(zLeft, "cipher_log_source")==0 ){ - if(zRight) { - if(sqlite3_stricmp(zRight, "NONE" )==0) sqlcipher_log_source = SQLCIPHER_LOG_NONE; - else if(sqlite3_stricmp(zRight, "ANY" )==0) sqlcipher_log_source = SQLCIPHER_LOG_ANY; - else { - if(sqlite3_stricmp(zRight, "CORE" )==0) SQLCIPHER_FLAG_SET(sqlcipher_log_source, SQLCIPHER_LOG_CORE); - else if(sqlite3_stricmp(zRight, "MEMORY" )==0) SQLCIPHER_FLAG_SET(sqlcipher_log_source, SQLCIPHER_LOG_MEMORY); - else if(sqlite3_stricmp(zRight, "MUTEX" )==0) SQLCIPHER_FLAG_SET(sqlcipher_log_source, SQLCIPHER_LOG_MUTEX); - else if(sqlite3_stricmp(zRight, "PROVIDER")==0) SQLCIPHER_FLAG_SET(sqlcipher_log_source, SQLCIPHER_LOG_PROVIDER); - } - } - sqlcipher_vdbe_return_string(pParse, "cipher_log_source", sqlcipher_get_log_sources_str(sqlcipher_log_source), P4_DYNAMIC); - } else - if( sqlite3_stricmp(zLeft, "cipher_log")== 0 && zRight ){ - char *status = 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 - -/* - * 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* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { - codec_ctx *ctx = (codec_ctx *) iCtx; - int offset = 0, rc = 0; - unsigned char *pData = (unsigned char *) data; - int cctx = CIPHER_READ_CTX; - void *out = NULL; - sqlite3_mutex *mutex = ctx->pBt->sharable ? sqlcipher_mutex(SQLCIPHER_MUTEX_SHAREDCACHE) : NULL; - - /* in shared cache mode, this needs to be mutexed to prevent a separate database handle from - * nuking the context on the shared Btree */ - if(mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering mutex %p", __func__, mutex); - sqlite3_mutex_enter(mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered mutex %p", __func__, mutex); - } - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlite3Codec: pgno=%d, mode=%d, ctx->page_sz=%d", pgno, mode, ctx->page_sz); - - if(ctx->error != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: identified deferred error condition: %d", __func__, rc); - sqlcipher_codec_ctx_set_error(ctx, ctx->error); - goto cleanup; - } - - /* call to derive keys if not present yet */ - if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3Codec: error occurred during key derivation: %d", rc); - sqlcipher_codec_ctx_set_error(ctx, rc); - goto cleanup; - } - - /* 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(ctx->plaintext_header_sz < 0) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3Codec: error invalid ctx->plaintext_header_sz: %d", ctx->plaintext_header_sz); - sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR); - goto cleanup; - } - - if(pgno == 1) /* adjust starting pointers in data page for header offset on first page*/ - offset = ctx->plaintext_header_sz ? ctx->plaintext_header_sz : FILE_HEADER_SZ; - - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "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(ctx->buffer, ctx->plaintext_header_sz ? pData : (void *) SQLITE_FILE_HEADER, offset); - - rc = sqlcipher_page_cipher(ctx, cctx, pgno, SQLCIPHER_DECRYPT, ctx->page_sz - offset, pData + offset, (unsigned char*)ctx->buffer + offset); -#ifdef SQLCIPHER_TEST - if((cipher_test_flags & TEST_FAIL_DECRYPT) > 0 && sqlcipher_get_test_fail()) { - rc = SQLITE_ERROR; - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_CORE, "sqlite3Codec: simulating decryption failure for pgno=%d, mode=%d, ctx->page_sz=%d", pgno, mode, ctx->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. The only exception here is when a database is being "recovered", - * which we consider to be the case if the plaintext header size is set to the full non-reserved size of a page. If that is the case we consider - * this to be operating in recovery mode, and will log the error but not permanently put the codec into an error state */ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3Codec: error decrypting page %d data: %d", pgno, rc); - sqlcipher_memset((unsigned char*) ctx->buffer+offset, 0, ctx->page_sz-offset); - if(ctx->plaintext_header_sz == ctx->page_sz - ctx->reserve_sz) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: plaintext header size of %d indicates recovery mode, suppressing permanent error", __func__, ctx->plaintext_header_sz); - } else { - sqlcipher_codec_ctx_set_error(ctx, rc); - } - } else { - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_KEY_USED); - } - memcpy(pData, ctx->buffer, ctx->page_sz); /* copy buffer data back to pData and return */ - out = pData; - goto cleanup; - 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_LOG_CORE, "sqlite3Codec: error retrieving salt: %d", rc); - sqlcipher_codec_ctx_set_error(ctx, rc); - goto cleanup; - } - memcpy(ctx->buffer, ctx->plaintext_header_sz ? pData : kdf_salt, offset); - } - rc = sqlcipher_page_cipher(ctx, cctx, pgno, SQLCIPHER_ENCRYPT, ctx->page_sz - offset, pData + offset, (unsigned char*)ctx->buffer + offset); -#ifdef SQLCIPHER_TEST - if((cipher_test_flags & TEST_FAIL_ENCRYPT) > 0 && sqlcipher_get_test_fail()) { - rc = SQLITE_ERROR; - sqlcipher_log(SQLCIPHER_LOG_WARN, SQLCIPHER_LOG_CORE, "sqlite3Codec: simulating encryption failure for pgno=%d, mode=%d, ctx->page_sz=%d", pgno, mode, ctx->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_LOG_CORE, "sqlite3Codec: error encrypting page %d data: %d", pgno, rc); - sqlcipher_memset((unsigned char*)ctx->buffer+offset, 0, ctx->page_sz-offset); - sqlcipher_codec_ctx_set_error(ctx, rc); - goto cleanup; - } - SQLCIPHER_FLAG_SET(ctx->flags, CIPHER_FLAG_KEY_USED); - out = ctx->buffer; /* return persistent buffer data, pData remains intact */ - goto cleanup; - break; - - default: - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3Codec: error unsupported codec mode %d", mode); - sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR); /* unsupported mode, set error */ - out = pData; - goto cleanup; - break; - } - -cleanup: - if(mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving mutex %p", __func__, mutex); - sqlite3_mutex_leave(mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left mutex %p", __func__, mutex); - } - return out; -} - -/* This callback will be invoked when a database connection is closed. It is basically a light wrapper - * ariund sqlciher_codec_ctx_free that locks the shared cache mutex if necessary */ -static void sqlite3FreeCodecArg(void *pCodecArg) { - codec_ctx *ctx = (codec_ctx *) pCodecArg; - sqlite3_mutex *mutex = ctx->pBt->sharable ? sqlcipher_mutex(SQLCIPHER_MUTEX_SHAREDCACHE) : NULL; - - if(pCodecArg == NULL) return; - - /* in shared cache mode, this needs to be mutexed to prevent a codec context from being deallocated when - * it is in use by the codec due to cross-database handle access to the shared Btree */ - if(mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering mutex %p", __func__, mutex); - sqlite3_mutex_enter(mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered mutex %p", __func__, mutex); - } - - sqlcipher_codec_ctx_free(&ctx); /* wipe and free allocated memory for the context */ - - if(mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving mutex %p", __func__, mutex); - sqlite3_mutex_leave(mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left mutex %p", __func__, mutex); - } -} - -int sqlcipherCodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { - struct Db *pDb = NULL; - sqlite3_file *fd = NULL; - codec_ctx *ctx = NULL; - Pager *pPager = NULL; - int rc = SQLITE_OK; - sqlite3_mutex *extra_mutex = NULL; - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: db=%p, nDb=%d", __func__, db, nDb); - - if(!sqlcipher_init) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: sqlcipher not initialized %d", __func__, sqlcipher_init_error); - return sqlcipher_init_error; - } - - /* error pKey is not null and nKey is > 0 */ - if(!(nKey && zKey)) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: no key", __func__); - return SQLITE_MISUSE; - } - - if(!(db && (pDb = &db->aDb[nDb]))) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: invalid database", __func__); - return SQLITE_MISUSE; - } - - /* After this point, early returns for API misuse are complete, lock on a mutex and ensure it is cleaned - * up later. If shared cache is enabled then enter a specially defined "global" recursive mutex specifically - * for isolating shared cache connections, otherwise use the built-in databse mutex */ - extra_mutex = pDb->pBt->sharable ? sqlcipher_mutex(SQLCIPHER_MUTEX_SHAREDCACHE) : NULL; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering database mutex %p", __func__, db->mutex); - sqlite3_mutex_enter(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered database mutex %p", __func__, db->mutex); - - if(extra_mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entering mutex %p", __func__, extra_mutex); - sqlite3_mutex_enter(extra_mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: entered mutex %p", __func__, extra_mutex); - } - - pPager = sqlite3BtreePager(pDb->pBt); - ctx = (codec_ctx*) sqlcipherPagerGetCodec(pPager); - - if(ctx != NULL) { - /* There is already a codec attached to this database */ - if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_KEY_USED)) { - /* The key was derived and used successfully, so return early */ - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_CORE, "%s: disregarding attempt to set key on an previously keyed database connection handle", __func__); - goto cleanup; -#ifndef SQLITE_DEBUG - } else if (pDb->pBt->sharable) { - /* This Btree is participating in shared cache. It would be usafe to reset and reattach a new codec, so return early. - * - * When compiled with SQLITE_DEBUG, all database connections have shared cached enabled. This behavior of disallowing reset - * of the codec on a shared cache connection will break several tests that depend on the the ability to reset the codec, - * like migration tests, repeat-keying tests, etc. Asa result we will disable shared cache handling when compiled with - * SQLIE_DEBUG enabled.*/ - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_CORE, "%s: disregarding attempt to set key on an shared cache handle", __func__); - goto cleanup; -#endif - } else { - /* To preseve legacy functionality where an incorrect key could be replaced by a correct key without closing the database, - * if the key has not been used, and shared cache is not enabled, reset the codec on this pager entirely. - * This will call sqlcipher_codec_ctx_free directly instead of through sqlite3FreeCodecArg because this function already - * holds the shared cache mutex if it is necessary, and that avoids requiring a more expensive recursive mutex */ - sqlcipher_log(SQLCIPHER_LOG_INFO, SQLCIPHER_LOG_CORE, "%s: resetting existing codec on pager", __func__); - sqlcipher_codec_ctx_free(&ctx); - sqlcipherPagerSetCodec(pPager, NULL, NULL, NULL, NULL); - ctx = NULL; - } - } - - /* check if the sqlite3_file is open, and if not force handle to NULL */ - if((fd = sqlite3PagerFile(pPager))->pMethods == 0) fd = NULL; - - /* point the internal codec argument against the contet to be prepared */ - rc = sqlcipher_codec_ctx_init(&ctx, pDb, pPager, zKey, nKey); - - if(rc != SQLITE_OK) { - /* initialization failed, do not attach potentially corrupted context */ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: context initialization failed, forcing error state with rc=%d", __func__, 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 */ - sqlite3pager_error(pPager, rc); - pDb->pBt->pBt->db->errCode = rc; - goto cleanup; - } - - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: calling sqlcipherPagerSetCodec()", __func__); - sqlcipherPagerSetCodec(pPager, sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx); - - 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 - sqlite3PagerDontWrite optimizations) */ - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: calling sqlite3BtreeSecureDelete()", __func__); - 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, SQLCIPHER_LOG_CORE, "%s: calling sqlite3BtreeSetAutoVacuum()", __func__); - sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM); - } - -cleanup: - - if(extra_mutex) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving mutex %p", __func__, extra_mutex); - sqlite3_mutex_leave(extra_mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left mutex %p", __func__, extra_mutex); - } - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: leaving database mutex %p", __func__, db->mutex); - sqlite3_mutex_leave(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "%s: left database mutex %p", __func__, db->mutex); - - return rc; -} - -int sqlcipher_find_db_index(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 sqlite3_activate_see(const char* in) { - /* do nothing, security enhancements are always active */ -} - -SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: db=%p", __func__, db); - return sqlite3_key_v2(db, "main", pKey, nKey); -} - -SQLITE_API int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { - int db_index = sqlcipher_find_db_index(db, zDb); - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "%s: db=%p zDb=%s db_index=%d", __func__, db, zDb, db_index); - return sqlcipherCodecAttach(db, db_index, pKey, nKey); -} - -SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlite3_rekey: db=%p", db); - return sqlite3_rekey_v2(db, "main", pKey, nKey); -} - -/* 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 sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: db=%p zDb=%s", db, zDb); - - if(!sqlcipher_init) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: sqlcipher not initialized %d",__func__, sqlcipher_init_error); - return sqlcipher_init_error; - } - - 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_LOG_CORE, "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 = sqlite3BtreePager(pDb->pBt); - - ctx = (codec_ctx*) sqlcipherPagerGetCodec(pPager); - - if(ctx == NULL) { - /* there was no codec attached to this database, so this should do nothing! */ - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: no codec attached to db %s: rekey can't be used on an unencrypted database", zDb); - return SQLITE_MISUSE; - } - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlite3_rekey_v2: entering database mutex %p", db->mutex); - sqlite3_mutex_enter(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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 = sqlite3BtreeBeginTrans(pDb->pBt, 1, 0); /* begin write transaction */ - 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(!sqlite3pager_is_sj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */ - rc = sqlite3PagerGet(pPager, pgno, &page, 0); - if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */ - rc = sqlite3PagerWrite(page); - if(rc == SQLITE_OK) { - sqlite3PagerUnref(page); - } else { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: error %d occurred writing page %d", rc, pgno); - } - } else { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: error %d occurred reading 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_LOG_CORE, "sqlite3_rekey_v2: committing"); - rc = sqlite3BtreeCommit(pDb->pBt); - sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX); - } else { - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: rollback"); - sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK, 0); - } - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlite3_rekey_v2: leaving database mutex %p", db->mutex); - sqlite3_mutex_leave(db->mutex); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlite3_rekey_v2: left database mutex %p", db->mutex); - } - return SQLITE_OK; - } - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3_rekey_v2: no key provided for db %s: rekey can't be used to decrypt an encrypted database", zDb); - return SQLITE_ERROR; -} - -/* - * Retrieves the current key attached to the database if there is a codec attached to it. - * The key will be passed back using internally allocated memory and must be freed using - * sqlcipher_free to avoid memory leaks. If no key is present, zKey will be set to NULL - * and nKey to 0. - * - * If the encryption key has not yet been derived or the key material is stored, it will - * be passed back directly. Otherwise, a "keyspec" consisting of the raw key and salt - * will be used instead. */ -void sqlcipherCodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) { - struct Db *pDb = &db->aDb[nDb]; - sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipherCodecGetKey:db=%p, nDb=%d", db, nDb); - if( pDb->pBt ) { - codec_ctx *ctx = (codec_ctx*) sqlcipherPagerGetCodec(sqlite3BtreePager(pDb->pBt)); - - if(ctx) { - /* if the key has not been derived yet, or the key is stored (vi PRAGMA cipher_store_pass) - * then return the key material. Other wise pass back the keyspec */ - if(ctx->read_ctx->derive_key || ctx->store_pass == 1) { - *zKey = sqlcipher_malloc(ctx->read_ctx->pass_sz); - *nKey = ctx->read_ctx->pass_sz; - memcpy(*zKey, ctx->read_ctx->pass, ctx->read_ctx->pass_sz); - } else { - sqlcipher_cipher_ctx_get_keyspec(ctx, ctx->read_ctx, (char**) 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(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ - int rc; - rc = sqlite3VdbeFinalize((Vdbe*)pStmt); - if( rc ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - } - return rc; -} - -/* -** Execute zSql on database db. Return an error code. -** -** Based on execSql from vacuum.c -*/ -static int sqlcipher_execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - VVA_ONLY( int rc; ) - if( !zSql ){ - return SQLITE_NOMEM; - } - if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - return sqlite3_errcode(db); - } - VVA_ONLY( rc = ) 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(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - int rc; - - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - rc = sqlcipher_execSql(db, pzErrMsg, (char*)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 sqlite3RunVacuum from vacuum.c -*/ -static void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) { - sqlite3 *db = 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 = sqlite3_mprintf("invalid number of arguments (%d) passed to sqlcipher_export", argc); - goto end_of_export; - } - - if(sqlite3_value_type(argv[0]) == SQLITE_NULL) { - rc = SQLITE_ERROR; - pzErrMsg = sqlite3_mprintf("target database can't be NULL"); - goto end_of_export; - } - - targetDb = (const char*) sqlite3_value_text(argv[0]); - sourceDb = "main"; - - if(argc == 2) { - if(sqlite3_value_type(argv[1]) == SQLITE_NULL) { - rc = SQLITE_ERROR; - pzErrMsg = sqlite3_mprintf("target database can't be NULL"); - goto end_of_export; - } - sourceDb = (char *) 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 && sqlite3_stricmp("main", targetDb) != 0) { - rc = SQLITE_ERROR; - pzErrMsg = 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 = 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; - sqlite3_free(zSql); - - zSql = 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; - sqlite3_free(zSql); - - zSql = 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; - 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 = 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; - sqlite3_free(zSql); - - /* Copy over the contents of the sequence table - */ - zSql = 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; - 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 = 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; - 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) sqlite3_free(zSql); - - if(rc) { - if(pzErrMsg != NULL) { - sqlite3_result_error(context, pzErrMsg, -1); - sqlite3DbFree(db, pzErrMsg); - } else { - sqlite3_result_error(context, sqlite3ErrStr(rc), -1); - } - } -} -#endif -/* END SQLCIPHER */ - -/************** End of sqlcipher.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 - -#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, const 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_LOG_MUTEX, "sqlcipher_ltc_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_ltc_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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]; - int bytes = 0; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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 - bytes = rng_get_bytes(random_buffer, FORTUNA_MAX_SZ, NULL); -#endif - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_PROVIDER, "sqlcipher_ltc_activate: seeded fortuna with %d bytes from rng_get_bytes", bytes); - - 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_LOG_MUTEX, "sqlcipher_ltc_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - - return SQLITE_OK; -} - -static int sqlcipher_ltc_deactivate(void *ctx) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_ltc_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_ltc_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND"); - - fortuna_read(buffer, length, &prng); - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: left SQLCIPHER_MUTEX_PROVIDER_RAND"); - - return SQLITE_OK; -} - -static int sqlcipher_ltc_hmac( - void *ctx, int algorithm, - const unsigned char *hmac_key, int key_sz, - const unsigned char *in, int in_sz, - const 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, - const 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, - const unsigned char *key, int key_sz, - const unsigned char *iv, - const 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 == SQLCIPHER_ENCRYPT ? 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->init = NULL; - p->shutdown = NULL; - 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 "sqlcipher.h" */ -#include -#include -#include - -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_LOG_MUTEX, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - return SQLITE_OK; -} - -static int sqlcipher_nss_deactivate(void *ctx) { - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - return SQLITE_OK; -} - -static int sqlcipher_nss_add_random(void *ctx, const 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, - const unsigned char *hmac_key, int key_sz, - const unsigned char *in, int in_sz, - const 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, - const 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, - const unsigned char *key, int key_sz, - const unsigned char *iv, - const 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 == SQLCIPHER_ENCRYPT) { - rv = PK11_Encrypt(symKey, CKM_AES_CBC, ¶ms, out, &outLen, - in_sz + 16, in, in_sz); - } else { - rv = PK11_Decrypt(symKey, CKM_AES_CBC, ¶ms, 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->init = NULL; - p->shutdown = NULL; - 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 "sqlcipher.h" */ -#include /* amalgamator: dontcache */ -#include /* amalgamator: dontcache */ -#include /* amalgamator: dontcache */ -#include /* amalgamator: dontcache */ -#include /* amalgamator: dontcache */ -#include /* amalgamator: dontcache */ - -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_LOG_PROVIDER, "sqlcipher_openssl_log_errors: ERR_get_error() returned %lx: %s", err, ERR_error_string(err, NULL)); - } -} - -static int sqlcipher_openssl_add_random(void *ctx, const void *buffer, int length) { -#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_openssl_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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 */ - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - -#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) - ERR_load_crypto_strings(); -#endif - - openssl_init_count++; - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_openssl_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - - openssl_init_count--; - - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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) { -#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) - return OPENSSL_VERSION_TEXT; -#else - return OpenSSL_version(OPENSSL_VERSION); -#endif -} - -/* 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_LOG_MUTEX, "sqlcipher_openssl_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "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_LOG_MUTEX, "sqlcipher_openssl_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND"); - sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); - sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_openssl_random: left SQLCIPHER_MUTEX_PROVIDER_RAND"); -#endif - if(!rc) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_PROVIDER, "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, - const unsigned char *hmac_key, int key_sz, - const unsigned char *in, int in_sz, - const unsigned char *in2, int in2_sz, - unsigned char *out -) { - int rc = 0; - - 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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "sqlcipher_openssl_hmac: invalid algorithm %d", algorithm); - goto error; - } - - if(!(rc = EVP_MAC_update(hctx, in, in_sz))) { - sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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); - - return rc; -} - -static int sqlcipher_openssl_kdf( - void *ctx, int algorithm, - const unsigned char *pass, int pass_sz, - const 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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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, - const unsigned char *key, int key_sz, - const unsigned char *iv, - const 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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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_LOG_PROVIDER, "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) { - return 0; -} - -int sqlcipher_openssl_setup(sqlcipher_provider *p) { - p->init = NULL; - p->shutdown = NULL; - 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 "sqlcipher.h" */ -#include -#include -#include - -int sqlcipher_cc_setup(sqlcipher_provider *p); - -static int sqlcipher_cc_add_random(void *ctx, const 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 - /* macOS uses com.apple.security with a lowercase s */ - CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); - CFTypeRef bundle_ver; - const char *ver; - - /* if the bundle wasn't identified, try secrurity with a capial S (works for iOS) */ - if(!bundle) { - bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Security")); - } - - /* If the bundle was resolved, retrieve the bundle version key then attempt to convert it to a C string. - * Note that it is possible for CFStringGetCString to return NULL (this is warned against extensively in the - * header), so only return a value if the conversion was successful. */ - if( - bundle - && (bundle_ver = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey)) - && (ver = CFStringGetCStringPtr(bundle_ver, kCFStringEncodingUTF8)) - ) { - return ver; - } - -#endif - /* unable to detect the CoreCrypto version, return a fixed string "unknown" */ - return "unknown"; -} - -static int sqlcipher_cc_hmac( - void *ctx, int algorithm, - const unsigned char *hmac_key, int key_sz, - const unsigned char *in, int in_sz, - const 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, - const 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, - const unsigned char *key, int key_sz, - const unsigned char *iv, - const unsigned char *in, int in_sz, - unsigned char *out -) { - CCCryptorRef cryptor; - size_t tmp_csz, csz; - CCOperation op = mode == SQLCIPHER_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->init = NULL; - p->shutdown = NULL; - 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 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains routines used for walking the parser tree for -** an SQL statement. -*/ -/* #include "sqliteInt.h" */ -/* #include */ -/* #include */ - - -#if !defined(SQLITE_OMIT_WINDOWFUNC) -/* -** Walk all expressions linked into the list of Window objects passed -** as the second argument. -*/ -static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){ - Window *pWin; - for(pWin=pList; pWin; pWin=pWin->pNextWin){ - int rc; - rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExprList(pWalker, pWin->pPartition); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pFilter); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pStart); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pEnd); - if( rc ) return WRC_Abort; - if( bOneOnly ) break; - } - return WRC_Continue; -} -#endif - -/* -** Walk an expression tree. Invoke the callback once for each node -** of the expression, while descending. (In other words, the callback -** is invoked before visiting children.) -** -** The return value from the callback should be one of the WRC_* -** constants to specify how to proceed with the walk. -** -** WRC_Continue Continue descending down the tree. -** -** WRC_Prune Do not descend into child nodes, but allow -** the walk to continue with sibling nodes. -** -** WRC_Abort Do no more callbacks. Unwind the stack and -** return from the top-level walk call. -** -** The return value from this routine is WRC_Abort to abandon the tree walk -** and WRC_Continue to continue. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3WalkExprNN(Walker *pWalker, Expr *pExpr){ - int rc; - testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); - testcase( ExprHasProperty(pExpr, EP_Reduced) ); - while(1){ - rc = pWalker->xExprCallback(pWalker, pExpr); - if( rc ) return rc & WRC_Abort; - if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - assert( pExpr->x.pList==0 || pExpr->pRight==0 ); - if( pExpr->pLeft && sqlite3WalkExprNN(pWalker, pExpr->pLeft) ){ - return WRC_Abort; - } - if( pExpr->pRight ){ - assert( !ExprHasProperty(pExpr, EP_WinFunc) ); - pExpr = pExpr->pRight; - continue; - }else if( ExprUseXSelect(pExpr) ){ - assert( !ExprHasProperty(pExpr, EP_WinFunc) ); - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else{ - if( pExpr->x.pList ){ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort; - } -#endif - } - } - break; - } - return WRC_Continue; -} -SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ - return pExpr ? sqlite3WalkExprNN(pWalker,pExpr) : WRC_Continue; -} - -/* -** Call sqlite3WalkExpr() for every expression in list p or until -** an abort request is seen. -*/ -SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){ - int i; - struct ExprList_item *pItem; - if( p ){ - for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ - if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort; - } - } - return WRC_Continue; -} - -/* -** This is a no-op callback for Walker->xSelectCallback2. If this -** callback is set, then the Select->pWinDefn list is traversed. -*/ -SQLITE_PRIVATE void 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. -** Return WRC_Abort or WRC_Continue. -*/ -SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){ - if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort; - if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; - if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; -#if !defined(SQLITE_OMIT_WINDOWFUNC) - if( p->pWinDefn ){ - Parse *pParse; - if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback - || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT) -#ifndef SQLITE_OMIT_CTE - || pWalker->xSelectCallback2==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, 0); - return rc; - } - } -#endif - return WRC_Continue; -} - -/* -** Walk the parse trees associated with all subqueries in the -** FROM clause of SELECT statement p. Do not invoke the select -** callback on p, but do invoke it on each FROM clause subquery -** and on any subqueries further down in the tree. Return -** WRC_Abort or WRC_Continue; -*/ -SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ - SrcList *pSrc; - int i; - SrcItem *pItem; - - pSrc = p->pSrc; - if( ALWAYS(pSrc) ){ - for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( pItem->fg.isSubquery - && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect) - ){ - return WRC_Abort; - } - if( pItem->fg.isTabFunc - && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } - } - } - return WRC_Continue; -} - -/* -** Call sqlite3WalkExpr() for every expression in Select statement p. -** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and -** on the compound select chain, p->pPrior. -** -** If it is not NULL, the xSelectCallback() callback is invoked before -** the walk of the expressions and FROM clause. The xSelectCallback2() -** method is invoked following the walk of the expressions and FROM clause, -** but only if both xSelectCallback and xSelectCallback2 are both non-NULL -** and if the expressions and FROM clause both return WRC_Continue; -** -** Return WRC_Continue under normal conditions. Return WRC_Abort if -** there is an abort request. -** -** If the Walker does not have an xSelectCallback() then this routine -** is a no-op returning WRC_Continue. -*/ -SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ - int rc; - if( p==0 ) return WRC_Continue; - if( pWalker->xSelectCallback==0 ) return WRC_Continue; - do{ - rc = pWalker->xSelectCallback(pWalker, p); - if( rc ) return rc & WRC_Abort; - if( sqlite3WalkSelectExpr(pWalker, p) - || sqlite3WalkSelectFrom(pWalker, p) - ){ - return WRC_Abort; - } - if( pWalker->xSelectCallback2 ){ - pWalker->xSelectCallback2(pWalker, p); - } - p = p->pPrior; - }while( p!=0 ); - return WRC_Continue; -} - -/* Increase the walkerDepth when entering a subquery, and -** decrease when leaving the subquery. -*/ -SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pSelect); - pWalker->walkerDepth++; - return WRC_Continue; -} -SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pSelect); - pWalker->walkerDepth--; -} - - -/* -** No-op routine for the parse-tree walker. -** -** When this routine is the Walker.xExprCallback then expression trees -** are walked without any actions being taken at each node. Presumably, -** when this routine is used for Walker.xExprCallback then -** Walker.xSelectCallback is set to do something useful for every -** subquery in the parser tree. -*/ -SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return WRC_Continue; -} - -/* -** No-op routine for the parse-tree walker for SELECT statements. -** subquery in the parser tree. -*/ -SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return WRC_Continue; -} - -/************** End of walker.c **********************************************/ -/************** Begin file resolve.c *****************************************/ -/* -** 2008 August 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains routines used for walking the parser tree and -** resolve all identifiers by associating them with a particular -** table and column. -*/ -/* #include "sqliteInt.h" */ - -/* -** Magic table number to mean the EXCLUDED table in an UPSERT statement. -*/ -#define EXCLUDED_TABLE_NUMBER 2 - -/* -** Walk the expression tree pExpr and increase the aggregate function -** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. -** This needs to occur when copying a TK_AGG_FUNCTION node from an -** outer query into an inner subquery. -** -** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..) -** is a helper function - a callback for the tree walker. -** -** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c -*/ -static int incrAggDepth(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n; - return WRC_Continue; -} -static void incrAggFunctionDepth(Expr *pExpr, int N){ - if( N>0 ){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = incrAggDepth; - w.u.n = N; - sqlite3WalkExpr(&w, pExpr); - } -} - -/* -** Turn the pExpr expression into an alias for the iCol-th column of the -** result set in pEList. -** -** If the reference is followed by a COLLATE operator, then make sure -** the COLLATE operator is preserved. For example: -** -** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; -** -** Should be transformed into: -** -** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; -** -** The nSubquery parameter specifies how many levels of subquery the -** alias is removed from the original expression. The usual value is -** zero but it might be more if the alias is contained within a subquery -** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION -** structures must be increased by the nSubquery amount. -*/ -static void resolveAlias( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* A result set */ - int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ - Expr *pExpr, /* Transform this into an alias to the result set */ - int nSubquery /* Number of subqueries that the label is moving */ -){ - Expr *pOrig; /* The iCol-th column of the result set */ - Expr *pDup; /* Copy of pOrig */ - sqlite3 *db; /* The database connection */ - - assert( iCol>=0 && iColnExpr ); - pOrig = pEList->a[iCol].pExpr; - assert( pOrig!=0 ); - assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ); - if( pExpr->pAggInfo ) return; - db = pParse->db; - pDup = sqlite3ExprDup(db, pOrig, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - pDup = 0; - }else{ - Expr temp; - incrAggFunctionDepth(pDup, nSubquery); - if( pExpr->op==TK_COLLATE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); - } - memcpy(&temp, pDup, sizeof(Expr)); - memcpy(pDup, pExpr, sizeof(Expr)); - memcpy(pExpr, &temp, sizeof(Expr)); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - if( ALWAYS(pExpr->y.pWin!=0) ){ - pExpr->y.pWin->pOwner = pExpr; - } - } - sqlite3ExprDeferredDelete(pParse, pDup); - } -} - -/* -** Subqueries store the original database, table and column names for their -** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN", -** and mark the expression-list item by setting ExprList.a[].fg.eEName -** to ENAME_TAB. -** -** Check to see if the zSpan/eEName of the expression-list item passed to this -** routine matches the zDb, zTab, and zCol. If any of zDb, zTab, and zCol are -** NULL then those fields will match anything. Return true if there is a match, -** or false otherwise. -** -** SF_NestedFrom subqueries also store an entry for the implicit rowid (or -** _rowid_, or oid) column by setting ExprList.a[].fg.eEName to ENAME_ROWID, -** and setting zSpan to "DATABASE.TABLE.". This type of pItem -** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid) -** is set to 1 if there is this kind of match. -*/ -SQLITE_PRIVATE int sqlite3MatchEName( - const struct ExprList_item *pItem, - const char *zCol, - const char *zTab, - const char *zDb, - int *pbRowid -){ - int n; - const char *zSpan; - int eEName = pItem->fg.eEName; - if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || NEVER(pbRowid==0)) ){ - return 0; - } - assert( pbRowid==0 || *pbRowid==0 ); - zSpan = pItem->zEName; - for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} - if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ - return 0; - } - zSpan += n+1; - for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} - if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){ - return 0; - } - zSpan += n+1; - if( zCol ){ - if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0; - if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0; - } - if( eEName==ENAME_ROWID ) *pbRowid = 1; - return 1; -} - -/* -** Return TRUE if the double-quoted string mis-feature should be supported. -*/ -static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){ - if( db->init.busy ) return 1; /* Always support for legacy schemas */ - if( pTopNC->ncFlags & NC_IsDDL ){ - /* Currently parsing a DDL statement */ - if( sqlite3WritableSchema(db) && (db->flags & SQLITE_DqsDML)!=0 ){ - return 1; - } - return (db->flags & SQLITE_DqsDDL)!=0; - }else{ - /* Currently parsing a DML statement */ - return (db->flags & SQLITE_DqsDML)!=0; - } -} - -/* -** The argument is guaranteed to be a non-NULL Expr node of type TK_COLUMN. -** return the appropriate colUsed mask. -*/ -SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){ - int n; - Table *pExTab; - - n = pExpr->iColumn; - assert( ExprUseYTab(pExpr) ); - pExTab = pExpr->y.pTab; - assert( pExTab!=0 ); - assert( n < pExTab->nCol ); - if( (pExTab->tabFlags & TF_HasGenerated)!=0 - && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 - ){ - testcase( pExTab->nCol==BMS-1 ); - testcase( pExTab->nCol==BMS ); - return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1; - }else{ - testcase( n==BMS-1 ); - testcase( n==BMS ); - if( n>=BMS ) n = BMS-1; - return ((Bitmask)1)<db, TK_COLUMN, 0, 0); - if( pNew ){ - pNew->iTable = pMatch->iCursor; - pNew->iColumn = iColumn; - pNew->y.pTab = pMatch->pSTab; - assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ); - ExprSetProperty(pNew, EP_CanBeNull); - *ppList = sqlite3ExprListAppend(pParse, *ppList, pNew); - } -} - -/* -** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab. -*/ -static SQLITE_NOINLINE int isValidSchemaTableName( - const char *zTab, /* Name as it appears in the SQL */ - Table *pTab, /* The schema table we are trying to match */ - const char *zDb /* non-NULL if a database qualifier is present */ -){ - const char *zLegacy; - assert( pTab!=0 ); - assert( pTab->tnum==1 ); - if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0; - zLegacy = pTab->zName; - if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){ - if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){ - return 1; - } - if( zDb==0 ) return 0; - if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1; - if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1; - }else{ - if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1; - } - return 0; -} - -/* -** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up -** that name in the set of source tables in pSrcList and make the pExpr -** expression node refer back to that source column. The following changes -** are made to pExpr: -** -** pExpr->iDb Set the index in db->aDb[] of the database X -** (even if X is implied). -** pExpr->iTable Set to the cursor number for the table obtained -** from pSrcList. -** pExpr->y.pTab Points to the Table structure of X.Y (even if -** X and/or Y are implied.) -** pExpr->iColumn Set to the column number within the table. -** pExpr->op Set to TK_COLUMN. -** pExpr->pLeft Any expression this points to is deleted -** pExpr->pRight Any expression this points to is deleted. -** -** The zDb variable is the name of the database (the "X"). This value may be -** NULL meaning that name is of the form Y.Z or Z. Any available database -** can be used. The zTable variable is the name of the table (the "Y"). This -** value can be NULL if zDb is also NULL. If zTable is NULL it -** means that the form of the name is Z and that columns from any table -** can be used. -** -** If the name cannot be resolved unambiguously, leave an error message -** in pParse and return WRC_Abort. Return WRC_Prune on success. -*/ -static int lookupName( - Parse *pParse, /* The parsing context */ - const char *zDb, /* Name of the database containing table, or NULL */ - const char *zTab, /* Name of table containing column, or NULL */ - const Expr *pRight, /* Name of the column. */ - NameContext *pNC, /* The name context used to resolve the name */ - Expr *pExpr /* Make this EXPR node point to the selected column */ -){ - int i, j; /* Loop counters */ - int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of potential "rowid" matches */ - int nSubquery = 0; /* How many levels of subquery */ - sqlite3 *db = pParse->db; /* The database connection */ - 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 holding the row */ - ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ - const char *zCol = pRight->u.zToken; - - 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 */ - pExpr->iTable = -1; - ExprSetVVAProperty(pExpr, EP_NoReduce); - - /* Translate the schema name in zDb into a pointer to the corresponding - ** schema. If not found, pSchema will remain NULL and nothing will match - ** resulting in an appropriate error message toward the end of this routine - */ - if( zDb ){ - testcase( pNC->ncFlags & NC_PartIdx ); - testcase( pNC->ncFlags & NC_IsCheck ); - if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ - /* Silently ignore database qualifiers inside CHECK constraints and - ** partial indices. Do not raise errors because that might break - ** legacy and because it does not hurt anything to just ignore the - ** database name. */ - zDb = 0; - }else{ - for(i=0; inDb; i++){ - assert( db->aDb[i].zDbSName ); - if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ - pSchema = db->aDb[i].pSchema; - break; - } - } - if( i==db->nDb && sqlite3StrICmp("main", zDb)==0 ){ - /* This branch is taken when the main database has been renamed - ** using SQLITE_DBCONFIG_MAINDBNAME. */ - pSchema = db->aDb[0].pSchema; - zDb = db->aDb[0].zDbSName; - } - } - } - - /* Start at the inner-most context and move outward until a match is found */ - assert( pNC && cnt==0 ); - do{ - ExprList *pEList; - SrcList *pSrcList = pNC->pSrcList; - - if( pSrcList ){ - for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ - pTab = pItem->pSTab; - assert( pTab!=0 && pTab->zName!=0 ); - assert( pTab->nCol>0 || pParse->nErr ); - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem)); - 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; - Select *pSel; - assert( pItem->fg.isSubquery ); - assert( pItem->u4.pSubq!=0 ); - pSel = pItem->u4.pSubq->pSelect; - assert( pSel!=0 ); - pEList = pSel->pEList; - assert( pEList!=0 ); - assert( pEList->nExpr==pTab->nCol ); - for(j=0; jnExpr; j++){ - int bRowid = 0; /* True if possible rowid match */ - if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){ - continue; - } - if( bRowid==0 ){ - if( cnt>0 ){ - if( pItem->fg.isUsing==0 - || 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. */ - 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; - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else{ - /* For a FULL JOIN, we must construct a coalesce() func */ - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); - } - } - cnt++; - hit = 1; - }else if( cnt>0 ){ - /* This is a potential rowid match, but there has already been - ** a real match found. So this can be ignored. */ - continue; - } - cntTab++; - pMatch = pItem; - pExpr->iColumn = j; - pEList->a[j].fg.bUsed = 1; - - /* rowid cannot be part of a USING clause - assert() this. */ - assert( bRowid==0 || pEList->a[j].fg.bUsingTerm==0 ); - if( pEList->a[j].fg.bUsingTerm ) break; - } - if( hit || zTab==0 ) continue; - } - assert( zDb==0 || zTab!=0 ); - if( zTab ){ - if( zDb ){ - if( pTab->pSchema!=pSchema ) continue; - if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue; - } - if( pItem->zAlias!=0 ){ - if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){ - continue; - } - }else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){ - if( pTab->tnum!=1 ) continue; - if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue; - } - assert( ExprUseYTab(pExpr) ); - if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); - } - } - j = sqlite3ColumnIndex(pTab, zCol); - if( j>=0 ){ - if( cnt>0 ){ - if( pItem->fg.isUsing==0 - || 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. */ - 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; - 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 ){ - sqlite3SrcItemColumnUsed(pItem, j); - } - } - if( 0==cnt && VisibleRowid(pTab) ){ - /* pTab is a potential ROWID match. Keep track of it and match - ** the ROWID later if that seems appropriate. (Search for "cntTab" - ** to find related code.) Only allow a ROWID match if there is - ** a single ROWID match candidate. - */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match - ** if there is a single VIEW candidate or if there is a single - ** non-VIEW candidate plus multiple VIEW candidates. In other - ** words non-VIEW candidate terms take precedence over VIEWs. - */ - if( cntTab==0 - || (cntTab==1 - && pMatch!=0 - && ALWAYS(pMatch->pSTab!=0) - && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0 - && (pTab->tabFlags & TF_Ephemeral)==0) - ){ - cntTab = 1; - pMatch = pItem; - }else{ - cntTab++; - } -#else - /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is - ** simpler since we require exactly one candidate, which will - ** always be a non-VIEW - */ - cntTab++; - pMatch = pItem; -#endif - } - } - if( pMatch ){ - pExpr->iTable = pMatch->iCursor; - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pMatch->pSTab; - if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){ - ExprSetProperty(pExpr, EP_CanBeNull); - } - pSchema = pExpr->y.pTab->pSchema; - } - } /* if( pSrcList ) */ - -#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. Or maybe it is - ** a reference in the RETURNING clause to a table being modified. - */ - 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( pParse->bReturning ){ - if( (pNC->ncFlags & NC_UBaseReg)!=0 - && ALWAYS(zTab==0 - || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0 - || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0)) - ){ - pExpr->iTable = op!=TK_DELETE; - pTab = pParse->pTriggerTab; - } - }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){ - pExpr->iTable = 1; - pTab = pParse->pTriggerTab; - }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){ - pExpr->iTable = 0; - pTab = pParse->pTriggerTab; - } - } -#endif /* SQLITE_OMIT_TRIGGER */ -#ifndef SQLITE_OMIT_UPSERT - if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){ - Upsert *pUpsert = pNC->uNC.pUpsert; - if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){ - pTab = pUpsert->pUpsertSrc->a[0].pSTab; - pExpr->iTable = EXCLUDED_TABLE_NUMBER; - } - } -#endif /* SQLITE_OMIT_UPSERT */ - - if( pTab ){ - int iCol; - pSchema = pTab->pSchema; - cntTab++; - iCol = sqlite3ColumnIndex(pTab, zCol); - if( iCol>=0 ){ - if( pTab->iPKey==iCol ) iCol = -1; - }else{ - if( sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ - iCol = -1; - }else{ - iCol = pTab->nCol; - } - } - if( iColnCol ){ - 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; - eNewExprOp = TK_COLUMN; - }else{ - pExpr->iTable = pNC->uNC.pUpsert->regData + - sqlite3TableColumnToStorage(pTab, iCol); - eNewExprOp = TK_REGISTER; - } - }else -#endif /* SQLITE_OMIT_UPSERT */ - { - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pTab; - if( pParse->bReturning ){ - eNewExprOp = TK_REGISTER; - pExpr->op2 = TK_COLUMN; - pExpr->iColumn = iCol; - pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable + - 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)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<=1 - && pMatch - && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 - && sqlite3IsRowid(zCol) - && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom) - ){ - cnt = cntTab; -#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2 - if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){ - eNewExprOp = TK_NULL; - } -#endif - if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; - pExpr->affExpr = SQLITE_AFF_INTEGER; - } - - /* - ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z - ** might refer to an result-set alias. This happens, for example, when - ** we are resolving names in the WHERE clause of the following command: - ** - ** SELECT a+b AS x FROM table WHERE x<10; - ** - ** In cases like this, replace pExpr with a copy of the expression that - ** forms the result set entry ("a+b" in the example) and return immediately. - ** Note that the expression in the result set should have already been - ** resolved by the time the WHERE clause is resolved. - ** - ** The ability to use an output result-set column in the WHERE, GROUP BY, - ** or HAVING clauses, or as part of a larger expression in the ORDER BY - ** clause is not standard SQL. This is a (goofy) SQLite extension, that - ** is supported for backwards compatibility only. Hence, we issue a warning - ** on sqlite3_log() whenever the capability is used. - */ - if( cnt==0 - && (pNC->ncFlags & NC_UEList)!=0 - && zTab==0 - ){ - pEList = pNC->uNC.pEList; - assert( pEList!=0 ); - for(j=0; jnExpr; j++){ - char *zAs = pEList->a[j].zEName; - if( pEList->a[j].fg.eEName==ENAME_NAME - && sqlite3_stricmp(zAs, zCol)==0 - ){ - Expr *pOrig; - assert( pExpr->pLeft==0 && pExpr->pRight==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) ){ - sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); - return WRC_Abort; - } - if( ExprHasProperty(pOrig, EP_Win) - && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC ) - ){ - sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs); - return WRC_Abort; - } - if( sqlite3ExprVectorSize(pOrig)!=1 ){ - sqlite3ErrorMsg(pParse, "row value misused"); - return WRC_Abort; - } - resolveAlias(pParse, pEList, j, pExpr, nSubquery); - cnt = 1; - pMatch = 0; - assert( zTab==0 && zDb==0 ); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); - } - goto lookupname_end; - } - } - } - - /* Advance to the next name context. The loop will exit when either - ** we have a match (cnt>0) or when we run out of name contexts. - */ - if( cnt ) break; - pNC = pNC->pNext; - nSubquery++; - }while( pNC ); - - - /* - ** If X and Y are NULL (in other words if only the column name Z is - ** supplied) and the value of Z is enclosed in double-quotes, then - ** Z is a string literal if it doesn't match any column names. In that - ** case, we need to return right away and not make any changes to - ** pExpr. - ** - ** Because no reference was made to outer contexts, the pNC->nRef - ** fields are not changed in any context. - */ - if( cnt==0 && zTab==0 ){ - assert( pExpr->op==TK_ID ); - if( ExprHasProperty(pExpr,EP_DblQuoted) - && areDoubleQuotedStringsEnabled(db, pTopNC) - ){ - /* If a double-quoted identifier does not match any known column name, - ** then treat it as a string. - ** - ** This hack was added in the early days of SQLite in a misguided attempt - ** to be compatible with MySQL 3.x, which used double-quotes for strings. - ** I now sorely regret putting in this hack. The effect of this hack is - ** that misspelled identifier names are silently converted into strings - ** rather than causing an error, to the frustration of countless - ** programmers. To all those frustrated programmers, my apologies. - ** - ** Someday, I hope to get rid of this hack. Unfortunately there is - ** a huge amount of legacy SQL that uses it. So for now, we just - ** issue a warning. - */ - sqlite3_log(SQLITE_WARNING, - "double-quoted string literal: \"%w\"", zCol); -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol); -#endif - pExpr->op = TK_STRING; - memset(&pExpr->y, 0, sizeof(pExpr->y)); - return WRC_Prune; - } - if( sqlite3ExprIdToTrueFalse(pExpr) ){ - return WRC_Prune; - } - } - - /* - ** 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{ - sqlite3ExprDelete(db, pExpr->pLeft); - pExpr->pLeft = 0; - 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{ - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - } - } - zErr = cnt==0 ? "no such column" : "ambiguous column name"; - if( zDb ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); - }else if( zTab ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); - }else if( cnt==0 && ExprHasProperty(pRight,EP_DblQuoted) ){ - sqlite3ErrorMsg(pParse, "%s: \"%s\" - should this be a" - " string literal in single-quotes?", - zErr, zCol); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); - } - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); - pParse->checkSchema = 1; - pTopNC->nNcErr++; - eNewExprOp = TK_NULL; - } - assert( pFJMatch==0 ); - - /* Remove all substructure from pExpr */ - if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - sqlite3ExprDelete(db, pExpr->pLeft); - pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; - ExprSetProperty(pExpr, EP_Leaf); - } - - /* If a column from a table in pSrcList is referenced, then record - ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes - ** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is - ** set if the 63rd or any subsequent column is used. - ** - ** The colUsed mask is an optimization used to help determine if an - ** index is a covering index. The correct answer is still obtained - ** if the mask contains extra set bits. However, it is important to - ** avoid setting bits beyond the maximum column number of the table. - ** (See ticket [b92e5e8ec2cdbaa1]). - ** - ** If a generated column is referenced, set bits for every column - ** of the table. - */ - if( pMatch ){ - if( pExpr->iColumn>=0 ){ - pMatch->colUsed |= sqlite3ExprColUsed(pExpr); - }else{ - pMatch->fg.rowidUsed = 1; - } - } - - pExpr->op = eNewExprOp; -lookupname_end: - if( cnt==1 ){ - assert( pNC!=0 ); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pParse->db->xAuth - && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) - ){ - 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(;;){ - assert( pTopNC!=0 ); - pTopNC->nRef++; - if( pTopNC==pNC ) break; - pTopNC = pTopNC->pNext; - } - return WRC_Prune; - } else { - return WRC_Abort; - } -} - -/* -** Allocate and return a pointer to an expression to load the column iCol -** from datasource iSrc in SrcList pSrc. -*/ -SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ - Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); - if( p ){ - SrcItem *pItem = &pSrc->a[iSrc]; - Table *pTab; - assert( ExprUseYTab(p) ); - pTab = p->y.pTab = pItem->pSTab; - p->iTable = pItem->iCursor; - if( p->y.pTab->iPKey==iCol ){ - p->iColumn = -1; - }else{ - p->iColumn = (ynVar)iCol; - if( (pTab->tabFlags & TF_HasGenerated)!=0 - && (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0 - ){ - testcase( pTab->nCol==63 ); - testcase( pTab->nCol==64 ); - pItem->colUsed = pTab->nCol>=64 ? ALLBITS : MASKBIT(pTab->nCol)-1; - }else{ - testcase( iCol==BMS ); - testcase( iCol==BMS-1 ); - pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); - } - } - } - return p; -} - -/* -** Report an error that an expression is not valid for some set of -** pNC->ncFlags values determined by validMask. -** -** static void notValid( -** Parse *pParse, // Leave error message here -** NameContext *pNC, // The name context -** const char *zMsg, // Type of error -** int validMask, // Set of contexts for which prohibited -** Expr *pExpr // Invalidate this expression on error -** ){...} -** -** As an optimization, since the conditional is almost always false -** (because errors are rare), the conditional is moved outside of the -** function call using a macro. -*/ -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 *pError /* Associate error with this expression */ -){ - const char *zIn = "partial index WHERE clauses"; - if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; -#ifndef SQLITE_OMIT_CHECK - else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints"; -#endif -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns"; -#endif - sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); - if( pExpr ) pExpr->op = TK_NULL; - sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); -} -#define 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,R); - -/* -** Expression p should encode a floating point value between 1.0 and 0.0. -** Return 1024 times this value. Or return -1 if p is not a floating point -** value between 1.0 and 0.0. -*/ -static int exprProbability(Expr *p){ - double r = -1.0; - if( p->op!=TK_FLOAT ) return -1; - assert( !ExprHasProperty(p, EP_IntValue) ); - sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); - assert( r>=0.0 ); - if( r>1.0 ) return -1; - return (int)(r*134217728.0); -} - -/* -** This routine is callback for sqlite3WalkExpr(). -** -** Resolve symbolic names into TK_COLUMN operators for the current -** node in the expression tree. Return 0 to continue the search down -** the tree or 2 to abort the tree walk. -** -** This routine also does error checking and name resolution for -** function names. The operator for aggregate functions is changed -** to TK_AGG_FUNCTION. -*/ -static int resolveExprStep(Walker *pWalker, Expr *pExpr){ - NameContext *pNC; - Parse *pParse; - - pNC = pWalker->u.pNC; - assert( pNC!=0 ); - pParse = pNC->pParse; - assert( pParse==pWalker->pParse ); - -#ifndef NDEBUG - if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ - SrcList *pSrcList = pNC->pSrcList; - int i; - for(i=0; ipSrcList->nSrc; i++){ - assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); - } - } -#endif - switch( pExpr->op ){ - - /* The special operator TK_ROW means use the rowid for the first - ** column in the FROM clause. This is used by the LIMIT and ORDER BY - ** clause processing on UPDATE and DELETE statements, and by - ** UPDATE ... FROM statement processing. - */ - case TK_ROW: { - SrcList *pSrcList = pNC->pSrcList; - SrcItem *pItem; - assert( pSrcList && pSrcList->nSrc>=1 ); - pItem = pSrcList->a; - pExpr->op = TK_COLUMN; - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pItem->pSTab; - pExpr->iTable = pItem->iCursor; - pExpr->iColumn--; - pExpr->affExpr = SQLITE_AFF_INTEGER; - 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. - ** - ** 2024-03-28: Beware of aggregates. A bare column of aggregated table - ** can still evaluate to NULL even though it is marked as NOT NULL. - ** Example: - ** - ** CREATE TABLE t1(a INT NOT NULL); - ** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1; - ** - ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized - ** here because at the time this case is hit, we do not yet know whether - ** or not t1 is being aggregated. We have to assume the worst and omit - ** the optimization. The only time it is safe to apply this optimization - ** is within the WHERE clause. - */ - case TK_NOTNULL: - case TK_ISNULL: { - int anRef[8]; - NameContext *p; - int i; - for(i=0, p=pNC; p && ipNext, i++){ - anRef[i] = p->nRef; - } - sqlite3WalkExpr(pWalker, pExpr->pLeft); - if( IN_RENAME_OBJECT ) return WRC_Prune; - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ - /* The expression can be NULL. So the optimization does not apply */ - return WRC_Prune; - } - - for(i=0, p=pNC; p; p=p->pNext, i++){ - if( (p->ncFlags & NC_Where)==0 ){ - return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */ - } - } - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x80000 ){ - sqlite3DebugPrintf( - "NOT NULL strength reduction converts the following to %d:\n", - pExpr->op==TK_NOTNULL - ); - sqlite3ShowExpr(pExpr); - } -#endif /* TREETRACE_ENABLED */ - pExpr->u.iValue = (pExpr->op==TK_NOTNULL); - pExpr->flags |= EP_IntValue; - pExpr->op = TK_INTEGER; - for(i=0, p=pNC; p && ipNext, i++){ - p->nRef = anRef[i]; - } - 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 - ** - ** The TK_ID and TK_OUT cases are combined so that there will only - ** be one call to lookupName(). Then the compiler will in-line - ** lookupName() for a size reduction and performance increase. - */ - case TK_ID: - case TK_DOT: { - const char *zTable; - const char *zDb; - Expr *pRight; - - if( pExpr->op==TK_ID ){ - zDb = 0; - zTable = 0; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pRight = pExpr; - }else{ - Expr *pLeft = pExpr->pLeft; - testcase( pNC->ncFlags & NC_IdxExpr ); - testcase( pNC->ncFlags & NC_GenCol ); - sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator", - 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; - assert( ExprUseYTab(pExpr) ); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); - } - } - return lookupName(pParse, zDb, zTable, pRight, pNC, pExpr); - } - - /* Resolve function names - */ - case TK_FUNCTION: { - ExprList *pList; /* The argument list */ - int n; /* Number of arguments */ - int no_such_func = 0; /* True if no such function exists */ - int wrong_num_args = 0; /* True if wrong number of arguments */ - int is_agg = 0; /* True if is an aggregate function */ - const char *zId; /* The function name. */ - FuncDef *pDef; /* Information about the function */ - u8 enc = ENC(pParse->db); /* The database encoding */ - int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin)); -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0); -#endif - assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); - assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER ); - pList = pExpr->x.pList; - n = pList ? pList->nExpr : 0; - zId = pExpr->u.zToken; - pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); - if( pDef==0 ){ - pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); - if( pDef==0 ){ - no_such_func = 1; - }else{ - wrong_num_args = 1; - } - }else{ - is_agg = pDef->xFinalize!=0; - if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ - ExprSetProperty(pExpr, EP_Unlikely); - if( n==2 ){ - pExpr->iTable = exprProbability(pList->a[1].pExpr); - if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, - "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 - ** equivalent to likelihood(X, 0.0625). - ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is - ** short-hand for likelihood(X,0.0625). - ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand - ** for likelihood(X,0.9375). - ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent - ** to likelihood(X,0.9375). */ - /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ - pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; - } - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); - if( auth!=SQLITE_OK ){ - if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %#T", - pExpr); - pNC->nNcErr++; - } - pExpr->op = TK_NULL; - return WRC_Prune; - } - } -#endif - - /* If the function may call sqlite3_value_subtype(), then set the - ** EP_SubtArg flag on all of its argument expressions. This prevents - ** where.c from replacing the expression with a value read from an - ** index on the same expression, which will not have the correct - ** subtype. Also set the flag if the function expression itself is - ** an EP_SubtArg expression. In this case subtypes are required as - ** the function may return a value with a subtype back to its - ** caller using sqlite3_result_value(). */ - if( (pDef->funcFlags & SQLITE_SUBTYPE) - || ExprHasProperty(pExpr, EP_SubtArg) - ){ - int ii; - for(ii=0; iia[ii].pExpr, EP_SubtArg); - } - } - - if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){ - /* For the purposes of the EP_ConstFunc flag, date and time - ** functions and other functions that change slowly are considered - ** constant because they are constant for the duration of one query. - ** This allows them to be factored out of inner loops. */ - ExprSetProperty(pExpr,EP_ConstFunc); - } - if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ - /* Clearly non-deterministic functions like random(), but also - ** date/time functions that use 'now', and other functions like - ** sqlite_version() that might change over time cannot be used - ** in an index or generated column. Curiously, they can be used - ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all - ** allow this. */ - sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions", - 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; - } - if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 - && pParse->nested==0 - && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 - ){ - /* Internal-use-only functions are disallowed unless the - ** SQL is being compiled using sqlite3NestedParse() or - ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be - ** used to activate internal functions for testing purposes */ - no_such_func = 1; - pDef = 0; - }else - if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 - && !IN_RENAME_OBJECT - ){ - if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL); - sqlite3ExprFunctionUsable(pParse, pExpr, pDef); - } - } - - if( 0==IN_RENAME_OBJECT ){ -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) - || (pDef->xValue==0 && pDef->xInverse==0) - || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) - ); - if( pDef && pDef->xValue==0 && pWin ){ - sqlite3ErrorMsg(pParse, - "%#T() may not be used as a window function", pExpr - ); - pNC->nNcErr++; - }else if( - (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin) - || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0) - ){ - const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){ - zType = "window"; - }else{ - zType = "aggregate"; - } - sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr); - pNC->nNcErr++; - is_agg = 0; - } -#else - if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ - sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr); - pNC->nNcErr++; - is_agg = 0; - } -#endif - else if( no_such_func && pParse->db->init.busy==0 -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - && pParse->explain==0 -#endif - ){ - sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr); - pNC->nNcErr++; - }else if( wrong_num_args ){ - 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) ){ - sqlite3ErrorMsg(pParse, - "FILTER may not be used with non-aggregate %#T()", - pExpr - ); - pNC->nNcErr++; - } -#endif - else if( is_agg==0 && pExpr->pLeft ){ - sqlite3ExprOrderByAggregateError(pParse, pExpr); - pNC->nNcErr++; - } - if( is_agg ){ - /* Window functions may not be arguments of aggregate functions. - ** Or arguments of other window functions. But aggregate functions - ** may be arguments for window functions. */ -#ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0)); -#else - pNC->ncFlags &= ~NC_AllowAgg; -#endif - } - } - else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){ - is_agg = 1; - } - sqlite3WalkExprList(pWalker, pList); - if( is_agg ){ - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin && pParse->nErr==0 ){ - Select *pSel = pNC->pWinSelect; - assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin ); - if( IN_RENAME_OBJECT==0 ){ - sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef); - if( pParse->db->mallocFailed ) break; - } - sqlite3WalkExprList(pWalker, pWin->pPartition); - sqlite3WalkExprList(pWalker, pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pWin->pFilter); - sqlite3WindowLink(pSel, pWin); - pNC->ncFlags |= NC_HasWin; - }else -#endif /* SQLITE_OMIT_WINDOWFUNC */ - { - NameContext *pNC2; /* For looping up thru outer contexts */ - pExpr->op = TK_AGG_FUNCTION; - pExpr->op2 = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); - } -#endif - pNC2 = pNC; - while( pNC2 - && sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0 - ){ - pExpr->op2 += (1 + pNC2->nNestedSelect); - pNC2 = pNC2->pNext; - } - assert( pDef!=0 || IN_RENAME_OBJECT ); - if( pNC2 && pDef ){ - pExpr->op2 += pNC2->nNestedSelect; - assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); - assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg ); - testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); - 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; - } - /* FIX ME: Compute pExpr->affinity based on the expected return - ** type of the function - */ - return WRC_Prune; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_SELECT: - case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); -#endif - case TK_IN: { - testcase( pExpr->op==TK_IN ); - 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 ); - assert( pExpr->x.pSelect ); - if( pNC->ncFlags & NC_SelfRef ){ - notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); - }else{ - sqlite3WalkSelect(pWalker, pExpr->x.pSelect); - } - assert( pNC->nRef>=nRef ); - if( nRef!=pNC->nRef ){ - ExprSetProperty(pExpr, EP_VarSelect); - pExpr->x.pSelect->selFlags |= SF_Correlated; - } - pNC->ncFlags |= NC_Subquery; - } - break; - } - case TK_VARIABLE: { - testcase( pNC->ncFlags & NC_IsCheck ); - testcase( pNC->ncFlags & NC_PartIdx ); - testcase( pNC->ncFlags & NC_IdxExpr ); - testcase( pNC->ncFlags & NC_GenCol ); - sqlite3ResolveNotValid(pParse, pNC, "parameters", - NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr); - break; - } - case TK_IS: - case TK_ISNOT: { - Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight); - 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( 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 ){ - pExpr->op2 = pExpr->op; - pExpr->op = TK_TRUTH; - return WRC_Continue; - } - } - /* no break */ deliberate_fall_through - } - case TK_BETWEEN: - case TK_EQ: - case TK_NE: - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: { - int nLeft, nRight; - if( pParse->db->mallocFailed ) break; - assert( pExpr->pLeft!=0 ); - nLeft = sqlite3ExprVectorSize(pExpr->pLeft); - if( pExpr->op==TK_BETWEEN ){ - assert( ExprUseXList(pExpr) ); - nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); - if( nRight==nLeft ){ - nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); - } - }else{ - assert( pExpr->pRight!=0 ); - nRight = sqlite3ExprVectorSize(pExpr->pRight); - } - if( nLeft!=nRight ){ - testcase( pExpr->op==TK_EQ ); - testcase( pExpr->op==TK_NE ); - testcase( pExpr->op==TK_LT ); - testcase( pExpr->op==TK_LE ); - testcase( pExpr->op==TK_GT ); - testcase( pExpr->op==TK_GE ); - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_BETWEEN ); - sqlite3ErrorMsg(pParse, "row value misused"); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); - } - break; - } - } - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); - return pParse->nErr ? WRC_Abort : WRC_Continue; -} - -/* -** pEList is a list of expressions which are really the result set of the -** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause. -** This routine checks to see if pE is a simple identifier which corresponds -** to the AS-name of one of the terms of the expression list. If it is, -** this routine return an integer between 1 and N where N is the number of -** elements in pEList, corresponding to the matching entry. If there is -** no match, or if pE is not a simple identifier, then this routine -** return 0. -** -** pEList has been resolved. pE has not. -*/ -static int resolveAsName( - Parse *pParse, /* Parsing context for error messages */ - ExprList *pEList, /* List of expressions to scan */ - Expr *pE /* Expression we are trying to match */ -){ - int i; /* Loop counter */ - - UNUSED_PARAMETER(pParse); - - if( pE->op==TK_ID ){ - const char *zCol; - assert( !ExprHasProperty(pE, EP_IntValue) ); - zCol = pE->u.zToken; - for(i=0; inExpr; i++){ - if( pEList->a[i].fg.eEName==ENAME_NAME - && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0 - ){ - return i+1; - } - } - } - return 0; -} - -/* -** pE is a pointer to an expression which is a single term in the -** ORDER BY of a compound SELECT. The expression has not been -** name resolved. -** -** At the point this routine is called, we already know that the -** ORDER BY term is not an integer index into the result set. That -** case is handled by the calling routine. -** -** Attempt to match pE against result set columns in the left-most -** SELECT statement. Return the index i of the matching column, -** as an indication to the caller that it should sort by the i-th column. -** The left-most column is 1. In other words, the value returned is the -** same integer value that would be used in the SQL statement to indicate -** the column. -** -** If there is no match, return 0. Return -1 if an error occurs. -*/ -static int resolveOrderByTermToExprList( - Parse *pParse, /* Parsing context for error messages */ - Select *pSelect, /* The SELECT statement with the ORDER BY clause */ - Expr *pE /* The specific ORDER BY term */ -){ - int i; /* Loop counter */ - ExprList *pEList; /* The columns of the result set */ - NameContext nc; /* Name context for resolving pE */ - sqlite3 *db; /* Database connection */ - int rc; /* Return code from subprocedures */ - u8 savedSuppErr; /* Saved value of db->suppressErr */ - - assert( sqlite3ExprIsInteger(pE, &i, 0)==0 ); - pEList = pSelect->pEList; - - /* Resolve all names in the ORDER BY term expression - */ - memset(&nc, 0, sizeof(nc)); - nc.pParse = pParse; - nc.pSrcList = pSelect->pSrc; - nc.uNC.pEList = pEList; - nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect; - nc.nNcErr = 0; - db = pParse->db; - savedSuppErr = db->suppressErr; - db->suppressErr = 1; - rc = sqlite3ResolveExprNames(&nc, pE); - db->suppressErr = savedSuppErr; - if( rc ) return 0; - - /* Try to match the ORDER BY expression against an expression - ** in the result set. Return an 1-based index of the matching - ** result-set entry. - */ - for(i=0; inExpr; i++){ - if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){ - return i+1; - } - } - - /* If no match, return 0. */ - return 0; -} - -/* -** Generate an ORDER BY or GROUP BY term out-of-range error. -*/ -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 */ - Expr *pError /* Associate the error with the expression */ -){ - sqlite3ErrorMsg(pParse, - "%r %s BY term out of range - should be " - "between 1 and %d", i, zType, mx); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); -} - -/* -** Analyze the ORDER BY clause in a compound SELECT statement. Modify -** each term of the ORDER BY clause is a constant integer between 1 -** and N where N is the number of columns in the compound SELECT. -** -** ORDER BY terms that are already an integer between 1 and N are -** unmodified. ORDER BY terms that are integers outside the range of -** 1 through N generate an error. ORDER BY terms that are expressions -** are matched against result set expressions of compound SELECT -** beginning with the left-most SELECT and working toward the right. -** At the first match, the ORDER BY expression is transformed into -** the integer column number. -** -** Return the number of errors seen. -*/ -static int resolveCompoundOrderBy( - Parse *pParse, /* Parsing context. Leave error messages here */ - Select *pSelect /* The SELECT statement containing the ORDER BY */ -){ - int i; - ExprList *pOrderBy; - ExprList *pEList; - sqlite3 *db; - int moreToDo = 1; - - pOrderBy = pSelect->pOrderBy; - if( pOrderBy==0 ) return 0; - db = pParse->db; - if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); - return 1; - } - for(i=0; inExpr; i++){ - pOrderBy->a[i].fg.done = 0; - } - pSelect->pNext = 0; - while( pSelect->pPrior ){ - pSelect->pPrior->pNext = pSelect; - pSelect = pSelect->pPrior; - } - while( pSelect && moreToDo ){ - struct ExprList_item *pItem; - moreToDo = 0; - pEList = pSelect->pEList; - assert( pEList!=0 ); - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - int iCol = -1; - Expr *pE, *pDup; - if( pItem->fg.done ) continue; - pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); - if( NEVER(pE==0) ) continue; - if( sqlite3ExprIsInteger(pE, &iCol, 0) ){ - if( iCol<=0 || iCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE); - return 1; - } - }else{ - iCol = resolveAsName(pParse, pEList, pE); - if( iCol==0 ){ - /* Now test if expression pE matches one of the values returned - ** by pSelect. In the usual case this is done by duplicating the - ** expression, resolving any symbols in it, and then comparing - ** it against each expression returned by the SELECT statement. - ** Once the comparisons are finished, the duplicate expression - ** is deleted. - ** - ** 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 = sqlite3ExprDup(db, pE, 0); - if( !db->mallocFailed ){ - assert(pDup); - iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); - if( IN_RENAME_OBJECT && iCol>0 ){ - resolveOrderByTermToExprList(pParse, pSelect, pE); - } - } - 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. */ - if( !IN_RENAME_OBJECT ){ - Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); - if( pNew==0 ) return 1; - pNew->flags |= EP_IntValue; - pNew->u.iValue = iCol; - if( pItem->pExpr==pE ){ - pItem->pExpr = pNew; - }else{ - Expr *pParent = pItem->pExpr; - assert( pParent->op==TK_COLLATE ); - while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; - assert( pParent->pLeft==pE ); - pParent->pLeft = pNew; - } - sqlite3ExprDelete(db, pE); - pItem->u.x.iOrderByCol = (u16)iCol; - } - pItem->fg.done = 1; - }else{ - moreToDo = 1; - } - } - pSelect = pSelect->pNext; - } - for(i=0; inExpr; i++){ - if( pOrderBy->a[i].fg.done==0 ){ - sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " - "column in the result set", i+1); - return 1; - } - } - return 0; -} - -/* -** Check every term in the ORDER BY or GROUP BY clause pOrderBy of -** the SELECT statement pSelect. If any term is reference to a -** result set expression (as determined by the ExprList.a.u.x.iOrderByCol -** field) then convert that term into a copy of the corresponding result set -** column. -** -** If any errors are detected, add an error message to pParse and -** return non-zero. Return zero if no errors are seen. -*/ -SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( - Parse *pParse, /* Parsing context. Leave error messages here */ - Select *pSelect, /* The SELECT statement containing the clause */ - ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ - const char *zType /* "ORDER" or "GROUP" */ -){ - int i; - sqlite3 *db = pParse->db; - ExprList *pEList; - struct ExprList_item *pItem; - - if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0; - if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); - return 1; - } - pEList = pSelect->pEList; - assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - if( pItem->u.x.iOrderByCol ){ - if( pItem->u.x.iOrderByCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0); - return 1; - } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0); - } - } - return 0; -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Walker callback for windowRemoveExprFromSelect(). -*/ -static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ - UNUSED_PARAMETER(pWalker); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window *pWin = pExpr->y.pWin; - sqlite3WindowUnlinkFromSelect(pWin); - } - return WRC_Continue; -} - -/* -** Remove any Window objects owned by the expression pExpr from the -** Select.pWin list of Select object pSelect. -*/ -static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){ - if( pSelect->pWin ){ - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.xExprCallback = resolveRemoveWindowsCb; - sWalker.u.pSelect = pSelect; - sqlite3WalkExpr(&sWalker, pExpr); - } -} -#else -# define windowRemoveExprFromSelect(a, b) -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. -** The Name context of the SELECT statement is pNC. zType is either -** "ORDER" or "GROUP" depending on which type of clause pOrderBy is. -** -** This routine resolves each term of the clause into an expression. -** If the order-by term is an integer I between 1 and N (where N is the -** number of columns in the result set of the SELECT) then the expression -** in the resolution is a copy of the I-th result-set expression. If -** the order-by term is an identifier that corresponds to the AS-name of -** a result-set expression, then the term resolves to a copy of the -** result-set expression. Otherwise, the expression is resolved in -** the usual way - using sqlite3ResolveExprNames(). -** -** This routine returns the number of errors. If errors occur, then -** an appropriate error message might be left in pParse. (OOM errors -** excepted.) -*/ -static int resolveOrderGroupBy( - NameContext *pNC, /* The name context of the SELECT statement */ - Select *pSelect, /* The SELECT statement holding pOrderBy */ - ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */ - const char *zType /* Either "ORDER" or "GROUP", as appropriate */ -){ - int i, j; /* Loop counters */ - int iCol; /* Column number */ - struct ExprList_item *pItem; /* A term of the ORDER BY clause */ - Parse *pParse; /* Parsing context */ - int nResult; /* Number of terms in the result set */ - - assert( pOrderBy!=0 ); - nResult = pSelect->pEList->nExpr; - pParse = pNC->pParse; - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - Expr *pE = pItem->pExpr; - Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE); - if( NEVER(pE2==0) ) continue; - if( zType[0]!='G' ){ - iCol = resolveAsName(pParse, pSelect->pEList, pE2); - if( iCol>0 ){ - /* If an AS-name match is found, mark this ORDER BY column as being - ** a copy of the iCol-th result-set column. The subsequent call to - ** sqlite3ResolveOrderGroupBy() will convert the expression to a - ** copy of the iCol-th result-set expression. */ - pItem->u.x.iOrderByCol = (u16)iCol; - continue; - } - } - if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){ - /* The ORDER BY term is an integer constant. Again, set the column - ** number so that sqlite3ResolveOrderGroupBy() will convert the - ** order-by term to a copy of the result-set expression */ - if( iCol<1 || iCol>0xffff ){ - resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2); - return 1; - } - pItem->u.x.iOrderByCol = (u16)iCol; - continue; - } - - /* Otherwise, treat the ORDER BY term as an ordinary expression */ - pItem->u.x.iOrderByCol = 0; - if( sqlite3ResolveExprNames(pNC, pE) ){ - return 1; - } - for(j=0; jpEList->nExpr; j++){ - if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ - /* Since this expression is being changed into a reference - ** to an identical expression in the result set, remove all Window - ** objects belonging to the expression from the Select.pWin list. */ - windowRemoveExprFromSelect(pSelect, pE); - pItem->u.x.iOrderByCol = j+1; - } - } - } - return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); -} - -/* -** Resolve names in the SELECT statement p and all of its descendants. -*/ -static int resolveSelectStep(Walker *pWalker, Select *p){ - NameContext *pOuterNC; /* Context that contains this SELECT */ - NameContext sNC; /* Name context of this SELECT */ - int isCompound; /* True if p is a compound select */ - int nCompound; /* Number of compound terms processed so far */ - Parse *pParse; /* Parsing context */ - int i; /* Loop counter */ - ExprList *pGroupBy; /* The GROUP BY clause */ - Select *pLeftmost; /* Left-most of SELECT of a compound */ - sqlite3 *db; /* Database connection */ - - - assert( p!=0 ); - if( p->selFlags & SF_Resolved ){ - return WRC_Prune; - } - pOuterNC = pWalker->u.pNC; - pParse = pWalker->pParse; - db = pParse->db; - - /* Normally sqlite3SelectExpand() will be called first and will have - ** already expanded this SELECT. However, if this is a subquery within - ** an expression, sqlite3ResolveExprNames() will be called without a - ** prior call to sqlite3SelectExpand(). When that happens, let - ** sqlite3SelectPrep() do all of the processing for this SELECT. - ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and - ** this routine in the correct order. - */ - if( (p->selFlags & SF_Expanded)==0 ){ - sqlite3SelectPrep(pParse, p, pOuterNC); - return pParse->nErr ? WRC_Abort : WRC_Prune; - } - - isCompound = p->pPrior!=0; - nCompound = 0; - pLeftmost = p; - while( p ){ - assert( (p->selFlags & SF_Expanded)!=0 ); - assert( (p->selFlags & SF_Resolved)==0 ); - p->selFlags |= SF_Resolved; - - /* Resolve the expressions in the LIMIT and OFFSET clauses. These - ** are not allowed to refer to any names, so pass an empty NameContext. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pWinSelect = p; - if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ - return WRC_Abort; - } - - /* If the SF_Converted flags is set, then this Select object was - ** was created by the convertCompoundSelectToSubquery() function. - ** In this case the ORDER BY clause (p->pOrderBy) should be resolved - ** as if it were part of the sub-query, not the parent. This block - ** moves the pOrderBy down to the sub-query. It will be moved back - ** after the names have been resolved. */ - if( p->selFlags & SF_Converted ){ - Select *pSub; - assert( p->pSrc->a[0].fg.isSubquery ); - assert( p->pSrc->a[0].u4.pSubq!=0 ); - pSub = p->pSrc->a[0].u4.pSubq->pSelect; - assert( pSub!=0 ); - assert( p->pSrc->nSrc==1 && p->pOrderBy ); - assert( pSub->pPrior && pSub->pOrderBy==0 ); - pSub->pOrderBy = p->pOrderBy; - p->pOrderBy = 0; - } - - /* Recursively resolve names in all subqueries in the FROM clause - */ - if( pOuterNC ) pOuterNC->nNestedSelect++; - for(i=0; ipSrc->nSrc; i++){ - SrcItem *pItem = &p->pSrc->a[i]; - assert( pItem->zName!=0 - || pItem->fg.isSubquery ); /* Test of tag-20240424-1*/ - if( pItem->fg.isSubquery - && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0 - ){ - int nRef = pOuterNC ? pOuterNC->nRef : 0; - const char *zSavedContext = pParse->zAuthContext; - - if( pItem->zName ) pParse->zAuthContext = pItem->zName; - sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC); - pParse->zAuthContext = zSavedContext; - if( pParse->nErr ) return WRC_Abort; - assert( db->mallocFailed==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); - } - } - } - if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){ - pOuterNC->nNestedSelect--; - } - - /* Set up the local name-context to pass to sqlite3ResolveExprNames() to - ** resolve the result-set expression list. - */ - sNC.ncFlags = NC_AllowAgg|NC_AllowWin; - sNC.pSrcList = p->pSrc; - sNC.pNext = pOuterNC; - - /* Resolve names in the result set. */ - if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; - sNC.ncFlags &= ~NC_AllowWin; - - /* If there are no aggregate functions in the result-set, and no GROUP BY - ** expression, do not allow aggregates in any of the other expressions. - */ - assert( (p->selFlags & SF_Aggregate)==0 ); - pGroupBy = p->pGroupBy; - if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ - assert( NC_MinMaxAgg==SF_MinMaxAgg ); - assert( NC_OrderAgg==SF_OrderByReqd ); - p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg)); - }else{ - sNC.ncFlags &= ~NC_AllowAgg; - } - - /* Add the output column list to the name-context before parsing the - ** other expressions in the SELECT statement. This is so that - ** expressions in the WHERE clause (etc.) can refer to expressions by - ** aliases in the result set. - ** - ** 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|NC_UBaseReg))==0 ); - sNC.uNC.pEList = p->pEList; - sNC.ncFlags |= NC_UEList; - if( p->pHaving ){ - if( (p->selFlags & SF_Aggregate)==0 ){ - sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query"); - return WRC_Abort; - } - if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; - } - sNC.ncFlags |= NC_Where; - if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; - sNC.ncFlags &= ~NC_Where; - - /* Resolve names in table-valued-function arguments */ - for(i=0; ipSrc->nSrc; i++){ - SrcItem *pItem = &p->pSrc->a[i]; - if( pItem->fg.isTabFunc - && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( IN_RENAME_OBJECT ){ - Window *pWin; - for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){ - if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy) - || sqlite3ResolveExprListNames(&sNC, pWin->pPartition) - ){ - return WRC_Abort; - } - } - } -#endif - - /* The ORDER BY and GROUP BY clauses may not refer to terms in - ** outer queries - */ - sNC.pNext = 0; - sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; - - /* If this is a converted compound query, move the ORDER BY clause from - ** the sub-query back to the parent query. At this point each term - ** within the ORDER BY clause has been transformed to an integer value. - ** These integers will be replaced by copies of the corresponding result - ** set expressions by the call to resolveOrderGroupBy() below. */ - if( p->selFlags & SF_Converted ){ - Select *pSub; - assert( p->pSrc->a[0].fg.isSubquery ); - pSub = p->pSrc->a[0].u4.pSubq->pSelect; - assert( pSub!=0 ); - p->pOrderBy = pSub->pOrderBy; - pSub->pOrderBy = 0; - } - - /* Process the ORDER BY clause for singleton SELECT statements. - ** The ORDER BY clause for compounds SELECT statements is handled - ** below, after all of the result-sets for all of the elements of - ** the compound have been resolved. - ** - ** If there is an ORDER BY clause on a term of a compound-select other - ** than the right-most term, then that is a syntax error. But the error - ** 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( p->pOrderBy!=0 - && isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ - && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") - ){ - return WRC_Abort; - } - if( db->mallocFailed ){ - return WRC_Abort; - } - sNC.ncFlags &= ~NC_AllowWin; - - /* Resolve the GROUP BY clause. At the same time, make sure - ** the GROUP BY clause does not contain aggregate functions. - */ - if( pGroupBy ){ - struct ExprList_item *pItem; - - if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){ - return WRC_Abort; - } - for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ - if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ - sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " - "the GROUP BY clause"); - return WRC_Abort; - } - } - } - - /* 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 ){ - sqlite3SelectWrongNumTermsError(pParse, p->pNext); - return WRC_Abort; - } - - /* Advance to the next term of the compound - */ - p = p->pPrior; - nCompound++; - } - - /* Resolve the ORDER BY on a compound SELECT after all terms of - ** the compound have been resolved. - */ - if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){ - return WRC_Abort; - } - - return WRC_Prune; -} - -/* -** This routine walks an expression tree and resolves references to -** table columns and result-set columns. At the same time, do error -** checking on function usage and set a flag if any aggregate functions -** are seen. -** -** To resolve table columns references we look for nodes (or subtrees) of the -** form X.Y.Z or Y.Z or just Z where -** -** X: The name of a database. Ex: "main" or "temp" or -** the symbolic name assigned to an ATTACH-ed database. -** -** Y: The name of a table in a FROM clause. Or in a trigger -** one of the special names "old" or "new". -** -** Z: The name of a column in table Y. -** -** The node at the root of the subtree is modified as follows: -** -** Expr.op Changed to TK_COLUMN -** Expr.pTab Points to the Table object for X.Y -** Expr.iColumn The column index in X.Y. -1 for the rowid. -** Expr.iTable The VDBE cursor number for X.Y -** -** -** To resolve result-set references, look for expression nodes of the -** form Z (with no X and Y prefix) where the Z matches the right-hand -** size of an AS clause in the result-set of a SELECT. The Z expression -** is replaced by a copy of the left-hand side of the result-set expression. -** Table-name and function resolution occurs on the substituted expression -** tree. For example, in: -** -** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x; -** -** The "x" term of the order by is replaced by "a+b" to render: -** -** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b; -** -** Function calls are checked to make sure that the function is -** defined and that the correct number of arguments are specified. -** If the function is an aggregate function, then the NC_HasAgg flag is -** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION. -** If an expression contains aggregate functions then the EP_Agg -** property on the expression is set. -** -** An error message is left in pParse if anything is amiss. The number -** if errors is returned. -*/ -SQLITE_PRIVATE int sqlite3ResolveExprNames( - NameContext *pNC, /* Namespace to resolve expressions in. */ - Expr *pExpr /* The expression to be analyzed. */ -){ - int savedHasAgg; - Walker w; - - if( pExpr==0 ) return SQLITE_OK; - 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 = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep; - w.xSelectCallback2 = 0; - w.u.pNC = pNC; -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight += pExpr->nHeight; - if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){ - return SQLITE_ERROR; - } -#endif - assert( pExpr!=0 ); - sqlite3WalkExprNN(&w, pExpr); -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight -= pExpr->nHeight; -#endif - assert( EP_Agg==NC_HasAgg ); - assert( EP_Win==NC_HasWin ); - testcase( pNC->ncFlags & NC_HasAgg ); - testcase( pNC->ncFlags & NC_HasWin ); - ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) ); - pNC->ncFlags |= savedHasAgg; - return pNC->nNcErr>0 || w.pParse->nErr>0; -} - -/* -** Resolve all names for all expression in an expression list. This is -** just like sqlite3ResolveExprNames() except that it works for an expression -** list rather than a single expression. -** -** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a -** failure. -*/ -SQLITE_PRIVATE int sqlite3ResolveExprListNames( - NameContext *pNC, /* Namespace to resolve expressions in. */ - ExprList *pList /* The expression list to be analyzed. */ -){ - int i; - int savedHasAgg = 0; - Walker w; - if( pList==0 ) return SQLITE_OK; - w.pParse = pNC->pParse; - w.xExprCallback = resolveExprStep; - w.xSelectCallback = resolveSelectStep; - w.xSelectCallback2 = 0; - w.u.pNC = pNC; - savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - if( pExpr==0 ) continue; -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight += pExpr->nHeight; - if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){ - return SQLITE_ERROR; - } -#endif - sqlite3WalkExprNN(&w, pExpr); -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight -= pExpr->nHeight; -#endif - assert( EP_Agg==NC_HasAgg ); - assert( EP_Win==NC_HasWin ); - testcase( pNC->ncFlags & NC_HasAgg ); - testcase( pNC->ncFlags & 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|NC_OrderAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - } - if( w.pParse->nErr>0 ) return SQLITE_ERROR; - } - pNC->ncFlags |= savedHasAgg; - return SQLITE_OK; -} - -/* -** Resolve all names in all expressions of a SELECT and in all -** descendants of the SELECT, including compounds off of p->pPrior, -** subqueries in expressions, and subqueries used as FROM clause -** terms. -** -** See sqlite3ResolveExprNames() for a description of the kinds of -** transformations that occur. -** -** All SELECT statements should have been expanded using -** sqlite3SelectExpand() prior to invoking this routine. -*/ -SQLITE_PRIVATE void sqlite3ResolveSelectNames( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - NameContext *pOuterNC /* Name context for parent SELECT statement */ -){ - Walker w; - - assert( p!=0 ); - w.xExprCallback = resolveExprStep; - w.xSelectCallback = resolveSelectStep; - w.xSelectCallback2 = 0; - w.pParse = pParse; - w.u.pNC = pOuterNC; - sqlite3WalkSelect(&w, p); -} - -/* -** Resolve names in expressions that can only reference a single table -** or which cannot reference any tables at all. Examples: -** -** "type" flag -** ------------ -** (1) CHECK constraints NC_IsCheck -** (2) WHERE clauses on partial indices NC_PartIdx -** (3) Expressions in indexes on expressions NC_IdxExpr -** (4) Expression arguments to VACUUM INTO. 0 -** (5) GENERATED ALWAYS as expressions NC_GenCol -** -** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN -** nodes of the expression is set to -1 and the Expr.iColumn value is -** set to the column number. In case (4), TK_COLUMN nodes cause an error. -** -** Any errors cause an error message to be set in pParse. -*/ -SQLITE_PRIVATE int sqlite3ResolveSelfReference( - Parse *pParse, /* Parsing context */ - Table *pTab, /* The table being referenced, or NULL */ - int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */ - Expr *pExpr, /* Expression to resolve. May be NULL. */ - ExprList *pList /* Expression list to resolve. May be NULL. */ -){ - SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */ - NameContext sNC; /* Name context for pParse->pNewTable */ - int rc; - u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ - - assert( type==0 || pTab!=0 ); - assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr - || type==NC_GenCol || pTab==0 ); - memset(&sNC, 0, sizeof(sNC)); - pSrc = (SrcList*)srcSpace; - memset(pSrc, 0, SZ_SRCLIST_1); - if( pTab ){ - pSrc->nSrc = 1; - pSrc->a[0].zName = pTab->zName; - pSrc->a[0].pSTab = pTab; - pSrc->a[0].iCursor = -1; - if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){ - /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP - ** schema elements */ - type |= NC_FromDDL; - } - } - sNC.pParse = pParse; - sNC.pSrcList = pSrc; - sNC.ncFlags = type | NC_IsDDL; - if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc; - if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList); - return rc; -} - -/************** End of resolve.c *********************************************/ -/************** Begin file expr.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains routines used for analyzing expressions and -** for generating VDBE code that evaluates expressions in SQLite. -*/ -/* #include "sqliteInt.h" */ - -/* Forward declarations */ -static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int); -static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree); - -/* -** Return the affinity character for a single column of a table. -*/ -SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table *pTab, int iCol){ - if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER; - return pTab->aCol[iCol].affinity; -} - -/* -** Return the 'affinity' of the expression pExpr if any. -** -** If pExpr is a column, a reference to a column via an 'AS' alias, -** or a sub-select with a column as the return value, then the -** affinity of that column is returned. Otherwise, 0x00 is returned, -** indicating no affinity for the expression. -** -** i.e. the WHERE clause expressions in the following statements all -** have an affinity: -** -** CREATE TABLE t1(a); -** SELECT * FROM t1 WHERE a; -** SELECT a AS b FROM t1 WHERE b; -** SELECT * FROM t1 WHERE (select a from t1); -*/ -SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){ - int op; - op = pExpr->op; - while( 1 /* exit-by-break */ ){ - if( op==TK_COLUMN || (op==TK_AGG_COLUMN && pExpr->y.pTab!=0) ){ - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); - } - if( op==TK_SELECT ){ - assert( ExprUseXSelect(pExpr) ); - assert( pExpr->x.pSelect!=0 ); - assert( pExpr->x.pSelect->pEList!=0 ); - assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 ); - return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); - } -#ifndef SQLITE_OMIT_CAST - if( op==TK_CAST ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - return sqlite3AffinityType(pExpr->u.zToken, 0); - } -#endif - if( op==TK_SELECT_COLUMN ){ - assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) ); - assert( pExpr->iColumn < pExpr->iTable ); - assert( pExpr->iColumn >= 0 ); - assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); - return sqlite3ExprAffinity( - pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr - ); - } - if( op==TK_VECTOR - || (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER) - ){ - assert( ExprUseXList(pExpr) ); - return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); - } - if( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){ - assert( pExpr->op==TK_COLLATE - || pExpr->op==TK_IF_NULL_ROW - || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) ); - pExpr = pExpr->pLeft; - op = pExpr->op; - continue; - } - if( op!=TK_REGISTER ) break; - op = pExpr->op2; - if( NEVER( op==TK_REGISTER ) ) break; - } - return pExpr->affExpr; -} - -/* -** Make a guess at all the possible datatypes of the result that could -** be returned by an expression. Return a bitmask indicating the answer: -** -** 0x01 Numeric -** 0x02 Text -** 0x04 Blob -** -** If the expression must return NULL, then 0x00 is returned. -*/ -SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr){ - while( pExpr ){ - switch( pExpr->op ){ - case TK_COLLATE: - case TK_IF_NULL_ROW: - case TK_UPLUS: { - pExpr = pExpr->pLeft; - break; - } - case TK_NULL: { - pExpr = 0; - break; - } - case TK_STRING: { - return 0x02; - } - case TK_BLOB: { - return 0x04; - } - case TK_CONCAT: { - return 0x06; - } - case TK_VARIABLE: - case TK_AGG_FUNCTION: - case TK_FUNCTION: { - return 0x07; - } - case TK_COLUMN: - case TK_AGG_COLUMN: - case TK_SELECT: - case TK_CAST: - case TK_SELECT_COLUMN: - case TK_VECTOR: { - int aff = sqlite3ExprAffinity(pExpr); - if( aff>=SQLITE_AFF_NUMERIC ) return 0x05; - if( aff==SQLITE_AFF_TEXT ) return 0x06; - return 0x07; - } - case TK_CASE: { - int res = 0; - int ii; - ExprList *pList = pExpr->x.pList; - assert( ExprUseXList(pExpr) && pList!=0 ); - assert( pList->nExpr > 0); - for(ii=1; iinExpr; ii+=2){ - res |= sqlite3ExprDataType(pList->a[ii].pExpr); - } - if( pList->nExpr % 2 ){ - res |= sqlite3ExprDataType(pList->a[pList->nExpr-1].pExpr); - } - return res; - } - default: { - return 0x01; - } - } /* End of switch(op) */ - } /* End of while(pExpr) */ - return 0x00; -} - -/* -** Set the collating sequence for expression pExpr to be the collating -** sequence named by pToken. Return a pointer to a new Expr node that -** implements the COLLATE operator. -** -** If a memory allocation error occurs, that fact is recorded in pParse->db -** and the pExpr parameter is returned unchanged. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken( - 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 */ -){ - if( pCollName->n>0 ){ - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); - if( pNew ){ - pNew->pLeft = pExpr; - pNew->flags |= EP_Collate|EP_Skip; - pExpr = pNew; - } - } - return pExpr; -} -SQLITE_PRIVATE Expr *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 ); - sqlite3TokenInit(&s, (char*)zC); - return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); -} - -/* -** Skip over any TK_COLLATE operators. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ - while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ - assert( pExpr->op==TK_COLLATE ); - pExpr = pExpr->pLeft; - } - return pExpr; -} - -/* -** Skip over any TK_COLLATE operators and/or any unlikely() -** or likelihood() or likely() functions at the root of an -** expression. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ - while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ - if( ExprHasProperty(pExpr, EP_Unlikely) ){ - assert( ExprUseXList(pExpr) ); - assert( pExpr->x.pList->nExpr>0 ); - assert( pExpr->op==TK_FUNCTION ); - pExpr = pExpr->x.pList->a[0].pExpr; - }else if( pExpr->op==TK_COLLATE ){ - pExpr = pExpr->pLeft; - }else{ - break; - } - } - return pExpr; -} - -/* -** Return the collation sequence for the expression pExpr. If -** there is no defined collating sequence, return NULL. -** -** See also: sqlite3ExprNNCollSeq() -** -** The sqlite3ExprNNCollSeq() works the same exact that it returns the -** default collation if pExpr has no defined collation. -** -** The collating sequence might be determined by a COLLATE operator -** or by the presence of a column with a defined collating sequence. -** COLLATE operators take first precedence. Left operands take -** precedence over right operands. -*/ -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ - sqlite3 *db = pParse->db; - CollSeq *pColl = 0; - const Expr *p = pExpr; - while( p ){ - int op = p->op; - if( op==TK_REGISTER ) op = p->op2; - if( (op==TK_AGG_COLUMN && p->y.pTab!=0) - || op==TK_COLUMN || op==TK_TRIGGER - ){ - int j; - assert( ExprUseYTab(p) ); - assert( p->y.pTab!=0 ); - if( (j = p->iColumn)>=0 ){ - const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]); - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - } - break; - } - if( op==TK_CAST || op==TK_UPLUS ){ - p = p->pLeft; - continue; - } - if( op==TK_VECTOR - || (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER) - ){ - assert( ExprUseXList(p) ); - p = p->x.pList->a[0].pExpr; - continue; - } - if( op==TK_COLLATE ){ - assert( !ExprHasProperty(p, EP_IntValue) ); - pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); - break; - } - if( p->flags & EP_Collate ){ - if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ - p = p->pLeft; - }else{ - Expr *pNext = p->pRight; - /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( !ExprUseXList(p) || p->x.pList==0 || p->pRight==0 ); - if( ExprUseXList(p) && p->x.pList!=0 && !db->mallocFailed ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ - pNext = p->x.pList->a[i].pExpr; - break; - } - } - } - p = pNext; - } - }else{ - break; - } - } - if( sqlite3CheckCollSeq(pParse, pColl) ){ - pColl = 0; - } - return pColl; -} - -/* -** Return the collation sequence for the expression pExpr. If -** there is no defined collating sequence, return a pointer to the -** default collation sequence. -** -** See also: sqlite3ExprCollSeq() -** -** The sqlite3ExprCollSeq() routine works the same except that it -** returns NULL if there is no defined collation. -*/ -SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){ - CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr); - if( p==0 ) p = pParse->db->pDfltColl; - assert( p!=0 ); - return p; -} - -/* -** Return TRUE if the two expressions have equivalent collating sequences. -*/ -SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){ - CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1); - CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2); - return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0; -} - -/* -** pExpr is an operand of a comparison operator. aff2 is the -** type affinity of the other operand. This routine returns the -** type affinity that should be used for the comparison operator. -*/ -SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2){ - char aff1 = sqlite3ExprAffinity(pExpr); - if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){ - /* Both sides of the comparison are columns. If one has numeric - ** affinity, use that. Otherwise use no affinity. - */ - if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ - return SQLITE_AFF_NUMERIC; - }else{ - return SQLITE_AFF_BLOB; - } - }else{ - /* One side is a column, the other is not. Use the columns affinity. */ - assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE ); - return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE; - } -} - -/* -** pExpr is a comparison operator. Return the type affinity that should -** be applied to both operands prior to doing the comparison. -*/ -static char comparisonAffinity(const Expr *pExpr){ - char aff; - assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || - pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || - pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); - assert( pExpr->pLeft ); - aff = sqlite3ExprAffinity(pExpr->pLeft); - if( pExpr->pRight ){ - aff = sqlite3CompareAffinity(pExpr->pRight, aff); - }else if( ExprUseXSelect(pExpr) ){ - aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); - }else if( aff==0 ){ - aff = SQLITE_AFF_BLOB; - } - return aff; -} - -/* -** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. -** idx_affinity is the affinity of an indexed column. Return true -** if the index with affinity idx_affinity may be used to implement -** the comparison in pExpr. -*/ -SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){ - char aff = comparisonAffinity(pExpr); - if( affflags & EP_Collate ){ - pColl = sqlite3ExprCollSeq(pParse, pLeft); - }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ - pColl = sqlite3ExprCollSeq(pParse, pRight); - }else{ - pColl = sqlite3ExprCollSeq(pParse, pLeft); - if( !pColl ){ - pColl = sqlite3ExprCollSeq(pParse, pRight); - } - } - return pColl; -} - -/* Expression p is a comparison operator. Return a collation sequence -** appropriate for the comparison operator. -** -** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). -** However, if the OP_Commuted flag is set, then the order of the operands -** is reversed in the sqlite3BinaryCompareCollSeq() call so that the -** correct collating sequence is found. -*/ -SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){ - if( ExprHasProperty(p, EP_Commuted) ){ - return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft); - }else{ - return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight); - } -} - -/* -** Generate code for a comparison operator. -*/ -static int codeCompare( - Parse *pParse, /* The parsing (and code generating) context */ - Expr *pLeft, /* The left operand */ - Expr *pRight, /* The right operand */ - int opcode, /* The comparison opcode */ - int in1, int in2, /* Register holding operands */ - int dest, /* Jump here if true. */ - int jumpIfNull, /* If true, jump if either operand is NULL */ - int isCommuted /* The comparison has been commuted */ -){ - int p5; - int addr; - CollSeq *p4; - - if( pParse->nErr ) return 0; - if( isCommuted ){ - p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft); - }else{ - p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); - } - p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); - addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, - (void*)p4, P4_COLLSEQ); - sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5); - return addr; -} - -/* -** Return true if expression pExpr is a vector, or false otherwise. -** -** A vector is defined as any expression that results in two or more -** columns of result. Every TK_VECTOR node is an vector because the -** parser will not generate a TK_VECTOR with fewer than two entries. -** 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 sqlite3ExprIsVector(const Expr *pExpr){ - return sqlite3ExprVectorSize(pExpr)>1; -} - -/* -** If the expression passed as the only argument is of type TK_VECTOR -** return the number of expressions in the vector. Or, if the expression -** is a sub-select, return the number of columns in the sub-select. For -** any other type of expression, return 1. -*/ -SQLITE_PRIVATE int 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; - } -} - -/* -** Return a pointer to a subexpression of pVector that is the i-th -** column of the vector (numbered starting with 0). The caller must -** ensure that i is within range. -** -** If pVector is really a scalar (and "scalar" here includes subqueries -** that return a single column!) then return pVector unmodified. -** -** pVector retains ownership of the returned subexpression. -** -** If the vector is a (SELECT ...) then the expression returned is -** just the expression for the i-th term of the result set, and may -** not be ready for evaluation because the table cursor has not yet -** been positioned. -*/ -SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ - assert( iop==TK_ERROR ); - if( 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; - } - } - return pVector; -} - -/* -** Compute and return a new Expr object which when passed to -** sqlite3ExprCode() will generate all necessary code to compute -** the iField-th column of the vector expression pVector. -** -** It is ok for pVector to be a scalar (as long as iField==0). -** In that case, this routine works like sqlite3ExprDup(). -** -** The caller owns the returned Expr object and is responsible for -** ensuring that the returned value eventually gets freed. -** -** The caller retains ownership of pVector. If pVector is a TK_SELECT, -** then the returned object will reference pVector and so pVector must remain -** valid for the life of the returned object. If pVector is a TK_VECTOR -** or a scalar expression, then it can be deleted as soon as this routine -** returns. -** -** A trick to cause a TK_SELECT pVector to be deleted together with -** the returned Expr object is to attach the pVector to the pRight field -** of the returned TK_SELECT_COLUMN Expr object. -*/ -SQLITE_PRIVATE Expr *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 nField /* Total number of columns in the vector */ -){ - Expr *pRet; - if( pVector->op==TK_SELECT ){ - assert( ExprUseXSelect(pVector) ); - /* The TK_SELECT_COLUMN Expr node: - ** - ** pLeft: pVector containing TK_SELECT. Not deleted. - ** pRight: not used. But recursively deleted. - ** iColumn: Index of a column in pVector - ** iTable: 0 or the number of columns on the LHS of an assignment - ** pLeft->iTable: First in an array of register holding result, or 0 - ** if the result is not yet computed. - ** - ** sqlite3ExprDelete() specifically skips the recursive delete of - ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector - ** can be attached to pRight to cause this node to take ownership of - ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes - ** with the same pLeft pointer to the pVector, but only one of them - ** will own the pVector. - */ - pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); - if( pRet ){ - ExprSetProperty(pRet, EP_FullSize); - pRet->iTable = nField; - pRet->iColumn = iField; - pRet->pLeft = pVector; - } - }else{ - 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 = sqlite3ExprDup(pParse->db, pVector, 0); - } - return pRet; -} - -/* -** If expression pExpr is of type TK_SELECT, generate code to evaluate -** it. Return the register in which the result is stored (or, if the -** sub-select returns more than one column, the first in an array -** of registers in which the result is stored). -** -** If pExpr is not a TK_SELECT expression, return 0. -*/ -static int exprCodeSubselect(Parse *pParse, Expr *pExpr){ - int reg = 0; -#ifndef SQLITE_OMIT_SUBQUERY - if( pExpr->op==TK_SELECT ){ - reg = sqlite3CodeSubselect(pParse, pExpr); - } -#endif - return reg; -} - -/* -** Argument pVector points to a vector expression - either a TK_VECTOR -** or TK_SELECT that returns more than one column. This function returns -** the register number of a register that contains the value of -** element iField of the vector. -** -** If pVector is a TK_SELECT expression, then code for it must have -** already been generated using the exprCodeSubselect() routine. In this -** case parameter regSelect should be the first in an array of registers -** containing the results of the sub-select. -** -** If pVector is of type TK_VECTOR, then code for the requested field -** is generated. In this case (*pRegFree) may be set to the number of -** a temporary register to be freed by the caller before returning. -** -** Before returning, output parameter (*ppExpr) is set to point to the -** Expr object corresponding to element iElem of the vector. -*/ -static int exprVectorRegister( - Parse *pParse, /* Parse context */ - Expr *pVector, /* Vector to extract element from */ - int iField, /* Field to extract from pVector */ - int regSelect, /* First in array of registers */ - Expr **ppExpr, /* OUT: Expression element */ - int *pRegFree /* OUT: Temp register to free */ -){ - u8 op = pVector->op; - assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR ); - if( op==TK_REGISTER ){ - *ppExpr = 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; - } - if( op==TK_VECTOR ){ - assert( ExprUseXList(pVector) ); - *ppExpr = pVector->x.pList->a[iField].pExpr; - return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); - } - return 0; -} - -/* -** Expression pExpr is a comparison between two vector values. Compute -** the result of the comparison (1, 0, or NULL) and write that -** result into register dest. -** -** The caller must satisfy the following preconditions: -** -** if pExpr->op==TK_IS: op==TK_EQ and p5==SQLITE_NULLEQ -** if pExpr->op==TK_ISNOT: op==TK_NE and p5==SQLITE_NULLEQ -** otherwise: op==pExpr->op and p5==0 -*/ -static void codeVectorCompare( - Parse *pParse, /* Code generator context */ - Expr *pExpr, /* The comparison operation */ - int dest, /* Write results into this register */ - u8 op, /* Comparison operator */ - u8 p5 /* SQLITE_NULLEQ or zero */ -){ - Vdbe *v = pParse->pVdbe; - Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - int nLeft = sqlite3ExprVectorSize(pLeft); - int i; - int regLeft = 0; - int regRight = 0; - u8 opx = op; - int addrCmp = 0; - int addrDone = sqlite3VdbeMakeLabel(pParse); - int isCommuted = ExprHasProperty(pExpr,EP_Commuted); - - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); - if( pParse->nErr ) return; - if( nLeft!=sqlite3ExprVectorSize(pRight) ){ - sqlite3ErrorMsg(pParse, "row value misused"); - return; - } - assert( pExpr->op==TK_EQ || pExpr->op==TK_NE - || pExpr->op==TK_IS || pExpr->op==TK_ISNOT - || pExpr->op==TK_LT || pExpr->op==TK_GT - || pExpr->op==TK_LE || pExpr->op==TK_GE - ); - assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) - || (pExpr->op==TK_ISNOT && op==TK_NE) ); - assert( p5==0 || pExpr->op!=op ); - assert( p5==SQLITE_NULLEQ || pExpr->op==op ); - - 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); - - sqlite3VdbeAddOp2(v, OP_Integer, 1, dest); - for(i=0; 1 /*Loop exits by "break"*/; i++){ - int regFree1 = 0, regFree2 = 0; - Expr *pL = 0, *pR = 0; - int r1, r2; - assert( i>=0 && i0 -/* -** Check that argument nHeight is less than or equal to the maximum -** expression depth allowed. If it is not, leave an error message in -** pParse. -*/ -SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){ - int rc = SQLITE_OK; - int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; - if( nHeight>mxHeight ){ - sqlite3ErrorMsg(pParse, - "Expression tree is too large (maximum depth %d)", mxHeight - ); - rc = SQLITE_ERROR; - } - return rc; -} - -/* The following three functions, heightOfExpr(), heightOfExprList() -** and heightOfSelect(), are used to determine the maximum height -** of any expression tree referenced by the structure passed as the -** first argument. -** -** If this maximum height is greater than the current value pointed -** to by pnHeight, the second parameter, then set *pnHeight to that -** value. -*/ -static void heightOfExpr(const Expr *p, int *pnHeight){ - if( p ){ - if( p->nHeight>*pnHeight ){ - *pnHeight = p->nHeight; - } - } -} -static void heightOfExprList(const ExprList *p, int *pnHeight){ - if( p ){ - int i; - for(i=0; inExpr; i++){ - heightOfExpr(p->a[i].pExpr, pnHeight); - } - } -} -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); - heightOfExpr(p->pLimit, pnHeight); - heightOfExprList(p->pEList, pnHeight); - heightOfExprList(p->pGroupBy, pnHeight); - heightOfExprList(p->pOrderBy, pnHeight); - } -} - -/* -** Set the Expr.nHeight variable in the structure passed as an -** argument. An expression with no children, Expr.pList or -** Expr.pSelect member has a height of 1. Any other expression -** has a height equal to the maximum height of any other -** referenced Expr plus one. -** -** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, -** if appropriate. -*/ -static void exprSetHeight(Expr *p){ - int nHeight = p->pLeft ? p->pLeft->nHeight : 0; - if( NEVER(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); - p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); - } - p->nHeight = nHeight + 1; -} - -/* -** Set the Expr.nHeight variable using the exprSetHeight() function. If -** the height is greater than the maximum allowed expression depth, -** leave an error in pParse. -** -** Also propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. -*/ -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( pParse->nErr ) return; - exprSetHeight(p); - sqlite3ExprCheckHeight(pParse, p->nHeight); -} - -/* -** Return the maximum height of any expression tree referenced -** by the select statement passed as an argument. -*/ -SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *p){ - int nHeight = 0; - heightOfSelect(p, &nHeight); - return nHeight; -} -#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ -/* -** Propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. -*/ -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( pParse->nErr ) return; - if( p && ExprUseXList(p) && p->x.pList ){ - p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); - } -} -#define exprSetHeight(y) -#endif /* SQLITE_MAX_EXPR_DEPTH>0 */ - -/* -** Set the error offset for an Expr node, if possible. -*/ -SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr *pExpr, int iOfst){ - if( pExpr==0 ) return; - if( NEVER(ExprUseWJoin(pExpr)) ) return; - pExpr->w.iOfst = iOfst; -} - -/* -** This routine is the core allocator for Expr nodes. -** -** Construct a new expression node and return a pointer to it. Memory -** for this node and for the pToken argument is a single allocation -** obtained from sqlite3DbMalloc(). The calling function -** is responsible for making sure the node eventually gets freed. -** -** If dequote is true, then the token (if it exists) is dequoted. -** If dequote is false, no dequoting is performed. The deQuote -** parameter is ignored if pToken is NULL or if the token does not -** appear to be quoted. If the quotes were of the form "..." (double-quotes) -** then the EP_DblQuoted flag is set on the expression node. -** -** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to -** a string that can be translated into a 32-bit integer, then the token is -** not stored in u.zToken. Instead, the integer values is written -** into u.iValue and the EP_IntValue flag is set. No extra storage -** is allocated to hold the integer text and the dequote flag is ignored. -** See also tag-20240227-b. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAlloc( - sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ - int op, /* Expression opcode */ - const Token *pToken, /* Token argument. Might be NULL */ - int dequote /* True to dequote */ -){ - Expr *pNew; - int nExtra = 0; - int iValue = 0; - - assert( db!=0 ); - if( pToken ){ - if( op!=TK_INTEGER || pToken->z==0 - || sqlite3GetInt32(pToken->z, &iValue)==0 ){ - nExtra = pToken->n+1; /* tag-20240227-a */ - assert( iValue>=0 ); - } - } - pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); - if( pNew ){ - memset(pNew, 0, sizeof(Expr)); - pNew->op = (u8)op; - pNew->iAgg = -1; - if( pToken ){ - if( nExtra==0 ){ - pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse); - pNew->u.iValue = iValue; - }else{ - pNew->u.zToken = (char*)&pNew[1]; - assert( pToken->z!=0 || pToken->n==0 ); - if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); - pNew->u.zToken[pToken->n] = 0; - if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ - sqlite3DequoteExpr(pNew); - } - } - } -#if SQLITE_MAX_EXPR_DEPTH>0 - pNew->nHeight = 1; -#endif - } - return pNew; -} - -/* -** Allocate a new expression node from a zero-terminated token that has -** already been dequoted. -*/ -SQLITE_PRIVATE Expr *sqlite3Expr( - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ - int op, /* Expression opcode */ - const char *zToken /* Token argument. Might be NULL */ -){ - Token x; - x.z = zToken; - x.n = sqlite3Strlen30(zToken); - return sqlite3ExprAlloc(db, op, &x, 0); -} - -/* -** Attach subtrees pLeft and pRight to the Expr node pRoot. -** -** If pRoot==NULL that means that a memory allocation error has occurred. -** In that case, delete the subtrees pLeft and pRight. -*/ -SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( - sqlite3 *db, - Expr *pRoot, - Expr *pLeft, - Expr *pRight -){ - if( pRoot==0 ){ - assert( db->mallocFailed ); - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); - }else{ - assert( ExprUseXList(pRoot) ); - assert( pRoot->x.pSelect==0 ); - if( pRight ){ - pRoot->pRight = pRight; - pRoot->flags |= EP_Propagate & pRight->flags; -#if SQLITE_MAX_EXPR_DEPTH>0 - pRoot->nHeight = pRight->nHeight+1; - }else{ - pRoot->nHeight = 1; -#endif - } - if( pLeft ){ - pRoot->pLeft = pLeft; - pRoot->flags |= EP_Propagate & pLeft->flags; -#if SQLITE_MAX_EXPR_DEPTH>0 - if( pLeft->nHeight>=pRoot->nHeight ){ - pRoot->nHeight = pLeft->nHeight+1; - } -#endif - } - } -} - -/* -** Allocate an Expr node which joins as many as two subtrees. -** -** One or both of the subtrees can be NULL. Return a pointer to the new -** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed, -** free the subtrees and return NULL. -*/ -SQLITE_PRIVATE Expr *sqlite3PExpr( - Parse *pParse, /* Parsing context */ - int op, /* Expression opcode */ - Expr *pLeft, /* Left operand */ - Expr *pRight /* Right operand */ -){ - Expr *p; - p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); - if( p ){ - memset(p, 0, sizeof(Expr)); - p->op = op & 0xff; - p->iAgg = -1; - sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); - sqlite3ExprCheckHeight(pParse, p->nHeight); - }else{ - sqlite3ExprDelete(pParse->db, pLeft); - sqlite3ExprDelete(pParse->db, pRight); - } - return p; -} - -/* -** Add pSelect to the Expr.x.pSelect field. Or, if pExpr is NULL (due -** do a memory allocation failure) then delete the pSelect object. -*/ -SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){ - if( pExpr ){ - pExpr->x.pSelect = pSelect; - ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, pExpr); - }else{ - assert( pParse->db->mallocFailed ); - sqlite3SelectDelete(pParse->db, pSelect); - } -} - -/* -** 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 *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){ - int ii; - Select *pRet = 0; - assert( nElem>1 ); - for(ii=0; iinExpr; 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 ){ - sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d", - nExprElem, nExprElem>1?"s":"", nElem - ); - break; - } - assert( ExprUseXList(pExpr) ); - pSel = 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; - } - sqlite3ExprListDelete(pParse->db, pEList); - return pRet; -} - -/* -** Join two expressions using an AND operator. If either expression is -** NULL, then just return the other expression. -** -** If one side or the other of the AND is known to be false, and neither side -** is part of an ON clause, then instead of returning an AND expression, -** just return a constant expression with a value of false. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ - sqlite3 *db = pParse->db; - if( pLeft==0 ){ - return pRight; - }else if( pRight==0 ){ - return pLeft; - }else{ - u32 f = pLeft->flags | pRight->flags; - if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse|EP_HasFunc))==EP_IsFalse - && !IN_RENAME_OBJECT - ){ - sqlite3ExprDeferredDelete(pParse, pLeft); - sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3Expr(db, TK_INTEGER, "0"); - }else{ - return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); - } - } -} - -/* -** Construct a new expression node for a function with multiple -** arguments. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprFunction( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* Argument list */ - const Token *pToken, /* Name of the function */ - int eDistinct /* SF_Distinct or SF_ALL or 0 */ -){ - Expr *pNew; - sqlite3 *db = pParse->db; - assert( pToken ); - pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ - return 0; - } - 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 - ){ - sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); - } - pNew->x.pList = pList; - ExprSetProperty(pNew, EP_HasFunc); - assert( ExprUseXList(pNew) ); - sqlite3ExprSetHeightAndFlags(pParse, pNew); - if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); - return pNew; -} - -/* -** Report an error when attempting to use an ORDER BY clause within -** the arguments of a non-aggregate function. -*/ -SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse *pParse, Expr *p){ - sqlite3ErrorMsg(pParse, - "ORDER BY may not be used with non-aggregate %#T()", p - ); -} - -/* -** Attach an ORDER BY clause to a function call. -** -** functionname( arguments ORDER BY sortlist ) -** \_____________________/ \______/ -** pExpr pOrderBy -** -** The ORDER BY clause is inserted into a new Expr node of type TK_ORDER -** and added to the Expr.pLeft field of the parent TK_FUNCTION node. -*/ -SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The function call to which ORDER BY is to be added */ - ExprList *pOrderBy /* The ORDER BY clause to add */ -){ - Expr *pOB; - sqlite3 *db = pParse->db; - if( NEVER(pOrderBy==0) ){ - assert( db->mallocFailed ); - return; - } - if( pExpr==0 ){ - assert( db->mallocFailed ); - sqlite3ExprListDelete(db, pOrderBy); - return; - } - assert( pExpr->op==TK_FUNCTION ); - assert( pExpr->pLeft==0 ); - assert( ExprUseXList(pExpr) ); - if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){ - /* Ignore ORDER BY on zero-argument aggregates */ - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pOrderBy); - return; - } - if( IsWindowFunc(pExpr) ){ - sqlite3ExprOrderByAggregateError(pParse, pExpr); - sqlite3ExprListDelete(db, pOrderBy); - return; - } - - pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0); - if( pOB==0 ){ - sqlite3ExprListDelete(db, pOrderBy); - return; - } - pOB->x.pList = pOrderBy; - assert( ExprUseXList(pOB) ); - pExpr->pLeft = pOB; - ExprSetProperty(pOB, EP_FullSize); -} - -/* -** Check to see if a function is usable according to current access -** rules: -** -** SQLITE_FUNC_DIRECT - Only usable from top-level SQL -** -** SQLITE_FUNC_UNSAFE - Usable if TRUSTED_SCHEMA or from -** top-level SQL -** -** If the function is not usable, create an error. -*/ -SQLITE_PRIVATE void sqlite3ExprFunctionUsable( - Parse *pParse, /* Parsing and code generating context */ - 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 ); - if( ExprHasProperty(pExpr, EP_FromDDL) ){ - if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 - || (pParse->db->flags & SQLITE_TrustedSchema)==0 - ){ - /* Functions prohibited in triggers and views if: - ** (1) tagged with SQLITE_DIRECTONLY - ** (2) not tagged with SQLITE_INNOCUOUS (which means it - ** is tagged with SQLITE_FUNC_UNSAFE) and - ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning - ** that the schema is possibly tainted). - */ - sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr); - } - } -} - -/* -** Assign a variable number to an expression that encodes a wildcard -** in the original SQL statement. -** -** Wildcards consisting of a single "?" are assigned the next sequential -** variable number. -** -** Wildcards of the form "?nnn" are assigned the number "nnn". We make -** sure "nnn" is not too big to avoid a denial of service attack when -** the SQL statement comes from an external source. -** -** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number -** as the previous instance of the same wildcard. Or if this is the first -** instance of the wildcard, the next sequential variable number is -** assigned. -*/ -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ - sqlite3 *db = pParse->db; - const char *z; - ynVar x; - - if( pExpr==0 ) return; - assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); - z = pExpr->u.zToken; - assert( z!=0 ); - assert( z[0]!=0 ); - assert( n==(u32)sqlite3Strlen30(z) ); - if( z[1]==0 ){ - /* Wildcard of the form "?". Assign the next variable number */ - assert( z[0]=='?' ); - x = (ynVar)(++pParse->nVar); - }else{ - int doAdd = 0; - if( z[0]=='?' ){ - /* Wildcard of the form "?nnn". Convert "nnn" to an integer and - ** use it as the variable number */ - i64 i; - int bOk; - if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/ - i = z[1]-'0'; /* The common case of ?N for a single digit N */ - bOk = 1; - }else{ - bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); - } - testcase( i==0 ); - testcase( i==1 ); - testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); - testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); - if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ - sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", - db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); - return; - } - x = (ynVar)i; - if( x>pParse->nVar ){ - pParse->nVar = (int)x; - doAdd = 1; - }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){ - doAdd = 1; - } - }else{ - /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable - ** number as the prior appearance of the same name, or if the name - ** has never appeared before, reuse the same variable number - */ - x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n); - if( x==0 ){ - x = (ynVar)(++pParse->nVar); - doAdd = 1; - } - } - if( doAdd ){ - pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x); - } - } - pExpr->iColumn = x; - if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ - sqlite3ErrorMsg(pParse, "too many SQL variables"); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); - } -} - -/* -** Recursively delete an expression tree. -*/ -static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ - assert( p!=0 ); - assert( db!=0 ); -exprDeleteRestart: - 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( !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( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 ); - if( p->pRight ){ - assert( !ExprHasProperty(p, EP_WinFunc) ); - sqlite3ExprDeleteNN(db, p->pRight); - }else if( ExprUseXSelect(p) ){ - assert( !ExprHasProperty(p, EP_WinFunc) ); - sqlite3SelectDelete(db, p->x.pSelect); - }else{ - sqlite3ExprListDelete(db, p->x.pList); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_WinFunc) ){ - sqlite3WindowDelete(db, p->y.pWin); - } -#endif - } - if( p->pLeft && p->op!=TK_SELECT_COLUMN ){ - Expr *pLeft = p->pLeft; - if( !ExprHasProperty(p, EP_Static) - && !ExprHasProperty(pLeft, EP_Static) - ){ - /* Avoid unnecessary recursion on unary operators */ - sqlite3DbNNFreeNN(db, p); - p = pLeft; - goto exprDeleteRestart; - }else{ - sqlite3ExprDeleteNN(db, pLeft); - } - } - } - if( !ExprHasProperty(p, EP_Static) ){ - sqlite3DbNNFreeNN(db, p); - } -} -SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ - if( p ) sqlite3ExprDeleteNN(db, p); -} -SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){ - if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p); -} - -/* -** Clear both elements of an OnOrUsing object -*/ -SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ - if( p==0 ){ - /* Nothing to clear */ - }else if( p->pOn ){ - sqlite3ExprDeleteNN(db, p->pOn); - }else if( p->pUsing ){ - sqlite3IdListDelete(db, p->pUsing); - } -} - -/* -** Arrange to cause pExpr to be deleted when the pParse is deleted. -** This is similar to sqlite3ExprDelete() except that the delete is -** deferred until the pParse is deleted. -** -** The pExpr might be deleted immediately on an OOM error. -** -** Return 0 if the delete was successfully deferred. Return non-zero -** if the delete happened immediately because of an OOM. -*/ -SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ - return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr); -} - -/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the -** expression. -*/ -SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){ - if( p ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprUnmap(pParse, p); - } - sqlite3ExprDeleteNN(pParse->db, p); - } -} - -/* -** Return the number of bytes allocated for the expression structure -** passed as the first argument. This is always one of EXPR_FULLSIZE, -** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. -*/ -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; -} - -/* -** The dupedExpr*Size() routines each return the number of bytes required -** to store a copy of an expression or expression tree. They differ in -** how much of the tree is measured. -** -** dupedExprStructSize() Size of only the Expr structure -** dupedExprNodeSize() Size of Expr + space for token -** dupedExprSize() Expr + token + subtree components -** -*************************************************************************** -** -** The dupedExprStructSize() function returns two values OR-ed together: -** (1) the space required for a copy of the Expr structure only and -** (2) the EP_xxx flags that indicate what the structure size should be. -** The return values is always one of: -** -** EXPR_FULLSIZE -** EXPR_REDUCEDSIZE | EP_Reduced -** EXPR_TOKENONLYSIZE | EP_TokenOnly -** -** The size of the structure can be found by masking the return value -** of this routine with 0xfff. The flags can be found by masking the -** return value with EP_Reduced|EP_TokenOnly. -** -** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size -** (unreduced) Expr objects as they or originally constructed by the parser. -** During expression analysis, extra information is computed and moved into -** later parts of the Expr object and that extra information might get chopped -** off if the expression is reduced. Note also that it does not work to -** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal -** to reduce a pristine expression tree from the parser. The implementation -** of dupedExprStructSize() contain multiple assert() statements that attempt -** to enforce this constraint. -*/ -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 ); - assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags || ExprHasProperty(p, EP_FullSize) ){ - nSize = EXPR_FULLSIZE; - }else{ - assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasProperty(p, EP_OuterON) ); - assert( !ExprHasVVAProperty(p, EP_NoReduce) ); - if( p->pLeft || p->x.pList ){ - nSize = EXPR_REDUCEDSIZE | EP_Reduced; - }else{ - assert( p->pRight==0 ); - nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; - } - } - return nSize; -} - -/* -** This function returns the space in bytes required to store the copy -** of the Expr structure and a copy of the Expr.u.zToken string (if that -** string is defined.) -*/ -static int dupedExprNodeSize(const Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags) & 0xfff; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nByte += sqlite3Strlen30NN(p->u.zToken)+1; - } - return ROUND8(nByte); -} - -/* -** Return the number of bytes required to create a duplicate of the -** expression passed as the first argument. -** -** The value returned includes space to create a copy of the Expr struct -** itself and the buffer referred to by Expr.u.zToken, if any. -** -** The return value includes space to duplicate all Expr nodes in the -** tree formed by Expr.pLeft and Expr.pRight, but not any other -** substructure such as Expr.x.pList, Expr.x.pSelect, and Expr.y.pWin. -*/ -static int dupedExprSize(const Expr *p){ - int nByte; - assert( p!=0 ); - nByte = dupedExprNodeSize(p, EXPRDUP_REDUCE); - if( p->pLeft ) nByte += dupedExprSize(p->pLeft); - if( p->pRight ) nByte += dupedExprSize(p->pRight); - assert( nByte==ROUND8(nByte) ); - return nByte; -} - -/* -** An EdupBuf is a memory allocation used to stored multiple Expr objects -** together with their Expr.zToken content. This is used to help implement -** compression while doing sqlite3ExprDup(). The top-level Expr does the -** allocation for itself and many of its decendents, then passes an instance -** of the structure down into exprDup() so that they decendents can have -** access to that memory. -*/ -typedef struct EdupBuf EdupBuf; -struct EdupBuf { - u8 *zAlloc; /* Memory space available for storage */ -#ifdef SQLITE_DEBUG - u8 *zEnd; /* First byte past the end of memory */ -#endif -}; - -/* -** This function is similar to sqlite3ExprDup(), except that if pEdupBuf -** is not NULL then it points to memory that can be used to store a copy -** of the input Expr p together with its p->u.zToken (if any). pEdupBuf -** is updated with the new buffer tail prior to returning. -*/ -static Expr *exprDup( - sqlite3 *db, /* Database connection (for memory allocation) */ - const Expr *p, /* Expr tree to be duplicated */ - int dupFlags, /* EXPRDUP_REDUCE for compression. 0 if not */ - EdupBuf *pEdupBuf /* Preallocated storage space, or NULL */ -){ - Expr *pNew; /* Value to return */ - EdupBuf sEdupBuf; /* Memory space from which to build Expr object */ - u32 staticFlag; /* EP_Static if space not obtained from malloc */ - int nToken = -1; /* Space needed for p->u.zToken. -1 means unknown */ - - assert( db!=0 ); - assert( p ); - assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE ); - assert( pEdupBuf==0 || dupFlags==EXPRDUP_REDUCE ); - - /* Figure out where to write the new Expr structure. */ - if( pEdupBuf ){ - sEdupBuf.zAlloc = pEdupBuf->zAlloc; -#ifdef SQLITE_DEBUG - sEdupBuf.zEnd = pEdupBuf->zEnd; -#endif - staticFlag = EP_Static; - assert( sEdupBuf.zAlloc!=0 ); - assert( dupFlags==EXPRDUP_REDUCE ); - }else{ - int nAlloc; - if( dupFlags ){ - nAlloc = dupedExprSize(p); - }else if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30NN(p->u.zToken)+1; - nAlloc = ROUND8(EXPR_FULLSIZE + nToken); - }else{ - nToken = 0; - nAlloc = ROUND8(EXPR_FULLSIZE); - } - assert( nAlloc==ROUND8(nAlloc) ); - sEdupBuf.zAlloc = sqlite3DbMallocRawNN(db, nAlloc); -#ifdef SQLITE_DEBUG - sEdupBuf.zEnd = sEdupBuf.zAlloc ? sEdupBuf.zAlloc+nAlloc : 0; -#endif - - staticFlag = 0; - } - pNew = (Expr *)sEdupBuf.zAlloc; - assert( EIGHT_BYTE_ALIGNMENT(pNew) ); - - if( pNew ){ - /* Set nNewSize to the size allocated for the structure pointed to - ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or - ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->u.zToken string (if any). - */ - const unsigned nStructSize = dupedExprStructSize(p, dupFlags); - int nNewSize = nStructSize & 0xfff; - if( nToken<0 ){ - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; - } - } - if( dupFlags ){ - assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= nNewSize+nToken ); - assert( ExprHasProperty(p, EP_Reduced)==0 ); - memcpy(sEdupBuf.zAlloc, p, nNewSize); - }else{ - u32 nSize = (u32)exprStructSize(p); - assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= - (int)EXPR_FULLSIZE+nToken ); - memcpy(sEdupBuf.zAlloc, p, nSize); - if( nSizeflags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); - pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); - pNew->flags |= staticFlag; - ExprClearVVAProperties(pNew); - if( dupFlags ){ - ExprSetVVAProperty(pNew, EP_Immutable); - } - - /* Copy the p->u.zToken string, if any. */ - assert( nToken>=0 ); - if( nToken>0 ){ - char *zToken = pNew->u.zToken = (char*)&sEdupBuf.zAlloc[nNewSize]; - memcpy(zToken, p->u.zToken, nToken); - nNewSize += nToken; - } - sEdupBuf.zAlloc += ROUND8(nNewSize); - - if( ((p->flags|pNew->flags)&(EP_TokenOnly|EP_Leaf))==0 ){ - - /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ - if( ExprUseXSelect(p) ){ - pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); - }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, - p->op!=TK_ORDER ? dupFlags : 0); - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_WinFunc) ){ - pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); - assert( ExprHasProperty(pNew, EP_WinFunc) ); - } -#endif /* SQLITE_OMIT_WINDOWFUNC */ - - /* Fill in pNew->pLeft and pNew->pRight. */ - if( dupFlags ){ - if( p->op==TK_SELECT_COLUMN ){ - pNew->pLeft = p->pLeft; - assert( p->pRight==0 - || p->pRight==p->pLeft - || ExprHasProperty(p->pLeft, EP_Subquery) ); - }else{ - pNew->pLeft = p->pLeft ? - exprDup(db, p->pLeft, EXPRDUP_REDUCE, &sEdupBuf) : 0; - } - pNew->pRight = p->pRight ? - exprDup(db, p->pRight, EXPRDUP_REDUCE, &sEdupBuf) : 0; - }else{ - if( p->op==TK_SELECT_COLUMN ){ - pNew->pLeft = p->pLeft; - assert( p->pRight==0 - || p->pRight==p->pLeft - || ExprHasProperty(p->pLeft, EP_Subquery) ); - }else{ - pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - } - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); - } - } - } - if( pEdupBuf ) memcpy(pEdupBuf, &sEdupBuf, sizeof(sEdupBuf)); - assert( sEdupBuf.zAlloc <= sEdupBuf.zEnd ); - return pNew; -} - -/* -** Create and return a deep copy of the object passed as the second -** argument. If an OOM condition is encountered, NULL is returned -** and the db->mallocFailed flag set. -*/ -#ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){ - With *pRet = 0; - if( p ){ - sqlite3_int64 nByte = SZ_WITH(p->nCte); - pRet = sqlite3DbMallocZero(db, nByte); - if( pRet ){ - int i; - pRet->nCte = p->nCte; - for(i=0; inCte; i++){ - pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); - pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); - pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); - pRet->a[i].eM10d = p->a[i].eM10d; - } - } - } - return pRet; -} -#else -# define sqlite3WithDup(x,y) 0 -#endif - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** The gatherSelectWindows() procedure and its helper routine -** gatherSelectWindowsCallback() are used to scan all the expressions -** an a newly duplicated SELECT statement and gather all of the Window -** objects found there, assembling them onto the linked list at Select->pWin. -*/ -static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){ - Select *pSelect = pWalker->u.pSelect; - Window *pWin = pExpr->y.pWin; - assert( pWin ); - assert( IsWindowFunc(pExpr) ); - assert( pWin->ppThis==0 ); - sqlite3WindowLink(pSelect, pWin); - } - return WRC_Continue; -} -static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){ - return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune; -} -static void gatherSelectWindows(Select *p){ - Walker w; - w.xExprCallback = gatherSelectWindowsCallback; - w.xSelectCallback = gatherSelectWindowsSelectCallback; - w.xSelectCallback2 = 0; - w.pParse = 0; - w.u.pSelect = p; - sqlite3WalkSelect(&w, p); -} -#endif - - -/* -** The following group of routines make deep copies of expressions, -** expression lists, ID lists, and select statements. The copies can -** be deleted (by being passed to their respective ...Delete() routines) -** without effecting the originals. -** -** The expression list, ID, and source lists return by sqlite3ExprListDup(), -** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded -** by subsequent calls to sqlite*ListAppend() routines. -** -** Any tables that the SrcList might point to are not duplicated. -** -** The flags parameter contains a combination of the EXPRDUP_XXX flags. -** If the EXPRDUP_REDUCE flag is set, then the structure returned is a -** 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 *sqlite3ExprDup(sqlite3 *db, const Expr *p, int flags){ - assert( flags==0 || flags==EXPRDUP_REDUCE ); - return p ? exprDup(db, p, flags, 0) : 0; -} -SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){ - ExprList *pNew; - struct ExprList_item *pItem; - const struct ExprList_item *pOldItem; - int i; - Expr *pPriorSelectColOld = 0; - Expr *pPriorSelectColNew = 0; - assert( db!=0 ); - if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, 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; inExpr; i++, pItem++, pOldItem++){ - Expr *pOldExpr = pOldItem->pExpr; - Expr *pNewExpr; - pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); - if( pOldExpr - && pOldExpr->op==TK_SELECT_COLUMN - && (pNewExpr = pItem->pExpr)!=0 - ){ - if( pNewExpr->pRight ){ - pPriorSelectColOld = pOldExpr->pRight; - pPriorSelectColNew = pNewExpr->pRight; - pNewExpr->pLeft = pNewExpr->pRight; - }else{ - if( pOldExpr->pLeft!=pPriorSelectColOld ){ - pPriorSelectColOld = pOldExpr->pLeft; - pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags); - pNewExpr->pRight = pPriorSelectColNew; - } - pNewExpr->pLeft = pPriorSelectColNew; - } - } - pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName); - pItem->fg = pOldItem->fg; - pItem->u = pOldItem->u; - } - return pNew; -} - -/* -** If cursors, triggers, views and subqueries are all omitted from -** the build, then none of the following routines, except for -** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes -** called with a NULL argument. -*/ -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ - || !defined(SQLITE_OMIT_SUBQUERY) -SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){ - SrcList *pNew; - int i; - assert( db!=0 ); - if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) ); - if( pNew==0 ) return 0; - pNew->nSrc = pNew->nAlloc = p->nSrc; - for(i=0; inSrc; i++){ - SrcItem *pNewItem = &pNew->a[i]; - const SrcItem *pOldItem = &p->a[i]; - Table *pTab; - pNewItem->fg = pOldItem->fg; - if( pOldItem->fg.isSubquery ){ - Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery)); - if( pNewSubq==0 ){ - assert( db->mallocFailed ); - pNewItem->fg.isSubquery = 0; - }else{ - memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq)); - pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags); - if( pNewSubq->pSelect==0 ){ - sqlite3DbFree(db, pNewSubq); - pNewSubq = 0; - pNewItem->fg.isSubquery = 0; - } - } - pNewItem->u4.pSubq = pNewSubq; - }else if( pOldItem->fg.fixedSchema ){ - pNewItem->u4.pSchema = pOldItem->u4.pSchema; - }else{ - pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase); - } - pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); - pNewItem->iCursor = pOldItem->iCursor; - if( pNewItem->fg.isIndexedBy ){ - pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); - }else if( pNewItem->fg.isTabFunc ){ - pNewItem->u1.pFuncArg = - sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); - }else{ - pNewItem->u1.nRow = pOldItem->u1.nRow; - } - pNewItem->u2 = pOldItem->u2; - if( pNewItem->fg.isCte ){ - pNewItem->u2.pCteUse->nUse++; - } - pTab = pNewItem->pSTab = pOldItem->pSTab; - if( pTab ){ - pTab->nTabRef++; - } - if( pOldItem->fg.isUsing ){ - assert( pNewItem->fg.isUsing ); - pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing); - }else{ - pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags); - } - pNewItem->colUsed = pOldItem->colUsed; - } - return pNew; -} -SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ - IdList *pNew; - int i; - assert( db!=0 ); - if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId)); - if( pNew==0 ) return 0; - pNew->nId = p->nId; - for(i=0; inId; i++){ - struct IdList_item *pNewItem = &pNew->a[i]; - const struct IdList_item *pOldItem = &p->a[i]; - pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - } - return pNew; -} -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){ - Select *pRet = 0; - Select *pNext = 0; - Select **pp = &pRet; - const Select *p; - - assert( db!=0 ); - for(p=pDup; p; p=p->pPrior){ - Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); - if( pNew==0 ) break; - pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); - pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); - pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); - pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); - pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); - pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); - pNew->op = p->op; - pNew->pNext = pNext; - pNew->pPrior = 0; - pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); - pNew->iLimit = 0; - pNew->iOffset = 0; - pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral; - pNew->addrOpenEphm[0] = -1; - pNew->addrOpenEphm[1] = -1; - pNew->nSelectRow = p->nSelectRow; - pNew->pWith = sqlite3WithDup(db, p->pWith); -#ifndef SQLITE_OMIT_WINDOWFUNC - pNew->pWin = 0; - pNew->pWinDefn = 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; - sqlite3SelectDelete(db, pNew); - break; - } - *pp = pNew; - pp = &pNew->pPrior; - pNext = pNew; - } - return pRet; -} -#else -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags){ - assert( p==0 ); - return 0; -} -#endif - - -/* -** Add a new element to the end of an expression list. If pList is -** initially NULL, then create a new expression list. -** -** The pList argument must be either NULL or a pointer to an ExprList -** obtained from a prior call to sqlite3ExprListAppend(). -** -** If a memory allocation error occurs, the entire list is freed and -** 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 *sqlite3ExprListAppendNew( - sqlite3 *db, /* Database handle. Used for memory allocation */ - Expr *pExpr /* Expression to be appended. Might be NULL */ -){ - struct ExprList_item *pItem; - ExprList *pList; - - pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4)); - if( pList==0 ){ - 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 *sqlite3ExprListAppendGrow( - 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 = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc)); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pList); - sqlite3ExprDelete(db, pExpr); - return 0; - }else{ - pList = pNew; - } - pItem = &pList->a[pList->nExpr++]; - *pItem = zeroItem; - pItem->pExpr = pExpr; - return pList; -} -SQLITE_PRIVATE ExprList *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; - if( pList==0 ){ - return sqlite3ExprListAppendNew(pParse->db,pExpr); - } - if( pList->nAllocnExpr+1 ){ - return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr); - } - pItem = &pList->a[pList->nExpr++]; - *pItem = zeroItem; - pItem->pExpr = pExpr; - return pList; -} - -/* -** pColumns and pExpr form a vector assignment which is part of the SET -** clause of an UPDATE statement. Like this: -** -** (a,b,c) = (expr1,expr2,expr3) -** Or: (a,b,c) = (SELECT x,y,z FROM ....) -** -** For each term of the vector assignment, append new entries to the -** expression list pList. In the case of a subquery on the RHS, append -** TK_SELECT_COLUMN expressions. -*/ -SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to append. Might be NULL */ - IdList *pColumns, /* List of names of LHS of the assignment */ - Expr *pExpr /* Vector expression to be appended. Might be NULL */ -){ - sqlite3 *db = pParse->db; - int n; - int i; - int iFirst = pList ? pList->nExpr : 0; - /* pColumns can only be NULL due to an OOM but an OOM will cause an - ** exit prior to this routine being invoked */ - if( NEVER(pColumns==0) ) goto vector_append_error; - if( pExpr==0 ) goto vector_append_error; - - /* If the RHS is a vector, then we can immediately check to see that - ** the size of the RHS and LHS match. But if the RHS is a SELECT, - ** wildcards ("*") in the result set of the SELECT must be expanded before - ** we can do the size check, so defer the size check until code generation. - */ - if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){ - sqlite3ErrorMsg(pParse, "%d columns assigned %d values", - pColumns->nId, n); - goto vector_append_error; - } - - for(i=0; inId; i++){ - Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId); - assert( pSubExpr!=0 || db->mallocFailed ); - if( pSubExpr==0 ) continue; - pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); - if( pList ){ - assert( pList->nExpr==iFirst+i+1 ); - pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName; - pColumns->a[i].zName = 0; - } - } - - if( !db->mallocFailed && pExpr->op==TK_SELECT && ALWAYS(pList!=0) ){ - Expr *pFirst = pList->a[iFirst].pExpr; - assert( pFirst!=0 ); - assert( pFirst->op==TK_SELECT_COLUMN ); - - /* Store the SELECT statement in pRight so it will be deleted when - ** sqlite3ExprListDelete() is called */ - pFirst->pRight = pExpr; - pExpr = 0; - - /* Remember the size of the LHS in iTable so that we can check that - ** the RHS and LHS sizes match during code generation. */ - pFirst->iTable = pColumns->nId; - } - -vector_append_error: - sqlite3ExprUnmapAndDelete(pParse, pExpr); - sqlite3IdListDelete(db, pColumns); - return pList; -} - -/* -** Set the sort order for the last element on the given ExprList. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ - struct ExprList_item *pItem; - if( p==0 ) return; - assert( p->nExpr>0 ); - - assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 ); - assert( iSortOrder==SQLITE_SO_UNDEFINED - || iSortOrder==SQLITE_SO_ASC - || iSortOrder==SQLITE_SO_DESC - ); - assert( eNulls==SQLITE_SO_UNDEFINED - || eNulls==SQLITE_SO_ASC - || eNulls==SQLITE_SO_DESC - ); - - pItem = &p->a[p->nExpr-1]; - assert( pItem->fg.bNulls==0 ); - if( iSortOrder==SQLITE_SO_UNDEFINED ){ - iSortOrder = SQLITE_SO_ASC; - } - pItem->fg.sortFlags = (u8)iSortOrder; - - if( eNulls!=SQLITE_SO_UNDEFINED ){ - pItem->fg.bNulls = 1; - if( iSortOrder!=eNulls ){ - pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL; - } - } -} - -/* -** Set the ExprList.a[].zEName element of the most recently added item -** on the expression list. -** -** pList might be NULL following an OOM error. But pName should never be -** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag -** is set. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetName( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to add the span. */ - const Token *pName, /* Name to be added */ - int dequote /* True to cause the name to be dequoted */ -){ - assert( pList!=0 || pParse->db->mallocFailed!=0 ); - assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 ); - if( pList ){ - struct ExprList_item *pItem; - assert( pList->nExpr>0 ); - pItem = &pList->a[pList->nExpr-1]; - assert( pItem->zEName==0 ); - assert( pItem->fg.eEName==ENAME_NAME ); - pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); - if( dequote ){ - /* If dequote==0, then pName->z does not point to part of a DDL - ** statement handled by the parser. And so no token need be added - ** to the token-map. */ - sqlite3Dequote(pItem->zEName); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (const void*)pItem->zEName, pName); - } - } - } -} - -/* -** Set the ExprList.a[].zSpan element of the most recently added item -** on the expression list. -** -** pList might be NULL following an OOM error. But pSpan should never be -** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag -** is set. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetSpan( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to add the span. */ - const char *zStart, /* Start of the span */ - const char *zEnd /* End of the span */ -){ - sqlite3 *db = pParse->db; - assert( pList!=0 || db->mallocFailed!=0 ); - if( pList ){ - struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; - assert( pList->nExpr>0 ); - if( pItem->zEName==0 ){ - pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd); - pItem->fg.eEName = ENAME_SPAN; - } - } -} - -/* -** If the expression list pEList contains more than iLimit elements, -** leave an error message in pParse. -*/ -SQLITE_PRIVATE void sqlite3ExprListCheckLength( - Parse *pParse, - ExprList *pEList, - const char *zObject -){ - int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; - testcase( pEList && pEList->nExpr==mx ); - testcase( pEList && pEList->nExpr==mx+1 ); - if( pEList && pEList->nExpr>mx ){ - sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); - } -} - -/* -** Delete an entire expression list. -*/ -static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){ - int i = pList->nExpr; - struct ExprList_item *pItem = pList->a; - assert( pList->nExpr>0 ); - assert( db!=0 ); - do{ - sqlite3ExprDelete(db, pItem->pExpr); - if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName); - pItem++; - }while( --i>0 ); - sqlite3DbNNFreeNN(db, pList); -} -SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ - if( pList ) exprListDeleteNN(db, pList); -} -SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){ - if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList); -} - -/* -** Return the bitwise-OR of all Expr.flags fields in the given -** ExprList. -*/ -SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ - int i; - u32 m = 0; - assert( pList!=0 ); - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - assert( pExpr!=0 ); - m |= pExpr->flags; - } - return m; -} - -/* -** This is a SELECT-node callback for the expression walker that -** always "fails". By "fail" in this case, we mean set -** pWalker->eCode to zero and abort. -** -** This callback is used by multiple expression walkers. -*/ -SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){ - UNUSED_PARAMETER(NotUsed); - pWalker->eCode = 0; - return WRC_Abort; -} - -/* -** Check the input string to see if it is "true" or "false" (in any case). -** -** If the string is.... Return -** "true" EP_IsTrue -** "false" EP_IsFalse -** anything else 0 -*/ -SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char *zIn){ - if( sqlite3StrICmp(zIn, "true")==0 ) return EP_IsTrue; - if( sqlite3StrICmp(zIn, "false")==0 ) return EP_IsFalse; - return 0; -} - - -/* -** If the input expression is an ID with the name "true" or "false" -** then convert it into an TK_TRUEFALSE term. Return non-zero if -** the conversion happened, and zero if the expression is unaltered. -*/ -SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ - u32 v; - assert( pExpr->op==TK_ID || pExpr->op==TK_STRING ); - if( !ExprHasProperty(pExpr, EP_Quoted|EP_IntValue) - && (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0 - ){ - pExpr->op = TK_TRUEFALSE; - ExprSetProperty(pExpr, v); - return 1; - } - return 0; -} - -/* -** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE -** and 0 if it is FALSE. -*/ -SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ - pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); - assert( pExpr->op==TK_TRUEFALSE ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 - || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); - return pExpr->u.zToken[4]==0; -} - -/* -** If pExpr is an AND or OR expression, try to simplify it by eliminating -** terms that are always true or false. Return the simplified expression. -** Or return the original expression if no simplification is possible. -** -** Examples: -** -** (x<10) AND true => (x<10) -** (x<10) AND false => false -** (x<10) AND (y=22 OR false) => (x<10) AND (y=22) -** (x<10) AND (y=22 OR true) => (x<10) -** (y=22) OR true => true -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ - assert( pExpr!=0 ); - if( pExpr->op==TK_AND || pExpr->op==TK_OR ){ - Expr *pRight = sqlite3ExprSimplifiedAndOr(pExpr->pRight); - Expr *pLeft = sqlite3ExprSimplifiedAndOr(pExpr->pLeft); - if( ExprAlwaysTrue(pLeft) || ExprAlwaysFalse(pRight) ){ - pExpr = pExpr->op==TK_AND ? pRight : pLeft; - }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){ - pExpr = pExpr->op==TK_AND ? pLeft : pRight; - } - } - return pExpr; -} - -/* -** pExpr is a TK_FUNCTION node. Try to determine whether or not the -** function is a constant function. A function is constant if all of -** the following are true: -** -** (1) It is a scalar function (not an aggregate or window function) -** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG -** property. -** (3) All of its arguments are constants -** -** This routine sets pWalker->eCode to 0 if pExpr is not a constant. -** It makes no changes to pWalker->eCode if pExpr is constant. In -** every case, it returns WRC_Abort. -** -** Called as a service subroutine from exprNodeIsConstant(). -*/ -static SQLITE_NOINLINE int exprNodeIsConstantFunction( - Walker *pWalker, - Expr *pExpr -){ - int n; /* Number of arguments */ - ExprList *pList; /* List of arguments */ - FuncDef *pDef; /* The function */ - sqlite3 *db; /* The database */ - - assert( pExpr->op==TK_FUNCTION ); - if( ExprHasProperty(pExpr, EP_TokenOnly) - || (pList = pExpr->x.pList)==0 - ){; - n = 0; - }else{ - n = pList->nExpr; - sqlite3WalkExprList(pWalker, pList); - if( pWalker->eCode==0 ) return WRC_Abort; - } - db = pWalker->pParse->db; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( pDef==0 - || pDef->xFinalize!=0 - || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || ExprHasProperty(pExpr, EP_WinFunc) - ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Prune; -} - - -/* -** These routines are Walker callbacks used to check expressions to -** see if they are "constant" for some definition of constant. The -** Walker.eCode value determines the type of "constant" we are looking -** for. -** -** These callback routines are used to implement the following: -** -** sqlite3ExprIsConstant() pWalker->eCode==1 -** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2 -** sqlite3ExprIsTableConstant() pWalker->eCode==3 -** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5 -** -** In all cases, the callbacks set Walker.eCode=0 and abort if the expression -** is found to not be a constant. -** -** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT -** expressions in a CREATE TABLE statement. The Walker.eCode value is 5 -** when parsing an existing schema out of the sqlite_schema table and 4 -** when processing a new CREATE TABLE statement. A bound parameter raises -** an error for new statements, but is silently converted -** to NULL for existing schemas. This allows sqlite_schema tables that -** contain a bound parameter because they were generated by older versions -** of SQLite to be parsed by newer versions of SQLite without raising a -** malformed schema error. -*/ -static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ - assert( pWalker->eCode>0 ); - - /* If pWalker->eCode is 2 then any term of the expression that comes from - ** the ON or USING clauses of an outer join disqualifies the expression - ** from being considered constant. */ - if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){ - pWalker->eCode = 0; - return WRC_Abort; - } - - switch( pExpr->op ){ - /* Consider functions to be constant if all their arguments are constant - ** and either pWalker->eCode==4 or 5 or the function has the - ** SQLITE_FUNC_CONST flag. */ - case TK_FUNCTION: - if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc)) - && !ExprHasProperty(pExpr, EP_WinFunc) - ){ - if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); - return WRC_Continue; - }else if( pWalker->pParse ){ - return exprNodeIsConstantFunction(pWalker, pExpr); - }else{ - pWalker->eCode = 0; - return WRC_Abort; - } - case TK_ID: - /* Convert "true" or "false" in a DEFAULT clause into the - ** appropriate TK_TRUEFALSE operator */ - if( sqlite3ExprIdToTrueFalse(pExpr) ){ - return WRC_Prune; - } - /* no break */ deliberate_fall_through - case TK_COLUMN: - case TK_AGG_FUNCTION: - case TK_AGG_COLUMN: - testcase( pExpr->op==TK_ID ); - testcase( pExpr->op==TK_COLUMN ); - testcase( pExpr->op==TK_AGG_FUNCTION ); - testcase( pExpr->op==TK_AGG_COLUMN ); - if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){ - return WRC_Continue; - } - if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ - return WRC_Continue; - } - /* no break */ deliberate_fall_through - case TK_IF_NULL_ROW: - case TK_REGISTER: - case TK_DOT: - case TK_RAISE: - testcase( pExpr->op==TK_REGISTER ); - testcase( pExpr->op==TK_IF_NULL_ROW ); - testcase( pExpr->op==TK_DOT ); - testcase( pExpr->op==TK_RAISE ); - pWalker->eCode = 0; - return WRC_Abort; - case TK_VARIABLE: - if( pWalker->eCode==5 ){ - /* Silently convert bound parameters that appear inside of CREATE - ** statements into a NULL when parsing the CREATE statement text out - ** of the sqlite_schema table */ - pExpr->op = TK_NULL; - }else if( pWalker->eCode==4 ){ - /* A bound parameter in a CREATE statement that originates from - ** sqlite3_prepare() causes an error */ - pWalker->eCode = 0; - return WRC_Abort; - } - /* no break */ deliberate_fall_through - default: - testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ - testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ - return WRC_Continue; - } -} -static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ - Walker w; - w.eCode = initFlag; - w.pParse = pParse; - w.xExprCallback = exprNodeIsConstant; - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - sqlite3WalkExpr(&w, p); - return w.eCode; -} - -/* -** Walk an expression tree. Return non-zero if the expression is constant -** and 0 if it involves variables or function calls. -** -** For the purposes of this function, a double-quoted string (ex: "abc") -** is considered a variable but a single-quoted string (ex: 'abc') is -** a constant. -** -** The pParse parameter may be NULL. But if it is NULL, there is no way -** to determine if function calls are constant or not, and hence all -** function calls will be considered to be non-constant. If pParse is -** not NULL, then a function call might be constant, depending on the -** function and on its parameters. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 1); -} - -/* -** Walk an expression tree. Return non-zero if -** -** (1) the expression is constant, and -** (2) the expression does originate in the ON or USING clause -** of a LEFT JOIN, and -** (3) the expression does not contain any EP_FixedCol TK_COLUMN -** operands created by the constant propagation optimization. -** -** When this routine returns true, it indicates that the expression -** can be added to the pParse->pConstExpr list and evaluated once when -** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). -*/ -static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 2); -} - -/* -** This routine examines sub-SELECT statements as an expression is being -** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered -** constant as long as they are uncorrelated - meaning that they do not -** contain any terms from outer contexts. -*/ -static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){ - assert( pSelect!=0 ); - assert( pWalker->eCode==3 || pWalker->eCode==0 ); - if( (pSelect->selFlags & SF_Correlated)!=0 ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Prune; -} - -/* -** Walk an expression tree. Return non-zero if the expression is constant -** for any single row of the table with cursor iCur. In other words, the -** expression must not refer to any non-deterministic function nor any -** table other than iCur. -** -** Consider uncorrelated subqueries to be constants if the bAllowSubq -** parameter is true. -*/ -static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){ - Walker w; - w.eCode = 3; - w.pParse = 0; - w.xExprCallback = exprNodeIsConstant; - if( bAllowSubq ){ - w.xSelectCallback = exprSelectWalkTableConstant; - }else{ - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - } - w.u.iCur = iCur; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - -/* -** Check pExpr to see if it is an constraint on the single data source -** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr -** constrains pSrc but does not depend on any other tables or data -** sources anywhere else in the query. Return true (non-zero) if pExpr -** is a constraint on pSrc only. -** -** 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 single-source constraint, the following must be true: -** -** (1) pExpr cannot refer to any table other than pSrc->iCursor. -** -** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is -** true and the subquery is non-correlated -** -** (2b) pExpr cannot use 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 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. -** -** (6) Either: -** -** (6a) pExpr does not originate in an ON or USING clause, or -** -** (6b) The ON or USING clause from which pExpr is derived is -** not to the left of a RIGHT JOIN (or FULL JOIN). -** -** Without this restriction, accepting pExpr as a single-table -** constraint might move the the ON/USING filter expression -** from the left side of a RIGHT JOIN over to the right side, -** which leads to incorrect answers. See also restriction (9) -** on push-down. -*/ -SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( - Expr *pExpr, /* The constraint */ - const SrcList *pSrcList, /* Complete FROM clause */ - int iSrc, /* Which element of pSrcList to use */ - int bAllowSubq /* Allow non-correlated subqueries */ -){ - const SrcItem *pSrc = &pSrcList->a[iSrc]; - 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) */ - } - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) /* (6a) */ - && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (6b) */ - ){ - int jj; - for(jj=0; jjw.iJoin==pSrcList->a[jj].iCursor ){ - if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ - return 0; /* restriction (6) */ - } - break; - } - } - } - /* Rules (1), (2a), and (2b) handled by the following: */ - return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq); -} - - -/* -** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy(). -*/ -static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){ - ExprList *pGroupBy = pWalker->u.pGroupBy; - int i; - - /* Check if pExpr is identical to any GROUP BY term. If so, consider - ** it constant. */ - for(i=0; inExpr; i++){ - Expr *p = pGroupBy->a[i].pExpr; - if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){ - CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p); - if( sqlite3IsBinary(pColl) ){ - return WRC_Prune; - } - } - } - - /* Check if pExpr is a sub-select. If so, consider it variable. */ - if( ExprUseXSelect(pExpr) ){ - pWalker->eCode = 0; - return WRC_Abort; - } - - return exprNodeIsConstant(pWalker, pExpr); -} - -/* -** Walk the expression tree passed as the first argument. Return non-zero -** if the expression consists entirely of constants or copies of terms -** in pGroupBy that sort with the BINARY collation sequence. -** -** This routine is used to determine if a term of the HAVING clause can -** be promoted into the WHERE clause. In order for such a promotion to work, -** the value of the HAVING clause term must be the same for all members of -** a "group". The requirement that the GROUP BY term must be BINARY -** assumes that no other collating sequence will have a finer-grained -** grouping than binary. In other words (A=B COLLATE binary) implies -** A=B in every other collating sequence. The requirement that the -** GROUP BY be BINARY is stricter than necessary. It would also work -** to promote HAVING clauses that use the same alternative collating -** sequence as the GROUP BY term, but that is much harder to check, -** alternative collating sequences are uncommon, and this is only an -** optimization, so we take the easy way out and simply require the -** GROUP BY to use the BINARY collating sequence. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){ - Walker w; - w.eCode = 1; - w.xExprCallback = exprNodeIsConstantOrGroupBy; - w.xSelectCallback = 0; - w.u.pGroupBy = pGroupBy; - w.pParse = pParse; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - -/* -** Walk an expression tree for the DEFAULT field of a column definition -** in a CREATE TABLE statement. Return non-zero if the expression is -** acceptable for use as a DEFAULT. That is to say, return non-zero if -** the expression is constant or a function call with constant arguments. -** Return and 0 if there are any variables. -** -** isInit is true when parsing from sqlite_schema. isInit is false when -** processing a new CREATE TABLE statement. When isInit is true, parameters -** (such as ? or $abc) in the expression are converted into NULL. When -** isInit is false, parameters raise an error. Parameters should not be -** allowed in a CREATE TABLE statement, but some legacy versions of SQLite -** allowed it, so we need to support it when reading sqlite_schema for -** backwards compatibility. -** -** If isInit is true, set EP_FromDDL on every TK_FUNCTION node. -** -** For the purposes of this function, a double-quoted string (ex: "abc") -** is considered a variable but a single-quoted string (ex: 'abc') is -** a constant. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ - assert( isInit==0 || isInit==1 ); - return exprIsConst(0, p, 4+isInit); -} - -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Walk an expression tree. Return 1 if the expression contains a -** subquery of some kind. Return 0 if there are no subqueries. -*/ -SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){ - Walker w; - w.eCode = 1; - w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - sqlite3WalkExpr(&w, p); - return w.eCode==0; -} -#endif - -/* -** If the expression p codes a constant integer that is small enough -** to fit in a 32-bit integer, return 1 and put the value of the integer -** 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. -** -** If the pParse pointer is provided, then allow the expression p to be -** a parameter (TK_VARIABLE) that is bound to an integer. -** But if pParse is NULL, then p must be a pure integer literal. -*/ -SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ - int rc = 0; - if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */ - - /* If an expression is an integer literal that fits in a signed 32-bit - ** integer, then the EP_IntValue flag will have already been set */ - assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0 - || sqlite3GetInt32(p->u.zToken, &rc)==0 ); - - if( p->flags & EP_IntValue ){ - *pValue = p->u.iValue; - return 1; - } - switch( p->op ){ - case TK_UPLUS: { - rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0); - break; - } - case TK_UMINUS: { - int v = 0; - if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){ - assert( ((unsigned int)v)!=0x80000000 ); - *pValue = -v; - rc = 1; - } - break; - } - case TK_VARIABLE: { - sqlite3_value *pVal; - if( pParse==0 ) break; - if( NEVER(pParse->pVdbe==0) ) break; - if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break; - sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn); - pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn, - SQLITE_AFF_BLOB); - if( pVal ){ - if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){ - sqlite3_int64 vv = sqlite3_value_int64(pVal); - if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */ - *pValue = (int)vv; - rc = 1; - } - } - sqlite3ValueFree(pVal); - } - break; - } - default: break; - } - return rc; -} - -/* -** Return FALSE if there is no chance that the expression can be NULL. -** -** If the expression might be NULL or if the expression is too complex -** to tell return TRUE. -** -** This routine is used as an optimization, to skip OP_IsNull opcodes -** when we know that a value cannot be NULL. Hence, a false positive -** (returning TRUE when in fact the expression can never be NULL) might -** be a small performance hit but is otherwise harmless. On the other -** hand, a false negative (returning FALSE when the result could be NULL) -** will likely result in an incorrect answer. So when in doubt, return -** TRUE. -*/ -SQLITE_PRIVATE int 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; - switch( op ){ - case TK_INTEGER: - case TK_STRING: - case TK_FLOAT: - case TK_BLOB: - return 0; - case TK_COLUMN: - assert( ExprUseYTab(p) ); - return ExprHasProperty(p, EP_CanBeNull) - || NEVER(p->y.pTab==0) /* Reference to column of index on expr */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - || (p->iColumn==XN_ROWID && IsView(p->y.pTab)) -#endif - || (p->iColumn>=0 - && p->y.pTab->aCol!=0 /* Possible due to prior error */ - && ALWAYS(p->iColumny.pTab->nCol) - && p->y.pTab->aCol[p->iColumn].notNull==0); - default: - return 1; - } -} - -/* -** Return TRUE if the given expression is a constant which would be -** unchanged by OP_Affinity with the affinity given in the second -** argument. -** -** This routine is used to determine if the OP_Affinity operation -** can be omitted. When in doubt return FALSE. A false negative -** is harmless. A false positive, however, can result in the wrong -** answer. -*/ -SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ - u8 op; - int unaryMinus = 0; - if( aff==SQLITE_AFF_BLOB ) return 1; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ - if( p->op==TK_UMINUS ) unaryMinus = 1; - p = p->pLeft; - } - op = p->op; - if( op==TK_REGISTER ) op = p->op2; - switch( op ){ - case TK_INTEGER: { - return aff>=SQLITE_AFF_NUMERIC; - } - case TK_FLOAT: { - return aff>=SQLITE_AFF_NUMERIC; - } - case TK_STRING: { - return !unaryMinus && aff==SQLITE_AFF_TEXT; - } - case TK_BLOB: { - return !unaryMinus; - } - case TK_COLUMN: { - assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ - return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0; - } - default: { - return 0; - } - } -} - -/* -** Return TRUE if the given string is a row-id column name. -*/ -SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ - if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; - if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; - if( sqlite3StrICmp(z, "OID")==0 ) return 1; - return 0; -} - -/* -** Return a pointer to a buffer containing a usable rowid alias for table -** pTab. An alias is usable if there is not an explicit user-defined column -** of the same name. -*/ -SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){ - const char *azOpt[] = {"_ROWID_", "ROWID", "OID"}; - int ii; - assert( VisibleRowid(pTab) ); - for(ii=0; iix.pSelect; - if( p->pPrior ) return 0; /* Not a compound SELECT */ - if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); - return 0; /* No DISTINCT keyword and no aggregate functions */ - } - assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ - if( p->pLimit ) return 0; /* Has no LIMIT clause */ - if( p->pWhere ) return 0; /* Has no WHERE clause */ - pSrc = p->pSrc; - assert( pSrc!=0 ); - if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ - if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */ - pTab = pSrc->a[0].pSTab; - assert( pTab!=0 ); - 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 ); - /* All SELECT results must be columns. */ - for(i=0; inExpr; i++){ - Expr *pRes = pEList->a[i].pExpr; - if( pRes->op!=TK_COLUMN ) return 0; - assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ - } - return p; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code that checks the left-most column of index table iCur to see if -** it contains any NULL entries. Cause the register at regHasNull to be set -** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull -** to be set to NULL if iCur contains one or more NULL values. -*/ -static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ - int addr1; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull); - addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull); - sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); - VdbeComment((v, "first_entry_in(%d)", iCur)); - sqlite3VdbeJumpHere(v, addr1); -} -#endif - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** The argument is an IN operator with a list (not a subquery) on the -** right-hand side. Return TRUE if that list is constant. -*/ -static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){ - Expr *pLHS; - int res; - assert( !ExprHasProperty(pIn, EP_xIsSelect) ); - pLHS = pIn->pLeft; - pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pParse, pIn); - pIn->pLeft = pLHS; - return res; -} -#endif - -/* -** This function is used by the implementation of the IN (...) operator. -** The pX parameter is the expression on the RHS of the IN operator, which -** might be either a list of expressions or a subquery. -** -** The job of this routine is to find or create a b-tree object that can -** be used either to test for membership in the RHS set or to iterate through -** all members of the RHS set, skipping duplicates. -** -** A cursor is opened on the b-tree object that is the RHS of the IN operator -** 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: -** -** IN_INDEX_ROWID - The cursor was opened on a database table. -** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. -** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. -** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated ephemeral table. -** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be -** implemented as a sequence of comparisons. -** -** An existing b-tree might be used if the RHS expression pX is a simple -** subquery such as: -** -** SELECT , ... FROM -** -** 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. In this case, the creation and initialization of the -** ephemeral 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 -** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast -** membership test. When the IN_INDEX_LOOP bit is set, the IN index will -** be used to loop over all values of the RHS of the IN operator. -** -** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate -** through the set members) then the b-tree must not contain duplicates. -** An ephemeral table will be created unless the selected columns are guaranteed -** to be unique - either because it is an INTEGER PRIMARY KEY or due to -** a UNIQUE constraint or index. -** -** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used -** for fast set membership tests) then an ephemeral table must -** be used unless is a single INTEGER PRIMARY KEY column or an -** index can be found with the specified as its left-most. -** -** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and -** if the RHS of the IN operator is a list (not a subquery) then this -** routine might decide that creating an ephemeral b-tree for membership -** testing is too expensive and return IN_INDEX_NOOP. In that case, the -** calling routine should implement the IN operator using a sequence -** of Eq or Ne comparison operations. -** -** When the b-tree is being used for membership tests, the calling function -** might need to know whether or not the RHS side of the IN operator -** contains a NULL. If prRhsHasNull is not a NULL pointer and -** if there is any chance that the (...) might contain a NULL value at -** runtime, then a register is allocated and the register number written -** to *prRhsHasNull. If there is no chance that the (...) contains a -** NULL value, then *prRhsHasNull is left unchanged. -** -** If a register is allocated and its location stored in *prRhsHasNull, then -** the value in that register will be NULL if the b-tree contains one or more -** NULL values, and it will be some non-NULL value if the b-tree contains no -** NULL values. -** -** If the aiMap parameter is not NULL, it must point to an array containing -** one element for each column returned by the SELECT statement on the RHS -** of the IN(...) operator. The i'th entry of the array is populated with the -** offset of the index column that matches the i'th column returned by the -** SELECT. For example, if the expression and selected index are: -** -** (?,?,?) IN (SELECT a, b, c FROM t1) -** CREATE INDEX i1 ON t1(b, c, a); -** -** then aiMap[] is populated with {2, 0, 1}. -*/ -#ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3FindInIndex( - Parse *pParse, /* Parsing context */ - Expr *pX, /* The IN expression */ - u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ - int *prRhsHasNull, /* Register holding NULL status. See notes */ - int *aiMap, /* Mapping from Index fields to RHS fields */ - int *piTab /* OUT: index to use */ -){ - Select *p; /* SELECT to the right of IN operator */ - int eType = 0; /* Type of RHS table. IN_INDEX_* */ - int iTab; /* Cursor of the RHS table */ - int mustBeUnique; /* True if RHS must be unique */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - - assert( pX->op==TK_IN ); - mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; - 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 && ExprUseXSelect(pX) ){ - int i; - ExprList *pEList = pX->x.pSelect->pEList; - for(i=0; inExpr; i++){ - if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; - } - if( i==pEList->nExpr ){ - prRhsHasNull = 0; - } - } - - /* Check to see if an existing table or index can be used to - ** satisfy the query. This is preferable to generating a new - ** ephemeral table. */ - if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ - sqlite3 *db = pParse->db; /* Database connection */ - Table *pTab; /* Table
    . */ - int iDb; /* Database idx for pTab */ - ExprList *pEList = p->pEList; - int nExpr = pEList->nExpr; - - assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ - pTab = p->pSrc->a[0].pSTab; - - /* Code an OP_Transaction and OP_TableLock for
    . */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 && iDbtnum, 0, pTab->zName); - - assert(v); /* sqlite3GetVdbe() has always been previously called */ - if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ - /* The "x IN (SELECT rowid FROM table)" case */ - int iAddr = sqlite3VdbeAddOp0(v, OP_Once); - VdbeCoverage(v); - - sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - eType = IN_INDEX_ROWID; - ExplainQueryPlan((pParse, 0, - "USING ROWID SEARCH ON TABLE %s FOR IN-OPERATOR",pTab->zName)); - sqlite3VdbeJumpHere(v, iAddr); - }else{ - Index *pIdx; /* Iterator variable */ - int affinity_ok = 1; - int i; - - /* Check that the affinity that will be used to perform each - ** comparison is the same as the affinity of each column in table - ** on the RHS of the IN operator. If it not, it is not possible to - ** use any index of the RHS table. */ - for(i=0; ipLeft, i); - int iCol = pEList->a[i].pExpr->iColumn; - char idxaff = sqlite3TableColumnAffinity(pTab,iCol); /* RHS table */ - char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); - testcase( cmpaff==SQLITE_AFF_BLOB ); - testcase( cmpaff==SQLITE_AFF_TEXT ); - switch( cmpaff ){ - case SQLITE_AFF_BLOB: - break; - case SQLITE_AFF_TEXT: - /* sqlite3CompareAffinity() only returns TEXT if one side or the - ** other has no affinity and the other side is TEXT. Hence, - ** the only way for cmpaff to be TEXT is for idxaff to be TEXT - ** and for the term on the LHS of the IN to have no affinity. */ - assert( idxaff==SQLITE_AFF_TEXT ); - break; - default: - affinity_ok = sqlite3IsNumericAffinity(idxaff); - } - } - - if( affinity_ok ){ - /* Search for an existing index that will work for this IN operator */ - for(pIdx=pTab->pIndex; pIdx && eType==0; pIdx=pIdx->pNext){ - Bitmask colUsed; /* Columns of the index used */ - Bitmask mCol; /* Mask for the current column */ - if( pIdx->nColumnpPartIdxWhere!=0 ) continue; - /* Maximum nColumn is BMS-2, not BMS-1, so that we can compute - ** BITMASK(nExpr) without overflowing */ - testcase( pIdx->nColumn==BMS-2 ); - testcase( pIdx->nColumn==BMS-1 ); - if( pIdx->nColumn>=BMS-1 ) continue; - if( mustBeUnique ){ - if( pIdx->nKeyCol>nExpr - ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx)) - ){ - continue; /* This index is not unique over the IN RHS columns */ - } - } - - colUsed = 0; /* Columns of index used so far */ - for(i=0; ipLeft, i); - Expr *pRhs = pEList->a[i].pExpr; - CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); - int j; - - for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; - assert( pIdx->azColl[j] ); - if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ - continue; - } - break; - } - if( j==nExpr ) break; - mCol = MASKBIT(j); - if( mCol & colUsed ) break; /* Each column used only once */ - colUsed |= mCol; - if( aiMap ) aiMap[i] = j; - } - - assert( nExpr>0 && nExprzName)); - sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); - eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - - if( prRhsHasNull ){ -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - i64 mask = (1<nMem; - if( nExpr==1 ){ - sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); - } - } - sqlite3VdbeJumpHere(v, iAddr); - } - } /* End loop over indexes */ - } /* End if( affinity_ok ) */ - } /* End if not an rowid index */ - } /* End attempt to optimize using an index */ - - /* If no preexisting index is available for the IN clause - ** and IN_INDEX_NOOP is an allowed reply - ** and the RHS of the IN operator is a list, not a subquery - ** and the RHS is not constant or has two or fewer terms, - ** then it is not worth creating an ephemeral table to evaluate - ** the IN operator so return IN_INDEX_NOOP. - */ - if( eType==0 - && (inFlags & IN_INDEX_NOOP_OK) - && ExprUseXList(pX) - && (!sqlite3InRhsIsConstant(pParse,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; - } - - if( eType==0 ){ - /* Could not find an existing table or index to use as the RHS b-tree. - ** We will have to generate an ephemeral table to do the job. - */ - u32 savedNQueryLoop = pParse->nQueryLoop; - int rMayHaveNull = 0; - eType = IN_INDEX_EPH; - if( inFlags & IN_INDEX_LOOP ){ - pParse->nQueryLoop = 0; - }else if( prRhsHasNull ){ - *prRhsHasNull = rMayHaveNull = ++pParse->nMem; - } - assert( pX->op==TK_IN ); - sqlite3CodeRhsOfIN(pParse, pX, iTab); - if( rMayHaveNull ){ - sqlite3SetHasNullFlag(v, iTab, rMayHaveNull); - } - pParse->nQueryLoop = savedNQueryLoop; - } - - if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){ - int i, n; - n = sqlite3ExprVectorSize(pX->pLeft); - for(i=0; ipLeft; - int nVal = sqlite3ExprVectorSize(pLeft); - Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0; - char *zRet; - - assert( pExpr->op==TK_IN ); - zRet = sqlite3DbMallocRaw(pParse->db, 1+(i64)nVal); - if( zRet ){ - int i; - for(i=0; ipEList->a[i].pExpr, a); - }else{ - zRet[i] = a; - } - } - zRet[nVal] = '\0'; - } - return zRet; -} -#endif - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Load the Parse object passed as the first argument with an error -** message of the form: -** -** "sub-select returns N columns - expected M" -*/ -SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){ - if( pParse->nErr==0 ){ - const char *zFmt = "sub-select returns %d columns - expected %d"; - sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect); - } -} -#endif - -/* -** Expression pExpr is a vector that has been used in a context where -** it is not permitted. If pExpr is a sub-select vector, this routine -** loads the Parse object with a message of the form: -** -** "sub-select returns N columns - expected 1" -** -** Or, if it is a regular scalar vector: -** -** "row value misused" -*/ -SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ -#ifndef SQLITE_OMIT_SUBQUERY - if( ExprUseXSelect(pExpr) ){ - sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); - }else -#endif - { - sqlite3ErrorMsg(pParse, "row value misused"); - } -} - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Scan all previously generated bytecode looking for an OP_BeginSubrtn -** that is compatible with pExpr. If found, add the y.sub values -** to pExpr and return true. If not found, return false. -*/ -static int findCompatibleInRhsSubrtn( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* IN operator with RHS that we want to reuse */ - SubrtnSig *pNewSig /* Signature for the IN operator */ -){ - VdbeOp *pOp, *pEnd; - SubrtnSig *pSig; - Vdbe *v; - - if( pNewSig==0 ) return 0; - if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0; - assert( pExpr->op==TK_IN ); - assert( !ExprUseYSub(pExpr) ); - assert( ExprUseXSelect(pExpr) ); - assert( pExpr->x.pSelect!=0 ); - assert( (pExpr->x.pSelect->selFlags & SF_All)==0 ); - v = pParse->pVdbe; - assert( v!=0 ); - pOp = sqlite3VdbeGetOp(v, 1); - pEnd = sqlite3VdbeGetLastOp(v); - for(; pOpp4type!=P4_SUBRTNSIG ) continue; - assert( pOp->opcode==OP_BeginSubrtn ); - pSig = pOp->p4.pSubrtnSig; - assert( pSig!=0 ); - if( !pSig->bComplete ) continue; - if( pNewSig->selId!=pSig->selId ) continue; - if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue; - pExpr->y.sub.iAddr = pSig->iAddr; - pExpr->y.sub.regReturn = pSig->regReturn; - pExpr->iTable = pSig->iTable; - ExprSetProperty(pExpr, EP_Subrtn); - return 1; - } - return 0; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code that will construct an ephemeral table containing all terms -** in the RHS of an IN operator. The IN operator can be in either of two -** forms: -** -** x IN (4,5,11) -- IN operator with list on right-hand side -** x IN (SELECT a FROM b) -- IN operator with subquery on the right -** -** The pExpr parameter is the IN operator. The cursor number for the -** constructed ephemeral table is returned. The first time the ephemeral -** table is computed, the cursor number is also stored in pExpr->iTable, -** however the cursor number returned might not be the same, as it might -** have been duplicated using OP_OpenDup. -** -** If the LHS expression ("x" in the examples) is a column value, or -** the SELECT statement returns a column value, then the affinity of that -** column is used to build the index keys. If both 'x' and the -** SELECT... statement are columns, then numeric affinity is used -** if either column has NUMERIC or INTEGER affinity. If neither -** 'x' nor the SELECT... statement are columns, then numeric affinity -** is used. -*/ -SQLITE_PRIVATE void sqlite3CodeRhsOfIN( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The IN operator */ - int iTab /* Use this cursor number */ -){ - int addrOnce = 0; /* Address of the OP_Once instruction at top */ - int addr; /* Address of OP_OpenEphemeral instruction */ - Expr *pLeft; /* the LHS of the IN operator */ - KeyInfo *pKeyInfo = 0; /* Key information */ - int nVal; /* Size of vector pLeft */ - Vdbe *v; /* The prepared statement under construction */ - SubrtnSig *pSig = 0; /* Signature for this subroutine */ - - v = pParse->pVdbe; - assert( v!=0 ); - - /* The evaluation of the IN must be repeated every time it - ** is encountered if any of the following is true: - ** - ** * The right-hand side is a correlated subquery - ** * The right-hand side is an expression list containing variables - ** * We are inside a trigger - ** - ** If all of the above are false, then we can compute the RHS just once - ** and reuse it many names. - */ - if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){ - /* Reuse of the RHS is allowed - ** - ** Compute a signature for the RHS of the IN operator to facility - ** finding and reusing prior instances of the same IN operator. - */ - assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 ); - if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){ - pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0])); - if( pSig ){ - pSig->selId = pExpr->x.pSelect->selId; - pSig->zAff = exprINAffinity(pParse, pExpr); - } - } - - /* Check to see if there is a prior materialization of the RHS of - ** this IN operator. If there is, then make use of that prior - ** materialization rather than recomputing it. - */ - if( ExprHasProperty(pExpr, EP_Subrtn) - || findCompatibleInRhsSubrtn(pParse, pExpr, pSig) - ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - if( ExprUseXSelect(pExpr) ){ - ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d", - pExpr->x.pSelect->selId)); - } - assert( ExprUseYSub(pExpr) ); - sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr); - assert( iTab!=pExpr->iTable ); - sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable); - sqlite3VdbeJumpHere(v, addrOnce); - if( pSig ){ - sqlite3DbFree(pParse->db, pSig->zAff); - sqlite3DbFree(pParse->db, pSig); - } - 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 = - sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; - if( pSig ){ - pSig->bComplete = 0; - pSig->iAddr = pExpr->y.sub.iAddr; - pSig->regReturn = pExpr->y.sub.regReturn; - pSig->iTable = iTab; - pParse->mSubrtnSig = 1 << (pSig->selId&7); - sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG); - } - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - - /* Check to see if this is a vector IN operator */ - pLeft = pExpr->pLeft; - nVal = sqlite3ExprVectorSize(pLeft); - - /* Construct the ephemeral table that will contain the content of - ** RHS of the IN operator. - */ - pExpr->iTable = iTab; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal); -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - if( ExprUseXSelect(pExpr) ){ - VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId)); - }else{ - VdbeComment((v, "RHS of IN operator")); - } -#endif - pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1); - - if( ExprUseXSelect(pExpr) ){ - /* Case 1: expr IN (SELECT ...) - ** - ** Generate code to write the results of the select into the temporary - ** table allocated and opened above. - */ - Select *pSelect = pExpr->x.pSelect; - ExprList *pEList = pSelect->pEList; - - ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d", - addrOnce?"":"CORRELATED ", pSelect->selId - )); - /* 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; - int addrBloom = 0; - sqlite3SelectDestInit(&dest, SRT_Set, iTab); - dest.zAffSdst = exprINAffinity(pParse, pExpr); - pSelect->iLimit = 0; - if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ - int regBloom = ++pParse->nMem; - addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom); - VdbeComment((v, "Bloom filter")); - dest.iSDParm2 = regBloom; - } - testcase( pSelect->selFlags & SF_Distinct ); - testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ - pCopy = sqlite3SelectDup(pParse->db, pSelect, 0); - rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest); - sqlite3SelectDelete(pParse->db, pCopy); - sqlite3DbFree(pParse->db, dest.zAffSdst); - if( addrBloom ){ - /* Remember that location of the Bloom filter in the P3 operand - ** of the OP_Once that began this subroutine. tag-202407032019 */ - sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2; - if( dest.iSDParm2==0 ){ - /* If the Bloom filter won't actually be used, keep it small */ - sqlite3VdbeGetOp(v, addrBloom)->p1 = 10; - } - } - if( rc ){ - sqlite3KeyInfoUnref(pKeyInfo); - return; - } - assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ - assert( pEList!=0 ); - assert( pEList->nExpr>0 ); - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( - pParse, p, pEList->a[i].pExpr - ); - } - } - }else if( ALWAYS(pExpr->x.pList!=0) ){ - /* Case 2: expr IN (exprlist) - ** - ** For each expression, build an index key from the evaluation and - ** store it in the temporary table. If is a column, then use - ** that columns affinity when building index keys. If is not - ** a column, use numeric affinity. - */ - char affinity; /* Affinity of the LHS of the IN */ - int i; - ExprList *pList = pExpr->x.pList; - struct ExprList_item *pItem; - int r1, r2; - affinity = sqlite3ExprAffinity(pLeft); - if( affinity<=SQLITE_AFF_NONE ){ - affinity = SQLITE_AFF_BLOB; - }else if( affinity==SQLITE_AFF_REAL ){ - affinity = SQLITE_AFF_NUMERIC; - } - if( pKeyInfo ){ - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - } - - /* Loop through each expression in . */ - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempReg(pParse); - for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ - Expr *pE2 = pItem->pExpr; - - /* If the expression is not constant then we will need to - ** disable the test that was generated above that makes sure - ** this code only executes once. Because for a non-constant - ** expression we need to rerun this code each time. - */ - if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){ - sqlite3VdbeChangeToNoop(v, addrOnce-1); - sqlite3VdbeChangeToNoop(v, addrOnce); - ExprClearProperty(pExpr, EP_Subrtn); - addrOnce = 0; - } - - /* Evaluate the expression and insert it into the temp table */ - sqlite3ExprCode(pParse, pE2, r1); - sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1); - } - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } - if( pSig ) pSig->bComplete = 1; - if( pKeyInfo ){ - sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); - } - if( addrOnce ){ - sqlite3VdbeAddOp1(v, OP_NullRow, iTab); - sqlite3VdbeJumpHere(v, addrOnce); - /* Subroutine return */ - assert( ExprUseYSub(pExpr) ); - assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn - || pParse->nErr ); - sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr, 1); - VdbeCoverage(v); - sqlite3ClearTempRegCache(pParse); - } -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -/* -** Generate code for scalar subqueries used as a subquery expression -** or EXISTS operator: -** -** (SELECT a FROM b) -- subquery -** EXISTS (SELECT a FROM b) -- EXISTS subquery -** -** The pExpr parameter is the SELECT or EXISTS operator to be coded. -** -** Return the register that holds the result. For a multi-column SELECT, -** the result is stored in a contiguous array of registers and the -** return value is the register of the left-most result column. -** Return 0 if an error occurs. -*/ -#ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ - int addrOnce = 0; /* Address of OP_Once at top of subroutine */ - int rReg = 0; /* Register storing resulting */ - Select *pSel; /* SELECT statement to encode */ - SelectDest dest; /* How to deal with SELECT result */ - int nReg; /* Registers to allocate */ - Expr *pLimit; /* New limit expression */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; /* Address of OP_Explain instruction */ -#endif - - 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( 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) ); - 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 = - 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: - ** - ** * The right-hand side is a correlated subquery - ** * The right-hand side is an expression list containing variables - ** * We are inside a trigger - ** - ** If all of the above are false, then we can run this code just once - ** save the results, and reuse the same result on subsequent invocations. - */ - if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - - /* For a SELECT, generate code to put the values for all columns of - ** the first row into an array of registers and return the index of - ** the first register. - ** - ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists) - ** into a register and return that register number. - ** - ** In both cases, the query is augmented with "LIMIT 1". Any - ** preexisting limit is discarded in place of the new LIMIT 1. - */ - ExplainQueryPlan2(addrExplain, (pParse, 1, "%sSCALAR SUBQUERY %d", - addrOnce?"":"CORRELATED ", pSel->selId)); - sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, -1); - nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; - sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); - pParse->nMem += nReg; - if( pExpr->op==TK_SELECT ){ - dest.eDest = SRT_Mem; - dest.iSdst = dest.iSDParm; - dest.nSdst = nReg; - sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1); - VdbeComment((v, "Init subquery result")); - }else{ - dest.eDest = SRT_Exists; - sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); - VdbeComment((v, "Init EXISTS result")); - } - if( pSel->pLimit ){ - /* The subquery already has a limit. If the pre-existing limit is X - ** then make the new limit X<>0 so that the new limit is either 1 or 0 */ - sqlite3 *db = pParse->db; - pLimit = sqlite3Expr(db, TK_INTEGER, "0"); - if( pLimit ){ - pLimit->affExpr = SQLITE_AFF_NUMERIC; - pLimit = sqlite3PExpr(pParse, TK_NE, - sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit); - } - sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft); - pSel->pLimit->pLeft = pLimit; - }else{ - /* If there is no pre-existing limit add a limit of 1 */ - pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); - pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); - } - pSel->iLimit = 0; - if( 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 ){ - sqlite3VdbeJumpHere(v, addrOnce); - } - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); - - /* Subroutine return */ - assert( ExprUseYSub(pExpr) ); - assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn - || pParse->nErr ); - sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr, 1); - VdbeCoverage(v); - sqlite3ClearTempRegCache(pParse); - return rReg; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Expr pIn is an IN(...) expression. This function checks that the -** sub-select on the RHS of the IN() operator has the same number of -** columns as the vector on the LHS. Or, if the RHS of the IN() is not -** a sub-query, that the LHS is a vector of size 1. -*/ -SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ - int nVector = sqlite3ExprVectorSize(pIn->pLeft); - if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){ - if( nVector!=pIn->x.pSelect->pEList->nExpr ){ - sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); - return 1; - } - }else if( nVector!=1 ){ - sqlite3VectorErrorMsg(pParse, pIn->pLeft); - return 1; - } - return 0; -} -#endif - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code for an IN expression. -** -** x IN (SELECT ...) -** x IN (value, value, ...) -** -** The left-hand side (LHS) is a scalar or vector expression. The -** right-hand side (RHS) is an array of zero or more scalar values, or a -** subquery. If the RHS is a subquery, the number of result columns must -** match the number of columns in the vector on the LHS. If the RHS is -** a list of values, the LHS must be a scalar. -** -** The IN operator is true if the LHS value is contained within the RHS. -** The result is false if the LHS is definitely not in the RHS. The -** result is NULL if the presence of the LHS in the RHS cannot be -** determined due to NULLs. -** -** This routine generates code that jumps to destIfFalse if the LHS is not -** contained within the RHS. If due to NULLs we cannot determine if the LHS -** is contained in the RHS then jump to destIfNull. If the LHS is contained -** within the RHS then fall through. -** -** See the separate in-operator.md documentation file in the canonical -** SQLite source tree for additional information. -*/ -static void sqlite3ExprCodeIN( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* The IN expression */ - int destIfFalse, /* Jump here if LHS is not contained in the RHS */ - int destIfNull /* Jump here if the results are unknown due to NULLs */ -){ - int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ - int eType; /* Type of the RHS */ - int rLhs; /* Register(s) holding the LHS values */ - int rLhsOrig; /* LHS values prior to reordering by aiMap[] */ - Vdbe *v; /* Statement under construction */ - int *aiMap = 0; /* Map from vector field to index column */ - char *zAff = 0; /* Affinity string for comparisons */ - int nVector; /* Size of vectors for this IN operator */ - int iDummy; /* Dummy parameter to exprCodeVector() */ - Expr *pLeft; /* The LHS of the IN operator */ - int i; /* loop counter */ - int destStep2; /* Where to jump when NULLs seen in step 2 */ - int destStep6 = 0; /* Start of code for Step 6 */ - int addrTruthOp; /* Address of opcode that determines the IN is true */ - int destNotNull; /* Jump here if a comparison is not true in step 6 */ - int addrTop; /* Top of the step-6 loop */ - int iTab = 0; /* Index to use */ - u8 okConstFactor = pParse->okConstFactor; - - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); - pLeft = pExpr->pLeft; - if( sqlite3ExprCheckIN(pParse, pExpr) ) return; - zAff = exprINAffinity(pParse, pExpr); - nVector = sqlite3ExprVectorSize(pExpr->pLeft); - aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int)); - if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error; - - /* Attempt to compute the RHS. After this step, if anything other than - ** IN_INDEX_NOOP is returned, the table opened with cursor iTab - ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, - ** the RHS has not yet been coded. */ - v = pParse->pVdbe; - assert( v!=0 ); /* OOM detected prior to this routine */ - VdbeNoopComment((v, "begin IN expr")); - eType = sqlite3FindInIndex(pParse, pExpr, - IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, - destIfFalse==destIfNull ? 0 : &rRhsHasNull, - aiMap, &iTab); - - assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH - || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC - ); -#ifdef SQLITE_DEBUG - /* Confirm that aiMap[] contains nVector integer values between 0 and - ** nVector-1. */ - for(i=0; i from " IN (...)". If the LHS is a - ** vector, then it is stored in an array of nVector registers starting - ** at r1. - ** - ** sqlite3FindInIndex() might have reordered the fields of the LHS vector - ** so that the fields are in the same order as an existing index. The - ** aiMap[] array contains a mapping from the original LHS field order to - ** the field order that matches the RHS index. - ** - ** Avoid factoring the LHS of the IN(...) expression out of the loop, - ** even if it is constant, as OP_Affinity may be used on the register - ** by code generated below. */ - assert( pParse->okConstFactor==okConstFactor ); - pParse->okConstFactor = 0; - rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); - pParse->okConstFactor = okConstFactor; - for(i=0; ix.pList; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - if( destIfNull!=destIfFalse ){ - regCkNull = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); - } - for(ii=0; iinExpr; ii++){ - r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); - if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ - sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); - } - sqlite3ReleaseTempReg(pParse, regToFree); - if( iinExpr-1 || destIfNull!=destIfFalse ){ - int op = rLhs!=r2 ? OP_Eq : OP_NotNull; - sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2, - (void*)pColl, P4_COLLSEQ); - VdbeCoverageIf(v, iinExpr-1 && op==OP_Eq); - VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq); - VdbeCoverageIf(v, iinExpr-1 && op==OP_NotNull); - VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull); - sqlite3VdbeChangeP5(v, zAff[0]); - }else{ - int op = rLhs!=r2 ? OP_Ne : OP_IsNull; - assert( destIfNull==destIfFalse ); - sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2, - (void*)pColl, P4_COLLSEQ); - VdbeCoverageIf(v, op==OP_Ne); - VdbeCoverageIf(v, op==OP_IsNull); - sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL); - } - } - if( regCkNull ){ - sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfFalse); - } - sqlite3VdbeResolveLabel(v, labelOk); - sqlite3ReleaseTempReg(pParse, regCkNull); - goto sqlite3ExprCodeIN_finished; - } - - /* Step 2: Check to see if the LHS contains any NULL columns. If the - ** LHS does contain NULLs then the result must be either FALSE or NULL. - ** We will then skip the binary search of the RHS. - */ - if( destIfNull==destIfFalse ){ - destStep2 = destIfFalse; - }else{ - destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse); - } - for(i=0; ipLeft, i); - if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error; - if( sqlite3ExprCanBeNull(p) ){ - sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); - VdbeCoverage(v); - } - } - - /* Step 3. The LHS is now known to be non-NULL. Do the binary search - ** of the RHS using the LHS as a probe. If found, the result is - ** true. - */ - if( eType==IN_INDEX_ROWID ){ - /* In this case, the RHS is the ROWID of table b-tree and so we also - ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 - ** into a single opcode. */ - sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs); - VdbeCoverage(v); - addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ - }else{ - sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); - if( destIfFalse==destIfNull ){ - /* Combine Step 3 and Step 5 into a single opcode */ - if( ExprHasProperty(pExpr, EP_Subrtn) ){ - const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); - assert( pOp->opcode==OP_Once || pParse->nErr ); - if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */ - assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ); - sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse, - rLhs, nVector); VdbeCoverage(v); - } - } - sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse, - rLhs, nVector); VdbeCoverage(v); - goto sqlite3ExprCodeIN_finished; - } - /* Ordinary Step 3, for the case where FALSE and NULL are distinct */ - addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, iTab, 0, - rLhs, nVector); VdbeCoverage(v); - } - - /* Step 4. If the RHS is known to be non-NULL and we did not find - ** an match on the search above, then the result must be FALSE. - */ - if( rRhsHasNull && nVector==1 ){ - sqlite3VdbeAddOp2(v, OP_NotNull, rRhsHasNull, destIfFalse); - VdbeCoverage(v); - } - - /* Step 5. If we do not care about the difference between NULL and - ** FALSE, then just return false. - */ - if( destIfFalse==destIfNull ) sqlite3VdbeGoto(v, destIfFalse); - - /* Step 6: Loop through rows of the RHS. Compare each row to the LHS. - ** If any comparison is NULL, then the result is NULL. If all - ** comparisons are FALSE then the final result is FALSE. - ** - ** For a scalar LHS, it is sufficient to check just the first row - ** of the RHS. - */ - if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6); - addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse); - VdbeCoverage(v); - if( nVector>1 ){ - destNotNull = sqlite3VdbeMakeLabel(pParse); - }else{ - /* For nVector==1, combine steps 6 and 7 by immediately returning - ** FALSE if the first comparison is not NULL */ - destNotNull = destIfFalse; - } - for(i=0; i1 ){ - sqlite3VdbeResolveLabel(v, destNotNull); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addrTop+1); - VdbeCoverage(v); - - /* Step 7: If we reach this point, we know that the result must - ** be false. */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); - } - - /* Jumps here in order to return true. */ - sqlite3VdbeJumpHere(v, addrTruthOp); - -sqlite3ExprCodeIN_finished: - if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); - VdbeComment((v, "end IN expr")); -sqlite3ExprCodeIN_oom_error: - sqlite3DbFree(pParse->db, aiMap); - sqlite3DbFree(pParse->db, zAff); -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Generate an instruction that will put the floating point -** value described by z[0..n-1] into register iMem. -** -** The z[] string will probably not be zero-terminated. But the -** z[n] character is guaranteed to be something that does not look -** like the continuation of the number. -*/ -static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ - if( ALWAYS(z!=0) ){ - double value; - sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); - assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ - if( negateFlag ) value = -value; - sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); - } -} -#endif - - -/* -** Generate an instruction that will put the integer describe by -** text z[0..n-1] into register iMem. -** -** Expr.u.zToken is always UTF8 and zero-terminated. -*/ -static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ - Vdbe *v = pParse->pVdbe; - if( pExpr->flags & EP_IntValue ){ - int i = pExpr->u.iValue; - assert( i>=0 ); - if( negFlag ) i = -i; - sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else{ - int c; - i64 value; - const char *z = pExpr->u.zToken; - assert( z!=0 ); - c = sqlite3DecOrHexToI64(z, &value); - if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ -#ifdef SQLITE_OMIT_FLOATING_POINT - sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr); -#else -#ifndef SQLITE_OMIT_HEX_INTEGER - if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T", - negFlag?"-":"",pExpr); - }else -#endif - { - codeReal(v, z, negFlag, iMem); - } -#endif - }else{ - if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; } - sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); - } - } -} - - -/* Generate code that will load into register regOut a value that is -** appropriate for the iIdxCol-th column of index pIdx. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn( - Parse *pParse, /* The parsing context */ - Index *pIdx, /* The index whose column is to be loaded */ - int iTabCur, /* Cursor pointing to a table row */ - int iIdxCol, /* The column of the index to be loaded */ - int regOut /* Store the index column value in this register */ -){ - i16 iTabCol = pIdx->aiColumn[iIdxCol]; - if( iTabCol==XN_EXPR ){ - assert( pIdx->aColExpr ); - assert( pIdx->aColExpr->nExpr>iIdxCol ); - pParse->iSelfTab = iTabCur + 1; - sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); - pParse->iSelfTab = 0; - }else{ - sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, - iTabCol, regOut); - } -} - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* -** Generate code that will compute the value of generated column pCol -** and store the result in register regOut -*/ -SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( - 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; - int nErr = pParse->nErr; - assert( v!=0 ); - assert( pParse->iSelfTab!=0 ); - if( pParse->iSelfTab>0 ){ - iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); - }else{ - iAddr = 0; - } - sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); - if( pCol->affinity>=SQLITE_AFF_TEXT ){ - sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); - } - if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); - if( pParse->nErr>nErr ) pParse->db->errByteOffset = -1; -} -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - -/* -** Generate code to extract the value of the iCol-th column of a table. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( - Vdbe *v, /* Parsing context */ - Table *pTab, /* The table containing the value */ - int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */ - int iCol, /* Index of the column to extract */ - int regOut /* Extract the value into this register */ -){ - Column *pCol; - assert( v!=0 ); - assert( pTab!=0 ); - assert( iCol!=XN_EXPR ); - if( iCol<0 || iCol==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); - VdbeComment((v, "%s.rowid", pTab->zName)); - }else{ - int op; - int x; - if( IsVirtual(pTab) ){ - op = OP_VColumn; - x = iCol; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){ - Parse *pParse = sqlite3VdbeParser(v); - if( pCol->colFlags & COLFLAG_BUSY ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", - pCol->zCnName); - }else{ - int savedSelfTab = pParse->iSelfTab; - pCol->colFlags |= COLFLAG_BUSY; - pParse->iSelfTab = iTabCur+1; - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut); - pParse->iSelfTab = savedSelfTab; - pCol->colFlags &= ~COLFLAG_BUSY; - } - return; -#endif - }else if( !HasRowid(pTab) ){ - testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) ); - x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol); - op = OP_Column; - }else{ - x = sqlite3TableColumnToStorage(pTab,iCol); - testcase( x!=iCol ); - op = OP_Column; - } - sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut); - sqlite3ColumnDefault(v, pTab, iCol, regOut); - } -} - -/* -** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in register iReg. -** -** There must be an open cursor to pTab in iTable when this routine -** is called. If iColumn<0 then code is generated that extracts the rowid. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* Description of the table we are reading from */ - int iColumn, /* Index of the table column */ - int iTable, /* The cursor pointing to the table */ - int iReg, /* Store results here */ - u8 p5 /* P5 value for OP_Column + FLAGS */ -){ - assert( pParse->pVdbe!=0 ); - assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); - assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); - sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); - if( p5 ){ - VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); - if( pOp->opcode==OP_Column ) pOp->p5 = p5; - if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); - } - return iReg; -} - -/* -** Generate code to move content from registers iFrom...iFrom+nReg-1 -** over to iTo..iTo+nReg-1. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ - sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); -} - -/* -** Convert a scalar expression node to a TK_REGISTER referencing -** register iReg. The caller must ensure that iReg already contains -** the correct value for the expression. -*/ -SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr); - if( NEVER(p==0) ) return; - if( p->op==TK_REGISTER ){ - assert( p->iTable==iReg ); - }else{ - p->op2 = p->op; - p->op = TK_REGISTER; - p->iTable = iReg; - ExprClearProperty(p, EP_Skip); - } -} - -/* -** Evaluate an expression (either a vector or a scalar expression) and store -** the result in contiguous temporary registers. Return the index of -** the first register used to store the result. -** -** If the returned result register is a temporary scalar, then also write -** that register number into *piFreeable. If the returned result register -** is not a temporary or if the expression is a vector set *piFreeable -** to 0. -*/ -static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ - int iResult; - int nResult = sqlite3ExprVectorSize(p); - if( nResult==1 ){ - iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable); - }else{ - *piFreeable = 0; - if( p->op==TK_SELECT ){ -#if SQLITE_OMIT_SUBQUERY - iResult = 0; -#else - iResult = sqlite3CodeSubselect(pParse, p); -#endif - }else{ - int i; - iResult = pParse->nMem+1; - pParse->nMem += nResult; - assert( ExprUseXList(p) ); - for(i=0; ix.pList->a[i].pExpr, i+iResult); - } - } - } - return iResult; -} - -/* -** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5) -** so that a subsequent copy will not be merged into this one. -*/ -static void setDoNotMergeFlagOnCopy(Vdbe *v){ - if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){ - sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergeable */ - } -} - -/* -** Generate code to implement special SQL functions that are implemented -** in-line rather than by using the usual callbacks. -*/ -static int exprCodeInlineFunction( - Parse *pParse, /* Parsing context */ - ExprList *pFarg, /* List of function arguments */ - int iFuncId, /* Function ID. One of the INTFUNC_... values */ - int target /* Store function result in this register */ -){ - int nFarg; - Vdbe *v = pParse->pVdbe; - assert( v!=0 ); - assert( pFarg!=0 ); - nFarg = pFarg->nExpr; - assert( nFarg>0 ); /* All in-line functions have at least one argument */ - switch( iFuncId ){ - case INLINEFUNC_coalesce: { - /* Attempt a direct implementation of the built-in COALESCE() and - ** IFNULL() functions. This avoids unnecessary evaluation of - ** arguments past the first non-NULL argument. - */ - int endCoalesce = sqlite3VdbeMakeLabel(pParse); - int i; - assert( nFarg>=2 ); - sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); - for(i=1; ia[i].pExpr, target); - } - setDoNotMergeFlagOnCopy(v); - sqlite3VdbeResolveLabel(v, endCoalesce); - break; - } - case INLINEFUNC_iif: { - Expr caseExpr; - memset(&caseExpr, 0, sizeof(caseExpr)); - caseExpr.op = TK_CASE; - caseExpr.x.pList = pFarg; - return 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 ){ - sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); - }else{ - 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. - */ - assert( nFarg==1 || nFarg==2 ); - target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); - break; - } - - /*********************************************************************** - ** 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 sqlite3ExprCompare() */ - assert( nFarg==2 ); - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprCompare(0,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1), - target); - break; - } - - case INLINEFUNC_expr_implies_expr: { - /* Compare two expressions using sqlite3ExprImpliesExpr() */ - assert( nFarg==2 ); - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprImpliesExpr(pParse,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1), - target); - break; - } - - case INLINEFUNC_implies_nonnull_row: { - /* Result of sqlite3ExprImpliesNonNullRow() */ - Expr *pA1; - assert( nFarg==2 ); - pA1 = pFarg->a[1].pExpr; - if( pA1->op==TK_COLUMN ){ - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1), - target); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - break; - } - - case INLINEFUNC_affinity: { - /* The AFFINITY() function evaluates to a string that describes - ** the type affinity of the argument. This is used for testing of - ** the SQLite type logic. - */ - const char *azAff[] = { "blob", "text", "numeric", "integer", - "real", "flexnum" }; - char aff; - assert( nFarg==1 ); - aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); - assert( aff<=SQLITE_AFF_NONE - || (aff>=SQLITE_AFF_BLOB && aff<=SQLITE_AFF_FLEXNUM) ); - sqlite3VdbeLoadString(v, target, - (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); - break; - } -#endif /* !defined(SQLITE_UNTESTABLE) */ - } - return target; -} - -/* -** Expression Node callback for sqlite3ExprCanReturnSubtype(). -** -** Only a function call is able to return a subtype. So if the node -** is not a function call, return WRC_Prune immediately. -** -** A function call is able to return a subtype if it has the -** SQLITE_RESULT_SUBTYPE property. -** -** Assume that every function is able to pass-through a subtype from -** one of its argument (using sqlite3_result_value()). Most functions -** are not this way, but we don't have a mechanism to distinguish those -** that are from those that are not, so assume they all work this way. -** That means that if one of its arguments is another function and that -** other function is able to return a subtype, then this function is -** able to return a subtype. -*/ -static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){ - int n; - FuncDef *pDef; - sqlite3 *db; - if( pExpr->op!=TK_FUNCTION ){ - return WRC_Prune; - } - assert( ExprUseXList(pExpr) ); - db = pWalker->pParse->db; - n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ - pWalker->eCode = 1; - return WRC_Prune; - } - return WRC_Continue; -} - -/* -** Return TRUE if expression pExpr is able to return a subtype. -** -** A TRUE return does not guarantee that a subtype will be returned. -** It only indicates that a subtype return is possible. False positives -** are acceptable as they only disable an optimization. False negatives, -** on the other hand, can lead to incorrect answers. -*/ -static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){ - Walker w; - memset(&w, 0, sizeof(w)); - w.pParse = pParse; - w.xExprCallback = exprNodeCanReturnSubtype; - sqlite3WalkExpr(&w, pExpr); - return w.eCode; -} - - -/* -** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr. -** If it is, then resolve the expression by reading from the index and -** return the register into which the value has been read. If pExpr is -** not an indexed expression, then return negative. -*/ -static SQLITE_NOINLINE int sqlite3IndexedExprLookup( - Parse *pParse, /* The parsing context */ - Expr *pExpr, /* The expression to potentially bypass */ - int target /* Where to store the result of the expression */ -){ - IndexedExpr *p; - Vdbe *v; - for(p=pParse->pIdxEpr; p; p=p->pIENext){ - u8 exprAff; - int iDataCur = p->iDataCur; - if( iDataCur<0 ) continue; - if( pParse->iSelfTab ){ - if( p->iDataCur!=pParse->iSelfTab-1 ) continue; - iDataCur = -1; - } - if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue; - assert( p->aff>=SQLITE_AFF_BLOB && p->aff<=SQLITE_AFF_NUMERIC ); - exprAff = sqlite3ExprAffinity(pExpr); - if( (exprAff<=SQLITE_AFF_BLOB && p->aff!=SQLITE_AFF_BLOB) - || (exprAff==SQLITE_AFF_TEXT && p->aff!=SQLITE_AFF_TEXT) - || (exprAff>=SQLITE_AFF_NUMERIC && p->aff!=SQLITE_AFF_NUMERIC) - ){ - /* Affinity mismatch on a generated column */ - continue; - } - - - /* Functions that might set a subtype should not be replaced by the - ** value taken from an expression index if they are themselves an - ** argument to another scalar function or aggregate. - ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */ - if( ExprHasProperty(pExpr, EP_SubtArg) - && sqlite3ExprCanReturnSubtype(pParse, pExpr) - ){ - continue; - } - - v = pParse->pVdbe; - assert( v!=0 ); - if( p->bMaybeNullRow ){ - /* If the index is on a NULL row due to an outer join, then we - ** cannot extract the value from the index. The value must be - ** computed using the original expression. */ - int addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); - VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); - sqlite3VdbeGoto(v, 0); - p = pParse->pIdxEpr; - pParse->pIdxEpr = 0; - sqlite3ExprCode(pParse, pExpr, target); - pParse->pIdxEpr = p; - sqlite3VdbeJumpHere(v, addr+2); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); - VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); - } - return target; - } - return -1; /* Not found */ -} - - -/* -** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This -** function checks the Parse.pIdxPartExpr list to see if this column -** can be replaced with a constant value. If so, it generates code to -** put the constant value in a register (ideally, but not necessarily, -** register iTarget) and returns the register number. -** -** Or, if the TK_COLUMN cannot be replaced by a constant, zero is -** returned. -*/ -static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){ - IndexedExpr *p; - for(p=pParse->pIdxPartExpr; p; p=p->pIENext){ - if( pExpr->iColumn==p->iIdxCol && pExpr->iTable==p->iDataCur ){ - Vdbe *v = pParse->pVdbe; - int addr = 0; - int ret; - - if( p->bMaybeNullRow ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNullRow, p->iIdxCur); - } - ret = sqlite3ExprCodeTarget(pParse, p->pExpr, iTarget); - sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, ret, 1, 0, - (const char*)&p->aff, 1); - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeChangeP3(v, addr, ret); - } - return ret; - } - } - return 0; -} - - -/* -** Generate code into the current Vdbe to evaluate the given -** expression. Attempt to store the results in register "target". -** Return the register where results are stored. -** -** With this routine, there is no guarantee that results will -** be stored in target. The result might be stored in some other -** register if it is convenient to do so. The calling function -** must check the return code and move the results to the desired -** register. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ - Vdbe *v = pParse->pVdbe; /* The VM under construction */ - int op; /* The opcode being coded */ - int inReg = target; /* Results stored in register inReg */ - int regFree1 = 0; /* If non-zero free this temporary register */ - int regFree2 = 0; /* If non-zero free this temporary register */ - int r1, r2; /* Various register numbers */ - Expr tempX; /* Temporary expression node */ - int p5 = 0; - - assert( target>0 && target<=pParse->nMem ); - assert( v!=0 ); - -expr_code_doover: - if( pExpr==0 ){ - op = TK_NULL; - }else if( pParse->pIdxEpr!=0 - && !ExprHasProperty(pExpr, EP_Leaf) - && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0 - ){ - return r1; - }else{ - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); - op = pExpr->op; - } - assert( op!=TK_ORDER ); - switch( op ){ - case TK_AGG_COLUMN: { - AggInfo *pAggInfo = pExpr->pAggInfo; - struct AggInfo_col *pCol; - assert( pAggInfo!=0 ); - assert( pExpr->iAgg>=0 ); - if( pExpr->iAgg>=pAggInfo->nColumn ){ - /* Happens when the left table of a RIGHT JOIN is null and - ** is using an expression index */ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); -#ifdef SQLITE_VDBE_COVERAGE - /* Verify that the OP_Null above is exercised by tests - ** tag-20230325-2 */ - sqlite3VdbeAddOp3(v, OP_NotNull, target, 1, 20230325); - VdbeCoverageNeverTaken(v); -#endif - break; - } - pCol = &pAggInfo->aCol[pExpr->iAgg]; - if( !pAggInfo->directMode ){ - return AggInfoColumnReg(pAggInfo, pExpr->iAgg); - }else if( pAggInfo->useSortingIdx ){ - Table *pTab = pCol->pTab; - sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, - pCol->iSorterColumn, target); - if( pTab==0 ){ - /* No comment added */ - }else if( pCol->iColumn<0 ){ - VdbeComment((v,"%s.rowid",pTab->zName)); - }else{ - VdbeComment((v,"%s.%s", - pTab->zName, pTab->aCol[pCol->iColumn].zCnName)); - if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - } - } - return target; - }else if( pExpr->y.pTab==0 ){ - /* This case happens when the argument to an aggregate function - ** is rewritten by aggregateConvertIndexedExprRefToColumn() */ - sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, pExpr->iColumn, target); - return target; - } - /* Otherwise, fall thru into the TK_COLUMN case */ - /* no break */ deliberate_fall_through - } - case TK_COLUMN: { - int iTab = pExpr->iTable; - int iReg; - if( ExprHasProperty(pExpr, EP_FixedCol) ){ - /* This COLUMN expression is really a constant due to WHERE clause - ** constraints, and that constant is coded by the pExpr->pLeft - ** expression. However, make sure the constant has the correct - ** datatype by applying the Affinity of the table column to the - ** constant. - */ - int aff; - iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); - if( aff>SQLITE_AFF_BLOB ){ - static const char zAff[] = "B\000C\000D\000E\000F"; - assert( SQLITE_AFF_BLOB=='A' ); - assert( SQLITE_AFF_TEXT=='B' ); - sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, - &zAff[(aff-'B')*2], P4_STATIC); - } - return iReg; - } - if( iTab<0 ){ - if( pParse->iSelfTab<0 ){ - /* Other columns in the same row for CHECK constraints or - ** generated columns or for inserting into partial index. - ** The row is unpacked into registers beginning at - ** 0-(pParse->iSelfTab). The rowid (if any) is in a register - ** immediately prior to the first column. - */ - Column *pCol; - Table *pTab; - int iSrc; - int iCol = pExpr->iColumn; - assert( ExprUseYTab(pExpr) ); - pTab = pExpr->y.pTab; - assert( pTab!=0 ); - assert( iCol>=XN_ROWID ); - assert( iColnCol ); - if( iCol<0 ){ - return -1-pParse->iSelfTab; - } - pCol = pTab->aCol + iCol; - testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) ); - iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pCol->colFlags & COLFLAG_GENERATED ){ - if( pCol->colFlags & COLFLAG_BUSY ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", - pCol->zCnName); - return 0; - } - pCol->colFlags |= COLFLAG_BUSY; - if( pCol->colFlags & COLFLAG_NOTAVAIL ){ - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc); - } - pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL); - return iSrc; - }else -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - if( pCol->affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target); - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - return target; - }else{ - return iSrc; - } - }else{ - /* Coding an expression that is part of an index where column names - ** in the index refer to the table to which the index belongs */ - iTab = pParse->iSelfTab - 1; - } - } - else if( pParse->pIdxPartExpr - && 0!=(r1 = exprPartidxExprLookup(pParse, pExpr, target)) - ){ - return r1; - } - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, - pExpr->iColumn, iTab, target, - pExpr->op2); - return iReg; - } - case TK_INTEGER: { - codeInteger(pParse, pExpr, 0, target); - return target; - } - case TK_TRUEFALSE: { - sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target); - return target; - } -#ifndef SQLITE_OMIT_FLOATING_POINT - case TK_FLOAT: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - codeReal(v, pExpr->u.zToken, 0, target); - return target; - } -#endif - case TK_STRING: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3VdbeLoadString(v, target, pExpr->u.zToken); - return target; - } - case TK_NULLS: { - /* Set a range of registers to NULL. pExpr->y.nReg registers starting - ** with target */ - sqlite3VdbeAddOp3(v, OP_Null, 0, target, target + pExpr->y.nReg - 1); - return target; - } - default: { - /* Make NULL the default case so that if a bug causes an illegal - ** 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 || op==TK_ERROR || pParse->db->mallocFailed ); - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - return target; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: { - int n; - const char *z; - char *zBlob; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); - assert( pExpr->u.zToken[1]=='\'' ); - z = &pExpr->u.zToken[2]; - n = sqlite3Strlen30(z) - 1; - assert( z[n]=='\'' ); - zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); - sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); - return target; - } -#endif - case TK_VARIABLE: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( pExpr->u.zToken!=0 ); - assert( pExpr->u.zToken[0]!=0 ); - sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); - return target; - } - case TK_REGISTER: { - return pExpr->iTable; - } -#ifndef SQLITE_OMIT_CAST - case TK_CAST: { - /* Expressions of the form: CAST(pLeft AS token) */ - sqlite3ExprCode(pParse, pExpr->pLeft, target); - assert( inReg==target ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3VdbeAddOp2(v, OP_Cast, target, - sqlite3AffinityType(pExpr->u.zToken, 0)); - return inReg; - } -#endif /* SQLITE_OMIT_CAST */ - case TK_IS: - case TK_ISNOT: - op = (op==TK_IS) ? TK_EQ : TK_NE; - p5 = SQLITE_NULLEQ; - /* fall-through */ - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - Expr *pLeft = pExpr->pLeft; - if( sqlite3ExprIsVector(pLeft) ){ - codeVectorCompare(pParse, pExpr, target, op, p5); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg); - codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2, - 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); - assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - if( p5==SQLITE_NULLEQ ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg); - }else{ - sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2); - } - testcase( regFree1==0 ); - testcase( regFree2==0 ); - } - break; - } - case TK_AND: - case TK_OR: - case TK_PLUS: - case TK_STAR: - case TK_MINUS: - case TK_REM: - case TK_BITAND: - case TK_BITOR: - case TK_SLASH: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: { - assert( TK_AND==OP_And ); testcase( op==TK_AND ); - assert( TK_OR==OP_Or ); testcase( op==TK_OR ); - assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); - assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); - assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); - assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); - assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); - assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH ); - assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); - assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT ); - assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - sqlite3VdbeAddOp3(v, op, r2, r1, target); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_UMINUS: { - Expr *pLeft = pExpr->pLeft; - assert( pLeft ); - if( pLeft->op==TK_INTEGER ){ - codeInteger(pParse, pLeft, 1, target); - return target; -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( pLeft->op==TK_FLOAT ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - codeReal(v, pLeft->u.zToken, 1, target); - return target; -#endif - }else{ - tempX.op = TK_INTEGER; - tempX.flags = EP_IntValue|EP_TokenOnly; - tempX.u.iValue = 0; - ExprClearVVAProperties(&tempX); - r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); - sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); - testcase( regFree2==0 ); - } - break; - } - case TK_BITNOT: - case TK_NOT: { - assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT ); - assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - sqlite3VdbeAddOp2(v, op, r1, inReg); - break; - } - case TK_TRUTH: { - int isTrue; /* IS TRUE or IS NOT TRUE */ - int bNormal; /* IS TRUE or IS FALSE */ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - bNormal = pExpr->op2==TK_IS; - testcase( isTrue && bNormal); - testcase( !isTrue && bNormal); - sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - int addr; - assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); - assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); - sqlite3VdbeAddOp2(v, OP_Integer, 1, target); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - addr = sqlite3VdbeAddOp1(v, op, r1); - VdbeCoverageIf(v, op==TK_ISNULL); - VdbeCoverageIf(v, op==TK_NOTNULL); - sqlite3VdbeAddOp2(v, OP_Integer, 0, target); - sqlite3VdbeJumpHere(v, addr); - break; - } - case TK_AGG_FUNCTION: { - AggInfo *pInfo = pExpr->pAggInfo; - if( pInfo==0 - || NEVER(pExpr->iAgg<0) - || NEVER(pExpr->iAgg>=pInfo->nFunc) - ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr); - }else{ - return AggInfoFuncReg(pInfo, pExpr->iAgg); - } - break; - } - case TK_FUNCTION: { - ExprList *pFarg; /* List of function arguments */ - int nFarg; /* Number of function arguments */ - FuncDef *pDef; /* The function definition object */ - const char *zId; /* The function name */ - u32 constMask = 0; /* Mask of function arguments that are constant */ - int i; /* Loop counter */ - sqlite3 *db = pParse->db; /* The database connection */ - u8 enc = ENC(db); /* The text encoding used by this database */ - CollSeq *pColl = 0; /* A collating sequence */ - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - return pExpr->y.pWin->regResult; - } -#endif - - if( ConstFactorOk(pParse) - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) - ){ - /* SQL functions can be expensive. So try to avoid running them - ** multiple times if we know they always give the same result */ - return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); - } - assert( !ExprHasProperty(pExpr, EP_TokenOnly) ); - assert( ExprUseXList(pExpr) ); - pFarg = pExpr->x.pList; - nFarg = pFarg ? pFarg->nExpr : 0; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - zId = pExpr->u.zToken; - pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pDef==0 && pParse->explain ){ - pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0); - } -#endif - if( pDef==0 || pDef->xFinalize!=0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); - break; - } - if( (pDef->funcFlags & SQLITE_FUNC_INLINE)!=0 && ALWAYS(pFarg!=0) ){ - assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 ); - assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 ); - return exprCodeInlineFunction(pParse, pFarg, - SQLITE_PTR_TO_INT(pDef->pUserData), target); - }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){ - sqlite3ExprFunctionUsable(pParse, pExpr, pDef); - } - - for(i=0; ia[i].pExpr) ){ - testcase( i==31 ); - constMask |= MASKBIT32(i); - } - if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ - pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); - } - } - if( pFarg ){ - if( constMask ){ - r1 = pParse->nMem+1; - pParse->nMem += nFarg; - }else{ - r1 = sqlite3GetTempRange(pParse, nFarg); - } - - /* For length() and typeof() and octet_length() functions, - ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG - ** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid - ** unnecessary data loading. - */ - if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ - u8 exprOp; - assert( nFarg==1 ); - assert( pFarg->a[0].pExpr!=0 ); - exprOp = pFarg->a[0].pExpr->op; - if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ - assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); - assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - assert( SQLITE_FUNC_BYTELEN==OPFLAG_BYTELENARG ); - assert( (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG)==OPFLAG_BYTELENARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_LENGTHARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_TYPEOFARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_BYTELENARG); - pFarg->a[0].pExpr->op2 = pDef->funcFlags & OPFLAG_BYTELENARG; - } - } - - sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_FACTOR); - }else{ - r1 = 0; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Possibly overload the function if the first argument is - ** a virtual table column. - ** - ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the - ** second argument, not the first, as the argument to test to - ** see if it is a column in a virtual table. This is done because - ** the left operand of infix functions (the operand we want to - ** control overloading) ends up as the second argument to the - ** function. The expression "A glob B" is equivalent to - ** "glob(B,A). We want to use the A in "A glob B" to test - ** for function overloading. But we use the B term in "glob(B,A)". - */ - if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ - pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); - }else if( nFarg>0 ){ - pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); - } -#endif - if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - if( !pColl ) pColl = db->pDfltColl; - sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg, - pDef, pExpr->op2); - if( nFarg ){ - if( constMask==0 ){ - sqlite3ReleaseTempRange(pParse, r1, nFarg); - }else{ - sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1); - } - } - return target; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: - case TK_SELECT: { - int nCol; - testcase( op==TK_EXISTS ); - testcase( op==TK_SELECT ); - if( pParse->db->mallocFailed ){ - return 0; - }else if( op==TK_SELECT - && ALWAYS( ExprUseXSelect(pExpr) ) - && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 - ){ - sqlite3SubselectError(pParse, nCol, 1); - }else{ - return sqlite3CodeSubselect(pParse, pExpr); - } - break; - } - case TK_SELECT_COLUMN: { - int n; - Expr *pLeft = pExpr->pLeft; - if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){ - pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft); - pLeft->op2 = pParse->withinRJSubrtn; - } - assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR ); - n = sqlite3ExprVectorSize(pLeft); - if( pExpr->iTable!=n ){ - sqlite3ErrorMsg(pParse, "%d columns assigned %d values", - pExpr->iTable, n); - } - return pLeft->iTable + pExpr->iColumn; - } - case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(pParse); - int destIfNull = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); - sqlite3VdbeAddOp2(v, OP_Integer, 1, target); - sqlite3VdbeResolveLabel(v, destIfFalse); - sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); - sqlite3VdbeResolveLabel(v, destIfNull); - return target; - } -#endif /* SQLITE_OMIT_SUBQUERY */ - - - /* - ** x BETWEEN y AND z - ** - ** This is equivalent to - ** - ** x>=y AND x<=z - ** - ** X is stored in pExpr->pLeft. - ** Y is stored in pExpr->pList->a[0].pExpr. - ** Z is stored in pExpr->pList->a[1].pExpr. - */ - case TK_BETWEEN: { - exprCodeBetween(pParse, pExpr, target, 0, 0); - return target; - } - case TK_COLLATE: { - if( !ExprHasProperty(pExpr, EP_Collate) ){ - /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called - ** "SOFT-COLLATE" that is added to constraints that are pushed down - ** from outer queries into sub-queries by the WHERE-clause push-down - ** optimization. Clear subtypes as subtypes may not cross a subquery - ** boundary. - */ - assert( pExpr->pLeft ); - sqlite3ExprCode(pParse, pExpr->pLeft, target); - sqlite3VdbeAddOp1(v, OP_ClrSubtype, target); - return target; - }else{ - pExpr = pExpr->pLeft; - goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */ - } - } - case TK_SPAN: - case TK_UPLUS: { - pExpr = pExpr->pLeft; - goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ - } - - case TK_TRIGGER: { - /* If the opcode is TK_TRIGGER, then the expression is a reference - ** to a column in the new.* or old.* pseudo-tables available to - ** trigger programs. In this case Expr.iTable is set to 1 for the - ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn - ** is set to the column of the pseudo-table to read, or to -1 to - ** read the rowid field. - ** - ** The expression is implemented using an OP_Param opcode. The p1 - ** parameter is set to 0 for an old.rowid reference, or to (i+1) - ** to reference another column of the old.* pseudo-table, where - ** i is the index of the column. For a new.rowid reference, p1 is - ** set to (n+1), where n is the number of columns in each pseudo-table. - ** For a reference to any other column in the new.* pseudo-table, p1 - ** is set to (n+2+i), where n and i are as defined previously. For - ** example, if the table on which triggers are being fired is - ** declared as: - ** - ** CREATE TABLE t1(a, b); - ** - ** Then p1 is interpreted as follows: - ** - ** p1==0 -> old.rowid p1==3 -> new.rowid - ** p1==1 -> old.a p1==4 -> new.a - ** p1==2 -> old.b p1==5 -> new.b - */ - Table *pTab; - int iCol; - int p1; - - assert( ExprUseYTab(pExpr) ); - pTab = pExpr->y.pTab; - iCol = pExpr->iColumn; - p1 = pExpr->iTable * (pTab->nCol+1) + 1 - + sqlite3TableColumnToStorage(pTab, iCol); - - assert( pExpr->iTable==0 || pExpr->iTable==1 ); - assert( iCol>=-1 && iColnCol ); - assert( pTab->iPKey<0 || iCol!=pTab->iPKey ); - assert( p1>=0 && p1<(pTab->nCol*2+2) ); - - 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].zCnName) - )); - -#ifndef SQLITE_OMIT_FLOATING_POINT - /* If the column has REAL affinity, it may currently be stored as an - ** integer. Use OP_RealAffinity to make sure it is really real. - ** - ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to - ** floating point when extracting it from the record. */ - if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - } -#endif - break; - } - - case TK_VECTOR: { - sqlite3ErrorMsg(pParse, "row value misused"); - break; - } - - /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions - ** that derive from the right-hand table of a LEFT JOIN. The - ** Expr.iTable value is the table number for the right-hand table. - ** The expression is only evaluated if that table is not currently - ** on a LEFT JOIN NULL row. - */ - case TK_IF_NULL_ROW: { - int addrINR; - u8 okConstFactor = pParse->okConstFactor; - AggInfo *pAggInfo = pExpr->pAggInfo; - if( pAggInfo ){ - assert( pExpr->iAgg>=0 && pExpr->iAggnColumn ); - if( !pAggInfo->directMode ){ - inReg = AggInfoColumnReg(pAggInfo, pExpr->iAgg); - break; - } - if( pExpr->pAggInfo->useSortingIdx ){ - sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, - pAggInfo->aCol[pExpr->iAgg].iSorterColumn, - target); - inReg = target; - break; - } - } - addrINR = sqlite3VdbeAddOp3(v, OP_IfNullRow, pExpr->iTable, 0, target); - /* The OP_IfNullRow opcode above can overwrite the result register with - ** NULL. So we have to ensure that the result register is not a value - ** that is suppose to be a constant. Two defenses are needed: - ** (1) Temporarily disable factoring of constant expressions - ** (2) Make sure the computed value really is stored in register - ** "target" and not someplace else. - */ - pParse->okConstFactor = 0; /* note (1) above */ - sqlite3ExprCode(pParse, pExpr->pLeft, target); - assert( target==inReg ); - pParse->okConstFactor = okConstFactor; - sqlite3VdbeJumpHere(v, addrINR); - break; - } - - /* - ** Form A: - ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END - ** - ** Form B: - ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END - ** - ** Form A is can be transformed into the equivalent form B as follows: - ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ... - ** WHEN x=eN THEN rN ELSE y END - ** - ** X (if it exists) is in pExpr->pLeft. - ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is - ** odd. The Y is also optional. If the number of elements in x.pList - ** is even, then Y is omitted and the "otherwise" result is NULL. - ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. - ** - ** The result of the expression is the Ri for the first matching Ei, - ** or if there is no matching Ei, the ELSE term Y, or if there is - ** no ELSE term, NULL. - */ - case TK_CASE: { - int endLabel; /* GOTO label for end of CASE stmt */ - int nextCase; /* GOTO label for next WHEN clause */ - int nExpr; /* 2x number of WHEN terms */ - int i; /* Loop counter */ - ExprList *pEList; /* List of WHEN terms */ - struct ExprList_item *aListelem; /* Array of WHEN terms */ - Expr opCompare; /* The X==Ei expression */ - Expr *pX; /* The X expression */ - Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ - Expr *pDel = 0; - sqlite3 *db = pParse->db; - - assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 ); - assert(pExpr->x.pList->nExpr > 0); - pEList = pExpr->x.pList; - aListelem = pEList->a; - nExpr = pEList->nExpr; - endLabel = sqlite3VdbeMakeLabel(pParse); - if( (pX = pExpr->pLeft)!=0 ){ - pDel = sqlite3ExprDup(db, pX, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDel); - break; - } - testcase( pX->op==TK_COLUMN ); - sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); - testcase( regFree1==0 ); - memset(&opCompare, 0, sizeof(opCompare)); - opCompare.op = TK_EQ; - opCompare.pLeft = pDel; - pTest = &opCompare; - /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: - ** The value in regFree1 might get SCopy-ed into the file result. - ** So make sure that the regFree1 register is not reused for other - ** purposes and possibly overwritten. */ - regFree1 = 0; - } - for(i=0; iop==TK_COLUMN ); - sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); - testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); - sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); - sqlite3VdbeGoto(v, endLabel); - sqlite3VdbeResolveLabel(v, nextCase); - } - if( (nExpr&1)!=0 ){ - sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - sqlite3ExprDelete(db, pDel); - setDoNotMergeFlagOnCopy(v); - sqlite3VdbeResolveLabel(v, endLabel); - break; - } -#ifndef SQLITE_OMIT_TRIGGER - case TK_RAISE: { - assert( pExpr->affExpr==OE_Rollback - || pExpr->affExpr==OE_Abort - || pExpr->affExpr==OE_Fail - || pExpr->affExpr==OE_Ignore - ); - if( !pParse->pTriggerTab && !pParse->nested ){ - sqlite3ErrorMsg(pParse, - "RAISE() may only be used within a trigger-program"); - return 0; - } - if( pExpr->affExpr==OE_Abort ){ - sqlite3MayAbort(pParse); - } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - if( pExpr->affExpr==OE_Ignore ){ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore); - VdbeCoverage(v); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp3(v, OP_Halt, - pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR, - pExpr->affExpr, r1); - } - break; - } -#endif - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); - return inReg; -} - -/* -** Generate code that will evaluate expression pExpr just one time -** per prepared statement execution. -** -** If the expression uses functions (that might throw an exception) then -** guard them with an OP_Once opcode to ensure that the code is only executed -** once. If no functions are involved, then factor the code out and put it at -** the end of the prepared statement in the initialization section. -** -** If regDest>0 then the result is always stored in that register and the -** result is not reusable. If regDest<0 then this routine is free to -** store the value wherever it wants. The register where the expression -** is stored is returned. When regDest<0, two identical expressions might -** code to the same register, if they do not contain function calls and hence -** are factored out into the initialization section at the end of the -** prepared statement. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The expression to code when the VDBE initializes */ - int regDest /* Store the value in this register */ -){ - ExprList *p; - assert( ConstFactorOk(pParse) ); - assert( regDest!=0 ); - p = pParse->pConstExpr; - if( regDest<0 && p ){ - struct ExprList_item *pItem; - int i; - for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ - if( pItem->fg.reusable - && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 - ){ - return pItem->u.iConstExprReg; - } - } - } - pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){ - Vdbe *v = pParse->pVdbe; - int addr; - assert( v ); - addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - pParse->okConstFactor = 0; - if( !pParse->db->mallocFailed ){ - if( regDest<0 ) regDest = ++pParse->nMem; - sqlite3ExprCode(pParse, pExpr, regDest); - } - pParse->okConstFactor = 1; - sqlite3ExprDelete(pParse->db, pExpr); - sqlite3VdbeJumpHere(v, addr); - }else{ - p = sqlite3ExprListAppend(pParse, p, pExpr); - if( p ){ - struct ExprList_item *pItem = &p->a[p->nExpr-1]; - pItem->fg.reusable = regDest<0; - if( regDest<0 ) regDest = ++pParse->nMem; - pItem->u.iConstExprReg = regDest; - } - pParse->pConstExpr = p; - } - return regDest; -} - -/* -** Make arrangements to invoke OP_Null on a range of registers -** during initialization. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3ExprNullRegisterRange( - Parse *pParse, /* Parsing context */ - int iReg, /* First register to set to NULL */ - int nReg /* Number of sequential registers to NULL out */ -){ - u8 okConstFactor = pParse->okConstFactor; - Expr t; - memset(&t, 0, sizeof(t)); - t.op = TK_NULLS; - t.y.nReg = nReg; - pParse->okConstFactor = 1; - sqlite3ExprCodeRunJustOnce(pParse, &t, iReg); - pParse->okConstFactor = okConstFactor; -} - -/* -** Generate code to evaluate an expression and store the results -** into a register. Return the register number where the results -** are stored. -** -** If the register is a temporary register that can be deallocated, -** then write its number into *pReg. If the result register is not -** a temporary, then set *pReg to zero. -** -** If pExpr is a constant, then this routine might generate this -** code to fill the register in the initialization section of the -** VDBE program, in order to factor it out of the evaluation loop. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ - int r2; - pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); - if( ConstFactorOk(pParse) - && ALWAYS(pExpr!=0) - && pExpr->op!=TK_REGISTER - && sqlite3ExprIsConstantNotJoin(pParse, pExpr) - ){ - *pReg = 0; - r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); - }else{ - int r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); - if( r2==r1 ){ - *pReg = r1; - }else{ - sqlite3ReleaseTempReg(pParse, r1); - *pReg = 0; - } - } - return r2; -} - -/* -** Generate code that will evaluate expression pExpr and store the -** results in register target. The results are guaranteed to appear -** in register target. -*/ -SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ - int inReg; - - assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) ); - assert( target>0 && target<=pParse->nMem ); - assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); - if( pParse->pVdbe==0 ) return; - inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); - if( inReg!=target ){ - u8 op; - Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr); - testcase( pX!=pExpr ); - if( ALWAYS(pX) - && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER) - ){ - op = OP_Copy; - }else{ - op = OP_SCopy; - } - sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target); - } -} - -/* -** Make a transient copy of expression pExpr and then code it using -** sqlite3ExprCode(). This routine works just like sqlite3ExprCode() -** except that the input expression is guaranteed to be unchanged. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){ - sqlite3 *db = pParse->db; - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target); - sqlite3ExprDelete(db, pExpr); -} - -/* -** Generate code that will evaluate expression pExpr and store the -** results in register target. The results are guaranteed to appear -** in register target. If the expression is constant, then this routine -** might choose to code the expression at initialization time. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ - if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ - sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); - }else{ - sqlite3ExprCodeCopy(pParse, pExpr, target); - } -} - -/* -** Generate code that pushes the value of every element of the given -** expression list into a sequence of registers beginning at target. -** -** Return the number of elements evaluated. The number returned will -** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF -** is defined. -** -** The SQLITE_ECEL_DUP flag prevents the arguments from being -** filled using OP_SCopy. OP_Copy must be used instead. -** -** The SQLITE_ECEL_FACTOR argument allows constant arguments to be -** factored out into initialization code. -** -** The SQLITE_ECEL_REF flag means that expressions in the list with -** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored -** in registers at srcReg, and so the value can be copied from there. -** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0 -** are simply omitted rather than being copied from srcReg. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeExprList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* The expression list to be coded */ - int target, /* Where to write results */ - int srcReg, /* Source registers if SQLITE_ECEL_REF */ - u8 flags /* SQLITE_ECEL_* flags */ -){ - struct ExprList_item *pItem; - int i, j, n; - u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; - Vdbe *v = pParse->pVdbe; - assert( pList!=0 ); - assert( target>0 ); - assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ - n = pList->nExpr; - if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; - for(pItem=pList->a, i=0; ipExpr; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pItem->fg.bSorterRef ){ - i--; - n--; - }else -#endif - if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ - if( flags & SQLITE_ECEL_OMITREF ){ - i--; - n--; - }else{ - sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); - } - }else if( (flags & SQLITE_ECEL_FACTOR)!=0 - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) - ){ - sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); - }else{ - int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); - if( inReg!=target+i ){ - VdbeOp *pOp; - if( copyOp==OP_Copy - && (pOp=sqlite3VdbeGetLastOp(v))->opcode==OP_Copy - && pOp->p1+pOp->p3+1==inReg - && pOp->p2+pOp->p3+1==target+i - && pOp->p5==0 /* The do-not-merge flag must be clear */ - ){ - pOp->p3++; - }else{ - sqlite3VdbeAddOp2(v, copyOp, inReg, target+i); - } - } - } - } - return n; -} - -/* -** Generate code for a BETWEEN operator. -** -** x BETWEEN y AND z -** -** The above is equivalent to -** -** x>=y AND x<=z -** -** Code it as such, taking care to do the common subexpression -** elimination of x. -** -** The xJumpIf parameter determines details: -** -** NULL: Store the boolean result in reg[dest] -** sqlite3ExprIfTrue: Jump to dest if true -** sqlite3ExprIfFalse: Jump to dest if false -** -** The jumpIfNull parameter is ignored if xJumpIf is NULL. -*/ -static void exprCodeBetween( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* The BETWEEN expression */ - int dest, /* Jump destination or storage location */ - void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ - int jumpIfNull /* Take the jump if the BETWEEN is NULL */ -){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ - Expr compLeft; /* The x>=y term */ - Expr compRight; /* The x<=z term */ - int regFree1 = 0; /* Temporary use register */ - Expr *pDel = 0; - sqlite3 *db = pParse->db; - - memset(&compLeft, 0, sizeof(Expr)); - memset(&compRight, 0, sizeof(Expr)); - memset(&exprAnd, 0, sizeof(Expr)); - - assert( ExprUseXList(pExpr) ); - pDel = sqlite3ExprDup(db, pExpr->pLeft, 0); - if( db->mallocFailed==0 ){ - exprAnd.op = TK_AND; - exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; - compLeft.op = TK_GE; - compLeft.pLeft = pDel; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; - compRight.op = TK_LE; - compRight.pLeft = pDel; - compRight.pRight = pExpr->x.pList->a[1].pExpr; - sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); - if( xJump ){ - xJump(pParse, &exprAnd, dest, jumpIfNull); - }else{ - /* Mark the expression is being from the ON or USING clause of a join - ** so that the 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_OuterON bit. Bummer. */ - pDel->flags |= EP_OuterON; - sqlite3ExprCodeTarget(pParse, &exprAnd, dest); - } - sqlite3ReleaseTempReg(pParse, regFree1); - } - sqlite3ExprDelete(db, pDel); - - /* Ensure adequate test coverage */ - testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); - testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 ); - testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 ); - testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1!=0 ); - testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 ); - testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1!=0 ); - testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1==0 ); - testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1!=0 ); - testcase( xJump==0 ); -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is true but execution -** continues straight thru if the expression is false. -** -** If the expression evaluates to NULL (neither true nor false), then -** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. -** -** This code depends on the fact that certain token values (ex: TK_EQ) -** are the same as opcode values (ex: OP_Eq) that implement the corresponding -** operation. Special comments in vdbe.c and the mkopcodeh.awk script in -** the make process cause these values to align. Assert()s in the code -** below verify that the numbers are aligned correctly. -*/ -SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - int regFree1 = 0; - int regFree2 = 0; - int r1, r2; - - assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ - if( NEVER(pExpr==0) ) return; /* No way this can happen */ - assert( !ExprHasVVAProperty(pExpr, EP_Immutable) ); - op = pExpr->op; - switch( op ){ - case TK_AND: - case TK_OR: { - Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); - if( pAlt!=pExpr ){ - sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull); - }else if( op==TK_AND ){ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - }else{ - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - } - break; - } - case TK_NOT: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_TRUTH: { - int isNot; /* IS NOT TRUE or IS NOT FALSE */ - int isTrue; /* IS TRUE or IS NOT TRUE */ - testcase( jumpIfNull==0 ); - isNot = pExpr->op2==TK_ISNOT; - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - testcase( isTrue && isNot ); - testcase( !isTrue && isNot ); - if( isTrue ^ isNot ){ - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, - isNot ? SQLITE_JUMPIFNULL : 0); - }else{ - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, - isNot ? SQLITE_JUMPIFNULL : 0); - } - break; - } - case TK_IS: - case TK_ISNOT: - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - op = (op==TK_IS) ? TK_EQ : TK_NE; - jumpIfNull = SQLITE_NULLEQ; - /* no break */ deliberate_fall_through - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; - testcase( jumpIfNull==0 ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull, 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); - assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); - VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); - VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); - VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); - VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); - assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - assert( regFree1==0 || regFree1==r1 ); - if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1); - sqlite3VdbeAddOp2(v, op, r1, dest); - VdbeCoverageIf(v, op==TK_ISNULL); - VdbeCoverageIf(v, op==TK_NOTNULL); - break; - } - case TK_BETWEEN: { - testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(pParse); - int destIfNull = jumpIfNull ? dest : destIfFalse; - sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); - sqlite3VdbeGoto(v, dest); - sqlite3VdbeResolveLabel(v, destIfFalse); - break; - } -#endif - default: { - default_expr: - if( ExprAlwaysTrue(pExpr) ){ - sqlite3VdbeGoto(v, dest); - }else if( ExprAlwaysFalse(pExpr) ){ - /* No-op */ - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); - VdbeCoverage(v); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); - } - break; - } - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is false but execution -** continues straight thru if the expression is true. -** -** If the expression evaluates to NULL (neither true nor false) then -** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull -** is 0. -*/ -SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - int regFree1 = 0; - int regFree2 = 0; - int r1, r2; - - assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ - if( pExpr==0 ) return; - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); - - /* The value of pExpr->op and op are related as follows: - ** - ** pExpr->op op - ** --------- ---------- - ** TK_ISNULL OP_NotNull - ** TK_NOTNULL OP_IsNull - ** TK_NE OP_Eq - ** TK_EQ OP_Ne - ** TK_GT OP_Le - ** TK_LE OP_Gt - ** TK_GE OP_Lt - ** TK_LT OP_Ge - ** - ** For other values of pExpr->op, op is undefined and unused. - ** The value of TK_ and OP_ constants are arranged such that we - ** can compute the mapping above using the following expression. - ** Assert()s verify that the computation is correct. - */ - op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); - - /* Verify correct alignment of TK_ and OP_ constants - */ - assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); - assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); - assert( pExpr->op!=TK_NE || op==OP_Eq ); - assert( pExpr->op!=TK_EQ || op==OP_Ne ); - assert( pExpr->op!=TK_LT || op==OP_Ge ); - assert( pExpr->op!=TK_LE || op==OP_Gt ); - assert( pExpr->op!=TK_GT || op==OP_Le ); - assert( pExpr->op!=TK_GE || op==OP_Lt ); - - switch( pExpr->op ){ - case TK_AND: - case TK_OR: { - Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); - if( pAlt!=pExpr ){ - sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull); - }else if( pExpr->op==TK_AND ){ - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - }else{ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - } - break; - } - case TK_NOT: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_TRUTH: { - int isNot; /* IS NOT TRUE or IS NOT FALSE */ - int isTrue; /* IS TRUE or IS NOT TRUE */ - testcase( jumpIfNull==0 ); - isNot = pExpr->op2==TK_ISNOT; - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - testcase( isTrue && isNot ); - testcase( !isTrue && isNot ); - if( isTrue ^ isNot ){ - /* IS TRUE and IS NOT FALSE */ - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, - isNot ? 0 : SQLITE_JUMPIFNULL); - - }else{ - /* IS FALSE and IS NOT TRUE */ - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, - isNot ? 0 : SQLITE_JUMPIFNULL); - } - break; - } - case TK_IS: - case TK_ISNOT: - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_ISNOT ); - op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; - jumpIfNull = SQLITE_NULLEQ; - /* no break */ deliberate_fall_through - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; - testcase( jumpIfNull==0 ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull,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); - assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); - VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ); - VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); - VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); - VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - assert( regFree1==0 || regFree1==r1 ); - if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1); - sqlite3VdbeAddOp2(v, op, r1, dest); - testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); - testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); - break; - } - case TK_BETWEEN: { - testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_IN: { - if( jumpIfNull ){ - sqlite3ExprCodeIN(pParse, pExpr, dest, dest); - }else{ - int destIfNull = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull); - sqlite3VdbeResolveLabel(v, destIfNull); - } - break; - } -#endif - default: { - default_expr: - if( ExprAlwaysFalse(pExpr) ){ - sqlite3VdbeGoto(v, dest); - }else if( ExprAlwaysTrue(pExpr) ){ - /* no-op */ - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); - VdbeCoverage(v); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); - } - break; - } - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); -} - -/* -** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before -** code generation, and that copy is deleted after code generation. This -** ensures that the original pExpr is unchanged. -*/ -SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ - sqlite3 *db = pParse->db; - Expr *pCopy = sqlite3ExprDup(db, pExpr, 0); - if( db->mallocFailed==0 ){ - sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull); - } - sqlite3ExprDelete(db, pCopy); -} - -/* -** Expression pVar is guaranteed to be an SQL variable. pExpr may be any -** type of expression. -** -** If pExpr is a simple SQL value - an integer, real, string, blob -** or NULL value - then the VDBE currently being prepared is configured -** to re-prepare each time a new value is bound to variable pVar. -** -** Additionally, if pExpr is a simple SQL value and the value is the -** same as that currently bound to variable pVar, non-zero is returned. -** Otherwise, if the values are not the same or if pExpr is not a simple -** SQL value, zero is returned. -** -** If the SQLITE_EnableQPSG flag is set on the database connection, then -** this routine always returns false. -*/ -static SQLITE_NOINLINE int exprCompareVariable( - const Parse *pParse, - const Expr *pVar, - const Expr *pExpr -){ - int res = 2; - int iVar; - sqlite3_value *pL, *pR = 0; - - if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){ - return 0; - } - if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2; - sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR); - if( pR ){ - iVar = pVar->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); - pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB); - if( pL ){ - if( sqlite3_value_type(pL)==SQLITE_TEXT ){ - sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */ - } - res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0; - } - sqlite3ValueFree(pR); - sqlite3ValueFree(pL); - } - return res; -} - -/* -** Do a deep comparison of two expression trees. Return 0 if the two -** expressions are completely identical. Return 1 if they differ only -** by a COLLATE operator at the top level. Return 2 if there are differences -** other than the top-level COLLATE operator. -** -** If any subelement of pB has Expr.iTable==(-1) then it is allowed -** to compare equal to an equivalent element in pA with Expr.iTable==iTab. -** -** The pA side might be using TK_REGISTER. If that is the case and pB is -** not using TK_REGISTER but is otherwise equivalent, then still return 0. -** -** Sometimes this routine will return 2 even if the two expressions -** really are equivalent. If we cannot prove that the expressions are -** identical, we return 2 just to be safe. So if this routine -** returns 2, then you do not really know for certain if the two -** expressions are the same. But if you get a 0 or 1 return, then you -** can be sure the expressions are the same. In the places where -** this routine is used, it does not hurt to get an extra 2 - that -** just might result in some slightly slower code. But returning -** an incorrect 0 or 1 could lead to a malfunction. -** -** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE -** terms in pA with bindings in pParse->pReprepare can be matched against -** literals in pB. The pParse->pVdbe->expmask bitmask is updated for -** each variable referenced. -*/ -SQLITE_PRIVATE int sqlite3ExprCompare( - const Parse *pParse, - const Expr *pA, - const Expr *pB, - int iTab -){ - u32 combinedFlags; - if( pA==0 || pB==0 ){ - return pB==pA ? 0 : 2; - } - if( pParse && pA->op==TK_VARIABLE ){ - return exprCompareVariable(pParse, pA, pB); - } - combinedFlags = pA->flags | pB->flags; - if( combinedFlags & EP_IntValue ){ - if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){ - return 0; - } - return 2; - } - if( pA->op!=pB->op || pA->op==TK_RAISE ){ - if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){ - return 1; - } - if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ - return 1; - } - if( pA->op==TK_AGG_COLUMN && pB->op==TK_COLUMN - && pB->iTable<0 && pA->iTable==iTab - ){ - /* fall through */ - }else{ - return 2; - } - } - 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( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( pA->op==pB->op ); - if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){ - return 2; - } - if( ExprHasProperty(pA,EP_WinFunc) ){ - if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){ - return 2; - } - } -#endif - }else if( pA->op==TK_NULL ){ - return 0; - }else if( pA->op==TK_COLLATE ){ - if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; - }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; - } - } - if( (pA->flags & (EP_Distinct|EP_Commuted)) - != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2; - if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ - if( combinedFlags & EP_xIsSelect ) return 2; - if( (combinedFlags & EP_FixedCol)==0 - && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; - if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; - if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; - if( pA->op!=TK_STRING - && pA->op!=TK_TRUEFALSE - && ALWAYS((combinedFlags & EP_Reduced)==0) - ){ - if( pA->iColumn!=pB->iColumn ) return 2; - if( pA->op2!=pB->op2 && pA->op==TK_TRUTH ) return 2; - if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){ - return 2; - } - } - } - return 0; -} - -/* -** Compare two ExprList objects. Return 0 if they are identical, 1 -** if they are certainly different, or 2 if it is not possible to -** determine if they are identical or not. -** -** If any subelement of pB has Expr.iTable==(-1) then it is allowed -** to compare equal to an equivalent element in pA with Expr.iTable==iTab. -** -** This routine might return non-zero for equivalent ExprLists. The -** only consequence will be disabled optimizations. But this routine -** must never return 0 if the two ExprList objects are different, or -** a malfunction will result. -** -** Two NULL pointers are considered to be the same. But a NULL pointer -** always differs from a non-NULL pointer. -*/ -SQLITE_PRIVATE int 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; - if( pA->nExpr!=pB->nExpr ) return 1; - for(i=0; inExpr; i++){ - int res; - Expr *pExprA = pA->a[i].pExpr; - Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1; - if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res; - } - return 0; -} - -/* -** Like sqlite3ExprCompare() except COLLATE operators at the top-level -** are ignored. -*/ -SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){ - return sqlite3ExprCompare(0, - sqlite3ExprSkipCollate(pA), - sqlite3ExprSkipCollate(pB), - iTab); -} - -/* -** Return non-zero if Expr p can only be true if pNN is not NULL. -** -** Or if seenNot is true, return non-zero if Expr p can only be -** non-NULL if pNN is not NULL -*/ -static int exprImpliesNotNull( - 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 */ -){ - assert( p ); - assert( pNN ); - if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){ - return pNN->op!=TK_NULL; - } - switch( p->op ){ - case TK_IN: { - if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 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; - assert( ExprUseXList(p) ); - pList = p->x.pList; - assert( pList!=0 ); - assert( pList->nExpr==2 ); - if( seenNot ) return 0; - if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1) - || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1) - ){ - return 1; - } - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - case TK_EQ: - case TK_NE: - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_PLUS: - case TK_MINUS: - case TK_BITOR: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: - seenNot = 1; - /* no break */ deliberate_fall_through - case TK_STAR: - case TK_REM: - case TK_BITAND: - case TK_SLASH: { - if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1; - /* no break */ deliberate_fall_through - } - case TK_SPAN: - case TK_COLLATE: - case TK_UPLUS: - case TK_UMINUS: { - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); - } - case TK_TRUTH: { - if( seenNot ) return 0; - if( p->op2!=TK_IS ) return 0; - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - case TK_BITNOT: - case TK_NOT: { - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - } - return 0; -} - -/* -** Return true if the boolean value of the expression is always either -** FALSE or NULL. -*/ -static int sqlite3ExprIsNotTrue(Expr *pExpr){ - int v; - if( pExpr->op==TK_NULL ) return 1; - if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1; - v = 1; - if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1; - return 0; -} - -/* -** Return true if the expression is one of the following: -** -** CASE WHEN x THEN y END -** CASE WHEN x THEN y ELSE NULL END -** CASE WHEN x THEN y ELSE false END -** iif(x,y) -** iif(x,y,NULL) -** iif(x,y,false) -*/ -static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){ - ExprList *pList; - if( pExpr->op==TK_FUNCTION ){ - const char *z = pExpr->u.zToken; - FuncDef *pDef; - if( (z[0]!='i' && z[0]!='I') ) return 0; - if( pExpr->x.pList==0 ) return 0; - pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pDef==0 ) return 0; -#else - if( NEVER(pDef==0) ) return 0; -#endif - if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0; - if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0; - }else if( pExpr->op==TK_CASE ){ - if( pExpr->pLeft!=0 ) return 0; - }else{ - return 0; - } - pList = pExpr->x.pList; - assert( pList!=0 ); - if( pList->nExpr==2 ) return 1; - if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1; - return 0; -} - -/* -** Return true if we can prove the pE2 will always be true if pE1 is -** true. Return false if we cannot complete the proof or if pE2 might -** be false. Examples: -** -** pE1: x==5 pE2: x==5 Result: true -** pE1: x>0 pE2: x==5 Result: false -** pE1: x=21 pE2: x=21 OR y=43 Result: true -** pE1: x!=123 pE2: x IS NOT NULL Result: true -** pE1: x!=?1 pE2: x IS NOT NULL Result: true -** pE1: x IS NULL pE2: x IS NOT NULL Result: false -** pE1: x IS ?2 pE2: x IS NOT NULL Result: false -** pE1: iif(x,y) pE2: x Result: true -** PE1: iif(x,y,0) pE2: x Result: true -** -** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has -** Expr.iTable<0 then assume a table number given by iTab. -** -** If pParse is not NULL, then the values of bound variables in pE1 are -** compared against literal values in pE2 and pParse->pVdbe->expmask is -** modified to record which bound variables are referenced. If pParse -** is NULL, then false will be returned if pE1 contains any bound variables. -** -** When in doubt, return false. Returning true might give a performance -** improvement. Returning false might cause a performance reduction, but -** it will always give the correct answer and is hence always safe. -*/ -SQLITE_PRIVATE int sqlite3ExprImpliesExpr( - const Parse *pParse, - const Expr *pE1, - const Expr *pE2, - int iTab -){ - if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){ - return 1; - } - if( pE2->op==TK_OR - && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab) - || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) ) - ){ - return 1; - } - if( pE2->op==TK_NOTNULL - && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0) - ){ - return 1; - } - if( sqlite3ExprIsIIF(pParse->db, pE1) ){ - return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab); - } - return 0; -} - -/* This is a helper function to impliesNotNullRow(). In this routine, -** set pWalker->eCode to one only if *both* of the input expressions -** separately have the implies-not-null-row property. -*/ -static void bothImplyNotNullRow(Walker *pWalker, Expr *pE1, Expr *pE2){ - if( pWalker->eCode==0 ){ - sqlite3WalkExpr(pWalker, pE1); - if( pWalker->eCode ){ - pWalker->eCode = 0; - sqlite3WalkExpr(pWalker, pE2); - } - } -} - -/* -** This is the Expr node callback for sqlite3ExprImpliesNonNullRow(). -** If the expression node requires that the table at pWalker->iCur -** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. -** -** pWalker->mWFlags is non-zero if this inquiry is being undertaking on -** behalf of a RIGHT JOIN (or FULL JOIN). That makes a difference when -** evaluating terms in the ON clause of an inner join. -** -** This routine controls an optimization. False positives (setting -** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives -** (never setting pWalker->eCode) is a harmless missed optimization. -*/ -static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_AGG_FUNCTION ); - if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune; - if( ExprHasProperty(pExpr, EP_InnerON) && pWalker->mWFlags ){ - /* If iCur is used in an inner-join ON clause to the left of a - ** RIGHT JOIN, that does *not* mean that the table must be non-null. - ** But it is difficult to check for that condition precisely. - ** To keep things simple, any use of iCur from any inner-join is - ** ignored while attempting to simplify a RIGHT JOIN. */ - return WRC_Prune; - } - switch( pExpr->op ){ - case TK_ISNOT: - case TK_ISNULL: - case TK_NOTNULL: - case TK_IS: - case TK_VECTOR: - case TK_FUNCTION: - case TK_TRUTH: - case TK_CASE: - testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_ISNULL ); - testcase( pExpr->op==TK_NOTNULL ); - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_VECTOR ); - testcase( pExpr->op==TK_FUNCTION ); - testcase( pExpr->op==TK_TRUTH ); - testcase( pExpr->op==TK_CASE ); - return WRC_Prune; - - case TK_COLUMN: - if( pWalker->u.iCur==pExpr->iTable ){ - pWalker->eCode = 1; - return WRC_Abort; - } - return WRC_Prune; - - case TK_OR: - case TK_AND: - /* Both sides of an AND or OR must separately imply non-null-row. - ** Consider these cases: - ** 1. NOT (x AND y) - ** 2. x OR y - ** If only one of x or y is non-null-row, then the overall expression - ** can be true if the other arm is false (case 1) or true (case 2). - */ - testcase( pExpr->op==TK_OR ); - testcase( pExpr->op==TK_AND ); - bothImplyNotNullRow(pWalker, pExpr->pLeft, pExpr->pRight); - return WRC_Prune; - - case TK_IN: - /* Beware of "x NOT IN ()" and "x NOT IN (SELECT 1 WHERE false)", - ** both of which can be true. But apart from these cases, if - ** the left-hand side of the IN is NULL then the IN itself will be - ** NULL. */ - if( ExprUseXList(pExpr) && ALWAYS(pExpr->x.pList->nExpr>0) ){ - sqlite3WalkExpr(pWalker, pExpr->pLeft); - } - return WRC_Prune; - - case TK_BETWEEN: - /* In "x NOT BETWEEN y AND z" either x must be non-null-row or else - ** both y and z must be non-null row */ - assert( ExprUseXList(pExpr) ); - assert( pExpr->x.pList->nExpr==2 ); - sqlite3WalkExpr(pWalker, pExpr->pLeft); - bothImplyNotNullRow(pWalker, pExpr->x.pList->a[0].pExpr, - pExpr->x.pList->a[1].pExpr); - return WRC_Prune; - - /* Virtual tables are allowed to use constraints like x=NULL. So - ** a term of the form x=y does not prove that y is not null if x - ** is the column of a virtual table */ - case TK_EQ: - case TK_NE: - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: { - Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - testcase( pExpr->op==TK_EQ ); - testcase( pExpr->op==TK_NE ); - testcase( pExpr->op==TK_LT ); - testcase( pExpr->op==TK_LE ); - testcase( pExpr->op==TK_GT ); - testcase( pExpr->op==TK_GE ); - /* The y.pTab=0 assignment in wherecode.c always happens after the - ** impliesNotNullRow() test */ - assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) ); - assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) ); - 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)) - ){ - return WRC_Prune; - } - /* no break */ deliberate_fall_through - } - default: - return WRC_Continue; - } -} - -/* -** Return true (non-zero) if expression p can only be true if at least -** one column of table iTab is non-null. In other words, return true -** if expression p will always be NULL or false if every column of iTab -** is NULL. -** -** False negatives are acceptable. In other words, it is ok to return -** zero even if expression p will never be true of every column of iTab -** is NULL. A false negative is merely a missed optimization opportunity. -** -** False positives are not allowed, however. A false positive may result -** in an incorrect answer. -** -** 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 -** clause requires that some column of the right table of the LEFT JOIN -** be non-NULL, then the LEFT JOIN can be safely converted into an -** ordinary join. -*/ -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){ - Walker w; - p = sqlite3ExprSkipCollateAndLikely(p); - if( p==0 ) return 0; - if( p->op==TK_NOTNULL ){ - p = p->pLeft; - }else{ - while( p->op==TK_AND ){ - if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1; - p = p->pRight; - } - } - w.xExprCallback = impliesNotNullRow; - w.xSelectCallback = 0; - w.xSelectCallback2 = 0; - w.eCode = 0; - w.mWFlags = isRJ!=0; - w.u.iCur = iTab; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - -/* -** An instance of the following structure is used by the tree walker -** to determine if an expression can be evaluated by reference to the -** index only, without having to do a search for the corresponding -** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur -** is the cursor for the table. -*/ -struct IdxCover { - Index *pIdx; /* The index to be tested for coverage */ - int iCur; /* Cursor number for the table corresponding to the index */ -}; - -/* -** Check to see if there are references to columns in table -** pWalker->u.pIdxCover->iCur can be satisfied using the index -** pWalker->u.pIdxCover->pIdx. -*/ -static int exprIdxCover(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN - && pExpr->iTable==pWalker->u.pIdxCover->iCur - && sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0 - ){ - pWalker->eCode = 1; - return WRC_Abort; - } - return WRC_Continue; -} - -/* -** Determine if an index pIdx on table with cursor iCur contains will -** the expression pExpr. Return true if the index does cover the -** expression and false if the pExpr expression references table columns -** that are not found in the index pIdx. -** -** An index covering an expression means that the expression can be -** evaluated using only the index and without having to lookup the -** corresponding table entry. -*/ -SQLITE_PRIVATE int sqlite3ExprCoveredByIndex( - Expr *pExpr, /* The index to be tested */ - int iCur, /* The cursor number for the corresponding table */ - Index *pIdx /* The index that might be used for coverage */ -){ - Walker w; - struct IdxCover xcov; - memset(&w, 0, sizeof(w)); - xcov.iCur = iCur; - xcov.pIdx = pIdx; - w.xExprCallback = exprIdxCover; - w.u.pIdxCover = &xcov; - sqlite3WalkExpr(&w, pExpr); - return !w.eCode; -} - - -/* Structure used to pass information throughout the Walker in order to -** implement sqlite3ReferencesSrcList(). -*/ -struct RefSrcList { - sqlite3 *db; /* Database connection used for 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 */ -}; - -/* -** Walker SELECT callbacks for 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 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 = 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; inSrc; 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; - } -} - -/* This is the Walker EXPR callback for 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 exprRefToSrcList(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN - || pExpr->op==TK_AGG_COLUMN - ){ - int i; - struct RefSrcList *p = pWalker->u.pRefSrcList; - SrcList *pSrc = p->pRef; - int nSrc = pSrc ? pSrc->nSrc : 0; - for(i=0; iiTable==pSrc->a[i].iCursor ){ - pWalker->eCode |= 1; - return WRC_Continue; - } - } - for(i=0; inExclude && p->aiExclude[i]!=pExpr->iTable; i++){} - if( i>=p->nExclude ){ - pWalker->eCode |= 2; - } - } - return WRC_Continue; -} - -/* -** 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 sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){ - Walker w; - struct RefSrcList x; - assert( pParse->db!=0 ); - memset(&w, 0, sizeof(w)); - 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) ); - sqlite3WalkExprList(&w, pExpr->x.pList); - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - assert( pExpr->pLeft->x.pList!=0 ); - sqlite3WalkExprList(&w, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter); - } -#endif - if( x.aiExclude ) sqlite3DbNNFreeNN(pParse->db, x.aiExclude); - if( w.eCode & 0x01 ){ - return 1; - }else if( w.eCode ){ - return 0; - }else{ - return -1; - } -} - -/* -** This is a Walker expression node callback. -** -** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo -** object that is referenced does not refer directly to the Expr. If -** it does, make a copy. This is done because the pExpr argument is -** subject to change. -** -** The copy is scheduled for deletion using the sqlite3ExprDeferredDelete() -** which builds on the sqlite3ParserAddCleanup() mechanism. -*/ -static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ - if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced)) - && pExpr->pAggInfo!=0 - ){ - AggInfo *pAggInfo = pExpr->pAggInfo; - int iAgg = pExpr->iAgg; - Parse *pParse = pWalker->pParse; - sqlite3 *db = pParse->db; - assert( iAgg>=0 ); - if( pExpr->op!=TK_AGG_FUNCTION ){ - if( iAggnColumn - && pAggInfo->aCol[iAgg].pCExpr==pExpr - ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ - pAggInfo->aCol[iAgg].pCExpr = pExpr; - } - } - }else{ - assert( pExpr->op==TK_AGG_FUNCTION ); - if( ALWAYS(iAggnFunc) - && pAggInfo->aFunc[iAgg].pFExpr==pExpr - ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ - pAggInfo->aFunc[iAgg].pFExpr = pExpr; - } - } - } - } - return WRC_Continue; -} - -/* -** Initialize a Walker object so that will persist AggInfo entries referenced -** by the tree that is walked. -*/ -SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){ - memset(pWalker, 0, sizeof(*pWalker)); - pWalker->pParse = pParse; - pWalker->xExprCallback = agginfoPersistExprCb; - pWalker->xSelectCallback = sqlite3SelectWalkNoop; -} - -/* -** Add a new element to the pAggInfo->aCol[] array. Return the index of -** the new element. Return a negative number if malloc fails. -*/ -static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ - int i; - pInfo->aCol = sqlite3ArrayAllocate( - db, - pInfo->aCol, - sizeof(pInfo->aCol[0]), - &pInfo->nColumn, - &i - ); - return i; -} - -/* -** Add a new element to the pAggInfo->aFunc[] array. Return the index of -** the new element. Return a negative number if malloc fails. -*/ -static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ - int i; - pInfo->aFunc = sqlite3ArrayAllocate( - db, - pInfo->aFunc, - sizeof(pInfo->aFunc[0]), - &pInfo->nFunc, - &i - ); - return i; -} - -/* -** Search the AggInfo object for an aCol[] entry that has iTable and iColumn. -** Return the index in aCol[] of the entry that describes that column. -** -** If no prior entry is found, create a new one and return -1. The -** new column will have an index of pAggInfo->nColumn-1. -*/ -static void findOrCreateAggInfoColumn( - Parse *pParse, /* Parsing context */ - AggInfo *pAggInfo, /* The AggInfo object to search and/or modify */ - Expr *pExpr /* Expr describing the column to find or insert */ -){ - struct AggInfo_col *pCol; - int k; - int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; - - assert( mxTerm <= SMXV(i16) ); - assert( pAggInfo->iFirstReg==0 ); - pCol = pAggInfo->aCol; - for(k=0; knColumn; k++, pCol++){ - if( pCol->pCExpr==pExpr ) return; - if( pCol->iTable==pExpr->iTable - && pCol->iColumn==pExpr->iColumn - && pExpr->op!=TK_IF_NULL_ROW - ){ - goto fix_up_expr; - } - } - k = addAggInfoColumn(pParse->db, pAggInfo); - if( k<0 ){ - /* OOM on resize */ - assert( pParse->db->mallocFailed ); - return; - } - if( k>mxTerm ){ - sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); - k = mxTerm; - } - pCol = &pAggInfo->aCol[k]; - assert( ExprUseYTab(pExpr) ); - pCol->pTab = pExpr->y.pTab; - pCol->iTable = pExpr->iTable; - pCol->iColumn = pExpr->iColumn; - pCol->iSorterColumn = -1; - pCol->pCExpr = pExpr; - if( pAggInfo->pGroupBy && pExpr->op!=TK_IF_NULL_ROW ){ - int j, n; - ExprList *pGB = pAggInfo->pGroupBy; - struct ExprList_item *pTerm = pGB->a; - n = pGB->nExpr; - for(j=0; jpExpr; - if( pE->op==TK_COLUMN - && pE->iTable==pExpr->iTable - && pE->iColumn==pExpr->iColumn - ){ - pCol->iSorterColumn = j; - break; - } - } - } - if( pCol->iSorterColumn<0 ){ - pCol->iSorterColumn = pAggInfo->nSortingColumn++; - } -fix_up_expr: - ExprSetVVAProperty(pExpr, EP_NoReduce); - assert( pExpr->pAggInfo==0 || pExpr->pAggInfo==pAggInfo ); - pExpr->pAggInfo = pAggInfo; - if( pExpr->op==TK_COLUMN ){ - pExpr->op = TK_AGG_COLUMN; - } - assert( k <= SMXV(pExpr->iAgg) ); - pExpr->iAgg = (i16)k; -} - -/* -** This is the xExprCallback for a tree walker. It is used to -** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates -** for additional information. -*/ -static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ - int i; - NameContext *pNC = pWalker->u.pNC; - Parse *pParse = pNC->pParse; - SrcList *pSrcList = pNC->pSrcList; - AggInfo *pAggInfo = pNC->uNC.pAggInfo; - - assert( pNC->ncFlags & NC_UAggInfo ); - assert( pAggInfo->iFirstReg==0 ); - switch( pExpr->op ){ - default: { - IndexedExpr *pIEpr; - Expr tmp; - assert( pParse->iSelfTab==0 ); - if( (pNC->ncFlags & NC_InAggFunc)==0 ) break; - if( pParse->pIdxEpr==0 ) break; - for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ - int iDataCur = pIEpr->iDataCur; - if( iDataCur<0 ) continue; - if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break; - } - if( pIEpr==0 ) break; - if( NEVER(!ExprUseYTab(pExpr)) ) break; - for(i=0; inSrc; i++){ - if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break; - } - if( i>=pSrcList->nSrc ) break; - if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */ - if( pParse->nErr ){ return WRC_Abort; } - - /* If we reach this point, it means that expression pExpr can be - ** translated into a reference to an index column as described by - ** pIEpr. - */ - memset(&tmp, 0, sizeof(tmp)); - tmp.op = TK_AGG_COLUMN; - tmp.iTable = pIEpr->iIdxCur; - tmp.iColumn = pIEpr->iIdxCol; - findOrCreateAggInfoColumn(pParse, pAggInfo, &tmp); - if( pParse->nErr ){ return WRC_Abort; } - assert( pAggInfo->aCol!=0 ); - assert( tmp.iAggnColumn ); - pAggInfo->aCol[tmp.iAgg].pCExpr = pExpr; - pExpr->pAggInfo = pAggInfo; - pExpr->iAgg = tmp.iAgg; - return WRC_Prune; - } - case TK_IF_NULL_ROW: - case TK_AGG_COLUMN: - case TK_COLUMN: { - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_COLUMN ); - testcase( pExpr->op==TK_IF_NULL_ROW ); - /* Check to see if the column is in one of the tables in the FROM - ** clause of the aggregate query */ - if( ALWAYS(pSrcList!=0) ){ - SrcItem *pItem = pSrcList->a; - for(i=0; inSrc; i++, pItem++){ - assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - if( pExpr->iTable==pItem->iCursor ){ - findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr); - break; - } /* endif pExpr->iTable==pItem->iCursor */ - } /* end loop over pSrcList */ - } - return WRC_Continue; - } - case TK_AGG_FUNCTION: { - if( (pNC->ncFlags & NC_InAggFunc)==0 - && pWalker->walkerDepth==pExpr->op2 - && pExpr->pAggInfo==0 - ){ - /* Check to see if pExpr is a duplicate of another aggregate - ** function that is already in the pAggInfo structure - */ - struct AggInfo_func *pItem = pAggInfo->aFunc; - int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; - assert( mxTerm <= SMXV(i16) ); - for(i=0; inFunc; i++, pItem++){ - if( NEVER(pItem->pFExpr==pExpr) ) break; - if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ - break; - } - } - if( i>mxTerm ){ - sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); - i = mxTerm; - assert( inFunc ); - }else if( i>=pAggInfo->nFunc ){ - /* pExpr is original. Make a new entry in pAggInfo->aFunc[] - */ - u8 enc = ENC(pParse->db); - i = addAggInfoFunc(pParse->db, pAggInfo); - if( i>=0 ){ - int nArg; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pItem = &pAggInfo->aFunc[i]; - pItem->pFExpr = pExpr; - assert( ExprUseUToken(pExpr) ); - nArg = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; - pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, nArg, enc, 0); - assert( pItem->bOBUnique==0 ); - if( pExpr->pLeft - && (pItem->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)==0 - ){ - /* The NEEDCOLL test above causes any ORDER BY clause on - ** aggregate min() or max() to be ignored. */ - ExprList *pOBList; - assert( nArg>0 ); - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - pItem->iOBTab = pParse->nTab++; - pOBList = pExpr->pLeft->x.pList; - assert( pOBList->nExpr>0 ); - assert( pItem->bOBUnique==0 ); - if( pOBList->nExpr==1 - && nArg==1 - && sqlite3ExprCompare(0,pOBList->a[0].pExpr, - pExpr->x.pList->a[0].pExpr,0)==0 - ){ - pItem->bOBPayload = 0; - pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); - }else{ - pItem->bOBPayload = 1; - } - pItem->bUseSubtype = - (pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0; - }else{ - pItem->iOBTab = -1; - } - if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ - pItem->iDistinct = pParse->nTab++; - }else{ - pItem->iDistinct = -1; - } - } - } - /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry - */ - assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - ExprSetVVAProperty(pExpr, EP_NoReduce); - assert( i <= SMXV(pExpr->iAgg) ); - pExpr->iAgg = (i16)i; - pExpr->pAggInfo = pAggInfo; - return WRC_Prune; - }else{ - return WRC_Continue; - } - } - } - return WRC_Continue; -} - -/* -** Analyze the pExpr expression looking for aggregate functions and -** for variables that need to be added to AggInfo object that pNC->pAggInfo -** points to. Additional entries are made on the AggInfo object as -** necessary. -** -** This routine should only be called after the expression has been -** analyzed by sqlite3ResolveExprNames(). -*/ -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ - Walker w; - w.xExprCallback = analyzeAggregate; - w.xSelectCallback = sqlite3WalkerDepthIncrease; - w.xSelectCallback2 = sqlite3WalkerDepthDecrease; - w.walkerDepth = 0; - w.u.pNC = pNC; - w.pParse = 0; - assert( pNC->pSrcList!=0 ); - sqlite3WalkExpr(&w, pExpr); -} - -/* -** Call sqlite3ExprAnalyzeAggregates() for every expression in an -** expression list. Return the number of errors. -** -** If an error is found, the analysis is cut short. -*/ -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ - struct ExprList_item *pItem; - int i; - if( pList ){ - for(pItem=pList->a, i=0; inExpr; i++, pItem++){ - sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); - } - } -} - -/* -** Allocate a single new register for use to hold some intermediate result. -*/ -SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ - if( pParse->nTempReg==0 ){ - return ++pParse->nMem; - } - return pParse->aTempReg[--pParse->nTempReg]; -} - -/* -** Deallocate a register, making available for reuse for some other -** purpose. -*/ -SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ - if( iReg ){ - sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0); - if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = iReg; - } - } -} - -/* -** Allocate or deallocate a block of nReg consecutive registers. -*/ -SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ - int i, n; - if( nReg==1 ) return sqlite3GetTempReg(pParse); - i = pParse->iRangeReg; - n = pParse->nRangeReg; - if( nReg<=n ){ - pParse->iRangeReg += nReg; - pParse->nRangeReg -= nReg; - }else{ - i = pParse->nMem+1; - pParse->nMem += nReg; - } - return i; -} -SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ - if( nReg==1 ){ - sqlite3ReleaseTempReg(pParse, iReg); - return; - } - sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0, 0); - if( nReg>pParse->nRangeReg ){ - pParse->nRangeReg = nReg; - pParse->iRangeReg = iReg; - } -} - -/* -** Mark all temporary registers as being unavailable for reuse. -** -** Always invoke this procedure after coding a subroutine or co-routine -** that might be invoked from other parts of the code, to ensure that -** the sub/co-routine does not use registers in common with the code that -** invokes the sub/co-routine. -*/ -SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ - pParse->nTempReg = 0; - pParse->nRangeReg = 0; -} - -/* -** Make sure sufficient registers have been allocated so that -** iReg is a valid register number. -*/ -SQLITE_PRIVATE void sqlite3TouchRegister(Parse *pParse, int iReg){ - if( pParse->nMemnMem = iReg; -} - -#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG) -/* -** Return the latest reusable register in the set of all registers. -** The value returned is no less than iMin. If any register iMin or -** greater is in permanent use, then return one more than that last -** permanent register. -*/ -SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse *pParse, int iMin){ - const ExprList *pList = pParse->pConstExpr; - if( pList ){ - int i; - for(i=0; inExpr; i++){ - if( pList->a[i].u.iConstExprReg>=iMin ){ - iMin = pList->a[i].u.iConstExprReg + 1; - } - } - } - pParse->nTempReg = 0; - pParse->nRangeReg = 0; - return iMin; -} -#endif /* SQLITE_ENABLE_STAT4 || SQLITE_DEBUG */ - -/* -** Validate that no temporary register falls within the range of -** iFirst..iLast, inclusive. This routine is only call from within assert() -** statements. -*/ -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ - int i; - if( pParse->nRangeReg>0 - && pParse->iRangeReg+pParse->nRangeReg > iFirst - && pParse->iRangeReg <= iLast - ){ - return 0; - } - for(i=0; inTempReg; i++){ - if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){ - return 0; - } - } - if( pParse->pConstExpr ){ - ExprList *pList = pParse->pConstExpr; - for(i=0; inExpr; i++){ - int iReg = pList->a[i].u.iConstExprReg; - if( iReg==0 ) continue; - if( iReg>=iFirst && iReg<=iLast ) return 0; - } - } - return 1; -} -#endif /* SQLITE_DEBUG */ - -/************** End of expr.c ************************************************/ -/************** Begin file alter.c *******************************************/ -/* -** 2005 February 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that used to generate VDBE code -** that implements the ALTER TABLE command. -*/ -/* #include "sqliteInt.h" */ - -/* -** The code in this file only exists if we are not omitting the -** ALTER TABLE logic from the build. -*/ -#ifndef SQLITE_OMIT_ALTERTABLE - -/* -** Parameter zName is the name of a table that is about to be altered -** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). -** If the table is a system table, this function leaves an error message -** in pParse->zErr (system tables may not be altered) and returns non-zero. -** -** Or, if zName is not a system table, zero is returned. -*/ -static int isAlterableTable(Parse *pParse, Table *pTab){ - if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) -#ifndef SQLITE_OMIT_VIRTUALTABLE - || (pTab->tabFlags & TF_Eponymous)!=0 - || ( (pTab->tabFlags & TF_Shadow)!=0 - && sqlite3ReadOnlyShadowTables(pParse->db) - ) -#endif - ){ - sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); - return 1; - } - return 0; -} - -/* -** Generate code to verify that the schemas of database zDb and, if -** bTemp is not true, database "temp", can still be parsed. This is -** called at the end of the generation of an ALTER TABLE ... RENAME ... -** statement to ensure that the operation has not rendered any schema -** objects unusable. -*/ -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; - sqlite3NestedParse(pParse, - "SELECT 1 " - "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, %Q, %d)=NULL ", - zDb, - zDb, bTemp, zWhen, bNoDQS - ); - - if( bTemp==0 ){ - sqlite3NestedParse(pParse, - "SELECT 1 " - "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, %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){ - 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 ){ - 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%%'" - ); - } -} - -/* -** 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, u16 p5){ - Vdbe *v = pParse->pVdbe; - if( v ){ - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5); - if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5); - } -} - -/* -** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" -** command. -*/ -SQLITE_PRIVATE void sqlite3AlterRenameTable( - Parse *pParse, /* Parser context. */ - SrcList *pSrc, /* The table to rename. */ - Token *pName /* The new table name. */ -){ - int iDb; /* Database that contains the table */ - char *zDb; /* Name of database iDb */ - Table *pTab; /* Table being renamed */ - char *zName = 0; /* NULL-terminated version of pName */ - sqlite3 *db = pParse->db; /* Database connection */ - int nTabName; /* Number of UTF-8 characters in zTabName */ - const char *zTabName; /* Original name of the table */ - Vdbe *v; - VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ - - if( NEVER(db->mallocFailed) ) goto exit_rename_table; - assert( pSrc->nSrc==1 ); - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_rename_table; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - zDb = db->aDb[iDb].zDbSName; - - /* Get a NULL terminated version of the new table name. */ - zName = sqlite3NameFromToken(db, pName); - if( !zName ) goto exit_rename_table; - - /* Check that a table or index named 'zName' does not already exist - ** in database iDb. If so, this is an error. - */ - if( sqlite3FindTable(db, zName, zDb) - || sqlite3FindIndex(db, zName, zDb) - || sqlite3IsShadowTableOf(db, pTab, zName) - ){ - sqlite3ErrorMsg(pParse, - "there is already another table or index with this name: %s", zName); - goto exit_rename_table; - } - - /* Make sure it is not a system table being altered, or a reserved name - ** that the table is being renamed to. - */ - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ - goto exit_rename_table; - } - if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){ - goto exit_rename_table; - } - -#ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); - goto exit_rename_table; - } -#endif - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - goto exit_rename_table; - } -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto exit_rename_table; - } - if( IsVirtual(pTab) ){ - pVTab = sqlite3GetVTable(db, pTab); - if( pVTab->pVtab->pModule->xRename==0 ){ - pVTab = 0; - } - } -#endif - - /* Begin a transaction for database iDb. Then modify the schema cookie - ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(), - ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the - ** nested SQL may raise an exception. */ - v = sqlite3GetVdbe(pParse); - if( v==0 ){ - goto exit_rename_table; - } - sqlite3MayAbort(pParse); - - /* figure out how many UTF-8 characters are in zName */ - zTabName = pTab->zName; - nTabName = sqlite3Utf8CharLen(zTabName, -1); - - /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in - ** the schema to use the new table name. */ - sqlite3NestedParse(pParse, - "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'" - , zDb, zDb, zTabName, zName, (iDb==1), zTabName - ); - - /* Update the tbl_name and name columns of the sqlite_schema table - ** as required. */ - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET " - "tbl_name = %Q, " - "name = CASE " - "WHEN type='table' THEN %Q " - "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' " - " AND type='index' THEN " - "'sqlite_autoindex_' || %Q || substr(name,%d+18) " - "ELSE name END " - "WHERE tbl_name=%Q COLLATE nocase AND " - "(type='table' OR type='index' OR type='trigger');", - zDb, - zName, zName, zName, - nTabName, zTabName - ); - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* If the sqlite_sequence table exists in this database, then update - ** it with the new table name. - */ - if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ - sqlite3NestedParse(pParse, - "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", - zDb, zName, pTab->zName); - } -#endif - - /* If the table being renamed is not itself part of the temp database, - ** edit view and trigger definitions within the temp database - ** as required. */ - if( iDb!=1 ){ - sqlite3NestedParse(pParse, - "UPDATE sqlite_temp_schema SET " - "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, 'after rename', 0) " - "THEN %Q ELSE tbl_name END " - "WHERE type IN ('view', 'trigger')" - , zDb, zTabName, zName, zTabName, zDb, zName); - } - - /* If this is a virtual table, invoke the xRename() function if - ** one is defined. The xRename() callback will modify the names - ** of any resources used by the v-table implementation (including other - ** SQLite tables) that are identified by the name of the virtual table. - */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pVTab ){ - int i = ++pParse->nMem; - sqlite3VdbeLoadString(v, i, zName); - sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); - } -#endif - - renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); - renameTestSchema(pParse, zDb, iDb==1, "after rename", 0); - -exit_rename_table: - sqlite3SrcListDelete(db, pSrc); - sqlite3DbFree(db, zName); -} - -/* -** Write code that will raise an error if the table described by -** zDb and zTab is not empty. -*/ -static void sqlite3ErrorIfNotEmpty( - Parse *pParse, /* Parsing context */ - const char *zDb, /* Schema holding the table */ - const char *zTab, /* Table to check for empty */ - const char *zErr /* Error message text */ -){ - sqlite3NestedParse(pParse, - "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", - zErr, zDb, zTab - ); -} - -/* -** This function is called after an "ALTER TABLE ... ADD" statement -** has been parsed. Argument pColDef contains the text of the new -** column definition. -** -** The Table structure pParse->pNewTable was extended to include -** the new column during parsing. -*/ -SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ - Table *pNew; /* Copy of pParse->pNewTable */ - Table *pTab; /* Table being altered */ - int iDb; /* Database number */ - const char *zDb; /* Database name */ - const char *zTab; /* Table name */ - char *zCol; /* Null-terminated column definition */ - Column *pCol; /* The new column */ - Expr *pDflt; /* Default value for the new column */ - sqlite3 *db; /* The database connection; */ - Vdbe *v; /* The prepared statement under construction */ - int r1; /* Temporary registers */ - - db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ) return; - assert( db->mallocFailed==0 ); - pNew = pParse->pNewTable; - assert( pNew ); - - assert( sqlite3BtreeHoldsAllMutexes(db) ); - iDb = sqlite3SchemaToIndex(db, pNew->pSchema); - zDb = db->aDb[iDb].zDbSName; - zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ - pCol = &pNew->aCol[pNew->nCol-1]; - pDflt = sqlite3ColumnExpr(pNew, pCol); - pTab = sqlite3FindTable(db, zTab, zDb); - assert( pTab ); - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - return; - } -#endif - - - /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. - ** If there is a NOT NULL constraint, then the default value for the - ** column must not be NULL. - */ - if( pCol->colFlags & COLFLAG_PRIMKEY ){ - sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); - return; - } - if( pNew->pIndex ){ - sqlite3ErrorMsg(pParse, - "Cannot add a UNIQUE column"); - return; - } - if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){ - /* If the default value for the new column was specified with a - ** literal NULL, then set pDflt to 0. This simplifies checking - ** for an SQL NULL default below. - */ - assert( pDflt==0 || pDflt->op==TK_SPAN ); - if( pDflt && pDflt->pLeft->op==TK_NULL ){ - pDflt = 0; - } - assert( IsOrdinaryTable(pNew) ); - if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a REFERENCES column with non-NULL default value"); - } - if( pCol->notNull && !pDflt ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a NOT NULL column with default value NULL"); - } - - - /* Ensure the default expression is something that sqlite3ValueFromExpr() - ** can handle (i.e. not CURRENT_TIME etc.) - */ - if( pDflt ){ - sqlite3_value *pVal = 0; - int rc; - rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - if( rc!=SQLITE_OK ){ - assert( db->mallocFailed == 1 ); - return; - } - if( !pVal ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a column with non-constant default"); - } - sqlite3ValueFree(pVal); - } - }else if( pCol->colFlags & COLFLAG_STORED ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column"); - } - - - /* Modify the CREATE TABLE statement. */ - zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); - if( zCol ){ - char *zEnd = &zCol[pColDef->n-1]; - while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ - *zEnd-- = '\0'; - } - /* 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) ); - sqlite3NestedParse(pParse, - "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->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset, - zTab - ); - sqlite3DbFree(db, zCol); - } - - v = 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 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); - sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); - sqlite3ReleaseTempReg(pParse, r1); - - /* 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) - || (pTab->tabFlags & TF_Strict)!=0 - ){ - sqlite3NestedParse(pParse, - "SELECT CASE WHEN quick_check GLOB 'CHECK*'" - " THEN raise(ABORT,'CHECK constraint failed')" - " WHEN quick_check GLOB 'non-* value in*'" - " THEN raise(ABORT,'type mismatch on DEFAULT')" - " ELSE raise(ABORT,'NOT NULL constraint failed')" - " END" - " FROM pragma_quick_check(%Q,%Q)" - " WHERE quick_check GLOB 'CHECK*'" - " OR quick_check GLOB 'NULL*'" - " OR quick_check GLOB 'non-* value in*'", - zTab, zDb - ); - } - } -} - -/* -** This function is called by the parser after the table-name in -** an "ALTER TABLE ADD" statement is parsed. Argument -** pSrc is the full-name of the table being altered. -** -** This routine makes a (partial) copy of the Table structure -** for the table being altered and sets Parse.pNewTable to point -** to it. Routines called by the parser as the column definition -** is parsed (i.e. sqlite3AddColumn()) add the new Column data to -** the copy. The copy of the Table structure is deleted by tokenize.c -** after parsing is finished. -** -** Routine sqlite3AlterFinishAddColumn() will be called to complete -** coding the "ALTER TABLE ... ADD" statement. -*/ -SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ - Table *pNew; - Table *pTab; - int iDb; - int i; - int nAlloc; - sqlite3 *db = pParse->db; - - /* Look up the table being altered. */ - assert( pParse->pNewTable==0 ); - assert( sqlite3BtreeHoldsAllMutexes(db) ); - if( db->mallocFailed ) goto exit_begin_add_column; - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_begin_add_column; - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); - goto exit_begin_add_column; - } -#endif - - /* Make sure this is not an attempt to ALTER a view. */ - if( IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); - goto exit_begin_add_column; - } - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ - goto exit_begin_add_column; - } - - sqlite3MayAbort(pParse); - assert( IsOrdinaryTable(pTab) ); - assert( pTab->u.tab.addColOffset>0 ); - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - - /* Put a copy of the Table struct in Parse.pNewTable for the - ** sqlite3AddColumn() function and friends to modify. But modify - ** the name by adding an "sqlite_altertab_" prefix. By adding this - ** prefix, we insure that the name will not collide with an existing - ** table because user table are not allowed to have the "sqlite_" - ** prefix on their name. - */ - pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); - if( !pNew ) goto exit_begin_add_column; - pParse->pNewTable = pNew; - pNew->nTabRef = 1; - pNew->nCol = pTab->nCol; - assert( pNew->nCol>0 ); - nAlloc = (((pNew->nCol-1)/8)*8)+8; - assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); - pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc); - pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); - if( !pNew->aCol || !pNew->zName ){ - assert( db->mallocFailed ); - goto exit_begin_add_column; - } - memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol); - for(i=0; inCol; i++){ - Column *pCol = &pNew->aCol[i]; - pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName); - pCol->hName = sqlite3StrIHash(pCol->zCnName); - } - assert( IsOrdinaryTable(pNew) ); - pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0); - pNew->pSchema = db->aDb[iDb].pSchema; - pNew->u.tab.addColOffset = pTab->u.tab.addColOffset; - assert( pNew->nTabRef==1 ); - -exit_begin_add_column: - sqlite3SrcListDelete(db, pSrc); - return; -} - -/* -** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN -** command. This function checks if the table is a view or virtual -** table (columns of views or virtual tables may not be renamed). If so, -** it loads an error message into pParse and returns non-zero. -** -** 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, int bDrop){ - const char *zType = 0; -#ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ - zType = "view"; - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - zType = "virtual table"; - } -#endif - if( zType ){ - 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,z) (0) -#endif - -/* -** Handles the following parser reduction: -** -** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew -*/ -SQLITE_PRIVATE void sqlite3AlterRenameColumn( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ - Token *pOld, /* Name of column being changed */ - Token *pNew /* New column name */ -){ - sqlite3 *db = pParse->db; /* Database connection */ - Table *pTab; /* Table being updated */ - int iCol; /* Index of column being renamed */ - char *zOld = 0; /* Old column name */ - char *zNew = 0; /* New column name */ - const char *zDb; /* Name of schema containing the table */ - int iSchema; /* Index of the schema */ - int bQuote; /* True to quote the new name */ - - /* Locate the table to be altered */ - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_rename_column; - - /* Cannot alter a system table */ - if( SQLITE_OK!=isAlterableTable(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 = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iSchema>=0 ); - zDb = db->aDb[iSchema].zDbSName; - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - goto exit_rename_column; - } -#endif - - /* Make sure the old name really is a column name in the table to be - ** altered. Set iCol to be the index of the column being renamed */ - zOld = sqlite3NameFromToken(db, pOld); - if( !zOld ) goto exit_rename_column; - iCol = sqlite3ColumnIndex(pTab, zOld); - if( iCol<0 ){ - 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. - */ - sqlite3MayAbort(pParse); - zNew = sqlite3NameFromToken(db, pNew); - if( !zNew ) goto exit_rename_column; - assert( pNew->n>0 ); - bQuote = sqlite3Isquote(pNew->z[0]); - sqlite3NestedParse(pParse, - "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)", - zDb, - zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, - pTab->zName - ); - - sqlite3NestedParse(pParse, - "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, INITFLAG_AlterRename); - renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1); - - exit_rename_column: - sqlite3SrcListDelete(db, pSrc); - sqlite3DbFree(db, zOld); - sqlite3DbFree(db, zNew); - return; -} - -/* -** Each RenameToken object maps an element of the parse tree into -** the token that generated that element. The parse tree element -** might be one of: -** -** * A pointer to an Expr that represents an ID -** * The name of a table column in Column.zName -** -** A list of RenameToken objects can be constructed during parsing. -** Each new object is created by sqlite3RenameTokenMap(). -** As the parse tree is transformed, the sqlite3RenameTokenRemap() -** routine is used to keep the mapping current. -** -** After the parse finishes, renameTokenFind() routine can be used -** to look up the actual token value that created some element in -** the parse tree. -*/ -struct RenameToken { - 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 */ -}; - -/* -** The context of an ALTER TABLE RENAME COLUMN operation that gets passed -** down into the Walker. -*/ -typedef struct RenameCtx RenameCtx; -struct RenameCtx { - RenameToken *pList; /* List of tokens to overwrite */ - int nList; /* Number of tokens in pList */ - int iCol; /* Index of column being renamed */ - Table *pTab; /* Table being ALTERed */ - const char *zOld; /* Old column name */ -}; - -#ifdef SQLITE_DEBUG -/* -** This function is only for debugging. It performs two tasks: -** -** 1. Checks that pointer pPtr does not already appear in the -** rename-token list. -** -** 2. Dereferences each pointer in the rename-token list. -** -** The second is most effective when debugging under valgrind or -** address-sanitizer or similar. If any of these pointers no longer -** point to valid objects, an exception is raised by the memory-checking -** tool. -** -** The point of this is to prevent comparisons of invalid pointer values. -** Even though this always seems to work, it is undefined according to the -** C standard. Example of undefined comparison: -** -** sqlite3_free(x); -** if( x==y ) ... -** -** 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, const void *pPtr){ - assert( pParse==pParse->db->pParse ); - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); - if( pParse->nErr==0 ){ - const RenameToken *p; - u32 i = 1; - for(p=pParse->pRename; p; p=p->pNext){ - if( p->p ){ - assert( p->p!=pPtr ); - i += *(u8*)(p->p) | 1; - } - } - assert( i>0 ); - } -} -#else -# define renameTokenCheckAll(x,y) -#endif - -/* -** Remember that the parser tree element pPtr was created using -** the token pToken. -** -** In other words, construct a new RenameToken object and add it -** to the list of RenameToken objects currently being built up -** in pParse->pRename. -** -** The pPtr argument is returned so that this routine can be used -** with tail recursion in tokenExpr() routine, for a small performance -** improvement. -*/ -SQLITE_PRIVATE const void *sqlite3RenameTokenMap( - Parse *pParse, - const void *pPtr, - const Token *pToken -){ - RenameToken *pNew; - assert( pPtr || pParse->db->mallocFailed ); - renameTokenCheckAll(pParse, pPtr); - if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){ - pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); - if( pNew ){ - pNew->p = pPtr; - pNew->t = *pToken; - pNew->pNext = pParse->pRename; - pParse->pRename = pNew; - } - } - - return pPtr; -} - -/* -** It is assumed that there is already a RenameToken object associated -** with parse tree element pFrom. This function remaps the associated token -** to parse tree element pTo. -*/ -SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){ - RenameToken *p; - renameTokenCheckAll(pParse, pTo); - for(p=pParse->pRename; p; p=p->pNext){ - if( p->p==pFrom ){ - p->p = pTo; - break; - } - } -} - -/* -** Walker callback used by sqlite3RenameExprUnmap(). -*/ -static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ - Parse *pParse = pWalker->pParse; - sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr); - if( ExprUseYTab(pExpr) ){ - sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab); - } - return WRC_Continue; -} - -/* -** Iterate through the Select objects that are part of WITH clauses attached -** to select statement pSelect. -*/ -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 = sqlite3WithDup(pParse->db, pWith); - pCopy = sqlite3WithPush(pParse, pCopy, 1); - } - for(i=0; inCte; i++){ - Select *p = pWith->a[i].pSelect; - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC); - if( sNC.pParse->db->mallocFailed ) return; - sqlite3WalkSelect(pWalker, p); - sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols); - } - if( pCopy && pParse->pWith==pCopy ){ - pParse->pWith = pCopy->pOuter; - } - } -} - -/* -** Unmap all tokens in the IdList object passed as the second argument. -*/ -static void unmapColumnIdlistNames( - Parse *pParse, - const IdList *pIdList -){ - int ii; - assert( pIdList!=0 ); - for(ii=0; iinId; ii++){ - sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName); - } -} - -/* -** Walker callback used by sqlite3RenameExprUnmap(). -*/ -static int renameUnmapSelectCb(Walker *pWalker, Select *p){ - Parse *pParse = pWalker->pParse; - int i; - if( pParse->nErr ) return WRC_Abort; - 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; inExpr; i++){ - if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); - } - } - } - if( ALWAYS(p->pSrc) ){ /* Every Select as a SrcList, even if it is empty */ - SrcList *pSrc = p->pSrc; - for(i=0; inSrc; i++){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName); - if( pSrc->a[i].fg.isUsing==0 ){ - sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn); - }else{ - unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing); - } - } - } - - renameWalkWith(pWalker, p); - return WRC_Continue; -} - -/* -** Remove all nodes that are part of expression pExpr from the rename list. -*/ -SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ - u8 eMode = pParse->eParseMode; - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = pParse; - sWalker.xExprCallback = renameUnmapExprCb; - sWalker.xSelectCallback = renameUnmapSelectCb; - pParse->eParseMode = PARSE_MODE_UNMAP; - sqlite3WalkExpr(&sWalker, pExpr); - pParse->eParseMode = eMode; -} - -/* -** Remove all nodes that are part of expression-list pEList from the -** rename list. -*/ -SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ - if( pEList ){ - int i; - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = pParse; - sWalker.xExprCallback = renameUnmapExprCb; - sqlite3WalkExprList(&sWalker, pEList); - for(i=0; inExpr; i++){ - if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName); - } - } - } -} - -/* -** Free the list of RenameToken objects given in the second argument -*/ -static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ - RenameToken *pNext; - RenameToken *p; - for(p=pToken; p; p=pNext){ - pNext = p->pNext; - sqlite3DbFree(db, p); - } -} - -/* -** Search the Parse object passed as the first argument for a RenameToken -** 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 RenameToken *renameTokenFind( - Parse *pParse, - struct RenameCtx *pCtx, - const void *pPtr -){ - RenameToken **pp; - if( NEVER(pPtr==0) ){ - return 0; - } - for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ - if( (*pp)->p==pPtr ){ - RenameToken *pToken = *pp; - if( pCtx ){ - *pp = pToken->pNext; - pToken->pNext = pCtx->pList; - pCtx->pList = pToken; - pCtx->nList++; - } - return pToken; - } - } - return 0; -} - -/* -** This is a Walker select callback. It does nothing. It is only required -** because without a dummy callback, sqlite3WalkExpr() and similar do not -** descend into sub-select statements. -*/ -static int renameColumnSelectCb(Walker *pWalker, Select *p){ - 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; -} - -/* -** This is a Walker expression callback. -** -** For every TK_COLUMN node in the expression tree, search to see -** if the column being references is the column being renamed by an -** ALTER TABLE statement. If it is, then attach its associated -** RenameToken object to the list of RenameToken objects being -** constructed in RenameCtx object at pWalker->u.pRename. -*/ -static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ - RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_TRIGGER - && pExpr->iColumn==p->iCol - && pWalker->pParse->pTriggerTab==p->pTab - ){ - 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); - } - return WRC_Continue; -} - -/* -** The RenameCtx contains a list of tokens that reference a column that -** is being renamed by an ALTER TABLE statement. Return the "last" -** RenameToken in the RenameCtx and remove that RenameToken from the -** RenameContext. "Last" means the last RenameToken encountered when -** the input SQL is parsed from left to right. Repeated calls to this routine -** return all column name tokens in the order that they are encountered -** in the SQL statement. -*/ -static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ - RenameToken *pBest = pCtx->pList; - RenameToken *pToken; - RenameToken **pp; - - for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ - if( pToken->t.z>pBest->t.z ) pBest = pToken; - } - for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); - *pp = pBest->pNext; - - return pBest; -} - -/* -** An error occurred while parsing or otherwise processing a database -** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an -** ALTER TABLE RENAME COLUMN program. The error message emitted by the -** sub-routine is currently stored in pParse->zErrMsg. This function -** adds context to the error message and then stores it in pCtx. -*/ -static void renameColumnParseError( - sqlite3_context *pCtx, - const char *zWhen, - sqlite3_value *pType, - sqlite3_value *pObject, - Parse *pParse -){ - const char *zT = (const char*)sqlite3_value_text(pType); - const char *zN = (const char*)sqlite3_value_text(pObject); - char *zErr; - - zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s", - zT, zN, (zWhen[0] ? " " : ""), zWhen, - pParse->zErrMsg - ); - sqlite3_result_error(pCtx, zErr, -1); - sqlite3DbFree(pParse->db, zErr); -} - -/* -** For each name in the the expression-list pEList (i.e. each -** pEList->a[i].zName) that matches the string in zOld, extract the -** corresponding rename-token from Parse object pParse and add it -** to the RenameCtx pCtx. -*/ -static void renameColumnElistNames( - Parse *pParse, - RenameCtx *pCtx, - const ExprList *pEList, - const char *zOld -){ - if( pEList ){ - int i; - for(i=0; inExpr; i++){ - const char *zName = pEList->a[i].zEName; - if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) - && ALWAYS(zName!=0) - && 0==sqlite3_stricmp(zName, zOld) - ){ - renameTokenFind(pParse, pCtx, (const void*)zName); - } - } - } -} - -/* -** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) -** that matches the string in zOld, extract the corresponding rename-token -** from Parse object pParse and add it to the RenameCtx pCtx. -*/ -static void renameColumnIdlistNames( - Parse *pParse, - RenameCtx *pCtx, - const IdList *pIdList, - const char *zOld -){ - if( pIdList ){ - int i; - for(i=0; inId; i++){ - const char *zName = pIdList->a[i].zName; - if( 0==sqlite3_stricmp(zName, zOld) ){ - renameTokenFind(pParse, pCtx, (const void*)zName); - } - } - } -} - - -/* -** Parse the SQL statement zSql using Parse object (*p). The Parse object -** is initialized by this function before it is used. -*/ -static int renameParseSql( - Parse *p, /* Memory to use for Parse object */ - const char *zDb, /* Name of schema SQL belongs to */ - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL to parse */ - int bTemp /* True if SQL is from temp schema */ -){ - int rc; - u64 flags; - - sqlite3ParseObjectInit(p, db); - if( zSql==0 ){ - return SQLITE_NOMEM; - } - if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ - return SQLITE_CORRUPT_BKPT; - } - if( bTemp ){ - db->init.iDb = 1; - }else{ - int iDb = sqlite3FindDbName(db, zDb); - assert( iDb>=0 && iDb<=0xff ); - db->init.iDb = (u8)iDb; - } - p->eParseMode = PARSE_MODE_RENAME; - p->db = db; - p->nQueryLoop = 1; - flags = db->flags; - testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 ); - db->flags |= SQLITE_Comments; - rc = sqlite3RunParser(p, zSql); - db->flags = flags; - if( db->mallocFailed ) rc = SQLITE_NOMEM; - if( rc==SQLITE_OK - && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) - ){ - rc = SQLITE_CORRUPT_BKPT; - } - -#ifdef SQLITE_DEBUG - /* Ensure that all mappings in the Parse.pRename list really do map to - ** a part of the input string. */ - if( rc==SQLITE_OK ){ - int nSql = sqlite3Strlen30(zSql); - RenameToken *pToken; - for(pToken=p->pRename; pToken; pToken=pToken->pNext){ - assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); - } - } -#endif - - db->init.iDb = 0; - return rc; -} - -/* -** This function edits SQL statement zSql, replacing each token identified -** by the linked list pRename with the text of zNew. If argument bQuote is -** true, then zNew is always quoted first. If no error occurs, the result -** is loaded into context object pCtx as the result. -** -** Or, if an error occurs (i.e. an OOM condition), an error is left in -** pCtx and an SQLite error code returned. -*/ -static int renameEditSql( - sqlite3_context *pCtx, /* Return result here */ - RenameCtx *pRename, /* Rename context */ - const char *zSql, /* SQL statement to edit */ - const char *zNew, /* New token text */ - int bQuote /* True to always quote token */ -){ - i64 nNew = sqlite3Strlen30(zNew); - i64 nSql = sqlite3Strlen30(zSql); - sqlite3 *db = sqlite3_context_db_handle(pCtx); - int rc = SQLITE_OK; - char *zQuot = 0; - char *zOut; - 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 = sqlite3MPrintf(db, "\"%w\" ", zNew); - if( zQuot==0 ){ - return SQLITE_NOMEM; - }else{ - nQuot = sqlite3Strlen30(zQuot)-1; - } - - assert( nQuot>=nNew && nSql>=0 && nNew>=0 ); - zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1); - }else{ - assert( nSql>0 ); - zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 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, or with single-quoted versions of themselves. - ** All that remains is to construct and return the edited SQL string. */ - if( zOut ){ - i64 nOut = nSql; - assert( nSql>0 ); - memcpy(zOut, zSql, (size_t)nSql); - while( pRename->pList ){ - int iOff; /* Offset of token to replace in zOut */ - i64 nReplace; - const char *zReplace; - RenameToken *pBest = renameColumnTokenNext(pRename); - - if( zNew ){ - if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){ - nReplace = nNew; - zReplace = zNew; - }else{ - nReplace = nQuot; - zReplace = zQuot; - if( pBest->t.z[pBest->t.n]=='"' ) nReplace++; - } - }else{ - /* 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; - sqlite3Dequote(zBuf1); - assert( nSql < 0x15555554 /* otherwise malloc would have failed */ ); - sqlite3_snprintf((int)(nSql*2), zBuf2, "%Q%s", zBuf1, - pBest->t.z[pBest->t.n]=='\'' ? " " : "" - ); - zReplace = zBuf2; - nReplace = sqlite3Strlen30(zReplace); - } - - iOff = (int)(pBest->t.z - zSql); - if( pBest->t.n!=nReplace ){ - memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], - nOut - (iOff + pBest->t.n) - ); - nOut += nReplace - pBest->t.n; - zOut[nOut] = '\0'; - } - memcpy(&zOut[iOff], zReplace, nReplace); - sqlite3DbFree(db, pBest); - } - - sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); - sqlite3DbFree(db, zOut); - }else{ - rc = SQLITE_NOMEM; - } - - sqlite3_free(zQuot); - return rc; -} - -/* -** Set all pEList->a[].fg.eEName fields in the expression-list to val. -*/ -static void renameSetENames(ExprList *pEList, int val){ - assert( val==ENAME_NAME || val==ENAME_TAB || val==ENAME_SPAN ); - if( pEList ){ - int i; - for(i=0; inExpr; i++){ - assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME ); - pEList->a[i].fg.eEName = val&0x3; - } - } -} - -/* -** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming -** it was read from the schema of database zDb. Return SQLITE_OK if -** successful. Otherwise, return an SQLite error code and leave an error -** message in the Parse object. -*/ -static int renameResolveTrigger(Parse *pParse){ - sqlite3 *db = pParse->db; - Trigger *pNew = pParse->pNewTrigger; - TriggerStep *pStep; - NameContext sNC; - int rc = SQLITE_OK; - - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - assert( pNew->pTabSchema ); - pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, - db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName - ); - pParse->eTriggerOp = pNew->op; - /* ALWAYS() because if the table of the trigger does not exist, the - ** error would have been hit before this point */ - if( ALWAYS(pParse->pTriggerTab) ){ - rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0; - } - - /* Resolve symbols in WHEN clause */ - if( rc==SQLITE_OK && pNew->pWhen ){ - rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); - } - - for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ - if( pStep->pSelect ){ - sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); - if( pParse->nErr ) rc = pParse->rc; - } - if( rc==SQLITE_OK && pStep->zTarget ){ - SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); - if( pSrc ){ - Select *pSel = sqlite3SelectNew( - pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 - ); - if( pSel==0 ){ - pStep->pExprList = 0; - pSrc = 0; - rc = SQLITE_NOMEM; - }else{ - /* pStep->pExprList contains an expression-list used for an UPDATE - ** statement. So the a[].zEName values are the RHS of the - ** "= " clauses of the UPDATE statement. So, before - ** running SelectPrep(), change all the eEName values in - ** pStep->pExprList to ENAME_SPAN (from their current value of - ** ENAME_NAME). This is to prevent any ids in ON() clauses that are - ** part of pSrc from being incorrectly resolved against the - ** a[].zEName values as if they were column aliases. */ - renameSetENames(pStep->pExprList, ENAME_SPAN); - sqlite3SelectPrep(pParse, pSel, 0); - renameSetENames(pStep->pExprList, ENAME_NAME); - 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; - sqlite3SelectDelete(db, pSel); - } - if( pStep->pFrom ){ - int i; - for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){ - SrcItem *p = &pStep->pFrom->a[i]; - if( p->fg.isSubquery ){ - assert( p->u4.pSubq!=0 ); - sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0); - } - } - } - - if( db->mallocFailed ){ - rc = SQLITE_NOMEM; - } - sNC.pSrcList = pSrc; - if( rc==SQLITE_OK && pStep->pWhere ){ - rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); - } - assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); - if( pStep->pUpsert && rc==SQLITE_OK ){ - Upsert *pUpsert = pStep->pUpsert; - pUpsert->pUpsertSrc = pSrc; - sNC.uNC.pUpsert = pUpsert; - sNC.ncFlags = NC_UUpsert; - rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); - if( rc==SQLITE_OK ){ - ExprList *pUpsertSet = pUpsert->pUpsertSet; - rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); - } - sNC.ncFlags = 0; - } - sNC.pSrcList = 0; - sqlite3SrcListDelete(db, pSrc); - }else{ - rc = SQLITE_NOMEM; - } - } - } - return rc; -} - -/* -** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr -** objects that are part of the trigger passed as the second argument. -*/ -static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ - TriggerStep *pStep; - - /* Find tokens to edit in WHEN clause */ - sqlite3WalkExpr(pWalker, pTrigger->pWhen); - - /* Find tokens to edit in trigger steps */ - for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - sqlite3WalkSelect(pWalker, pStep->pSelect); - sqlite3WalkExpr(pWalker, pStep->pWhere); - sqlite3WalkExprList(pWalker, pStep->pExprList); - if( pStep->pUpsert ){ - Upsert *pUpsert = pStep->pUpsert; - sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); - sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); - sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); - sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); - } - if( pStep->pFrom ){ - int i; - SrcList *pFrom = pStep->pFrom; - for(i=0; inSrc; i++){ - if( pFrom->a[i].fg.isSubquery ){ - assert( pFrom->a[i].u4.pSubq!=0 ); - sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect); - } - } - } - } -} - -/* -** Free the contents of Parse object (*pParse). Do not free the memory -** occupied by the Parse object itself. -*/ -static void renameParseCleanup(Parse *pParse){ - sqlite3 *db = pParse->db; - Index *pIdx; - if( pParse->pVdbe ){ - sqlite3VdbeFinalize(pParse->pVdbe); - } - sqlite3DeleteTable(db, pParse->pNewTable); - while( (pIdx = pParse->pNewIndex)!=0 ){ - pParse->pNewIndex = pIdx->pNext; - sqlite3FreeIndex(db, pIdx); - } - sqlite3DeleteTrigger(db, pParse->pNewTrigger); - sqlite3DbFree(db, pParse->zErrMsg); - renameTokenFree(db, pParse->pRename); - sqlite3ParseObjectReset(pParse); -} - -/* -** SQL function: -** -** 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.) -** 2. object: Name of object -** 3. Database: Database name (e.g. "main") -** 4. Table: Table name -** 5. iCol: Index of column to rename -** 6. zNew: New column name -** 7. bQuote: Non-zero if the new column name should be quoted. -** 8. bTemp: True if zSql comes from temp schema -** -** Do a column rename operation on the CREATE statement given in zSql. -** The iCol-th column (left-most is 0) of table zTable is renamed from zCol -** into zNew. The name should be quoted if bQuote is true. -** -** This function is used internally by the ALTER TABLE RENAME COLUMN command. -** It is only accessible to SQL created using sqlite3NestedParse(). It is -** not reachable from ordinary SQL passed into sqlite3_prepare() unless the -** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. -*/ -static void renameColumnFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - RenameCtx sCtx; - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - const char *zDb = (const char*)sqlite3_value_text(argv[3]); - const char *zTable = (const char*)sqlite3_value_text(argv[4]); - int iCol = sqlite3_value_int(argv[5]); - const char *zNew = (const char*)sqlite3_value_text(argv[6]); - int bQuote = sqlite3_value_int(argv[7]); - int bTemp = sqlite3_value_int(argv[8]); - const char *zOld; - int rc; - Parse sParse; - Walker sWalker; - Index *pIdx; - int i; - Table *pTab; -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; -#endif - - UNUSED_PARAMETER(NotUsed); - if( zSql==0 ) return; - if( zTable==0 ) return; - if( zNew==0 ) return; - if( iCol<0 ) return; - sqlite3BtreeEnterAll(db); - pTab = sqlite3FindTable(db, zTable, zDb); - if( pTab==0 || iCol>=pTab->nCol ){ - sqlite3BtreeLeaveAll(db); - return; - } - zOld = pTab->aCol[iCol].zCnName; - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = 0; -#endif - rc = renameParseSql(&sParse, zDb, db, zSql, bTemp); - - /* Find tokens that need to be replaced. */ - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = &sParse; - sWalker.xExprCallback = renameColumnExprCb; - sWalker.xSelectCallback = renameColumnSelectCb; - sWalker.u.pRename = &sCtx; - - sCtx.pTab = pTab; - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - if( sParse.pNewTable ){ - if( IsView(sParse.pNewTable) ){ - Select *pSelect = sParse.pNewTable->u.view.pSelect; - pSelect->selFlags &= ~(u32)SF_View; - sParse.rc = SQLITE_OK; - sqlite3SelectPrep(&sParse, pSelect, 0); - rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); - if( rc==SQLITE_OK ){ - sqlite3WalkSelect(&sWalker, pSelect); - } - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - }else if( IsOrdinaryTable(sParse.pNewTable) ){ - /* A regular table */ - int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); - FKey *pFKey; - sCtx.pTab = sParse.pNewTable; - if( bFKOnly==0 ){ - if( iColnCol ){ - renameTokenFind( - &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName - ); - } - if( sCtx.iCol<0 ){ - renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); - } - sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); - for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3WalkExprList(&sWalker, pIdx->aColExpr); - } - for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3WalkExprList(&sWalker, pIdx->aColExpr); - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - for(i=0; inCol; i++){ - Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable, - &sParse.pNewTable->aCol[i]); - sqlite3WalkExpr(&sWalker, pExpr); - } -#endif - } - - assert( IsOrdinaryTable(sParse.pNewTable) ); - for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - for(i=0; inCol; i++){ - if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ - renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); - } - if( 0==sqlite3_stricmp(pFKey->zTo, zTable) - && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) - ){ - renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol); - } - } - } - } - }else if( sParse.pNewIndex ){ - sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); - }else{ - /* A trigger */ - TriggerStep *pStep; - rc = renameResolveTrigger(&sParse); - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - - for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget ){ - Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); - if( pTarget==pTab ){ - if( pStep->pUpsert ){ - ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; - renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); - } - renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); - renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); - } - } - } - - - /* Find tokens to edit in UPDATE OF clause */ - if( sParse.pTriggerTab==pTab ){ - renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); - } - - /* Find tokens to edit in various expressions and selects */ - renameWalkTrigger(&sWalker, sParse.pNewTrigger); - } - - assert( rc==SQLITE_OK ); - rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); - -renameColumnFunc_done: - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ - sqlite3_result_value(context, argv[0]); - }else if( sParse.zErrMsg ){ - renameColumnParseError(context, "", argv[1], argv[2], &sParse); - }else{ - sqlite3_result_error_code(context, rc); - } - } - - renameParseCleanup(&sParse); - renameTokenFree(db, sCtx.pList); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - sqlite3BtreeLeaveAll(db); -} - -/* -** Walker expression callback used by "RENAME TABLE". -*/ -static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ - RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN - && ALWAYS(ExprUseYTab(pExpr)) - && p->pTab==pExpr->y.pTab - ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); - } - return WRC_Continue; -} - -/* -** Walker select callback used by "RENAME TABLE". -*/ -static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ - int i; - RenameCtx *p = pWalker->u.pRename; - SrcList *pSrc = pSelect->pSrc; - 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; inSrc; i++){ - SrcItem *pItem = &pSrc->a[i]; - if( pItem->pSTab==p->pTab ){ - renameTokenFind(pWalker->pParse, p, pItem->zName); - } - } - renameWalkWith(pWalker, pSelect); - - return WRC_Continue; -} - - -/* -** This C function implements an SQL user function that is used by SQL code -** generated by the ALTER TABLE ... RENAME command to modify the definition -** of any foreign key constraints that use the table being renamed as the -** parent table. It is passed three arguments: -** -** 0: The database containing the table being renamed. -** 1. type: Type of object ("table", "view" etc.) -** 2. object: Name of object -** 3: The complete text of the schema statement being modified, -** 4: The old name of the table being renamed, and -** 5: The new name of the table being renamed. -** 6: True if the schema statement comes from the temp db. -** -** It returns the new schema statement. For example: -** -** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) -** -> 'CREATE TABLE t1(a REFERENCES t3)' -*/ -static void renameTableFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zDb = (const char*)sqlite3_value_text(argv[0]); - const char *zInput = (const char*)sqlite3_value_text(argv[3]); - const char *zOld = (const char*)sqlite3_value_text(argv[4]); - const char *zNew = (const char*)sqlite3_value_text(argv[5]); - int bTemp = sqlite3_value_int(argv[6]); - UNUSED_PARAMETER(NotUsed); - - if( zInput && zOld && zNew ){ - Parse sParse; - int rc; - int bQuote = 1; - RenameCtx sCtx; - Walker sWalker; - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - sqlite3BtreeEnterAll(db); - - memset(&sCtx, 0, sizeof(RenameCtx)); - sCtx.pTab = sqlite3FindTable(db, zOld, zDb); - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = &sParse; - sWalker.xExprCallback = renameTableExprCb; - sWalker.xSelectCallback = renameTableSelectCb; - sWalker.u.pRename = &sCtx; - - rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); - - if( rc==SQLITE_OK ){ - int isLegacy = (db->flags & SQLITE_LegacyAlter); - if( sParse.pNewTable ){ - Table *pTab = sParse.pNewTable; - - if( IsView(pTab) ){ - if( isLegacy==0 ){ - Select *pSelect = pTab->u.view.pSelect; - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sParse; - - assert( pSelect->selFlags & SF_View ); - pSelect->selFlags &= ~(u32)SF_View; - sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC); - if( sParse.nErr ){ - rc = sParse.rc; - }else{ - 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)) - && !IsVirtual(pTab) - ){ - FKey *pFKey; - assert( IsOrdinaryTable(pTab) ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ - renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); - } - } - } -#endif - - /* If this is the table being altered, fix any table refs in CHECK - ** expressions. Also update the name that appears right after the - ** "CREATE [VIRTUAL] TABLE" bit. */ - if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ - sCtx.pTab = pTab; - if( isLegacy==0 ){ - sqlite3WalkExprList(&sWalker, pTab->pCheck); - } - renameTokenFind(&sParse, &sCtx, pTab->zName); - } - } - } - - else if( sParse.pNewIndex ){ - renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); - if( isLegacy==0 ){ - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); - } - } - -#ifndef SQLITE_OMIT_TRIGGER - else{ - Trigger *pTrigger = sParse.pNewTrigger; - TriggerStep *pStep; - if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) - && sCtx.pTab->pSchema==pTrigger->pTabSchema - ){ - renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); - } - - if( isLegacy==0 ){ - rc = renameResolveTrigger(&sParse); - if( rc==SQLITE_OK ){ - renameWalkTrigger(&sWalker, pTrigger); - for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ - renameTokenFind(&sParse, &sCtx, pStep->zTarget); - } - if( pStep->pFrom ){ - int i; - for(i=0; ipFrom->nSrc; i++){ - SrcItem *pItem = &pStep->pFrom->a[i]; - if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ - renameTokenFind(&sParse, &sCtx, pItem->zName); - } - } - } - } - } - } - } -#endif - } - - if( rc==SQLITE_OK ){ - rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); - } - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ - sqlite3_result_value(context, argv[3]); - }else if( sParse.zErrMsg ){ - renameColumnParseError(context, "", argv[1], argv[2], &sParse); - }else{ - sqlite3_result_error_code(context, rc); - } - } - - renameParseCleanup(&sParse); - renameTokenFree(db, sCtx.pList); - sqlite3BtreeLeaveAll(db); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - } - - 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( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - char const *zDb = (const char*)sqlite3_value_text(argv[0]); - char const *zInput = (const char*)sqlite3_value_text(argv[1]); - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - 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 &= ~(u32)SF_View; - sParse.rc = SQLITE_OK; - sqlite3SelectPrep(&sParse, pSelect, 0); - rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); - if( rc==SQLITE_OK ){ - sqlite3WalkSelect(&sWalker, pSelect); - } - }else{ - int i; - sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - for(i=0; inCol; i++){ - sqlite3WalkExpr(&sWalker, - sqlite3ColumnExpr(sParse.pNewTable, - &sParse.pNewTable->aCol[i])); - } -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - } - }else if( sParse.pNewIndex ){ - sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); - 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( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){ - sqlite3_result_value(context, argv[1]); - }else{ - sqlite3_result_error_code(context, rc); - } - } - renameParseCleanup(&sParse); - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - - 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 -** reloaded, this function is called on each SQL statement in the schema -** to ensure that it is still usable. -** -** 0: Database name ("main", "temp" etc.). -** 1: SQL statement. -** 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. -** -** The return value is computed as follows: -** -** 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( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - char const *zDb = (const char*)sqlite3_value_text(argv[0]); - char const *zInput = (const char*)sqlite3_value_text(argv[1]); - int bTemp = sqlite3_value_int(argv[4]); - int isLegacy = (db->flags & SQLITE_LegacyAlter); - char const *zWhen = (const char*)sqlite3_value_text(argv[5]); - int bNoDQS = sqlite3_value_int(argv[6]); - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - UNUSED_PARAMETER(NotUsed); - - if( zDb && zInput ){ - int rc; - Parse sParse; - u64 flags = db->flags; - if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); - rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); - db->flags = flags; - if( rc==SQLITE_OK ){ - if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sParse; - sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC); - if( sParse.nErr ) rc = sParse.rc; - } - - else if( sParse.pNewTrigger ){ - if( isLegacy==0 ){ - rc = renameResolveTrigger(&sParse); - } - if( rc==SQLITE_OK ){ - int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); - int i2 = sqlite3FindDbName(db, zDb); - if( i1==i2 ){ - /* Handle output case B */ - sqlite3_result_int(context, 1); - } - } - } - } - - if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){ - /* Output case A */ - renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); - } - renameParseCleanup(&sParse); - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif -} - -/* -** 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( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - int iSchema = sqlite3_value_int(argv[0]); - const char *zSql = (const char*)sqlite3_value_text(argv[1]); - int iCol = 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 - 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( iColnCol-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 = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); - sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT); - sqlite3_free(zNew); - -drop_column_done: - renameParseCleanup(&sParse); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - if( rc!=SQLITE_OK ){ - 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 sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){ - 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( sqlite3BtreeHoldsAllMutexes(db) ); - if( NEVER(db->mallocFailed) ) goto exit_drop_column; - pTab = 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 = sqlite3NameFromToken(db, pName); - if( zCol==0 ){ - assert( db->mallocFailed ); - goto exit_drop_column; - } - iCol = sqlite3ColumnIndex(pTab, zCol); - if( iCol<0 ){ - 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) ){ - 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 ){ - sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol); - goto exit_drop_column; - } - - /* Edit the sqlite_schema table */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 ); - zDb = db->aDb[iDb].zDbSName; -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( 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); - 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 = sqlite3GetVdbe(pParse); - iCur = pParse->nTab++; - sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); - addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - reg = ++pParse->nMem; - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg); - pParse->nMem += pTab->nCol; - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem += pPk->nColumn; - for(i=0; inKeyCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1); - } - nField = pPk->nKeyCol; - } - regRec = ++pParse->nMem; - for(i=0; inCol; i++){ - if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ - int regOut; - if( pPk ){ - int iPos = sqlite3TableColumnToIndex(pPk, i); - int iColPos = sqlite3TableColumnToIndex(pPk, iCol); - if( iPosnKeyCol ) continue; - regOut = reg+1+iPos-(iPos>iColPos); - }else{ - regOut = reg+1+nField; - } - if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); - }else{ - char aff = pTab->aCol[i].affinity; - if( aff==SQLITE_AFF_REAL ){ - pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC; - } - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); - pTab->aCol[i].affinity = aff; - } - nField++; - } - } - if( nField==0 ){ - /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */ - pParse->nMem++; - sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1); - nField = 1; - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); - }else{ - sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); - } - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - - sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr); - } - -exit_drop_column: - sqlite3DbFree(db, zCol); - sqlite3SrcListDelete(db, pSrc); -} - -/* -** Register built-in functions used to help implement ALTER TABLE -*/ -SQLITE_PRIVATE void sqlite3AlterFunctions(void){ - static FuncDef aAlterTableFuncs[] = { - 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), - }; - sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); -} -#endif /* SQLITE_ALTER_TABLE */ - -/************** End of alter.c ***********************************************/ -/************** Begin file analyze.c *****************************************/ -/* -** 2005-07-08 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code associated with the ANALYZE command. -** -** The ANALYZE command gather statistics about the content of tables -** and indices. These statistics are made available to the query planner -** to help it make better decisions about how to perform queries. -** -** The following system tables are or have been supported: -** -** CREATE TABLE sqlite_stat1(tbl, idx, stat); -** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample); -** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample); -** CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample); -** -** Additional tables might be added in future releases of SQLite. -** The sqlite_stat2 table is not created or used unless the SQLite version -** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled -** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. -** The sqlite_stat2 table is superseded by sqlite_stat3, which is only -** created and used by SQLite versions 3.7.9 through 3.29.0 when -** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 -** is a superset of sqlite_stat2 and is also now deprecated. The -** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only -** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite -** versions 3.8.1 and later. STAT4 is the only variant that is still -** supported. -** -** For most applications, sqlite_stat1 provides all the statistics required -** for the query planner to make good choices. -** -** Format of sqlite_stat1: -** -** There is normally one row per index, with the index identified by the -** name in the idx column. The tbl column is the name of the table to -** which the index belongs. In each such row, the stat column will be -** a string consisting of a list of integers. The first integer in this -** list is the number of rows in the index. (This is the same as the -** number of rows in the table, except for partial indices.) The second -** integer is the average number of rows in the index that have the same -** value in the first column of the index. The third integer is the average -** number of rows in the index that have the same value for the first two -** columns. The N-th integer (for N>1) is the average number of rows in -** the index which have the same value for the first N-1 columns. For -** a K-column index, there will be K+1 integers in the stat column. If -** the index is unique, then the last integer will be 1. -** -** The list of integers in the stat column can optionally be followed -** by the keyword "unordered". The "unordered" keyword, if it is present, -** must be separated from the last integer by a single space. If the -** "unordered" keyword is present, then the query planner assumes that -** the index is unordered and will not use the index for a range query. -** -** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat -** column contains a single integer which is the (estimated) number of -** rows in the table identified by sqlite_stat1.tbl. -** -** Format of sqlite_stat2: -** -** The sqlite_stat2 is only created and is only used if SQLite is compiled -** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between -** 3.6.18 and 3.7.8. The "stat2" table contains additional information -** about the distribution of keys within an index. The index is identified by -** the "idx" column and the "tbl" column is the name of the table to which -** the index belongs. There are usually 10 rows in the sqlite_stat2 -** table for each index. -** -** The sqlite_stat2 entries for an index that have sampleno between 0 and 9 -** inclusive are samples of the left-most key value in the index taken at -** evenly spaced points along the index. Let the number of samples be S -** (10 in the standard build) and let C be the number of rows in the index. -** Then the sampled rows are given by: -** -** rownumber = (i*C*2 + C)/(S*2) -** -** For i between 0 and S-1. Conceptually, the index space is divided into -** S uniform buckets and the samples are the middle row from each bucket. -** -** The format for sqlite_stat2 is recorded here for legacy reference. This -** version of SQLite does not support sqlite_stat2. It neither reads nor -** writes the sqlite_stat2 table. This version of SQLite only supports -** sqlite_stat3. -** -** Format for sqlite_stat3: -** -** The sqlite_stat3 format is a subset of sqlite_stat4. Hence, the -** sqlite_stat4 format will be described first. Further information -** about sqlite_stat3 follows the sqlite_stat4 description. -** -** Format for sqlite_stat4: -** -** As with sqlite_stat2, the sqlite_stat4 table contains histogram data -** to aid the query planner in choosing good indices based on the values -** that indexed columns are compared against in the WHERE clauses of -** queries. -** -** The sqlite_stat4 table contains multiple entries for each index. -** The idx column names the index and the tbl column is the table of the -** index. If the idx and tbl columns are the same, then the sample is -** of the INTEGER PRIMARY KEY. The sample column is a blob which is the -** binary encoding of a key from the index. The nEq column is a -** list of integers. The first integer is the approximate number -** of entries in the index whose left-most column exactly matches -** the left-most column of the sample. The second integer in nEq -** is the approximate number of entries in the index where the -** first two columns match the first two columns of the sample. -** And so forth. nLt is another list of integers that show the approximate -** number of entries that are strictly less than the sample. The first -** integer in nLt contains the number of entries in the index where the -** left-most column is less than the left-most column of the sample. -** The K-th integer in the nLt entry is the number of index entries -** where the first K columns are less than the first K columns of the -** sample. The nDLt column is like nLt except that it contains the -** number of distinct entries in the index that are less than the -** sample. -** -** There can be an arbitrary number of sqlite_stat4 entries per index. -** The ANALYZE command will typically generate sqlite_stat4 tables -** that contain between 10 and 40 samples which are distributed across -** the key space, though not uniformly, and which include samples with -** large nEq values. -** -** Format for sqlite_stat3 redux: -** -** The sqlite_stat3 table is like sqlite_stat4 except that it only -** looks at the left-most column of the index. The sqlite_stat3.sample -** column contains the actual value of the left-most column instead -** of a blob encoding of the complete index key as is found in -** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3 -** all contain just a single integer which is the same as the first -** integer in the equivalent columns in sqlite_stat4. -*/ -#ifndef SQLITE_OMIT_ANALYZE -/* #include "sqliteInt.h" */ - -#if defined(SQLITE_ENABLE_STAT4) -# define IsStat4 1 -#else -# define IsStat4 0 -# undef SQLITE_STAT4_SAMPLES -# define SQLITE_STAT4_SAMPLES 1 -#endif - -/* -** This routine generates code that opens the sqlite_statN tables. -** The sqlite_stat1 table is always relevant. sqlite_stat2 is now -** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when -** appropriate compile-time options are provided. -** -** If the sqlite_statN tables do not previously exist, it is created. -** -** Argument zWhere may be a pointer to a buffer containing a table name, -** or it may be a NULL pointer. If it is not NULL, then all entries in -** the sqlite_statN tables associated with the named table are deleted. -** If zWhere==0, then code is generated to delete all stat table entries. -*/ -static void openStatTable( - Parse *pParse, /* Parsing context */ - int iDb, /* The database we are looking in */ - int iStatCur, /* Open the sqlite_stat1 table on this cursor */ - const char *zWhere, /* Delete entries for this table or index */ - const char *zWhereType /* Either "tbl" or "idx" */ -){ - static const struct { - const char *zName; - const char *zCols; - } aTable[] = { - { "sqlite_stat1", "tbl,idx,stat" }, -#if defined(SQLITE_ENABLE_STAT4) - { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" }, -#else - { "sqlite_stat4", 0 }, -#endif - { "sqlite_stat3", 0 }, - }; - int i; - sqlite3 *db = pParse->db; - Db *pDb; - Vdbe *v = sqlite3GetVdbe(pParse); - u32 aRoot[ArraySize(aTable)]; - u8 aCreateTbl[ArraySize(aTable)]; -#ifdef SQLITE_ENABLE_STAT4 - const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1; -#else - const int nToOpen = 1; -#endif - - if( v==0 ) return; - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3VdbeDb(v)==db ); - pDb = &db->aDb[iDb]; - - /* Create new statistic tables if they do not exist, or clear them - ** if they do already exist. - */ - for(i=0; izDbSName))==0 ){ - if( iregRoot. This is important - ** because the OpenWrite opcode below will be needing it. */ - sqlite3NestedParse(pParse, - "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols - ); - assert( pParse->isCreate || pParse->nErr ); - aRoot[i] = (u32)pParse->u1.cr.regRoot; - aCreateTbl[i] = OPFLAG_P2ISREG; - } - }else{ - /* The table already exists. If zWhere is not NULL, delete all entries - ** associated with the table zWhere. If zWhere is NULL, delete the - ** entire contents of the table. */ - aRoot[i] = pStat->tnum; - sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); - if( zWhere ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE %s=%Q", - pDb->zDbSName, zTab, zWhereType, zWhere - ); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - }else if( db->xPreUpdateCallback ){ - sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab); -#endif - }else{ - /* The sqlite_stat[134] table already exists. Delete all rows. */ - sqlite3VdbeAddOp2(v, OP_Clear, (int)aRoot[i], iDb); - } - } - } - - /* Open the sqlite_stat[134] tables for writing. */ - for(i=0; inRowid ){ - sqlite3DbFree(db, p->u.aRowid); - p->nRowid = 0; - } -} -#endif - -/* Initialize the BLOB value of a ROWID -*/ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){ - assert( db!=0 ); - if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); - p->u.aRowid = sqlite3DbMallocRawNN(db, n); - if( p->u.aRowid ){ - p->nRowid = n; - memcpy(p->u.aRowid, pData, n); - }else{ - p->nRowid = 0; - } -} -#endif - -/* Initialize the INTEGER value of a ROWID. -*/ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){ - assert( db!=0 ); - if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); - p->nRowid = 0; - p->u.iRowid = iRowid; -} -#endif - - -/* -** Copy the contents of object (*pFrom) into (*pTo). -*/ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){ - pTo->isPSample = pFrom->isPSample; - pTo->iCol = pFrom->iCol; - pTo->iHash = pFrom->iHash; - memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol); - memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol); - memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol); - if( pFrom->nRowid ){ - sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid); - }else{ - sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid); - } -} -#endif - -/* -** Reclaim all memory of a StatAccum structure. -*/ -static void statAccumDestructor(void *pOld){ - StatAccum *p = (StatAccum*)pOld; -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ){ - int i; - for(i=0; inCol; i++) sampleClear(p->db, p->aBest+i); - for(i=0; imxSample; i++) sampleClear(p->db, p->a+i); - sampleClear(p->db, &p->current); - } -#endif - sqlite3DbFree(p->db, p); -} - -/* -** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters -** are: -** N: The number of columns in the index including the rowid/pk (note 1) -** K: The number of columns in the index excluding the rowid/pk. -** C: Estimated number of rows in the index -** L: A limit on the number of rows to scan, or 0 for no-limit -** -** Note 1: In the special case of the covering index that implements a -** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the -** total number of columns in the table. -** -** For indexes on ordinary rowid tables, N==K+1. But for indexes on -** WITHOUT ROWID tables, N=K+P where P is the number of columns in the -** PRIMARY KEY of the table. The covering index that implements the -** original WITHOUT ROWID table as N==K as a special case. -** -** This routine allocates the StatAccum object in heap memory. The return -** value is a pointer to the StatAccum object. The datatype of the -** return value is BLOB, but it is really just a pointer to the StatAccum -** object. -*/ -static void statInit( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - StatAccum *p; - int nCol; /* Number of columns in index being sampled */ - int nKeyCol; /* Number of key columns */ - int nColUp; /* nCol rounded up for alignment */ - i64 n; /* Bytes of space to allocate */ - sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */ -#ifdef SQLITE_ENABLE_STAT4 - /* Maximum number of samples. 0 if STAT4 data is not collected */ - int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0; -#endif - - /* Decode the three function arguments */ - UNUSED_PARAMETER(argc); - nCol = sqlite3_value_int(argv[0]); - assert( nCol>0 ); - nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol; - nKeyCol = sqlite3_value_int(argv[1]); - assert( nKeyCol<=nCol ); - assert( nKeyCol>0 ); - - /* Allocate the space required for the StatAccum object */ - n = sizeof(*p) - + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ -#ifdef SQLITE_ENABLE_STAT4 - n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */ - if( mxSample ){ - n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */ - + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */ - + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample); - } -#endif - p = sqlite3DbMallocZero(db, n); - if( p==0 ){ - sqlite3_result_error_nomem(context); - return; - } - - p->db = db; - p->nEst = sqlite3_value_int64(argv[2]); - p->nRow = 0; - p->nLimit = sqlite3_value_int(argv[3]); - p->nCol = nCol; - p->nKeyCol = nKeyCol; - p->nSkipAhead = 0; - p->current.anDLt = (tRowcnt*)&p[1]; - -#ifdef SQLITE_ENABLE_STAT4 - p->current.anEq = &p->current.anDLt[nColUp]; - p->mxSample = p->nLimit==0 ? mxSample : 0; - if( mxSample ){ - u8 *pSpace; /* Allocated space not yet assigned */ - int i; /* Used to iterate through p->aSample[] */ - - p->iGet = -1; - p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1); - p->current.anLt = &p->current.anEq[nColUp]; - p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); - - /* Set up the StatAccum.a[] and aBest[] arrays */ - p->a = (struct StatSample*)&p->current.anLt[nColUp]; - p->aBest = &p->a[mxSample]; - pSpace = (u8*)(&p->a[mxSample+nCol]); - for(i=0; i<(mxSample+nCol); i++){ - p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); - p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); - p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); - } - assert( (pSpace - (u8*)p)==n ); - - for(i=0; iaBest[i].iCol = i; - } - } -#endif - - /* Return a pointer to the allocated object to the caller. Note that - ** only the pointer (the 2nd parameter) matters. The size of the object - ** (given by the 3rd parameter) is never used and can be any positive - ** value. */ - sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor); -} -static const FuncDef statInitFuncdef = { - 4, /* nArg */ - SQLITE_UTF8, /* funcFlags */ - 0, /* pUserData */ - 0, /* pNext */ - statInit, /* xSFunc */ - 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ - "stat_init", /* zName */ - {0} -}; - -#ifdef SQLITE_ENABLE_STAT4 -/* -** pNew and pOld are both candidate non-periodic samples selected for -** the same column (pNew->iCol==pOld->iCol). Ignoring this column and -** considering only any trailing columns and the sample hash value, this -** function returns true if sample pNew is to be preferred over pOld. -** In other words, if we assume that the cardinalities of the selected -** column for pNew and pOld are equal, is pNew to be preferred over pOld. -** -** This function assumes that for each argument sample, the contents of -** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. -*/ -static int sampleIsBetterPost( - StatAccum *pAccum, - StatSample *pNew, - StatSample *pOld -){ - int nCol = pAccum->nCol; - int i; - assert( pNew->iCol==pOld->iCol ); - for(i=pNew->iCol+1; ianEq[i]>pOld->anEq[i] ) return 1; - if( pNew->anEq[i]anEq[i] ) return 0; - } - if( pNew->iHash>pOld->iHash ) return 1; - return 0; -} -#endif - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Return true if pNew is to be preferred over pOld. -** -** This function assumes that for each argument sample, the contents of -** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. -*/ -static int sampleIsBetter( - StatAccum *pAccum, - StatSample *pNew, - StatSample *pOld -){ - tRowcnt nEqNew = pNew->anEq[pNew->iCol]; - tRowcnt nEqOld = pOld->anEq[pOld->iCol]; - - assert( pOld->isPSample==0 && pNew->isPSample==0 ); - assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); - - if( (nEqNew>nEqOld) ) return 1; - if( nEqNew==nEqOld ){ - if( pNew->iColiCol ) return 1; - return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); - } - return 0; -} - -/* -** Copy the contents of sample *pNew into the p->a[] array. If necessary, -** remove the least desirable sample from p->a[] to make room. -*/ -static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){ - StatSample *pSample = 0; - int i; - - assert( IsStat4 || nEqZero==0 ); - - /* StatAccum.nMaxEqZero is set to the maximum number of leading 0 - ** values in the anEq[] array of any sample in StatAccum.a[]. In - ** other words, if nMaxEqZero is n, then it is guaranteed that there - ** are no samples with StatSample.anEq[m]==0 for (m>=n). */ - if( nEqZero>p->nMaxEqZero ){ - p->nMaxEqZero = nEqZero; - } - if( pNew->isPSample==0 ){ - StatSample *pUpgrade = 0; - assert( pNew->anEq[pNew->iCol]>0 ); - - /* This sample is being added because the prefix that ends in column - ** iCol occurs many times in the table. However, if we have already - ** added a sample that shares this prefix, there is no need to add - ** this one. Instead, upgrade the priority of the highest priority - ** existing sample that shares this prefix. */ - for(i=p->nSample-1; i>=0; i--){ - StatSample *pOld = &p->a[i]; - if( pOld->anEq[pNew->iCol]==0 ){ - if( pOld->isPSample ) return; - assert( pOld->iCol>pNew->iCol ); - assert( sampleIsBetter(p, pNew, pOld) ); - if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ - pUpgrade = pOld; - } - } - } - if( pUpgrade ){ - pUpgrade->iCol = pNew->iCol; - pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol]; - goto find_new_min; - } - } - - /* If necessary, remove sample iMin to make room for the new sample. */ - if( p->nSample>=p->mxSample ){ - StatSample *pMin = &p->a[p->iMin]; - tRowcnt *anEq = pMin->anEq; - tRowcnt *anLt = pMin->anLt; - tRowcnt *anDLt = pMin->anDLt; - sampleClear(p->db, pMin); - memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1)); - pSample = &p->a[p->nSample-1]; - pSample->nRowid = 0; - pSample->anEq = anEq; - pSample->anDLt = anDLt; - pSample->anLt = anLt; - p->nSample = p->mxSample-1; - } - - /* The "rows less-than" for the rowid column must be greater than that - ** for the last sample in the p->a[] array. Otherwise, the samples would - ** be out of order. */ - assert( p->nSample==0 - || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] ); - - /* Insert the new sample */ - pSample = &p->a[p->nSample]; - sampleCopy(p, pSample, pNew); - p->nSample++; - - /* Zero the first nEqZero entries in the anEq[] array. */ - memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); - -find_new_min: - if( p->nSample>=p->mxSample ){ - int iMin = -1; - for(i=0; imxSample; i++){ - if( p->a[i].isPSample ) continue; - if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ - iMin = i; - } - } - assert( iMin>=0 ); - p->iMin = iMin; - } -} -#endif /* SQLITE_ENABLE_STAT4 */ - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Field iChng of the index being scanned has changed. So at this point -** p->current contains a sample that reflects the previous row of the -** index. The value of anEq[iChng] and subsequent anEq[] elements are -** correct at this point. -*/ -static void samplePushPrevious(StatAccum *p, int iChng){ - int i; - - /* Check if any samples from the aBest[] array should be pushed - ** into IndexSample.a[] at this point. */ - for(i=(p->nCol-2); i>=iChng; i--){ - StatSample *pBest = &p->aBest[i]; - pBest->anEq[i] = p->current.anEq[i]; - if( p->nSamplemxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ - sampleInsert(p, pBest, i); - } - } - - /* Check that no sample contains an anEq[] entry with an index of - ** p->nMaxEqZero or greater set to zero. */ - for(i=p->nSample-1; i>=0; i--){ - int j; - for(j=p->nMaxEqZero; jnCol; j++) assert( p->a[i].anEq[j]>0 ); - } - - /* Update the anEq[] fields of any samples already collected. */ - if( iChngnMaxEqZero ){ - for(i=p->nSample-1; i>=0; i--){ - int j; - for(j=iChng; jnCol; j++){ - if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; - } - } - p->nMaxEqZero = iChng; - } -} -#endif /* SQLITE_ENABLE_STAT4 */ - -/* -** Implementation of the stat_push SQL function: stat_push(P,C,R) -** Arguments: -** -** P Pointer to the StatAccum object created by stat_init() -** C Index of left-most column to differ from previous row -** R Rowid for the current row. Might be a key record for -** WITHOUT ROWID tables. -** -** The purpose of this routine is to collect statistical data and/or -** samples from the index being analyzed into the StatAccum object. -** The stat_get() SQL function will be used afterwards to -** retrieve the information gathered. -** -** This SQL function usually returns NULL, but might return an integer -** if it wants the byte-code to do special processing. -** -** The R parameter is only used for STAT4 -*/ -static void statPush( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int i; - - /* The three function arguments */ - StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]); - int iChng = sqlite3_value_int(argv[1]); - - UNUSED_PARAMETER( argc ); - UNUSED_PARAMETER( context ); - assert( p->nCol>0 ); - assert( iChngnCol ); - - if( p->nRow==0 ){ - /* This is the first call to this function. Do initialization. */ -#ifdef SQLITE_ENABLE_STAT4 - for(i=0; inCol; i++) p->current.anEq[i] = 1; -#endif - }else{ - /* Second and subsequent calls get processed here */ -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ) samplePushPrevious(p, iChng); -#endif - - /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply - ** to the current row of the index. */ -#ifdef SQLITE_ENABLE_STAT4 - for(i=0; icurrent.anEq[i]++; - } -#endif - for(i=iChng; inCol; i++){ - p->current.anDLt[i]++; -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i]; - p->current.anEq[i] = 1; -#endif - } - } - - p->nRow++; -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ){ - tRowcnt nLt; - if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){ - sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2])); - }else{ - sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]), - sqlite3_value_blob(argv[2])); - } - p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345; - - nLt = p->current.anLt[p->nCol-1]; - /* Check if this is to be a periodic sample. If so, add it. */ - if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){ - p->current.isPSample = 1; - p->current.iCol = 0; - sampleInsert(p, &p->current, p->nCol-1); - p->current.isPSample = 0; - } - - /* Update the aBest[] array. */ - for(i=0; i<(p->nCol-1); i++){ - p->current.iCol = i; - if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ - sampleCopy(p, &p->aBest[i], &p->current); - } - } - }else -#endif - if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){ - p->nSkipAhead++; - sqlite3_result_int(context, p->current.anDLt[0]>0); - } -} - -static const FuncDef statPushFuncdef = { - 2+IsStat4, /* nArg */ - SQLITE_UTF8, /* funcFlags */ - 0, /* pUserData */ - 0, /* pNext */ - statPush, /* xSFunc */ - 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ - "stat_push", /* zName */ - {0} -}; - -#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ -#define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */ -#define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */ -#define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */ -#define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */ - -/* -** Implementation of the stat_get(P,J) SQL function. This routine is -** used to query statistical information that has been gathered into -** the StatAccum object by prior calls to stat_push(). The P parameter -** has type BLOB but it is really just a pointer to the StatAccum object. -** The content to returned is determined by the parameter J -** which is one of the STAT_GET_xxxx values defined above. -** -** The stat_get(P,J) function is not available to generic SQL. It is -** inserted as part of a manually constructed bytecode program. (See -** the callStatGet() routine below.) It is guaranteed that the P -** parameter will always be a pointer to a StatAccum object, never a -** NULL. -** -** If STAT4 is not enabled, then J is always -** STAT_GET_STAT1 and is hence omitted and this routine becomes -** a one-parameter function, stat_get(P), that always returns the -** stat1 table entry information. -*/ -static void statGet( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]); -#ifdef SQLITE_ENABLE_STAT4 - /* STAT4 has a parameter on this routine. */ - int eCall = sqlite3_value_int(argv[1]); - assert( argc==2 ); - assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ - || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT - || eCall==STAT_GET_NDLT - ); - assert( eCall==STAT_GET_STAT1 || p->mxSample ); - if( eCall==STAT_GET_STAT1 ) -#else - assert( argc==1 ); -#endif - { - /* Return the value to store in the "stat" column of the sqlite_stat1 - ** table for this index. - ** - ** The value is a string composed of a list of integers describing - ** the index. The first integer in the list is the total number of - ** entries in the index. There is one additional integer in the list - ** for each indexed column. This additional integer is an estimate of - ** the number of rows matched by a equality query on the index using - ** a key with the corresponding number of fields. In other words, - ** if the index is on columns (a,b) and the sqlite_stat1 value is - ** "100 10 2", then SQLite estimates that: - ** - ** * the index contains 100 rows, - ** * "WHERE a=?" matches 10 rows, and - ** * "WHERE a=? AND b=?" matches 2 rows. - ** - ** If D is the count of distinct values and K is the total number of - ** rows, then each estimate is 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. - */ - sqlite3_str sStat; /* Text of the constructed "stat" line */ - int i; /* Loop counter */ - - sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100); - sqlite3_str_appendf(&sStat, "%llu", - p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow); - for(i=0; inKeyCol; i++){ - u64 nDistinct = p->current.anDLt[i] + 1; - u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; - if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1; - sqlite3_str_appendf(&sStat, " %llu", iVal); -#ifdef SQLITE_ENABLE_STAT4 - assert( p->current.anEq[i] || p->nRow==0 ); -#endif - } - sqlite3ResultStrAccum(context, &sStat); - } -#ifdef SQLITE_ENABLE_STAT4 - else if( eCall==STAT_GET_ROWID ){ - if( p->iGet<0 ){ - samplePushPrevious(p, 0); - p->iGet = 0; - } - if( p->iGetnSample ){ - StatSample *pS = p->a + p->iGet; - if( pS->nRowid==0 ){ - sqlite3_result_int64(context, pS->u.iRowid); - }else{ - sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid, - SQLITE_TRANSIENT); - } - } - }else{ - tRowcnt *aCnt = 0; - sqlite3_str sStat; - int i; - - assert( p->iGetnSample ); - switch( eCall ){ - case STAT_GET_NEQ: aCnt = p->a[p->iGet].anEq; break; - case STAT_GET_NLT: aCnt = p->a[p->iGet].anLt; break; - default: { - aCnt = p->a[p->iGet].anDLt; - p->iGet++; - break; - } - } - sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100); - for(i=0; inCol; i++){ - sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]); - } - if( sStat.nChar ) sStat.nChar--; - sqlite3ResultStrAccum(context, &sStat); - } -#endif /* SQLITE_ENABLE_STAT4 */ -#ifndef SQLITE_DEBUG - UNUSED_PARAMETER( argc ); -#endif -} -static const FuncDef statGetFuncdef = { - 1+IsStat4, /* nArg */ - SQLITE_UTF8, /* funcFlags */ - 0, /* pUserData */ - 0, /* pNext */ - statGet, /* xSFunc */ - 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ - "stat_get", /* zName */ - {0} -}; - -static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){ -#ifdef SQLITE_ENABLE_STAT4 - sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1); -#elif SQLITE_DEBUG - assert( iParam==STAT_GET_STAT1 ); -#else - UNUSED_PARAMETER( iParam ); -#endif - assert( regOut!=regStat && regOut!=regStat+1 ); - sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4, - &statGetFuncdef, 0); -} - -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS -/* Add a comment to the most recent VDBE opcode that is the name -** of the k-th column of the pIdx index. -*/ -static void analyzeVdbeCommentIndexWithColumnName( - Vdbe *v, /* Prepared statement under construction */ - Index *pIdx, /* Index whose column is being loaded */ - int k /* Which column index */ -){ - int i; /* Index of column in the table */ - assert( k>=0 && knColumn ); - i = pIdx->aiColumn[k]; - if( NEVER(i==XN_ROWID) ){ - VdbeComment((v,"%s.rowid",pIdx->zName)); - }else if( i==XN_EXPR ){ - assert( pIdx->bHasExpr ); - VdbeComment((v,"%s.expr(%d)",pIdx->zName, k)); - }else{ - VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName)); - } -} -#else -# define analyzeVdbeCommentIndexWithColumnName(a,b,c) -#endif /* SQLITE_DEBUG */ - -/* -** Generate code to do an analysis of all indices associated with -** a single table. -*/ -static void analyzeOneTable( - Parse *pParse, /* Parser context */ - Table *pTab, /* Table whose indices are to be analyzed */ - Index *pOnlyIdx, /* If not NULL, only analyze this one index */ - int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ - int iMem, /* Available memory locations begin here */ - int iTab /* Next available cursor */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - Index *pIdx; /* An index to being analyzed */ - int iIdxCur; /* Cursor open on index being analyzed */ - int iTabCur; /* Table cursor */ - Vdbe *v; /* The virtual machine being built up */ - int i; /* Loop counter */ - int jZeroRows = -1; /* Jump from here if number of rows is zero */ - int iDb; /* Index of database containing pTab */ - u8 needTableCnt = 1; /* True to count the table */ - int regNewRowid = iMem++; /* Rowid for the inserted record */ - int regStat = iMem++; /* Register to hold StatAccum object */ - int regChng = iMem++; /* Index of changed index field */ - int regRowid = iMem++; /* Rowid argument passed to stat_push() */ - int regTemp = iMem++; /* Temporary use register */ - int regTemp2 = iMem++; /* Second temporary use register */ - int regTabname = iMem++; /* Register containing table name */ - int regIdxname = iMem++; /* Register containing index name */ - int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ - int regPrev = iMem; /* MUST BE LAST (see below) */ -#ifdef SQLITE_ENABLE_STAT4 - int doOnce = 1; /* Flag for a one-time computation */ -#endif -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - Table *pStat1 = 0; -#endif - - sqlite3TouchRegister(pParse, iMem); - assert( sqlite3NoTempsInRange(pParse, regNewRowid, iMem) ); - v = sqlite3GetVdbe(pParse); - if( v==0 || NEVER(pTab==0) ){ - return; - } - if( !IsOrdinaryTable(pTab) ){ - /* Do not gather statistics on views or virtual tables */ - return; - } - if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ - /* Do not gather statistics on system tables */ - return; - } - assert( sqlite3BtreeHoldsAllMutexes(db) ); - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 ); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - db->aDb[iDb].zDbSName ) ){ - return; - } -#endif - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( db->xPreUpdateCallback ){ - pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13); - if( pStat1==0 ) return; - pStat1->zName = (char*)&pStat1[1]; - memcpy(pStat1->zName, "sqlite_stat1", 13); - pStat1->nCol = 3; - pStat1->iPKey = -1; - sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC); - } -#endif - - /* Establish a read-lock on the table at the shared-cache level. - ** Open a read-only cursor on the table. Also allocate a cursor number - ** to use for scanning indexes (iIdxCur). No index cursor is opened at - ** this time though. */ - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - iTabCur = iTab++; - iIdxCur = iTab++; - pParse->nTab = MAX(pParse->nTab, iTab); - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeLoadString(v, regTabname, pTab->zName); - - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int nCol; /* Number of columns in pIdx. "N" */ - int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */ - int addrNextRow; /* Address of "next_row:" */ - const char *zIdxName; /* Name of the index */ - int nColTest; /* Number of columns to test for changes */ - - if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; - if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0; - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){ - nCol = pIdx->nKeyCol; - zIdxName = pTab->zName; - nColTest = nCol - 1; - }else{ - nCol = pIdx->nColumn; - zIdxName = pIdx->zName; - nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1; - } - - /* Populate the register containing the index name. */ - sqlite3VdbeLoadString(v, regIdxname, zIdxName); - VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName)); - - /* - ** Pseudo-code for loop that calls stat_push(): - ** - ** regChng = 0 - ** Rewind csr - ** if eof(csr){ - ** stat_init() with count = 0; - ** goto end_of_scan; - ** } - ** count() - ** stat_init() - ** goto chng_addr_0; - ** - ** next_row: - ** regChng = 0 - ** if( idx(0) != regPrev(0) ) goto chng_addr_0 - ** regChng = 1 - ** if( idx(1) != regPrev(1) ) goto chng_addr_1 - ** ... - ** regChng = N - ** goto chng_addr_N - ** - ** chng_addr_0: - ** regPrev(0) = idx(0) - ** chng_addr_1: - ** regPrev(1) = idx(1) - ** ... - ** - ** endDistinctTest: - ** regRowid = idx(rowid) - ** stat_push(P, regChng, regRowid) - ** Next csr - ** if !eof(csr) goto next_row; - ** - ** end_of_scan: - */ - - /* Make sure there are enough memory cells allocated to accommodate - ** the regPrev array and a trailing rowid (the rowid slot is required - ** when building a record to insert into the sample column of - ** the sqlite_stat4 table. */ - sqlite3TouchRegister(pParse, regPrev+nColTest); - - /* Open a read-only cursor on the index being analyzed. */ - assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); - sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - - /* Implementation of the following: - ** - ** regChng = 0 - ** Rewind csr - ** if eof(csr){ - ** stat_init() with count = 0; - ** goto end_of_scan; - ** } - ** count() - ** stat_init() - ** goto chng_addr_0; - */ - assert( regTemp2==regStat+4 ); - sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2); - - /* Arguments to stat_init(): - ** (1) the number of columns in the index including the rowid - ** (or for a WITHOUT ROWID table, the number of PK columns), - ** (2) the number of columns in the key without the rowid/pk - ** (3) estimated number of rows in the index. */ - sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1); - assert( regRowid==regStat+2 ); - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid); - sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, - OptimizationDisabled(db, SQLITE_Stat4)); - sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4, - &statInitFuncdef, 0); - addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); - VdbeCoverage(v); - - sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); - addrNextRow = sqlite3VdbeCurrentAddr(v); - - if( nColTest>0 ){ - int endDistinctTest = sqlite3VdbeMakeLabel(pParse); - int *aGotoChng; /* Array of jump instruction addresses */ - aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); - if( aGotoChng==0 ) continue; - - /* - ** next_row: - ** regChng = 0 - ** if( idx(0) != regPrev(0) ) goto chng_addr_0 - ** regChng = 1 - ** if( idx(1) != regPrev(1) ) goto chng_addr_1 - ** ... - ** regChng = N - ** goto endDistinctTest - */ - sqlite3VdbeAddOp0(v, OP_Goto); - addrNextRow = sqlite3VdbeCurrentAddr(v); - if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){ - /* For a single-column UNIQUE index, once we have found a non-NULL - ** row, we know that all the rest will be distinct, so skip - ** subsequent distinctness tests. */ - sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest); - VdbeCoverage(v); - } - for(i=0; iazColl[i]); - sqlite3VdbeAddOp2(v, OP_Integer, i, regChng); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp); - analyzeVdbeCommentIndexWithColumnName(v,pIdx,i); - aGotoChng[i] = - sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - VdbeCoverage(v); - } - sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng); - sqlite3VdbeGoto(v, endDistinctTest); - - - /* - ** chng_addr_0: - ** regPrev(0) = idx(0) - ** chng_addr_1: - ** regPrev(1) = idx(1) - ** ... - */ - sqlite3VdbeJumpHere(v, addrNextRow-1); - for(i=0; ipTable); - int j, k, regKey; - regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol); - for(j=0; jnKeyCol; j++){ - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]); - assert( k>=0 && knColumn ); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); - analyzeVdbeCommentIndexWithColumnName(v,pIdx,k); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid); - sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol); - } - } -#endif - assert( regChng==(regStat+1) ); - { - sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4, - &statPushFuncdef, 0); - if( db->nAnalysisLimit ){ - int j1, j2, j3; - j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v); - j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j2); - sqlite3VdbeJumpHere(v, j3); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); - } - } - - /* Add the entry to the stat1 table. */ - if( pIdx->pPartIdxWhere ){ - /* Partial indexes might get a zero-entry in sqlite_stat1. But - ** an empty table is omitted from sqlite_stat1. */ - sqlite3VdbeJumpHere(v, addrGotoEnd); - addrGotoEnd = 0; - } - callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1); - assert( "BBB"[0]==SQLITE_AFF_TEXT ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); -#endif - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - - /* Add the entries to the stat4 table. */ -#ifdef SQLITE_ENABLE_STAT4 - if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){ - int regEq = regStat1; - int regLt = regStat1+1; - int regDLt = regStat1+2; - int regSample = regStat1+3; - int regCol = regStat1+4; - int regSampleRowid = regCol + nCol; - int addrNext; - int addrIsNull; - u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - - /* No STAT4 data is generated if the number of rows is zero */ - if( addrGotoEnd==0 ){ - sqlite3VdbeAddOp2(v, OP_Cast, regStat1, SQLITE_AFF_INTEGER); - addrGotoEnd = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); - VdbeCoverage(v); - } - - if( doOnce ){ - int mxCol = nCol; - Index *pX; - - /* Compute the maximum number of columns in any index */ - for(pX=pTab->pIndex; pX; pX=pX->pNext){ - int nColX; /* Number of columns in pX */ - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pX) ){ - nColX = pX->nKeyCol; - }else{ - nColX = pX->nColumn; - } - if( nColX>mxCol ) mxCol = nColX; - } - - /* Allocate space to compute results for the largest index */ - sqlite3TouchRegister(pParse, regCol+mxCol); - doOnce = 0; -#ifdef SQLITE_DEBUG - /* Verify that the call to sqlite3ClearTempRegCache() below - ** really is needed. - ** https://sqlite.org/forum/forumpost/83cb4a95a0 (2023-03-25) - */ - testcase( !sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) ); -#endif - sqlite3ClearTempRegCache(pParse); /* tag-20230325-1 */ - assert( sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) ); - } - assert( sqlite3NoTempsInRange(pParse, regEq, regCol+nCol) ); - - addrNext = sqlite3VdbeCurrentAddr(v); - callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid); - addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); - VdbeCoverage(v); - callStatGet(pParse, regStat, STAT_GET_NEQ, regEq); - callStatGet(pParse, regStat, STAT_GET_NLT, regLt); - callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt); - sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); - VdbeCoverage(v); - for(i=0; izName)); - sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); - assert( "BBB"[0]==SQLITE_AFF_TEXT ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); -#endif - sqlite3VdbeJumpHere(v, jZeroRows); - } -} - - -/* -** Generate code that will cause the most recent index analysis to -** be loaded into internal hash tables where is can be used. -*/ -static void loadAnalysis(Parse *pParse, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); - } -} - -/* -** Generate code that will do an analysis of an entire database -*/ -static void analyzeDatabase(Parse *pParse, int iDb){ - sqlite3 *db = pParse->db; - Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ - HashElem *k; - int iStatCur; - int iMem; - int iTab; - - sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab; - pParse->nTab += 3; - openStatTable(pParse, iDb, iStatCur, 0, 0); - iMem = pParse->nMem+1; - iTab = pParse->nTab; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pTab = (Table*)sqliteHashData(k); - analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); -#ifdef SQLITE_ENABLE_STAT4 - iMem = sqlite3FirstAvailableRegister(pParse, iMem); -#else - assert( iMem==sqlite3FirstAvailableRegister(pParse,iMem) ); -#endif - } - loadAnalysis(pParse, iDb); -} - -/* -** Generate code that will do an analysis of a single table in -** a database. If pOnlyIdx is not NULL then it is a single index -** in pTab that should be analyzed. -*/ -static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ - int iDb; - int iStatCur; - - assert( pTab!=0 ); - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab; - pParse->nTab += 3; - if( pOnlyIdx ){ - openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx"); - }else{ - openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl"); - } - analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab); - loadAnalysis(pParse, iDb); -} - -/* -** Generate code for the ANALYZE command. The parser calls this routine -** when it recognizes an ANALYZE command. -** -** ANALYZE -- 1 -** ANALYZE -- 2 -** ANALYZE ?.? -- 3 -** -** Form 1 causes all indices in all attached databases to be analyzed. -** Form 2 analyzes all indices the single database named. -** Form 3 analyzes all indices associated with the named table. -*/ -SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ - sqlite3 *db = pParse->db; - int iDb; - int i; - char *z, *zDb; - Table *pTab; - Index *pIdx; - Token *pTableName; - Vdbe *v; - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - return; - } - - assert( pName2!=0 || pName1==0 ); - if( pName1==0 ){ - /* Form 1: Analyze everything */ - for(i=0; inDb; i++){ - if( i==1 ) continue; /* Do not analyze the TEMP database */ - analyzeDatabase(pParse, i); - } - }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){ - /* Analyze the schema named as the argument */ - analyzeDatabase(pParse, iDb); - }else{ - /* Form 3: Analyze the table or index named as an argument */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); - if( iDb>=0 ){ - zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; - z = sqlite3NameFromToken(db, pTableName); - if( z ){ - if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ - analyzeTable(pParse, pIdx->pTable, pIdx); - }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ - analyzeTable(pParse, pTab, 0); - } - sqlite3DbFree(db, z); - } - } - } - if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ - sqlite3VdbeAddOp0(v, OP_Expire); - } -} - -/* -** Used to pass information from the analyzer reader through to the -** callback routine. -*/ -typedef struct analysisInfo analysisInfo; -struct analysisInfo { - sqlite3 *db; - const char *zDatabase; -}; - -/* -** The first argument points to a nul-terminated string containing a -** list of space separated integers. Read the first nOut of these into -** the array aOut[]. -*/ -static void decodeIntArray( - char *zIntArray, /* String containing int array to decode */ - int nOut, /* Number of slots in aOut[] */ - tRowcnt *aOut, /* Store integers here */ - LogEst *aLog, /* Or, if aOut==0, here */ - Index *pIndex /* Handle extra flags for this index, if not NULL */ -){ - char *z = zIntArray; - int c; - int i; - tRowcnt v; - -#ifdef SQLITE_ENABLE_STAT4 - if( z==0 ) z = ""; -#else - assert( z!=0 ); -#endif - for(i=0; *z && i='0' && c<='9' ){ - v = v*10 + c - '0'; - z++; - } -#ifdef SQLITE_ENABLE_STAT4 - if( aOut ) aOut[i] = v; - if( aLog ) aLog[i] = sqlite3LogEst(v); -#else - assert( aOut==0 ); - UNUSED_PARAMETER(aOut); - assert( aLog!=0 ); - aLog[i] = sqlite3LogEst(v); -#endif - if( *z==' ' ) z++; - } -#ifndef SQLITE_ENABLE_STAT4 - assert( pIndex!=0 ); { -#else - if( pIndex ){ -#endif - pIndex->bUnordered = 0; - pIndex->noSkipScan = 0; - while( z[0] ){ - if( sqlite3_strglob("unordered*", z)==0 ){ - pIndex->bUnordered = 1; - }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ - int sz = sqlite3Atoi(z+3); - if( sz<2 ) sz = 2; - pIndex->szIdxRow = sqlite3LogEst(sz); - }else if( sqlite3_strglob("noskipscan*", z)==0 ){ - pIndex->noSkipScan = 1; - } -#ifdef SQLITE_ENABLE_COSTMULT - else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ - pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9)); - } -#endif - while( z[0]!=0 && z[0]!=' ' ) z++; - while( z[0]==' ' ) z++; - } - } -} - -/* -** This callback is invoked once for each index when reading the -** sqlite_stat1 table. -** -** argv[0] = name of the table -** argv[1] = name of the index (might be NULL) -** argv[2] = results of analysis - on integer for each column -** -** Entries for which argv[1]==NULL simply record the number of rows in -** the table. -*/ -static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ - analysisInfo *pInfo = (analysisInfo*)pData; - Index *pIndex; - Table *pTable; - const char *z; - - assert( argc==3 ); - UNUSED_PARAMETER2(NotUsed, argc); - - if( argv==0 || argv[0]==0 || argv[2]==0 ){ - return 0; - } - pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase); - if( pTable==0 ){ - return 0; - } - if( argv[1]==0 ){ - pIndex = 0; - }else if( sqlite3_stricmp(argv[0],argv[1])==0 ){ - pIndex = sqlite3PrimaryKeyIndex(pTable); - }else{ - pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); - } - z = argv[2]; - - if( pIndex ){ - tRowcnt *aiRowEst = 0; - int nCol = pIndex->nKeyCol+1; -#ifdef SQLITE_ENABLE_STAT4 - /* Index.aiRowEst may already be set here if there are duplicate - ** sqlite_stat1 entries for this index. In that case just clobber - ** the old data with the new instead of allocating a new array. */ - if( pIndex->aiRowEst==0 ){ - pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); - if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); - } - aiRowEst = pIndex->aiRowEst; -#endif - pIndex->bUnordered = 0; - decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); - pIndex->hasStat1 = 1; - if( pIndex->pPartIdxWhere==0 ){ - pTable->nRowLogEst = pIndex->aiRowLogEst[0]; - pTable->tabFlags |= TF_HasStat1; - } - }else{ - Index fakeIdx; - fakeIdx.szIdxRow = pTable->szTabRow; -#ifdef SQLITE_ENABLE_COSTMULT - fakeIdx.pTable = pTable; -#endif - decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); - pTable->szTabRow = fakeIdx.szIdxRow; - pTable->tabFlags |= TF_HasStat1; - } - - return 0; -} - -/* -** If the Index.aSample variable is not NULL, delete the aSample[] array -** and its contents. -*/ -SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ - assert( db!=0 ); - assert( pIdx!=0 ); -#ifdef SQLITE_ENABLE_STAT4 - if( pIdx->aSample ){ - int j; - for(j=0; jnSample; j++){ - IndexSample *p = &pIdx->aSample[j]; - sqlite3DbFree(db, p->p); - } - sqlite3DbFree(db, pIdx->aSample); - } - if( db->pnBytesFreed==0 ){ - pIdx->nSample = 0; - pIdx->aSample = 0; - } -#else - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(pIdx); -#endif /* SQLITE_ENABLE_STAT4 */ -} - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Populate the pIdx->aAvgEq[] array based on the samples currently -** stored in pIdx->aSample[]. -*/ -static void initAvgEq(Index *pIdx){ - if( pIdx ){ - IndexSample *aSample = pIdx->aSample; - IndexSample *pFinal = &aSample[pIdx->nSample-1]; - int iCol; - int nCol = 1; - if( pIdx->nSampleCol>1 ){ - /* If this is stat4 data, then calculate aAvgEq[] values for all - ** sample columns except the last. The last is always set to 1, as - ** once the trailing PK fields are considered all index keys are - ** unique. */ - nCol = pIdx->nSampleCol-1; - pIdx->aAvgEq[nCol] = 1; - } - for(iCol=0; iColnSample; - int i; /* Used to iterate through samples */ - tRowcnt sumEq = 0; /* Sum of the nEq values */ - tRowcnt avgEq = 0; - tRowcnt nRow; /* Number of rows in index */ - i64 nSum100 = 0; /* Number of terms contributing to sumEq */ - i64 nDist100; /* Number of distinct values in index */ - - if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ - nRow = pFinal->anLt[iCol]; - nDist100 = (i64)100 * pFinal->anDLt[iCol]; - nSample--; - }else{ - nRow = pIdx->aiRowEst[0]; - nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1]; - } - pIdx->nRowEst0 = nRow; - - /* Set nSum to the number of distinct (iCol+1) field prefixes that - ** occur in the stat4 table for this index. Set sumEq to the sum of - ** the nEq values for column iCol for the same set (adding the value - ** only once where there exist duplicate prefixes). */ - for(i=0; inSample-1) - || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] - ){ - sumEq += aSample[i].anEq[iCol]; - nSum100 += 100; - } - } - - if( nDist100>nSum100 && sumEqaAvgEq[iCol] = avgEq; - } - } -} - -/* -** Look up an index by name. Or, if the name of a WITHOUT ROWID table -** is supplied instead, find the PRIMARY KEY index for that table. -*/ -static Index *findIndexOrPrimaryKey( - sqlite3 *db, - const char *zName, - const char *zDb -){ - Index *pIdx = sqlite3FindIndex(db, zName, zDb); - if( pIdx==0 ){ - Table *pTab = sqlite3FindTable(db, zName, zDb); - if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab); - } - return pIdx; -} - -/* -** Load the content from either the sqlite_stat4 -** into the relevant Index.aSample[] arrays. -** -** Arguments zSql1 and zSql2 must point to SQL statements that return -** data equivalent to the following: -** -** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx -** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4 -** -** where %Q is replaced with the database name before the SQL is executed. -*/ -static int loadStatTbl( - sqlite3 *db, /* Database handle */ - const char *zSql1, /* SQL statement 1 (see above) */ - const char *zSql2, /* SQL statement 2 (see above) */ - const char *zDb /* Database name (e.g. "main") */ -){ - int rc; /* Result codes from subroutines */ - sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ - char *zSql; /* Text of the SQL statement */ - Index *pPrevIdx = 0; /* Previous index in the loop */ - IndexSample *pSample; /* A slot in pIdx->aSample[] */ - - assert( db->lookaside.bDisable ); - zSql = sqlite3MPrintf(db, zSql1, zDb); - if( !zSql ){ - return SQLITE_NOMEM_BKPT; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3DbFree(db, zSql); - if( rc ) return rc; - - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - int nIdxCol = 1; /* Number of columns in stat4 records */ - - char *zIndex; /* Index name */ - Index *pIdx; /* Pointer to the index object */ - int nSample; /* Number of samples */ - i64 nByte; /* Bytes of space required */ - i64 i; /* Bytes of space required */ - tRowcnt *pSpace; /* Available allocated memory space */ - u8 *pPtr; /* Available memory as a u8 for easier manipulation */ - - zIndex = (char *)sqlite3_column_text(pStmt, 0); - if( zIndex==0 ) continue; - nSample = sqlite3_column_int(pStmt, 1); - pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); - assert( pIdx==0 || pIdx->nSample==0 ); - if( pIdx==0 ) continue; - if( pIdx->aSample!=0 ){ - /* The same index appears in sqlite_stat4 under multiple names */ - continue; - } - assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nIdxCol = pIdx->nKeyCol; - }else{ - nIdxCol = pIdx->nColumn; - } - pIdx->nSampleCol = nIdxCol; - pIdx->mxSample = nSample; - nByte = ROUND8(sizeof(IndexSample) * nSample); - nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; - nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ - - pIdx->aSample = sqlite3DbMallocZero(db, nByte); - if( pIdx->aSample==0 ){ - sqlite3_finalize(pStmt); - return SQLITE_NOMEM_BKPT; - } - pPtr = (u8*)pIdx->aSample; - pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0])); - pSpace = (tRowcnt*)pPtr; - assert( EIGHT_BYTE_ALIGNMENT( pSpace ) ); - pIdx->aAvgEq = pSpace; pSpace += nIdxCol; - pIdx->pTable->tabFlags |= TF_HasStat4; - for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; - pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; - pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; - } - assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) ); - } - rc = sqlite3_finalize(pStmt); - if( rc ) return rc; - - zSql = sqlite3MPrintf(db, zSql2, zDb); - if( !zSql ){ - return SQLITE_NOMEM_BKPT; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3DbFree(db, zSql); - if( rc ) return rc; - - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - char *zIndex; /* Index name */ - Index *pIdx; /* Pointer to the index object */ - int nCol = 1; /* Number of columns in index */ - - zIndex = (char *)sqlite3_column_text(pStmt, 0); - if( zIndex==0 ) continue; - pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); - if( pIdx==0 ) continue; - if( pIdx->nSample>=pIdx->mxSample ){ - /* Too many slots used because the same index appears in - ** sqlite_stat4 using multiple names */ - continue; - } - /* This next condition is true if data has already been loaded from - ** the sqlite_stat4 table. */ - nCol = pIdx->nSampleCol; - if( pIdx!=pPrevIdx ){ - initAvgEq(pPrevIdx); - pPrevIdx = pIdx; - } - pSample = &pIdx->aSample[pIdx->nSample]; - decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); - decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); - decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); - - /* Take a copy of the sample. Add 8 extra 0x00 bytes the end of the buffer. - ** This is in case the sample record is corrupted. In that case, the - ** sqlite3VdbeRecordCompare() may read up to two varints past the - ** end of the allocated buffer before it realizes it is dealing with - ** a corrupt record. Or it might try to read a large integer from the - ** buffer. In any case, eight 0x00 bytes prevents this from causing - ** a buffer overread. */ - pSample->n = sqlite3_column_bytes(pStmt, 4); - pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); - if( pSample->p==0 ){ - sqlite3_finalize(pStmt); - return SQLITE_NOMEM_BKPT; - } - if( pSample->n ){ - memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); - } - pIdx->nSample++; - } - rc = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) initAvgEq(pPrevIdx); - return rc; -} - -/* -** Load content from the sqlite_stat4 table into -** the Index.aSample[] arrays of all indices. -*/ -static int loadStat4(sqlite3 *db, const char *zDb){ - int rc = SQLITE_OK; /* Result codes from subroutines */ - const Table *pStat4; - - assert( db->lookaside.bDisable ); - if( OptimizationEnabled(db, SQLITE_Stat4) - && (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0 - && IsOrdinaryTable(pStat4) - ){ - rc = loadStatTbl(db, - "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx COLLATE nocase", - "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", - zDb - ); - } - return rc; -} -#endif /* SQLITE_ENABLE_STAT4 */ - -/* -** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The -** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] -** arrays. The contents of sqlite_stat4 are used to populate the -** Index.aSample[] arrays. -** -** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR -** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined -** during compilation and the sqlite_stat4 table is present, no data is -** read from it. -** -** If SQLITE_ENABLE_STAT4 was defined during compilation and the -** sqlite_stat4 table is not present in the database, SQLITE_ERROR is -** returned. However, in this case, data is read from the sqlite_stat1 -** table (if it is present) before returning. -** -** If an OOM error occurs, this function always sets db->mallocFailed. -** This means if the caller does not care about other errors, the return -** code may be ignored. -*/ -SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ - analysisInfo sInfo; - HashElem *i; - char *zSql; - int rc = SQLITE_OK; - Schema *pSchema = db->aDb[iDb].pSchema; - const Table *pStat1; - - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 ); - - /* Clear any prior statistics */ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - pTab->tabFlags &= ~TF_HasStat1; - } - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ - Index *pIdx = sqliteHashData(i); - pIdx->hasStat1 = 0; -#ifdef SQLITE_ENABLE_STAT4 - sqlite3DeleteIndexSamples(db, pIdx); - pIdx->aSample = 0; -#endif - } - - /* Load new statistics out of the sqlite_stat1 table */ - sInfo.db = db; - sInfo.zDatabase = db->aDb[iDb].zDbSName; - if( (pStat1 = sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)) - && IsOrdinaryTable(pStat1) - ){ - zSql = sqlite3MPrintf(db, - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); - if( zSql==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - sqlite3DbFree(db, zSql); - } - } - - /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ - Index *pIdx = sqliteHashData(i); - if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx); - } - - /* Load the statistics from the sqlite_stat4 table. */ -#ifdef SQLITE_ENABLE_STAT4 - if( rc==SQLITE_OK ){ - DisableLookaside; - rc = loadStat4(db, sInfo.zDatabase); - EnableLookaside; - } - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ - Index *pIdx = sqliteHashData(i); - sqlite3_free(pIdx->aiRowEst); - pIdx->aiRowEst = 0; - } -#endif - - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(db); - } - return rc; -} - - -#endif /* SQLITE_OMIT_ANALYZE */ - -/************** End of analyze.c *********************************************/ -/************** Begin file attach.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the ATTACH and DETACH commands. -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_ATTACH -/* -** Resolve an expression that was part of an ATTACH or DETACH statement. This -** is slightly different from resolving a normal SQL expression, because simple -** identifiers are treated as strings, not possible column names or aliases. -** -** i.e. if the parser sees: -** -** ATTACH DATABASE abc AS def -** -** it treats the two expressions as literal strings 'abc' and 'def' instead of -** looking for columns of the same name. -** -** This only applies to the root node of pExpr, so the statement: -** -** ATTACH DATABASE abc||def AS 'db2' -** -** will fail because neither abc or def can be resolved. -*/ -static int resolveAttachExpr(NameContext *pName, Expr *pExpr) -{ - int rc = SQLITE_OK; - if( pExpr ){ - if( pExpr->op!=TK_ID ){ - rc = sqlite3ResolveExprNames(pName, pExpr); - }else{ - pExpr->op = TK_STRING; - } - } - return rc; -} - -/* -** Return true if zName points to a name that may be used to refer to -** database iDb attached to handle db. -*/ -SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){ - return ( - sqlite3StrICmp(db->aDb[iDb].zDbSName, zName)==0 - || (iDb==0 && sqlite3StrICmp("main", zName)==0) - ); -} - -/* -** An SQL user-function registered to do the work of an ATTACH statement. The -** three arguments to the function come directly from an attach statement: -** -** ATTACH DATABASE x AS y KEY z -** -** SELECT sqlite_attach(x, y, z) -** -** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the -** third argument. -** -** If the db->init.reopenMemdb flags is set, then instead of attaching a -** new database, close the database on db->init.iDb and reopen it as an -** empty MemDB. -*/ -static void attachFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - int i; - int rc = 0; - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zName; - const char *zFile; - char *zPath = 0; - char *zErr = 0; - unsigned int flags; - Db *aNew; /* New array of Db pointers */ - Db *pNew = 0; /* Db object for the newly attached database */ - char *zErrDyn = 0; - sqlite3_vfs *pVfs; - - UNUSED_PARAMETER(NotUsed); - zFile = (const char *)sqlite3_value_text(argv[0]); - zName = (const char *)sqlite3_value_text(argv[1]); - if( zFile==0 ) zFile = ""; - if( zName==0 ) zName = ""; - -#ifndef SQLITE_OMIT_DESERIALIZE -# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) -#else -# define REOPEN_AS_MEMDB(db) (0) -#endif - - if( REOPEN_AS_MEMDB(db) ){ - /* This is not a real ATTACH. Instead, this routine is being called - ** from sqlite3_deserialize() to close database db->init.iDb and - ** reopen it as a MemDB */ - Btree *pNewBt = 0; - pVfs = sqlite3_vfs_find("memdb"); - if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); - if( rc==SQLITE_OK ){ - Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); - if( pNewSchema ){ - /* Both the Btree and the new Schema were allocated successfully. - ** Close the old db and update the aDb[] slot with the new memdb - ** values. */ - pNew = &db->aDb[db->init.iDb]; - if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt); - pNew->pBt = pNewBt; - pNew->pSchema = pNewSchema; - }else{ - sqlite3BtreeClose(pNewBt); - rc = SQLITE_NOMEM; - } - } - if( rc ) goto attach_error; - }else{ - /* This is a real ATTACH - ** - ** Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - for(i=0; inDb; i++){ - assert( zName ); - if( sqlite3DbIsNamed(db, i, zName) ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); - goto attach_error; - } - } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(1+(i64)db->nDb)); - if( aNew==0 ) return; - } - db->aDb = aNew; - pNew = &db->aDb[db->nDb]; - memset(pNew, 0, sizeof(*pNew)); - - /* Open the database file. If the btree is successfully opened, use - ** it to obtain the database schema. At this point the schema may - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - if( (db->flags & SQLITE_AttachWrite)==0 ){ - flags &= ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE); - flags |= SQLITE_OPEN_READONLY; - }else if( (db->flags & SQLITE_AttachCreate)==0 ){ - flags &= ~SQLITE_OPEN_CREATE; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); - db->nDb++; - pNew->zDbSName = sqlite3DbStrDup(db, zName); - } - db->noSharedCache = 0; - if( rc==SQLITE_CONSTRAINT ){ - rc = SQLITE_ERROR; - zErrDyn = sqlite3MPrintf(db, "database is already attached"); - }else if( rc==SQLITE_OK ){ - Pager *pPager; - pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt); - if( !pNew->pSchema ){ - rc = SQLITE_NOMEM_BKPT; - }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){ - zErrDyn = sqlite3MPrintf(db, - "attached databases must use the same text encoding as main database"); - rc = SQLITE_ERROR; - } - sqlite3BtreeEnter(pNew->pBt); - pPager = sqlite3BtreePager(pNew->pBt); - sqlite3PagerLockingMode(pPager, db->dfltLockMode); - sqlite3BtreeSecureDelete(pNew->pBt, - sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); -#ifndef SQLITE_OMIT_PAGER_PRAGMAS - sqlite3BtreeSetPagerFlags(pNew->pBt, - PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); -#endif - sqlite3BtreeLeave(pNew->pBt); - } - pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - if( rc==SQLITE_OK && pNew->zDbSName==0 ){ - rc = SQLITE_NOMEM_BKPT; - } - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( rc==SQLITE_OK ){ - extern int sqlcipherCodecAttach(sqlite3*, int, const void*, int); - extern void sqlcipherCodecGetKey(sqlite3*, int, void**, int*); - extern void sqlcipher_free(void*, sqlite3_uint64); - int nKey; - char *zKey; - int t = sqlite3_value_type(argv[2]); - switch( t ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); - rc = SQLITE_ERROR; - break; - - case SQLITE_TEXT: - case SQLITE_BLOB: - nKey = sqlite3_value_bytes(argv[2]); - zKey = (char *)sqlite3_value_blob(argv[2]); - /* SQLCipher allows a special case to attach a plaintext database - * to an encrypted database by passing key as an empty string, eg. - * ATTACH DATABASE 'plain.db' AS plain KEY ''; - * In this case, do not attempt to attach a codec to the attached - * database */ - if(nKey && zKey) { - 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( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){ - sqlcipherCodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey || sqlite3BtreeGetRequestedReserve(db->aDb[0].pBt)>0 ){ - rc = sqlcipherCodecAttach(db, db->nDb-1, zKey, nKey); - } - if(nKey) sqlcipher_free(zKey, nKey); - } - break; - } - } -#endif -/* END SQLCIPHER */ - sqlite3_free_filename( zPath ); - - /* If the file was opened successfully, read the schema for the new database. - ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the - ** way we found it. - */ - if( rc==SQLITE_OK ){ - sqlite3BtreeEnterAll(db); - db->init.iDb = 0; - db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){ - int val = 1; - sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt)); - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val); - } -#endif - if( !REOPEN_AS_MEMDB(db) ){ - rc = sqlite3Init(db, &zErrDyn); - } - sqlite3BtreeLeaveAll(db); - assert( zErrDyn==0 || rc!=SQLITE_OK ); - } - if( rc ){ - if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); - } - } - goto attach_error; - } - - return; - -attach_error: - /* Return an error if we get here */ - if( zErrDyn ){ - sqlite3_result_error(context, zErrDyn, -1); - sqlite3DbFree(db, zErrDyn); - } - if( rc ) sqlite3_result_error_code(context, rc); -} - -/* -** An SQL user-function registered to do the work of an DETACH statement. The -** three arguments to the function come directly from a detach statement: -** -** DETACH DATABASE x -** -** SELECT sqlite_detach(x) -*/ -static void detachFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - const char *zName = (const char *)sqlite3_value_text(argv[0]); - sqlite3 *db = sqlite3_context_db_handle(context); - int i; - Db *pDb = 0; - HashElem *pEntry; - char zErr[128]; - - UNUSED_PARAMETER(NotUsed); - - if( zName==0 ) zName = ""; - for(i=0; inDb; i++){ - pDb = &db->aDb[i]; - if( pDb->pBt==0 ) continue; - if( sqlite3DbIsNamed(db, i, zName) ) break; - } - - if( i>=db->nDb ){ - sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); - goto detach_error; - } - if( i<2 ){ - sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); - goto detach_error; - } - if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE - || sqlite3BtreeIsInBackup(pDb->pBt) - ){ - sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); - goto detach_error; - } - - /* If any TEMP triggers reference the schema being detached, move those - ** triggers to reference the TEMP schema itself. */ - assert( db->aDb[1].pSchema ); - pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); - while( pEntry ){ - Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); - if( pTrig->pTabSchema==pDb->pSchema ){ - pTrig->pTabSchema = pTrig->pSchema; - } - pEntry = sqliteHashNext(pEntry); - } - - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - sqlite3CollapseDatabaseArray(db); - return; - -detach_error: - sqlite3_result_error(context, zErr, -1); -} - -/* -** This procedure generates VDBE code for a single invocation of either the -** sqlite_detach() or sqlite_attach() SQL user functions. -*/ -static void codeAttach( - Parse *pParse, /* The parser context */ - int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ - FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */ - Expr *pAuthArg, /* Expression to pass to authorization callback */ - Expr *pFilename, /* Name of database file */ - Expr *pDbname, /* Name of the database to use internally */ - Expr *pKey /* Database key for encryption extension */ -){ - int rc; - NameContext sName; - Vdbe *v; - sqlite3* db = pParse->db; - int regArgs; - - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end; - - if( pParse->nErr ) goto attach_end; - memset(&sName, 0, sizeof(NameContext)); - sName.pParse = pParse; - - if( - SQLITE_OK!=resolveAttachExpr(&sName, pFilename) || - SQLITE_OK!=resolveAttachExpr(&sName, pDbname) || - SQLITE_OK!=resolveAttachExpr(&sName, pKey) - ){ - goto attach_end; - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( ALWAYS(pAuthArg) ){ - char *zAuthArg; - if( pAuthArg->op==TK_STRING ){ - assert( !ExprHasProperty(pAuthArg, EP_IntValue) ); - zAuthArg = pAuthArg->u.zToken; - }else{ - zAuthArg = 0; - } - rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); - if(rc!=SQLITE_OK ){ - goto attach_end; - } - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - - - v = sqlite3GetVdbe(pParse); - regArgs = sqlite3GetTempRange(pParse, 4); - sqlite3ExprCode(pParse, pFilename, regArgs); - sqlite3ExprCode(pParse, pDbname, regArgs+1); - sqlite3ExprCode(pParse, pKey, regArgs+2); - - assert( v || db->mallocFailed ); - if( v ){ - sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3, - pFunc->nArg, pFunc, 0); - /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this - ** statement only). For DETACH, set it to false (expire all existing - ** statements). - */ - sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); - } - -attach_end: - sqlite3ExprDelete(db, pFilename); - sqlite3ExprDelete(db, pDbname); - sqlite3ExprDelete(db, pKey); -} - -/* -** Called by the parser to compile a DETACH statement. -** -** DETACH pDbname -*/ -SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){ - static const FuncDef detach_func = { - 1, /* nArg */ - SQLITE_UTF8, /* funcFlags */ - 0, /* pUserData */ - 0, /* pNext */ - detachFunc, /* xSFunc */ - 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ - "sqlite_detach", /* zName */ - {0} - }; - codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); -} - -/* -** Called by the parser to compile an ATTACH statement. -** -** ATTACH p AS pDbname KEY pKey -*/ -SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ - static const FuncDef attach_func = { - 3, /* nArg */ - SQLITE_UTF8, /* funcFlags */ - 0, /* pUserData */ - 0, /* pNext */ - attachFunc, /* xSFunc */ - 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ - "sqlite_attach", /* zName */ - {0} - }; - codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); -} -#endif /* SQLITE_OMIT_ATTACH */ - -/* -** Expression callback used by 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{ - sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); - return WRC_Abort; - } - } - return WRC_Continue; -} - -/* -** Select callback used by sqlite3FixAAAA() routines. -*/ -static int fixSelectCb(Walker *p, Select *pSelect){ - DbFixer *pFix = p->u.pFix; - int i; - SrcItem *pItem; - sqlite3 *db = pFix->pParse->db; - int iDb = sqlite3FindDbName(db, pFix->zDb); - SrcList *pList = pSelect->pSrc; - - if( NEVER(pList==0) ) return WRC_Continue; - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){ - if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){ - if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){ - sqlite3ErrorMsg(pFix->pParse, - "%s %T cannot reference objects in database %s", - pFix->zType, pFix->pName, pItem->u4.zDatabase); - return WRC_Abort; - } - sqlite3DbFree(db, pItem->u4.zDatabase); - pItem->fg.notCte = 1; - pItem->fg.hadSchema = 1; - } - pItem->u4.pSchema = pFix->pSchema; - pItem->fg.fromDDL = 1; - pItem->fg.fixedSchema = 1; - } -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) - if( pList->a[i].fg.isUsing==0 - && sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn) - ){ - return WRC_Abort; - } -#endif - } - if( pSelect->pWith ){ - for(i=0; ipWith->nCte; i++){ - if( 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. -*/ -SQLITE_PRIVATE void sqlite3FixInit( - DbFixer *pFix, /* The fixer to be initialized */ - Parse *pParse, /* Error messages will be written here */ - int iDb, /* This is the database that must be used */ - const char *zType, /* "view", "trigger", or "index" */ - const Token *pName /* Name of the view, trigger, or index */ -){ - sqlite3 *db = pParse->db; - assert( db->nDb>iDb ); - pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zDbSName; - pFix->pSchema = db->aDb[iDb].pSchema; - 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 = sqlite3WalkWinDefnDummyCallback; - pFix->w.walkerDepth = 0; - pFix->w.eCode = 0; - pFix->w.u.pFix = pFix; -} - -/* -** The following set of routines walk through the parse tree and assign -** a specific database to all table references where the database name -** was left unspecified in the original SQL statement. The pFix structure -** must have been initialized by a prior call to sqlite3FixInit(). -** -** These routines are used to make sure that an index, trigger, or -** view in one database does not refer to objects in a different database. -** (Exception: indices, triggers, and views in the TEMP database are -** allowed to refer to anything.) If a reference is explicitly made -** to an object in a different database, an error message is added to -** pParse->zErrMsg and these routines return non-zero. If everything -** checks out, these routines return 0. -*/ -SQLITE_PRIVATE int sqlite3FixSrcList( - DbFixer *pFix, /* Context of the fixation */ - SrcList *pList /* The Source list to check and modify */ -){ - int res = 0; - if( pList ){ - Select s; - memset(&s, 0, sizeof(s)); - s.pSrc = pList; - res = sqlite3WalkSelect(&pFix->w, &s); - } - return res; -} -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE int sqlite3FixSelect( - DbFixer *pFix, /* Context of the fixation */ - Select *pSelect /* The SELECT statement to be fixed to one database */ -){ - return sqlite3WalkSelect(&pFix->w, pSelect); -} -SQLITE_PRIVATE int sqlite3FixExpr( - DbFixer *pFix, /* Context of the fixation */ - Expr *pExpr /* The expression to be fixed to one database */ -){ - return sqlite3WalkExpr(&pFix->w, pExpr); -} -#endif - -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE int sqlite3FixTriggerStep( - DbFixer *pFix, /* Context of the fixation */ - TriggerStep *pStep /* The trigger step be fixed to one database */ -){ - while( pStep ){ - if( sqlite3WalkSelect(&pFix->w, pStep->pSelect) - || sqlite3WalkExpr(&pFix->w, pStep->pWhere) - || sqlite3WalkExprList(&pFix->w, pStep->pExprList) - || sqlite3FixSrcList(pFix, pStep->pFrom) - ){ - return 1; - } -#ifndef SQLITE_OMIT_UPSERT - { - Upsert *pUp; - for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){ - if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget) - || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere) - || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet) - || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere) - ){ - return 1; - } - } - } -#endif - pStep = pStep->pNext; - } - - return 0; -} -#endif - -/************** End of attach.c **********************************************/ -/************** Begin file auth.c ********************************************/ -/* -** 2003 January 11 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the sqlite3_set_authorizer() -** API. This facility is an optional feature of the library. Embedded -** systems that do not need this facility may omit it by recompiling -** the library with -DSQLITE_OMIT_AUTHORIZATION=1 -*/ -/* #include "sqliteInt.h" */ - -/* -** All of the code in this file may be omitted by defining a single -** macro. -*/ -#ifndef SQLITE_OMIT_AUTHORIZATION - -/* -** Set or clear the access authorization function. -** -** The access authorization function is be called during the compilation -** phase to verify that the user has read and/or write access permission on -** various fields of the database. The first argument to the auth function -** is a copy of the 3rd argument to this routine. The second argument -** to the auth function is one of these constants: -** -** SQLITE_CREATE_INDEX -** SQLITE_CREATE_TABLE -** SQLITE_CREATE_TEMP_INDEX -** SQLITE_CREATE_TEMP_TABLE -** SQLITE_CREATE_TEMP_TRIGGER -** SQLITE_CREATE_TEMP_VIEW -** SQLITE_CREATE_TRIGGER -** SQLITE_CREATE_VIEW -** SQLITE_DELETE -** SQLITE_DROP_INDEX -** SQLITE_DROP_TABLE -** SQLITE_DROP_TEMP_INDEX -** SQLITE_DROP_TEMP_TABLE -** SQLITE_DROP_TEMP_TRIGGER -** SQLITE_DROP_TEMP_VIEW -** SQLITE_DROP_TRIGGER -** SQLITE_DROP_VIEW -** SQLITE_INSERT -** SQLITE_PRAGMA -** SQLITE_READ -** SQLITE_SELECT -** SQLITE_TRANSACTION -** SQLITE_UPDATE -** -** The third and fourth arguments to the auth function are the name of -** the table and the column that are being accessed. The auth function -** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If -** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY -** means that the SQL statement will never-run - the sqlite3_exec() call -** will return with an error. SQLITE_IGNORE means that the SQL statement -** should run but attempts to read the specified column will return NULL -** and attempts to write the column will be ignored. -** -** Setting the auth function to NULL disables this hook. The default -** setting of the auth function is NULL. -*/ -SQLITE_API int sqlite3_set_authorizer( - sqlite3 *db, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pArg -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - db->xAuth = (sqlite3_xauth)xAuth; - db->pAuthArg = pArg; - if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Write an error message into pParse->zErrMsg that explains that the -** user-supplied authorization function returned an illegal value. -*/ -static void sqliteAuthBadReturnCode(Parse *pParse){ - sqlite3ErrorMsg(pParse, "authorizer malfunction"); - pParse->rc = SQLITE_ERROR; -} - -/* -** Invoke the authorization callback for permission to read column zCol from -** table zTab in database zDb. This function assumes that an authorization -** callback has been registered (i.e. that sqlite3.xAuth is not NULL). -** -** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed -** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE -** is treated as SQLITE_DENY. In this case an error is left in pParse. -*/ -SQLITE_PRIVATE int sqlite3AuthReadCol( - Parse *pParse, /* The parser context */ - const char *zTab, /* Table name */ - const char *zCol, /* Column name */ - int iDb /* Index of containing database. */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */ - int rc; /* Auth callback return code */ - - if( db->init.busy ) return SQLITE_OK; - rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext); - if( rc==SQLITE_DENY ){ - char *z = sqlite3_mprintf("%s.%s", zTab, zCol); - if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z); - sqlite3ErrorMsg(pParse, "access to %z is prohibited", z); - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ - sqliteAuthBadReturnCode(pParse); - } - return rc; -} - -/* -** The pExpr should be a TK_COLUMN expression. The table referred to -** is in pTabList or else it is the NEW or OLD table of a trigger. -** Check to see if it is OK to read this particular column. -** -** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN -** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, -** then generate an error. -*/ -SQLITE_PRIVATE void sqlite3AuthRead( - Parse *pParse, /* The parser context */ - Expr *pExpr, /* The expression to check authorization on */ - Schema *pSchema, /* The schema of the expression */ - SrcList *pTabList /* All table that pExpr might refer to */ -){ - 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 */ - int iDb; /* The index of the database the expression refers to */ - int iCol; /* Index of column in table */ - - assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); - assert( !IN_RENAME_OBJECT ); - assert( pParse->db->xAuth!=0 ); - iDb = sqlite3SchemaToIndex(pParse->db, pSchema); - if( iDb<0 ){ - /* An attempt to read a column out of a subquery or other - ** temporary table. */ - return; - } - - if( pExpr->op==TK_TRIGGER ){ - pTab = pParse->pTriggerTab; - }else{ - assert( pTabList ); - for(iSrc=0; iSrcnSrc; iSrc++){ - if( pExpr->iTable==pTabList->a[iSrc].iCursor ){ - pTab = pTabList->a[iSrc].pSTab; - break; - } - } - } - iCol = pExpr->iColumn; - if( pTab==0 ) return; - - if( iCol>=0 ){ - assert( iColnCol ); - zCol = pTab->aCol[iCol].zCnName; - }else if( pTab->iPKey>=0 ){ - assert( pTab->iPKeynCol ); - zCol = pTab->aCol[pTab->iPKey].zCnName; - }else{ - zCol = "ROWID"; - } - assert( iDb>=0 && iDbdb->nDb ); - if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){ - pExpr->op = TK_NULL; - } -} - -/* -** Do an authorization check using the code and arguments given. Return -** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY -** is returned, then the error count and error message in pParse are -** modified appropriately. -*/ -SQLITE_PRIVATE int sqlite3AuthCheck( - Parse *pParse, - int code, - const char *zArg1, - const char *zArg2, - const char *zArg3 -){ - sqlite3 *db = pParse->db; - int rc; - - /* Don't do any authorization checks if the database is initializing - ** or if the parser is being invoked from within sqlite3_declare_vtab. - */ - assert( !IN_RENAME_OBJECT || db->xAuth==0 ); - if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){ - return SQLITE_OK; - } - - /* EVIDENCE-OF: R-43249-19882 The third through sixth parameters to the - ** callback are either NULL pointers or zero-terminated strings that - ** contain additional details about the action to be authorized. - ** - ** The following testcase() macros show that any of the 3rd through 6th - ** parameters can be either NULL or a string. */ - testcase( zArg1==0 ); - testcase( zArg2==0 ); - testcase( zArg3==0 ); - testcase( pParse->zAuthContext==0 ); - - rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext); - if( rc==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized"); - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ - rc = SQLITE_DENY; - sqliteAuthBadReturnCode(pParse); - } - return rc; -} - -/* -** Push an authorization context. After this routine is called, the -** zArg3 argument to authorization callbacks will be zContext until -** popped. Or if pParse==0, this routine is a no-op. -*/ -SQLITE_PRIVATE void sqlite3AuthContextPush( - Parse *pParse, - AuthContext *pContext, - const char *zContext -){ - assert( pParse ); - pContext->pParse = pParse; - pContext->zAuthContext = pParse->zAuthContext; - pParse->zAuthContext = zContext; -} - -/* -** Pop an authorization context that was previously pushed -** by sqlite3AuthContextPush -*/ -SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ - if( pContext->pParse ){ - pContext->pParse->zAuthContext = pContext->zAuthContext; - pContext->pParse = 0; - } -} - -#endif /* SQLITE_OMIT_AUTHORIZATION */ - -/************** End of auth.c ************************************************/ -/************** Begin file build.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the SQLite parser -** when syntax rules are reduced. The routines in this file handle the -** following kinds of SQL syntax: -** -** CREATE TABLE -** DROP TABLE -** CREATE INDEX -** DROP INDEX -** creating ID lists -** BEGIN TRANSACTION -** COMMIT -** ROLLBACK -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** The TableLock structure is only used by the sqlite3TableLock() and -** codeTableLocks() functions. -*/ -struct TableLock { - int iDb; /* The database containing the table to be locked */ - Pgno iTab; /* The root page of the table to be locked */ - u8 isWriteLock; /* True for write lock. False for a read lock */ - const char *zLockName; /* Name of the table */ -}; - -/* -** Record the fact that we want to lock a table at run-time. -** -** The table to be locked has root page iTab and is found in database iDb. -** A read or a write lock can be taken depending on isWritelock. -** -** This routine just records the fact that the lock is desired. The -** code to make the lock occur is generated by a later call to -** codeTableLocks() which occurs during sqlite3FinishCoding(). -*/ -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 */ - u8 isWriteLock, /* True for a write lock */ - const char *zName /* Name of the table to be locked */ -){ - Parse *pToplevel; - int i; - int nBytes; - TableLock *p; - assert( iDb>=0 ); - - pToplevel = sqlite3ParseToplevel(pParse); - for(i=0; inTableLock; i++){ - p = &pToplevel->aTableLock[i]; - if( p->iDb==iDb && p->iTab==iTab ){ - p->isWriteLock = (p->isWriteLock || isWriteLock); - return; - } - } - - assert( pToplevel->nTableLock < 0x7fff0000 ); - nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1); - pToplevel->aTableLock = - sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes); - if( pToplevel->aTableLock ){ - p = &pToplevel->aTableLock[pToplevel->nTableLock++]; - p->iDb = iDb; - p->iTab = iTab; - p->isWriteLock = isWriteLock; - p->zLockName = zName; - }else{ - pToplevel->nTableLock = 0; - sqlite3OomFault(pToplevel->db); - } -} -SQLITE_PRIVATE void 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( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return; - lockTable(pParse, iDb, iTab, isWriteLock, zName); -} - -/* -** Code an OP_TableLock instruction for each table locked by the -** statement (configured by calls to sqlite3TableLock()). -*/ -static void codeTableLocks(Parse *pParse){ - int i; - Vdbe *pVdbe = pParse->pVdbe; - assert( pVdbe!=0 ); - - for(i=0; inTableLock; i++){ - TableLock *p = &pParse->aTableLock[i]; - int p1 = p->iDb; - sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, - p->zLockName, P4_STATIC); - } -} -#else - #define codeTableLocks(x) -#endif - -/* -** Return TRUE if the given yDbMask object is empty - if it contains no -** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero() -** macros when SQLITE_MAX_ATTACHED is greater than 30. -*/ -#if SQLITE_MAX_ATTACHED>30 -SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){ - int i; - for(i=0; ipToplevel==0 ); - db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nested ) return; - 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 = pParse->pVdbe; - if( v==0 ){ - if( db->init.busy ){ - pParse->rc = SQLITE_DONE; - return; - } - v = sqlite3GetVdbe(pParse); - if( v==0 ) pParse->rc = SQLITE_ERROR; - } - assert( !pParse->isMultiWrite - || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); - if( v ){ - if( pParse->bReturning ){ - Returning *pReturning; - int addrRewind; - int reg; - - assert( !pParse->isCreate ); - pReturning = pParse->u1.d.pReturning; - if( pReturning->nRetCol ){ - sqlite3VdbeAddOp0(v, OP_FkCheck); - addrRewind = - sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); - VdbeCoverage(v); - reg = pReturning->iRetReg; - for(i=0; inRetCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i); - sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrRewind); - } - } - sqlite3VdbeAddOp0(v, OP_Halt); - - /* The cookie mask contains one bit for each database file open. - ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are - ** set for each database that is used. Generate code to start a - ** transaction on each used database and to verify the schema cookie - ** on each used database. - */ - assert( pParse->nErr>0 || sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); - sqlite3VdbeJumpHere(v, 0); - assert( db->nDb>0 ); - iDb = 0; - do{ - Schema *pSchema; - if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; - sqlite3VdbeUsesBtree(v, iDb); - pSchema = db->aDb[iDb].pSchema; - sqlite3VdbeAddOp4Int(v, - OP_Transaction, /* Opcode */ - iDb, /* P1 */ - DbMaskTest(pParse->writeMask,iDb), /* P2 */ - pSchema->schema_cookie, /* P3 */ - pSchema->iGeneration /* P4 */ - ); - if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); - VdbeComment((v, - "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); - }while( ++iDbnDb ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - for(i=0; inVtabLock; i++){ - char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); - sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); - } - pParse->nVtabLock = 0; -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE - /* Once all the cookies have been verified and transactions opened, - ** obtain the required table-locks. This is a no-op unless the - ** shared-cache feature is enabled. - */ - if( pParse->nTableLock ) codeTableLocks(pParse); -#endif - - /* Initialize any AUTOINCREMENT data structures required. - */ - if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); - - /* Code constant expressions that were factored out of inner loops. - */ - if( pParse->pConstExpr ){ - ExprList *pEL = pParse->pConstExpr; - pParse->okConstFactor = 0; - for(i=0; inExpr; i++){ - assert( pEL->a[i].u.iConstExprReg>0 ); - sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); - } - } - - if( pParse->bReturning ){ - Returning *pRet; - assert( !pParse->isCreate ); - pRet = pParse->u1.d.pReturning; - if( pRet->nRetCol ){ - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); - } - } - - /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeGoto(v, 1); - } - - /* Get the VDBE program ready for execution - */ - 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 ); - sqlite3VdbeMakeReady(v, pParse); - pParse->rc = SQLITE_DONE; - }else{ - pParse->rc = SQLITE_ERROR; - } -} - -/* -** 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. Notes: -** -** * 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 sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ - va_list ap; - char *zSql; - sqlite3 *db = pParse->db; - u32 savedDbFlags = db->mDbFlags; - char saveBuf[PARSE_TAIL_SZ]; - - if( pParse->nErr ) return; - if( pParse->eParseMode ) return; - assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ - va_start(ap, zFormat); - zSql = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - if( zSql==0 ){ - /* This can result either from an OOM or because the formatted string - ** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set - ** an error */ - if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG; - pParse->nErr++; - return; - } - pParse->nested++; - memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); - memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); - db->mDbFlags |= DBFLAG_PreferBuiltin; - sqlite3RunParser(pParse, zSql); - db->mDbFlags = savedDbFlags; - sqlite3DbFree(db, zSql); - memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); - pParse->nested--; -} - -/* -** Locate the in-memory structure that describes a particular database -** table given the name of that table and (optionally) the name of the -** database containing the table. Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the table and the -** first matching table is returned. (No checking for duplicate table -** names is done.) The search order is TEMP first, then MAIN, then any -** auxiliary databases added using the ATTACH command. -** -** See also sqlite3LocateTable(). -*/ -SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ - Table *p = 0; - int i; - - /* All mutexes are required for schema access. Make sure we hold them. */ - assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - if( zDatabase ){ - for(i=0; inDb; i++){ - if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break; - } - if( i>=db->nDb ){ - /* No match against the official names. But always match "main" - ** to schema 0 as a legacy fallback. */ - if( sqlite3StrICmp(zDatabase,"main")==0 ){ - i = 0; - }else{ - return 0; - } - } - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName); - if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( i==1 ){ - if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 - || sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 - || sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 - ){ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, - LEGACY_TEMP_SCHEMA_TABLE); - } - }else{ - if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, - LEGACY_SCHEMA_TABLE); - } - } - } - }else{ - /* Match against TEMP first */ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName); - if( p ) return p; - /* The main database is second */ - p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName); - if( p ) return p; - /* Attached databases are in order of attachment */ - for(i=2; inDb; i++){ - assert( sqlite3SchemaMutexHeld(db, i, 0) ); - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName); - if( p ) break; - } - if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE); - }else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, - LEGACY_TEMP_SCHEMA_TABLE); - } - } - } - return p; -} - -/* -** Locate the in-memory structure that describes a particular database -** table given the name of that table and (optionally) the name of the -** database containing the table. Return NULL if not found. Also leave an -** error message in pParse->zErrMsg. -** -** The difference between this routine and sqlite3FindTable() is that this -** routine leaves an error message in pParse->zErrMsg where -** sqlite3FindTable() does not. -*/ -SQLITE_PRIVATE Table *sqlite3LocateTable( - Parse *pParse, /* context in which to report errors */ - u32 flags, /* LOCATE_VIEW or LOCATE_NOERR */ - const char *zName, /* Name of the table we are looking for */ - const char *zDbase /* Name of the database. Might be NULL */ -){ - Table *p; - sqlite3 *db = pParse->db; - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 - && SQLITE_OK!=sqlite3ReadSchema(pParse) - ){ - return 0; - } - - p = sqlite3FindTable(db, zName, zDbase); - if( p==0 ){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* 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->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){ - Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); - if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(db, zName); - } - if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ - testcase( pMod->pEpoTab==0 ); - return pMod->pEpoTab; - } - } -#endif - if( flags & LOCATE_NOERR ) return 0; - pParse->checkSchema = 1; - }else if( IsVirtual(p) && (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)!=0 ){ - p = 0; - } - - if( p==0 ){ - const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; - if( zDbase ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); - } - }else{ - assert( HasRowid(p) || p->iPKey<0 ); - } - - return p; -} - -/* -** Locate the table identified by *p. -** -** This is a wrapper around sqlite3LocateTable(). The difference between -** sqlite3LocateTable() and this function is that this function restricts -** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be -** non-NULL if it is part of a view or trigger program definition. See -** sqlite3FixSrcList() for details. -*/ -SQLITE_PRIVATE Table *sqlite3LocateTableItem( - Parse *pParse, - u32 flags, - SrcItem *p -){ - const char *zDb; - if( p->fg.fixedSchema ){ - int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema); - zDb = pParse->db->aDb[iDb].zDbSName; - }else{ - assert( !p->fg.isSubquery ); - zDb = p->u4.zDatabase; - } - return sqlite3LocateTable(pParse, flags, p->zName, zDb); -} - -/* -** Return the preferred table name for system tables. Translate legacy -** names into the new preferred names, as appropriate. -*/ -SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char *zName){ - if( sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 ){ - return PREFERRED_SCHEMA_TABLE; - } - if( 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. -** Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the -** table and the first matching index is returned. (No checking -** for duplicate index names is done.) The search order is -** TEMP first, then MAIN, then any auxiliary databases added -** using the ATTACH command. -*/ -SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ - Index *p = 0; - int i; - /* All mutexes are required for schema access. Make sure we hold them. */ - assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - Schema *pSchema = db->aDb[j].pSchema; - assert( pSchema ); - if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&pSchema->idxHash, zName); - if( p ) break; - } - return p; -} - -/* -** Reclaim the memory used by an index -*/ -SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3 *db, Index *p){ -#ifndef SQLITE_OMIT_ANALYZE - sqlite3DeleteIndexSamples(db, p); -#endif - sqlite3ExprDelete(db, p->pPartIdxWhere); - sqlite3ExprListDelete(db, p->aColExpr); - sqlite3DbFree(db, p->zColAff); - if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl); -#ifdef SQLITE_ENABLE_STAT4 - sqlite3_free(p->aiRowEst); -#endif - sqlite3DbFree(db, p); -} - -/* -** For the index called zIdxName which is found in the database iDb, -** unlike that index from its Table then remove the index from -** the index hash table and free all memory structures associated -** with the index. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ - Index *pIndex; - Hash *pHash; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pHash = &db->aDb[iDb].pSchema->idxHash; - pIndex = sqlite3HashInsert(pHash, zIdxName, 0); - if( ALWAYS(pIndex) ){ - if( pIndex->pTable->pIndex==pIndex ){ - pIndex->pTable->pIndex = pIndex->pNext; - }else{ - Index *p; - /* Justification of ALWAYS(); The index must be on the list of - ** indices. */ - p = pIndex->pTable->pIndex; - while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; } - if( ALWAYS(p && p->pNext==pIndex) ){ - p->pNext = pIndex->pNext; - } - } - sqlite3FreeIndex(db, pIndex); - } - db->mDbFlags |= DBFLAG_SchemaChange; -} - -/* -** Look through the list of open database files in db->aDb[] and if -** any have been closed, remove them from the list. Reallocate the -** db->aDb[] structure to a smaller size, if possible. -** -** Entry 0 (the "main" database) and entry 1 (the "temp" database) -** are never candidates for being collapsed. -*/ -SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ - int i, j; - for(i=j=2; inDb; i++){ - struct Db *pDb = &db->aDb[i]; - if( pDb->pBt==0 ){ - sqlite3DbFree(db, pDb->zDbSName); - pDb->zDbSName = 0; - continue; - } - if( jaDb[j] = db->aDb[i]; - } - j++; - } - db->nDb = j; - if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ - memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); - sqlite3DbFree(db, db->aDb); - db->aDb = db->aDbStatic; - } -} - -/* -** Reset the schema for the database at index iDb. Also reset the -** TEMP schema. The reset is deferred if db->nSchemaLock is not zero. -** Deferred resets may be run by calling with iDb<0. -*/ -SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ - int i; - assert( iDbnDb ); - - if( iDb>=0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - DbSetProperty(db, iDb, DB_ResetWanted); - DbSetProperty(db, 1, DB_ResetWanted); - db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - } - - if( db->nSchemaLock==0 ){ - for(i=0; inDb; i++){ - if( DbHasProperty(db, i, DB_ResetWanted) ){ - sqlite3SchemaClear(db->aDb[i].pSchema); - } - } - } -} - -/* -** Erase all schema information from all attached databases (including -** "main" and "temp") for a single database connection. -*/ -SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ - int i; - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pSchema ){ - if( db->nSchemaLock==0 ){ - sqlite3SchemaClear(pDb->pSchema); - }else{ - DbSetProperty(db, i, DB_ResetWanted); - } - } - } - db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); - sqlite3VtabUnlockList(db); - sqlite3BtreeLeaveAll(db); - if( db->nSchemaLock==0 ){ - sqlite3CollapseDatabaseArray(db); - } -} - -/* -** This routine is called when a commit occurs. -*/ -SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ - db->mDbFlags &= ~DBFLAG_SchemaChange; -} - -/* -** 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 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->nExpriDflt) - ){ - pCol->iDflt = pList==0 ? 1 : pList->nExpr+1; - pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr); - }else{ - 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 *sqlite3ColumnExpr(Table *pTab, Column *pCol){ - if( pCol->iDflt==0 ) return 0; - if( !IsOrdinaryTable(pTab) ) return 0; - if( NEVER(pTab->u.tab.pDfltList==0) ) return 0; - if( NEVER(pTab->u.tab.pDfltList->nExpriDflt) ) return 0; - return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; -} - -/* -** Set the collating sequence name for a column. -*/ -SQLITE_PRIVATE void sqlite3ColumnSetColl( - sqlite3 *db, - Column *pCol, - const char *zColl -){ - i64 nColl; - i64 n; - char *zNew; - assert( zColl!=0 ); - n = sqlite3Strlen30(pCol->zCnName) + 1; - if( pCol->colFlags & COLFLAG_HASTYPE ){ - n += sqlite3Strlen30(pCol->zCnName+n) + 1; - } - nColl = sqlite3Strlen30(zColl) + 1; - zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n); - if( zNew ){ - pCol->zCnName = zNew; - memcpy(pCol->zCnName + n, zColl, nColl); - pCol->colFlags |= COLFLAG_HASCOLL; - } -} - -/* -** Return the collating sequence name for a column -*/ -SQLITE_PRIVATE const char *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). -*/ -SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ - int i; - Column *pCol; - assert( pTable!=0 ); - assert( db!=0 ); - if( (pCol = pTable->aCol)!=0 ){ - for(i=0; inCol; i++, pCol++){ - assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) ); - sqlite3DbFree(db, pCol->zCnName); - } - sqlite3DbNNFreeNN(db, pTable->aCol); - if( IsOrdinaryTable(pTable) ){ - sqlite3ExprListDelete(db, pTable->u.tab.pDfltList); - } - if( db->pnBytesFreed==0 ){ - pTable->aCol = 0; - pTable->nCol = 0; - if( IsOrdinaryTable(pTable) ){ - pTable->u.tab.pDfltList = 0; - } - } - } -} - -/* -** Remove the memory data structures associated with the given -** Table. No changes are made to disk by this routine. -** -** This routine just deletes the data structure. It does not unlink -** the table data structure from the hash table. But it does destroy -** memory structures of the indices and foreign keys associated with -** the table. -** -** The db parameter is optional. It is needed if the Table object -** contains lookaside memory. (Table objects in the schema do not use -** lookaside memory, but some ephemeral Table objects do.) Or the -** db parameter can be used with db->pnBytesFreed to measure the memory -** used by the Table object. -*/ -static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ - Index *pIndex, *pNext; - -#ifdef SQLITE_DEBUG - /* Record the number of outstanding lookaside allocations in schema Tables - ** prior to doing any free() operations. Since schema Tables do not use - ** lookaside, this number should not change. - ** - ** If malloc has already failed, it may be that it failed while allocating - ** a Table object that was going to be marked ephemeral. So do not check - ** that no lookaside memory is used in this case either. */ - int nLookaside = 0; - assert( db!=0 ); - if( !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ - nLookaside = sqlite3LookasideUsed(db, 0); - } -#endif - - /* Delete all indices associated with this table. */ - for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ - pNext = pIndex->pNext; - assert( pIndex->pSchema==pTable->pSchema - || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) ); - if( db->pnBytesFreed==0 && !IsVirtual(pTable) ){ - char *zName = pIndex->zName; - TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, 0 - ); - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); - assert( pOld==pIndex || pOld==0 ); - } - sqlite3FreeIndex(db, pIndex); - } - - if( IsOrdinaryTable(pTable) ){ - sqlite3FkDelete(db, pTable); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( IsVirtual(pTable) ){ - sqlite3VtabClear(db, pTable); - } -#endif - else{ - assert( IsView(pTable) ); - sqlite3SelectDelete(db, pTable->u.view.pSelect); - } - - /* Delete the Table structure itself. - */ - sqlite3DeleteColumnNames(db, pTable); - sqlite3DbFree(db, pTable->zName); - sqlite3DbFree(db, pTable->zColAff); - sqlite3ExprListDelete(db, pTable->pCheck); - sqlite3DbFree(db, pTable); - - /* Verify that no lookaside memory was used by schema tables */ - assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); -} -SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ - /* Do not delete the table until the reference count reaches zero. */ - assert( db!=0 ); - if( !pTable ) return; - if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return; - deleteTable(db, pTable); -} -SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){ - sqlite3DeleteTable(db, (Table*)pTable); -} - - -/* -** Unlink the given table from the hash tables and the delete the -** table structure with all its indices and foreign keys. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ - Table *p; - Db *pDb; - - assert( db!=0 ); - assert( iDb>=0 && iDbnDb ); - assert( zTabName ); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ - pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); - sqlite3DeleteTable(db, p); - db->mDbFlags |= DBFLAG_SchemaChange; -} - -/* -** Given a token, return a string that consists of the text of that -** token. Space to hold the returned string -** is obtained from sqliteMalloc() and must be freed by the calling -** function. -** -** Any quotation marks (ex: "name", 'name', [name], or `name`) that -** surround the body of the token are removed. -** -** Tokens are often just pointers into the original SQL text and so -** are not \000 terminated and are not persistent. The returned string -** is \000 terminated and is persistent. -*/ -SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, const Token *pName){ - char *zName; - if( pName ){ - zName = sqlite3DbStrNDup(db, (const char*)pName->z, pName->n); - sqlite3Dequote(zName); - }else{ - zName = 0; - } - return zName; -} - -/* -** Open the sqlite_schema table stored in database number iDb for -** writing. The table is opened using cursor 0. -*/ -SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *p, int iDb){ - Vdbe *v = sqlite3GetVdbe(p); - sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE); - sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5); - if( p->nTab==0 ){ - p->nTab = 1; - } -} - -/* -** Parameter zName points to a nul-terminated buffer containing the name -** of a database ("main", "temp" or the name of an attached db). This -** function returns the index of the named database in db->aDb[], or -** -1 if the named db cannot be found. -*/ -SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){ - int i = -1; /* Database number */ - if( zName ){ - Db *pDb; - for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break; - /* "main" is always an acceptable alias for the primary database - ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */ - if( i==0 && 0==sqlite3_stricmp("main", zName) ) break; - } - } - return i; -} - -/* -** The token *pName contains the name of a database (either "main" or -** "temp" or the name of an attached db). This routine returns the -** index of the named database in db->aDb[], or -1 if the named db -** does not exist. -*/ -SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){ - int i; /* Database number */ - char *zName; /* Name we are searching for */ - zName = sqlite3NameFromToken(db, pName); - i = sqlite3FindDbName(db, zName); - sqlite3DbFree(db, zName); - return i; -} - -/* The table or view or trigger name is passed to this routine via tokens -** pName1 and pName2. If the table name was fully qualified, for example: -** -** CREATE TABLE xxx.yyy (...); -** -** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if -** the table name is not fully qualified, i.e.: -** -** CREATE TABLE yyy(...); -** -** Then pName1 is set to "yyy" and pName2 is "". -** -** This routine sets the *ppUnqual pointer to point at the token (pName1 or -** pName2) that stores the unqualified table name. The index of the -** database "xxx" is returned. -*/ -SQLITE_PRIVATE int sqlite3TwoPartName( - Parse *pParse, /* Parsing and code generating context */ - Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ - Token *pName2, /* The "yyy" in the name "xxx.yyy" */ - Token **pUnqual /* Write the unqualified object name here */ -){ - int iDb; /* Database holding the object */ - sqlite3 *db = pParse->db; - - assert( pName2!=0 ); - if( pName2->n>0 ){ - if( db->init.busy ) { - sqlite3ErrorMsg(pParse, "corrupt database"); - return -1; - } - *pUnqual = pName2; - iDb = sqlite3FindDb(db, pName1); - if( iDb<0 ){ - sqlite3ErrorMsg(pParse, "unknown database %T", pName1); - return -1; - } - }else{ - assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE - || (db->mDbFlags & DBFLAG_Vacuum)!=0); - iDb = db->init.iDb; - *pUnqual = pName1; - } - return iDb; -} - -/* -** True if PRAGMA writable_schema is ON -*/ -SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){ - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - SQLITE_WriteSchema ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - SQLITE_Defensive ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - (SQLITE_WriteSchema|SQLITE_Defensive) ); - return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; -} - -/* -** This routine is used to check if the UTF-8 string zName is a legal -** unqualified name for a new schema object (table, index, view or -** trigger). All names are legal except those that begin with the string -** "sqlite_" (in upper, lower or mixed case). This portion of the namespace -** is reserved for internal use. -** -** When parsing the sqlite_schema table, this routine also checks to -** make sure the "type", "name", and "tbl_name" columns are consistent -** with the SQL. -*/ -SQLITE_PRIVATE int sqlite3CheckObjectName( - Parse *pParse, /* Parsing context */ - const char *zName, /* Name of the object to check */ - const char *zType, /* Type of this object */ - const char *zTblName /* Parent table name for triggers and indexes */ -){ - sqlite3 *db = pParse->db; - if( sqlite3WritableSchema(db) - || db->init.imposterTable - || !sqlite3Config.bExtraSchemaChecks - ){ - /* Skip these error checks for writable_schema=ON */ - return SQLITE_OK; - } - if( db->init.busy ){ - if( sqlite3_stricmp(zType, db->init.azInit[0]) - || sqlite3_stricmp(zName, db->init.azInit[1]) - || sqlite3_stricmp(zTblName, db->init.azInit[2]) - ){ - sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */ - return SQLITE_ERROR; - } - }else{ - if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7)) - || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName)) - ){ - sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", - zName); - return SQLITE_ERROR; - } - - } - return SQLITE_OK; -} - -/* -** Return the PRIMARY KEY index of a table -*/ -SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){ - Index *p; - for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){} - return p; -} - -/* -** Convert an table column number into a index column number. That is, -** for the column iCol in the table (as defined by the CREATE TABLE statement) -** find the (first) offset of that column in index pIdx. Or return -1 -** if column iCol is not used in index pIdx. -*/ -SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){ - int i; - i16 iCol16; - assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN ); - assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 ); - iCol16 = iCol; - for(i=0; inColumn; i++){ - if( iCol16==pIdx->aiColumn[i] ){ - return i; - } - } - return -1; -} - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* Convert a storage column number into a table column number. -** -** The storage column number (0,1,2,....) is the index of the value -** as it appears in the record on disk. The true column number -** is the index (0,1,2,...) of the column in the CREATE TABLE statement. -** -** The storage column number is less than the table column number if -** and only there are VIRTUAL columns to the left. -** -** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro. -*/ -SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){ - if( pTab->tabFlags & TF_HasVirtual ){ - int i; - for(i=0; i<=iCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++; - } - } - return iCol; -} -#endif - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* Convert a table column number into a storage column number. -** -** The storage column number (0,1,2,....) is the index of the value -** as it appears in the record on disk. Or, if the input column is -** the N-th virtual column (zero-based) then the storage number is -** the number of non-virtual columns in the table plus N. -** -** The true column number is the index (0,1,2,...) of the column in -** the CREATE TABLE statement. -** -** If the input column is a VIRTUAL column, then it should not appear -** in storage. But the value sometimes is cached in registers that -** follow the range of registers used to construct storage. This -** avoids computing the same VIRTUAL column multiple times, and provides -** values for use by OP_Param opcodes in triggers. Hence, if the -** input column is a VIRTUAL table, put it after all the other columns. -** -** In the following, N means "normal column", S means STORED, and -** V means VIRTUAL. Suppose the CREATE TABLE has columns like this: -** -** CREATE TABLE ex(N,S,V,N,S,V,N,S,V); -** -- 0 1 2 3 4 5 6 7 8 -** -** Then the mapping from this function is as follows: -** -** INPUTS: 0 1 2 3 4 5 6 7 8 -** OUTPUTS: 0 1 6 2 3 7 4 5 8 -** -** So, in other words, this routine shifts all the virtual columns to -** the end. -** -** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and -** this routine is a no-op macro. If the pTab does not have any virtual -** columns, then this routine is no-op that always return iCol. If iCol -** is negative (indicating the ROWID column) then this routine return iCol. -*/ -SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){ - int i; - i16 n; - assert( iColnCol ); - if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol; - for(i=0, n=0; iaCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++; - } - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){ - /* iCol is a virtual column itself */ - return pTab->nNVCol + i - n; - }else{ - /* iCol is a normal or stored column */ - return n; - } -} -#endif - -/* -** Insert a single OP_JournalMode query opcode in order to force the -** prepared statement to return false for 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 sqlite3_stmt_readonly() even if that statement -** is a read-only no-op. -*/ -static void sqlite3ForceNotReadOnly(Parse *pParse){ - int iReg = ++pParse->nMem; - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY); - 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 -** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp -** flag is true if the table should be stored in the auxiliary database -** file instead of in the main database file. This is normally the case -** when the "TEMP" or "TEMPORARY" keyword occurs in between -** CREATE and TABLE. -** -** The new table record is initialized and put in pParse->pNewTable. -** As more of the CREATE TABLE statement is parsed, additional action -** routines will be called to add more information to this record. -** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine -** is called to complete the construction of the new table record. -*/ -SQLITE_PRIVATE void sqlite3StartTable( - Parse *pParse, /* Parser context */ - Token *pName1, /* First part of the name of the table or view */ - Token *pName2, /* Second part of the name of the table or view */ - int isTemp, /* True if this is a TEMP table */ - int isView, /* True if this is a VIEW */ - int isVirtual, /* True if this is a VIRTUAL table */ - int noErr /* Do nothing if table already exists */ -){ - Table *pTable; - char *zName = 0; /* The name of the new table */ - sqlite3 *db = pParse->db; - Vdbe *v; - int iDb; /* Database number to create the table in */ - Token *pName; /* Unqualified name of the table to create */ - - if( db->init.busy && db->init.newTnum==1 ){ - /* Special case: Parsing the sqlite_schema or sqlite_temp_schema schema */ - iDb = db->init.iDb; - zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb)); - pName = pName1; - }else{ - /* The common case */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ) return; - if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){ - /* If creating a temp table, the name may not be qualified. Unless - ** the database name is "temp" anyway. */ - sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); - return; - } - if( !OMIT_TEMPDB && isTemp ) iDb = 1; - zName = sqlite3NameFromToken(db, pName); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)zName, pName); - } - } - pParse->sNameToken = *pName; - if( zName==0 ) return; - if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){ - goto begin_table_error; - } - if( db->init.iDb==1 ) isTemp = 1; -#ifndef SQLITE_OMIT_AUTHORIZATION - assert( isTemp==0 || isTemp==1 ); - assert( isView==0 || isView==1 ); - { - static const u8 aCode[] = { - SQLITE_CREATE_TABLE, - SQLITE_CREATE_TEMP_TABLE, - SQLITE_CREATE_VIEW, - SQLITE_CREATE_TEMP_VIEW - }; - char *zDb = db->aDb[iDb].zDbSName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ - goto begin_table_error; - } - if( !isVirtual && sqlite3AuthCheck(pParse, (int)aCode[isTemp+2*isView], - zName, 0, zDb) ){ - goto begin_table_error; - } - } -#endif - - /* Make sure the new table name does not collide with an existing - ** index or table name in the same database. Issue an error message if - ** it does. The exception is if the statement being parsed was passed - ** to an sqlite3_declare_vtab() call. In that case only the column names - ** and types will be used, so there is no need to test for namespace - ** collisions. - */ - if( !IN_SPECIAL_PARSE ){ - char *zDb = db->aDb[iDb].zDbSName; - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto begin_table_error; - } - pTable = sqlite3FindTable(db, zName, zDb); - if( pTable ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "%s %T already exists", - (IsView(pTable)? "view" : "table"), pName); - }else{ - assert( !db->init.busy || CORRUPT_DB ); - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3ForceNotReadOnly(pParse); - } - goto begin_table_error; - } - if( sqlite3FindIndex(db, zName, zDb)!=0 ){ - sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); - goto begin_table_error; - } - } - - pTable = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTable==0 ){ - assert( db->mallocFailed ); - pParse->rc = SQLITE_NOMEM_BKPT; - pParse->nErr++; - goto begin_table_error; - } - pTable->zName = zName; - pTable->iPKey = -1; - pTable->pSchema = db->aDb[iDb].pSchema; - pTable->nTabRef = 1; -#ifdef SQLITE_DEFAULT_ROWEST - pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST); -#else - pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); -#endif - assert( pParse->pNewTable==0 ); - pParse->pNewTable = pTable; - - /* 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 - ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause - ** indices to be created and the table record must come before the - ** indices. Hence, the record number for the table must be allocated - ** now. - */ - if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ - int addr1; - int fileFormat; - int reg1, reg2, reg3; - /* nullRow[] is an OP_Record encoding of a row containing 5 NULLs */ - static const char nullRow[] = { 6, 0, 0, 0, 0, 0 }; - sqlite3BeginWriteOperation(pParse, 1, iDb); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( isVirtual ){ - sqlite3VdbeAddOp0(v, OP_VBegin); - } -#endif - - /* If the file format and encoding in the database have not been set, - ** set them now. - */ - assert( pParse->isCreate ); - reg1 = pParse->u1.cr.regRowid = ++pParse->nMem; - reg2 = pParse->u1.cr.regRoot = ++pParse->nMem; - reg3 = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); - fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? - 1 : SQLITE_MAX_FILE_FORMAT; - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); - sqlite3VdbeJumpHere(v, addr1); - - /* This just creates a place-holder record in the sqlite_schema table. - ** The record created does not contain anything yet. It will be replaced - ** by the real entry in code generated at sqlite3EndTable(). - ** - ** The rowid for the new entry is left in register pParse->u1.cr.regRowid. - ** The root page of the new table is left in reg pParse->u1.cr.regRoot. - ** The rowid and root page number values are needed by the code that - ** sqlite3EndTable will generate. - */ -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) - if( isView || isVirtual ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); - }else -#endif - { - assert( !pParse->bReturning ); - pParse->u1.cr.addrCrTab = - sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); - } - sqlite3OpenSchemaTable(pParse, iDb); - sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); - sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); - sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp0(v, OP_Close); - } - - /* Normal (non-error) return. */ - return; - - /* If an error occurs, we jump here */ -begin_table_error: - pParse->checkSchema = 1; - sqlite3DbFree(db, zName); - return; -} - -/* Set properties of a table column based on the (magical) -** name of the column. -*/ -#if SQLITE_ENABLE_HIDDEN_COLUMNS -SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ - if( 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 - -/* -** Clean up the data structures associated with the RETURNING clause. -*/ -static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){ - Returning *pRet = (Returning*)pArg; - Hash *pHash; - pHash = &(db->aDb[1].pSchema->trigHash); - sqlite3HashInsert(pHash, pRet->zName, 0); - sqlite3ExprListDelete(db, pRet->pReturnEL); - 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 sqlite3TriggersExist(). -*/ -SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ - Returning *pRet; - Hash *pHash; - sqlite3 *db = pParse->db; - if( pParse->pNewTrigger ){ - sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); - }else{ - assert( pParse->bReturning==0 || pParse->ifNotExists ); - } - pParse->bReturning = 1; - pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); - if( pRet==0 ){ - sqlite3ExprListDelete(db, pList); - return; - } - assert( !pParse->isCreate ); - pParse->u1.d.pReturning = pRet; - pRet->pParse = pParse; - pRet->pReturnEL = pList; - sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet); - testcase( pParse->earlyCleanup ); - if( db->mallocFailed ) return; - sqlite3_snprintf(sizeof(pRet->zName), pRet->zName, - "sqlite_returning_%p", pParse); - pRet->retTrig.zName = pRet->zName; - 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( sqlite3HashFind(pHash, pRet->zName)==0 - || pParse->nErr || pParse->ifNotExists ); - if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) - ==&pRet->retTrig ){ - sqlite3OomFault(db); - } -} - -/* -** Add a new column to the table currently being constructed. -** -** The parser calls this routine once for each column declaration -** in a CREATE TABLE statement. sqlite3StartTable() gets called -** first to get things going. Then this routine is called for each -** column. -*/ -SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ - Table *p; - int i; - char *z; - char *zType; - Column *pCol; - sqlite3 *db = pParse->db; - 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] ){ - sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); - return; - } - if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); - - /* Because keywords GENERATE ALWAYS can be converted into identifiers - ** 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 - && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0 - ){ - sType.n -= 6; - while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--; - if( sType.n>=9 - && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0 - ){ - sType.n -= 9; - while( sType.n>0 && 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 ){ - sqlite3DequoteToken(&sType); - for(i=0; i0) ); - if( z==0 ) return; - if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName); - memcpy(z, sName.z, sName.n); - z[sName.n] = 0; - sqlite3Dequote(z); - if( p->nCol && sqlite3ColumnIndex(p, z)>=0 ){ - sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); - sqlite3DbFree(db, z); - return; - } - aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0])); - if( aNew==0 ){ - sqlite3DbFree(db, z); - return; - } - p->aCol = aNew; - pCol = &p->aCol[p->nCol]; - memset(pCol, 0, sizeof(p->aCol[0])); - pCol->zCnName = z; - pCol->hName = sqlite3StrIHash(z); - sqlite3ColumnPropertiesFromName(p, pCol); - - 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 = affinity; - pCol->eCType = eType; - pCol->szEst = szEst; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( affinity==SQLITE_AFF_BLOB ){ - if( 4>=sqlite3GlobalConfig.szSorterRef ){ - pCol->colFlags |= COLFLAG_SORTERREF; - } - } -#endif - }else{ - zType = z + sqlite3Strlen30(z) + 1; - memcpy(zType, sType.z, sType.n); - zType[sType.n] = 0; - sqlite3Dequote(zType); - pCol->affinity = sqlite3AffinityType(zType, pCol); - pCol->colFlags |= COLFLAG_HASTYPE; - } - if( p->nCol<=0xff ){ - u8 h = pCol->hName % sizeof(p->aHx); - p->aHx[h] = p->nCol; - } - p->nCol++; - p->nNVCol++; - assert( pParse->isCreate ); - pParse->u1.cr.constraintName.n = 0; -} - -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. A "NOT NULL" constraint has -** been seen on a column. This routine sets the notNull flag on -** the column currently under construction. -*/ -SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ - Table *p; - Column *pCol; - p = pParse->pNewTable; - if( p==0 || NEVER(p->nCol<1) ) return; - pCol = &p->aCol[p->nCol-1]; - pCol->notNull = (u8)onError; - p->tabFlags |= TF_HasNotNull; - - /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created - ** on this column. */ - if( pCol->colFlags & COLFLAG_UNIQUE ){ - Index *pIdx; - for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None ); - if( pIdx->aiColumn[0]==p->nCol-1 ){ - pIdx->uniqNotNull = 1; - } - } - } -} - -/* -** Scan the column type name zType (length nType) and return the -** associated affinity type. -** -** This routine does a case-independent search of zType for the -** substrings in the following table. If one of the substrings is -** found, the corresponding affinity is returned. If zType contains -** more than one of the substrings, entries toward the top of -** the table take priority. For example, if zType is 'BLOBINT', -** SQLITE_AFF_INTEGER is returned. -** -** Substring | Affinity -** -------------------------------- -** 'INT' | SQLITE_AFF_INTEGER -** 'CHAR' | SQLITE_AFF_TEXT -** 'CLOB' | SQLITE_AFF_TEXT -** 'TEXT' | SQLITE_AFF_TEXT -** 'BLOB' | SQLITE_AFF_BLOB -** 'REAL' | SQLITE_AFF_REAL -** 'FLOA' | SQLITE_AFF_REAL -** 'DOUB' | SQLITE_AFF_REAL -** -** If none of the substrings in the above table are found, -** SQLITE_AFF_NUMERIC is returned. -*/ -SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ - u32 h = 0; - char aff = SQLITE_AFF_NUMERIC; - const char *zChar = 0; - - assert( zIn!=0 ); - while( zIn[0] ){ - u8 x = *(u8*)zIn; - h = (h<<8) + sqlite3UpperToLower[x]; - zIn++; - if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ - aff = SQLITE_AFF_TEXT; - zChar = zIn; - }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ - aff = SQLITE_AFF_TEXT; - }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ - aff = SQLITE_AFF_TEXT; - }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ - && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ - aff = SQLITE_AFF_BLOB; - if( zIn[0]=='(' ) zChar = zIn; -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; - }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; - }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; -#endif - }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ - aff = SQLITE_AFF_INTEGER; - break; - } - } - - /* If pCol is not NULL, store an estimate of the field size. The - ** estimate is scaled so that the size of an integer is 1. */ - if( pCol ){ - int v = 0; /* default size is approx 4 bytes */ - if( aff r=(k/4+1) */ - sqlite3GetInt32(zChar, &v); - break; - } - zChar++; - } - }else{ - v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ - } - } -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( v>=sqlite3GlobalConfig.szSorterRef ){ - pCol->colFlags |= COLFLAG_SORTERREF; - } -#endif - v = v/4 + 1; - if( v>255 ) v = 255; - pCol->szEst = v; - } - return aff; -} - -/* -** The expression is the default value for the most recently added column -** of the table currently under construction. -** -** Default value expressions must be constant. Raise an exception if this -** is not the case. -** -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3AddDefaultValue( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The parsed expression of the default value */ - const char *zStart, /* Start of the default value text */ - const char *zEnd /* First character past end of default value text */ -){ - Table *p; - Column *pCol; - sqlite3 *db = pParse->db; - p = pParse->pNewTable; - if( p!=0 ){ - int isInit = db->init.busy && db->init.iDb!=1; - pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){ - sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", - pCol->zCnName); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - }else if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column"); -#endif - }else{ - /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. - */ - Expr x, *pDfltExpr; - memset(&x, 0, sizeof(x)); - x.op = TK_SPAN; - x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); - x.pLeft = pExpr; - x.flags = EP_Skip; - pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); - sqlite3DbFree(db, x.u.zToken); - sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr); - } - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprUnmap(pParse, pExpr); - } - sqlite3ExprDelete(db, pExpr); -} - -/* -** Backwards Compatibility Hack: -** -** Historical versions of SQLite accepted strings as column names in -** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example: -** -** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim) -** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC); -** -** This is goofy. But to preserve backwards compatibility we continue to -** accept it. This routine does the necessary conversion. It converts -** the expression given in its argument from a TK_STRING into a TK_ID -** if the expression is just a TK_STRING with an optional COLLATE clause. -** If the expression is anything other than TK_STRING, the expression is -** unchanged. -*/ -static void sqlite3StringToId(Expr *p){ - if( p->op==TK_STRING ){ - p->op = TK_ID; - }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){ - p->pLeft->op = TK_ID; - } -} - -/* -** Tag the given column as being part of the PRIMARY KEY -*/ -static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){ - pCol->colFlags |= COLFLAG_PRIMKEY; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, - "generated columns cannot be part of the PRIMARY KEY"); - } -#endif -} - -/* -** Designate the PRIMARY KEY for the table. pList is a list of names -** of columns that form the primary key. If pList is NULL, then the -** most recently added column of the table is the primary key. -** -** A table can have at most one primary key. If the table already has -** a primary key (and this is the second primary key) then create an -** error. -** -** If the PRIMARY KEY is on a single column whose datatype is INTEGER, -** then we will try to use that column as the rowid. Set the Table.iPKey -** field of the table under construction to be the index of the -** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is -** no INTEGER PRIMARY KEY. -** -** If the key is not an INTEGER PRIMARY KEY, then create a unique -** index for the key. No index is created for INTEGER PRIMARY KEYs. -*/ -SQLITE_PRIVATE void sqlite3AddPrimaryKey( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List of field names to be indexed */ - int onError, /* What to do with a uniqueness conflict */ - int autoInc, /* True if the AUTOINCREMENT keyword is present */ - int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ -){ - Table *pTab = pParse->pNewTable; - Column *pCol = 0; - int iCol = -1, i; - int nTerm; - if( pTab==0 ) goto primary_key_exit; - if( pTab->tabFlags & TF_HasPrimaryKey ){ - sqlite3ErrorMsg(pParse, - "table \"%s\" has more than one primary key", pTab->zName); - goto primary_key_exit; - } - pTab->tabFlags |= TF_HasPrimaryKey; - if( pList==0 ){ - iCol = pTab->nCol - 1; - pCol = &pTab->aCol[iCol]; - makeColumnPartOfPrimaryKey(pParse, pCol); - nTerm = 1; - }else{ - nTerm = pList->nExpr; - for(i=0; ia[i].pExpr); - assert( pCExpr!=0 ); - sqlite3StringToId(pCExpr); - if( pCExpr->op==TK_ID ){ - assert( !ExprHasProperty(pCExpr, EP_IntValue) ); - iCol = sqlite3ColumnIndex(pTab, pCExpr->u.zToken); - if( iCol>=0 ){ - pCol = &pTab->aCol[iCol]; - makeColumnPartOfPrimaryKey(pParse, pCol); - } - } - } - } - if( nTerm==1 - && pCol - && pCol->eCType==COLTYPE_INTEGER - && sortOrder!=SQLITE_SO_DESC - ){ - if( IN_RENAME_OBJECT && pList ){ - Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr); - sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr); - } - pTab->iPKey = iCol; - pTab->keyConf = (u8)onError; - assert( autoInc==0 || autoInc==1 ); - pTab->tabFlags |= autoInc*TF_Autoincrement; - if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags; - (void)sqlite3HasExplicitNulls(pParse, pList); - }else if( autoInc ){ -#ifndef SQLITE_OMIT_AUTOINCREMENT - sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " - "INTEGER PRIMARY KEY"); -#endif - }else{ - sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, - 0, sortOrder, 0, SQLITE_IDXTYPE_PRIMARYKEY); - pList = 0; - } - -primary_key_exit: - sqlite3ExprListDelete(pParse->db, pList); - return; -} - -/* -** Add a new CHECK constraint to the table currently under construction. -*/ -SQLITE_PRIVATE void sqlite3AddCheckConstraint( - Parse *pParse, /* Parsing context */ - Expr *pCheckExpr, /* The check expression */ - const char *zStart, /* Opening "(" */ - const char *zEnd /* Closing ")" */ -){ -#ifndef SQLITE_OMIT_CHECK - Table *pTab = pParse->pNewTable; - sqlite3 *db = pParse->db; - if( pTab && !IN_DECLARE_VTAB - && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt) - ){ - pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); - assert( pParse->isCreate ); - if( pParse->u1.cr.constraintName.n ){ - sqlite3ExprListSetName(pParse, pTab->pCheck, - &pParse->u1.cr.constraintName, 1); - }else{ - Token t; - for(zStart++; sqlite3Isspace(zStart[0]); zStart++){} - while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; } - t.z = zStart; - t.n = (int)(zEnd - t.z); - sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1); - } - }else -#endif - { - sqlite3ExprDelete(pParse->db, pCheckExpr); - } -} - -/* -** Set the collation function of the most recently parsed table column -** to the CollSeq given. -*/ -SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){ - Table *p; - int i; - char *zColl; /* Dequoted name of collation sequence */ - sqlite3 *db; - - if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return; - i = p->nCol-1; - db = pParse->db; - zColl = sqlite3NameFromToken(db, pToken); - if( !zColl ) return; - - if( sqlite3LocateCollSeq(pParse, zColl) ){ - Index *pIdx; - sqlite3ColumnSetColl(db, &p->aCol[i], zColl); - - /* If the column is declared as " PRIMARY KEY COLLATE ", - ** then an index may have been created on this column before the - ** collation type was added. Correct this if it is the case. - */ - for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nKeyCol==1 ); - if( pIdx->aiColumn[0]==i ){ - pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]); - } - } - } - sqlite3DbFree(db, zColl); -} - -/* Change the most recently parsed column to be a GENERATED ALWAYS AS -** column. -*/ -SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){ -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - u8 eType = COLFLAG_VIRTUAL; - Table *pTab = pParse->pNewTable; - Column *pCol; - if( pTab==0 ){ - /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */ - goto generated_done; - } - pCol = &(pTab->aCol[pTab->nCol-1]); - if( IN_DECLARE_VTAB ){ - sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns"); - goto generated_done; - } - if( pCol->iDflt>0 ) goto generated_error; - if( pType ){ - if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){ - /* no-op */ - }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){ - eType = COLFLAG_STORED; - }else{ - goto generated_error; - } - } - if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--; - pCol->colFlags |= eType; - assert( TF_HasVirtual==COLFLAG_VIRTUAL ); - assert( TF_HasStored==COLFLAG_STORED ); - pTab->tabFlags |= eType; - if( pCol->colFlags & COLFLAG_PRIMKEY ){ - makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */ - } - if( ALWAYS(pExpr) && pExpr->op==TK_ID ){ - /* The value of a generated column needs to be a real expression, not - ** just a reference to another column, in order for covering index - ** optimizations to work correctly. So if the value is not an expression, - ** turn it into one by adding a unary "+" operator. */ - pExpr = sqlite3PExpr(pParse, TK_UPLUS, pExpr, 0); - } - if( pExpr && pExpr->op!=TK_RAISE ) pExpr->affExpr = pCol->affinity; - sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr); - pExpr = 0; - goto generated_done; - -generated_error: - sqlite3ErrorMsg(pParse, "error in generated column \"%s\"", - pCol->zCnName); -generated_done: - sqlite3ExprDelete(pParse->db, pExpr); -#else - /* Throw and error for the GENERATED ALWAYS AS clause if the - ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */ - sqlite3ErrorMsg(pParse, "generated columns not supported"); - sqlite3ExprDelete(pParse->db, pExpr); -#endif -} - -/* -** Generate code that will increment the schema cookie. -** -** The schema cookie is used to determine when the schema for the -** database changes. After each schema change, the cookie value -** changes. When a process first reads the schema it records the -** cookie. Thereafter, whenever it goes to access the database, -** it checks the cookie to make sure the schema has not changed -** since it was last read. -** -** This plan is not completely bullet-proof. It is possible for -** the schema to change multiple times and for the cookie to be -** set back to prior value. But schema changes are infrequent -** and the probability of hitting the same cookie value is only -** 1 chance in 2^32. So we're safe enough. -** -** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments -** the schema-version whenever the schema changes. -*/ -SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ - sqlite3 *db = pParse->db; - Vdbe *v = pParse->pVdbe; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, - (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); -} - -/* -** Measure the number of characters needed to output the given -** identifier. The number returned includes any quotes used -** but does not include the null terminator. -** -** The estimate is conservative. It might be larger that what is -** really needed. -*/ -static int identLength(const char *z){ - int n; - for(n=0; *z; n++, z++){ - if( *z=='"' ){ n++; } - } - return n + 2; -} - -/* -** The first parameter is a pointer to an output buffer. The second -** parameter is a pointer to an integer that contains the offset at -** which to write into the output buffer. This function copies the -** nul-terminated string pointed to by the third parameter, zSignedIdent, -** to the specified offset in the buffer and updates *pIdx to refer -** to the first byte after the last byte written before returning. -** -** If the string zSignedIdent consists entirely of alphanumeric -** characters, does not begin with a digit and is not an SQL keyword, -** then it is copied to the output buffer exactly as it is. Otherwise, -** it is quoted using double-quotes. -*/ -static void identPut(char *z, int *pIdx, char *zSignedIdent){ - unsigned char *zIdent = (unsigned char*)zSignedIdent; - int i, j, needQuote; - i = *pIdx; - - for(j=0; zIdent[j]; j++){ - if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break; - } - needQuote = sqlite3Isdigit(zIdent[0]) - || sqlite3KeywordCode(zIdent, j)!=TK_ID - || zIdent[j]!=0 - || j==0; - - if( needQuote ) z[i++] = '"'; - for(j=0; zIdent[j]; j++){ - z[i++] = zIdent[j]; - if( zIdent[j]=='"' ) z[i++] = '"'; - } - if( needQuote ) z[i++] = '"'; - z[i] = 0; - *pIdx = i; -} - -/* -** Generate a CREATE TABLE statement appropriate for the given -** table. Memory to hold the text of the statement is obtained -** from sqliteMalloc() and must be freed by the calling function. -*/ -static char *createTableStmt(sqlite3 *db, Table *p){ - int i, k, len; - i64 n; - char *zStmt; - char *zSep, *zSep2, *zEnd; - Column *pCol; - n = 0; - for(pCol = p->aCol, i=0; inCol; i++, pCol++){ - n += identLength(pCol->zCnName) + 5; - } - n += identLength(p->zName); - if( n<50 ){ - zSep = ""; - zSep2 = ","; - zEnd = ")"; - }else{ - zSep = "\n "; - zSep2 = ",\n "; - zEnd = "\n)"; - } - n += 35 + 6*p->nCol; - zStmt = sqlite3DbMallocRaw(0, n); - if( zStmt==0 ){ - sqlite3OomFault(db); - return 0; - } - assert( n>14 && n<=0x7fffffff ); - memcpy(zStmt, "CREATE TABLE ", 13); - k = 13; - identPut(zStmt, &k, p->zName); - zStmt[k++] = '('; - for(pCol=p->aCol, i=0; inCol; i++, pCol++){ - static const char * const azType[] = { - /* SQLITE_AFF_BLOB */ "", - /* SQLITE_AFF_TEXT */ " TEXT", - /* SQLITE_AFF_NUMERIC */ " NUM", - /* SQLITE_AFF_INTEGER */ " INT", - /* SQLITE_AFF_REAL */ " REAL", - /* SQLITE_AFF_FLEXNUM */ " NUM", - }; - const char *zType; - - len = sqlite3Strlen30(zSep); - assert( k+lenzCnName); - assert( kaffinity-SQLITE_AFF_BLOB >= 0 ); - assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) ); - testcase( pCol->affinity==SQLITE_AFF_BLOB ); - testcase( pCol->affinity==SQLITE_AFF_TEXT ); - testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); - testcase( pCol->affinity==SQLITE_AFF_INTEGER ); - testcase( pCol->affinity==SQLITE_AFF_REAL ); - testcase( pCol->affinity==SQLITE_AFF_FLEXNUM ); - - zType = azType[pCol->affinity - SQLITE_AFF_BLOB]; - len = sqlite3Strlen30(zType); - assert( pCol->affinity==SQLITE_AFF_BLOB - || pCol->affinity==SQLITE_AFF_FLEXNUM - || pCol->affinity==sqlite3AffinityType(zType, 0) ); - assert( k+lennColumn>=N ) return SQLITE_OK; - db = pParse->db; - assert( N>0 ); - assert( N <= SQLITE_MAX_COLUMN*2 /* tag-20250221-1 */ ); - testcase( N==2*pParse->db->aLimit[SQLITE_LIMIT_COLUMN] ); - assert( pIdx->isResized==0 ); - nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*(u64)N; - zExtra = sqlite3DbMallocZero(db, nByte); - if( zExtra==0 ) return SQLITE_NOMEM_BKPT; - memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn); - pIdx->azColl = (const char**)zExtra; - zExtra += sizeof(char*)*N; - memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1)); - pIdx->aiRowLogEst = (LogEst*)zExtra; - zExtra += sizeof(LogEst)*N; - memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn); - pIdx->aiColumn = (i16*)zExtra; - zExtra += sizeof(i16)*N; - memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn); - pIdx->aSortOrder = (u8*)zExtra; - pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */ - pIdx->isResized = 1; - return SQLITE_OK; -} - -/* -** Estimate the total row width for a table. -*/ -static void estimateTableWidth(Table *pTab){ - unsigned wTable = 0; - const Column *pTabCol; - int i; - for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){ - wTable += pTabCol->szEst; - } - if( pTab->iPKey<0 ) wTable++; - pTab->szTabRow = sqlite3LogEst(wTable*4); -} - -/* -** Estimate the average size of a row for an index. -*/ -static void estimateIndexWidth(Index *pIdx){ - unsigned wIndex = 0; - int i; - const Column *aCol = pIdx->pTable->aCol; - for(i=0; inColumn; i++){ - i16 x = pIdx->aiColumn[i]; - assert( xpTable->nCol ); - wIndex += x<0 ? 1 : aCol[x].szEst; - } - pIdx->szIdxRow = sqlite3LogEst(wIndex*4); -} - -/* Return true if column number x is any of the first nCol entries of aiCol[]. -** This is used to determine if the column number x appears in any of the -** first nCol entries of an index. -*/ -static int hasColumn(const i16 *aiCol, int nCol, int x){ - while( nCol-- > 0 ){ - if( x==*(aiCol++) ){ - return 1; - } - } - return 0; -} - -/* -** Return true if any of the first nKey entries of index pIdx exactly -** match the iCol-th entry of pPk. pPk is always a WITHOUT ROWID -** PRIMARY KEY index. pIdx is an index on the same table. pIdx may -** or may not be the same index as pPk. -** -** The first nKey entries of pIdx are guaranteed to be ordinary columns, -** not a rowid or expression. -** -** This routine differs from hasColumn() in that both the column and the -** collating sequence must match for this routine, but for hasColumn() only -** the column name must match. -*/ -static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){ - int i, j; - assert( nKey<=pIdx->nColumn ); - assert( iColnColumn,pPk->nKeyCol) ); - assert( pPk->idxType==SQLITE_IDXTYPE_PRIMARYKEY ); - assert( pPk->pTable->tabFlags & TF_WithoutRowid ); - assert( pPk->pTable==pIdx->pTable ); - testcase( pPk==pIdx ); - j = pPk->aiColumn[iCol]; - assert( j!=XN_ROWID && j!=XN_EXPR ); - for(i=0; iaiColumn[i]>=0 || j>=0 ); - if( pIdx->aiColumn[i]==j - && sqlite3StrICmp(pIdx->azColl[i], pPk->azColl[iCol])==0 - ){ - return 1; - } - } - return 0; -} - -/* Recompute the colNotIdxed field of the Index. -** -** colNotIdxed is a bitmask that has a 0 bit representing each indexed -** columns that are within the first 63 columns of the table and a 1 for -** all other bits (all columns that are not in the index). The -** high-order bit of colNotIdxed is always 1. All unindexed columns -** of the table have a 1. -** -** 2019-10-24: For the purpose of this computation, virtual columns are -** not considered to be covered by the index, even if they are in the -** index, because we do not trust the logic in whereIndexExprTrans() to be -** able to find all instances of a reference to the indexed table column -** and convert them into references to the index. Hence we always want -** the actual table at hand in order to recompute the virtual column, if -** necessary. -** -** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask -** to determine if the index is covering index. -*/ -static void recomputeColumnsNotIndexed(Index *pIdx){ - Bitmask m = 0; - int j; - Table *pTab = pIdx->pTable; - for(j=pIdx->nColumn-1; j>=0; j--){ - int x = pIdx->aiColumn[j]; - if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){ - testcase( x==BMS-1 ); - testcase( x==BMS-2 ); - if( xcolNotIdxed = ~m; - assert( (pIdx->colNotIdxed>>63)==1 ); /* See note-20221022-a */ -} - -/* -** This routine runs at the end of parsing a CREATE TABLE statement that -** has a WITHOUT ROWID clause. The job of this routine is to convert both -** internal schema data structures and the generated VDBE code so that they -** are appropriate for a WITHOUT ROWID table instead of a rowid table. -** Changes include: -** -** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL. -** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY -** into BTREE_BLOBKEY. -** (3) Bypass the creation of the sqlite_schema table entry -** for the PRIMARY KEY as the primary key index is now -** identified by the sqlite_schema table entry of the table itself. -** (4) Set the Index.tnum of the PRIMARY KEY Index object in the -** schema to the rootpage from the main table. -** (5) Add all table columns to the PRIMARY KEY Index object -** so that the PRIMARY KEY is a covering index. The surplus -** columns are part of KeyInfo.nAllField and are not used for -** sorting or lookup or uniqueness checks. -** (6) Replace the rowid tail on all automatically generated UNIQUE -** indices with the PRIMARY KEY columns. -** -** For virtual tables, only (1) is performed. -*/ -static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ - Index *pIdx; - Index *pPk; - int nPk; - int nExtra; - int i, j; - sqlite3 *db = pParse->db; - Vdbe *v = pParse->pVdbe; - - /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables) - */ - if( !db->init.imposterTable ){ - for(i=0; inCol; i++){ - if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 - && (pTab->aCol[i].notNull==OE_None) - ){ - pTab->aCol[i].notNull = OE_Abort; - } - } - pTab->tabFlags |= TF_HasNotNull; - } - - /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY - ** into BTREE_BLOBKEY. - */ - assert( !pParse->bReturning ); - if( pParse->u1.cr.addrCrTab ){ - assert( v ); - sqlite3VdbeChangeP3(v, pParse->u1.cr.addrCrTab, BTREE_BLOBKEY); - } - - /* Locate the PRIMARY KEY index. Or, if this table was originally - ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. - */ - if( pTab->iPKey>=0 ){ - ExprList *pList; - Token ipkToken; - sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName); - pList = sqlite3ExprListAppend(pParse, 0, - sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); - if( pList==0 ){ - pTab->tabFlags &= ~TF_WithoutRowid; - return; - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); - } - pList->a[0].fg.sortFlags = pParse->iPkSortOrder; - assert( pParse->pNewTable==pTab ); - pTab->iPKey = -1; - sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, - SQLITE_IDXTYPE_PRIMARYKEY); - if( pParse->nErr ){ - pTab->tabFlags &= ~TF_WithoutRowid; - return; - } - assert( db->mallocFailed==0 ); - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk->nKeyCol==1 ); - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - - /* - ** Remove all redundant columns from the PRIMARY KEY. For example, change - ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later - ** code assumes the PRIMARY KEY contains no repeated columns. - */ - for(i=j=1; inKeyCol; i++){ - if( isDupColumn(pPk, j, pPk, i) ){ - pPk->nColumn--; - }else{ - testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ); - pPk->azColl[j] = pPk->azColl[i]; - pPk->aSortOrder[j] = pPk->aSortOrder[i]; - pPk->aiColumn[j++] = pPk->aiColumn[i]; - } - } - pPk->nKeyCol = j; - } - assert( pPk!=0 ); - pPk->isCovering = 1; - if( !db->init.imposterTable ) pPk->uniqNotNull = 1; - nPk = pPk->nColumn = pPk->nKeyCol; - - /* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema - ** table entry. This is only required if currently generating VDBE - ** code for a CREATE TABLE (not when parsing one as part of reading - ** a database schema). */ - if( v && pPk->tnum>0 ){ - assert( db->init.busy==0 ); - sqlite3VdbeChangeOpcode(v, (int)pPk->tnum, OP_Goto); - } - - /* The root page of the PRIMARY KEY is the table root page */ - pPk->tnum = pTab->tnum; - - /* Update the in-memory representation of all UNIQUE indices by converting - ** the final rowid column into one or more columns of the PRIMARY KEY. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int n; - if( IsPrimaryKeyIndex(pIdx) ) continue; - for(i=n=0; inKeyCol, pPk, i) ){ - testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); - n++; - } - } - if( n==0 ){ - /* This index is a superset of the primary key */ - pIdx->nColumn = pIdx->nKeyCol; - continue; - } - if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return; - for(i=0, j=pIdx->nKeyCol; inKeyCol, pPk, i) ){ - testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); - pIdx->aiColumn[j] = pPk->aiColumn[i]; - pIdx->azColl[j] = pPk->azColl[i]; - if( pPk->aSortOrder[i] ){ - /* See ticket https://sqlite.org/src/info/bba7b69f9849b5bf */ - pIdx->bAscKeyBug = 1; - } - j++; - } - } - assert( pIdx->nColumn>=pIdx->nKeyCol+n ); - assert( pIdx->nColumn>=j ); - } - - /* Add all table columns to the PRIMARY KEY index - */ - nExtra = 0; - for(i=0; inCol; i++){ - if( !hasColumn(pPk->aiColumn, nPk, i) - && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++; - } - if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return; - for(i=0, j=nPk; inCol; i++){ - if( !hasColumn(pPk->aiColumn, j, i) - && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 - ){ - assert( jnColumn ); - pPk->aiColumn[j] = i; - pPk->azColl[j] = sqlite3StrBINARY; - j++; - } - } - assert( pPk->nColumn==j ); - assert( pTab->nNVCol<=j ); - recomputeColumnsNotIndexed(pPk); -} - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Return true if pTab is a virtual table and zName is a shadow table name -** for that virtual table. -*/ -SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){ - int nName; /* Length of zName */ - Module *pMod; /* Module for the virtual table */ - - if( !IsVirtual(pTab) ) return 0; - nName = sqlite3Strlen30(pTab->zName); - if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; - if( zName[nName]!='_' ) return 0; - pMod = (Module*)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; - return pMod->pModule->xShadowName(zName+nName+1); -} -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - -#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 sqlite3MarkAllShadowTablesOf(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*)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 = 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( 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. -** -** zName is temporarily modified while this routine is running, but is -** restored to its original value prior to this routine returning. -*/ -SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ - char *zTail; /* Pointer to the last "_" in zName */ - Table *pTab; /* Table that zName is a shadow of */ - zTail = strrchr(zName, '_'); - if( zTail==0 ) return 0; - *zTail = 0; - pTab = sqlite3FindTable(db, zName, 0); - *zTail = '_'; - if( pTab==0 ) return 0; - if( !IsVirtual(pTab) ) return 0; - return sqlite3IsShadowTableOf(db, pTab, zName); -} -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - - -#ifdef SQLITE_DEBUG -/* -** Mark all nodes of an expression as EP_Immutable, indicating that -** they should not be changed. Expressions attached to a table or -** index definition are tagged this way to help ensure that we do -** not pass them into code generator routines by mistake. -*/ -static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){ - (void)pWalker; - ExprSetVVAProperty(pExpr, EP_Immutable); - return WRC_Continue; -} -static void markExprListImmutable(ExprList *pList){ - if( pList ){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = markImmutableExprStep; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.xSelectCallback2 = 0; - sqlite3WalkExprList(&w, pList); - } -} -#else -#define markExprListImmutable(X) /* no-op */ -#endif /* SQLITE_DEBUG */ - - -/* -** This routine is called to report the final ")" that terminates -** a CREATE TABLE statement. -** -** The table structure that other action routines have been building -** is added to the internal hash tables, assuming no errors have -** occurred. -** -** An entry for the table is made in the schema table on disk, unless -** this is a temporary table or db->init.busy==1. When db->init.busy==1 -** it means we are reading the sqlite_schema table because we just -** connected to the database or because the sqlite_schema table has -** recently changed, so the entry for this table already exists in -** the sqlite_schema table. We do not want to create it again. -** -** If the pSelect argument is not NULL, it means that this routine -** was called to create a table generated from a -** "CREATE TABLE ... AS SELECT ..." statement. The column names of -** the new table will match the result set of the SELECT. -*/ -SQLITE_PRIVATE void sqlite3EndTable( - Parse *pParse, /* Parse context */ - Token *pCons, /* The ',' token after the last column defn. */ - Token *pEnd, /* The ')' before options in the CREATE TABLE */ - u32 tabOpts, /* Extra table options. Usually 0. */ - Select *pSelect /* Select from a "CREATE ... AS SELECT" */ -){ - Table *p; /* The new table */ - sqlite3 *db = pParse->db; /* The database connection */ - int iDb; /* Database in which the table lives */ - Index *pIdx; /* An implied index of the table */ - - if( pEnd==0 && pSelect==0 ){ - return; - } - p = pParse->pNewTable; - if( p==0 ) return; - - if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){ - p->tabFlags |= TF_Shadow; - } - - /* If the db->init.busy is 1 it means we are reading the SQL off the - ** "sqlite_schema" or "sqlite_temp_schema" table on the disk. - ** So do not write to the disk again. Extract the root page number - ** for the table from the db->init.newTnum field. (The page number - ** should have been put there by the sqliteOpenCb routine.) - ** - ** If the root page number is 1, that means this is the sqlite_schema - ** table itself. So mark it read-only. - */ - if( db->init.busy ){ - if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){ - sqlite3ErrorMsg(pParse, ""); - return; - } - p->tnum = db->init.newTnum; - 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; iinCol; ii++){ - Column *pCol = &p->aCol[ii]; - if( pCol->eCType==COLTYPE_CUSTOM ){ - if( pCol->colFlags & COLFLAG_HASTYPE ){ - sqlite3ErrorMsg(pParse, - "unknown datatype for %s.%s: \"%s\"", - p->zName, pCol->zCnName, sqlite3ColumnType(pCol, "") - ); - }else{ - 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 || sqlite3PrimaryKeyIndex(p)!=0 ); - assert( (p->tabFlags & TF_HasPrimaryKey)!=0 - || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) ); - - /* Special processing for WITHOUT ROWID Tables */ - if( tabOpts & TF_WithoutRowid ){ - if( (p->tabFlags & TF_Autoincrement) ){ - sqlite3ErrorMsg(pParse, - "AUTOINCREMENT not allowed on WITHOUT ROWID tables"); - return; - } - if( (p->tabFlags & TF_HasPrimaryKey)==0 ){ - sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); - return; - } - p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; - convertToWithoutRowidTable(pParse, p); - } - iDb = sqlite3SchemaToIndex(db, p->pSchema); - -#ifndef SQLITE_OMIT_CHECK - /* Resolve names in all CHECK constraint expressions. - */ - if( p->pCheck ){ - sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); - if( pParse->nErr ){ - /* If errors are seen, delete the CHECK constraints now, else they might - ** actually be used if PRAGMA writable_schema=ON is set. */ - sqlite3ExprListDelete(db, p->pCheck); - p->pCheck = 0; - }else{ - markExprListImmutable(p->pCheck); - } - } -#endif /* !defined(SQLITE_OMIT_CHECK) */ -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( p->tabFlags & TF_HasGenerated ){ - int ii, nNG = 0; - testcase( p->tabFlags & TF_HasVirtual ); - testcase( p->tabFlags & TF_HasStored ); - for(ii=0; iinCol; ii++){ - u32 colFlags = p->aCol[ii].colFlags; - if( (colFlags & COLFLAG_GENERATED)!=0 ){ - Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]); - testcase( colFlags & COLFLAG_VIRTUAL ); - testcase( colFlags & COLFLAG_STORED ); - if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){ - /* If there are errors in resolving the expression, change the - ** expression to a NULL. This prevents code generators that operate - ** on the expression from inserting extra parts into the expression - ** 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. */ - sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii], - sqlite3ExprAlloc(db, TK_NULL, 0, 0)); - } - }else{ - nNG++; - } - } - if( nNG==0 ){ - sqlite3ErrorMsg(pParse, "must have at least one non-generated column"); - return; - } - } -#endif - - /* Estimate the average row size for the table and for all implied indices */ - estimateTableWidth(p); - for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ - estimateIndexWidth(pIdx); - } - - /* If not initializing, then create a record for the new table - ** in the schema table of the database. - ** - ** If this is a TEMPORARY table, write the entry into the auxiliary - ** file instead of into the main database file. - */ - if( !db->init.busy ){ - int n; - Vdbe *v; - char *zType; /* "view" or "table" */ - char *zType2; /* "VIEW" or "TABLE" */ - char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ - - v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return; - - sqlite3VdbeAddOp1(v, OP_Close, 0); - - /* - ** Initialize zType for the new view or table. - */ - if( IsOrdinaryTable(p) ){ - /* A regular table */ - zType = "table"; - zType2 = "TABLE"; -#ifndef SQLITE_OMIT_VIEW - }else{ - /* A view */ - zType = "view"; - zType2 = "VIEW"; -#endif - } - - /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT - ** statement to populate the new table. The root-page number for the - ** new table is in register pParse->u1.cr.regRoot. - ** - ** Once the SELECT has been coded by sqlite3Select(), it is in a - ** suitable state to query for the column names and types to be used - ** by the new table. - ** - ** A shared-cache write-lock is not required to write to the new table, - ** as a schema-lock must have already been obtained to create it. Since - ** a schema-lock excludes all other database users, the write-lock would - ** be redundant. - */ - if( pSelect ){ - SelectDest dest; /* Where the SELECT should store results */ - int regYield; /* Register holding co-routine entry-point */ - int addrTop; /* Top of the co-routine */ - int regRec; /* A record to be insert into the new table */ - int regRowid; /* Rowid of the next row to insert */ - int addrInsLoop; /* Top of the loop for inserting rows */ - Table *pSelTab; /* A table that describes the SELECT results */ - int iCsr; /* Write cursor on the new table */ - - if( IN_SPECIAL_PARSE ){ - pParse->rc = SQLITE_ERROR; - pParse->nErr++; - return; - } - iCsr = pParse->nTab++; - regYield = ++pParse->nMem; - regRec = ++pParse->nMem; - regRowid = ++pParse->nMem; - sqlite3MayAbort(pParse); - assert( pParse->isCreate ); - sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb); - sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - if( pParse->nErr ) return; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB); - if( pSelTab==0 ) return; - assert( p->aCol==0 ); - p->nCol = p->nNVCol = pSelTab->nCol; - p->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - sqlite3Select(pParse, pSelect, &dest); - if( pParse->nErr ) return; - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); - addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); - sqlite3TableAffinity(v, p, 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid); - sqlite3VdbeGoto(v, addrInsLoop); - sqlite3VdbeJumpHere(v, addrInsLoop); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); - } - - /* Compute the complete text of the CREATE statement */ - if( pSelect ){ - zStmt = createTableStmt(db, p); - }else{ - Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd; - n = (int)(pEnd2->z - pParse->sNameToken.z); - if( pEnd2->z[0]!=';' ) n += pEnd2->n; - zStmt = sqlite3MPrintf(db, - "CREATE %s %.*s", zType2, n, pParse->sNameToken.z - ); - } - - /* A slot for the record has already been allocated in the - ** schema table. We just need to update that slot with all - ** the information we've collected. - */ - assert( pParse->isCreate ); - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE - " SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q" - " WHERE rowid=#%d", - db->aDb[iDb].zDbSName, - zType, - p->zName, - p->zName, - pParse->u1.cr.regRoot, - zStmt, - pParse->u1.cr.regRowid - ); - sqlite3DbFree(db, zStmt); - sqlite3ChangeCookie(pParse, iDb); - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* Check to see if we need to create an sqlite_sequence table for - ** keeping track of autoincrement keys. - */ - if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){ - Db *pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( pDb->pSchema->pSeqTab==0 ){ - sqlite3NestedParse(pParse, - "CREATE TABLE %Q.sqlite_sequence(name,seq)", - pDb->zDbSName - ); - } - } -#endif - - /* Reparse everything to update our internal data structures */ - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0); - - /* Test for cycles in generated columns and illegal expressions - ** in CHECK constraints and in DEFAULT clauses. */ - if( p->tabFlags & TF_HasGenerated ){ - sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, - sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", - db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); - } - } - - /* Add the table to the in-memory representation of the database. - */ - if( db->init.busy ){ - Table *pOld; - Schema *pSchema = p->pSchema; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( HasRowid(p) || p->iPKey<0 ); - pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); - if( pOld ){ - assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ - sqlite3OomFault(db); - return; - } - pParse->pNewTable = 0; - db->mDbFlags |= DBFLAG_SchemaChange; - - /* 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( 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 -/* -** The parser calls this routine in order to create a new VIEW -*/ -SQLITE_PRIVATE void sqlite3CreateView( - Parse *pParse, /* The parsing context */ - Token *pBegin, /* The CREATE token that begins the statement */ - Token *pName1, /* The token that holds the name of the view */ - Token *pName2, /* The token that holds the name of the view */ - ExprList *pCNames, /* Optional list of view column names */ - Select *pSelect, /* A SELECT statement that will become the new view */ - int isTemp, /* TRUE for a TEMPORARY view */ - int noErr /* Suppress error messages if VIEW already exists */ -){ - Table *p; - int n; - const char *z; - Token sEnd; - DbFixer sFix; - Token *pName = 0; - int iDb; - sqlite3 *db = pParse->db; - - if( pParse->nVar>0 ){ - sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); - goto create_view_fail; - } - 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. The ability can also be toggled - ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */ -#else - p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */ -#endif - - sqlite3TwoPartName(pParse, pName1, pName2, &pName); - iDb = sqlite3SchemaToIndex(db, p->pSchema); - sqlite3FixInit(&sFix, pParse, iDb, "view", pName); - if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; - - /* Make a copy of the entire SELECT statement that defines the view. - ** This will force all the Expr.token.z values to be dynamically - ** allocated rather than point to the input string - which means that - ** they will persist after the current sqlite3_exec() call returns. - */ - pSelect->selFlags |= SF_View; - if( IN_RENAME_OBJECT ){ - p->u.view.pSelect = pSelect; - pSelect = 0; - }else{ - p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - } - p->pCheck = 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 - ** the end. - */ - sEnd = pParse->sLastToken; - assert( sEnd.z[0]!=0 || sEnd.n==0 ); - if( sEnd.z[0]!=';' ){ - sEnd.z += sEnd.n; - } - sEnd.n = 0; - n = (int)(sEnd.z - pBegin->z); - assert( n>0 ); - z = pBegin->z; - while( sqlite3Isspace(z[n-1]) ){ n--; } - sEnd.z = &z[n-1]; - sEnd.n = 1; - - /* Use sqlite3EndTable() to add the view to the schema table */ - sqlite3EndTable(pParse, 0, &sEnd, 0, 0); - -create_view_fail: - sqlite3SelectDelete(db, pSelect); - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprlistUnmap(pParse, pCNames); - } - sqlite3ExprListDelete(db, pCNames); - return; -} -#endif /* SQLITE_OMIT_VIEW */ - -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -/* -** The Table structure pTable is really a VIEW. Fill in the names of -** the columns of the view in the pTable structure. Return non-zero if -** there are errors. If an error is seen an error message is left -** in pParse->zErrMsg. -*/ -static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){ - 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 */ - sqlite3 *db = pParse->db; /* Database connection for malloc errors */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - int rc; -#endif -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth; /* Saved xAuth pointer */ -#endif - - assert( pTable ); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTable) ){ - db->nSchemaLock++; - rc = sqlite3VtabCallConnect(pParse, pTable); - db->nSchemaLock--; - return rc; - } -#endif - -#ifndef SQLITE_OMIT_VIEW - /* A positive nCol means the columns names for this view are - ** already known. This routine is not called unless either the - ** table is virtual or nCol is zero. - */ - assert( pTable->nCol<=0 ); - - /* A negative nCol is a special marker meaning that we are currently - ** trying to compute the column names. If we enter this routine with - ** a negative nCol, it means two or more views form a loop, like this: - ** - ** CREATE VIEW one AS SELECT * FROM two; - ** CREATE VIEW two AS SELECT * FROM one; - ** - ** Actually, the error above is now caught prior to reaching this point. - ** But the following test is still important as it does come up - ** in the following: - ** - ** CREATE TABLE main.ex1(a); - ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1; - ** SELECT * FROM temp.ex1; - */ - if( pTable->nCol<0 ){ - sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); - return 1; - } - assert( pTable->nCol>=0 ); - - /* If we get this far, it means we need to compute the table names. - ** Note that the call to sqlite3ResultSetOfSelect() will expand any - ** "*" elements in the results set of the view and will assign cursors - ** to the elements of the FROM clause. But we do not want these changes - ** to be permanent. So the computation is done on a copy of the SELECT - ** statement that defines the view. - */ - assert( IsView(pTable) ); - pSel = 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; - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); - pTable->nCol = -1; - DisableLookaside; -#ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; - db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); - db->xAuth = xAuth; -#else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); -#endif - pParse->nTab = nTab; - pParse->nSelect = nSelect; - if( pSelTab==0 ){ - pTable->nCol = 0; - nErr++; - }else if( pTable->pCheck ){ - /* CREATE VIEW name(arglist) AS ... - ** The names of the columns in the table are taken from - ** arglist which is stored in pTable->pCheck. The pCheck field - ** normally holds CHECK constraints on an ordinary table, but for - ** a VIEW it holds the list of column names. - */ - sqlite3ColumnsFromExprList(pParse, pTable->pCheck, - &pTable->nCol, &pTable->aCol); - if( pParse->nErr==0 - && pTable->nCol==pSel->pEList->nExpr - ){ - assert( db->mallocFailed==0 ); - sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE); - } - }else{ - /* CREATE VIEW name AS... without an argument list. Construct - ** the column names from the SELECT statement that defines the view. - */ - 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( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); - } - pTable->nNVCol = pTable->nCol; - sqlite3DeleteTable(db, pSelTab); - sqlite3SelectDelete(db, pSel); - EnableLookaside; - pParse->eParseMode = eParseMode; - } else { - nErr++; - } - pTable->pSchema->schemaFlags |= DB_UnresetViews; - if( db->mallocFailed ){ - sqlite3DeleteColumnNames(db, pTable); - } -#endif /* SQLITE_OMIT_VIEW */ - return nErr + pParse->nErr; -} -SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ - assert( pTable!=0 ); - if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0; - return viewGetColumnNames(pParse, pTable); -} -#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -#ifndef SQLITE_OMIT_VIEW -/* -** Clear the column names from every VIEW in database idx. -*/ -static void sqliteViewResetAll(sqlite3 *db, int idx){ - HashElem *i; - assert( sqlite3SchemaMutexHeld(db, idx, 0) ); - if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; - for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - if( IsView(pTab) ){ - sqlite3DeleteColumnNames(db, pTab); - } - } - DbClearProperty(db, idx, DB_UnresetViews); -} -#else -# define sqliteViewResetAll(A,B) -#endif /* SQLITE_OMIT_VIEW */ - -/* -** This function is called by the VDBE to adjust the internal schema -** used by SQLite when the btree layer moves a table root page. The -** root-page of a table or index in database iDb has changed from iFrom -** to iTo. -** -** Ticket #1728: The symbol table might still contain information -** on tables and/or indices that are the process of being deleted. -** If you are unlucky, one of those deleted indices or tables might -** have the same rootpage number as the real table or index that is -** being moved. So we cannot stop searching after the first match -** because the first match might be for one of the deleted indices -** or tables and not the table/index that is actually being moved. -** We must continue looping until all tables and indices with -** rootpage==iFrom have been converted to have a rootpage of iTo -** in order to be certain that we got the right one. -*/ -#ifndef SQLITE_OMIT_AUTOVACUUM -SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){ - HashElem *pElem; - Hash *pHash; - Db *pDb; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pDb = &db->aDb[iDb]; - pHash = &pDb->pSchema->tblHash; - for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - if( pTab->tnum==iFrom ){ - pTab->tnum = iTo; - } - } - pHash = &pDb->pSchema->idxHash; - for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ - Index *pIdx = sqliteHashData(pElem); - if( pIdx->tnum==iFrom ){ - pIdx->tnum = iTo; - } - } -} -#endif - -/* -** Write code to erase the table with root-page iTable from database iDb. -** Also write code to modify the sqlite_schema table and internal schema -** if a root-page of another table is moved by the btree-layer whilst -** erasing iTable (this can happen with an auto-vacuum database). -*/ -static void destroyRootPage(Parse *pParse, int iTable, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - int r1 = sqlite3GetTempReg(pParse); - if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); - sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); - sqlite3MayAbort(pParse); -#ifndef SQLITE_OMIT_AUTOVACUUM - /* OP_Destroy stores an in integer r1. If this integer - ** is non-zero, then it is the root page number of a table moved to - ** location iTable. The following code modifies the sqlite_schema table to - ** reflect this. - ** - ** The "#NNN" in the SQL is a special constant that means whatever value - ** is in register NNN. See grammar rules associated with the TK_REGISTER - ** token for additional information. - */ - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE - " SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zDbSName, iTable, r1, r1); -#endif - sqlite3ReleaseTempReg(pParse, r1); -} - -/* -** Write VDBE code to erase table pTab and all associated indices on disk. -** Code to update the sqlite_schema tables and internal schema definitions -** in case a root-page belonging to another table is moved by the btree layer -** is also added (this can happen with an auto-vacuum database). -*/ -static void destroyTable(Parse *pParse, Table *pTab){ - /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM - ** is not defined), then it is important to call OP_Destroy on the - ** table and index root-pages in order, starting with the numerically - ** largest root-page number. This guarantees that none of the root-pages - ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the - ** following were coded: - ** - ** OP_Destroy 4 0 - ** ... - ** OP_Destroy 5 0 - ** - ** and root page 5 happened to be the largest root-page number in the - ** database, then root page 5 would be moved to page 4 by the - ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit - ** a free-list page. - */ - Pgno iTab = pTab->tnum; - Pgno iDestroyed = 0; - - while( 1 ){ - Index *pIdx; - Pgno iLargest = 0; - - if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){ - Pgno iIdx = pIdx->tnum; - assert( pIdx->pSchema==pTab->pSchema ); - if( (iDestroyed==0 || (iIdxiLargest ){ - iLargest = iIdx; - } - } - if( iLargest==0 ){ - return; - }else{ - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - assert( iDb>=0 && iDbdb->nDb ); - destroyRootPage(pParse, iLargest, iDb); - iDestroyed = iLargest; - } - } -} - -/* -** Remove entries from the sqlite_statN tables (for N in (1,2,3)) -** after a DROP INDEX or DROP TABLE command. -*/ -static void sqlite3ClearStatTables( - Parse *pParse, /* The parsing context */ - int iDb, /* The database number */ - const char *zType, /* "idx" or "tbl" */ - const char *zName /* Name of index or table */ -){ - int i; - const char *zDbName = pParse->db->aDb[iDb].zDbSName; - for(i=1; i<=4; i++){ - char zTab[24]; - sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i); - if( sqlite3FindTable(pParse->db, zTab, zDbName) ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE %s=%Q", - zDbName, zTab, zType, zName - ); - } - } -} - -/* -** Generate code to drop a table. -*/ -SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){ - Vdbe *v; - sqlite3 *db = pParse->db; - Trigger *pTrigger; - Db *pDb = &db->aDb[iDb]; - - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - sqlite3BeginWriteOperation(pParse, 1, iDb); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp0(v, OP_VBegin); - } -#endif - - /* Drop all triggers associated with the table being dropped. Code - ** is generated to remove entries from sqlite_schema and/or - ** sqlite_temp_schema if required. - */ - pTrigger = sqlite3TriggerList(pParse, pTab); - while( pTrigger ){ - assert( pTrigger->pSchema==pTab->pSchema || - pTrigger->pSchema==db->aDb[1].pSchema ); - sqlite3DropTriggerPtr(pParse, pTrigger); - pTrigger = pTrigger->pNext; - } - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* Remove any entries of the sqlite_sequence table associated with - ** the table being dropped. This is done before the table is dropped - ** at the btree level, in case the sqlite_sequence table needs to - ** move as a result of the drop (can happen in auto-vacuum mode). - */ - if( pTab->tabFlags & TF_Autoincrement ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.sqlite_sequence WHERE name=%Q", - pDb->zDbSName, pTab->zName - ); - } -#endif - - /* Drop all entries in the schema table that refer to the - ** table. The program name loops through the schema table and deletes - ** every row that refers to a table of the same name as the one being - ** dropped. Triggers are handled separately because a trigger can be - ** created in the temp database that refers to a table in another - ** database. - */ - sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE - " WHERE tbl_name=%Q and type!='trigger'", - pDb->zDbSName, pTab->zName); - if( !isView && !IsVirtual(pTab) ){ - destroyTable(pParse, pTab); - } - - /* Remove the table entry from SQLite's internal schema and modify - ** the schema cookie. - */ - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); - sqlite3MayAbort(pParse); - } - sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); - sqlite3ChangeCookie(pParse, iDb); - sqliteViewResetAll(db, iDb); -} - -/* -** Return TRUE if shadow tables should be read-only in the current -** context. -*/ -SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (db->flags & SQLITE_Defensive)!=0 - && db->pVtabCtx==0 - && db->nVdbeExec==0 - && !sqlite3VtabInSync(db) - ){ - return 1; - } -#endif - return 0; -} - -/* -** Return true if it is not allowed to drop the given table -*/ -static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){ - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ - if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0; - if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0; - return 1; - } - if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){ - return 1; - } - if( pTab->tabFlags & TF_Eponymous ){ - return 1; - } - return 0; -} - -/* -** This routine is called to do the work of a DROP TABLE statement. -** pName is the name of the table to be dropped. -*/ -SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ - Table *pTab; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - if( db->mallocFailed ){ - goto exit_drop_table; - } - assert( pParse->nErr==0 ); - assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 ); - assert( pName->a[0].fg.isSubquery==0 ); - if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; - if( noErr ) db->suppressErr++; - assert( isView==0 || isView==LOCATE_VIEW ); - pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); - if( noErr ) db->suppressErr--; - - if( pTab==0 ){ - if( noErr ){ - sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase); - sqlite3ForceNotReadOnly(pParse); - } - goto exit_drop_table; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 && iDbnDb ); - - /* If pTab is a virtual table, call ViewGetColumnNames() to ensure - ** it is initialized. - */ - if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto exit_drop_table; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code; - const char *zTab = SCHEMA_TABLE(iDb); - const char *zDb = db->aDb[iDb].zDbSName; - const char *zArg2 = 0; - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ - goto exit_drop_table; - } - if( isView ){ - if( !OMIT_TEMPDB && iDb==1 ){ - code = SQLITE_DROP_TEMP_VIEW; - }else{ - code = SQLITE_DROP_VIEW; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( IsVirtual(pTab) ){ - code = SQLITE_DROP_VTABLE; - zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName; -#endif - }else{ - if( !OMIT_TEMPDB && iDb==1 ){ - code = SQLITE_DROP_TEMP_TABLE; - }else{ - code = SQLITE_DROP_TABLE; - } - } - if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ - goto exit_drop_table; - } - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ - goto exit_drop_table; - } - } -#endif - if( tableMayNotBeDropped(db, pTab) ){ - sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); - goto exit_drop_table; - } - -#ifndef SQLITE_OMIT_VIEW - /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used - ** on a table. - */ - if( isView && !IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); - goto exit_drop_table; - } - if( !isView && IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); - goto exit_drop_table; - } -#endif - - /* Generate code to remove the table from the schema table - ** on disk. - */ - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3BeginWriteOperation(pParse, 1, iDb); - if( !isView ){ - sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); - sqlite3FkDropTable(pParse, pName, pTab); - } - sqlite3CodeDropTable(pParse, pTab, iDb, isView); - } - -exit_drop_table: - sqlite3SrcListDelete(db, pName); -} - -/* -** This routine is called to create a new foreign key on the table -** currently under construction. pFromCol determines which columns -** in the current table point to the foreign key. If pFromCol==0 then -** connect the key to the last column inserted. pTo is the name of -** the table referred to (a.k.a the "parent" table). pToCol is a list -** of tables in the parent pTo table. flags contains all -** information about the conflict resolution algorithms specified -** in the ON DELETE, ON UPDATE and ON INSERT clauses. -** -** An FKey structure is created and added to the table currently -** under construction in the pParse->pNewTable field. -** -** The foreign key is set for IMMEDIATE processing. A subsequent call -** to sqlite3DeferForeignKey() might change this to DEFERRED. -*/ -SQLITE_PRIVATE void sqlite3CreateForeignKey( - Parse *pParse, /* Parsing context */ - ExprList *pFromCol, /* Columns in this table that point to other table */ - Token *pTo, /* Name of the other table */ - ExprList *pToCol, /* Columns in the other table */ - int flags /* Conflict resolution algorithms. */ -){ - sqlite3 *db = pParse->db; -#ifndef SQLITE_OMIT_FOREIGN_KEY - FKey *pFKey = 0; - FKey *pNextTo; - Table *p = pParse->pNewTable; - i64 nByte; - int i; - int nCol; - char *z; - - assert( pTo!=0 ); - if( p==0 || IN_DECLARE_VTAB ) goto fk_end; - if( pFromCol==0 ){ - int iCol = p->nCol-1; - if( NEVER(iCol<0) ) goto fk_end; - if( pToCol && pToCol->nExpr!=1 ){ - sqlite3ErrorMsg(pParse, "foreign key on %s" - " should reference only one column of table %T", - p->aCol[iCol].zCnName, pTo); - goto fk_end; - } - nCol = 1; - }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ - sqlite3ErrorMsg(pParse, - "number of columns in foreign key does not match the number of " - "columns in the referenced table"); - goto fk_end; - }else{ - nCol = pFromCol->nExpr; - } - nByte = SZ_FKEY(nCol) + pTo->n + 1; - if( pToCol ){ - for(i=0; inExpr; i++){ - nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1; - } - } - pFKey = sqlite3DbMallocZero(db, nByte ); - if( pFKey==0 ){ - goto fk_end; - } - pFKey->pFrom = p; - assert( IsOrdinaryTable(p) ); - pFKey->pNextFrom = p->u.tab.pFKey; - z = (char*)&pFKey->aCol[nCol]; - pFKey->zTo = z; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)z, pTo); - } - memcpy(z, pTo->z, pTo->n); - z[pTo->n] = 0; - sqlite3Dequote(z); - z += pTo->n+1; - pFKey->nCol = nCol; - if( pFromCol==0 ){ - pFKey->aCol[0].iFrom = p->nCol-1; - }else{ - for(i=0; inCol; j++){ - if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){ - pFKey->aCol[i].iFrom = j; - break; - } - } - if( j>=p->nCol ){ - sqlite3ErrorMsg(pParse, - "unknown column \"%s\" in foreign key definition", - pFromCol->a[i].zEName); - goto fk_end; - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName); - } - } - } - if( pToCol ){ - for(i=0; ia[i].zEName); - pFKey->aCol[i].zCol = z; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName); - } - memcpy(z, pToCol->a[i].zEName, n); - z[n] = 0; - z += n+1; - } - } - pFKey->isDeferred = 0; - pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */ - pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */ - - assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); - pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, - pFKey->zTo, (void *)pFKey - ); - if( pNextTo==pFKey ){ - sqlite3OomFault(db); - goto fk_end; - } - if( pNextTo ){ - assert( pNextTo->pPrevTo==0 ); - pFKey->pNextTo = pNextTo; - pNextTo->pPrevTo = pFKey; - } - - /* Link the foreign key to the table as the last step. - */ - assert( IsOrdinaryTable(p) ); - p->u.tab.pFKey = pFKey; - pFKey = 0; - -fk_end: - sqlite3DbFree(db, pFKey); -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - sqlite3ExprListDelete(db, pFromCol); - sqlite3ExprListDelete(db, pToCol); -} - -/* -** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED -** clause is seen as part of a foreign key definition. The isDeferred -** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. -** The behavior of the most recently created foreign key is adjusted -** accordingly. -*/ -SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ -#ifndef SQLITE_OMIT_FOREIGN_KEY - Table *pTab; - FKey *pFKey; - 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 -} - -/* -** Generate code that will erase and refill index *pIdx. This is -** used to initialize a newly created index or to recompute the -** content of an index in response to a REINDEX command. -** -** if memRootPage is not negative, it means that the index is newly -** created. The register specified by memRootPage contains the -** root page number of the index. If memRootPage is negative, then -** the index already exists and must be cleared before being refilled and -** the root page number of the index is taken from pIndex->tnum. -*/ -static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ - Table *pTab = pIndex->pTable; /* The table that is indexed */ - int iTab = pParse->nTab++; /* Btree cursor used for pTab */ - int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ - int iSorter; /* Cursor opened by OpenSorter (if in use) */ - int addr1; /* Address of top of loop */ - int addr2; /* Address to jump to for next iteration */ - Pgno tnum; /* Root page of index */ - int iPartIdxLabel; /* Jump to this label to skip a row */ - Vdbe *v; /* Generate code into this virtual machine */ - KeyInfo *pKey; /* KeyInfo for index */ - int regRecord; /* Register holding assembled index record */ - sqlite3 *db = pParse->db; /* The database connection */ - int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - db->aDb[iDb].zDbSName ) ){ - return; - } -#endif - - /* Require a write-lock on the table to perform this operation */ - sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); - - v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - if( memRootPage>=0 ){ - tnum = (Pgno)memRootPage; - }else{ - tnum = pIndex->tnum; - } - pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); - assert( pKey!=0 || pParse->nErr ); - - /* Open the sorter cursor if we are to use one. */ - iSorter = pParse->nTab++; - sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*) - sqlite3KeyInfoRef(pKey), P4_KEYINFO); - - /* Open the table. Loop through all rows of the table, inserting index - ** records into the sorter. */ - sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); - regRecord = sqlite3GetTempReg(pParse); - sqlite3MultiWrite(pParse); - - sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); - sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); - sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr1); - if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb, - (char *)pKey, P4_KEYINFO); - sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); - - addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); - if( IsUniqueIndex(pIndex) ){ - int j2 = sqlite3VdbeGoto(v, 1); - addr2 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeVerifyAbortable(v, OE_Abort); - sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, - pIndex->nKeyCol); VdbeCoverage(v); - sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); - sqlite3VdbeJumpHere(v, j2); - }else{ - /* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not - ** abort. The exception is if one of the indexed expressions contains a - ** user function that throws an exception when it is evaluated. But the - ** overhead of adding a statement journal to a CREATE INDEX statement is - ** very small (since most of the pages written do not contain content that - ** needs to be restored if the statement aborts), so we call - ** sqlite3MayAbort() for all CREATE INDEX statements. */ - sqlite3MayAbort(pParse); - addr2 = sqlite3VdbeCurrentAddr(v); - } - sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - if( !pIndex->bAscKeyBug ){ - /* This OP_SeekEnd opcode makes index insert for a REINDEX go much - ** faster by avoiding unnecessary seeks. But the optimization does - ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables - ** with DESC primary keys, since those indexes have there keys in - ** a different order from the main table. - ** See ticket: https://sqlite.org/src/info/bba7b69f9849b5bf - */ - sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); - } - sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr1); - - sqlite3VdbeAddOp1(v, OP_Close, iTab); - sqlite3VdbeAddOp1(v, OP_Close, iIdx); - sqlite3VdbeAddOp1(v, OP_Close, iSorter); -} - -/* -** Allocate heap space to hold an Index object with nCol columns. -** -** Increase the allocation size to provide an extra nExtra bytes -** of 8-byte aligned space after the Index object and return a -** pointer to this extra space in *ppExtra. -*/ -SQLITE_PRIVATE Index *sqlite3AllocateIndexObject( - sqlite3 *db, /* Database connection */ - int nCol, /* Total number of columns in the index */ - int nExtra, /* Number of bytes of extra space to alloc */ - char **ppExtra /* Pointer to the "extra" space */ -){ - Index *p; /* Allocated index object */ - i64 nByte; /* Bytes of space for Index object + arrays */ - - assert( nCol <= 2*db->aLimit[SQLITE_LIMIT_COLUMN] ); - nByte = ROUND8(sizeof(Index)) + /* Index structure */ - ROUND8(sizeof(char*)*nCol) + /* Index.azColl */ - ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */ - sizeof(i16)*nCol + /* Index.aiColumn */ - sizeof(u8)*nCol); /* Index.aSortOrder */ - p = sqlite3DbMallocZero(db, nByte + nExtra); - if( p ){ - char *pExtra = ((char*)p)+ROUND8(sizeof(Index)); - p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); - p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1); - p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol; - p->aSortOrder = (u8*)pExtra; - assert( nCol>0 ); - p->nColumn = (u16)nCol; - p->nKeyCol = (u16)(nCol - 1); - *ppExtra = ((char*)p) + nByte; - } - return p; -} - -/* -** If expression list pList contains an expression that was parsed with -** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in -** pParse and return non-zero. Otherwise, return zero. -*/ -SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ - if( pList ){ - int i; - for(i=0; inExpr; i++){ - if( pList->a[i].fg.bNulls ){ - u8 sf = pList->a[i].fg.sortFlags; - sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", - (sf==0 || sf==3) ? "FIRST" : "LAST" - ); - return 1; - } - } - } - return 0; -} - -/* -** Create a new index for an SQL table. pName1.pName2 is the name of the index -** and pTblList is the name of the table that is to be indexed. Both will -** be NULL for a primary key or an index that is created to satisfy a -** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable -** as the table to be indexed. pParse->pNewTable is a table that is -** currently being constructed by a CREATE TABLE statement. -** -** pList is a list of columns to be indexed. pList will be NULL if this -** is a primary key or unique-constraint on the most recent column added -** to the table currently under construction. -*/ -SQLITE_PRIVATE void sqlite3CreateIndex( - Parse *pParse, /* All information about this parse */ - Token *pName1, /* First part of index name. May be NULL */ - Token *pName2, /* Second part of index name. May be NULL */ - SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ - ExprList *pList, /* A list of columns to be indexed */ - int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - Token *pStart, /* The CREATE token that begins this statement */ - Expr *pPIWhere, /* WHERE clause for partial indices */ - int sortOrder, /* Sort order of primary key when pList==NULL */ - int ifNotExist, /* Omit error if index already exists */ - u8 idxType /* The index type */ -){ - Table *pTab = 0; /* Table to be indexed */ - Index *pIndex = 0; /* The index to be created */ - char *zName = 0; /* Name of the index */ - int nName; /* Number of characters in zName */ - int i, j; - DbFixer sFix; /* For assigning database names to pTable */ - int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ - sqlite3 *db = pParse->db; - Db *pDb; /* The specific table containing the indexed database */ - int iDb; /* Index of the database that is being written */ - Token *pName = 0; /* Unqualified name of the index to create */ - struct ExprList_item *pListItem; /* For looping over pList */ - int nExtra = 0; /* Space allocated for zExtra[] */ - int nExtraCol; /* Number of extra columns needed */ - char *zExtra = 0; /* Extra space after the Index object */ - Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - - assert( 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; - } - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto exit_create_index; - } - if( sqlite3HasExplicitNulls(pParse, pList) ){ - goto exit_create_index; - } - - /* - ** Find the table that is to be indexed. Return early if not found. - */ - if( pTblName!=0 ){ - - /* Use the two-part index name to determine the database - ** to search for the table. 'Fix' the table name to this db - ** before looking up the table. - */ - assert( pName1 && pName2 ); - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ) goto exit_create_index; - assert( pName && pName->z ); - -#ifndef SQLITE_OMIT_TEMPDB - /* If the index name was unqualified, check if the table - ** is a temp table. If so, set the database to 1. Do not do this - ** if initializing a database schema. - */ - if( !db->init.busy ){ - pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ - iDb = 1; - } - } -#endif - - sqlite3FixInit(&sFix, pParse, iDb, "index", pName); - if( sqlite3FixSrcList(&sFix, pTblName) ){ - /* Because the parser constructs pTblName from a single identifier, - ** sqlite3FixSrcList can never fail. */ - assert(0); - } - pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); - assert( db->mallocFailed==0 || pTab==0 ); - if( pTab==0 ) goto exit_create_index; - if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){ - sqlite3ErrorMsg(pParse, - "cannot create a TEMP index on non-TEMP table \"%s\"", - pTab->zName); - goto exit_create_index; - } - if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); - }else{ - assert( pName==0 ); - assert( pStart==0 ); - pTab = pParse->pNewTable; - if( !pTab ) goto exit_create_index; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - } - pDb = &db->aDb[iDb]; - - assert( pTab!=0 ); - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 - && db->init.busy==0 - && pTblName!=0 - ){ - sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); - goto exit_create_index; - } -#ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "views may not be indexed"); - goto exit_create_index; - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); - goto exit_create_index; - } -#endif - - /* - ** Find the name of the index. Make sure there is not already another - ** index or table with the same name. - ** - ** Exception: If we are reading the names of permanent indices from the - ** sqlite_schema table (because some other process changed the schema) and - ** one of the index names collides with the name of a temporary table or - ** index, then we will continue to process this index. - ** - ** If pName==0 it means that we are - ** dealing with a primary key or UNIQUE constraint. We have to invent our - ** own name. - */ - if( pName ){ - zName = sqlite3NameFromToken(db, pName); - if( zName==0 ) goto exit_create_index; - assert( pName->z!=0 ); - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){ - goto exit_create_index; - } - if( !IN_RENAME_OBJECT ){ - if( !db->init.busy ){ - if( sqlite3FindTable(db, zName, pDb->zDbSName)!=0 ){ - sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); - goto exit_create_index; - } - } - if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ - if( !ifNotExist ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3ForceNotReadOnly(pParse); - } - goto exit_create_index; - } - } - }else{ - int n; - Index *pLoop; - for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} - zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n); - if( zName==0 ){ - goto exit_create_index; - } - - /* Automatic index names generated from within sqlite3_declare_vtab() - ** must have names that are distinct from normal automatic index names. - ** The following statement converts "sqlite3_autoindex..." into - ** "sqlite3_butoindex..." in order to make the names distinct. - ** The "vtab_err.test" test demonstrates the need of this statement. */ - if( IN_SPECIAL_PARSE ) zName[7]++; - } - - /* Check for authorization to create an index. - */ -#ifndef SQLITE_OMIT_AUTHORIZATION - if( !IN_RENAME_OBJECT ){ - const char *zDb = pDb->zDbSName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ - goto exit_create_index; - } - i = SQLITE_CREATE_INDEX; - if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; - if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ - goto exit_create_index; - } - } -#endif - - /* If pList==0, it means this routine was called to make a primary - ** key out of the last column added to the table under construction. - ** So create a fake list to simulate this. - */ - if( pList==0 ){ - Token prevCol; - Column *pCol = &pTab->aCol[pTab->nCol-1]; - pCol->colFlags |= COLFLAG_UNIQUE; - sqlite3TokenInit(&prevCol, pCol->zCnName); - pList = sqlite3ExprListAppend(pParse, 0, - sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); - if( pList==0 ) goto exit_create_index; - assert( pList->nExpr==1 ); - sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED); - }else{ - sqlite3ExprListCheckLength(pParse, pList, "index"); - if( pParse->nErr ) goto exit_create_index; - } - - /* Figure out how many bytes of space are required to store explicitly - ** specified collation sequence names. - */ - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - assert( pExpr!=0 ); - if( pExpr->op==TK_COLLATE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); - } - } - - /* - ** Allocate the index structure. - */ - nName = sqlite3Strlen30(zName); - nExtraCol = pPk ? pPk->nKeyCol : 1; - assert( pList->nExpr + nExtraCol <= 32767 /* Fits in i16 */ ); - pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol, - nName + nExtra + 1, &zExtra); - if( db->mallocFailed ){ - goto exit_create_index; - } - assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) ); - assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); - pIndex->zName = zExtra; - zExtra += nName + 1; - memcpy(pIndex->zName, zName, nName+1); - pIndex->pTable = pTab; - pIndex->onError = (u8)onError; - pIndex->uniqNotNull = onError!=OE_None; - pIndex->idxType = idxType; - pIndex->pSchema = db->aDb[iDb].pSchema; - pIndex->nKeyCol = pList->nExpr; - if( pPIWhere ){ - sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0); - pIndex->pPartIdxWhere = pPIWhere; - pPIWhere = 0; - } - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - - /* Check to see if we should honor DESC requests on index columns - */ - if( pDb->pSchema->file_format>=4 ){ - sortOrderMask = -1; /* Honor DESC */ - }else{ - sortOrderMask = 0; /* Ignore DESC */ - } - - /* Analyze the list of expressions that form the terms of the index and - ** report any errors. In the common case where the expression is exactly - ** a table column, store that column in aiColumn[]. For general expressions, - ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. - ** - ** TODO: Issue a warning if two or more columns of the index are identical. - ** TODO: Issue a warning if the table primary key is used as part of the - ** index key. - */ - pListItem = pList->a; - if( IN_RENAME_OBJECT ){ - pIndex->aColExpr = pList; - pList = 0; - } - for(i=0; inKeyCol; i++, pListItem++){ - Expr *pCExpr; /* The i-th index expression */ - int requestedSortOrder; /* ASC or DESC on the i-th expression */ - const char *zColl; /* Collation sequence name */ - - sqlite3StringToId(pListItem->pExpr); - sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0); - if( pParse->nErr ) goto exit_create_index; - pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr); - if( pCExpr->op!=TK_COLUMN ){ - if( pTab==pParse->pNewTable ){ - sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY and " - "UNIQUE constraints"); - goto exit_create_index; - } - if( pIndex->aColExpr==0 ){ - pIndex->aColExpr = pList; - pList = 0; - } - j = XN_EXPR; - pIndex->aiColumn[i] = XN_EXPR; - pIndex->uniqNotNull = 0; - pIndex->bHasExpr = 1; - }else{ - j = pCExpr->iColumn; - assert( j<=0x7fff ); - if( j<0 ){ - j = pTab->iPKey; - }else{ - if( pTab->aCol[j].notNull==0 ){ - pIndex->uniqNotNull = 0; - } - if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){ - pIndex->bHasVCol = 1; - pIndex->bHasExpr = 1; - } - } - pIndex->aiColumn[i] = (i16)j; - } - zColl = 0; - if( pListItem->pExpr->op==TK_COLLATE ){ - int nColl; - assert( !ExprHasProperty(pListItem->pExpr, EP_IntValue) ); - zColl = pListItem->pExpr->u.zToken; - nColl = sqlite3Strlen30(zColl) + 1; - assert( nExtra>=nColl ); - memcpy(zExtra, zColl, nColl); - zColl = zExtra; - zExtra += nColl; - nExtra -= nColl; - }else if( j>=0 ){ - zColl = sqlite3ColumnColl(&pTab->aCol[j]); - } - if( !zColl ) zColl = sqlite3StrBINARY; - if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ - goto exit_create_index; - } - pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask; - pIndex->aSortOrder[i] = (u8)requestedSortOrder; - } - - /* Append the table key to the end of the index. For WITHOUT ROWID - ** tables (when pPk!=0) this will be the declared PRIMARY KEY. For - ** normal tables (when pPk==0) this will be the rowid. - */ - if( pPk ){ - for(j=0; jnKeyCol; j++){ - int x = pPk->aiColumn[j]; - assert( x>=0 ); - if( isDupColumn(pIndex, pIndex->nKeyCol, pPk, j) ){ - pIndex->nColumn--; - }else{ - testcase( hasColumn(pIndex->aiColumn,pIndex->nKeyCol,x) ); - pIndex->aiColumn[i] = x; - pIndex->azColl[i] = pPk->azColl[j]; - pIndex->aSortOrder[i] = pPk->aSortOrder[j]; - i++; - } - } - assert( i==pIndex->nColumn ); - }else{ - pIndex->aiColumn[i] = XN_ROWID; - pIndex->azColl[i] = sqlite3StrBINARY; - } - sqlite3DefaultRowEst(pIndex); - if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); - - /* If this index contains every column of its table, then mark - ** it as a covering index */ - assert( HasRowid(pTab) - || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 ); - recomputeColumnsNotIndexed(pIndex); - if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ - pIndex->isCovering = 1; - for(j=0; jnCol; j++){ - if( j==pTab->iPKey ) continue; - if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue; - pIndex->isCovering = 0; - break; - } - } - - if( pTab==pParse->pNewTable ){ - /* This routine has been called to create an automatic index as a - ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or - ** a PRIMARY KEY or UNIQUE clause following the column definitions. - ** i.e. one of: - ** - ** CREATE TABLE t(x PRIMARY KEY, y); - ** CREATE TABLE t(x, y, UNIQUE(x, y)); - ** - ** Either way, check to see if the table already has such an index. If - ** so, don't bother creating this one. This only applies to - ** automatically created indices. Users can do as they wish with - ** explicit indices. - ** - ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent - ** (and thus suppressing the second one) even if they have different - ** sort orders. - ** - ** If there are different collating sequences or if the columns of - ** the constraint occur in different orders, then the constraints are - ** considered distinct and both result in separate indices. - */ - Index *pIdx; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int k; - assert( IsUniqueIndex(pIdx) ); - assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF ); - assert( IsUniqueIndex(pIndex) ); - - if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue; - for(k=0; knKeyCol; k++){ - const char *z1; - const char *z2; - assert( pIdx->aiColumn[k]>=0 ); - if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - z1 = pIdx->azColl[k]; - z2 = pIndex->azColl[k]; - if( sqlite3StrICmp(z1, z2) ) break; - } - if( k==pIdx->nKeyCol ){ - if( pIdx->onError!=pIndex->onError ){ - /* This constraint creates the same index as a previous - ** constraint specified somewhere in the CREATE TABLE statement. - ** However the ON CONFLICT clauses are different. If both this - ** constraint and the previous equivalent constraint have explicit - ** ON CONFLICT clauses this is an error. Otherwise, use the - ** explicitly specified behavior for the index. - */ - if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ - sqlite3ErrorMsg(pParse, - "conflicting ON CONFLICT clauses specified", 0); - } - if( pIdx->onError==OE_Default ){ - pIdx->onError = pIndex->onError; - } - } - if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType; - if( IN_RENAME_OBJECT ){ - pIndex->pNext = pParse->pNewIndex; - pParse->pNewIndex = pIndex; - pIndex = 0; - } - goto exit_create_index; - } - } - } - - if( !IN_RENAME_OBJECT ){ - - /* Link the new Index structure to its table and to the other - ** in-memory database structures. - */ - assert( pParse->nErr==0 ); - if( db->init.busy ){ - Index *p; - assert( !IN_SPECIAL_PARSE ); - assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); - if( pTblName!=0 ){ - pIndex->tnum = db->init.newTnum; - if( sqlite3IndexHasDuplicateRootPage(pIndex) ){ - sqlite3ErrorMsg(pParse, "invalid rootpage"); - pParse->rc = SQLITE_CORRUPT_BKPT; - goto exit_create_index; - } - } - p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, pIndex); - if( p ){ - assert( p==pIndex ); /* Malloc must have failed */ - sqlite3OomFault(db); - goto exit_create_index; - } - db->mDbFlags |= DBFLAG_SchemaChange; - } - - /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the - ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then - ** emit code to allocate the index rootpage on disk and make an entry for - ** the index in the sqlite_schema table and populate the index with - ** content. But, do not do this if we are simply reading the sqlite_schema - ** table to parse the schema, or if this index is the PRIMARY KEY index - ** of a WITHOUT ROWID table. - ** - ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY - ** or UNIQUE index in a CREATE TABLE statement. Since the table - ** has just been created, it contains no data and the index initialization - ** step can be skipped. - */ - else if( HasRowid(pTab) || pTblName!=0 ){ - Vdbe *v; - char *zStmt; - int iMem = ++pParse->nMem; - - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto exit_create_index; - - sqlite3BeginWriteOperation(pParse, 1, iDb); - - /* Create the rootpage for the index using CreateIndex. But before - ** doing so, code a Noop instruction and store its address in - ** Index.tnum. This is required in case this index is actually a - ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In - ** that case the convertToWithoutRowidTable() routine will replace - ** the Noop with a Goto to jump over the VDBE code generated below. */ - pIndex->tnum = (Pgno)sqlite3VdbeAddOp0(v, OP_Noop); - sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); - - /* Gather the complete text of the CREATE INDEX statement into - ** the zStmt variable - */ - assert( pName!=0 || pStart==0 ); - if( pStart ){ - int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; - if( pName->z[n-1]==';' ) n--; - /* A named index with an explicit CREATE INDEX statement */ - zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", - onError==OE_None ? "" : " UNIQUE", n, pName->z); - }else{ - /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ - /* zStmt = sqlite3MPrintf(""); */ - zStmt = 0; - } - - /* Add an entry in sqlite_schema for this index - */ - sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zDbSName, - pIndex->zName, - pTab->zName, - iMem, - zStmt - ); - sqlite3DbFree(db, zStmt); - - /* Fill the index with data and reparse the schema. Code an OP_Expire - ** to invalidate all pre-compiled statements. - */ - if( pTblName ){ - sqlite3RefillIndex(pParse, pIndex, iMem); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0); - sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); - } - - sqlite3VdbeJumpHere(v, (int)pIndex->tnum); - } - } - if( db->init.busy || pTblName==0 ){ - pIndex->pNext = pTab->pIndex; - pTab->pIndex = pIndex; - pIndex = 0; - } - else if( IN_RENAME_OBJECT ){ - assert( pParse->pNewIndex==0 ); - pParse->pNewIndex = pIndex; - pIndex = 0; - } - - /* Clean up before exiting */ -exit_create_index: - if( pIndex ) sqlite3FreeIndex(db, 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; - if( pThis->onError!=OE_Replace ) continue; - while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){ - *ppFrom = pNext; - pThis->pNext = pNext->pNext; - pNext->pNext = pThis; - ppFrom = &pNext->pNext; - } - 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 - } - sqlite3ExprDelete(db, pPIWhere); - sqlite3ExprListDelete(db, pList); - sqlite3SrcListDelete(db, pTblName); - sqlite3DbFree(db, zName); -} - -/* -** Fill the Index.aiRowEst[] array with default information - information -** to be used when we have not run the ANALYZE command. -** -** aiRowEst[0] is supposed to contain the number of elements in the index. -** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the -** number of rows in the table that match any particular value of the -** first column of the index. aiRowEst[2] is an estimate of the number -** of rows that match any particular combination of the first 2 columns -** of the index. And so forth. It must always be the case that -* -** aiRowEst[N]<=aiRowEst[N-1] -** aiRowEst[N]>=1 -** -** Apart from that, we have little to go on besides intuition as to -** how aiRowEst[] should be initialized. The numbers generated here -** are based on typical values found in actual indices. -*/ -SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ - /* 10, 9, 8, 7, 6 */ - static const LogEst aVal[] = { 33, 32, 30, 28, 26 }; - LogEst *a = pIdx->aiRowLogEst; - LogEst x; - int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); - int i; - - /* Indexes with default row estimates should not have stat1 data */ - assert( !pIdx->hasStat1 ); - - /* Set the first entry (number of rows in the index) to the estimated - ** number of rows in the table, or half the number of rows in the table - ** for a partial index. - ** - ** 2020-05-27: If some of the stat data is coming from the sqlite_stat1 - ** table but other parts we are having to guess at, then do not let the - ** estimated number of rows in the table be less than 1000 (LogEst 99). - ** Failure to do this can cause the indexes for which we do not have - ** stat1 data to be ignored by the query planner. - */ - x = pIdx->pTable->nRowLogEst; - assert( 99==sqlite3LogEst(1000) ); - if( x<99 ){ - pIdx->pTable->nRowLogEst = x = 99; - } - if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==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 - ** 6 and each subsequent value (if any) is 5. */ - memcpy(&a[1], aVal, nCopy*sizeof(LogEst)); - for(i=nCopy+1; i<=pIdx->nKeyCol; i++){ - a[i] = 23; assert( 23==sqlite3LogEst(5) ); - } - - assert( 0==sqlite3LogEst(1) ); - if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0; -} - -/* -** This routine will drop an existing named index. This routine -** implements the DROP INDEX statement. -*/ -SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ - Index *pIndex; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - if( db->mallocFailed ){ - goto exit_drop_index; - } - assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */ - assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 ); - assert( pName->a[0].fg.isSubquery==0 ); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto exit_drop_index; - } - pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase); - if( pIndex==0 ){ - if( !ifExists ){ - sqlite3ErrorMsg(pParse, "no such index: %S", pName->a); - }else{ - sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase); - sqlite3ForceNotReadOnly(pParse); - } - pParse->checkSchema = 1; - goto exit_drop_index; - } - if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ - sqlite3ErrorMsg(pParse, "index associated with UNIQUE " - "or PRIMARY KEY constraint cannot be dropped", 0); - goto exit_drop_index; - } - iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code = SQLITE_DROP_INDEX; - Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[iDb].zDbSName; - const char *zTab = SCHEMA_TABLE(iDb); - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - goto exit_drop_index; - } - if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX; - if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ - goto exit_drop_index; - } - } -#endif - - /* Generate code to remove the index and from the schema table */ - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3BeginWriteOperation(pParse, 1, iDb); - sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'", - db->aDb[iDb].zDbSName, pIndex->zName - ); - sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); - sqlite3ChangeCookie(pParse, iDb); - destroyRootPage(pParse, pIndex->tnum, iDb); - sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); - } - -exit_drop_index: - sqlite3SrcListDelete(db, pName); -} - -/* -** pArray is a pointer to an array of objects. Each object in the -** array is szEntry bytes in size. This routine uses sqlite3DbRealloc() -** to extend the array so that there is space for a new object at the end. -** -** When this function is called, *pnEntry contains the current size of -** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes -** in total). -** -** If the realloc() is successful (i.e. if no OOM condition occurs), the -** space allocated for the new object is zeroed, *pnEntry updated to -** reflect the new size of the array and a pointer to the new allocation -** returned. *pIdx is set to the index of the new array entry in this case. -** -** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains -** unchanged and a copy of pArray returned. -*/ -SQLITE_PRIVATE void *sqlite3ArrayAllocate( - sqlite3 *db, /* Connection to notify of malloc failures */ - void *pArray, /* Array of objects. Might be reallocated */ - int szEntry, /* Size of each object in the array */ - int *pnEntry, /* Number of objects currently in use */ - int *pIdx /* Write the index of a new slot here */ -){ - char *z; - sqlite3_int64 n = *pIdx = *pnEntry; - if( (n & (n-1))==0 ){ - sqlite3_int64 sz = (n==0) ? 1 : 2*n; - void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); - if( pNew==0 ){ - *pIdx = -1; - return pArray; - } - pArray = pNew; - } - z = (char*)pArray; - memset(&z[n * szEntry], 0, szEntry); - ++*pnEntry; - return pArray; -} - -/* -** Append a new element to the given IdList. Create a new IdList if -** need be. -** -** A new IdList is returned, or NULL if malloc() fails. -*/ -SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ - sqlite3 *db = pParse->db; - int i; - if( pList==0 ){ - pList = sqlite3DbMallocZero(db, SZ_IDLIST(1)); - if( pList==0 ) return 0; - }else{ - IdList *pNew; - pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1)); - if( pNew==0 ){ - sqlite3IdListDelete(db, pList); - return 0; - } - pList = pNew; - } - i = pList->nId++; - pList->a[i].zName = sqlite3NameFromToken(db, pToken); - if( IN_RENAME_OBJECT && pList->a[i].zName ){ - sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); - } - return pList; -} - -/* -** Delete an IdList. -*/ -SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ - int i; - assert( db!=0 ); - if( pList==0 ) return; - for(i=0; inId; i++){ - sqlite3DbFree(db, pList->a[i].zName); - } - sqlite3DbNNFreeNN(db, pList); -} - -/* -** Return the index in pList of the identifier named zId. Return -1 -** if not found. -*/ -SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){ - int i; - assert( pList!=0 ); - for(i=0; inId; i++){ - if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; - } - return -1; -} - -/* -** Maximum size of a SrcList object. -** The SrcList object is used to represent the FROM clause of a -** SELECT statement, and the query planner cannot deal with more -** than 64 tables in a join. So any value larger than 64 here -** is sufficient for most uses. Smaller values, like say 10, are -** appropriate for small and memory-limited applications. -*/ -#ifndef SQLITE_MAX_SRCLIST -# define SQLITE_MAX_SRCLIST 200 -#endif - -/* -** Expand the space allocated for the given SrcList object by -** creating nExtra new slots beginning at iStart. iStart is zero based. -** New slots are zeroed. -** -** For example, suppose a SrcList initially contains two entries: A,B. -** To append 3 new entries onto the end, do this: -** -** sqlite3SrcListEnlarge(db, pSrclist, 3, 2); -** -** After the call above it would contain: A, B, nil, nil, nil. -** If the iStart argument had been 1 instead of 2, then the result -** would have been: A, nil, nil, nil, B. To prepend the new slots, -** the iStart value would be 0. The result then would -** be: nil, nil, nil, A, B. -** -** If a memory allocation fails or the SrcList becomes too large, leave -** the original SrcList unchanged, return NULL, and leave an error message -** in pParse. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( - Parse *pParse, /* Parsing context into which errors are reported */ - SrcList *pSrc, /* The SrcList to be enlarged */ - int nExtra, /* Number of new slots to add to pSrc->a[] */ - int iStart /* Index in pSrc->a[] of first new slot */ -){ - int i; - - /* Sanity checking on calling parameters */ - assert( iStart>=0 ); - assert( nExtra>=1 ); - assert( pSrc!=0 ); - assert( iStart<=pSrc->nSrc ); - - /* Allocate additional space if needed */ - if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ - SrcList *pNew; - sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra; - sqlite3 *db = pParse->db; - - if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){ - sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d", - SQLITE_MAX_SRCLIST); - return 0; - } - if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST; - pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc)); - if( pNew==0 ){ - assert( db->mallocFailed ); - return 0; - } - pSrc = pNew; - pSrc->nAlloc = nAlloc; - } - - /* Move existing slots that come after the newly inserted slots - ** out of the way */ - for(i=pSrc->nSrc-1; i>=iStart; i--){ - pSrc->a[i+nExtra] = pSrc->a[i]; - } - pSrc->nSrc += nExtra; - - /* Zero the newly allocated slots */ - memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra); - for(i=iStart; ia[i].iCursor = -1; - } - - /* Return a pointer to the enlarged SrcList */ - return pSrc; -} - - -/* -** Append a new table name to the given SrcList. Create a new SrcList if -** need be. A new entry is created in the SrcList even if pTable is NULL. -** -** A SrcList is returned, or NULL if there is an OOM error or if the -** SrcList grows to large. The returned -** SrcList might be the same as the SrcList that was input or it might be -** a new one. If an OOM error does occurs, then the prior value of pList -** that is input to this routine is automatically freed. -** -** If pDatabase is not null, it means that the table has an optional -** database name prefix. Like this: "database.table". The pDatabase -** points to the table name and the pTable points to the database name. -** The SrcList.a[].zName field is filled with the table name which might -** come from pTable (if pDatabase is NULL) or from pDatabase. -** SrcList.a[].zDatabase is filled with the database name from pTable, -** or with NULL if no database is specified. -** -** In other words, if call like this: -** -** sqlite3SrcListAppend(D,A,B,0); -** -** Then B is a table name and the database name is unspecified. If called -** like this: -** -** sqlite3SrcListAppend(D,A,B,C); -** -** Then C is the table name and B is the database name. If C is defined -** then so is B. In other words, we never have a case where: -** -** sqlite3SrcListAppend(D,A,0,C); -** -** Both pTable and pDatabase are assumed to be quoted. They are dequoted -** before being added to the SrcList. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( - Parse *pParse, /* Parsing context, in which errors are reported */ - SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ - Token *pTable, /* Table to append */ - Token *pDatabase /* Database of the table */ -){ - SrcItem *pItem; - sqlite3 *db; - assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ - assert( pParse!=0 ); - assert( pParse->db!=0 ); - db = pParse->db; - if( pList==0 ){ - pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1)); - if( pList==0 ) return 0; - pList->nAlloc = 1; - pList->nSrc = 1; - memset(&pList->a[0], 0, sizeof(pList->a[0])); - pList->a[0].iCursor = -1; - }else{ - SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc); - if( pNew==0 ){ - sqlite3SrcListDelete(db, pList); - return 0; - }else{ - pList = pNew; - } - } - pItem = &pList->a[pList->nSrc-1]; - if( pDatabase && pDatabase->z==0 ){ - pDatabase = 0; - } - assert( pItem->fg.fixedSchema==0 ); - assert( pItem->fg.isSubquery==0 ); - if( pDatabase ){ - pItem->zName = sqlite3NameFromToken(db, pDatabase); - pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable); - }else{ - pItem->zName = sqlite3NameFromToken(db, pTable); - pItem->u4.zDatabase = 0; - } - return pList; -} - -/* -** Assign VdbeCursor index numbers to all tables in a SrcList -*/ -SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ - int i; - SrcItem *pItem; - assert( pList || pParse->db->mallocFailed ); - if( ALWAYS(pList) ){ - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->iCursor>=0 ) continue; - pItem->iCursor = pParse->nTab++; - if( pItem->fg.isSubquery ){ - assert( pItem->u4.pSubq!=0 ); - assert( pItem->u4.pSubq->pSelect!=0 ); - assert( pItem->u4.pSubq->pSelect->pSrc!=0 ); - sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc); - } - } - } -} - -/* -** Delete a Subquery object and its substructure. -*/ -SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){ - assert( pSubq!=0 && pSubq->pSelect!=0 ); - sqlite3SelectDelete(db, pSubq->pSelect); - sqlite3DbFree(db, pSubq); -} - -/* -** Remove a Subquery from a SrcItem. Return the associated Select object. -** The returned Select becomes the responsibility of the caller. -*/ -SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){ - Select *pSel; - assert( pItem!=0 ); - assert( pItem->fg.isSubquery ); - pSel = pItem->u4.pSubq->pSelect; - sqlite3DbFree(db, pItem->u4.pSubq); - pItem->u4.pSubq = 0; - pItem->fg.isSubquery = 0; - return pSel; -} - -/* -** Delete an entire SrcList including all its substructure. -*/ -SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ - int i; - SrcItem *pItem; - assert( db!=0 ); - if( pList==0 ) return; - for(pItem=pList->a, i=0; inSrc; i++, pItem++){ - - /* Check invariants on SrcItem */ - assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc ); - assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy ); - assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery ); - assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 && - pItem->u4.pSubq->pSelect!=0) ); - - if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName); - if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias); - if( pItem->fg.isSubquery ){ - sqlite3SubqueryDelete(db, pItem->u4.pSubq); - }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){ - sqlite3DbNNFreeNN(db, pItem->u4.zDatabase); - } - if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy); - if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); - sqlite3DeleteTable(db, pItem->pSTab); - if( pItem->fg.isUsing ){ - sqlite3IdListDelete(db, pItem->u3.pUsing); - }else if( pItem->u3.pOn ){ - sqlite3ExprDelete(db, pItem->u3.pOn); - } - } - sqlite3DbNNFreeNN(db, pList); -} - -/* -** Attach a Subquery object to pItem->uv.pSubq. Set the -** pSelect value but leave all the other values initialized -** to zero. -** -** A copy of the Select object is made if dupSelect is true, and the -** SrcItem takes responsibility for deleting the copy. If dupSelect is -** false, ownership of the Select passes to the SrcItem. Either way, -** the SrcItem will take responsibility for deleting the Select. -** -** When dupSelect is zero, that means the Select might get deleted right -** away if there is an OOM error. Beware. -** -** Return non-zero on success. Return zero on an OOM error. -*/ -SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery( - Parse *pParse, /* Parsing context */ - SrcItem *pItem, /* Item to which the subquery is to be attached */ - Select *pSelect, /* The subquery SELECT. Must be non-NULL */ - int dupSelect /* If true, attach a copy of pSelect, not pSelect itself.*/ -){ - Subquery *p; - assert( pSelect!=0 ); - assert( pItem->fg.isSubquery==0 ); - if( pItem->fg.fixedSchema ){ - pItem->u4.pSchema = 0; - pItem->fg.fixedSchema = 0; - }else if( pItem->u4.zDatabase!=0 ){ - sqlite3DbFree(pParse->db, pItem->u4.zDatabase); - pItem->u4.zDatabase = 0; - } - if( dupSelect ){ - pSelect = sqlite3SelectDup(pParse->db, pSelect, 0); - if( pSelect==0 ) return 0; - } - p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery)); - if( p==0 ){ - sqlite3SelectDelete(pParse->db, pSelect); - return 0; - } - pItem->fg.isSubquery = 1; - p->pSelect = pSelect; - assert( offsetof(Subquery, pSelect)==0 ); - memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect)); - return 1; -} - - -/* -** This routine is called by the parser to add a new term to the -** end of a growing FROM clause. The "p" parameter is the part of -** the FROM clause that has already been constructed. "p" is NULL -** if this is the first term of the FROM clause. pTable and pDatabase -** are the name of the table and database named in the FROM clause term. -** pDatabase is NULL if the database name qualifier is missing - the -** usual case. If the term has an alias, then pAlias points to the -** alias token. If the term is a subquery, then pSubquery is the -** SELECT statement that the subquery encodes. The pTable and -** pDatabase parameters are NULL for subqueries. The pOn and pUsing -** parameters are the content of the ON and USING clauses. -** -** Return a new SrcList which encodes is the FROM with the new -** term added. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( - Parse *pParse, /* Parsing context */ - SrcList *p, /* The left part of the FROM clause already seen */ - Token *pTable, /* Name of the table to add to the FROM clause */ - 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 */ - OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */ -){ - SrcItem *pItem; - sqlite3 *db = pParse->db; - if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){ - sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", - (pOnUsing->pOn ? "ON" : "USING") - ); - goto append_from_error; - } - p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase); - if( p==0 ){ - goto append_from_error; - } - assert( p->nSrc>0 ); - pItem = &p->a[p->nSrc-1]; - assert( (pTable==0)==(pDatabase==0) ); - assert( pItem->zName==0 || pDatabase!=0 ); - if( IN_RENAME_OBJECT && pItem->zName ){ - Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable; - sqlite3RenameTokenMap(pParse, pItem->zName, pToken); - } - assert( pAlias!=0 ); - if( pAlias->n ){ - pItem->zAlias = sqlite3NameFromToken(db, pAlias); - } - assert( pSubquery==0 || pDatabase==0 ); - if( pSubquery ){ - if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){ - 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: - assert( p==0 ); - sqlite3ClearOnOrUsing(db, pOnUsing); - sqlite3SelectDelete(db, pSubquery); - return 0; -} - -/* -** Add an INDEXED BY or NOT INDEXED clause to the most recently added -** element of the source-list passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ - assert( pIndexedBy!=0 ); - if( p && pIndexedBy->n>0 ){ - SrcItem *pItem; - assert( p->nSrc>0 ); - pItem = &p->a[p->nSrc-1]; - assert( pItem->fg.notIndexed==0 ); - assert( pItem->fg.isIndexedBy==0 ); - assert( pItem->fg.isTabFunc==0 ); - if( pIndexedBy->n==1 && !pIndexedBy->z ){ - /* A "NOT INDEXED" clause was supplied. See parse.y - ** construct "indexed_opt" for details. */ - pItem->fg.notIndexed = 1; - }else{ - pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); - pItem->fg.isIndexedBy = 1; - assert( pItem->fg.isCte==0 ); /* No collision on union u2 */ - } - } -} - -/* -** Append the contents of SrcList p2 to SrcList p1 and return the resulting -** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2 -** are deleted by this function. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){ - assert( p1 && p1->nSrc==1 ); - if( p2 ){ - SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1); - if( pNew==0 ){ - sqlite3SrcListDelete(pParse->db, p2); - }else{ - p1 = pNew; - memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem)); - sqlite3DbFree(pParse->db, p2); - p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype); - } - } - return p1; -} - -/* -** Add the list of function arguments to the SrcList entry for a -** table-valued-function. -*/ -SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){ - if( p ){ - SrcItem *pItem = &p->a[p->nSrc-1]; - assert( pItem->fg.notIndexed==0 ); - assert( pItem->fg.isIndexedBy==0 ); - assert( pItem->fg.isTabFunc==0 ); - pItem->u1.pFuncArg = pList; - pItem->fg.isTabFunc = 1; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } -} - -/* -** When building up a FROM clause in the parser, the join operator -** is initially attached to the left operand. But the code generator -** expects the join operator to be on the right operand. This routine -** Shifts all join operators from left to right for an entire FROM -** clause. -** -** Example: Suppose the join is like this: -** -** A natural cross join B -** -** 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 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 ); - } - } -} - -/* -** Generate VDBE code for a BEGIN statement. -*/ -SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ - sqlite3 *db; - Vdbe *v; - int i; - - assert( pParse!=0 ); - db = pParse->db; - assert( db!=0 ); - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( !v ) return; - if( type!=TK_DEFERRED ){ - for(i=0; inDb; i++){ - int eTxnType; - Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeIsReadonly(pBt) ){ - eTxnType = 0; /* Read txn */ - }else if( type==TK_EXCLUSIVE ){ - eTxnType = 2; /* Exclusive txn */ - }else{ - eTxnType = 1; /* Write txn */ - } - sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType); - sqlite3VdbeUsesBtree(v, i); - } - } - sqlite3VdbeAddOp0(v, OP_AutoCommit); -} - -/* -** Generate VDBE code for a COMMIT or ROLLBACK statement. -** Code for ROLLBACK is generated if eType==TK_ROLLBACK. Otherwise -** code is generated for a COMMIT. -*/ -SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){ - Vdbe *v; - int isRollback; - - assert( pParse!=0 ); - assert( pParse->db!=0 ); - assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK ); - isRollback = eType==TK_ROLLBACK; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, - isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback); - } -} - -/* -** This function is called by the parser when it parses a command to create, -** release or rollback an SQL savepoint. -*/ -SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){ - char *zName = sqlite3NameFromToken(pParse->db, pName); - if( zName ){ - Vdbe *v = sqlite3GetVdbe(pParse); -#ifndef SQLITE_OMIT_AUTHORIZATION - static const char * const az[] = { "BEGIN", "RELEASE", "ROLLBACK" }; - assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 ); -#endif - if( !v || sqlite3AuthCheck(pParse, SQLITE_SAVEPOINT, az[op], zName, 0) ){ - sqlite3DbFree(pParse->db, zName); - return; - } - sqlite3VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC); - } -} - -/* -** Make sure the TEMP database is open and available for use. Return -** the number of errors. Leave any error messages in the pParse structure. -*/ -SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ - sqlite3 *db = pParse->db; - if( db->aDb[1].pBt==0 && !pParse->explain ){ - int rc; - Btree *pBt; - static const int flags = - SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | - SQLITE_OPEN_DELETEONCLOSE | - SQLITE_OPEN_TEMP_DB; - - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); - if( rc!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "unable to open a temporary database " - "file for storing temporary tables"); - pParse->rc = rc; - return 1; - } - db->aDb[1].pBt = pBt; - assert( db->aDb[1].pSchema ); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){ - sqlite3OomFault(db); - return 1; - } - } - return 0; -} - -/* -** Record the fact that the schema cookie will need to be verified -** for database iDb. The code to actually verify the schema cookie -** will occur at the end of the top-level VDBE and will be generated -** later, by sqlite3FinishCoding(). -*/ -static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){ - assert( iDb>=0 && iDbdb->nDb ); - assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 ); - assert( iDbdb, iDb, 0) ); - if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ - DbMaskSet(pToplevel->cookieMask, iDb); - if( !OMIT_TEMPDB && iDb==1 ){ - sqlite3OpenTempDatabase(pToplevel); - } - } -} -SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ - sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb); -} - - -/* -** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each -** attached database. Otherwise, invoke it for the database named zDb only. -*/ -SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){ - sqlite3 *db = pParse->db; - int i; - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){ - sqlite3CodeVerifySchema(pParse, i); - } - } -} - -/* -** Generate VDBE code that prepares for doing an operation that -** might change the database. -** -** This routine starts a new transaction if we are not already within -** a transaction. If we are already within a transaction, then a checkpoint -** is set if the setStatement parameter is true. A checkpoint should -** be set for operations that might fail (due to a constraint) part of -** the way through and which will need to undo some writes without having to -** rollback the whole transaction. For operations where all constraints -** can be checked before any changes are made to the database, it is never -** necessary to undo a write and the checkpoint should not be set. -*/ -SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb); - DbMaskSet(pToplevel->writeMask, iDb); - pToplevel->isMultiWrite |= setStatement; -} - -/* -** Indicate that the statement currently under construction might write -** more than one entry (example: deleting one row then inserting another, -** inserting multiple rows in a table, or inserting a row and index entries.) -** If an abort occurs after some of these writes have completed, then it will -** be necessary to undo the completed writes. -*/ -SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pToplevel->isMultiWrite = 1; -} - -/* -** The code generator calls this routine if is discovers that it is -** possible to abort a statement prior to completion. In order to -** perform this abort without corrupting the database, we need to make -** sure that the statement is protected by a statement transaction. -** -** Technically, we only need to set the mayAbort flag if the -** isMultiWrite flag was previously set. There is a time dependency -** such that the abort must occur after the multiwrite. This makes -** some statements involving the REPLACE conflict resolution algorithm -** go a little faster. But taking advantage of this time dependency -** makes it more difficult to prove that the code is correct (in -** particular, it prevents us from writing an effective -** implementation of sqlite3AssertMayAbort()) and so we have chosen -** to take the safe route and skip the optimization. -*/ -SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pToplevel->mayAbort = 1; -} - -/* -** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT -** error. The onError parameter determines which (if any) of the statement -** and/or current transaction is rolled back. -*/ -SQLITE_PRIVATE void sqlite3HaltConstraint( - Parse *pParse, /* Parsing context */ - int errCode, /* extended error code */ - int onError, /* Constraint type */ - char *p4, /* Error message */ - i8 p4type, /* P4_STATIC or P4_TRANSIENT */ - u8 p5Errmsg /* P5_ErrMsg type */ -){ - Vdbe *v; - assert( pParse->pVdbe!=0 ); - v = sqlite3GetVdbe(pParse); - assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested ); - if( onError==OE_Abort ){ - sqlite3MayAbort(pParse); - } - sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type); - sqlite3VdbeChangeP5(v, p5Errmsg); -} - -/* -** Code an OP_Halt due to UNIQUE or PRIMARY KEY constraint violation. -*/ -SQLITE_PRIVATE void sqlite3UniqueConstraint( - Parse *pParse, /* Parsing context */ - int onError, /* Constraint type */ - Index *pIdx /* The index that triggers the constraint */ -){ - char *zErr; - int j; - StrAccum errMsg; - Table *pTab = pIdx->pTable; - - sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, - pParse->db->aLimit[SQLITE_LIMIT_LENGTH]); - if( pIdx->aColExpr ){ - sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); - }else{ - for(j=0; jnKeyCol; j++){ - char *zCol; - assert( pIdx->aiColumn[j]>=0 ); - zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName; - if( j ) sqlite3_str_append(&errMsg, ", ", 2); - sqlite3_str_appendall(&errMsg, pTab->zName); - sqlite3_str_append(&errMsg, ".", 1); - sqlite3_str_appendall(&errMsg, zCol); - } - } - zErr = sqlite3StrAccumFinish(&errMsg); - sqlite3HaltConstraint(pParse, - IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY - : SQLITE_CONSTRAINT_UNIQUE, - onError, zErr, P4_DYNAMIC, P5_ConstraintUnique); -} - - -/* -** Code an OP_Halt due to non-unique rowid. -*/ -SQLITE_PRIVATE void sqlite3RowidConstraint( - Parse *pParse, /* Parsing context */ - int onError, /* Conflict resolution algorithm */ - Table *pTab /* The table with the non-unique rowid */ -){ - char *zMsg; - int rc; - if( pTab->iPKey>=0 ){ - zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName, - pTab->aCol[pTab->iPKey].zCnName); - rc = SQLITE_CONSTRAINT_PRIMARYKEY; - }else{ - zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName); - rc = SQLITE_CONSTRAINT_ROWID; - } - sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC, - P5_ConstraintUnique); -} - -/* -** Check to see if pIndex uses the collating sequence pColl. Return -** true if it does and false if it does not. -*/ -#ifndef SQLITE_OMIT_REINDEX -static int collationMatch(const char *zColl, Index *pIndex){ - int i; - assert( zColl!=0 ); - for(i=0; inColumn; i++){ - const char *z = pIndex->azColl[i]; - assert( z!=0 || pIndex->aiColumn[i]<0 ); - if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){ - return 1; - } - } - return 0; -} -#endif - -/* -** Recompute all indices of pTab that use the collating sequence pColl. -** If pColl==0 then recompute all indices of pTab. -*/ -#ifndef SQLITE_OMIT_REINDEX -static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ - if( !IsVirtual(pTab) ){ - Index *pIndex; /* An index associated with pTab */ - - for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( zColl==0 || collationMatch(zColl, pIndex) ){ - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3RefillIndex(pParse, pIndex, -1); - } - } - } -} -#endif - -/* -** Recompute all indices of all tables in all databases where the -** indices use the collating sequence pColl. If pColl==0 then recompute -** all indices everywhere. -*/ -#ifndef SQLITE_OMIT_REINDEX -static void reindexDatabases(Parse *pParse, char const *zColl){ - Db *pDb; /* A single database */ - int iDb; /* The database index number */ - sqlite3 *db = pParse->db; /* The database connection */ - HashElem *k; /* For looping over tables in pDb */ - Table *pTab; /* A table in the database */ - - assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ - for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ - assert( pDb!=0 ); - for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ - pTab = (Table*)sqliteHashData(k); - reindexTable(pParse, pTab, zColl); - } - } -} -#endif - -/* -** Generate code for the REINDEX command. -** -** REINDEX -- 1 -** REINDEX -- 2 -** REINDEX ?.? -- 3 -** REINDEX ?.? -- 4 -** -** Form 1 causes all indices in all attached databases to be rebuilt. -** Form 2 rebuilds all indices in all databases that use the named -** collating function. Forms 3 and 4 rebuild the named index or all -** indices associated with the named table. -*/ -#ifndef SQLITE_OMIT_REINDEX -SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ - CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */ - char *z; /* Name of a table or index */ - const char *zDb; /* Name of the database */ - Table *pTab; /* A table in the database */ - Index *pIndex; /* An index associated with pTab */ - int iDb; /* The database index number */ - sqlite3 *db = pParse->db; /* The database connection */ - Token *pObjName; /* Name of the table or index to be reindexed */ - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - return; - } - - if( pName1==0 ){ - reindexDatabases(pParse, 0); - return; - }else if( NEVER(pName2==0) || pName2->z==0 ){ - char *zColl; - assert( pName1->z ); - zColl = sqlite3NameFromToken(pParse->db, pName1); - if( !zColl ) return; - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - if( pColl ){ - reindexDatabases(pParse, zColl); - sqlite3DbFree(db, zColl); - return; - } - sqlite3DbFree(db, zColl); - } - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); - if( iDb<0 ) return; - z = sqlite3NameFromToken(db, pObjName); - if( z==0 ) return; - zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; - pTab = sqlite3FindTable(db, z, zDb); - if( pTab ){ - reindexTable(pParse, pTab, 0); - sqlite3DbFree(db, z); - return; - } - pIndex = sqlite3FindIndex(db, z, zDb); - sqlite3DbFree(db, z); - if( pIndex ){ - iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3RefillIndex(pParse, pIndex, -1); - return; - } - sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); -} -#endif - -/* -** Return a KeyInfo structure that is appropriate for the given Index. -** -** The caller should invoke sqlite3KeyInfoUnref() on the returned object -** when it has finished using it. -*/ -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ - int i; - int nCol = pIdx->nColumn; - int nKey = pIdx->nKeyCol; - KeyInfo *pKey; - if( pParse->nErr ) return 0; - if( pIdx->uniqNotNull ){ - pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); - }else{ - pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); - } - if( pKey ){ - assert( sqlite3KeyInfoIsWriteable(pKey) ); - for(i=0; iazColl[i]; - pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 : - sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortFlags[i] = pIdx->aSortOrder[i]; - assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) ); - } - if( pParse->nErr ){ - assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); - if( pIdx->bNoQuery==0 ){ - /* Deactivate the index because it contains an unknown collating - ** sequence. The only way to reactive the index is to reload the - ** schema. Adding the missing collating sequence later does not - ** reactive the index. The application had the chance to register - ** the missing index using the collation-needed callback. For - ** simplicity, SQLite will not give the application a second chance. - */ - pIdx->bNoQuery = 1; - pParse->rc = SQLITE_ERROR_RETRY; - } - sqlite3KeyInfoUnref(pKey); - pKey = 0; - } - } - return pKey; -} - -#ifndef SQLITE_OMIT_CTE -/* -** Create a new CTE object -*/ -SQLITE_PRIVATE Cte *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; - sqlite3 *db = pParse->db; - - pNew = sqlite3DbMallocZero(db, sizeof(*pNew)); - assert( pNew!=0 || db->mallocFailed ); - - if( db->mallocFailed ){ - sqlite3ExprListDelete(db, pArglist); - sqlite3SelectDelete(db, pQuery); - }else{ - pNew->pSelect = pQuery; - pNew->pCols = pArglist; - pNew->zName = 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(sqlite3 *db, Cte *pCte){ - assert( pCte!=0 ); - sqlite3ExprListDelete(db, pCte->pCols); - sqlite3SelectDelete(db, pCte->pSelect); - sqlite3DbFree(db, pCte->zName); -} - -/* -** Free the contents of the CTE object passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ - assert( pCte!=0 ); - cteClear(db, pCte); - sqlite3DbFree(db, pCte); -} - -/* -** This routine is invoked once per CTE by the parser while parsing a -** WITH clause. The CTE described by the 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 *sqlite3WithAdd( - Parse *pParse, /* Parsing context */ - With *pWith, /* Existing WITH clause, or NULL */ - Cte *pCte /* CTE to add to the WITH clause */ -){ - 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 = pCte->zName; - if( zName && pWith ){ - int i; - for(i=0; inCte; i++){ - if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ - sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName); - } - } - } - - if( pWith ){ - pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1)); - }else{ - pNew = sqlite3DbMallocZero(db, SZ_WITH(1)); - } - assert( (pNew!=0 && zName!=0) || db->mallocFailed ); - - if( db->mallocFailed ){ - sqlite3CteDelete(db, pCte); - pNew = pWith; - }else{ - pNew->a[pNew->nCte++] = *pCte; - sqlite3DbFree(db, pCte); - } - - return pNew; -} - -/* -** Free the contents of the With object passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ - if( pWith ){ - int i; - for(i=0; inCte; i++){ - cteClear(db, &pWith->a[i]); - } - sqlite3DbFree(db, pWith); - } -} -SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){ - sqlite3WithDelete(db, (With*)pWith); -} -#endif /* !defined(SQLITE_OMIT_CTE) */ - -/************** End of build.c ***********************************************/ -/************** Begin file callback.c ****************************************/ -/* -** 2005 May 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains functions used to access the internal hash tables -** of user defined functions and collation sequences. -*/ - -/* #include "sqliteInt.h" */ - -/* -** Invoke the 'collation needed' callback to request a collation sequence -** in the encoding enc of name zName, length nName. -*/ -static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ - assert( !db->xCollNeeded || !db->xCollNeeded16 ); - if( db->xCollNeeded ){ - char *zExternal = sqlite3DbStrDup(db, zName); - if( !zExternal ) return; - db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal); - sqlite3DbFree(db, zExternal); - } -#ifndef SQLITE_OMIT_UTF16 - if( db->xCollNeeded16 ){ - char const *zExternal; - sqlite3_value *pTmp = sqlite3ValueNew(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); - zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); - if( zExternal ){ - db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); - } - sqlite3ValueFree(pTmp); - } -#endif -} - -/* -** This routine is called if the collation factory fails to deliver a -** collation function in the best encoding but there may be other versions -** of this collation function (for other text encodings) available. Use one -** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if -** possible. -*/ -static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ - CollSeq *pColl2; - char *z = pColl->zName; - int i; - static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; - for(i=0; i<3; i++){ - pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0); - if( pColl2->xCmp!=0 ){ - memcpy(pColl, pColl2, sizeof(CollSeq)); - pColl->xDel = 0; /* Do not copy the destructor */ - return SQLITE_OK; - } - } - return SQLITE_ERROR; -} - -/* -** This routine is called on a collation sequence before it is used to -** check that it is defined. An undefined collation sequence exists when -** a database is loaded that contains references to collation sequences -** that have not been defined by sqlite3_create_collation() etc. -** -** If required, this routine calls the 'collation needed' callback to -** request a definition of the collating sequence. If this doesn't work, -** an equivalent collating sequence that uses a text encoding different -** from the main database is substituted, if one is available. -*/ -SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ - if( pColl && pColl->xCmp==0 ){ - const char *zName = pColl->zName; - sqlite3 *db = pParse->db; - CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName); - if( !p ){ - return SQLITE_ERROR; - } - assert( p==pColl ); - } - return SQLITE_OK; -} - - - -/* -** Locate and return an entry from the db.aCollSeq hash table. If the entry -** specified by zName and nName is not found and parameter 'create' is -** true, then create a new entry. Otherwise return NULL. -** -** Each pointer stored in the sqlite3.aCollSeq hash table contains an -** array of three CollSeq structures. The first is the collation sequence -** preferred for UTF-8, the second UTF-16le, and the third UTF-16be. -** -** Stored immediately after the three collation sequences is a copy of -** the collation sequence name. A pointer to this string is stored in -** each collation sequence structure. -*/ -static CollSeq *findCollSeqEntry( - sqlite3 *db, /* Database connection */ - const char *zName, /* Name of the collating sequence */ - int create /* Create a new entry if true */ -){ - CollSeq *pColl; - pColl = sqlite3HashFind(&db->aCollSeq, zName); - - if( 0==pColl && create ){ - int nName = sqlite3Strlen30(zName) + 1; - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName); - if( pColl ){ - CollSeq *pDel = 0; - pColl[0].zName = (char*)&pColl[3]; - pColl[0].enc = SQLITE_UTF8; - pColl[1].zName = (char*)&pColl[3]; - pColl[1].enc = SQLITE_UTF16LE; - pColl[2].zName = (char*)&pColl[3]; - pColl[2].enc = SQLITE_UTF16BE; - memcpy(pColl[0].zName, zName, nName); - pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); - - /* If a malloc() failure occurred in sqlite3HashInsert(), it will - ** return the pColl pointer to be deleted (because it wasn't added - ** to the hash table). - */ - assert( pDel==0 || pDel==pColl ); - if( pDel!=0 ){ - sqlite3OomFault(db); - sqlite3DbFree(db, pDel); - pColl = 0; - } - } - } - return pColl; -} - -/* -** Parameter zName points to a UTF-8 encoded string nName bytes long. -** Return the CollSeq* pointer for the collation sequence named zName -** for the encoding 'enc' from the database 'db'. -** -** If the entry specified is not found and 'create' is true, then create a -** new entry. Otherwise return NULL. -** -** A separate function sqlite3LocateCollSeq() is a wrapper around -** this routine. sqlite3LocateCollSeq() invokes the collation factory -** if necessary and generates an error message if the collating sequence -** cannot be found. -** -** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( - sqlite3 *db, /* Database connection to search */ - u8 enc, /* Desired text encoding */ - const char *zName, /* Name of the collating sequence. Might be NULL */ - int create /* True to create CollSeq if doesn't already exist */ -){ - CollSeq *pColl; - assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); - if( zName ){ - pColl = findCollSeqEntry(db, zName, create); - if( pColl ) pColl += enc-1; - }else{ - pColl = db->pDfltColl; - } - return pColl; -} - -/* -** Change the text encoding for a database connection. This means that -** the pDfltColl must change as well. -*/ -SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){ - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - db->enc = enc; - /* EVIDENCE-OF: R-08308-17224 The default collating function for all - ** strings is BINARY. - */ - db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0); - sqlite3ExpirePreparedStatements(db, 1); -} - -/* -** This function is responsible for invoking the collation factory callback -** or substituting a collation sequence of a different encoding when the -** requested collation sequence is not available in the desired encoding. -** -** If it is not NULL, then pColl must point to the database native encoding -** collation sequence with name zName, length nName. -** -** The return value is either the collation sequence to be used in database -** db for collation type name zName, length nName, or NULL, if no collation -** sequence can be found. If no collation is found, leave an error message. -** -** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( - Parse *pParse, /* Parsing context */ - u8 enc, /* The desired encoding for the collating sequence */ - CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ - const char *zName /* Collating sequence name */ -){ - CollSeq *p; - sqlite3 *db = pParse->db; - - p = pColl; - if( !p ){ - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( !p || !p->xCmp ){ - /* No collation sequence of this type for this encoding is registered. - ** Call the collation factory to see if it can supply us with one. - */ - callCollNeeded(db, enc, zName); - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( p && !p->xCmp && synthCollSeq(db, p) ){ - p = 0; - } - assert( !p || p->xCmp ); - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); - pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ; - } - return p; -} - -/* -** This function returns the collation sequence for database native text -** encoding identified by the string zName. -** -** If the requested collation sequence is not available, or not available -** in the database native encoding, the collation factory is invoked to -** request it. If the collation factory does not supply such a sequence, -** and the sequence is available in another text encoding, then that is -** returned instead. -** -** If no versions of the requested collations sequence are available, or -** another error occurs, NULL is returned and an error message written into -** pParse. -** -** This routine is a wrapper around sqlite3FindCollSeq(). This routine -** invokes the collation factory if the named collation cannot be found -** and generates an error message. -** -** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ - sqlite3 *db = pParse->db; - u8 enc = ENC(db); - u8 initbusy = db->init.busy; - CollSeq *pColl; - - pColl = sqlite3FindCollSeq(db, enc, zName, initbusy); - if( !initbusy && (!pColl || !pColl->xCmp) ){ - pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName); - } - - return pColl; -} - -/* During the search for the best function definition, this procedure -** is called to test how well the function passed as the first argument -** matches the request for a function with nArg arguments in a system -** that uses encoding enc. The value returned indicates how well the -** request is matched. A higher value indicates a better match. -** -** If nArg is -1 that means to only return a match (non-zero) if p->nArg -** is also -1. In other words, we are searching for a function that -** takes a variable number of arguments. -** -** If nArg is -2 that means that we are searching for any function -** regardless of the number of arguments it uses, so return a positive -** match score for any -** -** The returned value is always between 0 and 6, as follows: -** -** 0: Not a match. -** 1: UTF8/16 conversion required and function takes any number of arguments. -** 2: UTF16 byte order change required and function takes any number of args. -** 3: encoding matches and function takes any number of arguments -** 4: UTF8/16 conversion required - argument count matches exactly -** 5: UTF16 byte order conversion required - argument count matches exactly -** 6: Perfect match: encoding and argument count match exactly. -** -** If nArg==(-2) then any function with a non-null xSFunc is -** a perfect match and any function with xSFunc NULL is -** a non-match. -*/ -#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ -static int matchQuality( - FuncDef *p, /* The function we are evaluating for match quality */ - int nArg, /* Desired number of arguments. (-1)==any */ - u8 enc /* Desired text encoding */ -){ - int match; - assert( p->nArg>=(-4) && p->nArg!=(-2) ); - assert( nArg>=(-2) ); - - /* Wrong number of arguments means "no match" */ - if( p->nArg!=nArg ){ - if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH; - if( p->nArg>=0 ) return 0; - /* Special p->nArg values available to built-in functions only: - ** -3 1 or more arguments required - ** -4 2 or more arguments required - */ - if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0; - } - - /* Give a better score to a function with a specific number of arguments - ** than to function that accepts any number of arguments. */ - if( p->nArg==nArg ){ - match = 4; - }else{ - match = 1; - } - - /* Bonus points if the text encoding matches */ - if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){ - match += 2; /* Exact encoding match */ - }else if( (enc & p->funcFlags & 2)!=0 ){ - match += 1; /* Both are UTF16, but with different byte orders */ - } - - return match; -} - -/* -** Search a FuncDefHash for a function with the given name. Return -** a pointer to the matching FuncDef if found, or 0 if there is no match. -*/ -SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch( - int h, /* Hash of the name */ - const char *zFunc /* Name of function */ -){ - FuncDef *p; - for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ - assert( p->funcFlags & SQLITE_FUNC_BUILTIN ); - if( sqlite3StrICmp(p->zName, zFunc)==0 ){ - return p; - } - } - return 0; -} - -/* -** Insert a new FuncDef into a FuncDefHash hash table. -*/ -SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs( - FuncDef *aDef, /* List of global functions to be inserted */ - int nDef /* Length of the apDef[] list */ -){ - int i; - for(i=0; ipNext!=&aDef[i] ); - aDef[i].pNext = pOther->pNext; - pOther->pNext = &aDef[i]; - }else{ - aDef[i].pNext = 0; - aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h]; - sqlite3BuiltinFunctions.a[h] = &aDef[i]; - } - } -} - - - -/* -** Locate a user function given a name, a number of arguments and a flag -** indicating whether the function prefers UTF-16 over UTF-8. Return a -** pointer to the FuncDef structure that defines that function, or return -** NULL if the function does not exist. -** -** If the createFlag argument is true, then a new (blank) FuncDef -** structure is created and liked into the "db" structure if a -** no matching function previously existed. -** -** If nArg is -2, then the first valid function found is returned. A -** function is valid if xSFunc is non-zero. The nArg==(-2) -** case is used to see if zName is a valid function name for some number -** of arguments. If nArg is -2, then createFlag must be 0. -** -** If createFlag is false, then a function with the required name and -** number of arguments may be returned even if the eTextRep flag does not -** match that requested. -*/ -SQLITE_PRIVATE FuncDef *sqlite3FindFunction( - sqlite3 *db, /* An open database */ - const char *zName, /* Name of the function. zero-terminated */ - int nArg, /* Number of arguments. -1 means any number */ - u8 enc, /* Preferred text encoding */ - u8 createFlag /* Create new entry if true and does not otherwise exist */ -){ - FuncDef *p; /* Iterator variable */ - FuncDef *pBest = 0; /* Best match found so far */ - int bestScore = 0; /* Score of best match */ - int h; /* Hash value */ - int nName; /* Length of the name */ - - assert( nArg>=(-2) ); - assert( nArg>=(-1) || createFlag==0 ); - nName = sqlite3Strlen30(zName); - - /* First search for a match amongst the application-defined functions. - */ - p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName); - while( p ){ - int score = matchQuality(p, nArg, enc); - if( score>bestScore ){ - pBest = p; - bestScore = score; - } - p = p->pNext; - } - - /* If no match is found, search the built-in functions. - ** - ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in - ** functions even if a prior app-defined function was found. And give - ** priority to built-in functions. - ** - ** Except, if createFlag is true, that means that we are trying to - ** install a new function. Whatever FuncDef structure is returned it will - ** have fields overwritten with new information appropriate for the - ** new function. But the FuncDefs for built-in functions are read-only. - ** So we must not search for built-ins when creating a new function. - */ - if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ - bestScore = 0; - h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); - p = sqlite3FunctionSearch(h, zName); - while( p ){ - int score = matchQuality(p, nArg, enc); - if( score>bestScore ){ - pBest = p; - bestScore = score; - } - p = p->pNext; - } - } - - /* If the createFlag parameter is true and the search did not reveal an - ** exact match for the name, number of arguments and encoding, then add a - ** new entry to the hash table and return it. - */ - if( createFlag && bestScorezName = (const char*)&pBest[1]; - pBest->nArg = (u16)nArg; - pBest->funcFlags = enc; - memcpy((char*)&pBest[1], zName, nName+1); - for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z]; - pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); - if( pOther==pBest ){ - sqlite3DbFree(db, pBest); - sqlite3OomFault(db); - return 0; - }else{ - pBest->pNext = pOther; - } - } - - if( pBest && (pBest->xSFunc || createFlag) ){ - return pBest; - } - return 0; -} - -/* -** Free all resources held by the schema structure. The void* argument points -** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the -** pointer itself, it just cleans up subsidiary resources (i.e. the contents -** of the schema hash tables). -** -** The Schema.cache_size variable is not cleared. -*/ -SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ - Hash temp1; - Hash temp2; - HashElem *pElem; - Schema *pSchema = (Schema *)p; - sqlite3 xdb; - - memset(&xdb, 0, sizeof(xdb)); - temp1 = pSchema->tblHash; - temp2 = pSchema->trigHash; - sqlite3HashInit(&pSchema->trigHash); - sqlite3HashClear(&pSchema->idxHash); - for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem)); - } - sqlite3HashClear(&temp2); - sqlite3HashInit(&pSchema->tblHash); - for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - sqlite3DeleteTable(&xdb, pTab); - } - sqlite3HashClear(&temp1); - sqlite3HashClear(&pSchema->fkeyHash); - pSchema->pSeqTab = 0; - if( pSchema->schemaFlags & DB_SchemaLoaded ){ - pSchema->iGeneration++; - } - pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); -} - -/* -** Find and return the schema associated with a BTree. Create -** a new one if necessary. -*/ -SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ - Schema * p; - if( pBt ){ - p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); - }else{ - p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); - } - if( !p ){ - sqlite3OomFault(db); - }else if ( 0==p->file_format ){ - sqlite3HashInit(&p->tblHash); - sqlite3HashInit(&p->idxHash); - sqlite3HashInit(&p->trigHash); - sqlite3HashInit(&p->fkeyHash); - p->enc = SQLITE_UTF8; - } - return p; -} - -/************** End of callback.c ********************************************/ -/************** Begin file delete.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** in order to generate code for DELETE FROM statements. -*/ -/* #include "sqliteInt.h" */ - -/* -** While a SrcList can in general represent multiple tables and subqueries -** (as in the FROM clause of a SELECT statement) in this case it contains -** the name of a single table, as one might find in an INSERT, DELETE, -** or UPDATE statement. Look up that table in the symbol table and -** return a pointer. Set an error message and return NULL if the table -** name is not found or if any other error occurs. -** -** The following fields are initialized appropriate in pSrc: -** -** pSrc->a[0].spTab Pointer to the Table object -** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one -** -*/ -SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ - SrcItem *pItem = pSrc->a; - Table *pTab; - assert( pItem && pSrc->nSrc>=1 ); - pTab = sqlite3LocateTableItem(pParse, 0, pItem); - if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab); - pItem->pSTab = pTab; - pItem->fg.notCte = 1; - if( pTab ){ - pTab->nTabRef++; - if( pItem->fg.isIndexedBy && 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 sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){ - sqlite3VdbeAddOp0(v, OP_FkCheck); - sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1); - sqlite3VdbeSetNumCols(v, 1); - 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: -** -** 1) It is a virtual table and no implementation of the xUpdate method -** has been provided -** -** 2) A trigger is currently being coded and the table is a virtual table -** that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and -** the table is not SQLITE_VTAB_INNOCUOUS. -** -** 3) It is a system table (i.e. sqlite_schema), this call is not -** part of a nested parse and writable_schema pragma has not -** been specified -** -** 4) The table is a shadow table, the database connection is in -** defensive mode, and the current sqlite3_prepare() -** is for a top-level SQL statement. -*/ -static int vtabIsReadOnly(Parse *pParse, Table *pTab){ - assert( IsVirtual(pTab) ); - if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){ - return 1; - } - - /* Within triggers: - ** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY - ** virtual tables - ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS - ** virtual tables if PRAGMA trusted_schema=ON. - */ - if( pParse->pToplevel!=0 - && pTab->u.vtab.p->eVtabRisk > - ((pParse->db->flags & SQLITE_TrustedSchema)!=0) - ){ - sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", - pTab->zName); - } - return 0; -} -static int tabIsReadOnly(Parse *pParse, Table *pTab){ - sqlite3 *db; - if( IsVirtual(pTab) ){ - return vtabIsReadOnly(pParse, pTab); - } - if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; - db = pParse->db; - if( (pTab->tabFlags & TF_Readonly)!=0 ){ - return sqlite3WritableSchema(db)==0 && pParse->nested==0; - } - assert( pTab->tabFlags & TF_Shadow ); - return sqlite3ReadOnlyShadowTables(db); -} - -/* -** Check to make sure the given table is writable. -** -** If pTab is not writable -> generate an error message and return 1. -** If pTab is writable but other errors have occurred -> return 1. -** If pTab is writable and no prior errors -> return 0; -*/ -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, Trigger *pTrigger){ - if( tabIsReadOnly(pParse, pTab) ){ - sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); - return 1; - } -#ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) - && (pTrigger==0 || (pTrigger->bReturning && pTrigger->pNext==0)) - ){ - sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); - return 1; - } -#endif - return 0; -} - - -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) -/* -** Evaluate a view and store its result in an ephemeral table. The -** pWhere argument is an optional WHERE clause that restricts the -** set of rows in the view that are to be added to the ephemeral table. -*/ -SQLITE_PRIVATE void sqlite3MaterializeView( - Parse *pParse, /* Parsing context */ - Table *pView, /* View definition */ - Expr *pWhere, /* Optional WHERE clause to be added */ - ExprList *pOrderBy, /* Optional ORDER BY clause */ - Expr *pLimit, /* Optional LIMIT clause */ - int iCur /* Cursor number for ephemeral table */ -){ - SelectDest dest; - Select *pSel; - SrcList *pFrom; - sqlite3 *db = pParse->db; - int iDb = sqlite3SchemaToIndex(db, pView->pSchema); - pWhere = sqlite3ExprDup(db, pWhere, 0); - pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pFrom ){ - assert( pFrom->nSrc==1 ); - pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 ); - pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); - assert( pFrom->a[0].fg.isUsing==0 ); - assert( pFrom->a[0].u3.pOn==0 ); - } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, - SF_IncludeHidden, pLimit); - sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); - sqlite3Select(pParse, pSel, &dest); - sqlite3SelectDelete(db, pSel); -} -#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ - -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) -/* -** Generate an expression tree to implement the WHERE, ORDER BY, -** and LIMIT/OFFSET portion of DELETE and UPDATE statements. -** -** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1; -** \__________________________/ -** pLimitWhere (pInClause) -*/ -SQLITE_PRIVATE Expr *sqlite3LimitWhere( - Parse *pParse, /* The parser context */ - SrcList *pSrc, /* the FROM clause -- which tables to scan */ - Expr *pWhere, /* The WHERE clause. May be null */ - ExprList *pOrderBy, /* The ORDER BY clause. May be null */ - Expr *pLimit, /* The LIMIT clause. May be null */ - char *zStmtType /* Either DELETE or UPDATE. For err msgs. */ -){ - sqlite3 *db = pParse->db; - Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ - Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - ExprList *pEList = NULL; /* Expression list containing only pSelectRowid*/ - SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ - Select *pSelect = NULL; /* Complete SELECT tree */ - Table *pTab; - - /* Check that there isn't an ORDER BY without a LIMIT clause. - */ - if( pOrderBy && pLimit==0 ) { - sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); - sqlite3ExprDelete(pParse->db, pWhere); - sqlite3ExprListDelete(pParse->db, pOrderBy); - return 0; - } - - /* We only need to generate a select expression if there - ** is a limit/offset term to enforce. - */ - if( pLimit == 0 ) { - return pWhere; - } - - /* Generate a select expression tree to enforce the limit/offset - ** term for the DELETE or UPDATE statement. For example: - ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 - ** becomes: - ** DELETE FROM table_a WHERE rowid IN ( - ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 - ** ); - */ - - pTab = pSrc->a[0].pSTab; - if( HasRowid(pTab) ){ - pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0); - pEList = sqlite3ExprListAppend( - pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0) - ); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->nKeyCol>=1 ); - if( pPk->nKeyCol==1 ){ - const char *zName; - assert( pPk->aiColumn[0]>=0 && pPk->aiColumn[0]nCol ); - zName = pTab->aCol[pPk->aiColumn[0]].zCnName; - pLhs = sqlite3Expr(db, TK_ID, zName); - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName)); - }else{ - int i; - for(i=0; inKeyCol; i++){ - Expr *p; - assert( pPk->aiColumn[i]>=0 && pPk->aiColumn[i]nCol ); - p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); - pEList = sqlite3ExprListAppend(pParse, pEList, p); - } - pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( pLhs ){ - pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); - } - } - } - - /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree - ** and the SELECT subtree. */ - pSrc->a[0].pSTab = 0; - pSelectSrc = sqlite3SrcListDup(db, pSrc, 0); - pSrc->a[0].pSTab = pTab; - 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; - 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 = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, - pOrderBy,0,pLimit - ); - - /* now generate the new WHERE rowid IN clause for the DELETE/UPDATE */ - pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); - sqlite3PExprAddSelect(pParse, pInClause, pSelect); - return pInClause; -} -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ - /* && !defined(SQLITE_OMIT_SUBQUERY) */ - -/* -** Generate code for a DELETE FROM statement. -** -** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; -** \________/ \________________/ -** pTabList pWhere -*/ -SQLITE_PRIVATE void sqlite3DeleteFrom( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* The table from which we should delete things */ - Expr *pWhere, /* The WHERE clause. May be null */ - ExprList *pOrderBy, /* ORDER BY clause. May be null */ - Expr *pLimit /* LIMIT clause. May be null */ -){ - Vdbe *v; /* The virtual database engine */ - Table *pTab; /* The table from which records will be deleted */ - int i; /* Loop counter */ - WhereInfo *pWInfo; /* Information about the WHERE clause */ - Index *pIdx; /* For looping over indices of the table */ - int iTabCur; /* Cursor number for the table */ - int iDataCur = 0; /* VDBE cursor for the canonical data source */ - int iIdxCur = 0; /* Cursor number of the first index */ - int nIdx; /* Number of indices */ - sqlite3 *db; /* Main database structure */ - AuthContext sContext; /* Authorization context */ - NameContext sNC; /* Name context to resolve expressions in */ - int iDb; /* Database number */ - int memCnt = 0; /* Memory cell used for change counting */ - int rcauth; /* Value returned by authorization callback */ - int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ - int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ - u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ - Index *pPk; /* The PRIMARY KEY index on the table */ - int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */ - i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ - int iKey; /* Memory cell holding key of row to be deleted */ - i16 nKey; /* Number of memory cells in the row key */ - int iEphCur = 0; /* Ephemeral table holding all primary key values */ - int iRowSet = 0; /* Register for rowset of rows to delete */ - int addrBypass = 0; /* Address of jump over the delete logic */ - int addrLoop = 0; /* Top of the delete loop */ - int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ - int bComplex; /* True if there are triggers or FKs or - ** subqueries in the WHERE clause */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True if attempting to delete from a view */ - Trigger *pTrigger; /* List of table triggers, if required */ -#endif - - memset(&sContext, 0, sizeof(sContext)); - db = pParse->db; - 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 - ** an SrcList* parameter instead of just a Table* parameter. - */ - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ) goto delete_from_cleanup; - - /* Figure out if we have any triggers and if the table being - ** deleted from is a view - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - isView = IsView(pTab); -#else -# define pTrigger 0 -# define isView 0 -#endif - bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__); - sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere, - pOrderBy, pLimit, pTrigger); - } -#endif - -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( !isView ){ - pWhere = sqlite3LimitWhere( - pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE" - ); - pOrderBy = 0; - pLimit = 0; - } -#endif - - /* If pTab is really a view, make sure it has been initialized. - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto delete_from_cleanup; - } - - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ - goto delete_from_cleanup; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDbnDb ); - rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, - db->aDb[iDb].zDbSName); - assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); - if( rcauth==SQLITE_DENY ){ - goto delete_from_cleanup; - } - assert(!isView || pTrigger); - - /* Assign cursor numbers to the table and all its indices. - */ - assert( pTabList->nSrc==1 ); - iTabCur = pTabList->a[0].iCursor = pParse->nTab++; - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ - pParse->nTab++; - } - - /* Start the view context - */ - if( isView ){ - sqlite3AuthContextPush(pParse, &sContext, pTab->zName); - } - - /* Begin generating code. - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ){ - goto delete_from_cleanup; - } - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, bComplex, iDb); - - /* If we are trying to delete from a view, realize that view into - ** an ephemeral table. - */ -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) - if( isView ){ - sqlite3MaterializeView(pParse, pTab, - pWhere, pOrderBy, pLimit, iTabCur - ); - iDataCur = iIdxCur = iTabCur; - pOrderBy = 0; - pLimit = 0; - } -#endif - - /* Resolve the column names in the WHERE clause. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - if( sqlite3ResolveExprNames(&sNC, pWhere) ){ - goto delete_from_cleanup; - } - - /* Initialize the counter of the number of rows deleted, if - ** we are counting rows. - */ - if( (db->flags & SQLITE_CountRows)!=0 - && !pParse->nested - && !pParse->pTriggerTab - && !pParse->bReturning - ){ - memCnt = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); - } - -#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - /* Special case: A DELETE without a WHERE clause deletes everything. - ** It is easier just to erase the whole table. Prior to version 3.6.5, - ** this optimization caused the row change count (the value returned by - ** API function sqlite3_count_changes) to be set incorrectly. - ** - ** The "rcauth==SQLITE_OK" terms is the - ** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and - ** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but - ** the truncate optimization is disabled and all rows are deleted - ** individually. - */ - if( rcauth==SQLITE_OK - && pWhere==0 - && !bComplex - && !IsVirtual(pTab) -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - && db->xPreUpdateCallback==0 -#endif - ){ - assert( !isView ); - sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, - pTab->zName, P4_STATIC); - } - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->pSchema==pTab->pSchema ); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1); - }else{ - sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); - } - } - }else -#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ - { - u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; - if( sNC.ncFlags & NC_Subquery ) bComplex = 1; - wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); - if( HasRowid(pTab) ){ - /* For a rowid table, initialize the RowSet to an empty set */ - pPk = 0; - assert( nPk==1 ); - iRowSet = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); - }else{ - /* For a WITHOUT ROWID table, create an ephemeral table used to - ** hold all primary keys for rows to be deleted. */ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - nPk = pPk->nKeyCol; - iPk = pParse->nMem+1; - pParse->nMem += nPk; - iEphCur = pParse->nTab++; - addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk); - sqlite3VdbeSetP4KeyInfo(pParse, pPk); - } - - /* Construct a query to find the rowid or primary key for every row - ** to be deleted, based on the WHERE clause. Set variable eOnePass - ** to indicate the strategy used to implement this delete: - ** - ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. - ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. - ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. - */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1); - if( pWInfo==0 ) goto delete_from_cleanup; - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); - assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF - || OptimizationDisabled(db, SQLITE_OnePass) ); - if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); - if( sqlite3WhereUsesDeferredSeek(pWInfo) ){ - sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur); - } - - /* Keep track of the number of rows to be deleted */ - if( memCnt ){ - sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); - } - - /* Extract the rowid or primary key for the current row */ - if( pPk ){ - for(i=0; iaiColumn[i]>=0 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, - pPk->aiColumn[i], iPk+i); - } - iKey = iPk; - }else{ - iKey = ++pParse->nMem; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey); - } - - if( eOnePass!=ONEPASS_OFF ){ - /* For ONEPASS, no need to store the rowid/primary-key. There is only - ** one, so just keep it in its register(s) and fall through to the - ** delete code. */ - nKey = nPk; /* OP_Found will use an unpacked key */ - aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); - if( aToOpen==0 ){ - sqlite3WhereEnd(pWInfo); - goto delete_from_cleanup; - } - memset(aToOpen, 1, nIdx+1); - aToOpen[nIdx+1] = 0; - if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; - if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; - if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); - addrBypass = sqlite3VdbeMakeLabel(pParse); - }else{ - if( pPk ){ - /* Add the PK key for this row to the temporary table */ - iKey = ++pParse->nMem; - nKey = 0; /* Zero tells OP_Found to use a composite key */ - sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, - sqlite3IndexAffinityStr(pParse->db, pPk), nPk); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); - }else{ - /* Add the rowid of the row to be deleted to the RowSet */ - nKey = 1; /* OP_DeferredSeek always uses a single rowid */ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); - } - sqlite3WhereEnd(pWInfo); - } - - /* Unless this is a view, open cursors for the table we are - ** deleting from and all its indices. If this is a view, then the - ** only effect this statement has is to fire the INSTEAD OF - ** triggers. - */ - if( !isView ){ - int iAddrOnce = 0; - if( eOnePass==ONEPASS_MULTI ){ - iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - testcase( IsVirtual(pTab) ); - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, - iTabCur, aToOpen, &iDataCur, &iIdxCur); - assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); - assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); - if( eOnePass==ONEPASS_MULTI ){ - sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce); - } - } - - /* Set up a loop over the rowids/primary-keys that were found in the - ** where-clause loop above. - */ - if( eOnePass!=ONEPASS_OFF ){ - assert( nKey==nPk ); /* OP_Found will use an unpacked key */ - if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ - assert( pPk!=0 || IsView(pTab) ); - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); - VdbeCoverage(v); - } - }else if( pPk ){ - addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey); - }else{ - sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); - } - assert( nKey==0 ); /* OP_Found will use a composite key */ - }else{ - addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); - VdbeCoverage(v); - assert( nKey==1 ); - } - - /* Delete the row */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - sqlite3VtabMakeWritable(pParse, pTab); - assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); - sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE ){ - sqlite3VdbeAddOp1(v, OP_Close, iTabCur); - if( sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; - } - } - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, OE_Abort); - }else -#endif - { - int count = (pParse->nested==0); /* True to count changes */ - sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); - } - - /* End of the loop over all rowids/primary-keys. */ - if( eOnePass!=ONEPASS_OFF ){ - sqlite3VdbeResolveLabel(v, addrBypass); - sqlite3WhereEnd(pWInfo); - }else if( pPk ){ - sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrLoop); - }else{ - sqlite3VdbeGoto(v, addrLoop); - sqlite3VdbeJumpHere(v, addrLoop); - } - } /* End non-truncate path */ - - /* Update the sqlite_sequence table by storing the content of the - ** maximum rowid counter values recorded while inserting into - ** autoincrement tables. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* Return the number of rows that were deleted. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. - */ - if( memCnt ){ - sqlite3CodeChangeCount(v, memCnt, "rows deleted"); - } - -delete_from_cleanup: - sqlite3AuthContextPop(&sContext); - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprDelete(db, pWhere); -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) - sqlite3ExprListDelete(db, pOrderBy); - sqlite3ExprDelete(db, pLimit); -#endif - if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen); - return; -} -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif - -/* -** This routine generates VDBE code that causes a single row of a -** single table to be deleted. Both the original table entry and -** all indices are removed. -** -** Preconditions: -** -** 1. iDataCur is an open cursor on the btree that is the canonical data -** store for the table. (This will be either the table itself, -** in the case of a rowid table, or the PRIMARY KEY index in the case -** of a WITHOUT ROWID table.) -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number iIdxCur+i for the i-th index. -** -** 3. The primary key for the row to be deleted must be stored in a -** sequence of nPk memory cells starting at iPk. If nPk==0 that means -** that a search record formed from OP_MakeRecord is contained in the -** single memory location iPk. -** -** eMode: -** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or -** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor -** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF -** then this function must seek iDataCur to the entry identified by iPk -** and nPk before reading from it. -** -** If eMode is ONEPASS_MULTI, then this call is being made as part -** of a ONEPASS delete that affects multiple rows. In this case, if -** iIdxNoSeek is a valid cursor number (>=0) and is not the same as -** iDataCur, then its position should be preserved following the delete -** operation. Or, if iIdxNoSeek is not a valid cursor number, the -** position of iDataCur should be preserved instead. -** -** iIdxNoSeek: -** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur, -** then it identifies an index cursor (from within array of cursors -** starting at iIdxCur) that already points to the index entry to be deleted. -** Except, this optimization is disabled if there are BEFORE triggers since -** the trigger body might have moved the cursor. -*/ -SQLITE_PRIVATE void sqlite3GenerateRowDelete( - Parse *pParse, /* Parsing context */ - Table *pTab, /* Table containing the row to be deleted */ - Trigger *pTrigger, /* List of triggers to (potentially) fire */ - int iDataCur, /* Cursor from which column data is extracted */ - int iIdxCur, /* First index cursor */ - int iPk, /* First memory cell containing the PRIMARY KEY */ - i16 nPk, /* Number of PRIMARY KEY memory cells */ - u8 count, /* If non-zero, increment the row change counter */ - u8 onconf, /* Default ON CONFLICT policy for triggers */ - u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */ - int iIdxNoSeek /* Cursor number of cursor that does not need seeking */ -){ - Vdbe *v = pParse->pVdbe; /* Vdbe */ - int iOld = 0; /* First register in OLD.* array */ - int iLabel; /* Label resolved to end of generated code */ - u8 opSeek; /* Seek opcode */ - - /* Vdbe is guaranteed to have been allocated by this stage. */ - assert( v ); - VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)", - iDataCur, iIdxCur, iPk, (int)nPk)); - - /* Seek cursor iCur to the row to delete. If this row no longer exists - ** (this can happen if a trigger program has already deleted it), do - ** not attempt to delete it or fire any DELETE triggers. */ - iLabel = sqlite3VdbeMakeLabel(pParse); - opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - if( eMode==ONEPASS_OFF ){ - sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); - VdbeCoverageIf(v, opSeek==OP_NotExists); - VdbeCoverageIf(v, opSeek==OP_NotFound); - } - - /* If there are any triggers to fire, allocate a range of registers to - ** use for the old.* references in the triggers. */ - if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){ - u32 mask; /* Mask of OLD.* columns in use */ - int iCol; /* Iterator used while populating OLD.* */ - int addrStart; /* Start of BEFORE trigger programs */ - - /* TODO: Could use temporary registers here. Also could attempt to - ** avoid copying the contents of the rowid register. */ - mask = sqlite3TriggerColmask( - pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf - ); - mask |= sqlite3FkOldmask(pParse, pTab); - iOld = pParse->nMem+1; - pParse->nMem += (1 + pTab->nCol); - - /* Populate the OLD.* pseudo-table register array. These values will be - ** used by any BEFORE and AFTER triggers that exist. */ - sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld); - for(iCol=0; iColnCol; iCol++){ - testcase( mask!=0xffffffff && iCol==31 ); - testcase( mask!=0xffffffff && iCol==32 ); - if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){ - int kk = sqlite3TableColumnToStorage(pTab, iCol); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1); - } - } - - /* Invoke BEFORE DELETE trigger programs. */ - addrStart = sqlite3VdbeCurrentAddr(v); - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel - ); - - /* If any BEFORE triggers were coded, then seek the cursor to the - ** row to be deleted again. It may be that the BEFORE triggers moved - ** the cursor or already deleted the row that the cursor was - ** pointing to. - ** - ** Also disable the iIdxNoSeek optimization since the BEFORE trigger - ** may have moved that cursor. - */ - if( addrStart=0 ); - iIdxNoSeek = -1; - } - - /* Do FK processing. This call checks that any FK constraints that - ** refer to this table (i.e. constraints attached to other tables) - ** are not violated by deleting this row. */ - sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); - } - - /* Delete the index and table entries. Skip this step if pTab is really - ** a view (in which case the only effect of the DELETE statement is to - ** fire the INSTEAD OF triggers). - ** - ** If variable 'count' is non-zero, then this OP_Delete instruction should - ** invoke the update-hook. The pre-update-hook, on the other hand should - ** be invoked unless table pTab is a system table. The difference is that - ** the update-hook is not invoked for rows removed by REPLACE, but the - ** pre-update-hook is. - */ - if( !IsView(pTab) ){ - u8 p5 = 0; - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); - sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){ - sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); - } - if( eMode!=ONEPASS_OFF ){ - sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); - } - if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){ - sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - } - if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; - sqlite3VdbeChangeP5(v, p5); - } - - /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to - ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just deleted. */ - sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); - - /* Invoke AFTER DELETE trigger programs. */ - if( pTrigger ){ - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel - ); - } - - /* Jump here if the row had already been deleted before any BEFORE - ** trigger programs were invoked. Or if a trigger program throws a - ** RAISE(IGNORE) exception. */ - sqlite3VdbeResolveLabel(v, iLabel); - VdbeModuleComment((v, "END: GenRowDel()")); -} - -/* -** This routine generates VDBE code that causes the deletion of all -** index entries associated with a single row of a single table, pTab -** -** Preconditions: -** -** 1. A read/write cursor "iDataCur" must be open on the canonical storage -** btree for the table pTab. (This will be either the table itself -** for rowid tables or to the primary key index for WITHOUT ROWID -** tables.) -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex -** index is the 0-th index.) -** -** 3. The "iDataCur" cursor must be already be positioned on the row -** that is to be deleted. -*/ -SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* Table containing the row to be deleted */ - int iDataCur, /* Cursor of table holding data. */ - int iIdxCur, /* First index cursor */ - int *aRegIdx, /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ - int iIdxNoSeek /* Do not delete from this cursor */ -){ - int i; /* Index loop counter */ - int r1 = -1; /* Register holding an index key */ - int iPartIdxLabel; /* Jump destination for skipping partial index entries */ - Index *pIdx; /* Current index */ - Index *pPrior = 0; /* Prior index */ - Vdbe *v; /* The prepared statement under construction */ - Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */ - - v = pParse->pVdbe; - pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); - for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - assert( iIdxCur+i!=iDataCur || pPk==pIdx ); - if( aRegIdx!=0 && aRegIdx[i]==0 ) continue; - if( pIdx==pPk ) continue; - if( iIdxCur+i==iIdxNoSeek ) continue; - VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, - &iPartIdxLabel, pPrior, r1); - sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, - pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); - sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */ - sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); - pPrior = pIdx; - } -} - -/* -** Generate code that will assemble an index key and stores it in register -** regOut. The key with be for index pIdx which is an index on pTab. -** iCur is the index of a cursor open on the pTab table and pointing to -** the entry that needs indexing. If pTab is a WITHOUT ROWID table, then -** iCur must be the cursor of the PRIMARY KEY index. -** -** Return a register number which is the first in a block of -** registers that holds the elements of the index key. The -** block of registers has already been deallocated by the time -** this routine returns. -** -** If *piPartIdxLabel is not NULL, fill it in with a label and jump -** to that label if pIdx is a partial index that should be skipped. -** The label should be resolved using sqlite3ResolvePartIdxLabel(). -** A partial index should be skipped if its WHERE clause evaluates -** to false or null. If pIdx is not a partial index, *piPartIdxLabel -** will be set to zero which is an empty label that is ignored by -** sqlite3ResolvePartIdxLabel(). -** -** The pPrior and regPrior parameters are used to implement a cache to -** avoid unnecessary register loads. If pPrior is not NULL, then it is -** a pointer to a different index for which an index key has just been -** computed into register regPrior. If the current pIdx index is generating -** its key into the same sequence of registers and if pPrior and pIdx share -** a column in common, then the register corresponding to that column already -** holds the correct value and the loading of that register is skipped. -** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK -** on a table with multiple indices, and especially with the ROWID or -** PRIMARY KEY columns of the index. -*/ -SQLITE_PRIVATE int sqlite3GenerateIndexKey( - Parse *pParse, /* Parsing context */ - Index *pIdx, /* The index for which to generate a key */ - int iDataCur, /* Cursor number from which to take column data */ - int regOut, /* Put the new key into this register if not 0 */ - int prefixOnly, /* Compute only a unique prefix of the key */ - int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */ - Index *pPrior, /* Previously generated index key */ - int regPrior /* Register holding previous generated key */ -){ - Vdbe *v = pParse->pVdbe; - int j; - int regBase; - int nCol; - - if( piPartIdxLabel ){ - if( pIdx->pPartIdxWhere ){ - *piPartIdxLabel = sqlite3VdbeMakeLabel(pParse); - pParse->iSelfTab = iDataCur + 1; - sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, - SQLITE_JUMPIFNULL); - pParse->iSelfTab = 0; - pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02; - ** pPartIdxWhere may have corrupted regPrior registers */ - }else{ - *piPartIdxLabel = 0; - } - } - nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn; - regBase = sqlite3GetTempRange(pParse, nCol); - if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; - for(j=0; jaiColumn[j]==pIdx->aiColumn[j] - && pPrior->aiColumn[j]!=XN_EXPR - ){ - /* This column was already computed by the previous index */ - continue; - } - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); - 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 */ - sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); - } - } - if( regOut ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); - } - sqlite3ReleaseTempRange(pParse, regBase, nCol); - return regBase; -} - -/* -** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label -** because it was a partial index, then this routine should be called to -** resolve that label. -*/ -SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ - if( iLabel ){ - sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); - } -} - -/************** End of delete.c **********************************************/ -/************** Begin file func.c ********************************************/ -/* -** 2002 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C-language implementations for many of the SQL -** functions of SQLite. (Some function, and in particular the date and -** time functions, are implemented separately.) -*/ -/* #include "sqliteInt.h" */ -/* #include */ -/* #include */ -#ifndef SQLITE_OMIT_FLOATING_POINT -/* #include */ -#endif -/* #include "vdbeInt.h" */ - -/* -** Return the collating function associated with a function. -*/ -static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ - VdbeOp *pOp; - assert( context->pVdbe!=0 ); - pOp = &context->pVdbe->aOp[context->iOp-1]; - assert( pOp->opcode==OP_CollSeq ); - assert( pOp->p4type==P4_COLLSEQ ); - return pOp->p4.pColl; -} - -/* -** Indicate that the accumulator load should be skipped on this -** iteration of the aggregate loop. -*/ -static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ - assert( context->isError<=0 ); - context->isError = -1; - context->skipFlag = 1; -} - -/* -** Implementation of the non-aggregate min() and max() functions -*/ -static void minmaxFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int i; - int mask; /* 0 for min() or 0xffffffff for max() */ - int iBest; - CollSeq *pColl; - - assert( argc>1 ); - mask = sqlite3_user_data(context)==0 ? 0 : -1; - pColl = sqlite3GetFuncCollSeq(context); - assert( pColl ); - assert( mask==-1 || mask==0 ); - iBest = 0; - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - for(i=1; i=0 ){ - testcase( mask==0 ); - iBest = i; - } - } - sqlite3_result_value(context, argv[iBest]); -} - -/* -** Return the type of the argument. -*/ -static void typeofFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - static const char *azType[] = { "integer", "real", "text", "blob", "null" }; - int i = sqlite3_value_type(argv[0]) - 1; - UNUSED_PARAMETER(NotUsed); - assert( i>=0 && i=0xc0 ){ - while( (*z & 0xc0)==0x80 ){ z++; z0++; } - } - } - sqlite3_result_int(context, (int)(z-z0)); - break; - } - default: { - sqlite3_result_null(context); - break; - } - } -} - -/* -** Implementation of the octet_length() function -*/ -static void bytelengthFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_BLOB: { - sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); - break; - } - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - i64 m = sqlite3_context_db_handle(context)->enc<=SQLITE_UTF8 ? 1 : 2; - sqlite3_result_int64(context, sqlite3_value_bytes(argv[0])*m); - break; - } - case SQLITE_TEXT: { - if( sqlite3_value_encoding(argv[0])<=SQLITE_UTF8 ){ - sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); - }else{ - sqlite3_result_int(context, sqlite3_value_bytes16(argv[0])); - } - break; - } - default: { - sqlite3_result_null(context); - break; - } - } -} - -/* -** Implementation of the abs() function. -** -** IMP: R-23979-26855 The abs(X) function returns the absolute value of -** the numeric argument X. -*/ -static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_INTEGER: { - i64 iVal = sqlite3_value_int64(argv[0]); - if( iVal<0 ){ - if( iVal==SMALLEST_INT64 ){ - /* IMP: R-31676-45509 If X is the integer -9223372036854775808 - ** then abs(X) throws an integer overflow error since there is no - ** equivalent positive 64-bit two complement value. */ - sqlite3_result_error(context, "integer overflow", -1); - return; - } - iVal = -iVal; - } - sqlite3_result_int64(context, iVal); - break; - } - case SQLITE_NULL: { - /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ - sqlite3_result_null(context); - break; - } - default: { - /* Because sqlite3_value_double() returns 0.0 if the argument is not - ** something that can be converted into a number, we have: - ** IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob - ** that cannot be converted to a numeric value. - */ - double rVal = sqlite3_value_double(argv[0]); - if( rVal<0 ) rVal = -rVal; - sqlite3_result_double(context, rVal); - break; - } - } -} - -/* -** Implementation of the instr() function. -** -** instr(haystack,needle) finds the first occurrence of needle -** in haystack and returns the number of previous characters plus 1, -** or 0 if needle does not occur within haystack. -** -** If both haystack and needle are BLOBs, then the result is one more than -** the number of bytes in haystack prior to the first occurrence of needle, -** or 0 if needle never occurs in haystack. -*/ -static void instrFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zHaystack; - const unsigned char *zNeedle; - int nHaystack; - int nNeedle; - int typeHaystack, typeNeedle; - int N = 1; - int isText; - unsigned char firstChar; - sqlite3_value *pC1 = 0; - sqlite3_value *pC2 = 0; - - UNUSED_PARAMETER(argc); - typeHaystack = sqlite3_value_type(argv[0]); - typeNeedle = sqlite3_value_type(argv[1]); - if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; - nHaystack = sqlite3_value_bytes(argv[0]); - nNeedle = sqlite3_value_bytes(argv[1]); - if( nNeedle>0 ){ - if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ - zHaystack = sqlite3_value_blob(argv[0]); - zNeedle = sqlite3_value_blob(argv[1]); - isText = 0; - }else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){ - zHaystack = sqlite3_value_text(argv[0]); - zNeedle = sqlite3_value_text(argv[1]); - isText = 1; - }else{ - pC1 = sqlite3_value_dup(argv[0]); - zHaystack = sqlite3_value_text(pC1); - if( zHaystack==0 ) goto endInstrOOM; - nHaystack = sqlite3_value_bytes(pC1); - pC2 = sqlite3_value_dup(argv[1]); - zNeedle = sqlite3_value_text(pC2); - if( zNeedle==0 ) goto endInstrOOM; - nNeedle = sqlite3_value_bytes(pC2); - isText = 1; - } - if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM; - firstChar = zNeedle[0]; - while( nNeedle<=nHaystack - && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0) - ){ - N++; - do{ - nHaystack--; - zHaystack++; - }while( isText && (zHaystack[0]&0xc0)==0x80 ); - } - if( nNeedle>nHaystack ) N = 0; - } - sqlite3_result_int(context, N); -endInstr: - sqlite3_value_free(pC1); - sqlite3_value_free(pC2); - return; -endInstrOOM: - sqlite3_result_error_nomem(context); - goto endInstr; -} - -/* -** Implementation of the printf() (a.k.a. format()) SQL function. -*/ -static void printfFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - PrintfArguments x; - StrAccum str; - const char *zFormat; - int n; - sqlite3 *db = sqlite3_context_db_handle(context); - - if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ - x.nArg = argc-1; - x.nUsed = 0; - x.apArg = argv+1; - sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - str.printfFlags = SQLITE_PRINTF_SQLFUNC; - sqlite3_str_appendf(&str, zFormat, &x); - n = str.nChar; - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, - SQLITE_DYNAMIC); - } -} - -/* -** Implementation of the substr() function. -** -** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. -** p1 is 1-indexed. So substr(x,1,1) returns the first character -** of x. If x is text, then we actually count UTF-8 characters. -** If x is a blob, then we count bytes. -** -** If p1 is negative, then we begin abs(p1) from the end of x[]. -** -** If p2 is negative, return the p2 characters preceding p1. -*/ -static void substrFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *z; - const unsigned char *z2; - int len; - int p0type; - i64 p1, p2; - - assert( argc==3 || argc==2 ); - p0type = sqlite3_value_type(argv[0]); - p1 = sqlite3_value_int64(argv[1]); - if( p0type==SQLITE_BLOB ){ - len = sqlite3_value_bytes(argv[0]); - z = sqlite3_value_blob(argv[0]); - if( z==0 ) return; - assert( len==sqlite3_value_bytes(argv[0]) ); - }else{ - z = sqlite3_value_text(argv[0]); - if( z==0 ) return; - len = 0; - if( p1<0 ){ - for(z2=z; *z2; len++){ - SQLITE_SKIP_UTF8(z2); - } - } - } - if( argc==3 ){ - p2 = sqlite3_value_int64(argv[2]); - if( p2==0 && sqlite3_value_type(argv[2])==SQLITE_NULL ) return; - }else{ - p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; - } - if( p1==0 ){ -#ifdef SQLITE_SUBSTR_COMPATIBILITY - /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as - ** as substr(X,1,N) - it returns the first N characters of X. This - ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] - ** from 2009-02-02 for compatibility of applications that exploited the - ** old buggy behavior. */ - p1 = 1; /* */ -#endif - if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return; - } - if( p1<0 ){ - p1 += len; - if( p1<0 ){ - if( p2<0 ){ - p2 = 0; - }else{ - p2 += p1; - } - p1 = 0; - } - }else if( p1>0 ){ - p1--; - }else if( p2>0 ){ - p2--; - } - if( p2<0 ){ - if( p2<-p1 ){ - p2 = p1; - }else{ - p2 = -p2; - } - p1 -= p2; - } - assert( p1>=0 && p2>=0 ); - if( p0type!=SQLITE_BLOB ){ - while( *z && p1 ){ - SQLITE_SKIP_UTF8(z); - p1--; - } - for(z2=z; *z2 && p2; p2--){ - SQLITE_SKIP_UTF8(z2); - } - sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT, - SQLITE_UTF8); - }else{ - if( p1>=len ){ - p1 = p2 = 0; - }else if( p2>len-p1 ){ - p2 = len-p1; - assert( p2>0 ); - } - sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT); - } -} - -/* -** Implementation of the round() function -*/ -#ifndef SQLITE_OMIT_FLOATING_POINT -static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - i64 n = 0; - double r; - char *zBuf; - assert( argc==1 || argc==2 ); - if( argc==2 ){ - if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; - n = sqlite3_value_int64(argv[1]); - if( n>30 ) n = 30; - if( n<0 ) n = 0; - } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - r = sqlite3_value_double(argv[0]); - /* If Y==0 and X will fit in a 64-bit int, - ** handle the rounding directly, - ** otherwise use printf. - */ - if( r<-4503599627370496.0 || r>+4503599627370496.0 ){ - /* The value has no fractional part so there is nothing to round */ - }else if( n==0 ){ - r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); - }else{ - zBuf = sqlite3_mprintf("%!.*f",(int)n,r); - if( zBuf==0 ){ - sqlite3_result_error_nomem(context); - return; - } - sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); - sqlite3_free(zBuf); - } - sqlite3_result_double(context, r); -} -#endif - -/* -** Allocate nByte bytes of space using sqlite3Malloc(). If the -** allocation fails, call sqlite3_result_error_nomem() to notify -** the database handle that malloc() has failed and return NULL. -** If nByte is larger than the maximum string or blob length, then -** raise an SQLITE_TOOBIG exception and return NULL. -*/ -static void *contextMalloc(sqlite3_context *context, i64 nByte){ - char *z; - sqlite3 *db = sqlite3_context_db_handle(context); - assert( nByte>0 ); - testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); - if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - z = 0; - }else{ - z = sqlite3Malloc(nByte); - if( !z ){ - sqlite3_result_error_nomem(context); - } - } - return z; -} - -/* -** Implementation of the upper() and lower() SQL functions. -*/ -static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - char *z1; - const char *z2; - int i, n; - UNUSED_PARAMETER(argc); - z2 = (char*)sqlite3_value_text(argv[0]); - n = sqlite3_value_bytes(argv[0]); - /* Verify that the call to _bytes() does not invalidate the _text() pointer */ - assert( z2==(char*)sqlite3_value_text(argv[0]) ); - if( z2 ){ - z1 = contextMalloc(context, ((i64)n)+1); - if( z1 ){ - for(i=0; imatchOne; /* "?" or "_" */ - u32 matchAll = pInfo->matchAll; /* "*" or "%" */ - u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ - const u8 *zEscaped = 0; /* One past the last escaped input char */ - - while( (c = Utf8Read(zPattern))!=0 ){ - if( c==matchAll ){ /* Match "*" */ - /* 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 && matchOne!=0) ){ - if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ - return SQLITE_NOWILDCARDMATCH; - } - } - if( c==0 ){ - return SQLITE_MATCH; /* "*" at the end of the pattern matches */ - }else if( c==matchOther ){ - if( pInfo->matchSet==0 ){ - c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return SQLITE_NOWILDCARDMATCH; - }else{ - /* "[...]" immediately follows the "*". We have to do a slow - ** recursive search in this case, but it is an unusual case. */ - assert( matchOther<0x80 ); /* '[' is a single-byte character */ - while( *zString ){ - int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; - SQLITE_SKIP_UTF8(zString); - } - return SQLITE_NOWILDCARDMATCH; - } - } - - /* At this point variable c contains the first character of the - ** pattern string past the "*". Search in the input string for the - ** first matching character and recursively continue the match from - ** that point. - ** - ** For a case-insensitive search, set variable cx to be the same as - ** c but in the other case and search the input string for either - ** c or cx. - */ - if( c<0x80 ){ - char zStop[3]; - int bMatch; - if( noCase ){ - zStop[0] = sqlite3Toupper(c); - zStop[1] = sqlite3Tolower(c); - zStop[2] = 0; - }else{ - zStop[0] = c; - zStop[1] = 0; - } - while(1){ - zString += strcspn((const char*)zString, zStop); - if( zString[0]==0 ) break; - zString++; - bMatch = patternCompare(zPattern,zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; - } - }else{ - int bMatch; - while( (c2 = Utf8Read(zString))!=0 ){ - if( c2!=c ) continue; - bMatch = patternCompare(zPattern,zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; - } - } - return SQLITE_NOWILDCARDMATCH; - } - if( c==matchOther ){ - if( pInfo->matchSet==0 ){ - c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return SQLITE_NOMATCH; - zEscaped = zPattern; - }else{ - u32 prior_c = 0; - int seen = 0; - int invert = 0; - c = sqlite3Utf8Read(&zString); - if( c==0 ) return SQLITE_NOMATCH; - c2 = sqlite3Utf8Read(&zPattern); - if( c2=='^' ){ - invert = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - while( c2 && c2!=']' ){ - if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ - c2 = sqlite3Utf8Read(&zPattern); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else{ - if( c==c2 ){ - seen = 1; - } - prior_c = c2; - } - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==0 || (seen ^ invert)==0 ){ - return SQLITE_NOMATCH; - } - continue; - } - } - c2 = Utf8Read(zString); - if( c==c2 ) continue; - if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){ - continue; - } - if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; - return SQLITE_NOMATCH; - } - return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH; -} - -/* -** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and -** non-zero if there is no match. -*/ -SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ - if( zString==0 ){ - return zGlobPattern!=0; - }else if( zGlobPattern==0 ){ - return 1; - }else { - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); - } -} - -/* -** The sqlite3_strlike() interface. Return 0 on a match and non-zero for -** a miss - like strcmp(). -*/ -SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ - if( zStr==0 ){ - return zPattern!=0; - }else if( zPattern==0 ){ - return 1; - }else{ - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); - } -} - -/* -** Count the number of times that the LIKE operator (or GLOB which is -** just a variation of LIKE) gets called. This is used for testing -** only. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_like_count = 0; -#endif - - -/* -** Implementation of the like() SQL function. This function implements -** the built-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: -** -** A LIKE B -** -** is implemented as like(B,A). -** -** This same function (with a different compareInfo structure) computes -** the GLOB operator. -*/ -static void likeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zA, *zB; - u32 escape; - int nPat; - sqlite3 *db = sqlite3_context_db_handle(context); - struct compareInfo *pInfo = sqlite3_user_data(context); - struct compareInfo backupInfo; - -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( sqlite3_value_type(argv[0])==SQLITE_BLOB - || sqlite3_value_type(argv[1])==SQLITE_BLOB - ){ -#ifdef SQLITE_TEST - sqlite3_like_count++; -#endif - sqlite3_result_int(context, 0); - return; - } -#endif - - /* Limit the length of the LIKE or GLOB pattern to avoid problems - ** of deep recursion and N*N behavior in patternCompare(). - */ - nPat = sqlite3_value_bytes(argv[0]); - testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ); - testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 ); - if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){ - sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); - return; - } - if( argc==3 ){ - /* The escape character string must consist of a single UTF-8 character. - ** Otherwise, return an error. - */ - const unsigned char *zEsc = sqlite3_value_text(argv[2]); - if( zEsc==0 ) return; - if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ - sqlite3_result_error(context, - "ESCAPE expression must be a single character", -1); - return; - } - escape = sqlite3Utf8Read(&zEsc); - if( escape==pInfo->matchAll || escape==pInfo->matchOne ){ - memcpy(&backupInfo, pInfo, sizeof(backupInfo)); - pInfo = &backupInfo; - if( escape==pInfo->matchAll ) pInfo->matchAll = 0; - if( escape==pInfo->matchOne ) pInfo->matchOne = 0; - } - }else{ - escape = pInfo->matchSet; - } - zB = sqlite3_value_text(argv[0]); - zA = sqlite3_value_text(argv[1]); - if( zA && zB ){ -#ifdef SQLITE_TEST - sqlite3_like_count++; -#endif - sqlite3_result_int(context, - patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); - } -} - -/* -** Implementation of the NULLIF(x,y) function. The result is the first -** argument if the arguments are different. The result is NULL if the -** arguments are equal to each other. -*/ -static void nullifFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - CollSeq *pColl = sqlite3GetFuncCollSeq(context); - UNUSED_PARAMETER(NotUsed); - if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ - sqlite3_result_value(context, argv[0]); - } -} - -/* -** Implementation of the sqlite_version() function. The result is the version -** of the SQLite library that is running. -*/ -static void versionFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **NotUsed2 -){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - /* IMP: R-48699-48617 This function is an SQL wrapper around the - ** sqlite3_libversion() C-interface. */ - sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); -} - -/* -** Implementation of the sqlite_source_id() function. The result is a string -** that identifies the particular version of the source code used to build -** SQLite. -*/ -static void sourceidFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **NotUsed2 -){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - /* IMP: R-24470-31136 This function is an SQL wrapper around the - ** sqlite3_sourceid() C interface. */ - sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); -} - -/* -** Implementation of the sqlite_log() function. This is a wrapper around -** sqlite3_log(). The return value is NULL. The function exists purely for -** its side-effects. -*/ -static void errlogFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(context); - sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1])); -} - -/* -** Implementation of the sqlite_compileoption_used() function. -** The result is an integer that identifies if the compiler option -** was used to build SQLite. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -static void compileoptionusedFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zOptName; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL - ** function is a wrapper around the sqlite3_compileoption_used() C/C++ - ** function. - */ - if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ - sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); - } -} -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/* -** Implementation of the sqlite_compileoption_get() function. -** The result is a string that identifies the compiler options -** used to build SQLite. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -static void compileoptiongetFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int n; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function - ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. - */ - n = sqlite3_value_int(argv[0]); - sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); -} -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/* Array for converting from half-bytes (nybbles) into ASCII hex -** digits. */ -static const char hexdigits[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/* -** Append to pStr text that is the SQL literal representation of the -** value contained in pValue. -*/ -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){ - /* 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( sqlite3_value_type(pValue) ){ - case SQLITE_FLOAT: { - double r1, r2; - const char *zVal; - r1 = sqlite3_value_double(pValue); - sqlite3_str_appendf(pStr, "%!0.15g", r1); - zVal = sqlite3_str_value(pStr); - if( zVal ){ - sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); - if( r1!=r2 ){ - sqlite3_str_reset(pStr); - sqlite3_str_appendf(pStr, "%!0.20e", r1); - } - } - break; - } - case SQLITE_INTEGER: { - sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue)); - break; - } - case SQLITE_BLOB: { - char const *zBlob = sqlite3_value_blob(pValue); - i64 nBlob = sqlite3_value_bytes(pValue); - assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */ - sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4); - if( pStr->accError==0 ){ - char *zText = pStr->zText; - int i; - for(i=0; i>4)&0x0F]; - zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; - } - zText[(nBlob*2)+2] = '\''; - zText[(nBlob*2)+3] = '\0'; - zText[0] = 'X'; - zText[1] = '\''; - pStr->nChar = nBlob*2 + 3; - } - break; - } - case SQLITE_TEXT: { - const unsigned char *zArg = sqlite3_value_text(pValue); - sqlite3_str_appendf(pStr, bEscape ? "%#Q" : "%Q", zArg); - break; - } - default: { - assert( sqlite3_value_type(pValue)==SQLITE_NULL ); - sqlite3_str_append(pStr, "NULL", 4); - break; - } - } -} - -/* -** Return true if z[] begins with N hexadecimal digits, and write -** a decoding of those digits into *pVal. Or return false if any -** one of the first N characters in z[] is not a hexadecimal digit. -*/ -static int isNHex(const char *z, int N, u32 *pVal){ - int i; - int v = 0; - for(i=0; i0 ){ - memmove(&zOut[j], &zIn[i], n); - j += n; - i += n; - } - if( zIn[i+1]=='\\' ){ - i += 2; - zOut[j++] = '\\'; - }else if( sqlite3Isxdigit(zIn[i+1]) ){ - if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error; - i += 5; - j += sqlite3AppendOneUtf8Character(&zOut[j], v); - }else if( zIn[i+1]=='+' ){ - if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error; - i += 8; - j += sqlite3AppendOneUtf8Character(&zOut[j], v); - }else if( zIn[i+1]=='u' ){ - if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error; - i += 6; - j += sqlite3AppendOneUtf8Character(&zOut[j], v); - }else if( zIn[i+1]=='U' ){ - if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error; - i += 10; - j += sqlite3AppendOneUtf8Character(&zOut[j], v); - }else{ - goto unistr_error; - } - } - zOut[j] = 0; - sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8); - return; - -unistr_error: - sqlite3_free(zOut); - sqlite3_result_error(context, "invalid Unicode escape", -1); - return; -} - - -/* -** 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. -** -** If sqlite3_user_data() is non-zero, then the UNISTR_QUOTE() function is -** implemented instead. The difference is that UNISTR_QUOTE() uses the -** UNISTR() function to escape control characters. -*/ -static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - sqlite3_str str; - sqlite3 *db = sqlite3_context_db_handle(context); - assert( argc==1 ); - UNUSED_PARAMETER(argc); - sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context))); - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, - SQLITE_DYNAMIC); - if( str.accError!=SQLITE_OK ){ - sqlite3_result_null(context); - 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. -*/ -static void unicodeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *z = sqlite3_value_text(argv[0]); - (void)argc; - if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z)); -} - -/* -** The char() function takes zero or more arguments, each of which is -** an integer. It constructs a string where each character of the string -** is the unicode character for the corresponding integer argument. -*/ -static void charFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - unsigned char *z, *zOut; - int i; - zOut = z = sqlite3_malloc64( argc*4+1 ); - if( z==0 ){ - sqlite3_result_error_nomem(context); - return; - } - for(i=0; i0x10ffff ) x = 0xfffd; - c = (unsigned)(x & 0x1fffff); - if( c<0x00080 ){ - *zOut++ = (u8)(c&0xFF); - }else if( c<0x00800 ){ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - }else if( c<0x10000 ){ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - }else{ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - } \ - } - *zOut = 0; - sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); -} - -/* -** The hex() function. Interpret the argument as a blob. Return -** a hexadecimal rendering as text. -*/ -static void hexFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int i, n; - const unsigned char *pBlob; - char *zHex, *z; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - pBlob = sqlite3_value_blob(argv[0]); - n = sqlite3_value_bytes(argv[0]); - assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - z = zHex = contextMalloc(context, ((i64)n)*2 + 1); - if( zHex ){ - for(i=0; i>4)&0xf]; - *(z++) = hexdigits[c&0xf]; - } - *z = 0; - sqlite3_result_text64(context, zHex, (u64)(z-zHex), - sqlite3_free, SQLITE_UTF8); - } -} - -/* -** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr -** contains character ch, or 0 if it does not. -*/ -static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ - const u8 *zEnd = &zStr[nStr]; - const u8 *z = zStr; - while( zmallocFailed ); - return; - } - if( zPattern[0]==0 ){ - assert( sqlite3_value_type(argv[1])!=SQLITE_NULL ); - sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT); - return; - } - nPattern = sqlite3_value_bytes(argv[1]); - assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ - zRep = sqlite3_value_text(argv[2]); - if( zRep==0 ) return; - nRep = sqlite3_value_bytes(argv[2]); - assert( zRep==sqlite3_value_text(argv[2]) ); - nOut = nStr + 1; - assert( nOutnPattern ){ - nOut += nRep - nPattern; - testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); - if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - sqlite3_free(zOut); - return; - } - cntExpand++; - if( (cntExpand&(cntExpand-1))==0 ){ - /* Grow the size of the output buffer only on substitutions - ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */ - u8 *zOld; - zOld = zOut; - zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1)); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - sqlite3_free(zOld); - return; - } - } - } - memcpy(&zOut[j], zRep, nRep); - j += nRep; - i += nPattern-1; - } - } - assert( j+nStr-i+1<=nOut ); - memcpy(&zOut[j], &zStr[i], nStr-i); - j += nStr - i; - assert( j<=nOut ); - zOut[j] = 0; - sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); -} - -/* -** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. -** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. -*/ -static void trimFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zIn; /* Input string */ - const unsigned char *zCharSet; /* Set of characters to trim */ - unsigned int nIn; /* Number of bytes in input */ - int flags; /* 1: trimleft 2: trimright 3: trim */ - int i; /* Loop counter */ - 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 */ - - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - return; - } - zIn = sqlite3_value_text(argv[0]); - if( zIn==0 ) return; - nIn = (unsigned)sqlite3_value_bytes(argv[0]); - assert( zIn==sqlite3_value_text(argv[0]) ); - if( argc==1 ){ - static const unsigned lenOne[] = { 1 }; - static unsigned char * const azOne[] = { (u8*)" " }; - nChar = 1; - aLen = (unsigned*)lenOne; - azChar = (unsigned char **)azOne; - zCharSet = 0; - }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ - return; - }else{ - const unsigned char *z; - for(z=zCharSet, nChar=0; *z; nChar++){ - SQLITE_SKIP_UTF8(z); - } - if( nChar>0 ){ - azChar = contextMalloc(context, - ((i64)nChar)*(sizeof(char*)+sizeof(unsigned))); - if( azChar==0 ){ - return; - } - aLen = (unsigned*)&azChar[nChar]; - for(z=zCharSet, nChar=0; *z; nChar++){ - azChar[nChar] = (unsigned char *)z; - SQLITE_SKIP_UTF8(z); - aLen[nChar] = (unsigned)(z - azChar[nChar]); - } - } - } - if( nChar>0 ){ - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); - if( flags & 1 ){ - while( nIn>0 ){ - unsigned int len = 0; - for(i=0; i=nChar ) break; - zIn += len; - nIn -= len; - } - } - if( flags & 2 ){ - while( nIn>0 ){ - unsigned int len = 0; - for(i=0; i=nChar ) break; - nIn -= len; - } - } - if( zCharSet ){ - sqlite3_free(azChar); - } - } - sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); -} - -/* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...) -** functions. -** -** Return a string value that is the concatenation of all non-null -** entries in argv[]. Use zSep as the separator. -*/ -static void concatFuncCore( - sqlite3_context *context, - int argc, - sqlite3_value **argv, - int nSep, - const char *zSep -){ - i64 j, n = 0; - int i; - char *z; - for(i=0; i0 && nSep>0 ){ - memcpy(&z[j], zSep, nSep); - j += nSep; - } - memcpy(&z[j], v, k); - j += k; - } - } - } - z[j] = 0; - assert( j<=n ); - sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8); -} - -/* -** The CONCAT(...) function. Generate a string result that is the -** concatentation of all non-null arguments. -*/ -static void concatFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - concatFuncCore(context, argc, argv, 0, ""); -} - -/* -** The CONCAT_WS(separator, ...) function. -** -** Generate a string that is the concatenation of 2nd through the Nth -** argument. Use the first argument (which must be non-NULL) as the -** separator. -*/ -static void concatwsFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int nSep = sqlite3_value_bytes(argv[0]); - const char *zSep = (const char*)sqlite3_value_text(argv[0]); - if( zSep==0 ) return; - concatFuncCore(context, argc-1, argv+1, nSep, zSep); -} - - -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION -/* -** The "unknown" function is automatically substituted in place of -** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN -** when the SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option is used. -** When the "sqlite3" command-line shell is built using this functionality, -** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries -** involving application-defined functions to be examined in a generic -** sqlite3 shell. -*/ -static void unknownFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - /* no-op */ - (void)context; - (void)argc; - (void)argv; -} -#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/ - - -/* IMP: R-25361-16150 This function is omitted from SQLite by default. It -** is only available if the SQLITE_SOUNDEX compile-time option is used -** when SQLite is built. -*/ -#ifdef SQLITE_SOUNDEX -/* -** Compute the soundex encoding of a word. -** -** IMP: R-59782-00072 The soundex(X) function returns a string that is the -** soundex encoding of the string X. -*/ -static void soundexFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - char zResult[8]; - const u8 *zIn; - int i, j; - static const unsigned char iCode[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, - 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, - 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, - }; - assert( argc==1 ); - zIn = (u8*)sqlite3_value_text(argv[0]); - if( zIn==0 ) zIn = (u8*)""; - for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){} - if( zIn[i] ){ - u8 prevcode = iCode[zIn[i]&0x7f]; - zResult[0] = sqlite3Toupper(zIn[i]); - for(j=1; j<4 && zIn[i]; i++){ - int code = iCode[zIn[i]&0x7f]; - if( code>0 ){ - if( code!=prevcode ){ - prevcode = code; - zResult[j++] = code + '0'; - } - }else{ - prevcode = 0; - } - } - while( j<4 ){ - zResult[j++] = '0'; - } - zResult[j] = 0; - sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); - }else{ - /* IMP: R-64894-50321 The string "?000" is returned if the argument - ** is NULL or contains no ASCII alphabetic characters. */ - sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); - } -} -#endif /* SQLITE_SOUNDEX */ - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** A function that loads a shared-library extension then returns NULL. -*/ -static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ - const char *zFile = (const char *)sqlite3_value_text(argv[0]); - const char *zProc; - sqlite3 *db = sqlite3_context_db_handle(context); - char *zErrMsg = 0; - - /* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc - ** flag is set. See the sqlite3_enable_load_extension() API. - */ - if( (db->flags & SQLITE_LoadExtFunc)==0 ){ - sqlite3_result_error(context, "not authorized", -1); - return; - } - - if( argc==2 ){ - zProc = (const char *)sqlite3_value_text(argv[1]); - }else{ - zProc = 0; - } - if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ - sqlite3_result_error(context, zErrMsg, -1); - sqlite3_free(zErrMsg); - } -} -#endif - - -/* -** An instance of the following structure holds the context of a -** sum() or avg() aggregate computation. -*/ -typedef struct SumCtx SumCtx; -struct SumCtx { - double rSum; /* Running sum as as a double */ - double rErr; /* Error term for Kahan-Babushka-Neumaier summation */ - i64 iSum; /* Running sum as a signed integer */ - i64 cnt; /* Number of elements summed */ - u8 approx; /* True if any non-integer value was input to the sum */ - u8 ovrfl; /* Integer overflow seen */ -}; - -/* -** Do one step of the Kahan-Babushka-Neumaier summation. -** -** https://en.wikipedia.org/wiki/Kahan_summation_algorithm -** -** Variables are marked "volatile" to defeat c89 x86 floating point -** optimizations can mess up this algorithm. -*/ -static void kahanBabuskaNeumaierStep( - volatile SumCtx *pSum, - volatile double r -){ - volatile double s = pSum->rSum; - volatile double t = s + r; - if( fabs(s) > fabs(r) ){ - pSum->rErr += (s - t) + r; - }else{ - pSum->rErr += (r - t) + s; - } - pSum->rSum = t; -} - -/* -** Add a (possibly large) integer to the running sum. -*/ -static void kahanBabuskaNeumaierStepInt64(volatile SumCtx *pSum, i64 iVal){ - if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ - i64 iBig, iSm; - iSm = iVal % 16384; - iBig = iVal - iSm; - kahanBabuskaNeumaierStep(pSum, iBig); - kahanBabuskaNeumaierStep(pSum, iSm); - }else{ - kahanBabuskaNeumaierStep(pSum, (double)iVal); - } -} - -/* -** Initialize the Kahan-Babaska-Neumaier sum from a 64-bit integer -*/ -static void kahanBabuskaNeumaierInit( - volatile SumCtx *p, - i64 iVal -){ - if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ - i64 iSm = iVal % 16384; - p->rSum = (double)(iVal - iSm); - p->rErr = (double)iSm; - }else{ - p->rSum = (double)iVal; - p->rErr = 0.0; - } -} - -/* -** Routines used to compute the sum, average, and total. -** -** The SUM() function follows the (broken) SQL standard which means -** that it returns NULL if it sums over no inputs. TOTAL returns -** 0.0 in that case. In addition, TOTAL always returns a float where -** SUM might return an integer if it never encounters a floating point -** value. TOTAL never fails, but SUM might throw an exception if -** it overflows an integer. -*/ -static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ - SumCtx *p; - int type; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - type = sqlite3_value_numeric_type(argv[0]); - if( p && type!=SQLITE_NULL ){ - p->cnt++; - if( p->approx==0 ){ - if( type!=SQLITE_INTEGER ){ - kahanBabuskaNeumaierInit(p, p->iSum); - p->approx = 1; - kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); - }else{ - i64 x = p->iSum; - if( sqlite3AddInt64(&x, sqlite3_value_int64(argv[0]))==0 ){ - p->iSum = x; - }else{ - p->ovrfl = 1; - kahanBabuskaNeumaierInit(p, p->iSum); - p->approx = 1; - kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); - } - } - }else{ - if( type==SQLITE_INTEGER ){ - kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); - }else{ - p->ovrfl = 0; - kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); - } - } - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ - SumCtx *p; - int type; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - type = sqlite3_value_numeric_type(argv[0]); - /* p is always non-NULL because sumStep() will have been called first - ** to initialize it */ - if( ALWAYS(p) && type!=SQLITE_NULL ){ - assert( p->cnt>0 ); - p->cnt--; - if( !p->approx ){ - if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){ - p->ovrfl = 1; - p->approx = 1; - } - }else if( type==SQLITE_INTEGER ){ - i64 iVal = sqlite3_value_int64(argv[0]); - if( iVal!=SMALLEST_INT64 ){ - kahanBabuskaNeumaierStepInt64(p, -iVal); - }else{ - kahanBabuskaNeumaierStepInt64(p, LARGEST_INT64); - kahanBabuskaNeumaierStepInt64(p, 1); - } - }else{ - kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0])); - } - } -} -#else -# define sumInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ -static void sumFinalize(sqlite3_context *context){ - SumCtx *p; - p = sqlite3_aggregate_context(context, 0); - if( p && p->cnt>0 ){ - if( p->approx ){ - if( p->ovrfl ){ - sqlite3_result_error(context,"integer overflow",-1); - }else if( !sqlite3IsOverflow(p->rErr) ){ - sqlite3_result_double(context, p->rSum+p->rErr); - }else{ - sqlite3_result_double(context, p->rSum); - } - }else{ - sqlite3_result_int64(context, p->iSum); - } - } -} -static void avgFinalize(sqlite3_context *context){ - SumCtx *p; - p = sqlite3_aggregate_context(context, 0); - if( p && p->cnt>0 ){ - double r; - if( p->approx ){ - r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; - }else{ - r = (double)(p->iSum); - } - sqlite3_result_double(context, r/(double)p->cnt); - } -} -static void totalFinalize(sqlite3_context *context){ - SumCtx *p; - double r = 0.0; - p = sqlite3_aggregate_context(context, 0); - if( p ){ - if( p->approx ){ - r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; - }else{ - r = (double)(p->iSum); - } - } - sqlite3_result_double(context, r); -} - -/* -** The following structure keeps track of state information for the -** count() aggregate function. -*/ -typedef struct CountCtx CountCtx; -struct CountCtx { - i64 n; -#ifdef SQLITE_DEBUG - int bInverse; /* True if xInverse() ever called */ -#endif -}; - -/* -** Routines to implement the count() aggregate function. -*/ -static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ - CountCtx *p; - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ - p->n++; - } - -#ifndef SQLITE_OMIT_DEPRECATED - /* The sqlite3_aggregate_count() function is deprecated. But just to make - ** sure it still operates correctly, verify that its count agrees with our - ** internal count when using count(*) and when the total count can be - ** expressed as a 32-bit integer. */ - assert( argc==1 || p==0 || p->n>0x7fffffff || p->bInverse - || p->n==sqlite3_aggregate_count(context) ); -#endif -} -static void countFinalize(sqlite3_context *context){ - CountCtx *p; - p = sqlite3_aggregate_context(context, 0); - sqlite3_result_int64(context, p ? p->n : 0); -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void countInverse(sqlite3_context *ctx, int argc, sqlite3_value **argv){ - CountCtx *p; - p = sqlite3_aggregate_context(ctx, sizeof(*p)); - /* p is always non-NULL since countStep() will have been called first */ - if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && ALWAYS(p) ){ - p->n--; -#ifdef SQLITE_DEBUG - p->bInverse = 1; -#endif - } -} -#else -# define countInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** Routines to implement min() and max() aggregate functions. -*/ -static void minmaxStep( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - Mem *pArg = (Mem *)argv[0]; - Mem *pBest; - UNUSED_PARAMETER(NotUsed); - - pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); - if( !pBest ) return; - - if( sqlite3_value_type(pArg)==SQLITE_NULL ){ - if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); - }else if( pBest->flags ){ - int max; - int cmp; - CollSeq *pColl = sqlite3GetFuncCollSeq(context); - /* This step function is used for both the min() and max() aggregates, - ** the only difference between the two being that the sense of the - ** comparison is inverted. For the max() aggregate, the - ** sqlite3_user_data() function returns (void *)-1. For min() it - ** returns (void *)db, where db is the sqlite3* database pointer. - ** Therefore the next statement sets variable 'max' to 1 for the max() - ** aggregate, or 0 for min(). - */ - max = sqlite3_user_data(context)!=0; - cmp = sqlite3MemCompare(pBest, pArg, pColl); - if( (max && cmp<0) || (!max && cmp>0) ){ - sqlite3VdbeMemCopy(pBest, pArg); - }else{ - sqlite3SkipAccumulatorLoad(context); - } - }else{ - pBest->db = sqlite3_context_db_handle(context); - sqlite3VdbeMemCopy(pBest, pArg); - } -} -static void minMaxValueFinalize(sqlite3_context *context, int bValue){ - sqlite3_value *pRes; - pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); - if( pRes ){ - if( pRes->flags ){ - sqlite3_result_value(context, pRes); - } - if( bValue==0 ) sqlite3VdbeMemRelease(pRes); - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void minMaxValue(sqlite3_context *context){ - minMaxValueFinalize(context, 1); -} -#else -# define minMaxValue 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ -static void minMaxFinalize(sqlite3_context *context){ - minMaxValueFinalize(context, 0); -} - -/* -** group_concat(EXPR, ?SEPARATOR?) -** string_agg(EXPR, SEPARATOR) -** -** Content is accumulated in GroupConcatCtx.str with the SEPARATOR -** coming before the EXPR value, except for the first entry which -** omits the SEPARATOR. -** -** It is tragic that the SEPARATOR goes before the EXPR string. 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( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zVal; - GroupConcatCtx *pGCC; - const char *zSep; - int nVal, nSep; - assert( argc==1 || argc==2 ); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC)); - if( pGCC ){ - sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pGCC->str.mxAlloc==0; - pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; - if( argc==1 ){ - if( !firstTerm ){ - sqlite3_str_appendchar(&pGCC->str, 1, ','); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else{ - pGCC->nFirstSepLength = 1; - } -#endif - }else if( !firstTerm ){ - zSep = (char*)sqlite3_value_text(argv[1]); - nSep = sqlite3_value_bytes(argv[1]); - if( zSep ){ - 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*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int)); - if( pnsl!=0 ){ - int i = 0, nA = pGCC->nAccum-1; - while( inFirstSepLength; - } - }else{ - pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int)); - } - if( pnsl!=0 ){ - if( ALWAYS(pGCC->nAccum>0) ){ - pnsl[pGCC->nAccum-1] = nSep; - } - pGCC->pnSepLengths = pnsl; - }else{ - sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM); - } - } -#endif - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else{ - pGCC->nFirstSepLength = sqlite3_value_bytes(argv[1]); - } - pGCC->nAccum += 1; -#endif - zVal = (char*)sqlite3_value_text(argv[0]); - nVal = sqlite3_value_bytes(argv[0]); - if( zVal ) sqlite3_str_append(&pGCC->str, zVal, nVal); - } -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -static void groupConcatInverse( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GroupConcatCtx *pGCC; - assert( argc==1 || argc==2 ); - (void)argc; /* Suppress unused parameter warning */ - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC)); - /* pGCC is always non-NULL since groupConcatStep() will have always - ** run first to initialize it */ - if( ALWAYS(pGCC) ){ - int nVS; /* Number of characters to remove */ - /* Must call sqlite3_value_text() to convert the argument into text prior - ** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */ - (void)sqlite3_value_text(argv[0]); - nVS = 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{ - /* If removing single accumulated string, harmlessly over-do. */ - nVS += pGCC->nFirstSepLength; - } - if( nVS>=(int)pGCC->str.nChar ){ - pGCC->str.nChar = 0; - }else{ - pGCC->str.nChar -= nVS; - memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar); - } - if( pGCC->str.nChar==0 ){ - pGCC->str.mxAlloc = 0; - sqlite3_free(pGCC->pnSepLengths); - pGCC->pnSepLengths = 0; - } - } -} -#else -# define groupConcatInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ -static void groupConcatFinalize(sqlite3_context *context){ - GroupConcatCtx *pGCC - = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); - if( pGCC ){ - sqlite3ResultStrAccum(context, &pGCC->str); -#ifndef SQLITE_OMIT_WINDOWFUNC - sqlite3_free(pGCC->pnSepLengths); -#endif - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void groupConcatValue(sqlite3_context *context){ - GroupConcatCtx *pGCC - = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); - if( pGCC ){ - StrAccum *pAccum = &pGCC->str; - if( pAccum->accError==SQLITE_TOOBIG ){ - sqlite3_result_error_toobig(context); - }else if( pAccum->accError==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){ - sqlite3_result_text(context, "", 1, SQLITE_STATIC); - }else{ - const char *zText = sqlite3_str_value(pAccum); - sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT); - } - } -} -#else -# define groupConcatValue 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** This routine does per-connection function registration. Most -** of the built-in functions above are part of the global function set. -** This routine only deals with those that are not global. -*/ -SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ - int rc = sqlite3_overload_function(db, "MATCH", 2); - assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(db); - } -} - -/* -** Re-register the built-in LIKE functions. The caseSensitive -** parameter determines whether or not the LIKE operator is case -** sensitive. -*/ -SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ - FuncDef *pDef; - struct compareInfo *pInfo; - int flags; - int nArg; - if( caseSensitive ){ - pInfo = (struct compareInfo*)&likeInfoAlt; - flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE; - }else{ - pInfo = (struct compareInfo*)&likeInfoNorm; - flags = SQLITE_FUNC_LIKE; - } - for(nArg=2; nArg<=3; nArg++){ - sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc, - 0, 0, 0, 0, 0); - pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0); - pDef->funcFlags |= flags; - pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE; - } -} - -/* -** pExpr points to an expression which implements a function. If -** it is appropriate to apply the LIKE optimization to that function -** then set aWc[0] through aWc[2] to the wildcard characters and the -** escape character and then return TRUE. If the function is not a -** LIKE-style function then return FALSE. -** -** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE -** operator if c is a string literal that is exactly one byte in length. -** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is -** no ESCAPE clause. -** -** *pIsNocase is set to true if uppercase and lowercase are equivalent for -** the function (default for LIKE). If the function makes the distinction -** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to -** false. -*/ -SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ - FuncDef *pDef; - int nExpr; - assert( pExpr!=0 ); - assert( pExpr->op==TK_FUNCTION ); - assert( ExprUseXList(pExpr) ); - if( !pExpr->x.pList ){ - return 0; - } - nExpr = pExpr->x.pList->nExpr; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pDef==0 ) return 0; -#endif - if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ - return 0; - } - - /* The memcpy() statement assumes that the wildcard characters are - ** the first three statements in the compareInfo structure. The - ** asserts() that follow verify that assumption - */ - memcpy(aWc, pDef->pUserData, 3); - assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); - assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); - assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); - - if( nExpr<3 ){ - aWc[3] = 0; - }else{ - 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; - if( zEscape[0]==aWc[1] ) return 0; - aWc[3] = zEscape[0]; - } - - *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0; - 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 sqlite3_user_data() pointer is a pointer to the libm implementation -** of the underlying C function. -*/ -static void ceilingFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==1 ); - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: { - sqlite3_result_int64(context, sqlite3_value_int64(argv[0])); - break; - } - case SQLITE_FLOAT: { - double (*x)(double) = (double(*)(double))sqlite3_user_data(context); - sqlite3_result_double(context, x(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); } - -/* -** Some systems do not have log2() and log10() in their standard math -** libraries. -*/ -#if defined(HAVE_LOG10) && HAVE_LOG10==0 -# define log10(X) (0.4342944819032517867*log(X)) -#endif -#if defined(HAVE_LOG2) && HAVE_LOG2==0 -# define log2(X) (1.442695040888963456*log(X)) -#endif - - -/* -** 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( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double x, b, ans; - assert( argc==1 || argc==2 ); - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - x = sqlite3_value_double(argv[0]); - if( x<=0.0 ) return; - break; - default: - return; - } - if( argc==2 ){ - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - b = log(x); - if( b<=0.0 ) return; - x = sqlite3_value_double(argv[1]); - if( x<=0.0 ) return; - break; - default: - return; - } - ans = log(x)/b; - }else{ - switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){ - case 1: - ans = log10(x); - break; - case 2: - ans = log2(x); - break; - default: - ans = log(x); - break; - } - } - 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( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0; - double v0, ans; - double (*x)(double); - assert( argc==1 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - v0 = sqlite3_value_double(argv[0]); - x = (double(*)(double))sqlite3_user_data(context); - ans = x(v0); - 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( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0, type1; - double v0, v1, ans; - double (*x)(double,double); - assert( argc==2 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - type1 = sqlite3_value_numeric_type(argv[1]); - if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return; - v0 = sqlite3_value_double(argv[0]); - v1 = sqlite3_value_double(argv[1]); - x = (double(*)(double,double))sqlite3_user_data(context); - ans = x(v0, v1); - sqlite3_result_double(context, ans); -} - -/* -** Implementation of 0-argument pi() function. -*/ -static void piFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==0 ); - (void)argv; - sqlite3_result_double(context, M_PI); -} - -#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */ - -/* -** Implementation of sign(X) function. -*/ -static void signFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0; - double x; - UNUSED_PARAMETER(argc); - assert( argc==1 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - x = sqlite3_value_double(argv[0]); - sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0); -} - -#ifdef SQLITE_DEBUG -/* -** Implementation of fpdecode(x,y,z) function. -** -** x is a real number that is to be decoded. y is the precision. -** z is the maximum real precision. Return a string that shows the -** results of the sqlite3FpDecode() function. -** -** Used for testing and debugging only, specifically testing and debugging -** of the sqlite3FpDecode() function. This SQL function does not appear -** in production builds. This function is not an API and is subject to -** modification or removal in future versions of SQLite. -*/ -static void fpdecodeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - FpDecode s; - double x; - int y, z; - char zBuf[100]; - UNUSED_PARAMETER(argc); - assert( argc==3 ); - x = sqlite3_value_double(argv[0]); - y = sqlite3_value_int(argv[1]); - z = sqlite3_value_int(argv[2]); - if( z<=0 ) z = 1; - sqlite3FpDecode(&s, x, y, z); - if( s.isSpecial==2 ){ - sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN"); - }else{ - sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP); - } - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -** Implementation of parseuri(uri,flags) function. -** -** Required Arguments: -** "uri" The URI to parse. -** "flags" Bitmask of flags, as if to sqlite3_open_v2(). -** -** Additional arguments beyond the first two make calls to -** sqlite3_uri_key() for integers and sqlite3_uri_parameter for -** anything else. -** -** The result is a string showing the results of calling sqlite3ParseUri(). -** -** Used for testing and debugging only, specifically testing and debugging -** of the sqlite3ParseUri() function. This SQL function does not appear -** in production builds. This function is not an API and is subject to -** modification or removal in future versions of SQLite. -*/ -static void parseuriFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - sqlite3_str *pResult; - const char *zVfs; - const char *zUri; - unsigned int flgs; - int rc; - sqlite3_vfs *pVfs = 0; - char *zFile = 0; - char *zErr = 0; - - if( argc<2 ) return; - pVfs = sqlite3_vfs_find(0); - assert( pVfs ); - zVfs = pVfs->zName; - zUri = (const char*)sqlite3_value_text(argv[0]); - if( zUri==0 ) return; - flgs = (unsigned int)sqlite3_value_int(argv[1]); - rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr); - pResult = sqlite3_str_new(0); - if( pResult ){ - int i; - sqlite3_str_appendf(pResult, "rc=%d", rc); - sqlite3_str_appendf(pResult, ", flags=0x%x", flgs); - sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0); - sqlite3_str_appendf(pResult, ", err=%Q", zErr); - sqlite3_str_appendf(pResult, ", file=%Q", zFile); - if( zFile ){ - const char *z = zFile; - z += sqlite3Strlen30(z)+1; - while( z[0] ){ - sqlite3_str_appendf(pResult, ", %Q", z); - z += sqlite3Strlen30(z)+1; - } - for(i=2; iu.pHash){ - int n = sqlite3Strlen30(p->zName); - int h = p->zName[0] + n; - assert( p->funcFlags & SQLITE_FUNC_BUILTIN ); - printf(" %s(%d)", p->zName, h); - } - printf("\n"); - } - } -#endif -} - -/************** End of func.c ************************************************/ -/************** Begin file fkey.c ********************************************/ -/* -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used by the compiler to add foreign key -** support to compiled SQL statements. -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY -#ifndef SQLITE_OMIT_TRIGGER - -/* -** Deferred and Immediate FKs -** -------------------------- -** -** Foreign keys in SQLite come in two flavours: deferred and immediate. -** If an immediate foreign key constraint is violated, -** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current -** statement transaction rolled back. If a -** deferred foreign key constraint is violated, no action is taken -** immediately. However if the application attempts to commit the -** transaction before fixing the constraint violation, the attempt fails. -** -** Deferred constraints are implemented using a simple counter associated -** with the database handle. The counter is set to zero each time a -** database transaction is opened. Each time a statement is executed -** that causes a foreign key violation, the counter is incremented. Each -** time a statement is executed that removes an existing violation from -** the database, the counter is decremented. When the transaction is -** committed, the commit fails if the current value of the counter is -** greater than zero. This scheme has two big drawbacks: -** -** * When a commit fails due to a deferred foreign key constraint, -** there is no way to tell which foreign constraint is not satisfied, -** or which row it is not satisfied for. -** -** * If the database contains foreign key violations when the -** transaction is opened, this may cause the mechanism to malfunction. -** -** Despite these problems, this approach is adopted as it seems simpler -** than the alternatives. -** -** INSERT operations: -** -** I.1) For each FK for which the table is the child table, search -** the parent table for a match. If none is found increment the -** constraint counter. -** -** I.2) For each FK for which the table is the parent table, -** search the child table for rows that correspond to the new -** row in the parent table. Decrement the counter for each row -** found (as the constraint is now satisfied). -** -** DELETE operations: -** -** D.1) For each FK for which the table is the child table, -** search the parent table for a row that corresponds to the -** deleted row in the child table. If such a row is not found, -** decrement the counter. -** -** D.2) For each FK for which the table is the parent table, search -** the child table for rows that correspond to the deleted row -** in the parent table. For each found increment the counter. -** -** UPDATE operations: -** -** An UPDATE command requires that all 4 steps above are taken, but only -** for FK constraints for which the affected columns are actually -** modified (values must be compared at runtime). -** -** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2. -** This simplifies the implementation a bit. -** -** For the purposes of immediate FK constraints, the OR REPLACE conflict -** resolution is considered to delete rows before the new row is inserted. -** If a delete caused by OR REPLACE violates an FK constraint, an exception -** is thrown, even if the FK constraint would be satisfied after the new -** row is inserted. -** -** Immediate constraints are usually handled similarly. The only difference -** is that the counter used is stored as part of each individual statement -** object (struct Vdbe). If, after the statement has run, its immediate -** constraint counter is greater than zero, -** it returns SQLITE_CONSTRAINT_FOREIGNKEY -** and the statement transaction is rolled back. An exception is an INSERT -** statement that inserts a single row only (no triggers). In this case, -** instead of using a counter, an exception is thrown immediately if the -** INSERT violates a foreign key constraint. This is necessary as such -** an INSERT does not open a statement transaction. -** -** TODO: How should dropping a table be handled? How should renaming a -** table be handled? -** -** -** Query API Notes -** --------------- -** -** Before coding an UPDATE or DELETE row operation, the code-generator -** for those two operations needs to know whether or not the operation -** requires any FK processing and, if so, which columns of the original -** row are required by the FK processing VDBE code (i.e. if FKs were -** implemented using triggers, which of the old.* columns would be -** accessed). No information is required by the code-generator before -** coding an INSERT operation. The functions used by the UPDATE/DELETE -** generation code to query for this information are: -** -** sqlite3FkRequired() - Test to see if FK processing is required. -** sqlite3FkOldmask() - Query for the set of required old.* columns. -** -** -** Externally accessible module functions -** -------------------------------------- -** -** sqlite3FkCheck() - Check for foreign key violations. -** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions. -** sqlite3FkDelete() - Delete an FKey structure. -*/ - -/* -** VDBE Calling Convention -** ----------------------- -** -** Example: -** -** For the following INSERT statement: -** -** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c); -** INSERT INTO t1 VALUES(1, 2, 3.1); -** -** Register (x): 2 (type integer) -** Register (x+1): 1 (type integer) -** Register (x+2): NULL (type NULL) -** Register (x+3): 3.1 (type real) -*/ - -/* -** A foreign key constraint requires that the key columns in the parent -** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. -** Given that pParent is the parent table for foreign key constraint pFKey, -** search the schema for a unique index on the parent key columns. -** -** If successful, zero is returned. If the parent key is an INTEGER PRIMARY -** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx -** is set to point to the unique index. -** -** If the parent key consists of a single column (the foreign key constraint -** is not a composite foreign key), output variable *paiCol is set to NULL. -** Otherwise, it is set to point to an allocated array of size N, where -** N is the number of columns in the parent key. The first element of the -** array is the index of the child table column that is mapped by the FK -** constraint to the parent table column stored in the left-most column -** of index *ppIdx. The second element of the array is the index of the -** child table column that corresponds to the second left-most column of -** *ppIdx, and so on. -** -** If the required index cannot be found, either because: -** -** 1) The named parent key columns do not exist, or -** -** 2) The named parent key columns do exist, but are not subject to a -** UNIQUE or PRIMARY KEY constraint, or -** -** 3) No parent key columns were provided explicitly as part of the -** foreign key definition, and the parent table does not have a -** PRIMARY KEY, or -** -** 4) No parent key columns were provided explicitly as part of the -** foreign key definition, and the PRIMARY KEY of the parent table -** consists of a different number of columns to the child key in -** the child table. -** -** then non-zero is returned, and a "foreign key mismatch" error loaded -** into pParse. If an OOM error occurs, non-zero is returned and the -** pParse->db->mallocFailed flag is set. -*/ -SQLITE_PRIVATE int sqlite3FkLocateIndex( - Parse *pParse, /* Parse context to store any error in */ - Table *pParent, /* Parent table of FK constraint pFKey */ - FKey *pFKey, /* Foreign key to find index for */ - Index **ppIdx, /* OUT: Unique index on parent table */ - int **paiCol /* OUT: Map of index columns in pFKey */ -){ - Index *pIdx = 0; /* Value to return via *ppIdx */ - int *aiCol = 0; /* Value to return via *paiCol */ - int nCol = pFKey->nCol; /* Number of columns in parent key */ - char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */ - - /* The caller is responsible for zeroing output parameters. */ - assert( ppIdx && *ppIdx==0 ); - assert( !paiCol || *paiCol==0 ); - assert( pParse ); - - /* If this is a non-composite (single column) foreign key, check if it - ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx - ** and *paiCol set to zero and return early. - ** - ** Otherwise, for a composite foreign key (more than one column), allocate - ** space for the aiCol array (returned via output parameter *paiCol). - ** Non-composite foreign keys do not require the aiCol array. - */ - if( nCol==1 ){ - /* The FK maps to the IPK if any of the following are true: - ** - ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly - ** mapped to the primary key of table pParent, or - ** 2) The FK is explicitly mapped to a column declared as INTEGER - ** PRIMARY KEY. - */ - if( pParent->iPKey>=0 ){ - if( !zKey ) return 0; - if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){ - return 0; - } - } - }else if( paiCol ){ - assert( nCol>1 ); - aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); - if( !aiCol ) return 1; - *paiCol = aiCol; - } - - for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ - /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number - ** of columns. If each indexed column corresponds to a foreign key - ** column of pFKey, then this index is a winner. */ - - if( zKey==0 ){ - /* If zKey is NULL, then this foreign key is implicitly mapped to - ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be - ** identified by the test. */ - if( IsPrimaryKeyIndex(pIdx) ){ - if( aiCol ){ - int i; - for(i=0; iaCol[i].iFrom; - } - break; - } - }else{ - /* If zKey is non-NULL, then this foreign key was declared to - ** map to an explicit list of columns in table pParent. Check if this - ** index matches those columns. Also, check that the index uses - ** the default collation sequences for each column. */ - int i, j; - for(i=0; iaiColumn[i]; /* Index of column in parent tbl */ - const char *zDfltColl; /* Def. collation for column */ - char *zIdxCol; /* Name of indexed column */ - - if( iCol<0 ) break; /* No foreign keys against expression indexes */ - - /* 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 = sqlite3ColumnColl(&pParent->aCol[iCol]); - if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; - if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; - - zIdxCol = pParent->aCol[iCol].zCnName; - for(j=0; jaCol[j].zCol, zIdxCol)==0 ){ - if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; - break; - } - } - if( j==nCol ) break; - } - if( i==nCol ) break; /* pIdx is usable */ - } - } - } - - if( !pIdx ){ - if( !pParse->disableTriggers ){ - sqlite3ErrorMsg(pParse, - "foreign key mismatch - \"%w\" referencing \"%w\"", - pFKey->pFrom->zName, pFKey->zTo); - } - sqlite3DbFree(pParse->db, aiCol); - return 1; - } - - *ppIdx = pIdx; - return 0; -} - -/* -** This function is called when a row is inserted into or deleted from the -** child table of foreign key constraint pFKey. If an SQL UPDATE is executed -** on the child table of pFKey, this function is invoked twice for each row -** affected - once to "delete" the old row, and then again to "insert" the -** new row. -** -** Each time it is called, this function generates VDBE code to locate the -** row in the parent table that corresponds to the row being inserted into -** or deleted from the child table. If the parent row can be found, no -** special action is taken. Otherwise, if the parent row can *not* be -** found in the parent table: -** -** Operation | FK type | Action taken -** -------------------------------------------------------------------------- -** INSERT immediate Increment the "immediate constraint counter". -** -** DELETE immediate Decrement the "immediate constraint counter". -** -** INSERT deferred Increment the "deferred constraint counter". -** -** DELETE deferred Decrement the "deferred constraint counter". -** -** These operations are identified in the comment at the top of this file -** (fkey.c) as "I.1" and "D.1". -*/ -static void fkLookupParent( - Parse *pParse, /* Parse context */ - int iDb, /* Index of database housing pTab */ - Table *pTab, /* Parent table of FK pFKey */ - Index *pIdx, /* Unique index on parent key columns in pTab */ - FKey *pFKey, /* Foreign key constraint */ - int *aiCol, /* Map from parent key columns to child table columns */ - int regData, /* Address of array containing child table row */ - int nIncr, /* Increment constraint counter by this */ - int isIgnore /* If true, pretend pTab contains all NULL values */ -){ - int i; /* Iterator variable */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */ - int iCur = pParse->nTab - 1; /* Cursor number to use */ - int iOk = sqlite3VdbeMakeLabel(pParse); /* jump here if parent key found */ - - sqlite3VdbeVerifyAbortable(v, - (!pFKey->isDeferred - && !(pParse->db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel - && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore); - - /* If nIncr is less than zero, then check at runtime if there are any - ** outstanding constraints to resolve. If there are not, there is no need - ** to check if deleting this row resolves any outstanding violations. - ** - ** Check if any of the key columns in the child table row are NULL. If - ** any are, then the constraint is considered satisfied. No need to - ** search for a matching row in the parent table. */ - if( nIncr<0 ){ - sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); - VdbeCoverage(v); - } - for(i=0; inCol; i++){ - int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v); - } - - if( isIgnore==0 ){ - if( pIdx==0 ){ - /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY - ** column of the parent table (table pTab). */ - int iMustBeInt; /* Address of MustBeInt instruction */ - int regTemp = sqlite3GetTempReg(pParse); - - /* Invoke MustBeInt to coerce the child key value to an integer (i.e. - ** apply the affinity of the parent key). If this fails, then there - ** is no matching parent key. Before using MustBeInt, make a copy of - ** the value. Otherwise, the value inserted into the child key column - ** will have INTEGER affinity applied to it, which may not be correct. */ - sqlite3VdbeAddOp2(v, OP_SCopy, - sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp); - iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); - VdbeCoverage(v); - - /* If the parent table is the same as the child table, and we are about - ** to increment the constraint-counter (i.e. this is an INSERT operation), - ** then check if the row being inserted matches itself. If so, do not - ** increment the constraint-counter. */ - if( pTab==pFKey->pFrom && nIncr==1 ){ - sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - } - - sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); - sqlite3VdbeGoto(v, iOk); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - sqlite3VdbeJumpHere(v, iMustBeInt); - sqlite3ReleaseTempReg(pParse, regTemp); - }else{ - int nCol = pFKey->nCol; - int regTemp = sqlite3GetTempRange(pParse, nCol); - - sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - for(i=0; ipFrom, aiCol[i])+1+regData, - regTemp+i); - } - - /* If the parent table is the same as the child table, and we are about - ** to increment the constraint-counter (i.e. this is an INSERT operation), - ** then check if the row being inserted matches itself. If so, do not - ** increment the constraint-counter. - ** - ** If any of the parent-key values are NULL, then the row cannot match - ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any - ** of the parent-key values are NULL (at this point it is known that - ** none of the child key values are). - */ - if( pTab==pFKey->pFrom && nIncr==1 ){ - int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; - for(i=0; ipFrom,aiCol[i]) - +1+regData; - int iParent = 1+regData; - iParent += sqlite3TableColumnToStorage(pIdx->pTable, - pIdx->aiColumn[i]); - assert( pIdx->aiColumn[i]>=0 ); - assert( aiCol[i]!=pTab->iPKey ); - if( pIdx->aiColumn[i]==pTab->iPKey ){ - /* The parent key is a composite key that includes the IPK column */ - iParent = regData; - } - sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - } - sqlite3VdbeGoto(v, iOk); - } - - sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0, - sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol); - VdbeCoverage(v); - sqlite3ReleaseTempRange(pParse, regTemp, nCol); - } - } - - if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel - && !pParse->isMultiWrite - ){ - /* Special case: If this is an INSERT statement that will insert exactly - ** one row into the table, raise a constraint immediately instead of - ** incrementing a counter. This is necessary as the VM code is being - ** generated for will not open a statement transaction. */ - assert( nIncr==1 ); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, - OE_Abort, 0, P4_STATIC, P5_ConstraintFK); - }else{ - if( nIncr>0 && pFKey->isDeferred==0 ){ - sqlite3MayAbort(pParse); - } - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - } - - sqlite3VdbeResolveLabel(v, iOk); - sqlite3VdbeAddOp1(v, OP_Close, iCur); -} - - -/* -** Return an Expr object that refers to a memory register corresponding -** to column iCol of table pTab. -** -** regBase is the first of an array of register that contains the data -** for pTab. regBase itself holds the rowid. regBase+1 holds the first -** column. regBase+2 holds the second column, and so forth. -*/ -static Expr *exprTableRegister( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* The table whose content is at r[regBase]... */ - int regBase, /* Contents of table pTab */ - i16 iCol /* Which column of pTab is desired */ -){ - Expr *pExpr; - Column *pCol; - const char *zColl; - sqlite3 *db = pParse->db; - - pExpr = sqlite3Expr(db, TK_REGISTER, 0); - if( pExpr ){ - if( iCol>=0 && iCol!=pTab->iPKey ){ - pCol = &pTab->aCol[iCol]; - pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1; - pExpr->affExpr = pCol->affinity; - zColl = sqlite3ColumnColl(pCol); - if( zColl==0 ) zColl = db->pDfltColl->zName; - pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl); - }else{ - pExpr->iTable = regBase; - pExpr->affExpr = SQLITE_AFF_INTEGER; - } - } - return pExpr; -} - -/* -** Return an Expr object that refers to column iCol of table pTab which -** has cursor iCur. -*/ -static Expr *exprTableColumn( - sqlite3 *db, /* The database connection */ - Table *pTab, /* The table whose column is desired */ - int iCursor, /* The open cursor on the table */ - i16 iCol /* The column that is wanted */ -){ - Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); - if( pExpr ){ - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pTab; - pExpr->iTable = iCursor; - pExpr->iColumn = iCol; - } - return pExpr; -} - -/* -** This function is called to generate code executed when a row is deleted -** from the parent table of foreign key constraint pFKey and, if pFKey is -** deferred, when a row is inserted into the same table. When generating -** code for an SQL UPDATE operation, this function may be called twice - -** once to "delete" the old row and once to "insert" the new row. -** -** Parameter nIncr is passed -1 when inserting a row (as this may decrease -** the number of FK violations in the db) or +1 when deleting one (as this -** may increase the number of FK constraint problems). -** -** The code generated by this function scans through the rows in the child -** table that correspond to the parent table row being deleted or inserted. -** For each child row found, one of the following actions is taken: -** -** Operation | FK type | Action taken -** -------------------------------------------------------------------------- -** DELETE immediate Increment the "immediate constraint counter". -** -** INSERT immediate Decrement the "immediate constraint counter". -** -** DELETE deferred Increment the "deferred constraint counter". -** -** INSERT deferred Decrement the "deferred constraint counter". -** -** These operations are identified in the comment at the top of this file -** (fkey.c) as "I.2" and "D.2". -*/ -static void fkScanChildren( - Parse *pParse, /* Parse context */ - SrcList *pSrc, /* The child table to be scanned */ - Table *pTab, /* The parent table */ - Index *pIdx, /* Index on parent covering the foreign key */ - FKey *pFKey, /* The foreign key linking pSrc to pTab */ - int *aiCol, /* Map from pIdx cols to child table cols */ - int regData, /* Parent row data starts here */ - int nIncr /* Amount to increment deferred counter by */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - int i; /* Iterator variable */ - Expr *pWhere = 0; /* WHERE clause to scan with */ - NameContext sNameContext; /* Context used to resolve WHERE clause */ - WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */ - int iFkIfZero = 0; /* Address of OP_FkIfZero */ - Vdbe *v = sqlite3GetVdbe(pParse); - - assert( pIdx==0 || pIdx->pTable==pTab ); - assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol ); - assert( pIdx!=0 || pFKey->nCol==1 ); - assert( pIdx!=0 || HasRowid(pTab) ); - - if( nIncr<0 ){ - iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); - VdbeCoverage(v); - } - - /* Create an Expr object representing an SQL expression like: - ** - ** = AND = ... - ** - ** The collation sequence used for the comparison should be that of - ** the parent key columns. The affinity of the parent key column should - ** be applied to each child key value before the comparison takes place. - */ - for(i=0; inCol; i++){ - Expr *pLeft; /* Value from parent table row */ - Expr *pRight; /* Column ref to child table */ - Expr *pEq; /* Expression (pLeft = pRight) */ - i16 iCol; /* Index of column in child table */ - const char *zCol; /* Name of column in child table */ - - iCol = pIdx ? pIdx->aiColumn[i] : -1; - pLeft = exprTableRegister(pParse, pTab, regData, iCol); - iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; - assert( iCol>=0 ); - zCol = pFKey->pFrom->aCol[iCol].zCnName; - pRight = sqlite3Expr(db, TK_ID, zCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); - pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); - } - - /* If the child table is the same as the parent table, then add terms - ** to the WHERE clause that prevent this entry from being scanned. - ** The added WHERE clause terms are like this: - ** - ** $current_rowid!=rowid - ** NOT( $current_a==a AND $current_b==b AND ... ) - ** - ** The first form is used for rowid tables. The second form is used - ** for WITHOUT ROWID tables. In the second form, the *parent* key is - ** (a,b,...). Either the parent or primary key could be used to - ** uniquely identify the current row, but the parent key is more convenient - ** as the required values have already been loaded into registers - ** by the caller. - */ - if( pTab==pFKey->pFrom && nIncr>0 ){ - Expr *pNe; /* Expression (pLeft != pRight) */ - Expr *pLeft; /* Value from parent table row */ - Expr *pRight; /* Column ref to child table */ - if( HasRowid(pTab) ){ - pLeft = exprTableRegister(pParse, pTab, regData, -1); - pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); - pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight); - }else{ - Expr *pEq, *pAll = 0; - assert( pIdx!=0 ); - for(i=0; inKeyCol; i++){ - i16 iCol = pIdx->aiColumn[i]; - assert( iCol>=0 ); - pLeft = exprTableRegister(pParse, pTab, regData, iCol); - pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName); - pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight); - pAll = sqlite3ExprAnd(pParse, pAll, pEq); - } - pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); - } - pWhere = sqlite3ExprAnd(pParse, pWhere, pNe); - } - - /* Resolve the references in the WHERE clause. */ - memset(&sNameContext, 0, sizeof(NameContext)); - sNameContext.pSrcList = pSrc; - sNameContext.pParse = pParse; - sqlite3ResolveExprNames(&sNameContext, pWhere); - - /* Create VDBE to loop through the entries in pSrc that match the WHERE - ** clause. For each row found, increment either the deferred or immediate - ** foreign key constraint counter. */ - if( pParse->nErr==0 ){ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0); - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - if( pWInfo ){ - sqlite3WhereEnd(pWInfo); - } - } - - /* Clean up the WHERE clause constructed above. */ - sqlite3ExprDelete(db, pWhere); - if( iFkIfZero ){ - sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero); - } -} - -/* -** This function returns a linked list of FKey objects (connected by -** FKey.pNextTo) holding all children of table pTab. For example, -** given the following schema: -** -** CREATE TABLE t1(a PRIMARY KEY); -** CREATE TABLE t2(b REFERENCES t1(a); -** -** Calling this function with table "t1" as an argument returns a pointer -** to the FKey structure representing the foreign key constraint on table -** "t2". Calling this function with "t2" as the argument would return a -** NULL pointer (as there are no FK constraints for which t2 is the parent -** table). -*/ -SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ - return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); -} - -/* -** The second argument is a Trigger structure allocated by the -** fkActionTrigger() routine. This function deletes the Trigger structure -** and all of its sub-components. -** -** The Trigger structure or any of its sub-components may be allocated from -** the lookaside buffer belonging to database handle dbMem. -*/ -static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ - if( p ){ - TriggerStep *pStep = p->step_list; - sqlite3ExprDelete(dbMem, pStep->pWhere); - sqlite3ExprListDelete(dbMem, pStep->pExprList); - sqlite3SelectDelete(dbMem, pStep->pSelect); - sqlite3ExprDelete(dbMem, p->pWhen); - sqlite3DbFree(dbMem, 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 sqlite3FkClearTriggerCache(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 -** table pTab. -** -** Normally, no code is required. However, if either -** -** (a) The table is the parent table of a FK constraint, or -** (b) The table is the child table of a deferred FK constraint and it is -** determined at runtime that there are outstanding deferred FK -** constraint violations in the database, -** -** then the equivalent of "DELETE FROM " is executed before dropping -** the table from the database. Triggers are disabled while running this -** DELETE, but foreign key actions are not. -*/ -SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ - sqlite3 *db = pParse->db; - if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){ - int iSkip = 0; - Vdbe *v = sqlite3GetVdbe(pParse); - - assert( v ); /* VDBE has already been allocated */ - assert( IsOrdinaryTable(pTab) ); - if( 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 - ** generating any VDBE code. If one can be found, then jump over - ** the entire DELETE if there are no outstanding deferred constraints - ** when this statement is run. */ - FKey *p; - for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ - if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; - } - if( !p ) return; - iSkip = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); - } - - pParse->disableTriggers = 1; - sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0); - pParse->disableTriggers = 0; - - /* If the DELETE has generated immediate foreign key constraint - ** violations, halt the VDBE and return an error at this point, before - ** any modifications to the schema are made. This is because statement - ** transactions are not able to rollback schema changes. - ** - ** If the SQLITE_DeferFKs flag is set, then this is not required, as - ** the statement transaction will not be rolled back even if FK - ** constraints are violated. - */ - if( (db->flags & SQLITE_DeferFKs)==0 ){ - sqlite3VdbeVerifyAbortable(v, OE_Abort); - sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, - OE_Abort, 0, P4_STATIC, P5_ConstraintFK); - } - - if( iSkip ){ - sqlite3VdbeResolveLabel(v, iSkip); - } - } -} - - -/* -** The second argument points to an FKey object representing a foreign key -** for which pTab is the child table. An UPDATE statement against pTab -** is currently being processed. For each column of the table that is -** actually updated, the corresponding element in the aChange[] array -** is zero or greater (if a column is unmodified the corresponding element -** is set to -1). If the rowid column is modified by the UPDATE statement -** the bChngRowid argument is non-zero. -** -** This function returns true if any of the columns that are part of the -** child key for FK constraint *p are modified. -*/ -static int fkChildIsModified( - Table *pTab, /* Table being updated */ - FKey *p, /* Foreign key for which pTab is the child */ - int *aChange, /* Array indicating modified columns */ - int bChngRowid /* True if rowid is modified by this update */ -){ - int i; - for(i=0; inCol; i++){ - int iChildKey = p->aCol[i].iFrom; - if( aChange[iChildKey]>=0 ) return 1; - if( iChildKey==pTab->iPKey && bChngRowid ) return 1; - } - return 0; -} - -/* -** The second argument points to an FKey object representing a foreign key -** for which pTab is the parent table. An UPDATE statement against pTab -** is currently being processed. For each column of the table that is -** actually updated, the corresponding element in the aChange[] array -** is zero or greater (if a column is unmodified the corresponding element -** is set to -1). If the rowid column is modified by the UPDATE statement -** the bChngRowid argument is non-zero. -** -** This function returns true if any of the columns that are part of the -** parent key for FK constraint *p are modified. -*/ -static int fkParentIsModified( - Table *pTab, - FKey *p, - int *aChange, - int bChngRowid -){ - int i; - for(i=0; inCol; i++){ - char *zKey = p->aCol[i].zCol; - int iKey; - for(iKey=0; iKeynCol; iKey++){ - if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ - Column *pCol = &pTab->aCol[iKey]; - if( zKey ){ - if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1; - }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ - return 1; - } - } - } - } - return 0; -} - -/* -** Return true if the parser passed as the first argument is being -** used to code a trigger that is really a "SET NULL" action belonging -** to trigger pFKey. -*/ -static int isSetNullAction(Parse *pParse, FKey *pFKey){ - Parse *pTop = sqlite3ParseToplevel(pParse); - if( pTop->pTriggerPrg ){ - Trigger *p = pTop->pTriggerPrg->pTrigger; - if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) - || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) - ){ - assert( (pTop->db->flags & SQLITE_FkNoAction)==0 ); - return 1; - } - } - return 0; -} - -/* -** This function is called when inserting, deleting or updating a row of -** table pTab to generate VDBE code to perform foreign key constraint -** processing for the operation. -** -** For a DELETE operation, parameter regOld is passed the index of the -** first register in an array of (pTab->nCol+1) registers containing the -** rowid of the row being deleted, followed by each of the column values -** of the row being deleted, from left to right. Parameter regNew is passed -** zero in this case. -** -** For an INSERT operation, regOld is passed zero and regNew is passed the -** first register of an array of (pTab->nCol+1) registers containing the new -** row data. -** -** For an UPDATE operation, this function is called twice. Once before -** the original record is deleted from the table using the calling convention -** described for DELETE. Then again after the original record is deleted -** but before the new record is inserted using the INSERT convention. -*/ -SQLITE_PRIVATE void sqlite3FkCheck( - Parse *pParse, /* Parse context */ - Table *pTab, /* Row is being deleted from this table */ - int regOld, /* Previous row data is stored here */ - int regNew, /* New row data is stored here */ - int *aChange, /* Array indicating UPDATEd columns (or 0) */ - int bChngRowid /* True if rowid is UPDATEd */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - FKey *pFKey; /* Used to iterate through FKs */ - int iDb; /* Index of database containing pTab */ - const char *zDb; /* Name of database containing pTab */ - int isIgnoreErrors = pParse->disableTriggers; - - /* Exactly one of regOld and regNew should be non-zero. */ - assert( (regOld==0)!=(regNew==0) ); - - /* If foreign-keys are disabled, this function is a no-op. */ - if( (db->flags&SQLITE_ForeignKeys)==0 ) return; - if( !IsOrdinaryTable(pTab) ) return; - - iDb = 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->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; - int *aiCol; - int iCol; - int i; - int bIgnore = 0; - - if( aChange - && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 - && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 - ){ - continue; - } - - /* Find the parent table of this foreign key. Also find a unique index - ** on the parent key columns in the parent table. If either of these - ** schema items cannot be located, set an error in pParse and return - ** early. */ - if( pParse->disableTriggers ){ - pTo = sqlite3FindTable(db, pFKey->zTo, zDb); - }else{ - pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); - } - if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ - assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); - if( !isIgnoreErrors || db->mallocFailed ) return; - if( pTo==0 ){ - /* If isIgnoreErrors is true, then a table is being dropped. In this - ** case SQLite runs a "DELETE FROM xxx" on the table being dropped - ** before actually dropping it in order to check FK constraints. - ** If the parent table of an FK constraint on the current table is - ** missing, behave as if it is empty. i.e. decrement the relevant - ** FK counter for each row of the current table with non-NULL keys. - */ - Vdbe *v = sqlite3GetVdbe(pParse); - int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; - for(i=0; inCol; i++){ - int iFromCol, iReg; - iFromCol = pFKey->aCol[i].iFrom; - iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v); - } - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); - } - continue; - } - assert( pFKey->nCol==1 || (aiFree && pIdx) ); - - if( aiFree ){ - aiCol = aiFree; - }else{ - iCol = pFKey->aCol[0].iFrom; - aiCol = &iCol; - } - for(i=0; inCol; i++){ - if( aiCol[i]==pTab->iPKey ){ - aiCol[i] = -1; - } - assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Request permission to read the parent key columns. If the - ** authorization callback returns SQLITE_IGNORE, behave as if any - ** values read from the parent table are NULL. */ - if( db->xAuth ){ - int rcauth; - char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName; - rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); - bIgnore = (rcauth==SQLITE_IGNORE); - } -#endif - } - - /* Take a shared-cache advisory read-lock on the parent table. Allocate - ** a cursor to use to search the unique index on the parent key columns - ** in the parent table. */ - sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); - pParse->nTab++; - - if( regOld!=0 ){ - /* A row is being removed from the child table. Search for the parent. - ** If the parent does not exist, removing the child row resolves an - ** outstanding foreign key constraint violation. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); - } - if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ - /* A row is being added to the child table. If a parent row cannot - ** be found, adding the child row has violated the FK constraint. - ** - ** If this operation is being performed as part of a trigger program - ** that is actually a "SET NULL" action belonging to this very - ** foreign key, then omit this scan altogether. As all child key - ** values are guaranteed to be NULL, it is not possible for adding - ** this row to cause an FK violation. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); - } - - sqlite3DbFree(db, aiFree); - } - - /* Loop through all the foreign key constraints that refer to this table. - ** (the "child" constraints) */ - for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ - Index *pIdx = 0; /* Foreign key index for pFKey */ - SrcList *pSrc; - int *aiCol = 0; - - if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ - continue; - } - - if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel && !pParse->isMultiWrite - ){ - assert( regOld==0 && regNew!=0 ); - /* Inserting a single row into a parent table cannot cause (or fix) - ** an immediate foreign key violation. So do nothing in this case. */ - continue; - } - - if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ - if( !isIgnoreErrors || db->mallocFailed ) return; - continue; - } - assert( aiCol || pFKey->nCol==1 ); - - /* Create a SrcList structure containing the child table. We need the - ** child table as a SrcList for sqlite3WhereBegin() */ - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pSrc ){ - SrcItem *pItem = pSrc->a; - pItem->pSTab = pFKey->pFrom; - pItem->zName = pFKey->pFrom->zName; - pItem->pSTab->nTabRef++; - pItem->iCursor = pParse->nTab++; - - if( regNew!=0 ){ - fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); - } - if( regOld!=0 ){ - int eAction = pFKey->aAction[aChange!=0]; - if( (db->flags & SQLITE_FkNoAction) ) eAction = OE_None; - - fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); - /* If this is a deferred FK constraint, or a CASCADE or SET NULL - ** action applies, then any foreign key violations caused by - ** removing the parent key will be rectified by the action trigger. - ** So do not set the "may-abort" flag in this case. - ** - ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the - ** may-abort flag will eventually be set on this statement anyway - ** (when this function is called as part of processing the UPDATE - ** within the action trigger). - ** - ** Note 2: At first glance it may seem like SQLite could simply omit - ** all OP_FkCounter related scans when either CASCADE or SET NULL - ** applies. The trouble starts if the CASCADE or SET NULL action - ** trigger causes other triggers or action rules attached to the - ** child table to fire. In these cases the fk constraint counters - ** might be set incorrectly if any OP_FkCounter related scans are - ** omitted. */ - if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ - sqlite3MayAbort(pParse); - } - } - pItem->zName = 0; - sqlite3SrcListDelete(db, pSrc); - } - sqlite3DbFree(db, aiCol); - } -} - -#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) - -/* -** This function is called before generating code to update or delete a -** row contained in table pTab. -*/ -SQLITE_PRIVATE u32 sqlite3FkOldmask( - Parse *pParse, /* Parse context */ - Table *pTab /* Table being modified */ -){ - u32 mask = 0; - if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){ - FKey *p; - int i; - for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ - for(i=0; inCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); - } - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - Index *pIdx = 0; - sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); - if( pIdx ){ - for(i=0; inKeyCol; i++){ - assert( pIdx->aiColumn[i]>=0 ); - mask |= COLUMN_MASK(pIdx->aiColumn[i]); - } - } - } - } - return mask; -} - - -/* -** This function is called before generating code to update or delete a -** row contained in table pTab. If the operation is a DELETE, then -** parameter aChange is passed a NULL value. For an UPDATE, aChange points -** to an array of size N, where N is the number of columns in table pTab. -** If the i'th column is not modified by the UPDATE, then the corresponding -** entry in the aChange[] array is set to -1. If the column is modified, -** the value is 0 or greater. Parameter chngRowid is set to true if the -** UPDATE statement modifies the rowid fields of the table. -** -** If any foreign key processing will be required, this function returns -** non-zero. If there is no foreign key related processing, this function -** returns zero. -** -** For an UPDATE, this function returns 2 if: -** -** * 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). -** -** Or, assuming some other foreign key processing is required, 1. -*/ -SQLITE_PRIVATE int sqlite3FkRequired( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being modified */ - int *aChange, /* Non-NULL for UPDATE operations */ - int chngRowid /* True for UPDATE that affects rowid */ -){ - 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. */ - bHaveFK = (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->u.tab.pFKey; p; p=p->pNextFrom){ - if( fkChildIsModified(pTab, p, aChange, chngRowid) ){ - if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2; - bHaveFK = 1; - } - } - - /* Check if any parent key columns are being modified. */ - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - if( fkParentIsModified(pTab, p, aChange, chngRowid) ){ - if( (pParse->db->flags & SQLITE_FkNoAction)==0 - && p->aAction[1]!=OE_None - ){ - return 2; - } - bHaveFK = 1; - } - } - } - } - return bHaveFK ? eRet : 0; -} - -/* -** This function is called when an UPDATE or DELETE operation is being -** compiled on table pTab, which is the parent table of foreign-key pFKey. -** If the current operation is an UPDATE, then the pChanges parameter is -** passed a pointer to the list of columns being modified. If it is a -** DELETE, pChanges is passed a NULL pointer. -** -** 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" 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: -** -** CREATE TABLE p(pk PRIMARY KEY); -** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); -** -** then the returned trigger structure is equivalent to: -** -** CREATE TRIGGER ... DELETE ON p BEGIN -** DELETE FROM c WHERE ck = old.pk; -** END; -** -** The returned pointer is cached as part of the foreign key object. It -** is eventually freed along with the rest of the foreign key object by -** sqlite3FkDelete(). -*/ -static Trigger *fkActionTrigger( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being updated or deleted from */ - FKey *pFKey, /* Foreign key to get action for */ - ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - int action; /* One of OE_None, OE_Cascade etc. */ - Trigger *pTrigger; /* Trigger definition to return */ - int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ - - action = pFKey->aAction[iAction]; - if( (db->flags & SQLITE_FkNoAction) ) action = OE_None; - if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ - return 0; - } - pTrigger = pFKey->apTrigger[iAction]; - - if( action!=OE_None && !pTrigger ){ - char const *zFrom; /* Name of child table */ - int nFrom; /* Length in bytes of zFrom */ - Index *pIdx = 0; /* Parent key index for this FK */ - int *aiCol = 0; /* child table cols -> parent key cols */ - TriggerStep *pStep = 0; /* First (only) step of trigger program */ - Expr *pWhere = 0; /* WHERE clause of trigger step */ - ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ - Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ - int i; /* Iterator variable */ - Expr *pWhen = 0; /* WHEN clause for the trigger */ - - if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; - assert( aiCol || pFKey->nCol==1 ); - - for(i=0; inCol; i++){ - Token tOld = { "old", 3 }; /* Literal "old" token */ - Token tNew = { "new", 3 }; /* Literal "new" token */ - Token tFromCol; /* Name of column in child table */ - Token tToCol; /* Name of column in parent table */ - int iFromCol; /* Idx of column in child table */ - Expr *pEq; /* tFromCol = OLD.tToCol */ - - iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; - assert( iFromCol>=0 ); - assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); - assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); - sqlite3TokenInit(&tToCol, - pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName); - 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 - ** that the affinity and collation sequence associated with the - ** parent table are used for the comparison. */ - pEq = sqlite3PExpr(pParse, TK_EQ, - sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), - sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) - ); - pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); - - /* For ON UPDATE, construct the next term of the WHEN clause. - ** The final WHEN clause will be like this: - ** - ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) - */ - if( pChanges ){ - pEq = sqlite3PExpr(pParse, TK_IS, - sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), - sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) - ); - pWhen = sqlite3ExprAnd(pParse, pWhen, pEq); - } - - if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ - Expr *pNew; - if( action==OE_Cascade ){ - pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)); - }else if( action==OE_SetDflt ){ - Column *pCol = pFKey->pFrom->aCol + iFromCol; - Expr *pDflt; - if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - pDflt = 0; - }else{ - pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol); - } - if( pDflt ){ - pNew = sqlite3ExprDup(db, pDflt, 0); - }else{ - pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); - } - }else{ - pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); - } - pList = sqlite3ExprListAppend(pParse, pList, pNew); - sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); - } - } - sqlite3DbFree(db, aiCol); - - zFrom = pFKey->pFrom->zName; - nFrom = sqlite3Strlen30(zFrom); - - if( action==OE_Restrict ){ - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - SrcList *pSrc; - Expr *pRaise; - - pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"), - pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0); - if( pRaise ){ - pRaise->affExpr = OE_Abort; - } - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pSrc ){ - assert( pSrc->nSrc==1 ); - pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom); - assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 ); - pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); - } - pSelect = sqlite3SelectNew(pParse, - sqlite3ExprListAppend(pParse, 0, pRaise), - pSrc, - pWhere, - 0, 0, 0, 0, 0 - ); - pWhere = 0; - } - - /* Disable lookaside memory allocation */ - DisableLookaside; - - pTrigger = (Trigger *)sqlite3DbMallocZero(db, - sizeof(Trigger) + /* struct Trigger */ - sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->zTarget */ - ); - if( pTrigger ){ - pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->zTarget = (char *)&pStep[1]; - memcpy((char *)pStep->zTarget, zFrom, nFrom); - - pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); - pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - if( pWhen ){ - pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0); - pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); - } - } - - /* Re-enable the lookaside buffer, if it was disabled earlier. */ - EnableLookaside; - - sqlite3ExprDelete(db, pWhere); - sqlite3ExprDelete(db, pWhen); - sqlite3ExprListDelete(db, pList); - sqlite3SelectDelete(db, pSelect); - if( db->mallocFailed==1 ){ - fkTriggerDelete(db, pTrigger); - return 0; - } - assert( pStep!=0 ); - assert( pTrigger!=0 ); - - switch( action ){ - case OE_Restrict: - pStep->op = TK_SELECT; - break; - case OE_Cascade: - if( !pChanges ){ - pStep->op = TK_DELETE; - break; - } - /* no break */ deliberate_fall_through - default: - pStep->op = TK_UPDATE; - } - pStep->pTrig = pTrigger; - pTrigger->pSchema = pTab->pSchema; - pTrigger->pTabSchema = pTab->pSchema; - pFKey->apTrigger[iAction] = pTrigger; - pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE); - } - - return pTrigger; -} - -/* -** This function is called when deleting or updating a row to implement -** any required CASCADE, SET NULL or SET DEFAULT actions. -*/ -SQLITE_PRIVATE void sqlite3FkActions( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being updated or deleted from */ - ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ - int regOld, /* Address of array containing old row */ - int *aChange, /* Array indicating UPDATEd columns (or 0) */ - int bChngRowid /* True if rowid is UPDATEd */ -){ - /* If foreign-key support is enabled, iterate through all FKs that - ** refer to table pTab. If there is an action associated with the FK - ** for this operation (either update or delete), invoke the associated - ** trigger sub-program. */ - if( pParse->db->flags&SQLITE_ForeignKeys ){ - FKey *pFKey; /* Iterator variable */ - for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ - if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ - Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges); - if( pAct ){ - sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0); - } - } - } - } -} - -#endif /* ifndef SQLITE_OMIT_TRIGGER */ - -/* -** Free all memory associated with foreign key definitions attached to -** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash -** hash table. -*/ -SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ - FKey *pFKey; /* Iterator variable */ - FKey *pNext; /* Copy of pFKey->pNextFrom */ - - assert( IsOrdinaryTable(pTab) ); - assert( db!=0 ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){ - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); - - /* Remove the FK from the fkeyHash hash table. */ - if( db->pnBytesFreed==0 ){ - if( pFKey->pPrevTo ){ - pFKey->pPrevTo->pNextTo = pFKey->pNextTo; - }else{ - const char *z = (pFKey->pNextTo ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, pFKey->pNextTo); - } - if( pFKey->pNextTo ){ - pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; - } - } - - /* EV: R-30323-21917 Each foreign key constraint in SQLite is - ** classified as either immediate or deferred. - */ - assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 ); - - /* Delete any triggers created to implement actions for this FK. */ -#ifndef SQLITE_OMIT_TRIGGER - fkTriggerDelete(db, pFKey->apTrigger[0]); - fkTriggerDelete(db, pFKey->apTrigger[1]); -#endif - - pNext = pFKey->pNextFrom; - sqlite3DbFree(db, pFKey); - } -} -#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ - -/************** End of fkey.c ************************************************/ -/************** Begin file insert.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle INSERT statements in SQLite. -*/ -/* #include "sqliteInt.h" */ - -/* -** Generate code that will -** -** (1) acquire a lock for table pTab then -** (2) open pTab as cursor iCur. -** -** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index -** for that table that is actually opened. -*/ -SQLITE_PRIVATE void sqlite3OpenTable( - Parse *pParse, /* Generate code into this VDBE */ - int iCur, /* The cursor number of the table */ - int iDb, /* The database index in sqlite3.aDb[] */ - Table *pTab, /* The table to be opened */ - int opcode /* OP_OpenRead or OP_OpenWrite */ -){ - Vdbe *v; - assert( !IsVirtual(pTab) ); - assert( pParse->pVdbe!=0 ); - v = pParse->pVdbe; - assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - if( !pParse->db->noSharedCache ){ - sqlite3TableLock(pParse, iDb, pTab->tnum, - (opcode==OP_OpenWrite)?1:0, pTab->zName); - } - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol); - VdbeComment((v, "%s", pTab->zName)); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->tnum==pTab->tnum || CORRUPT_DB ); - sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pPk); - VdbeComment((v, "%s", pTab->zName)); - } -} - -/* -** Return a pointer to the column affinity string associated with index -** pIdx. A column affinity string has one character for each column in -** the table, according to the affinity of the column: -** -** Character Column affinity -** ------------------------------ -** 'A' BLOB -** 'B' TEXT -** 'C' NUMERIC -** 'D' INTEGER -** 'F' REAL -** -** An extra 'D' is appended to the end of the string to cover the -** rowid that appears as the last column in every index. -** -** Memory for the buffer containing the column index affinity string -** is managed along with the rest of the Index structure. It will be -** released when sqlite3DeleteIndex() is called. -*/ -static SQLITE_NOINLINE const char *computeIndexAffStr(sqlite3 *db, Index *pIdx){ - /* The first time a column affinity string for a particular index is - ** required, it is allocated and populated here. It is then stored as - ** a member of the Index structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqliteDeleteIndex() when the Index structure itself is cleaned - ** up. - */ - int n; - Table *pTab = pIdx->pTable; - pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); - if( !pIdx->zColAff ){ - sqlite3OomFault(db); - return 0; - } - for(n=0; nnColumn; n++){ - i16 x = pIdx->aiColumn[n]; - char aff; - if( x>=0 ){ - aff = pTab->aCol[x].affinity; - }else if( x==XN_ROWID ){ - aff = SQLITE_AFF_INTEGER; - }else{ - assert( x==XN_EXPR ); - assert( pIdx->bHasExpr ); - assert( pIdx->aColExpr!=0 ); - aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); - } - if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; - pIdx->zColAff[n] = aff; - } - pIdx->zColAff[n] = 0; - return pIdx->zColAff; -} -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ - if( !pIdx->zColAff ) return computeIndexAffStr(db, pIdx); - return pIdx->zColAff; -} - - -/* -** Compute an affinity string for a table. Space is obtained -** from sqlite3DbMalloc(). The caller is responsible for freeing -** the space when done. -*/ -SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){ - char *zColAff; - zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1); - if( zColAff ){ - int i, j; - for(i=j=0; inCol; i++){ - if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ - zColAff[j++] = pTab->aCol[i].affinity; - } - } - do{ - zColAff[j--] = 0; - }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB ); - } - return zColAff; -} - -/* -** 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 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 -** -** For STRICT tables: -** ------------------ -** -** Generate an appropriate 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 sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ - int i; - 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; - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - pPrev = sqlite3VdbeGetLastOp(v); - assert( pPrev!=0 ); - assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); - pPrev->opcode = OP_TypeCheck; - sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3); - }else{ - /* Insert an isolated OP_Typecheck */ - sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - } - return; - } - zColAff = pTab->zColAff; - if( zColAff==0 ){ - zColAff = sqlite3TableAffinityStr(0, pTab); - if( !zColAff ){ - sqlite3OomFault(sqlite3VdbeDb(v)); - return; - } - pTab->zColAff = zColAff; - } - assert( zColAff!=0 ); - i = sqlite3Strlen30NN(zColAff); - if( i ){ - if( iReg ){ - sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); - }else{ - assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord - || sqlite3VdbeDb(v)->mallocFailed ); - sqlite3VdbeChangeP4(v, -1, zColAff, i); - } - } -} - -/* -** Return non-zero if the table pTab in database iDb or any of its indices -** have been opened at any point in the VDBE program. This is used to see if -** a statement of the form "INSERT INTO SELECT ..." can -** run without using a temporary table for the results of the SELECT. -*/ -static int readsTable(Parse *p, int iDb, Table *pTab){ - Vdbe *v = sqlite3GetVdbe(p); - int i; - int iEnd = sqlite3VdbeCurrentAddr(v); -#ifndef SQLITE_OMIT_VIRTUALTABLE - VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; -#endif - - for(i=1; iopcode==OP_OpenRead && pOp->p3==iDb ){ - Index *pIndex; - Pgno tnum = pOp->p2; - if( tnum==pTab->tnum ){ - return 1; - } - for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( tnum==pIndex->tnum ){ - return 1; - } - } - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){ - assert( pOp->p4.pVtab!=0 ); - assert( pOp->p4type==P4_VTAB ); - return 1; - } -#endif - } - return 0; -} - -/* This walker callback will compute the union of colFlags flags for all -** referenced columns in a CHECK constraint or generated column expression. -*/ -static int exprColumnFlagUnion(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 ){ - assert( pExpr->iColumn < pWalker->u.pTab->nCol ); - pWalker->eCode |= pWalker->u.pTab->aCol[pExpr->iColumn].colFlags; - } - return WRC_Continue; -} - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* -** All regular columns for table pTab have been puts into registers -** starting with iRegStore. The registers that correspond to STORED -** or VIRTUAL columns have not yet been initialized. This routine goes -** back and computes the values for those columns based on the previously -** computed normal columns. -*/ -SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns( - Parse *pParse, /* Parsing context */ - int iRegStore, /* Register holding the first column */ - Table *pTab /* The table */ -){ - int i; - Walker w; - Column *pRedo; - int eProgress; - VdbeOp *pOp; - - assert( pTab->tabFlags & TF_HasGenerated ); - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - - /* Before computing generated columns, first go through and make sure - ** that appropriate affinity has been applied to the regular columns - */ - sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore); - if( (pTab->tabFlags & TF_HasStored)!=0 ){ - pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); - 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++; - } - }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; - } - } - - /* Because there can be multiple generated columns that refer to one another, - ** this is a two-pass algorithm. On the first pass, mark all generated - ** columns as "not available". - */ - for(i=0; inCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); - pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL; - } - } - - w.u.pTab = pTab; - w.xExprCallback = exprColumnFlagUnion; - w.xSelectCallback = 0; - w.xSelectCallback2 = 0; - - /* On the second pass, compute the value of each NOT-AVAILABLE column. - ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will - ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as - ** they are needed. - */ - pParse->iSelfTab = -iRegStore; - do{ - eProgress = 0; - pRedo = 0; - for(i=0; inCol; i++){ - Column *pCol = pTab->aCol + i; - if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){ - int x; - pCol->colFlags |= COLFLAG_BUSY; - w.eCode = 0; - sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol)); - pCol->colFlags &= ~COLFLAG_BUSY; - if( w.eCode & COLFLAG_NOTAVAIL ){ - pRedo = pCol; - continue; - } - eProgress = 1; - assert( pCol->colFlags & COLFLAG_GENERATED ); - x = sqlite3TableColumnToStorage(pTab, i) + iRegStore; - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x); - pCol->colFlags &= ~COLFLAG_NOTAVAIL; - } - } - }while( pRedo && eProgress ); - if( pRedo ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName); - } - pParse->iSelfTab = 0; -} -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - - -#ifndef SQLITE_OMIT_AUTOINCREMENT -/* -** Locate or create an AutoincInfo structure associated with table pTab -** which is in database iDb. Return the register number for the register -** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT -** table. (Also return zero when doing a VACUUM since we do not want to -** update the AUTOINCREMENT counters during a VACUUM.) -** -** There is at most one AutoincInfo structure per table even if the -** same table is autoincremented multiple times due to inserts within -** triggers. A new AutoincInfo structure is created if this is the -** first use of table pTab. On 2nd and subsequent uses, the original -** AutoincInfo structure is used. -** -** Four consecutive registers are allocated: -** -** (1) The name of the pTab table. -** (2) The maximum ROWID of pTab. -** (3) The rowid in sqlite_sequence of pTab -** (4) The original value of the max ROWID in pTab, or NULL if none -** -** The 2nd register is the one that is returned. That is all the -** insert routine needs to know about. -*/ -static int autoIncBegin( - Parse *pParse, /* Parsing context */ - int iDb, /* Index of the database holding pTab */ - Table *pTab /* The table we are writing to */ -){ - int memId = 0; /* Register holding maximum rowid */ - assert( pParse->db->aDb[iDb].pSchema!=0 ); - if( (pTab->tabFlags & TF_Autoincrement)!=0 - && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 - ){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - AutoincInfo *pInfo; - Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; - - /* Verify that the sqlite_sequence table exists and is an ordinary - ** rowid table with exactly two columns. - ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ - if( pSeqTab==0 - || !HasRowid(pSeqTab) - || NEVER(IsVirtual(pSeqTab)) - || pSeqTab->nCol!=2 - ){ - pParse->nErr++; - pParse->rc = SQLITE_CORRUPT_SEQUENCE; - return 0; - } - - pInfo = pToplevel->pAinc; - while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } - if( pInfo==0 ){ - pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); - sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo); - testcase( pParse->earlyCleanup ); - if( pParse->db->mallocFailed ) return 0; - pInfo->pNext = pToplevel->pAinc; - pToplevel->pAinc = pInfo; - pInfo->pTab = pTab; - pInfo->iDb = iDb; - pToplevel->nMem++; /* Register to hold name of table */ - pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ - pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ - } - memId = pInfo->regCtr; - } - return memId; -} - -/* -** This routine generates code that will initialize all of the -** register used by the autoincrement tracker. -*/ -SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ - AutoincInfo *p; /* Information about an AUTOINCREMENT */ - sqlite3 *db = pParse->db; /* The database connection */ - Db *pDb; /* Database only autoinc table */ - int memId; /* Register holding max rowid */ - Vdbe *v = pParse->pVdbe; /* VDBE under construction */ - - /* This routine is never called during trigger-generation. It is - ** only called from the top-level */ - assert( pParse->pTriggerTab==0 ); - assert( sqlite3IsToplevel(pParse) ); - - assert( v ); /* We failed long ago if this is not so */ - for(p = pParse->pAinc; p; p = p->pNext){ - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList autoInc[] = { - /* 0 */ {OP_Null, 0, 0, 0}, - /* 1 */ {OP_Rewind, 0, 10, 0}, - /* 2 */ {OP_Column, 0, 0, 0}, - /* 3 */ {OP_Ne, 0, 9, 0}, - /* 4 */ {OP_Rowid, 0, 0, 0}, - /* 5 */ {OP_Column, 0, 1, 0}, - /* 6 */ {OP_AddImm, 0, 0, 0}, - /* 7 */ {OP_Copy, 0, 0, 0}, - /* 8 */ {OP_Goto, 0, 11, 0}, - /* 9 */ {OP_Next, 0, 2, 0}, - /* 10 */ {OP_Integer, 0, 0, 0}, - /* 11 */ {OP_Close, 0, 0, 0} - }; - VdbeOp *aOp; - pDb = &db->aDb[p->iDb]; - memId = p->regCtr; - assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); - sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); - aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); - if( aOp==0 ) break; - aOp[0].p2 = memId; - aOp[0].p3 = memId+2; - aOp[2].p3 = memId; - aOp[3].p1 = memId-1; - aOp[3].p3 = memId; - aOp[3].p5 = SQLITE_JUMPIFNULL; - aOp[4].p2 = memId+1; - aOp[5].p3 = memId; - aOp[6].p1 = memId; - aOp[7].p2 = memId+2; - aOp[7].p1 = memId; - aOp[10].p2 = memId; - if( pParse->nTab==0 ) pParse->nTab = 1; - } -} - -/* -** Update the maximum rowid for an autoincrement calculation. -** -** This routine should be called when the regRowid register holds a -** new rowid that is about to be inserted. If that new rowid is -** larger than the maximum rowid in the memId memory cell, then the -** memory cell is updated. -*/ -static void autoIncStep(Parse *pParse, int memId, int regRowid){ - if( memId>0 ){ - sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); - } -} - -/* -** This routine generates the code needed to write autoincrement -** maximum rowid values back into the sqlite_sequence register. -** Every statement that might do an INSERT into an autoincrement -** table (either directly or through triggers) needs to call this -** routine just before the "exit" code. -*/ -static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ - AutoincInfo *p; - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - - assert( v ); - for(p = pParse->pAinc; p; p = p->pNext){ - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList autoIncEnd[] = { - /* 0 */ {OP_NotNull, 0, 2, 0}, - /* 1 */ {OP_NewRowid, 0, 0, 0}, - /* 2 */ {OP_MakeRecord, 0, 2, 0}, - /* 3 */ {OP_Insert, 0, 0, 0}, - /* 4 */ {OP_Close, 0, 0, 0} - }; - VdbeOp *aOp; - Db *pDb = &db->aDb[p->iDb]; - int iRec; - int memId = p->regCtr; - - iRec = sqlite3GetTempReg(pParse); - assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); - sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId); - VdbeCoverage(v); - sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); - if( aOp==0 ) break; - aOp[0].p1 = memId+1; - aOp[1].p2 = memId+1; - aOp[2].p1 = memId-1; - aOp[2].p3 = iRec; - aOp[3].p2 = iRec; - aOp[3].p3 = memId+1; - aOp[3].p5 = OPFLAG_APPEND; - sqlite3ReleaseTempReg(pParse, iRec); - } -} -SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ - if( pParse->pAinc ) autoIncrementEnd(pParse); -} -#else -/* -** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines -** above are all no-ops -*/ -# define autoIncBegin(A,B,C) (0) -# define autoIncStep(A,B,C) -#endif /* SQLITE_OMIT_AUTOINCREMENT */ - -/* -** If argument pVal is a Select object returned by an sqlite3MultiValues() -** that was able to use the co-routine optimization, finish coding the -** co-routine. -*/ -SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ - if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){ - SrcItem *pItem = &pVal->pSrc->a[0]; - assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr ); - if( pItem->fg.isSubquery ){ - sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn); - sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1); - } - } -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are constant. -*/ -static int exprListIsConstant(Parse *pParse, ExprList *pRow){ - int ii; - for(ii=0; iinExpr; ii++){ - if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0; - } - return 1; -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are both constant and have no affinity. -*/ -static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ - int ii; - if( exprListIsConstant(pParse,pRow)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - Expr *pExpr = pRow->a[ii].pExpr; - assert( pExpr->op!=TK_RAISE ); - assert( pExpr->affExpr==0 ); - if( 0!=sqlite3ExprAffinity(pExpr) ) return 0; - } - return 1; - -} - -/* -** This function is called by the parser for the second and subsequent -** rows of a multi-row VALUES clause. Argument pLeft is the part of -** the VALUES clause already parsed, argument pRow is the vector of values -** for the new row. The Select object returned represents the complete -** VALUES clause, including the new row. -** -** There are two ways in which this may be achieved - by incremental -** coding of a co-routine (the "co-routine" method) or by returning a -** Select object equivalent to the following (the "UNION ALL" method): -** -** "pLeft UNION ALL SELECT pRow" -** -** If the VALUES clause contains a lot of rows, this compound Select -** object may consume a lot of memory. -** -** When the co-routine method is used, each row that will be returned -** by the VALUES clause is coded into part of a co-routine as it is -** passed to this function. The returned Select object is equivalent to: -** -** SELECT * FROM ( -** Select object to read co-routine -** ) -** -** The co-routine method is used in most cases. Exceptions are: -** -** a) If the current statement has a WITH clause. This is to avoid -** statements like: -** -** WITH cte AS ( VALUES('x'), ('y') ... ) -** SELECT * FROM cte AS a, cte AS b; -** -** This will not work, as the co-routine uses a hard-coded register -** for its OP_Yield instructions, and so it is not possible for two -** cursors to iterate through it concurrently. -** -** b) The schema is currently being parsed (i.e. the VALUES clause is part -** of a schema item like a VIEW or TRIGGER). In this case there is no VM -** being generated when parsing is taking place, and so generating -** a co-routine is not possible. -** -** c) There are non-constant expressions in the VALUES clause (e.g. -** the VALUES clause is part of a correlated sub-query). -** -** d) One or more of the values in the first row of the VALUES clause -** has an affinity (i.e. is a CAST expression). This causes problems -** because the complex rules SQLite uses (see function -** sqlite3SubqueryColumnTypes() in select.c) to determine the effective -** affinity of such a column for all rows require access to all values in -** the column simultaneously. -*/ -SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - - if( pParse->bHasWith /* condition (a) above */ - || pParse->db->init.busy /* condition (b) above */ - || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ - || (pLeft->pSrc->nSrc==0 && - exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */ - || IN_SPECIAL_PARSE - ){ - /* The co-routine method cannot be used. Fall back to UNION ALL. */ - Select *pSelect = 0; - int f = SF_Values | SF_MultiValue; - if( pLeft->pSrc->nSrc ){ - sqlite3MultiValuesEnd(pParse, pLeft); - f = SF_Values; - }else if( pLeft->pPrior ){ - /* In this case set the SF_MultiValue flag only if it was set on pLeft */ - f = (f & pLeft->selFlags); - } - pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0); - pLeft->selFlags &= ~(u32)SF_MultiValue; - if( pSelect ){ - pSelect->op = TK_ALL; - pSelect->pPrior = pLeft; - pLeft = pSelect; - } - }else{ - SrcItem *p = 0; /* SrcItem that reads from co-routine */ - - if( pLeft->pSrc->nSrc==0 ){ - /* Co-routine has not yet been started and the special Select object - ** that accesses the co-routine has not yet been created. This block - ** does both those things. */ - Vdbe *v = sqlite3GetVdbe(pParse); - Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); - - /* Ensure the database schema has been read. This is to ensure we have - ** the correct text encoding. */ - if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){ - sqlite3ReadSchema(pParse); - } - - if( pRet ){ - SelectDest dest; - Subquery *pSubq; - pRet->pSrc->nSrc = 1; - pRet->pPrior = pLeft->pPrior; - pRet->op = pLeft->op; - if( pRet->pPrior ) pRet->selFlags |= SF_Values; - pLeft->pPrior = 0; - pLeft->op = TK_SELECT; - assert( pLeft->pNext==0 ); - assert( pRet->pNext==0 ); - p = &pRet->pSrc->a[0]; - p->fg.viaCoroutine = 1; - p->iCursor = -1; - assert( !p->fg.isIndexedBy && !p->fg.isTabFunc ); - p->u1.nRow = 2; - if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){ - pSubq = p->u4.pSubq; - pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; - pSubq->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, - pSubq->regReturn, 0, pSubq->addrFillSub); - sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn); - - /* Allocate registers for the output of the co-routine. Do so so - ** that there are two unused registers immediately before those - ** used by the co-routine. This allows the code in sqlite3Insert() - ** to use these registers directly, instead of copying the output - ** of the co-routine to a separate array for processing. */ - dest.iSdst = pParse->nMem + 3; - dest.nSdst = pLeft->pEList->nExpr; - pParse->nMem += 2 + dest.nSdst; - - pLeft->selFlags |= SF_MultiValue; - sqlite3Select(pParse, pLeft, &dest); - pSubq->regResult = dest.iSdst; - assert( pParse->nErr || dest.iSdst>0 ); - } - pLeft = pRet; - } - }else{ - p = &pLeft->pSrc->a[0]; - assert( !p->fg.isTabFunc && !p->fg.isIndexedBy ); - p->u1.nRow++; - } - - if( pParse->nErr==0 ){ - Subquery *pSubq; - assert( p!=0 ); - assert( p->fg.isSubquery ); - pSubq = p->u4.pSubq; - assert( pSubq!=0 ); - assert( pSubq->pSelect!=0 ); - assert( pSubq->pSelect->pEList!=0 ); - if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){ - sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect); - }else{ - sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0); - sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn); - } - } - sqlite3ExprListDelete(pParse->db, pRow); - } - - return pLeft; -} - -/* Forward declaration */ -static int xferOptimization( - Parse *pParse, /* Parser context */ - Table *pDest, /* The table we are inserting into */ - Select *pSelect, /* A SELECT statement to use as the data source */ - int onError, /* How to handle constraint errors */ - int iDbDest /* The database of pDest */ -); - -/* -** This routine is called to handle SQL of the following forms: -** -** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... -** insert into TABLE (IDLIST) select -** insert into TABLE (IDLIST) default values -** -** The IDLIST following the table name is always optional. If omitted, -** then a list of all (non-hidden) columns for the table is substituted. -** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST -** is omitted. -** -** For the pSelect parameter holds the values to be inserted for the -** first two forms shown above. A VALUES clause is really just short-hand -** for a SELECT statement that omits the FROM clause and everything else -** that follows. If the pSelect parameter is NULL, that means that the -** DEFAULT VALUES form of the INSERT statement is intended. -** -** The code generated follows one of four templates. For a simple -** insert with data coming from a single-row VALUES clause, the code executes -** once straight down through. Pseudo-code follows (we call this -** the "1st template"): -** -** open write cursor to
    and its indices -** put VALUES clause expressions into registers -** write the resulting record into
    -** cleanup -** -** The three remaining templates assume the statement is of the form -** -** INSERT INTO
    SELECT ... -** -** If the SELECT clause is of the restricted form "SELECT * FROM " - -** in other words if the SELECT pulls all columns from a single table -** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and -** if and are distinct tables but have identical -** schemas, including all the same indices, then a special optimization -** is invoked that copies raw records from over to . -** See the xferOptimization() function for the implementation of this -** template. This is the 2nd template. -** -** open a write cursor to
    -** open read cursor on -** transfer all records in over to
    -** close cursors -** foreach index on
    -** open a write cursor on the
    index -** open a read cursor on the corresponding index -** transfer all records from the read to the write cursors -** close cursors -** end foreach -** -** The 3rd template is for when the second template does not apply -** and the SELECT clause does not read from
    at any time. -** The generated code follows this template: -** -** X <- A -** goto B -** A: setup for the SELECT -** loop over the rows in the SELECT -** load values into registers R..R+n -** yield X -** end loop -** cleanup after the SELECT -** end-coroutine X -** B: open write cursor to
    and its indices -** C: yield X, at EOF goto D -** insert the select result into
    from R..R+n -** goto C -** D: cleanup -** -** The 4th template is used if the insert statement takes its -** values from a SELECT but the data is being inserted into a table -** that is also read as part of the SELECT. In the third form, -** we have to use an intermediate table to store the results of -** the select. The template is like this: -** -** X <- A -** goto B -** A: setup for the SELECT -** loop over the tables in the SELECT -** load value into register R..R+n -** yield X -** end loop -** cleanup after the SELECT -** end co-routine R -** B: open temp table -** L: yield X, at EOF goto M -** insert row from R..R+n into temp table -** goto L -** M: open write cursor to
    and its indices -** rewind temp table -** C: loop over rows of intermediate table -** transfer values form intermediate table into
    -** end loop -** D: cleanup -*/ -SQLITE_PRIVATE void sqlite3Insert( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* Name of table into which we are inserting */ - Select *pSelect, /* A SELECT statement to use as the data source */ - IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */ - int onError, /* How to handle constraint errors */ - Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ -){ - sqlite3 *db; /* The main database structure */ - Table *pTab; /* The table to insert into. aka TABLE */ - int i, j; /* Loop counters */ - Vdbe *v; /* Generate code into this virtual machine */ - Index *pIdx; /* For looping over indices of the table */ - int nColumn; /* Number of columns in the data */ - int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ - int iDataCur = 0; /* VDBE cursor that is the main data repository */ - int iIdxCur = 0; /* First index cursor */ - int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ - int endOfLoop; /* Label for the end of the insertion loop */ - int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ - int addrInsTop = 0; /* Jump to label "D" */ - int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ - SelectDest dest; /* Destination for SELECT on rhs of INSERT */ - int iDb; /* Index of database holding TABLE */ - u8 useTempTable = 0; /* Store SELECT results in intermediate table */ - u8 appendFlag = 0; /* True if the insert is likely to be an append */ - u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ - u8 bIdListInOrder; /* True if IDLIST is in table order */ - ExprList *pList = 0; /* List of VALUES() to be inserted */ - int iRegStore; /* Register in which to store next column */ - - /* Register allocations */ - int regFromSelect = 0;/* Base register for data coming from SELECT */ - int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ - int regRowCount = 0; /* Memory cell used for the row counter */ - int regIns; /* Block of regs holding rowid+data being inserted */ - int regRowid; /* registers holding insert rowid */ - int regData; /* register holding first column to insert */ - int *aRegIdx = 0; /* One register allocated to each index */ - int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True if attempting to insert into a view */ - Trigger *pTrigger; /* List of triggers on pTab, if required */ - int tmask; /* Mask of trigger times */ -#endif - - db = pParse->db; - 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 - ** single row (the common case) then keep that one row of values - ** and discard the other (unused) parts of the pSelect object - */ - if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ - pList = pSelect->pEList; - pSelect->pEList = 0; - sqlite3SelectDelete(db, pSelect); - pSelect = 0; - } - - /* Locate the table into which we will be inserting new information. - */ - assert( pTabList->nSrc==1 ); - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ){ - goto insert_cleanup; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDbnDb ); - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, - db->aDb[iDb].zDbSName) ){ - goto insert_cleanup; - } - withoutRowid = !HasRowid(pTab); - - /* Figure out if we have any triggers and if the table being - ** inserted into is a view - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); - isView = IsView(pTab); -#else -# define pTrigger 0 -# define tmask 0 -# define isView 0 -#endif -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__); - 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. - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto insert_cleanup; - } - - /* Cannot insert into a read-only table. - */ - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ - goto insert_cleanup; - } - - /* Allocate a VDBE - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto insert_cleanup; - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); - -#ifndef SQLITE_OMIT_XFER_OPT - /* If the statement is of the form - ** - ** INSERT INTO SELECT * FROM ; - ** - ** Then special optimizations can be applied that make the transfer - ** very fast and which reduce fragmentation of indices. - ** - ** This is the 2nd template. - */ - if( pColumn==0 - && pSelect!=0 - && pTrigger==0 - && xferOptimization(pParse, pTab, pSelect, onError, iDb) - ){ - assert( !pTrigger ); - assert( pList==0 ); - goto insert_end; - } -#endif /* SQLITE_OMIT_XFER_OPT */ - - /* If this is an AUTOINCREMENT table, look up the sequence number in the - ** sqlite_sequence table and store it in memory cell regAutoinc. - */ - regAutoinc = autoIncBegin(pParse, iDb, pTab); - - /* Allocate a block registers to hold the rowid and the values - ** for all columns of the new row. - */ - regRowid = regIns = pParse->nMem+1; - pParse->nMem += pTab->nCol + 1; - if( IsVirtual(pTab) ){ - regRowid++; - pParse->nMem++; - } - regData = regRowid+1; - - /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and - ** remember the column indices. - ** - ** If the table has an INTEGER PRIMARY KEY column and that column - ** is named in the IDLIST, then record in the ipkColumn variable - ** the index into IDLIST of the primary key column. ipkColumn is - ** the index of the primary key as it appears in IDLIST, not as - ** is appears in the original table. (The index of the INTEGER - ** PRIMARY KEY in the original table is pTab->iPKey.) After this - ** loop, if ipkColumn==(-1), that means that integer primary key - ** is unspecified, and hence the table is either WITHOUT ROWID or - ** it will automatically generated an integer primary key. - ** - ** bIdListInOrder is true if the columns in IDLIST are in storage - ** order. This enables an optimization that avoids shuffling the - ** columns into storage order. False negatives are harmless, - ** but false positives will cause database corruption. - */ - bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; - if( pColumn ){ - aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int)); - if( aTabColMap==0 ) goto insert_cleanup; - for(i=0; inId; i++){ - j = sqlite3ColumnIndex(pTab, pColumn->a[i].zName); - if( j>=0 ){ - if( aTabColMap[j]==0 ) aTabColMap[j] = i+1; - if( i!=j ) bIdListInOrder = 0; - if( j==pTab->iPKey ){ - ipkColumn = i; assert( !withoutRowid ); - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){ - sqlite3ErrorMsg(pParse, - "cannot INSERT into generated column \"%s\"", - pTab->aCol[j].zCnName); - goto insert_cleanup; - } -#endif - }else{ - if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ - ipkColumn = i; - bIdListInOrder = 0; - }else{ - sqlite3ErrorMsg(pParse, "table %S has no column named %s", - pTabList->a, pColumn->a[i].zName); - pParse->checkSchema = 1; - goto insert_cleanup; - } - } - } - } - - /* Figure out how many columns of data are supplied. If the data - ** is coming from a SELECT statement, then generate a co-routine that - ** produces a single row of the SELECT on each invocation. The - ** co-routine is the common header to the 3rd and 4th templates. - */ - if( pSelect ){ - /* Data is coming from a SELECT or from a multi-row VALUES clause. - ** Generate a co-routine to run the SELECT. */ - int rc; /* Result code */ - - if( pSelect->pSrc->nSrc==1 - && pSelect->pSrc->a[0].fg.viaCoroutine - && pSelect->pPrior==0 - ){ - SrcItem *pItem = &pSelect->pSrc->a[0]; - Subquery *pSubq; - assert( pItem->fg.isSubquery ); - pSubq = pItem->u4.pSubq; - dest.iSDParm = pSubq->regReturn; - regFromSelect = pSubq->regResult; - assert( pSubq->pSelect!=0 ); - assert( pSubq->pSelect->pEList!=0 ); - nColumn = pSubq->pSelect->pEList->nExpr; - ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); - if( bIdListInOrder && nColumn==pTab->nCol ){ - regData = regFromSelect; - regRowid = regData - 1; - regIns = regRowid - (IsVirtual(pTab) ? 1 : 0); - } - }else{ - int addrTop; /* Top of the co-routine */ - int regYield = ++pParse->nMem; - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - dest.iSdst = bIdListInOrder ? regData : 0; - dest.nSdst = pTab->nCol; - rc = sqlite3Select(pParse, pSelect, &dest); - regFromSelect = dest.iSdst; - assert( db->pParse==pParse ); - if( rc || pParse->nErr ) goto insert_cleanup; - assert( db->mallocFailed==0 ); - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; - } - - /* Set useTempTable to TRUE if the result of the SELECT statement - ** should be written into a temporary table (template 4). Set to - ** FALSE if each output row of the SELECT can be written directly into - ** the destination table (template 3). - ** - ** A temp table must be used if the table being updated is also one - ** of the tables being read by the SELECT statement. Also use a - ** temp table in the case of row triggers. - */ - if( pTrigger || readsTable(pParse, iDb, pTab) ){ - useTempTable = 1; - } - - if( useTempTable ){ - /* Invoke the coroutine to extract information from the SELECT - ** and add it to a transient table srcTab. The code generated - ** here is from the 4th template: - ** - ** B: open temp table - ** L: yield X, goto M at EOF - ** insert row from R..R+n into temp table - ** goto L - ** M: ... - */ - int regRec; /* Register to hold packed record */ - int regTempRowid; /* Register to hold temp table ROWID */ - int addrL; /* Label "L" */ - - srcTab = pParse->nTab++; - regRec = sqlite3GetTempReg(pParse); - regTempRowid = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); - sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); - sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeGoto(v, addrL); - sqlite3VdbeJumpHere(v, addrL); - sqlite3ReleaseTempReg(pParse, regRec); - sqlite3ReleaseTempReg(pParse, regTempRowid); - } - }else{ - /* This is the case if the data for the INSERT is coming from a - ** single-row VALUES clause - */ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - srcTab = -1; - assert( useTempTable==0 ); - if( pList ){ - nColumn = pList->nExpr; - if( sqlite3ResolveExprListNames(&sNC, pList) ){ - goto insert_cleanup; - } - }else{ - nColumn = 0; - } - } - - /* If there is no IDLIST term but the table has an integer primary - ** key, the set the ipkColumn variable to the integer primary key - ** column index in the original table definition. - */ - if( pColumn==0 && nColumn>0 ){ - ipkColumn = pTab->iPKey; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - for(i=ipkColumn-1; i>=0; i--){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); - ipkColumn--; - } - } - } -#endif - - /* 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; inCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++; - } - } - if( nColumn!=(pTab->nCol-nHidden) ){ - 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 ){ - sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); - goto insert_cleanup; - } - - /* Initialize the count of rows to be inserted - */ - if( (db->flags & SQLITE_CountRows)!=0 - && !pParse->nested - && !pParse->pTriggerTab - && !pParse->bReturning - ){ - regRowCount = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); - } - - /* If this is not a view, open the table and and all indices */ - if( !isView ){ - int nIdx; - nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, - &iDataCur, &iIdxCur); - aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+2)); - if( aRegIdx==0 ){ - goto insert_cleanup; - } - for(i=0, pIdx=pTab->pIndex; ipNext, i++){ - assert( pIdx ); - aRegIdx[i] = ++pParse->nMem; - pParse->nMem += pIdx->nColumn; - } - aRegIdx[i] = ++pParse->nMem; /* Register to store the table record */ - } -#ifndef SQLITE_OMIT_UPSERT - if( pUpsert ){ - Upsert *pNx; - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"", - pTab->zName); - goto insert_cleanup; - } - if( IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "cannot UPSERT a view"); - goto insert_cleanup; - } - if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ - goto insert_cleanup; - } - pTabList->a[0].iCursor = iDataCur; - pNx = pUpsert; - do{ - pNx->pUpsertSrc = pTabList; - pNx->regData = regData; - pNx->iDataCur = iDataCur; - pNx->iIdxCur = iIdxCur; - if( pNx->pUpsertTarget ){ - if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){ - goto insert_cleanup; - } - } - pNx = pNx->pNextUpsert; - }while( pNx!=0 ); - } -#endif - - - /* This is the top of the main insertion loop */ - if( useTempTable ){ - /* This block codes the top of loop only. The complete loop is the - ** following pseudocode (template 4): - ** - ** rewind temp table, if empty goto D - ** C: loop over rows of intermediate table - ** transfer values form intermediate table into
    - ** end loop - ** D: ... - */ - addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v); - addrCont = sqlite3VdbeCurrentAddr(v); - }else if( pSelect ){ - /* This block codes the top of loop only. The complete loop is the - ** following pseudocode (template 3): - ** - ** C: yield X, at EOF goto D - ** insert the select result into
    from R..R+n - ** goto C - ** D: ... - */ - sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0, 0); - addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - VdbeCoverage(v); - if( ipkColumn>=0 ){ - /* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the - ** SELECT, go ahead and copy the value into the rowid slot now, so that - ** the value does not get overwritten by a NULL at tag-20191021-002. */ - sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); - } - } - - /* Compute data for ordinary columns of the new entry. Values - ** are written in storage order into registers starting with regData. - ** Only ordinary columns are computed in this loop. The rowid - ** (if there is one) is computed later and generated columns are - ** computed after the rowid since they might depend on the value - ** of the rowid. - */ - nHidden = 0; - iRegStore = regData; assert( regData==regRowid+1 ); - for(i=0; inCol; i++, iRegStore++){ - int k; - u32 colFlags; - assert( i>=nHidden ); - if( i==pTab->iPKey ){ - /* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled - ** using the rowid. So put a NULL in the IPK slot of the record to avoid - ** using excess space. The file format definition requires this extra - ** NULL - we cannot optimize further by skipping the column completely */ - sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); - continue; - } - if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){ - nHidden++; - if( (colFlags & COLFLAG_VIRTUAL)!=0 ){ - /* Virtual columns do not participate in OP_MakeRecord. So back up - ** iRegStore by one slot to compensate for the iRegStore++ in the - ** outer for() loop */ - iRegStore--; - continue; - }else if( (colFlags & COLFLAG_STORED)!=0 ){ - /* Stored columns are computed later. But if there are BEFORE - ** triggers, the slots used for stored columns will be OP_Copy-ed - ** to a second block of registers, so the register needs to be - ** initialized to NULL to avoid an uninitialized register read */ - if( tmask & TRIGGER_BEFORE ){ - sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); - } - continue; - }else if( pColumn==0 ){ - /* Hidden columns that are not explicitly named in the INSERT - ** get their default value */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - } - } - if( pColumn ){ - j = aTabColMap[i]; - assert( j>=0 && j<=pColumn->nId ); - if( j==0 ){ - /* A column not named in the insert column list gets its - ** default value */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - } - k = j - 1; - }else if( nColumn==0 ){ - /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - }else{ - k = i - nHidden; - } - - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore); - }else if( pSelect ){ - if( regFromSelect!=regData ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore); - } - }else{ - Expr *pX = pList->a[k].pExpr; - int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore); - if( y!=iRegStore ){ - sqlite3VdbeAddOp2(v, - ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore); - } - } - } - - - /* Run the BEFORE and INSTEAD OF triggers, if there are any - */ - endOfLoop = sqlite3VdbeMakeLabel(pParse); - if( tmask & TRIGGER_BEFORE ){ - int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1); - - /* build the NEW.* reference row. Note that if there is an INTEGER - ** PRIMARY KEY into which a NULL is being inserted, that NULL will be - ** translated into a unique ID for the row. But on a BEFORE trigger, - ** we do not know what the unique ID will be (because the insert has - ** not happened yet) so we substitute a rowid of -1 - */ - if( ipkColumn<0 ){ - sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); - }else{ - int addr1; - assert( !withoutRowid ); - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols); - }else{ - assert( pSelect==0 ); /* Otherwise useTempTable is true */ - sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); - } - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); - } - - /* Copy the new data already generated. */ - assert( pTab->nNVCol>0 || pParse->nErr>0 ); - sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1); - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Compute the new value for generated columns after all other - ** columns have already been computed. This must be done after - ** computing the ROWID in case one of the generated columns - ** refers to the ROWID. */ - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab); - } -#endif - - /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, - ** do not attempt any conversions before assembling the record. - ** If this is a real table, attempt conversions as required by the - ** table column affinities. - */ - if( !isView ){ - sqlite3TableAffinity(v, pTab, regCols+1); - } - - /* Fire BEFORE or INSTEAD OF triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, - pTab, regCols-pTab->nCol-1, onError, endOfLoop); - - sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); - } - - if( !isView ){ - if( IsVirtual(pTab) ){ - /* The row that the VUpdate opcode will delete: none */ - sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); - } - if( ipkColumn>=0 ){ - /* Compute the new rowid */ - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid); - }else if( pSelect ){ - /* Rowid already initialized at tag-20191021-001 */ - }else{ - Expr *pIpk = pList->a[ipkColumn].pExpr; - if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){ - sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); - appendFlag = 1; - }else{ - sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); - } - } - /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid - ** to generate a unique primary key value. - */ - if( !appendFlag ){ - int addr1; - if( !IsVirtual(pTab) ){ - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); - sqlite3VdbeJumpHere(v, addr1); - }else{ - addr1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v); - } - sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v); - } - }else if( IsVirtual(pTab) || withoutRowid ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); - }else{ - sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); - appendFlag = 1; - } - autoIncStep(pParse, regAutoinc, regRowid); - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Compute the new value for generated columns after all other - ** columns have already been computed. This must be done after - ** computing the ROWID in case one of the generated columns - ** is derived from the INTEGER PRIMARY KEY. */ - if( pTab->tabFlags & TF_HasGenerated ){ - sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab); - } -#endif - - /* Generate code to check constraints and generate index keys and - ** do the insertion. - */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); - sqlite3MayAbort(pParse); - }else -#endif - { - int isReplace = 0;/* Set to true if constraints may cause a replace */ - int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ - sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert - ); - if( db->flags & SQLITE_ForeignKeys ){ - sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); - } - - /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE - ** constraints or (b) there are no triggers and this table is not a - ** parent table in a foreign key constraint. It is safe to set the - ** flag in the second case as if any REPLACE constraint is hit, an - ** OP_Delete or OP_IdxDelete instruction will be executed on each - ** cursor that is disturbed. And these instructions both clear the - ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT - ** functionality. */ - bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v)); - sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, - 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. */ - sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); -#endif - } - - /* Update the count of rows that are inserted - */ - if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); - } - - if( pTrigger ){ - /* Code AFTER triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, - pTab, regData-2-pTab->nCol, onError, endOfLoop); - } - - /* The bottom of the main insertion loop, if the data source - ** is a SELECT statement. - */ - sqlite3VdbeResolveLabel(v, endOfLoop); - if( useTempTable ){ - sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrInsTop); - sqlite3VdbeAddOp1(v, OP_Close, srcTab); - }else if( pSelect ){ - sqlite3VdbeGoto(v, addrCont); -#ifdef SQLITE_DEBUG - /* If we are jumping back to an OP_Yield that is preceded by an - ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the - ** OP_ReleaseReg will be included in the loop. */ - if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){ - assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield ); - sqlite3VdbeChangeP5(v, 1); - } -#endif - 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. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* - ** Return the number of rows inserted. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. - */ - if( regRowCount ){ - sqlite3CodeChangeCount(v, regRowCount, "rows inserted"); - } - -insert_cleanup: - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprListDelete(db, pList); - sqlite3UpsertDelete(db, pUpsert); - sqlite3SelectDelete(db, pSelect); - if( pColumn ){ - sqlite3IdListDelete(db, pColumn); - sqlite3DbFree(db, aTabColMap); - } - if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx); -} - -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif -#ifdef tmask - #undef tmask -#endif - -/* -** Meanings of bits in of pWalker->eCode for -** sqlite3ExprReferencesUpdatedColumn() -*/ -#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ -#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ - -/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). -* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this -** expression node references any of the -** columns that are being modified by an UPDATE statement. -*/ -static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN ){ - assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); - if( pExpr->iColumn>=0 ){ - if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){ - pWalker->eCode |= CKCNSTRNT_COLUMN; - } - }else{ - pWalker->eCode |= CKCNSTRNT_ROWID; - } - } - return WRC_Continue; -} - -/* -** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The -** only columns that are modified by the UPDATE are those for which -** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. -** -** Return true if CHECK constraint pExpr uses any of the -** changing columns (or the rowid if it is changing). In other words, -** return true if this CHECK constraint must be validated for -** the new row in the UPDATE statement. -** -** 2018-09-15: pExpr might also be an expression for an index-on-expressions. -** The operation of this routine is the same - return true if an only if -** the expression uses one or more of columns identified by the second and -** third arguments. -*/ -SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn( - Expr *pExpr, /* The expression to be checked */ - int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ - int chngRowid /* True if UPDATE changes the rowid */ -){ - Walker w; - memset(&w, 0, sizeof(w)); - w.eCode = 0; - w.xExprCallback = checkConstraintExprNode; - w.u.aiCol = aiChng; - sqlite3WalkExpr(&w, pExpr); - if( !chngRowid ){ - testcase( (w.eCode & CKCNSTRNT_ROWID)!=0 ); - w.eCode &= ~CKCNSTRNT_ROWID; - } - testcase( w.eCode==0 ); - testcase( w.eCode==CKCNSTRNT_COLUMN ); - testcase( w.eCode==CKCNSTRNT_ROWID ); - testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); - return w.eCode!=0; -} - -/* -** The 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. -** -** The regNewData parameter is the first register in a range that contains -** the data to be inserted or the data after the update. There will be -** pTab->nCol+1 registers in this range. The first register (the one -** that regNewData points to) will contain the new rowid, or NULL in the -** case of a WITHOUT ROWID table. The second register in the range will -** contain the content of the first table column. The third register will -** contain the content of the second table column. And so forth. -** -** The regOldData parameter is similar to regNewData except that it contains -** the data prior to an UPDATE rather than afterwards. regOldData is zero -** for an INSERT. This routine can distinguish between UPDATE and INSERT by -** checking regOldData for zero. -** -** For an UPDATE, the pkChng boolean is true if the true primary key (the -** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table) -** might be modified by the UPDATE. If pkChng is false, then the key of -** the iDataCur content table is guaranteed to be unchanged by the UPDATE. -** -** For an INSERT, the pkChng boolean indicates whether or not the rowid -** was explicitly specified as part of the INSERT statement. If pkChng -** is zero, it means that the either rowid is computed automatically or -** that the table is a WITHOUT ROWID table and has no rowid. On an INSERT, -** pkChng will only be true if the INSERT statement provides an integer -** value for either the rowid column or its INTEGER PRIMARY KEY alias. -** -** The code generated by this routine will store new index entries into -** registers identified by aRegIdx[]. No index entry is created for -** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is -** the same as the order of indices on the linked list of indices -** at pTab->pIndex. -** -** (2019-05-07) The generated code also creates a new record for the -** main table, if pTab is a rowid table, and stores that record in the -** register identified by aRegIdx[nIdx] - in other words in the first -** entry of aRegIdx[] past the last index. It is important that the -** record be generated during constraint checks to avoid affinity changes -** to the register content that occur after constraint checks but before -** the new record is inserted. -** -** The caller must have already opened writeable cursors on the main -** table and all applicable indices (that is to say, all indices for which -** aRegIdx[] is not zero). iDataCur is the cursor for the main table when -** inserting or updating a rowid table, or the cursor for the PRIMARY KEY -** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor -** for the first index in the pTab->pIndex list. Cursors for other indices -** are at iIdxCur+N for the N-th element of the pTab->pIndex list. -** -** This routine also generates code to check constraints. NOT NULL, -** CHECK, and UNIQUE constraints are all checked. If a constraint fails, -** then the appropriate action is performed. There are five possible -** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. -** -** Constraint type Action What Happens -** --------------- ---------- ---------------------------------------- -** any ROLLBACK The current transaction is rolled back and -** sqlite3_step() returns immediately with a -** return code of SQLITE_CONSTRAINT. -** -** any ABORT Back out changes from the current command -** only (do not do a complete rollback) then -** cause sqlite3_step() to return immediately -** with SQLITE_CONSTRAINT. -** -** any FAIL Sqlite3_step() returns immediately with a -** return code of SQLITE_CONSTRAINT. The -** transaction is not rolled back and any -** changes to prior rows are retained. -** -** any IGNORE The attempt in insert or update the current -** row is skipped, without throwing an error. -** Processing continues with the next row. -** (There is an immediate jump to ignoreDest.) -** -** NOT NULL REPLACE The NULL value is replace by the default -** value for that column. If the default value -** is NULL, the action is the same as ABORT. -** -** UNIQUE REPLACE The other row that conflicts with the row -** being inserted is removed. -** -** CHECK REPLACE Illegal. The results in an exception. -** -** Which action to take is determined by the overrideError parameter. -** Or if overrideError==OE_Default, then the pParse->onError parameter -** is used. Or if pParse->onError==OE_Default then the onError value -** for the constraint is used. -*/ -SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( - Parse *pParse, /* The parser context */ - Table *pTab, /* The table being inserted or updated */ - int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */ - int iDataCur, /* Canonical data cursor (main table or PK index) */ - int iIdxCur, /* First index cursor */ - int regNewData, /* First register in a range holding values to insert */ - int regOldData, /* Previous content. 0 for INSERTs */ - u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ - u8 overrideError, /* Override onError to this if not OE_Default */ - int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ - int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ - int *aiChng, /* column i is unchanged if aiChng[i]<0 */ - Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ -){ - Vdbe *v; /* VDBE under construction */ - Index *pIdx; /* Pointer to one of the indices */ - Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */ - sqlite3 *db; /* Database connection */ - int i; /* loop counter */ - int ix; /* Index loop counter */ - int nCol; /* Number of columns */ - 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 */ - 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 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 - ** replace triggers fire have run */ - int regTrigCnt; /* Register used to count replace trigger invocations */ - int addrRecheck = 0; /* Jump here to recheck all uniqueness constraints */ - 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( !IsView(pTab) ); /* This table is not a VIEW */ - nCol = pTab->nCol; - - /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for - ** normal rowid tables. nPkField is the number of key fields in the - ** pPk index or 1 for a rowid table. In other words, nPkField is the - ** number of fields in the true primary key of the table. */ - if( HasRowid(pTab) ){ - pPk = 0; - nPkField = 1; - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - nPkField = pPk->nKeyCol; - } - - /* Record that this module has started */ - VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)", - iDataCur, iIdxCur, regNewData, regOldData, pkChng)); - - /* Test all NOT NULL constraints. - */ - if( pTab->tabFlags & TF_HasNotNull ){ - int b2ndPass = 0; /* True if currently running 2nd pass */ - int nSeenReplace = 0; /* Number of ON CONFLICT REPLACE operations */ - int nGenerated = 0; /* Number of generated columns with NOT NULL */ - while(1){ /* Make 2 passes over columns. Exit loop via "break" */ - for(i=0; iaCol[i]; /* The column to check for NOT NULL */ - int isGenerated; /* non-zero if column is generated */ - onError = pCol->notNull; - if( onError==OE_None ) continue; /* No NOT NULL on this column */ - if( i==pTab->iPKey ){ - continue; /* ROWID is never NULL */ - } - isGenerated = pCol->colFlags & COLFLAG_GENERATED; - if( isGenerated && !b2ndPass ){ - nGenerated++; - continue; /* Generated columns processed on 2nd pass */ - } - if( aiChng && aiChng[i]<0 && !isGenerated ){ - /* Do not check NOT NULL on columns that do not change */ - continue; - } - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( onError==OE_Replace ){ - if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */ - || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */ - ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - testcase( pCol->colFlags & COLFLAG_GENERATED ); - onError = OE_Abort; - }else{ - assert( !isGenerated ); - } - }else if( b2ndPass && !isGenerated ){ - continue; - } - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); - testcase( i!=sqlite3TableColumnToStorage(pTab, i) ); - iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1; - switch( onError ){ - case OE_Replace: { - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg); - VdbeCoverage(v); - assert( (pCol->colFlags & COLFLAG_GENERATED)==0 ); - nSeenReplace++; - sqlite3ExprCodeCopy(pParse, - sqlite3ColumnExpr(pTab, pCol), iReg); - sqlite3VdbeJumpHere(v, addr1); - break; - } - case OE_Abort: - sqlite3MayAbort(pParse); - /* no break */ deliberate_fall_through - case OE_Rollback: - case OE_Fail: { - char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, - pCol->zCnName); - testcase( zMsg==0 && db->mallocFailed==0 ); - sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, - onError, iReg); - sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); - sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); - VdbeCoverage(v); - break; - } - default: { - assert( onError==OE_Ignore ); - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest); - VdbeCoverage(v); - break; - } - } /* end switch(onError) */ - } /* end loop i over columns */ - if( nGenerated==0 && nSeenReplace==0 ){ - /* If there are no generated columns with NOT NULL constraints - ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single - ** pass is sufficient */ - break; - } - if( b2ndPass ) break; /* Never need more than 2 passes */ - b2ndPass = 1; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){ - /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the - ** first pass, recomputed values for all generated columns, as - ** those values might depend on columns affected by the REPLACE. - */ - sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab); - } -#endif - } /* end of 2-pass loop */ - } /* end if( has-not-null-constraints ) */ - - /* Test all CHECK constraints - */ -#ifndef SQLITE_OMIT_CHECK - if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ - ExprList *pCheck = pTab->pCheck; - pParse->iSelfTab = -(regNewData+1); - onError = overrideError!=OE_Default ? overrideError : OE_Abort; - for(i=0; inExpr; i++){ - int allOk; - Expr *pCopy; - Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng - && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) - ){ - /* The check constraints do not reference any of the columns being - ** updated so there is no point it verifying the check constraint */ - continue; - } - if( bAffinityDone==0 ){ - sqlite3TableAffinity(v, pTab, regNewData+1); - bAffinityDone = 1; - } - allOk = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeVerifyAbortable(v, onError); - pCopy = sqlite3ExprDup(db, pExpr, 0); - if( !db->mallocFailed ){ - sqlite3ExprIfTrue(pParse, pCopy, allOk, SQLITE_JUMPIFNULL); - } - sqlite3ExprDelete(db, pCopy); - if( onError==OE_Ignore ){ - sqlite3VdbeGoto(v, ignoreDest); - }else{ - char *zName = pCheck->a[i].zEName; - assert( zName!=0 || pParse->db->mallocFailed ); - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */ - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, - onError, zName, P4_TRANSIENT, - P5_ConstraintCheck); - } - sqlite3VdbeResolveLabel(v, allOk); - } - pParse->iSelfTab = 0; - } -#endif /* !defined(SQLITE_OMIT_CHECK) */ - - /* UNIQUE and PRIMARY KEY constraints should be handled in the following - ** order: - ** - ** (1) OE_Update - ** (2) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore - ** (3) OE_Replace - ** - ** OE_Fail and OE_Ignore must happen before any changes are made. - ** OE_Update guarantees that only a single row will change, so it - ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback - ** could happen in any order, but they are grouped up front for - ** convenience. - ** - ** 2018-08-14: Ticket https://sqlite.org/src/info/908f001483982c43 - ** The order of constraints used to have OE_Update as (2) and OE_Abort - ** and so forth as (1). But apparently PostgreSQL checks the OE_Update - ** constraint before any others, so it had to be moved. - ** - ** Constraint checking code is generated in this order: - ** (A) The rowid constraint - ** (B) Unique index constraints that do not have OE_Replace as their - ** default conflict resolution strategy - ** (C) Unique index that do use OE_Replace by default. - ** - ** The ordering of (2) and (3) is accomplished by making sure the linked - ** list of indexes attached to a table puts all OE_Replace indexes last - ** in the list. See 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 ){ - /* 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 = 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 ); - } - } - - /* Determine if it is possible that triggers (either explicitly coded - ** triggers or FK resolution actions) might run as a result of deletes - ** that happen when OE_Replace conflict resolution occurs. (Call these - ** "replace triggers".) If any replace triggers run, we will need to - ** recheck all of the uniqueness constraints after they have all run. - ** But on the recheck, the resolution is OE_Abort instead of OE_Replace. - ** - ** If replace triggers are a possibility, then - ** - ** (1) Allocate register regTrigCnt and initialize it to zero. - ** That register will count the number of replace triggers that - ** fire. Constraint recheck only occurs if the number is positive. - ** (2) Initialize pTrigger to the list of all DELETE triggers on pTab. - ** (3) Initialize addrRecheck and lblRecheckOk - ** - ** The uniqueness rechecking code will create a series of tests to run - ** in a second pass. The addrRecheck and lblRecheckOk variables are - ** used to link together these tests which are separated from each other - ** in the generate bytecode. - */ - if( (db->flags & (SQLITE_RecTriggers|SQLITE_ForeignKeys))==0 ){ - /* There are not DELETE triggers nor FK constraints. No constraint - ** rechecks are needed. */ - pTrigger = 0; - regTrigCnt = 0; - }else{ - if( db->flags&SQLITE_RecTriggers ){ - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0); - }else{ - pTrigger = 0; - regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0); - } - if( regTrigCnt ){ - /* Replace triggers might exist. Allocate the counter and - ** initialize it to zero. */ - regTrigCnt = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regTrigCnt); - VdbeComment((v, "trigger count")); - lblRecheckOk = sqlite3VdbeMakeLabel(pParse); - addrRecheck = lblRecheckOk; - } - } - - /* If rowid is changing, make sure the new rowid does not previously - ** exist in the table. - */ - if( pkChng && pPk==0 ){ - int addrRowidOk = sqlite3VdbeMakeLabel(pParse); - - /* Figure out what action to take in case of a rowid collision */ - onError = pTab->keyConf; - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - - /* figure out whether or not upsert applies in this case */ - if( pUpsert ){ - pUpsertClause = 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 = sqlite3VdbeAddOp0(v, OP_Goto); - } - } - - /* If the response to a rowid conflict is REPLACE but the response - ** to some other UNIQUE constraint is FAIL or IGNORE, then we need - ** to defer the running of the rowid conflict checking until after - ** the UNIQUE constraints have run. - */ - if( onError==OE_Replace /* IPK rule is REPLACE */ - && onError!=overrideError /* Rules for other constraints are different */ - && pTab->pIndex /* There exist other constraints */ - && !upsertIpkDelay /* IPK check already deferred by UPSERT */ - ){ - ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; - VdbeComment((v, "defer IPK REPLACE until last")); - } - - if( isUpdate ){ - /* pkChng!=0 does not mean that the rowid has changed, only that - ** it might have changed. Skip the conflict logic below if the rowid - ** is unchanged. */ - sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - VdbeCoverage(v); - } - - /* Check to see if the new rowid already exists in the table. Skip - ** the following conflict logic if it does not. */ - VdbeNoopComment((v, "uniqueness check for ROWID")); - sqlite3VdbeVerifyAbortable(v, onError); - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); - VdbeCoverage(v); - - switch( onError ){ - default: { - onError = OE_Abort; - /* no break */ deliberate_fall_through - } - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - testcase( onError==OE_Rollback ); - testcase( onError==OE_Abort ); - testcase( onError==OE_Fail ); - sqlite3RowidConstraint(pParse, onError, pTab); - break; - } - case OE_Replace: { - /* If there are DELETE triggers on this table and the - ** recursive-triggers flag is set, call GenerateRowDelete() to - ** remove the conflicting row from the table. This will fire - ** the triggers and remove both the table and index b-tree entries. - ** - ** Otherwise, if there are no triggers or the recursive-triggers - ** flag is not set, but the table has one or more indexes, call - ** GenerateRowIndexDelete(). This removes the index b-tree entries - ** only. The table b-tree entry will be replaced by the new entry - ** when it is inserted. - ** - ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, - ** also invoke MultiWrite() to indicate that this VDBE may require - ** statement rollback (if the statement is aborted after the delete - ** takes place). Earlier versions called sqlite3MultiWrite() regardless, - ** but being more selective here allows statements like: - ** - ** REPLACE INTO t(rowid) VALUES($newrowid) - ** - ** to run without a statement journal if there are no indexes on the - ** table. - */ - if( regTrigCnt ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regNewData, 1, 0, OE_Replace, 1, -1); - sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ - nReplaceTrig++; - }else{ -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - assert( HasRowid(pTab) ); - /* This OP_Delete opcode fires the pre-update-hook only. It does - ** not modify the b-tree. It is more efficient to let the coming - ** OP_Insert replace the existing entry than it is to delete the - ** existing entry and then insert a new one. */ - sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); -#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - if( pTab->pIndex ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); - } - } - seenReplace = 1; - break; - } -#ifndef SQLITE_OMIT_UPSERT - case OE_Update: { - sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); - /* no break */ deliberate_fall_through - } -#endif - case OE_Ignore: { - testcase( onError==OE_Ignore ); - sqlite3VdbeGoto(v, ignoreDest); - break; - } - } - sqlite3VdbeResolveLabel(v, addrRowidOk); - if( pUpsert && pUpsertClause!=pUpsert ){ - upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto); - }else if( ipkTop ){ - ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, ipkTop-1); - } - } - - /* Test all UNIQUE constraints by creating entries for each UNIQUE - ** index and making sure that duplicate entries do not already exist. - ** Compute the revised record entries for indices as we go. - ** - ** This loop also handles the case of the PRIMARY KEY index for a - ** WITHOUT ROWID table. - */ - for(pIdx = indexIteratorFirst(&sIdxIter, &ix); - pIdx; - pIdx = indexIteratorNext(&sIdxIter, &ix) - ){ - int regIdx; /* Range of registers holding content for pIdx */ - int regR; /* Range of registers holding conflicting PK */ - int iThisCur; /* Cursor for this UNIQUE index */ - int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ - int addrConflictCk; /* First opcode in the conflict check logic */ - - if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ - if( pUpsert ){ - pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx); - if( upsertIpkDelay && pUpsertClause==pUpsert ){ - sqlite3VdbeJumpHere(v, upsertIpkDelay); - } - } - addrUniqueOk = sqlite3VdbeMakeLabel(pParse); - if( bAffinityDone==0 ){ - sqlite3TableAffinity(v, pTab, regNewData+1); - bAffinityDone = 1; - } - VdbeNoopComment((v, "prep index %s", pIdx->zName)); - iThisCur = iIdxCur+ix; - - - /* Skip partial indices for which the WHERE clause is not true */ - if( pIdx->pPartIdxWhere ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); - pParse->iSelfTab = -(regNewData+1); - sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, - SQLITE_JUMPIFNULL); - pParse->iSelfTab = 0; - } - - /* Create a record for this index entry as it should appear after - ** the insert or update. Store that record in the aRegIdx[ix] register - */ - regIdx = aRegIdx[ix]+1; - for(i=0; inColumn; i++){ - int iField = pIdx->aiColumn[i]; - int x; - if( iField==XN_EXPR ){ - pParse->iSelfTab = -(regNewData+1); - sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); - pParse->iSelfTab = 0; - VdbeComment((v, "%s column %d", pIdx->zName, i)); - }else if( iField==XN_ROWID || iField==pTab->iPKey ){ - x = regNewData; - sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i); - VdbeComment((v, "rowid")); - }else{ - testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField ); - x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1; - sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i); - VdbeComment((v, "%s", pTab->aCol[iField].zCnName)); - } - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); - VdbeComment((v, "for %s", pIdx->zName)); -#ifdef SQLITE_ENABLE_NULL_TRIM - if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ - sqlite3SetMakeRecordP5(v, pIdx->pTable); - } -#endif - sqlite3VdbeReleaseRegisters(pParse, regIdx, pIdx->nColumn, 0, 0); - - /* In an UPDATE operation, if this index is the PRIMARY KEY index - ** of a WITHOUT ROWID table and there has been no change the - ** primary key, then no collision is possible. The collision detection - ** logic below can all be skipped. */ - if( isUpdate && pPk==pIdx && pkChng==0 ){ - sqlite3VdbeResolveLabel(v, addrUniqueOk); - continue; - } - - /* Find out what action to take in case there is a uniqueness conflict */ - onError = pIdx->onError; - if( onError==OE_None ){ - sqlite3VdbeResolveLabel(v, addrUniqueOk); - continue; /* pIdx is not a UNIQUE index */ - } - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - - /* Figure out if the upsert clause applies to this index */ - if( pUpsertClause ){ - if( pUpsertClause->isDoUpdate==0 ){ - onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ - }else{ - onError = OE_Update; /* DO UPDATE */ - } - } - - /* Collision detection may be omitted if all of the following are true: - ** (1) The conflict resolution algorithm is REPLACE - ** (2) The table is a WITHOUT ROWID table - ** (3) There are no secondary indexes on the table - ** (4) No delete triggers need to be fired if there is a conflict - ** (5) No FK constraint counters need to be updated if a conflict occurs. - ** - ** 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 */ - && onError==OE_Replace /* Condition 1 */ - && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ - 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) - && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ - (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab))) - ){ - sqlite3VdbeResolveLabel(v, addrUniqueOk); - continue; - } -#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */ - - /* Check to see if the new index entry will be unique */ - sqlite3VdbeVerifyAbortable(v, onError); - addrConflictCk = - sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, - regIdx, pIdx->nKeyCol); VdbeCoverage(v); - - /* Generate code to handle collisions */ - regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField); - if( isUpdate || onError==OE_Replace ){ - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); - /* Conflict only if the rowid of the existing index entry - ** is different from old-rowid */ - if( isUpdate ){ - sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - VdbeCoverage(v); - } - }else{ - int x; - /* Extract the PRIMARY KEY from the end of the index entry and - ** store it in registers regR..regR+nPk-1 */ - if( pIdx!=pPk ){ - for(i=0; inKeyCol; i++){ - assert( pPk->aiColumn[i]>=0 ); - x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); - sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); - VdbeComment((v, "%s.%s", pTab->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. 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 - ** KEY values of this row before the update. */ - int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; - int op = OP_Ne; - int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); - - for(i=0; inKeyCol; i++){ - char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); - x = pPk->aiColumn[i]; - assert( x>=0 ); - if( i==(pPk->nKeyCol-1) ){ - addrJump = addrUniqueOk; - op = OP_Eq; - } - x = sqlite3TableColumnToStorage(pTab, x); - sqlite3VdbeAddOp4(v, op, - regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ - ); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - VdbeCoverageIf(v, op==OP_Eq); - VdbeCoverageIf(v, op==OP_Ne); - } - } - } - } - - /* Generate code that executes if the new index entry is not unique */ - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); - switch( onError ){ - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - testcase( onError==OE_Rollback ); - testcase( onError==OE_Abort ); - testcase( onError==OE_Fail ); - sqlite3UniqueConstraint(pParse, onError, pIdx); - break; - } -#ifndef SQLITE_OMIT_UPSERT - case OE_Update: { - sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix); - /* no break */ deliberate_fall_through - } -#endif - case OE_Ignore: { - testcase( onError==OE_Ignore ); - sqlite3VdbeGoto(v, ignoreDest); - break; - } - default: { - int nConflictCk; /* Number of opcodes in conflict check logic */ - - assert( onError==OE_Replace ); - nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk; - assert( nConflictCk>0 || db->mallocFailed ); - testcase( nConflictCk<=0 ); - testcase( nConflictCk>1 ); - if( regTrigCnt ){ - sqlite3MultiWrite(pParse); - nReplaceTrig++; - } - if( pTrigger && isUpdate ){ - sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur); - } - sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regR, nPkField, 0, OE_Replace, - (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); - if( pTrigger && isUpdate ){ - sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur); - } - if( regTrigCnt ){ - int addrBypass; /* Jump destination to bypass recheck logic */ - - sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ - addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */ - VdbeComment((v, "bypass recheck")); - - /* Here we insert code that will be invoked after all constraint - ** checks have run, if and only if one or more replace triggers - ** fired. */ - sqlite3VdbeResolveLabel(v, lblRecheckOk); - lblRecheckOk = sqlite3VdbeMakeLabel(pParse); - if( pIdx->pPartIdxWhere ){ - /* Bypass the recheck if this partial index is not defined - ** for the current row */ - sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk); - VdbeCoverage(v); - } - /* Copy the constraint check code from above, except change - ** the constraint-ok jump destination to be the address of - ** the next retest block */ - while( nConflictCk>0 ){ - VdbeOp x; /* Conflict check opcode to copy */ - /* The sqlite3VdbeAddOp4() call might reallocate the opcode array. - ** Hence, make a complete copy of the opcode, rather than using - ** a pointer to the opcode. */ - x = *sqlite3VdbeGetOp(v, addrConflictCk); - if( x.opcode!=OP_IdxRowid ){ - int p2; /* New P2 value for copied conflict check opcode */ - const char *zP4; - if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){ - p2 = lblRecheckOk; - }else{ - p2 = x.p2; - } - zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z; - sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type); - sqlite3VdbeChangeP5(v, x.p5); - VdbeCoverageIf(v, p2!=x.p2); - } - nConflictCk--; - addrConflictCk++; - } - /* If the retest fails, issue an abort */ - sqlite3UniqueConstraint(pParse, OE_Abort, pIdx); - - sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */ - } - seenReplace = 1; - break; - } - } - sqlite3VdbeResolveLabel(v, addrUniqueOk); - if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); - if( pUpsertClause - && upsertIpkReturn - && sqlite3UpsertNextIsIPK(pUpsertClause) - ){ - sqlite3VdbeGoto(v, upsertIpkDelay+1); - sqlite3VdbeJumpHere(v, upsertIpkReturn); - upsertIpkReturn = 0; - } - } - - /* If the IPK constraint is a REPLACE, run it last */ - if( ipkTop ){ - sqlite3VdbeGoto(v, ipkTop); - VdbeComment((v, "Do IPK REPLACE")); - assert( ipkBottom>0 ); - sqlite3VdbeJumpHere(v, ipkBottom); - } - - /* Recheck all uniqueness constraints after replace triggers have run */ - testcase( regTrigCnt!=0 && nReplaceTrig==0 ); - assert( regTrigCnt!=0 || nReplaceTrig==0 ); - if( nReplaceTrig ){ - sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v); - if( !pPk ){ - if( isUpdate ){ - sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData); - VdbeCoverage(v); - sqlite3RowidConstraint(pParse, OE_Abort, pTab); - }else{ - sqlite3VdbeGoto(v, addrRecheck); - } - sqlite3VdbeResolveLabel(v, lblRecheckOk); - } - - /* Generate the table record */ - if( HasRowid(pTab) ){ - int regRec = aRegIdx[ix]; - sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec); - sqlite3SetMakeRecordP5(v, pTab); - if( !bAffinityDone ){ - sqlite3TableAffinity(v, pTab, 0); - } - } - - *pbMayReplace = seenReplace; - VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); -} - -#ifdef SQLITE_ENABLE_NULL_TRIM -/* -** Change the P5 operand on the last opcode (which should be an OP_MakeRecord) -** to be the number of columns in table pTab that must not be NULL-trimmed. -** -** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero. -*/ -SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){ - u16 i; - - /* Records with omitted columns are only allowed for schema format - ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ - if( pTab->pSchema->file_format<2 ) return; - - for(i=pTab->nCol-1; i>0; i--){ - if( pTab->aCol[i].iDflt!=0 ) break; - if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; - } - sqlite3VdbeChangeP5(v, i+1); -} -#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 = sqlite3GetTempReg(pParse); - assert( !HasRowid(pTab) ); - assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB ); - sqlite3VdbeAddOp2(v, OP_Integer, 0, r); - sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE); - sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP); - 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 sqlite3GenerateConstraintChecks. -** A consecutive range of registers starting at regNewData contains the -** rowid and the content to be inserted. -** -** The arguments to this routine should be the same as the first six -** arguments to sqlite3GenerateConstraintChecks. -*/ -SQLITE_PRIVATE void sqlite3CompleteInsertion( - Parse *pParse, /* The parser context */ - Table *pTab, /* the table into which we are inserting */ - int iDataCur, /* Cursor of the canonical data source */ - int iIdxCur, /* First index cursor */ - int regNewData, /* Range of content */ - int *aRegIdx, /* Register used by each index. 0 for unused indices */ - int update_flags, /* True for UPDATE, False for INSERT */ - int appendBias, /* True if this is likely to be an append */ - int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ -){ - Vdbe *v; /* Prepared statements under construction */ - Index *pIdx; /* An index being inserted or updated */ - u8 pik_flags; /* flag values passed to the btree insert */ - int i; /* Loop counter */ - - assert( update_flags==0 - || update_flags==OPFLAG_ISUPDATE - || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION) - ); - - v = pParse->pVdbe; - assert( v!=0 ); - 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 - || pIdx->pNext==0 - || pIdx->pNext->onError==OE_Replace ); - if( aRegIdx[i]==0 ) continue; - if( pIdx->pPartIdxWhere ){ - sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - } - pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - pik_flags |= OPFLAG_NCHANGE; - pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); - if( update_flags==0 ){ - codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]); - } - } - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], - aRegIdx[i]+1, - pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); - sqlite3VdbeChangeP5(v, pik_flags); - } - if( !HasRowid(pTab) ) return; - if( pParse->nested ){ - pik_flags = 0; - }else{ - pik_flags = OPFLAG_NCHANGE; - pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID); - } - if( appendBias ){ - pik_flags |= OPFLAG_APPEND; - } - if( useSeekResult ){ - pik_flags |= OPFLAG_USESEEKRESULT; - } - sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, aRegIdx[i], regNewData); - if( !pParse->nested ){ - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - } - sqlite3VdbeChangeP5(v, pik_flags); -} - -/* -** Allocate cursors for the pTab table and all its indices and generate -** code to open and initialized those cursors. -** -** The cursor for the object that contains the complete data (normally -** the table itself, but the PRIMARY KEY index in the case of a WITHOUT -** ROWID table) is returned in *piDataCur. The first index cursor is -** returned in *piIdxCur. The number of indices is returned. -** -** Use iBase as the first cursor (either the *piDataCur for rowid tables -** or the first index for WITHOUT ROWID tables) if it is non-negative. -** If iBase is negative, then allocate the next available cursor. -** -** For a rowid table, *piDataCur will be exactly one less than *piIdxCur. -** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range -** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the -** pTab->pIndex list. -** -** If pTab is a virtual table, then this routine is a no-op and the -** *piDataCur and *piIdxCur values are left uninitialized. -*/ -SQLITE_PRIVATE int sqlite3OpenTableAndIndices( - Parse *pParse, /* Parsing context */ - Table *pTab, /* Table to be opened */ - int op, /* OP_OpenRead or OP_OpenWrite */ - u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ - int iBase, /* Use this for the table cursor, if there is one */ - u8 *aToOpen, /* If not NULL: boolean for each table and index */ - int *piDataCur, /* Write the database source cursor number here */ - int *piIdxCur /* Write the first index cursor number here */ -){ - int i; - int iDb; - int iDataCur; - Index *pIdx; - Vdbe *v; - - assert( op==OP_OpenRead || op==OP_OpenWrite ); - assert( op==OP_OpenWrite || p5==0 ); - assert( piDataCur!=0 ); - assert( piIdxCur!=0 ); - if( IsVirtual(pTab) ){ - /* This routine is a no-op for virtual tables. Leave the output - ** variables *piDataCur and *piIdxCur set to illegal cursor numbers - ** for improved error detection. */ - *piDataCur = *piIdxCur = -999; - return 0; - } - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - v = pParse->pVdbe; - assert( v!=0 ); - if( iBase<0 ) iBase = pParse->nTab; - iDataCur = iBase++; - *piDataCur = iDataCur; - if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ - sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); - }else if( pParse->db->noSharedCache==0 ){ - sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); - } - *piIdxCur = iBase; - for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - int iIdxCur = iBase++; - assert( pIdx->pSchema==pTab->pSchema ); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - *piDataCur = iIdxCur; - p5 = 0; - } - if( aToOpen==0 || aToOpen[i+1] ){ - sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - sqlite3VdbeChangeP5(v, p5); - VdbeComment((v, "%s", pIdx->zName)); - } - } - if( iBase>pParse->nTab ) pParse->nTab = iBase; - return i; -} - - -#ifdef SQLITE_TEST -/* -** The following global variable is incremented whenever the -** transfer optimization is used. This is used for testing -** purposes only - to make sure the transfer optimization really -** is happening when it is supposed to. -*/ -SQLITE_API int sqlite3_xferopt_count; -#endif /* SQLITE_TEST */ - - -#ifndef SQLITE_OMIT_XFER_OPT -/* -** Check to see if index pSrc is compatible as a source of data -** for index pDest in an insert transfer optimization. The rules -** for a compatible index: -** -** * The index is over the same set of columns -** * The same DESC and ASC markings occurs on all columns -** * The same onError processing (OE_Abort, OE_Ignore, etc) -** * The same collating sequence on each column -** * The index has the exact same WHERE clause -*/ -static int xferCompatibleIndex(Index *pDest, Index *pSrc){ - int i; - assert( pDest && pSrc ); - assert( pDest->pTable!=pSrc->pTable ); - if( pDest->nKeyCol!=pSrc->nKeyCol || pDest->nColumn!=pSrc->nColumn ){ - return 0; /* Different number of columns */ - } - if( pDest->onError!=pSrc->onError ){ - return 0; /* Different conflict resolution strategies */ - } - for(i=0; inKeyCol; i++){ - if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ - return 0; /* Different columns indexed */ - } - if( pSrc->aiColumn[i]==XN_EXPR ){ - assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); - if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr, - pDest->aColExpr->a[i].pExpr, -1)!=0 ){ - return 0; /* Different expressions in the index */ - } - } - if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ - return 0; /* Different sort orders */ - } - if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){ - return 0; /* Different collating sequences */ - } - } - if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ - return 0; /* Different WHERE clauses */ - } - - /* If no test above fails then the indices must be compatible */ - return 1; -} - -/* -** Attempt the transfer optimization on INSERTs of the form -** -** INSERT INTO tab1 SELECT * FROM tab2; -** -** The xfer optimization transfers raw records from tab2 over to tab1. -** Columns are not decoded and reassembled, which greatly improves -** performance. Raw index records are transferred in the same way. -** -** The xfer optimization is only attempted if tab1 and tab2 are compatible. -** There are lots of rules for determining compatibility - see comments -** embedded in the code for details. -** -** This routine returns TRUE if the optimization is guaranteed to be used. -** Sometimes the xfer optimization will only work if the destination table -** is empty - a factor that can only be determined at run-time. In that -** case, this routine generates code for the xfer optimization but also -** does a test to see if the destination table is empty and jumps over the -** xfer optimization code if the test fails. In that case, this routine -** returns FALSE so that the caller will know to go ahead and generate -** an unoptimized transfer. This routine also returns FALSE if there -** is no chance that the xfer optimization can be applied. -** -** This optimization is particularly useful at making VACUUM run faster. -*/ -static int xferOptimization( - Parse *pParse, /* Parser context */ - Table *pDest, /* The table we are inserting into */ - Select *pSelect, /* A SELECT statement to use as the data source */ - int onError, /* How to handle constraint errors */ - int iDbDest /* The database of pDest */ -){ - sqlite3 *db = pParse->db; - 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 */ - 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 */ - int addr1, addr2; /* Loop addresses */ - int emptyDestTest = 0; /* Address of test for empty pDest */ - int emptySrcTest = 0; /* Address of test for empty pSrc */ - Vdbe *v; /* The VDBE we are building */ - int regAutoinc; /* Memory register used by AUTOINC */ - int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ - int regData, regRowid; /* Registers holding data and rowid */ - - 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; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pDest) ){ - return 0; /* tab1 must not be a virtual table */ - } -#endif - if( onError==OE_Default ){ - if( pDest->iPKey>=0 ) onError = pDest->keyConf; - if( onError==OE_Default ) onError = OE_Abort; - } - assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ - if( pSelect->pSrc->nSrc!=1 ){ - return 0; /* FROM clause must have exactly one term */ - } - if( pSelect->pSrc->a[0].fg.isSubquery ){ - return 0; /* FROM clause cannot contain a subquery */ - } - if( pSelect->pWhere ){ - return 0; /* SELECT may not have a WHERE clause */ - } - if( pSelect->pOrderBy ){ - return 0; /* SELECT may not have an ORDER BY clause */ - } - /* Do not need to test for a HAVING clause. If HAVING is present but - ** there is no ORDER BY, we will get an error. */ - if( pSelect->pGroupBy ){ - return 0; /* SELECT may not have a GROUP BY clause */ - } - if( pSelect->pLimit ){ - return 0; /* SELECT may not have a LIMIT clause */ - } - if( pSelect->pPrior ){ - return 0; /* SELECT may not be a compound query */ - } - if( pSelect->selFlags & SF_Distinct ){ - return 0; /* SELECT may not be DISTINCT */ - } - pEList = pSelect->pEList; - assert( pEList!=0 ); - if( pEList->nExpr!=1 ){ - return 0; /* The result set must have exactly one column */ - } - assert( pEList->a[0].pExpr ); - if( pEList->a[0].pExpr->op!=TK_ASTERISK ){ - return 0; /* The result set must be the special operator "*" */ - } - - /* At this point we have established that the statement is of the - ** correct syntactic form to participate in this optimization. Now - ** we have to check the semantics. - */ - pItem = pSelect->pSrc->a; - pSrc = sqlite3LocateTableItem(pParse, 0, pItem); - if( pSrc==0 ){ - return 0; /* FROM clause does not contain a real table */ - } - if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){ - testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */ - return 0; /* tab1 and tab2 may not be the same table */ - } - if( HasRowid(pDest)!=HasRowid(pSrc) ){ - return 0; /* source and destination must both be WITHOUT ROWID or not */ - } - 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 */ - } - 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; inCol; i++){ - Column *pDestCol = &pDest->aCol[i]; - Column *pSrcCol = &pSrc->aCol[i]; -#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS - if( (db->mDbFlags & DBFLAG_Vacuum)==0 - && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN - ){ - return 0; /* Neither table may have __hidden__ columns */ - } -#endif -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Even if tables t1 and t2 have identical schemas, if they contain - ** generated columns, then this statement is semantically incorrect: - ** - ** INSERT INTO t2 SELECT * FROM t1; - ** - ** The reason is that generated column values are returned by the - ** the SELECT statement on the right but the INSERT statement on the - ** left wants them to be omitted. - ** - ** Nevertheless, this is a useful notational shorthand to tell SQLite - ** to do a bulk transfer all of the content from t1 over to t2. - ** - ** We could, in theory, disable this (except for internal use by the - ** VACUUM command where it is actually needed). But why do that? It - ** seems harmless enough, and provides a useful service. - */ - if( (pDestCol->colFlags & COLFLAG_GENERATED) != - (pSrcCol->colFlags & COLFLAG_GENERATED) ){ - return 0; /* Both columns have the same generated-column type */ - } - /* But the transfer is only allowed if both the source and destination - ** tables have the exact same expressions for generated columns. - ** This requirement could be relaxed for VIRTUAL columns, I suppose. - */ - if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){ - if( sqlite3ExprCompare(0, - sqlite3ColumnExpr(pSrc, pSrcCol), - sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){ - testcase( pDestCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pDestCol->colFlags & COLFLAG_STORED ); - return 0; /* Different generator expressions */ - } - } -#endif - if( pDestCol->affinity!=pSrcCol->affinity ){ - return 0; /* Affinity must be the same on all columns */ - } - if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol), - sqlite3ColumnColl(pSrcCol))!=0 ){ - return 0; /* Collating sequence must be the same on all columns */ - } - if( pDestCol->notNull && !pSrcCol->notNull ){ - return 0; /* tab2 must be NOT NULL if tab1 is */ - } - /* Default values for second and subsequent columns need to match. */ - if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){ - Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol); - Expr *pSrcExpr = 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 */ - } - } - } - for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - if( IsUniqueIndex(pDestIdx) ){ - destHasUniqueIdx = 1; - } - for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ - if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; - } - if( pSrcIdx==0 ){ - return 0; /* pDestIdx has no corresponding index in pSrc */ - } - if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema - && sqlite3FaultSim(411)==SQLITE_OK ){ - /* The sqlite3FaultSim() call allows this corruption test to be - ** bypassed during testing, in order to exercise other corruption tests - ** further downstream. */ - return 0; /* Corrupt schema - two indexes on the same btree */ - } - } -#ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck - && (db->mDbFlags & DBFLAG_Vacuum)==0 - && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) - ){ - return 0; /* Tables have different CHECK constraints. Ticket #2252 */ - } -#endif -#ifndef SQLITE_OMIT_FOREIGN_KEY - /* Disallow the transfer optimization if the destination table contains - ** any foreign key constraints. This is more restrictive than necessary. - ** But the main beneficiary of the transfer optimization is the VACUUM - ** command, and the VACUUM command disables foreign key constraints. So - ** the extra complication to make this rule less restrictive is probably - ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] - */ - assert( IsOrdinaryTable(pDest) ); - if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){ - return 0; - } -#endif - if( (db->flags & SQLITE_CountRows)!=0 ){ - return 0; /* xfer opt does not play well with PRAGMA count_changes */ - } - - /* If we get this far, it means that the xfer optimization is at - ** least a possibility, though it might only work if the destination - ** table (tab1) is initially empty. - */ -#ifdef SQLITE_TEST - sqlite3_xferopt_count++; -#endif - iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); - v = sqlite3GetVdbe(pParse); - sqlite3CodeVerifySchema(pParse, iDbSrc); - iSrc = pParse->nTab++; - iDest = pParse->nTab++; - regAutoinc = autoIncBegin(pParse, iDbDest, pDest); - regData = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, regData); - regRowid = sqlite3GetTempReg(pParse); - sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); - assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 && ( - (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ - || destHasUniqueIdx /* (2) */ - || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - )){ - /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. Unless the - ** DBFLAG_Vacuum flag is set, this block generates code to make - ** that determination. If DBFLAG_Vacuum is set, then the destination - ** table is always empty. - ** - ** Conditions under which the destination must be empty: - ** - ** (1) There is no INTEGER PRIMARY KEY but there are indices. - ** (If the destination is not initially empty, the rowid fields - ** of index entries might need to change.) - ** - ** (2) The destination has a unique index. (The xfer optimization - ** is unable to test uniqueness.) - ** - ** (3) onError is something other than OE_Abort and OE_Rollback. - */ - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); - emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, addr1); - } - if( HasRowid(pSrc) ){ - u8 insFlags; - sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); - emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); - if( pDest->iPKey>=0 ){ - addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeVerifyAbortable(v, onError); - addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); - VdbeCoverage(v); - sqlite3RowidConstraint(pParse, onError, pDest); - sqlite3VdbeJumpHere(v, addr2); - } - autoIncStep(pParse, regAutoinc, regRowid); - }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){ - addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); - }else{ - addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); - assert( (pDest->tabFlags & TF_Autoincrement)==0 ); - } - - if( db->mDbFlags & DBFLAG_Vacuum ){ - sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); - insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; - }else{ - insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT; - } -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - insFlags &= ~OPFLAG_PREFORMAT; - }else -#endif - { - sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid); - } - sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE); - } - sqlite3VdbeChangeP5(v, insFlags); - - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - }else{ - sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); - sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); - } - for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - u8 idxInsFlags = 0; - for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ - if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; - } - assert( pSrcIdx ); - sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc); - sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx); - VdbeComment((v, "%s", pSrcIdx->zName)); - sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); - sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); - sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); - VdbeComment((v, "%s", pDestIdx->zName)); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); - if( db->mDbFlags & DBFLAG_Vacuum ){ - /* This INSERT command is part of a VACUUM operation, which guarantees - ** that the destination table is empty. If all indexed columns use - ** collation sequence BINARY, then it can also be assumed that the - ** index will be populated by inserting keys in strictly sorted - ** order. In this case, instead of seeking within the b-tree as part - ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the - ** OP_IdxInsert to seek to the point within the b-tree where each key - ** should be inserted. This is faster. - ** - ** If any of the indexed columns use a collation sequence other than - ** BINARY, this optimization is disabled. This is because the user - ** might change the definition of a collation sequence and then run - ** a VACUUM command. In that case keys may not be written in strictly - ** sorted order. */ - for(i=0; inColumn; i++){ - const char *zColl = pSrcIdx->azColl[i]; - if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break; - } - if( i==pSrcIdx->nColumn ){ - idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; - sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); - sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc); - } - }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ - idxInsFlags |= OPFLAG_NCHANGE; - } - if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){ - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 - && !HasRowid(pDest) - && IsPrimaryKeyIndex(pDestIdx) - ){ - codeWithoutRowidPreupdate(pParse, pDest, iDest, regData); - } - } - sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); - sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - } - if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); - sqlite3ReleaseTempReg(pParse, regRowid); - sqlite3ReleaseTempReg(pParse, regData); - if( emptyDestTest ){ - sqlite3AutoincrementEnd(pParse); - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); - sqlite3VdbeJumpHere(v, emptyDestTest); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - return 0; - }else{ - return 1; - } -} -#endif /* SQLITE_OMIT_XFER_OPT */ - -/************** End of insert.c **********************************************/ -/************** Begin file legacy.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Main file for the SQLite library. The routines in this file -** implement the programmer interface to the library. Routines in -** other files are for internal use by SQLite and should not be -** accessed by users of the library. -*/ - -/* #include "sqliteInt.h" */ - -/* -** Execute SQL code. Return one of the SQLITE_ success/failure -** codes. Also write an error message into memory obtained from -** malloc() and make *pzErrMsg point to that message. -** -** If the SQL is a query, then for each row in the query result -** the xCallback() function is called. pArg becomes the first -** argument to xCallback(). If xCallback=NULL then no callback -** is invoked, even for queries. -*/ -SQLITE_API int sqlite3_exec( - sqlite3 *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - sqlite3_callback xCallback, /* Invoke this callback routine */ - void *pArg, /* First argument to xCallback() */ - char **pzErrMsg /* Write error messages here */ -){ - int rc = SQLITE_OK; /* Return code */ - const char *zLeftover; /* Tail of unprocessed SQL */ - sqlite3_stmt *pStmt = 0; /* The current SQL statement */ - char **azCols = 0; /* Names of result columns */ - int callbackIsInit; /* True if callback data is initialized */ - - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; - if( zSql==0 ) zSql = ""; - - sqlite3_mutex_enter(db->mutex); - sqlite3Error(db, SQLITE_OK); - while( rc==SQLITE_OK && zSql[0] ){ - int nCol = 0; - char **azVals = 0; - - pStmt = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); - assert( rc==SQLITE_OK || pStmt==0 ); - if( rc!=SQLITE_OK ){ - continue; - } - if( !pStmt ){ - /* this happens for a comment or white-space */ - zSql = zLeftover; - continue; - } - callbackIsInit = 0; - - while( 1 ){ - int i; - rc = sqlite3_step(pStmt); - - /* Invoke the callback function if required */ - if( xCallback && (SQLITE_ROW==rc || - (SQLITE_DONE==rc && !callbackIsInit - && db->flags&SQLITE_NullCallback)) ){ - if( !callbackIsInit ){ - nCol = sqlite3_column_count(pStmt); - azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*)); - if( azCols==0 ){ - goto exec_out; - } - for(i=0; ierrMask)==rc ); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/************** End of legacy.c **********************************************/ -/************** Begin file loadext.c *****************************************/ -/* -** 2006 June 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to dynamically load extensions into -** the SQLite library. -*/ - -#ifndef SQLITE_CORE - #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ -#endif -/************** Include sqlite3ext.h in the middle of loadext.c **************/ -/************** Begin file sqlite3ext.h **************************************/ -/* -** 2006 June 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the SQLite interface for use by -** shared libraries that want to be imported as extensions into -** an SQLite instance. Shared libraries that intend to be loaded -** as extensions by SQLite should #include this file instead of -** sqlite3.h. -*/ -#ifndef SQLITE3EXT_H -#define SQLITE3EXT_H -/* #include "sqlite3.h" */ - -/* -** The following structure holds pointers to all of the SQLite API -** routines. -** -** WARNING: In order to maintain backwards compatibility, add new -** interfaces to the end of this structure only. If you insert new -** interfaces in the middle of this structure, then older different -** versions of SQLite will not be able to load each other's shared -** libraries! -*/ -struct sqlite3_api_routines { - void * (*aggregate_context)(sqlite3_context*,int nBytes); - int (*aggregate_count)(sqlite3_context*); - int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); - int (*bind_double)(sqlite3_stmt*,int,double); - int (*bind_int)(sqlite3_stmt*,int,int); - int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); - int (*bind_null)(sqlite3_stmt*,int); - int (*bind_parameter_count)(sqlite3_stmt*); - int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); - const char * (*bind_parameter_name)(sqlite3_stmt*,int); - int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); - int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); - int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); - int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); - int (*busy_timeout)(sqlite3*,int ms); - int (*changes)(sqlite3*); - int (*close)(sqlite3*); - int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const char*)); - int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const void*)); - const void * (*column_blob)(sqlite3_stmt*,int iCol); - int (*column_bytes)(sqlite3_stmt*,int iCol); - int (*column_bytes16)(sqlite3_stmt*,int iCol); - int (*column_count)(sqlite3_stmt*pStmt); - const char * (*column_database_name)(sqlite3_stmt*,int); - const void * (*column_database_name16)(sqlite3_stmt*,int); - const char * (*column_decltype)(sqlite3_stmt*,int i); - const void * (*column_decltype16)(sqlite3_stmt*,int); - double (*column_double)(sqlite3_stmt*,int iCol); - int (*column_int)(sqlite3_stmt*,int iCol); - sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); - const char * (*column_name)(sqlite3_stmt*,int); - const void * (*column_name16)(sqlite3_stmt*,int); - const char * (*column_origin_name)(sqlite3_stmt*,int); - const void * (*column_origin_name16)(sqlite3_stmt*,int); - const char * (*column_table_name)(sqlite3_stmt*,int); - const void * (*column_table_name16)(sqlite3_stmt*,int); - const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); - const void * (*column_text16)(sqlite3_stmt*,int iCol); - int (*column_type)(sqlite3_stmt*,int iCol); - sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); - void * (*commit_hook)(sqlite3*,int(*)(void*),void*); - int (*complete)(const char*sql); - int (*complete16)(const void*sql); - int (*create_collation)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_collation16)(sqlite3*,const void*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_function)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_function16)(sqlite3*,const void*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); - int (*data_count)(sqlite3_stmt*pStmt); - sqlite3 * (*db_handle)(sqlite3_stmt*); - int (*declare_vtab)(sqlite3*,const char*); - int (*enable_shared_cache)(int); - int (*errcode)(sqlite3*db); - const char * (*errmsg)(sqlite3*); - const void * (*errmsg16)(sqlite3*); - int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); - int (*expired)(sqlite3_stmt*); - int (*finalize)(sqlite3_stmt*pStmt); - void (*free)(void*); - void (*free_table)(char**result); - int (*get_autocommit)(sqlite3*); - void * (*get_auxdata)(sqlite3_context*,int); - int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); - int (*global_recover)(void); - void (*interruptx)(sqlite3*); - sqlite_int64 (*last_insert_rowid)(sqlite3*); - const char * (*libversion)(void); - int (*libversion_number)(void); - void *(*malloc)(int); - char * (*mprintf)(const char*,...); - int (*open)(const char*,sqlite3**); - int (*open16)(const void*,sqlite3**); - int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); - void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); - void *(*realloc)(void*,int); - int (*reset)(sqlite3_stmt*pStmt); - void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_double)(sqlite3_context*,double); - void (*result_error)(sqlite3_context*,const char*,int); - void (*result_error16)(sqlite3_context*,const void*,int); - void (*result_int)(sqlite3_context*,int); - void (*result_int64)(sqlite3_context*,sqlite_int64); - void (*result_null)(sqlite3_context*); - void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); - void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_value)(sqlite3_context*,sqlite3_value*); - void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); - int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, - const char*,const char*),void*); - void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); - char * (*xsnprintf)(int,char*,const char*,...); - int (*step)(sqlite3_stmt*); - int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, - char const**,char const**,int*,int*,int*); - void (*thread_cleanup)(void); - int (*total_changes)(sqlite3*); - void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); - int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); - void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, - sqlite_int64),void*); - void * (*user_data)(sqlite3_context*); - const void * (*value_blob)(sqlite3_value*); - int (*value_bytes)(sqlite3_value*); - int (*value_bytes16)(sqlite3_value*); - double (*value_double)(sqlite3_value*); - int (*value_int)(sqlite3_value*); - sqlite_int64 (*value_int64)(sqlite3_value*); - int (*value_numeric_type)(sqlite3_value*); - const unsigned char * (*value_text)(sqlite3_value*); - const void * (*value_text16)(sqlite3_value*); - const void * (*value_text16be)(sqlite3_value*); - const void * (*value_text16le)(sqlite3_value*); - int (*value_type)(sqlite3_value*); - char *(*vmprintf)(const char*,va_list); - /* Added ??? */ - int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); - /* Added by 3.3.13 */ - int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - int (*clear_bindings)(sqlite3_stmt*); - /* Added by 3.4.1 */ - int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, - void (*xDestroy)(void *)); - /* Added by 3.5.0 */ - int (*bind_zeroblob)(sqlite3_stmt*,int,int); - int (*blob_bytes)(sqlite3_blob*); - int (*blob_close)(sqlite3_blob*); - int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, - int,sqlite3_blob**); - int (*blob_read)(sqlite3_blob*,void*,int,int); - int (*blob_write)(sqlite3_blob*,const void*,int,int); - int (*create_collation_v2)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*), - void(*)(void*)); - int (*file_control)(sqlite3*,const char*,int,void*); - sqlite3_int64 (*memory_highwater)(int); - sqlite3_int64 (*memory_used)(void); - sqlite3_mutex *(*mutex_alloc)(int); - void (*mutex_enter)(sqlite3_mutex*); - void (*mutex_free)(sqlite3_mutex*); - void (*mutex_leave)(sqlite3_mutex*); - int (*mutex_try)(sqlite3_mutex*); - int (*open_v2)(const char*,sqlite3**,int,const char*); - int (*release_memory)(int); - void (*result_error_nomem)(sqlite3_context*); - void (*result_error_toobig)(sqlite3_context*); - int (*sleep)(int); - void (*soft_heap_limit)(int); - sqlite3_vfs *(*vfs_find)(const char*); - int (*vfs_register)(sqlite3_vfs*,int); - int (*vfs_unregister)(sqlite3_vfs*); - int (*xthreadsafe)(void); - void (*result_zeroblob)(sqlite3_context*,int); - void (*result_error_code)(sqlite3_context*,int); - int (*test_control)(int, ...); - void (*randomness)(int,void*); - sqlite3 *(*context_db_handle)(sqlite3_context*); - int (*extended_result_codes)(sqlite3*,int); - int (*limit)(sqlite3*,int,int); - sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); - const char *(*sql)(sqlite3_stmt*); - int (*status)(int,int*,int*,int); - int (*backup_finish)(sqlite3_backup*); - sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); - int (*backup_pagecount)(sqlite3_backup*); - int (*backup_remaining)(sqlite3_backup*); - int (*backup_step)(sqlite3_backup*,int); - const char *(*compileoption_get)(int); - int (*compileoption_used)(const char*); - int (*create_function_v2)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*)); - int (*db_config)(sqlite3*,int,...); - sqlite3_mutex *(*db_mutex)(sqlite3*); - int (*db_status)(sqlite3*,int,int*,int*,int); - int (*extended_errcode)(sqlite3*); - void (*log)(int,const char*,...); - sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); - const char *(*sourceid)(void); - int (*stmt_status)(sqlite3_stmt*,int,int); - int (*strnicmp)(const char*,const char*,int); - int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); - int (*wal_autocheckpoint)(sqlite3*,int); - int (*wal_checkpoint)(sqlite3*,const char*); - void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); - int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); - int (*vtab_config)(sqlite3*,int op,...); - int (*vtab_on_conflict)(sqlite3*); - /* Version 3.7.16 and later */ - int (*close_v2)(sqlite3*); - const char *(*db_filename)(sqlite3*,const char*); - int (*db_readonly)(sqlite3*,const char*); - int (*db_release_memory)(sqlite3*); - const char *(*errstr)(int); - int (*stmt_busy)(sqlite3_stmt*); - int (*stmt_readonly)(sqlite3_stmt*); - int (*stricmp)(const char*,const char*); - int (*uri_boolean)(const char*,const char*,int); - sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); - const char *(*uri_parameter)(const char*,const char*); - char *(*xvsnprintf)(int,char*,const char*,va_list); - int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); - /* Version 3.8.7 and later */ - int (*auto_extension)(void(*)(void)); - int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, - void(*)(void*)); - int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, - void(*)(void*),unsigned char); - int (*cancel_auto_extension)(void(*)(void)); - int (*load_extension)(sqlite3*,const char*,const char*,char**); - void *(*malloc64)(sqlite3_uint64); - sqlite3_uint64 (*msize)(void*); - void *(*realloc64)(void*,sqlite3_uint64); - void (*reset_auto_extension)(void); - void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, - void(*)(void*)); - void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, - void(*)(void*), unsigned char); - int (*strglob)(const char*,const char*); - /* Version 3.8.11 and later */ - sqlite3_value *(*value_dup)(const sqlite3_value*); - void (*value_free)(sqlite3_value*); - int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); - int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); - /* Version 3.9.0 and later */ - unsigned int (*value_subtype)(sqlite3_value*); - void (*result_subtype)(sqlite3_context*,unsigned int); - /* Version 3.10.0 and later */ - int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); - int (*strlike)(const char*,const char*,unsigned int); - int (*db_cacheflush)(sqlite3*); - /* Version 3.12.0 and later */ - int (*system_errno)(sqlite3*); - /* Version 3.14.0 and later */ - int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); - char *(*expanded_sql)(sqlite3_stmt*); - /* Version 3.18.0 and later */ - void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); - /* Version 3.20.0 and later */ - int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, - sqlite3_stmt**,const char**); - int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, - sqlite3_stmt**,const void**); - int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); - void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); - void *(*value_pointer)(sqlite3_value*,const char*); - int (*vtab_nochange)(sqlite3_context*); - int (*value_nochange)(sqlite3_value*); - const char *(*vtab_collation)(sqlite3_index_info*,int); - /* Version 3.24.0 and later */ - int (*keyword_count)(void); - int (*keyword_name)(int,const char**,int*); - int (*keyword_check)(const char*,int); - sqlite3_str *(*str_new)(sqlite3*); - char *(*str_finish)(sqlite3_str*); - void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); - void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); - void (*str_append)(sqlite3_str*, const char *zIn, int N); - void (*str_appendall)(sqlite3_str*, const char *zIn); - void (*str_appendchar)(sqlite3_str*, int N, char C); - void (*str_reset)(sqlite3_str*); - int (*str_errcode)(sqlite3_str*); - int (*str_length)(sqlite3_str*); - char *(*str_value)(sqlite3_str*); - /* Version 3.25.0 and later */ - int (*create_window_function)(sqlite3*,const char*,int,int,void*, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInv)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*)); - /* Version 3.26.0 and later */ - const char *(*normalized_sql)(sqlite3_stmt*); - /* Version 3.28.0 and later */ - int (*stmt_isexplain)(sqlite3_stmt*); - int (*value_frombind)(sqlite3_value*); - /* Version 3.30.0 and later */ - int (*drop_modules)(sqlite3*,const char**); - /* Version 3.31.0 and later */ - sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64); - const char *(*uri_key)(const char*,int); - const char *(*filename_database)(const char*); - const char *(*filename_journal)(const char*); - const char *(*filename_wal)(const char*); - /* Version 3.32.0 and later */ - const char *(*create_filename)(const char*,const char*,const char*, - int,const char**); - void (*free_filename)(const char*); - sqlite3_file *(*database_file_object)(const char*); - /* Version 3.34.0 and later */ - int (*txn_state)(sqlite3*,const char*); - /* Version 3.36.1 and later */ - sqlite3_int64 (*changes64)(sqlite3*); - sqlite3_int64 (*total_changes64)(sqlite3*); - /* Version 3.37.0 and later */ - int (*autovacuum_pages)(sqlite3*, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, void(*)(void*)); - /* Version 3.38.0 and later */ - int (*error_offset)(sqlite3*); - int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**); - int (*vtab_distinct)(sqlite3_index_info*); - int (*vtab_in)(sqlite3_index_info*,int,int); - int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); - int (*vtab_in_next)(sqlite3_value*,sqlite3_value**); - /* Version 3.39.0 and later */ - int (*deserialize)(sqlite3*,const char*,unsigned char*, - sqlite3_int64,sqlite3_int64,unsigned); - unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, - unsigned int); - const char *(*db_name)(sqlite3*,int); - /* Version 3.40.0 and later */ - int (*value_encoding)(sqlite3_value*); - /* Version 3.41.0 and later */ - int (*is_interrupted)(sqlite3*); - /* Version 3.43.0 and later */ - int (*stmt_explain)(sqlite3_stmt*,int); - /* Version 3.44.0 and later */ - void *(*get_clientdata)(sqlite3*,const char*); - int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); - /* Version 3.50.0 and later */ - int (*setlk_timeout)(sqlite3*,int,int); -}; - -/* -** This is the function signature used for all extension entry points. It -** is also defined in the file "loadext.c". -*/ -typedef int (*sqlite3_loadext_entry)( - sqlite3 *db, /* Handle to the database. */ - char **pzErrMsg, /* Used to set error string on failure. */ - const sqlite3_api_routines *pThunk /* Extension API function pointers. */ -); - -/* -** The following macros redefine the API routines so that they are -** redirected through the global sqlite3_api structure. -** -** This header file is also used by the loadext.c source file -** (part of the main SQLite library - not an extension) so that -** it can get access to the sqlite3_api_routines structure -** definition. But the main library does not want to redefine -** the API. So the redefinition macros are only valid if the -** SQLITE_CORE macros is undefined. -*/ -#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) -#define sqlite3_aggregate_context sqlite3_api->aggregate_context -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_aggregate_count sqlite3_api->aggregate_count -#endif -#define sqlite3_bind_blob sqlite3_api->bind_blob -#define sqlite3_bind_double sqlite3_api->bind_double -#define sqlite3_bind_int sqlite3_api->bind_int -#define sqlite3_bind_int64 sqlite3_api->bind_int64 -#define sqlite3_bind_null sqlite3_api->bind_null -#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count -#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index -#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name -#define sqlite3_bind_text sqlite3_api->bind_text -#define sqlite3_bind_text16 sqlite3_api->bind_text16 -#define sqlite3_bind_value sqlite3_api->bind_value -#define sqlite3_busy_handler sqlite3_api->busy_handler -#define sqlite3_busy_timeout sqlite3_api->busy_timeout -#define sqlite3_changes sqlite3_api->changes -#define sqlite3_close sqlite3_api->close -#define sqlite3_collation_needed sqlite3_api->collation_needed -#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 -#define sqlite3_column_blob sqlite3_api->column_blob -#define sqlite3_column_bytes sqlite3_api->column_bytes -#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 -#define sqlite3_column_count sqlite3_api->column_count -#define sqlite3_column_database_name sqlite3_api->column_database_name -#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 -#define sqlite3_column_decltype sqlite3_api->column_decltype -#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 -#define sqlite3_column_double sqlite3_api->column_double -#define sqlite3_column_int sqlite3_api->column_int -#define sqlite3_column_int64 sqlite3_api->column_int64 -#define sqlite3_column_name sqlite3_api->column_name -#define sqlite3_column_name16 sqlite3_api->column_name16 -#define sqlite3_column_origin_name sqlite3_api->column_origin_name -#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 -#define sqlite3_column_table_name sqlite3_api->column_table_name -#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 -#define sqlite3_column_text sqlite3_api->column_text -#define sqlite3_column_text16 sqlite3_api->column_text16 -#define sqlite3_column_type sqlite3_api->column_type -#define sqlite3_column_value sqlite3_api->column_value -#define sqlite3_commit_hook sqlite3_api->commit_hook -#define sqlite3_complete sqlite3_api->complete -#define sqlite3_complete16 sqlite3_api->complete16 -#define sqlite3_create_collation sqlite3_api->create_collation -#define sqlite3_create_collation16 sqlite3_api->create_collation16 -#define sqlite3_create_function sqlite3_api->create_function -#define sqlite3_create_function16 sqlite3_api->create_function16 -#define sqlite3_create_module sqlite3_api->create_module -#define sqlite3_create_module_v2 sqlite3_api->create_module_v2 -#define sqlite3_data_count sqlite3_api->data_count -#define sqlite3_db_handle sqlite3_api->db_handle -#define sqlite3_declare_vtab sqlite3_api->declare_vtab -#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache -#define sqlite3_errcode sqlite3_api->errcode -#define sqlite3_errmsg sqlite3_api->errmsg -#define sqlite3_errmsg16 sqlite3_api->errmsg16 -#define sqlite3_exec sqlite3_api->exec -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_expired sqlite3_api->expired -#endif -#define sqlite3_finalize sqlite3_api->finalize -#define sqlite3_free sqlite3_api->free -#define sqlite3_free_table sqlite3_api->free_table -#define sqlite3_get_autocommit sqlite3_api->get_autocommit -#define sqlite3_get_auxdata sqlite3_api->get_auxdata -#define sqlite3_get_table sqlite3_api->get_table -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_global_recover sqlite3_api->global_recover -#endif -#define sqlite3_interrupt sqlite3_api->interruptx -#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid -#define sqlite3_libversion sqlite3_api->libversion -#define sqlite3_libversion_number sqlite3_api->libversion_number -#define sqlite3_malloc sqlite3_api->malloc -#define sqlite3_mprintf sqlite3_api->mprintf -#define sqlite3_open sqlite3_api->open -#define sqlite3_open16 sqlite3_api->open16 -#define sqlite3_prepare sqlite3_api->prepare -#define sqlite3_prepare16 sqlite3_api->prepare16 -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_profile sqlite3_api->profile -#define sqlite3_progress_handler sqlite3_api->progress_handler -#define sqlite3_realloc sqlite3_api->realloc -#define sqlite3_reset sqlite3_api->reset -#define sqlite3_result_blob sqlite3_api->result_blob -#define sqlite3_result_double sqlite3_api->result_double -#define sqlite3_result_error sqlite3_api->result_error -#define sqlite3_result_error16 sqlite3_api->result_error16 -#define sqlite3_result_int sqlite3_api->result_int -#define sqlite3_result_int64 sqlite3_api->result_int64 -#define sqlite3_result_null sqlite3_api->result_null -#define sqlite3_result_text sqlite3_api->result_text -#define sqlite3_result_text16 sqlite3_api->result_text16 -#define sqlite3_result_text16be sqlite3_api->result_text16be -#define sqlite3_result_text16le sqlite3_api->result_text16le -#define sqlite3_result_value sqlite3_api->result_value -#define sqlite3_rollback_hook sqlite3_api->rollback_hook -#define sqlite3_set_authorizer sqlite3_api->set_authorizer -#define sqlite3_set_auxdata sqlite3_api->set_auxdata -#define sqlite3_snprintf sqlite3_api->xsnprintf -#define sqlite3_step sqlite3_api->step -#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata -#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup -#define sqlite3_total_changes sqlite3_api->total_changes -#define sqlite3_trace sqlite3_api->trace -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings -#endif -#define sqlite3_update_hook sqlite3_api->update_hook -#define sqlite3_user_data sqlite3_api->user_data -#define sqlite3_value_blob sqlite3_api->value_blob -#define sqlite3_value_bytes sqlite3_api->value_bytes -#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 -#define sqlite3_value_double sqlite3_api->value_double -#define sqlite3_value_int sqlite3_api->value_int -#define sqlite3_value_int64 sqlite3_api->value_int64 -#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type -#define sqlite3_value_text sqlite3_api->value_text -#define sqlite3_value_text16 sqlite3_api->value_text16 -#define sqlite3_value_text16be sqlite3_api->value_text16be -#define sqlite3_value_text16le sqlite3_api->value_text16le -#define sqlite3_value_type sqlite3_api->value_type -#define sqlite3_vmprintf sqlite3_api->vmprintf -#define sqlite3_vsnprintf sqlite3_api->xvsnprintf -#define sqlite3_overload_function sqlite3_api->overload_function -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_clear_bindings sqlite3_api->clear_bindings -#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob -#define sqlite3_blob_bytes sqlite3_api->blob_bytes -#define sqlite3_blob_close sqlite3_api->blob_close -#define sqlite3_blob_open sqlite3_api->blob_open -#define sqlite3_blob_read sqlite3_api->blob_read -#define sqlite3_blob_write sqlite3_api->blob_write -#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 -#define sqlite3_file_control sqlite3_api->file_control -#define sqlite3_memory_highwater sqlite3_api->memory_highwater -#define sqlite3_memory_used sqlite3_api->memory_used -#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc -#define sqlite3_mutex_enter sqlite3_api->mutex_enter -#define sqlite3_mutex_free sqlite3_api->mutex_free -#define sqlite3_mutex_leave sqlite3_api->mutex_leave -#define sqlite3_mutex_try sqlite3_api->mutex_try -#define sqlite3_open_v2 sqlite3_api->open_v2 -#define sqlite3_release_memory sqlite3_api->release_memory -#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem -#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig -#define sqlite3_sleep sqlite3_api->sleep -#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit -#define sqlite3_vfs_find sqlite3_api->vfs_find -#define sqlite3_vfs_register sqlite3_api->vfs_register -#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister -#define sqlite3_threadsafe sqlite3_api->xthreadsafe -#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob -#define sqlite3_result_error_code sqlite3_api->result_error_code -#define sqlite3_test_control sqlite3_api->test_control -#define sqlite3_randomness sqlite3_api->randomness -#define sqlite3_context_db_handle sqlite3_api->context_db_handle -#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes -#define sqlite3_limit sqlite3_api->limit -#define sqlite3_next_stmt sqlite3_api->next_stmt -#define sqlite3_sql sqlite3_api->sql -#define sqlite3_status sqlite3_api->status -#define sqlite3_backup_finish sqlite3_api->backup_finish -#define sqlite3_backup_init sqlite3_api->backup_init -#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount -#define sqlite3_backup_remaining sqlite3_api->backup_remaining -#define sqlite3_backup_step sqlite3_api->backup_step -#define sqlite3_compileoption_get sqlite3_api->compileoption_get -#define sqlite3_compileoption_used sqlite3_api->compileoption_used -#define sqlite3_create_function_v2 sqlite3_api->create_function_v2 -#define sqlite3_db_config sqlite3_api->db_config -#define sqlite3_db_mutex sqlite3_api->db_mutex -#define sqlite3_db_status sqlite3_api->db_status -#define sqlite3_extended_errcode sqlite3_api->extended_errcode -#define sqlite3_log sqlite3_api->log -#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 -#define sqlite3_sourceid sqlite3_api->sourceid -#define sqlite3_stmt_status sqlite3_api->stmt_status -#define sqlite3_strnicmp sqlite3_api->strnicmp -#define sqlite3_unlock_notify sqlite3_api->unlock_notify -#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint -#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint -#define sqlite3_wal_hook sqlite3_api->wal_hook -#define sqlite3_blob_reopen sqlite3_api->blob_reopen -#define sqlite3_vtab_config sqlite3_api->vtab_config -#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict -/* Version 3.7.16 and later */ -#define sqlite3_close_v2 sqlite3_api->close_v2 -#define sqlite3_db_filename sqlite3_api->db_filename -#define sqlite3_db_readonly sqlite3_api->db_readonly -#define sqlite3_db_release_memory sqlite3_api->db_release_memory -#define sqlite3_errstr sqlite3_api->errstr -#define sqlite3_stmt_busy sqlite3_api->stmt_busy -#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly -#define sqlite3_stricmp sqlite3_api->stricmp -#define sqlite3_uri_boolean sqlite3_api->uri_boolean -#define sqlite3_uri_int64 sqlite3_api->uri_int64 -#define sqlite3_uri_parameter sqlite3_api->uri_parameter -#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf -#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 -/* Version 3.8.7 and later */ -#define sqlite3_auto_extension sqlite3_api->auto_extension -#define sqlite3_bind_blob64 sqlite3_api->bind_blob64 -#define sqlite3_bind_text64 sqlite3_api->bind_text64 -#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension -#define sqlite3_load_extension sqlite3_api->load_extension -#define sqlite3_malloc64 sqlite3_api->malloc64 -#define sqlite3_msize sqlite3_api->msize -#define sqlite3_realloc64 sqlite3_api->realloc64 -#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension -#define sqlite3_result_blob64 sqlite3_api->result_blob64 -#define sqlite3_result_text64 sqlite3_api->result_text64 -#define sqlite3_strglob sqlite3_api->strglob -/* Version 3.8.11 and later */ -#define sqlite3_value_dup sqlite3_api->value_dup -#define sqlite3_value_free sqlite3_api->value_free -#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 -#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 -/* Version 3.9.0 and later */ -#define sqlite3_value_subtype sqlite3_api->value_subtype -#define sqlite3_result_subtype sqlite3_api->result_subtype -/* Version 3.10.0 and later */ -#define sqlite3_status64 sqlite3_api->status64 -#define sqlite3_strlike sqlite3_api->strlike -#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush -/* Version 3.12.0 and later */ -#define sqlite3_system_errno sqlite3_api->system_errno -/* Version 3.14.0 and later */ -#define sqlite3_trace_v2 sqlite3_api->trace_v2 -#define sqlite3_expanded_sql sqlite3_api->expanded_sql -/* Version 3.18.0 and later */ -#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid -/* Version 3.20.0 and later */ -#define sqlite3_prepare_v3 sqlite3_api->prepare_v3 -#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3 -#define sqlite3_bind_pointer sqlite3_api->bind_pointer -#define sqlite3_result_pointer sqlite3_api->result_pointer -#define sqlite3_value_pointer sqlite3_api->value_pointer -/* Version 3.22.0 and later */ -#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange -#define sqlite3_value_nochange sqlite3_api->value_nochange -#define sqlite3_vtab_collation sqlite3_api->vtab_collation -/* Version 3.24.0 and later */ -#define sqlite3_keyword_count sqlite3_api->keyword_count -#define sqlite3_keyword_name sqlite3_api->keyword_name -#define sqlite3_keyword_check sqlite3_api->keyword_check -#define sqlite3_str_new sqlite3_api->str_new -#define sqlite3_str_finish sqlite3_api->str_finish -#define sqlite3_str_appendf sqlite3_api->str_appendf -#define sqlite3_str_vappendf sqlite3_api->str_vappendf -#define sqlite3_str_append sqlite3_api->str_append -#define sqlite3_str_appendall sqlite3_api->str_appendall -#define sqlite3_str_appendchar sqlite3_api->str_appendchar -#define sqlite3_str_reset sqlite3_api->str_reset -#define sqlite3_str_errcode sqlite3_api->str_errcode -#define sqlite3_str_length sqlite3_api->str_length -#define sqlite3_str_value sqlite3_api->str_value -/* Version 3.25.0 and later */ -#define sqlite3_create_window_function sqlite3_api->create_window_function -/* Version 3.26.0 and later */ -#define sqlite3_normalized_sql sqlite3_api->normalized_sql -/* Version 3.28.0 and later */ -#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain -#define sqlite3_value_frombind sqlite3_api->value_frombind -/* Version 3.30.0 and later */ -#define sqlite3_drop_modules sqlite3_api->drop_modules -/* Version 3.31.0 and later */ -#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64 -#define sqlite3_uri_key sqlite3_api->uri_key -#define sqlite3_filename_database sqlite3_api->filename_database -#define sqlite3_filename_journal sqlite3_api->filename_journal -#define sqlite3_filename_wal sqlite3_api->filename_wal -/* Version 3.32.0 and later */ -#define sqlite3_create_filename sqlite3_api->create_filename -#define sqlite3_free_filename sqlite3_api->free_filename -#define sqlite3_database_file_object sqlite3_api->database_file_object -/* Version 3.34.0 and later */ -#define sqlite3_txn_state sqlite3_api->txn_state -/* Version 3.36.1 and later */ -#define sqlite3_changes64 sqlite3_api->changes64 -#define sqlite3_total_changes64 sqlite3_api->total_changes64 -/* Version 3.37.0 and later */ -#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages -/* Version 3.38.0 and later */ -#define sqlite3_error_offset sqlite3_api->error_offset -#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value -#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct -#define sqlite3_vtab_in sqlite3_api->vtab_in -#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first -#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next -/* Version 3.39.0 and later */ -#ifndef SQLITE_OMIT_DESERIALIZE -#define sqlite3_deserialize sqlite3_api->deserialize -#define sqlite3_serialize sqlite3_api->serialize -#endif -#define sqlite3_db_name sqlite3_api->db_name -/* Version 3.40.0 and later */ -#define sqlite3_value_encoding sqlite3_api->value_encoding -/* Version 3.41.0 and later */ -#define sqlite3_is_interrupted sqlite3_api->is_interrupted -/* Version 3.43.0 and later */ -#define sqlite3_stmt_explain sqlite3_api->stmt_explain -/* Version 3.44.0 and later */ -#define sqlite3_get_clientdata sqlite3_api->get_clientdata -#define sqlite3_set_clientdata sqlite3_api->set_clientdata -/* Version 3.50.0 and later */ -#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout -#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ - -#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) - /* This case when the file really is being compiled as a loadable - ** extension */ -# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; -# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; -# define SQLITE_EXTENSION_INIT3 \ - extern const sqlite3_api_routines *sqlite3_api; -#else - /* This case when the file is being statically linked into the - ** application */ -# define SQLITE_EXTENSION_INIT1 /*no-op*/ -# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ -# define SQLITE_EXTENSION_INIT3 /*no-op*/ -#endif - -#endif /* SQLITE3EXT_H */ - -/************** End of sqlite3ext.h ******************************************/ -/************** Continuing where we left off in loadext.c ********************/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** Some API routines are omitted when various features are -** excluded from a build of SQLite. Substitute a NULL pointer -** for any missing APIs. -*/ -#ifndef SQLITE_ENABLE_COLUMN_METADATA -# define sqlite3_column_database_name 0 -# define sqlite3_column_database_name16 0 -# define sqlite3_column_table_name 0 -# define sqlite3_column_table_name16 0 -# define sqlite3_column_origin_name 0 -# define sqlite3_column_origin_name16 0 -#endif - -#ifdef SQLITE_OMIT_AUTHORIZATION -# define sqlite3_set_authorizer 0 -#endif - -#ifdef SQLITE_OMIT_UTF16 -# define sqlite3_bind_text16 0 -# define sqlite3_collation_needed16 0 -# define sqlite3_column_decltype16 0 -# define sqlite3_column_name16 0 -# define sqlite3_column_text16 0 -# define sqlite3_complete16 0 -# define sqlite3_create_collation16 0 -# define sqlite3_create_function16 0 -# define sqlite3_errmsg16 0 -# define sqlite3_open16 0 -# define sqlite3_prepare16 0 -# define sqlite3_prepare16_v2 0 -# define sqlite3_prepare16_v3 0 -# define sqlite3_result_error16 0 -# define sqlite3_result_text16 0 -# define sqlite3_result_text16be 0 -# define sqlite3_result_text16le 0 -# define sqlite3_value_text16 0 -# define sqlite3_value_text16be 0 -# define sqlite3_value_text16le 0 -# define sqlite3_column_database_name16 0 -# define sqlite3_column_table_name16 0 -# define sqlite3_column_origin_name16 0 -#endif - -#ifdef SQLITE_OMIT_COMPLETE -# define sqlite3_complete 0 -# define sqlite3_complete16 0 -#endif - -#ifdef SQLITE_OMIT_DECLTYPE -# define sqlite3_column_decltype16 0 -# define sqlite3_column_decltype 0 -#endif - -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK -# define sqlite3_progress_handler 0 -#endif - -#ifdef SQLITE_OMIT_VIRTUALTABLE -# define sqlite3_create_module 0 -# define sqlite3_create_module_v2 0 -# define sqlite3_declare_vtab 0 -# define sqlite3_vtab_config 0 -# define sqlite3_vtab_on_conflict 0 -# define sqlite3_vtab_collation 0 -#endif - -#ifdef SQLITE_OMIT_SHARED_CACHE -# define sqlite3_enable_shared_cache 0 -#endif - -#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED) -# define sqlite3_profile 0 -# define sqlite3_trace 0 -#endif - -#ifdef SQLITE_OMIT_GET_TABLE -# define sqlite3_free_table 0 -# define sqlite3_get_table 0 -#endif - -#ifdef SQLITE_OMIT_INCRBLOB -#define sqlite3_bind_zeroblob 0 -#define sqlite3_blob_bytes 0 -#define sqlite3_blob_close 0 -#define sqlite3_blob_open 0 -#define sqlite3_blob_read 0 -#define sqlite3_blob_write 0 -#define sqlite3_blob_reopen 0 -#endif - -#if defined(SQLITE_OMIT_TRACE) -# define sqlite3_trace_v2 0 -#endif - -/* -** The following structure contains pointers to all SQLite API routines. -** A pointer to this structure is passed into extensions when they are -** loaded so that the extension can make calls back into the SQLite -** library. -** -** When adding new APIs, add them to the bottom of this structure -** in order to preserve backwards compatibility. -** -** Extensions that use newer APIs should first call the -** sqlite3_libversion_number() to make sure that the API they -** intend to use is supported by the library. Extensions should -** also check to make sure that the pointer to the function is -** not NULL before calling it. -*/ -static const sqlite3_api_routines sqlite3Apis = { - sqlite3_aggregate_context, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_aggregate_count, -#else - 0, -#endif - sqlite3_bind_blob, - sqlite3_bind_double, - sqlite3_bind_int, - sqlite3_bind_int64, - sqlite3_bind_null, - sqlite3_bind_parameter_count, - sqlite3_bind_parameter_index, - sqlite3_bind_parameter_name, - sqlite3_bind_text, - sqlite3_bind_text16, - sqlite3_bind_value, - sqlite3_busy_handler, - sqlite3_busy_timeout, - sqlite3_changes, - sqlite3_close, - sqlite3_collation_needed, - sqlite3_collation_needed16, - sqlite3_column_blob, - sqlite3_column_bytes, - sqlite3_column_bytes16, - sqlite3_column_count, - sqlite3_column_database_name, - sqlite3_column_database_name16, - sqlite3_column_decltype, - sqlite3_column_decltype16, - sqlite3_column_double, - sqlite3_column_int, - sqlite3_column_int64, - sqlite3_column_name, - sqlite3_column_name16, - sqlite3_column_origin_name, - sqlite3_column_origin_name16, - sqlite3_column_table_name, - sqlite3_column_table_name16, - sqlite3_column_text, - sqlite3_column_text16, - sqlite3_column_type, - sqlite3_column_value, - sqlite3_commit_hook, - sqlite3_complete, - sqlite3_complete16, - sqlite3_create_collation, - sqlite3_create_collation16, - sqlite3_create_function, - sqlite3_create_function16, - sqlite3_create_module, - sqlite3_data_count, - sqlite3_db_handle, - sqlite3_declare_vtab, - sqlite3_enable_shared_cache, - sqlite3_errcode, - sqlite3_errmsg, - sqlite3_errmsg16, - sqlite3_exec, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_expired, -#else - 0, -#endif - sqlite3_finalize, - sqlite3_free, - sqlite3_free_table, - sqlite3_get_autocommit, - sqlite3_get_auxdata, - sqlite3_get_table, - 0, /* Was sqlite3_global_recover(), but that function is deprecated */ - sqlite3_interrupt, - sqlite3_last_insert_rowid, - sqlite3_libversion, - sqlite3_libversion_number, - sqlite3_malloc, - sqlite3_mprintf, - sqlite3_open, - sqlite3_open16, - sqlite3_prepare, - sqlite3_prepare16, - sqlite3_profile, - sqlite3_progress_handler, - sqlite3_realloc, - sqlite3_reset, - sqlite3_result_blob, - sqlite3_result_double, - sqlite3_result_error, - sqlite3_result_error16, - sqlite3_result_int, - sqlite3_result_int64, - sqlite3_result_null, - sqlite3_result_text, - sqlite3_result_text16, - sqlite3_result_text16be, - sqlite3_result_text16le, - sqlite3_result_value, - sqlite3_rollback_hook, - sqlite3_set_authorizer, - sqlite3_set_auxdata, - sqlite3_snprintf, - sqlite3_step, - sqlite3_table_column_metadata, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup, -#else - 0, -#endif - sqlite3_total_changes, - sqlite3_trace, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_transfer_bindings, -#else - 0, -#endif - sqlite3_update_hook, - sqlite3_user_data, - sqlite3_value_blob, - sqlite3_value_bytes, - sqlite3_value_bytes16, - sqlite3_value_double, - sqlite3_value_int, - sqlite3_value_int64, - sqlite3_value_numeric_type, - sqlite3_value_text, - sqlite3_value_text16, - sqlite3_value_text16be, - sqlite3_value_text16le, - sqlite3_value_type, - sqlite3_vmprintf, - /* - ** The original API set ends here. All extensions can call any - ** of the APIs above provided that the pointer is not NULL. But - ** before calling APIs that follow, extension should check the - ** sqlite3_libversion_number() to make sure they are dealing with - ** a library that is new enough to support that API. - ************************************************************************* - */ - sqlite3_overload_function, - - /* - ** Added after 3.3.13 - */ - sqlite3_prepare_v2, - sqlite3_prepare16_v2, - sqlite3_clear_bindings, - - /* - ** Added for 3.4.1 - */ - sqlite3_create_module_v2, - - /* - ** Added for 3.5.0 - */ - sqlite3_bind_zeroblob, - sqlite3_blob_bytes, - sqlite3_blob_close, - sqlite3_blob_open, - sqlite3_blob_read, - sqlite3_blob_write, - sqlite3_create_collation_v2, - sqlite3_file_control, - sqlite3_memory_highwater, - sqlite3_memory_used, -#ifdef SQLITE_MUTEX_OMIT - 0, - 0, - 0, - 0, - 0, -#else - sqlite3_mutex_alloc, - sqlite3_mutex_enter, - sqlite3_mutex_free, - sqlite3_mutex_leave, - sqlite3_mutex_try, -#endif - sqlite3_open_v2, - sqlite3_release_memory, - sqlite3_result_error_nomem, - sqlite3_result_error_toobig, - sqlite3_sleep, - sqlite3_soft_heap_limit, - sqlite3_vfs_find, - sqlite3_vfs_register, - sqlite3_vfs_unregister, - - /* - ** Added for 3.5.8 - */ - sqlite3_threadsafe, - sqlite3_result_zeroblob, - sqlite3_result_error_code, - sqlite3_test_control, - sqlite3_randomness, - sqlite3_context_db_handle, - - /* - ** Added for 3.6.0 - */ - sqlite3_extended_result_codes, - sqlite3_limit, - sqlite3_next_stmt, - sqlite3_sql, - sqlite3_status, - - /* - ** Added for 3.7.4 - */ - sqlite3_backup_finish, - sqlite3_backup_init, - sqlite3_backup_pagecount, - sqlite3_backup_remaining, - sqlite3_backup_step, -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - sqlite3_compileoption_get, - sqlite3_compileoption_used, -#else - 0, - 0, -#endif - sqlite3_create_function_v2, - sqlite3_db_config, - sqlite3_db_mutex, - sqlite3_db_status, - sqlite3_extended_errcode, - sqlite3_log, - sqlite3_soft_heap_limit64, - sqlite3_sourceid, - sqlite3_stmt_status, - sqlite3_strnicmp, -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - sqlite3_unlock_notify, -#else - 0, -#endif -#ifndef SQLITE_OMIT_WAL - sqlite3_wal_autocheckpoint, - sqlite3_wal_checkpoint, - sqlite3_wal_hook, -#else - 0, - 0, - 0, -#endif - sqlite3_blob_reopen, - sqlite3_vtab_config, - sqlite3_vtab_on_conflict, - sqlite3_close_v2, - sqlite3_db_filename, - sqlite3_db_readonly, - sqlite3_db_release_memory, - sqlite3_errstr, - sqlite3_stmt_busy, - sqlite3_stmt_readonly, - sqlite3_stricmp, - sqlite3_uri_boolean, - sqlite3_uri_int64, - sqlite3_uri_parameter, - sqlite3_vsnprintf, - sqlite3_wal_checkpoint_v2, - /* Version 3.8.7 and later */ - sqlite3_auto_extension, - sqlite3_bind_blob64, - sqlite3_bind_text64, - sqlite3_cancel_auto_extension, - sqlite3_load_extension, - sqlite3_malloc64, - sqlite3_msize, - sqlite3_realloc64, - sqlite3_reset_auto_extension, - sqlite3_result_blob64, - sqlite3_result_text64, - sqlite3_strglob, - /* Version 3.8.11 and later */ - (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, - sqlite3_value_free, - sqlite3_result_zeroblob64, - sqlite3_bind_zeroblob64, - /* Version 3.9.0 and later */ - sqlite3_value_subtype, - sqlite3_result_subtype, - /* Version 3.10.0 and later */ - sqlite3_status64, - sqlite3_strlike, - sqlite3_db_cacheflush, - /* Version 3.12.0 and later */ - sqlite3_system_errno, - /* Version 3.14.0 and later */ - sqlite3_trace_v2, - sqlite3_expanded_sql, - /* Version 3.18.0 and later */ - sqlite3_set_last_insert_rowid, - /* Version 3.20.0 and later */ - sqlite3_prepare_v3, - sqlite3_prepare16_v3, - sqlite3_bind_pointer, - sqlite3_result_pointer, - sqlite3_value_pointer, - /* Version 3.22.0 and later */ - sqlite3_vtab_nochange, - sqlite3_value_nochange, - sqlite3_vtab_collation, - /* Version 3.24.0 and later */ - sqlite3_keyword_count, - sqlite3_keyword_name, - sqlite3_keyword_check, - sqlite3_str_new, - sqlite3_str_finish, - sqlite3_str_appendf, - sqlite3_str_vappendf, - sqlite3_str_append, - sqlite3_str_appendall, - sqlite3_str_appendchar, - sqlite3_str_reset, - sqlite3_str_errcode, - sqlite3_str_length, - sqlite3_str_value, - /* Version 3.25.0 and later */ - sqlite3_create_window_function, - /* Version 3.26.0 and later */ -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3_normalized_sql, -#else - 0, -#endif - /* Version 3.28.0 and later */ - sqlite3_stmt_isexplain, - sqlite3_value_frombind, - /* Version 3.30.0 and later */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_drop_modules, -#else - 0, -#endif - /* Version 3.31.0 and later */ - sqlite3_hard_heap_limit64, - sqlite3_uri_key, - sqlite3_filename_database, - sqlite3_filename_journal, - sqlite3_filename_wal, - /* Version 3.32.0 and later */ - sqlite3_create_filename, - sqlite3_free_filename, - sqlite3_database_file_object, - /* Version 3.34.0 and later */ - sqlite3_txn_state, - /* Version 3.36.1 and later */ - sqlite3_changes64, - sqlite3_total_changes64, - /* Version 3.37.0 and later */ - sqlite3_autovacuum_pages, - /* Version 3.38.0 and later */ - sqlite3_error_offset, -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_vtab_rhs_value, - sqlite3_vtab_distinct, - sqlite3_vtab_in, - sqlite3_vtab_in_first, - sqlite3_vtab_in_next, -#else - 0, - 0, - 0, - 0, - 0, -#endif - /* Version 3.39.0 and later */ -#ifndef SQLITE_OMIT_DESERIALIZE - sqlite3_deserialize, - sqlite3_serialize, -#else - 0, - 0, -#endif - sqlite3_db_name, - /* Version 3.40.0 and later */ - sqlite3_value_encoding, - /* Version 3.41.0 and later */ - sqlite3_is_interrupted, - /* Version 3.43.0 and later */ - sqlite3_stmt_explain, - /* Version 3.44.0 and later */ - sqlite3_get_clientdata, - sqlite3_set_clientdata, - /* Version 3.50.0 and later */ - sqlite3_setlk_timeout -}; - -/* True if x is the directory separator character -*/ -#if SQLITE_OS_WIN -# define DirSep(X) ((X)=='/'||(X)=='\\') -#else -# define DirSep(X) ((X)=='/') -#endif - -/* -** Attempt to load an SQLite extension library contained in the file -** zFile. The entry point is zProc. zProc may be 0 in which case a -** default entry point name (sqlite3_extension_init) is used. Use -** of the default name is recommended. -** -** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. -** -** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with -** error message text. The calling function should free this memory -** by calling sqlite3DbFree(db, ). -*/ -static int sqlite3LoadExtension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -){ - sqlite3_vfs *pVfs = db->pVfs; - void *handle; - sqlite3_loadext_entry xInit; - char *zErrmsg = 0; - const char *zEntry; - char *zAltEntry = 0; - void **aHandle; - u64 nMsg = strlen(zFile); - int ii; - int rc; - - /* Shared library endings to try if zFile cannot be loaded as written */ - static const char *azEndings[] = { -#if SQLITE_OS_WIN - "dll" -#elif defined(__APPLE__) - "dylib" -#else - "so" -#endif - }; - - - if( pzErrMsg ) *pzErrMsg = 0; - - /* Ticket #1863. To avoid a creating security problems for older - ** applications that relink against newer versions of SQLite, the - ** ability to run load_extension is turned off by default. One - ** must call either sqlite3_enable_load_extension(db) or - ** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0) - ** to turn on extension loading. - */ - if( (db->flags & SQLITE_LoadExtension)==0 ){ - if( pzErrMsg ){ - *pzErrMsg = sqlite3_mprintf("not authorized"); - } - return SQLITE_ERROR; - } - - zEntry = zProc ? zProc : "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 - ** - ** Later (2023-03-25): Save an extra 6 bytes for the filename suffix. - ** See https://sqlite.org/forum/forumpost/24083b579d. - */ - if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found; - - /* Do not allow sqlite3_load_extension() to link to a copy of the - ** running application, by passing in an empty filename. */ - if( nMsg==0 ) goto extension_not_found; - - handle = sqlite3OsDlOpen(pVfs, zFile); -#if SQLITE_OS_UNIX || SQLITE_OS_WIN - for(ii=0; ii sqlite3_example_init - ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init - */ - if( xInit==0 && zProc==0 ){ - int iFile, iEntry, c; - int ncFile = sqlite3Strlen30(zFile); - zAltEntry = sqlite3_malloc64(ncFile+30); - if( zAltEntry==0 ){ - sqlite3OsDlClose(pVfs, handle); - return SQLITE_NOMEM_BKPT; - } - memcpy(zAltEntry, "sqlite3_", 8); - for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} - iFile++; - if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; - for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ - if( sqlite3Isalpha(c) ){ - zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; - } - } - memcpy(zAltEntry+iEntry, "_init", 6); - zEntry = zAltEntry; - xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); - } - if( xInit==0 ){ - if( pzErrMsg ){ - nMsg += strlen(zEntry) + 300; - *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); - if( zErrmsg ){ - assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ - sqlite3_snprintf((int)nMsg, zErrmsg, - "no entry point [%s] in shared library [%s]", zEntry, zFile); - sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - } - } - sqlite3OsDlClose(pVfs, handle); - sqlite3_free(zAltEntry); - return SQLITE_ERROR; - } - sqlite3_free(zAltEntry); - rc = xInit(db, &zErrmsg, &sqlite3Apis); - if( rc ){ - if( rc==SQLITE_OK_LOAD_PERMANENTLY ) return SQLITE_OK; - if( pzErrMsg ){ - *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); - } - sqlite3_free(zErrmsg); - sqlite3OsDlClose(pVfs, handle); - return SQLITE_ERROR; - } - - /* Append the new shared library handle to the db->aExtension array. */ - aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1)); - if( aHandle==0 ){ - return SQLITE_NOMEM_BKPT; - } - if( db->nExtension>0 ){ - memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); - } - sqlite3DbFree(db, db->aExtension); - db->aExtension = aHandle; - - db->aExtension[db->nExtension++] = handle; - return SQLITE_OK; - -extension_not_found: - if( pzErrMsg ){ - nMsg += 300; - *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); - if( zErrmsg ){ - assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ - sqlite3_snprintf((int)nMsg, zErrmsg, - "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile); - sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - } - } - return SQLITE_ERROR; -} -SQLITE_API int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -){ - int rc; - sqlite3_mutex_enter(db->mutex); - rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Call this routine when the database connection is closing in order -** to clean up loaded extensions -*/ -SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ - int i; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inExtension; i++){ - sqlite3OsDlClose(db->pVfs, db->aExtension[i]); - } - sqlite3DbFree(db, db->aExtension); -} - -/* -** Enable or disable extension loading. Extension loading is disabled by -** default so as not to open security holes in older applications. -*/ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - if( onoff ){ - db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; - }else{ - db->flags &= ~(u64)(SQLITE_LoadExtension|SQLITE_LoadExtFunc); - } - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ - -/* -** The following object holds the list of automatically loaded -** extensions. -** -** This list is shared across threads. The SQLITE_MUTEX_STATIC_MAIN -** mutex must be held while accessing this list. -*/ -typedef struct sqlite3AutoExtList sqlite3AutoExtList; -static SQLITE_WSD struct sqlite3AutoExtList { - u32 nExt; /* Number of entries in aExt[] */ - void (**aExt)(void); /* Pointers to the extension init functions */ -} sqlite3Autoext = { 0, 0 }; - -/* The "wsdAutoext" macro will resolve to the autoextension -** state vector. If writable static data is unsupported on the target, -** we have to locate the state vector at run-time. In the more common -** case where writable static data is supported, wsdStat can refer directly -** to the "sqlite3Autoext" state vector declared above. -*/ -#ifdef SQLITE_OMIT_WSD -# define wsdAutoextInit \ - sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext) -# define wsdAutoext x[0] -#else -# define wsdAutoextInit -# define wsdAutoext sqlite3Autoext -#endif - - -/* -** Register a statically linked extension that is automatically -** loaded by every new database connection. -*/ -SQLITE_API int sqlite3_auto_extension( - void (*xInit)(void) -){ - int rc = SQLITE_OK; -#ifdef SQLITE_ENABLE_API_ARMOR - if( xInit==0 ) return SQLITE_MISUSE_BKPT; -#endif -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ){ - return rc; - }else -#endif - { - u32 i; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); -#endif - wsdAutoextInit; - sqlite3_mutex_enter(mutex); - for(i=0; i=0; i--){ - if( wsdAutoext.aExt[i]==xInit ){ - wsdAutoext.nExt--; - wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; - n++; - break; - } - } - sqlite3_mutex_leave(mutex); - return n; -} - -/* -** Reset the automatic extension loading mechanism. -*/ -SQLITE_API void sqlite3_reset_auto_extension(void){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize()==SQLITE_OK ) -#endif - { -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); -#endif - wsdAutoextInit; - sqlite3_mutex_enter(mutex); - sqlite3_free(wsdAutoext.aExt); - wsdAutoext.aExt = 0; - wsdAutoext.nExt = 0; - sqlite3_mutex_leave(mutex); - } -} - -/* -** Load all automatic extensions. -** -** If anything goes wrong, set an error in the database connection. -*/ -SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ - u32 i; - int go = 1; - int rc; - sqlite3_loadext_entry xInit; - - wsdAutoextInit; - if( wsdAutoext.nExt==0 ){ - /* Common case: early out without every having to acquire a mutex */ - return; - } - for(i=0; go; i++){ - char *zErrmsg; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); -#endif -#ifdef SQLITE_OMIT_LOAD_EXTENSION - const sqlite3_api_routines *pThunk = 0; -#else - const sqlite3_api_routines *pThunk = &sqlite3Apis; -#endif - sqlite3_mutex_enter(mutex); - if( i>=wsdAutoext.nExt ){ - xInit = 0; - go = 0; - }else{ - xInit = (sqlite3_loadext_entry)wsdAutoext.aExt[i]; - } - sqlite3_mutex_leave(mutex); - zErrmsg = 0; - if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){ - sqlite3ErrorWithMsg(db, rc, - "automatic extension loading failed: %s", zErrmsg); - go = 0; - } - sqlite3_free(zErrmsg); - } -} - -/************** End of loadext.c *********************************************/ -/************** Begin file pragma.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the PRAGMA command. -*/ -/* #include "sqliteInt.h" */ - -#if !defined(SQLITE_ENABLE_LOCKING_STYLE) -# if defined(__APPLE__) -# define SQLITE_ENABLE_LOCKING_STYLE 1 -# else -# define SQLITE_ENABLE_LOCKING_STYLE 0 -# endif -#endif - -/*************************************************************************** -** The "pragma.h" include file is an automatically generated file that -** that includes the PragType_XXXX macro definitions and the aPragmaName[] -** object. This ensures that the aPragmaName[] table is arranged in -** lexicographical order to facility a binary search of the pragma name. -** Do not edit pragma.h directly. Edit and rerun the script in at -** ../tool/mkpragmatab.tcl. */ -/************** Include pragma.h in the middle of pragma.c *******************/ -/************** Begin file pragma.h ******************************************/ -/* DO NOT EDIT! -** This file is automatically generated by the script at -** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit -** that script and rerun it. -*/ - -/* The various pragma types */ -#define PragTyp_ACTIVATE_EXTENSIONS 0 -#define PragTyp_ANALYSIS_LIMIT 1 -#define PragTyp_HEADER_VALUE 2 -#define PragTyp_AUTO_VACUUM 3 -#define PragTyp_FLAG 4 -#define PragTyp_BUSY_TIMEOUT 5 -#define PragTyp_CACHE_SIZE 6 -#define PragTyp_CACHE_SPILL 7 -#define PragTyp_CASE_SENSITIVE_LIKE 8 -#define PragTyp_COLLATION_LIST 9 -#define PragTyp_COMPILE_OPTIONS 10 -#define PragTyp_DATA_STORE_DIRECTORY 11 -#define PragTyp_DATABASE_LIST 12 -#define PragTyp_DEFAULT_CACHE_SIZE 13 -#define PragTyp_ENCODING 14 -#define PragTyp_FOREIGN_KEY_CHECK 15 -#define PragTyp_FOREIGN_KEY_LIST 16 -#define PragTyp_FUNCTION_LIST 17 -#define PragTyp_HARD_HEAP_LIMIT 18 -#define PragTyp_INCREMENTAL_VACUUM 19 -#define PragTyp_INDEX_INFO 20 -#define PragTyp_INDEX_LIST 21 -#define PragTyp_INTEGRITY_CHECK 22 -#define PragTyp_JOURNAL_MODE 23 -#define PragTyp_JOURNAL_SIZE_LIMIT 24 -#define PragTyp_LOCK_PROXY_FILE 25 -#define PragTyp_LOCKING_MODE 26 -#define PragTyp_PAGE_COUNT 27 -#define PragTyp_MMAP_SIZE 28 -#define PragTyp_MODULE_LIST 29 -#define PragTyp_OPTIMIZE 30 -#define PragTyp_PAGE_SIZE 31 -#define PragTyp_PRAGMA_LIST 32 -#define PragTyp_SECURE_DELETE 33 -#define PragTyp_SHRINK_MEMORY 34 -#define PragTyp_SOFT_HEAP_LIMIT 35 -#define PragTyp_SYNCHRONOUS 36 -#define PragTyp_TABLE_INFO 37 -#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_KEY 44 -#define PragTyp_LOCK_STATUS 45 -#define PragTyp_STATS 46 - -/* Property flags associated with various pragma. */ -#define PragFlg_NeedSchema 0x01 /* Force schema load before running */ -#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ -#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ -#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */ -#define PragFlg_Result0 0x10 /* Acts as query when no argument */ -#define PragFlg_Result1 0x20 /* Acts as query when has one argument */ -#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */ -#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */ - -/* Names of columns for pragmas that return multi-column result -** or that return single-column results where the name of the -** result column is different from the name of the pragma -*/ -static const char *const pragCName[] = { - /* 0 */ "id", /* Used by: foreign_key_list */ - /* 1 */ "seq", - /* 2 */ "table", - /* 3 */ "from", - /* 4 */ "to", - /* 5 */ "on_update", - /* 6 */ "on_delete", - /* 7 */ "match", - /* 8 */ "cid", /* Used by: table_xinfo */ - /* 9 */ "name", - /* 10 */ "type", - /* 11 */ "notnull", - /* 12 */ "dflt_value", - /* 13 */ "pk", - /* 14 */ "hidden", - /* table_info reuses 8 */ - /* 15 */ "name", /* Used by: function_list */ - /* 16 */ "builtin", - /* 17 */ "type", - /* 18 */ "enc", - /* 19 */ "narg", - /* 20 */ "flags", - /* 21 */ "schema", /* Used by: table_list */ - /* 22 */ "name", - /* 23 */ "type", - /* 24 */ "ncol", - /* 25 */ "wr", - /* 26 */ "strict", - /* 27 */ "seqno", /* Used by: index_xinfo */ - /* 28 */ "cid", - /* 29 */ "name", - /* 30 */ "desc", - /* 31 */ "coll", - /* 32 */ "key", - /* 33 */ "seq", /* Used by: index_list */ - /* 34 */ "name", - /* 35 */ "unique", - /* 36 */ "origin", - /* 37 */ "partial", - /* 38 */ "tbl", /* Used by: stats */ - /* 39 */ "idx", - /* 40 */ "wdth", - /* 41 */ "hght", - /* 42 */ "flgs", - /* 43 */ "table", /* Used by: foreign_key_check */ - /* 44 */ "rowid", - /* 45 */ "parent", - /* 46 */ "fkid", - /* 47 */ "busy", /* Used by: wal_checkpoint */ - /* 48 */ "log", - /* 49 */ "checkpointed", - /* 50 */ "seq", /* Used by: database_list */ - /* 51 */ "name", - /* 52 */ "file", - /* index_info reuses 27 */ - /* 53 */ "database", /* Used by: lock_status */ - /* 54 */ "status", - /* collation_list reuses 33 */ - /* 55 */ "cache_size", /* Used by: default_cache_size */ - /* module_list pragma_list reuses 9 */ - /* 56 */ "timeout", /* Used by: busy_timeout */ -}; - -/* Definitions of all built-in pragmas */ -typedef struct PragmaName { - const char *const zName; /* Name of pragma */ - u8 ePragTyp; /* PragTyp_XXX value */ - u8 mPragFlg; /* Zero or more PragFlg_XXX values */ - u8 iPragCName; /* Start of column names in pragCName[] */ - u8 nPragCName; /* Num of col names. 0 means use pragma name */ - u64 iArg; /* Extra argument */ -} PragmaName; -static const PragmaName aPragmaName[] = { -#if defined(SQLITE_ENABLE_CEROD) - {/* zName: */ "activate_extensions", - /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif - {/* zName: */ "analysis_limit", - /* ePragTyp: */ PragTyp_ANALYSIS_LIMIT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "application_id", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_APPLICATION_ID }, -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - {/* zName: */ "auto_vacuum", - /* ePragTyp: */ PragTyp_AUTO_VACUUM, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) - {/* zName: */ "automatic_index", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_AutoIndex }, -#endif -#endif - {/* zName: */ "busy_timeout", - /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 56, 1, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "cache_size", - /* ePragTyp: */ PragTyp_CACHE_SIZE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_CACHE_SPILL, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA) - {/* zName: */ "case_sensitive_like", - /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, - /* ePragFlg: */ PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif - {/* zName: */ "cell_size_check", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CellSizeCk }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "checkpoint_fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CkptFullFSync }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "collation_list", - /* ePragTyp: */ PragTyp_COLLATION_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 33, 2, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) - {/* zName: */ "compile_options", - /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "count_changes", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CountRows }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN - {/* zName: */ "data_store_directory", - /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "data_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_DATA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "database_list", - /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 50, 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: */ 55, 1, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "defer_foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_DeferFKs }, -#endif -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "empty_result_callbacks", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_NullCallback }, -#endif -#if !defined(SQLITE_OMIT_UTF16) - {/* zName: */ "encoding", - /* ePragTyp: */ PragTyp_ENCODING, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "foreign_key_check", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 43, 4, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) - {/* zName: */ "foreign_key_list", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 0, 8, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ForeignKeys }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "freelist_count", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_FREE_PAGE_COUNT }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "full_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_FullColNames }, - {/* zName: */ "fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_FullFSync }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) - {/* zName: */ "function_list", - /* ePragTyp: */ PragTyp_FUNCTION_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 15, 6, - /* iArg: */ 0 }, -#endif -#endif - {/* zName: */ "hard_heap_limit", - /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "hexkey", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 2 }, - {/* zName: */ "hexrekey", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 3 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_CHECK) - {/* zName: */ "ignore_check_constraints", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_IgnoreChecks }, -#endif -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - {/* zName: */ "incremental_vacuum", - /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "index_info", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 27, 3, - /* iArg: */ 0 }, - {/* zName: */ "index_list", - /* ePragTyp: */ PragTyp_INDEX_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 33, 5, - /* iArg: */ 0 }, - {/* zName: */ "index_xinfo", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 27, 6, - /* iArg: */ 1 }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - {/* zName: */ "integrity_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "journal_mode", - /* ePragTyp: */ PragTyp_JOURNAL_MODE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "journal_size_limit", - /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "key", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "legacy_alter_table", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_LegacyAlter }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE - {/* zName: */ "lock_proxy_file", - /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - {/* zName: */ "lock_status", - /* ePragTyp: */ PragTyp_LOCK_STATUS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 53, 2, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "locking_mode", - /* ePragTyp: */ PragTyp_LOCKING_MODE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "max_page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "mmap_size", - /* ePragTyp: */ PragTyp_MMAP_SIZE, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) -#if !defined(SQLITE_OMIT_VIRTUALTABLE) -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) - {/* zName: */ "module_list", - /* ePragTyp: */ PragTyp_MODULE_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 9, 1, - /* iArg: */ 0 }, -#endif -#endif -#endif - {/* zName: */ "optimize", - /* ePragTyp: */ PragTyp_OPTIMIZE, - /* ePragFlg: */ PragFlg_Result1|PragFlg_NeedSchema, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "page_size", - /* ePragTyp: */ PragTyp_PAGE_SIZE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - {/* zName: */ "parser_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ParserTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) - {/* zName: */ "pragma_list", - /* ePragTyp: */ PragTyp_PRAGMA_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 9, 1, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "query_only", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_QueryOnly }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - {/* zName: */ "quick_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "read_uncommitted", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReadUncommit }, - {/* zName: */ "recursive_triggers", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_RecTriggers }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "rekey", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 1 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "reverse_unordered_selects", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReverseOrder }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "schema_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_SCHEMA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "secure_delete", - /* ePragTyp: */ PragTyp_SECURE_DELETE, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "short_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ShortColNames }, -#endif - {/* zName: */ "shrink_memory", - /* ePragTyp: */ PragTyp_SHRINK_MEMORY, - /* ePragFlg: */ PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "soft_heap_limit", - /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - {/* zName: */ "sql_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_SqlTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG) - {/* zName: */ "stats", - /* ePragTyp: */ PragTyp_STATS, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 38, 5, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "synchronous", - /* ePragTyp: */ PragTyp_SYNCHRONOUS, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "table_info", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* 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: */ 21, 6, - /* iArg: */ 0 }, - {/* zName: */ "table_xinfo", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 8, 7, - /* iArg: */ 1 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "temp_store", - /* ePragTyp: */ PragTyp_TEMP_STORE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "temp_store_directory", - /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "textkey", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 4 }, - {/* zName: */ "textrekey", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 5 }, -#endif - {/* zName: */ "threads", - /* ePragTyp: */ PragTyp_THREADS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "trusted_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_TrustedSchema }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "user_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_USER_VERSION }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - {/* zName: */ "vdbe_addoptrace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeAddopTrace }, - {/* zName: */ "vdbe_debug", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, - {/* zName: */ "vdbe_eqp", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeEQP }, - {/* zName: */ "vdbe_listing", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeListing }, - {/* zName: */ "vdbe_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_WAL) - {/* zName: */ "wal_autocheckpoint", - /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "wal_checkpoint", - /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 47, 3, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "writable_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, -#endif -}; -/* Number of pragmas: 68 on by default, 84 total. */ - -/************** End of pragma.h **********************************************/ -/************** Continuing where we left off in pragma.c *********************/ - -/* -** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands -** will be run with an analysis_limit set to the lessor of the value of -** the following macro or to the actual analysis_limit if it is non-zero, -** in order to prevent PRAGMA optimize from running for too long. -** -** The value of 2000 is chosen empirically so that the worst-case run-time -** for PRAGMA optimize does not exceed 100 milliseconds against a variety -** of test databases on a RaspberryPI-4 compiled using -Os and without -** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of -** this paragraph, "worst-case" means that ANALYZE ends up being -** run on every table in the database. The worst case typically only -** happens if PRAGMA optimize is run on a database file for which ANALYZE -** has not been previously run and the 0x10000 flag is included so that -** all tables are analyzed. The usual case for PRAGMA optimize is that -** no ANALYZE commands will be run at all, or if any ANALYZE happens it -** will be against a single table, so that expected timing for PRAGMA -** optimize on a PI-4 is more like 1 millisecond or less with the 0x10000 -** flag or less than 100 microseconds without the 0x10000 flag. -** -** An analysis limit of 2000 is almost always sufficient for the query -** planner to fully characterize an index. The additional accuracy from -** a larger analysis is not usually helpful. -*/ -#ifndef SQLITE_DEFAULT_OPTIMIZE_LIMIT -# define SQLITE_DEFAULT_OPTIMIZE_LIMIT 2000 -#endif - -/* -** Interpret the given string as a safety level. Return 0 for OFF, -** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or -** unrecognized string argument. The FULL and EXTRA option is disallowed -** if the omitFull parameter it 1. -** -** Note that the values returned are one less that the values that -** should be passed into sqlite3BtreeSetSafetyLevel(). The is done -** to support legacy SQL code. The safety level used to be boolean -** and older scripts may have used numbers 0 for OFF and 1 for ON. -*/ -static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ - /* 123456789 123456789 123 */ - static const char zText[] = "onoffalseyestruextrafull"; - static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; - static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; - static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; - /* on no off false yes true extra full */ - int i, n; - if( sqlite3Isdigit(*z) ){ - return (u8)sqlite3Atoi(z); - } - n = sqlite3Strlen30(z); - for(i=0; i=0&&i<=2)?i:0); -} -#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** Interpret the given string as a temp db location. Return 1 for file -** backed temporary databases, 2 for the Red-Black tree in memory database -** and 0 to use the compile-time default. -*/ -static int getTempStore(const char *z){ - if( z[0]>='0' && z[0]<='2' ){ - return z[0] - '0'; - }else if( sqlite3StrICmp(z, "file")==0 ){ - return 1; - }else if( sqlite3StrICmp(z, "memory")==0 ){ - return 2; - }else{ - return 0; - } -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** Invalidate temp storage, either when the temp storage is changed -** from default, or when 'file' and the temp_store_directory has changed -*/ -static int invalidateTempStorage(Parse *pParse){ - sqlite3 *db = pParse->db; - if( db->aDb[1].pBt!=0 ){ - if( !db->autoCommit - || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE - ){ - sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " - "from within a transaction"); - return SQLITE_ERROR; - } - sqlite3BtreeClose(db->aDb[1].pBt); - db->aDb[1].pBt = 0; - sqlite3ResetAllSchemasOfConnection(db); - } - return SQLITE_OK; -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** If the TEMP database is open, close it and mark the database schema -** as needing reloading. This must be done when using the SQLITE_TEMP_STORE -** or DEFAULT_TEMP_STORE pragmas. -*/ -static int changeTempStorage(Parse *pParse, const char *zStorageType){ - int ts = getTempStore(zStorageType); - sqlite3 *db = pParse->db; - if( db->temp_store==ts ) return SQLITE_OK; - if( invalidateTempStorage( pParse ) != SQLITE_OK ){ - return SQLITE_ERROR; - } - db->temp_store = (u8)ts; - return SQLITE_OK; -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -/* -** Set result column names for a pragma. -*/ -static void setPragmaResultColumnNames( - Vdbe *v, /* The query under construction */ - const PragmaName *pPragma /* The pragma */ -){ - u8 n = pPragma->nPragCName; - sqlite3VdbeSetNumCols(v, n==0 ? 1 : n); - if( n==0 ){ - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC); - }else{ - int i, j; - for(i=0, j=pPragma->iPragCName; iautoCommit ){ - Db *pDb = db->aDb; - int n = db->nDb; - assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); - assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); - assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); - assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) - == PAGER_FLAGS_MASK ); - assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level ); - while( (n--) > 0 ){ - if( pDb->pBt ){ - sqlite3BtreeSetPagerFlags(pDb->pBt, - pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) ); - } - pDb++; - } - } -} -#else -# define setAllPagerFlags(X) /* no-op */ -#endif - - -/* -** Return a human-readable name for a constraint resolution action. -*/ -#ifndef SQLITE_OMIT_FOREIGN_KEY -static const char *actionName(u8 action){ - const char *zName; - switch( action ){ - case OE_SetNull: zName = "SET NULL"; break; - case OE_SetDflt: zName = "SET DEFAULT"; break; - case OE_Cascade: zName = "CASCADE"; break; - case OE_Restrict: zName = "RESTRICT"; break; - default: zName = "NO ACTION"; - assert( action==OE_None ); break; - } - return zName; -} -#endif - - -/* -** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants -** defined in pager.h. This function returns the associated lowercase -** journal-mode name. -*/ -SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){ - static char * const azModeName[] = { - "delete", "persist", "off", "truncate", "memory" -#ifndef SQLITE_OMIT_WAL - , "wal" -#endif - }; - assert( PAGER_JOURNALMODE_DELETE==0 ); - assert( PAGER_JOURNALMODE_PERSIST==1 ); - assert( PAGER_JOURNALMODE_OFF==2 ); - assert( PAGER_JOURNALMODE_TRUNCATE==3 ); - assert( PAGER_JOURNALMODE_MEMORY==4 ); - assert( PAGER_JOURNALMODE_WAL==5 ); - assert( eMode>=0 && eMode<=ArraySize(azModeName) ); - - if( eMode==ArraySize(azModeName) ) return 0; - return azModeName[eMode]; -} - -/* -** Locate a pragma in the aPragmaName[] array. -*/ -static const PragmaName *pragmaLocate(const char *zName){ - int upr, lwr, mid = 0, rc; - lwr = 0; - upr = ArraySize(aPragmaName)-1; - while( lwr<=upr ){ - mid = (lwr+upr)/2; - rc = sqlite3_stricmp(zName, aPragmaName[mid].zName); - if( rc==0 ) break; - if( rc<0 ){ - upr = mid - 1; - }else{ - lwr = mid + 1; - } - } - return lwr>upr ? 0 : &aPragmaName[mid]; -} - -/* -** Create zero or more entries in the output for the SQL functions -** defined by FuncDef p. -*/ -static void pragmaFunclistLine( - Vdbe *v, /* The prepared statement being created */ - FuncDef *p, /* A particular function definition */ - 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 char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" }; - - assert( SQLITE_FUNC_ENCMASK==0x3 ); - assert( strcmp(azEnc[SQLITE_UTF8],"utf8")==0 ); - assert( strcmp(azEnc[SQLITE_UTF16LE],"utf16le")==0 ); - assert( strcmp(azEnc[SQLITE_UTF16BE],"utf16be")==0 ); - - if( p->xSFunc==0 ) continue; - if( (p->funcFlags & SQLITE_FUNC_INTERNAL)!=0 - && showInternFuncs==0 - ){ - continue; - } - if( p->xValue!=0 ){ - zType = "w"; - }else if( p->xFinalize!=0 ){ - zType = "a"; - }else{ - zType = "s"; - } - sqlite3VdbeMultiLoad(v, 1, "sissii", - p->zName, isBuiltin, - zType, azEnc[p->funcFlags&SQLITE_FUNC_ENCMASK], - p->nArg, - (p->funcFlags & mask) ^ SQLITE_INNOCUOUS - ); - } -} - - -/* -** Helper subroutine for PRAGMA integrity_check: -** -** Generate code to output a single-column result row with a value of the -** string held in register 3. Decrement the result count in register 1 -** and halt if the maximum number of result rows have been issued. -*/ -static int integrityCheckResultRow(Vdbe *v){ - int addr; - sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); - addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp0(v, OP_Halt); - return addr; -} - -/* -** Process a pragma statement. -** -** Pragmas are of this form: -** -** PRAGMA [schema.]id [= value] -** -** The identifier might also be a string. The value is a string, and -** identifier, or a number. If minusFlag is true, then the value is -** a number that was preceded by a minus sign. -** -** If the left side is "database.id" then pId1 is the database name -** and pId2 is the id. If the left side is just "id" then pId1 is the -** id and pId2 is any empty string. -*/ -SQLITE_PRIVATE void sqlite3Pragma( - Parse *pParse, - Token *pId1, /* First part of [schema.]id field */ - Token *pId2, /* Second part of [schema.]id field, or NULL */ - Token *pValue, /* Token for , or NULL */ - int minusFlag /* True if a '-' sign preceded */ -){ - char *zLeft = 0; /* Nul-terminated UTF-8 string */ - char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ - const char *zDb = 0; /* The database name */ - Token *pId; /* Pointer to token */ - char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ - int iDb; /* Database index for */ - int rc; /* return value form SQLITE_FCNTL_PRAGMA */ - sqlite3 *db = pParse->db; /* The database connection */ - Db *pDb; /* The specific database being pragmaed */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ - const PragmaName *pPragma; /* The pragma */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - extern int sqlcipher_codec_pragma(sqlite3*, int, Parse *, const char *, const char *); -#endif -/* END SQLCIPHER */ - - if( v==0 ) return; - sqlite3VdbeRunOnlyOnce(v); - pParse->nMem = 2; - - /* Interpret the [schema.] part of the pragma statement. iDb is the - ** index of the database this pragma is being applied to in db.aDb[]. */ - iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); - if( iDb<0 ) return; - pDb = &db->aDb[iDb]; - - /* If the temp database has been explicitly named as part of the - ** pragma, make sure it is open. - */ - if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ - return; - } - - zLeft = sqlite3NameFromToken(db, pId); - if( !zLeft ) return; - if( minusFlag ){ - zRight = sqlite3MPrintf(db, "-%T", pValue); - }else{ - zRight = sqlite3NameFromToken(db, pValue); - } - - assert( pId2 ); - zDb = pId2->n>0 ? pDb->zDbSName : 0; - if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ - goto pragma_out; - } - - /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS - ** connection. If it returns SQLITE_OK, then assume that the VFS - ** handled the pragma and generate a no-op prepared statement. - ** - ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, - ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file - ** object corresponding to the database file to which the pragma - ** statement refers. - ** - ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA - ** file control is an array of pointers to strings (char**) in which the - ** second element of the array is the name of the pragma and the third - ** element is the argument to the pragma or NULL if the pragma has no - ** argument. - */ - aFcntl[0] = 0; - aFcntl[1] = zLeft; - aFcntl[2] = zRight; - aFcntl[3] = 0; - db->busyHandler.nBusy = 0; - rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); - if( rc==SQLITE_OK ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); - returnSingleText(v, aFcntl[0]); - sqlite3_free(aFcntl[0]); - goto pragma_out; - } - if( rc!=SQLITE_NOTFOUND ){ - if( aFcntl[0] ){ - sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); - sqlite3_free(aFcntl[0]); - } - pParse->nErr++; - pParse->rc = rc; - - goto pragma_out; - } - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if(sqlcipher_codec_pragma(db, iDb, pParse, zLeft, zRight)) { - /* sqlcipher_codec_pragma executes internal */ - goto pragma_out; - } -#endif -/* END SQLCIPHER */ - - /* Locate the pragma in the lookup table */ - pPragma = pragmaLocate(zLeft); - 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 ){ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - } - - /* Register the result column names for pragmas that return results */ - if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 - && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0) - ){ - setPragmaResultColumnNames(v, pPragma); - } - - /* Jump to the appropriate pragma handler */ - switch( pPragma->ePragTyp ){ - -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) - /* - ** PRAGMA [schema.]default_cache_size - ** PRAGMA [schema.]default_cache_size=N - ** - ** The first form reports the current persistent setting for the - ** page cache size. The value returned is the maximum number of - ** pages in the page cache. The second form sets both the current - ** page cache size value and the persistent page cache size value - ** stored in the database file. - ** - ** Older versions of SQLite would set the default cache size to a - ** negative number to indicate synchronous=OFF. These days, synchronous - ** is always on by default regardless of the sign of the default cache - ** size. But continue to take the absolute value of the default cache - ** size of historical compatibility. - */ - case PragTyp_DEFAULT_CACHE_SIZE: { - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList getCacheSize[] = { - { OP_Transaction, 0, 0, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ - { OP_IfPos, 1, 8, 0}, - { OP_Integer, 0, 2, 0}, - { OP_Subtract, 1, 2, 1}, - { OP_IfPos, 1, 8, 0}, - { OP_Integer, 0, 1, 0}, /* 6 */ - { OP_Noop, 0, 0, 0}, - { OP_ResultRow, 1, 1, 0}, - }; - VdbeOp *aOp; - sqlite3VdbeUsesBtree(v, iDb); - if( !zRight ){ - pParse->nMem += 2; - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn); - if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; - }else{ - int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pDb->pSchema->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - break; - } -#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */ - -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - /* - ** PRAGMA [schema.]page_size - ** PRAGMA [schema.]page_size=N - ** - ** The first form reports the current setting for the - ** database page size in bytes. The second form sets the - ** database page size value. The value can only be set if - ** the database has not yet been created. - */ - case PragTyp_PAGE_SIZE: { - Btree *pBt = pDb->pBt; - assert( pBt!=0 ); - if( !zRight ){ - int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; - returnSingleInt(v, size); - }else{ - /* Malloc may fail when setting the page-size, as there is an internal - ** buffer that the pager module resizes using sqlite3_realloc(). - */ - db->nextPagesize = sqlite3Atoi(zRight); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){ - sqlite3OomFault(db); - } - } - break; - } - - /* - ** PRAGMA [schema.]secure_delete - ** PRAGMA [schema.]secure_delete=ON/OFF/FAST - ** - ** The first form reports the current setting for the - ** secure_delete flag. The second form changes the secure_delete - ** flag setting and reports the new value. - */ - case PragTyp_SECURE_DELETE: { - Btree *pBt = pDb->pBt; - int b = -1; - assert( pBt!=0 ); - if( zRight ){ - if( sqlite3_stricmp(zRight, "fast")==0 ){ - b = 2; - }else{ - b = sqlite3GetBoolean(zRight, 0); - } - } - if( pId2->n==0 && b>=0 ){ - int ii; - for(ii=0; iinDb; ii++){ - sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); - } - } - b = sqlite3BtreeSecureDelete(pBt, b); - returnSingleInt(v, b); - break; - } - - /* - ** PRAGMA [schema.]max_page_count - ** PRAGMA [schema.]max_page_count=N - ** - ** The first form reports the current setting for the - ** maximum number of pages in the database file. The - ** second form attempts to change this setting. Both - ** forms return the current setting. - ** - ** The absolute value of N is used. This is undocumented and might - ** change. The only purpose is to provide an easy way to test - ** the sqlite3AbsInt32() function. - ** - ** PRAGMA [schema.]page_count - ** - ** Return the number of pages in the specified database. - */ - case PragTyp_PAGE_COUNT: { - int iReg; - i64 x = 0; - sqlite3CodeVerifySchema(pParse, iDb); - iReg = ++pParse->nMem; - if( sqlite3Tolower(zLeft[0])=='p' ){ - sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); - }else{ - if( zRight && sqlite3DecOrHexToI64(zRight,&x)==0 ){ - if( x<0 ) x = 0; - else if( x>0xfffffffe ) x = 0xfffffffe; - }else{ - x = 0; - } - sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, (int)x); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); - break; - } - - /* - ** PRAGMA [schema.]locking_mode - ** PRAGMA [schema.]locking_mode = (normal|exclusive) - */ - case PragTyp_LOCKING_MODE: { - const char *zRet = "normal"; - int eMode = getLockingMode(zRight); - - if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ - /* Simple "PRAGMA locking_mode;" statement. This is a query for - ** the current default locking mode (which may be different to - ** the locking-mode of the main database). - */ - eMode = db->dfltLockMode; - }else{ - Pager *pPager; - if( pId2->n==0 ){ - /* This indicates that no database name was specified as part - ** of the PRAGMA command. In this case the locking-mode must be - ** set on all attached databases, as well as the main db file. - ** - ** Also, the sqlite3.dfltLockMode variable is set so that - ** any subsequently attached databases also use the specified - ** locking mode. - */ - int ii; - assert(pDb==&db->aDb[0]); - for(ii=2; iinDb; ii++){ - pPager = sqlite3BtreePager(db->aDb[ii].pBt); - sqlite3PagerLockingMode(pPager, eMode); - } - db->dfltLockMode = (u8)eMode; - } - pPager = sqlite3BtreePager(pDb->pBt); - eMode = sqlite3PagerLockingMode(pPager, eMode); - } - - assert( eMode==PAGER_LOCKINGMODE_NORMAL - || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); - if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ - zRet = "exclusive"; - } - returnSingleText(v, zRet); - break; - } - - /* - ** PRAGMA [schema.]journal_mode - ** PRAGMA [schema.]journal_mode = - ** (delete|persist|off|truncate|memory|wal|off) - */ - case PragTyp_JOURNAL_MODE: { - int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ - int ii; /* Loop counter */ - - if( zRight==0 ){ - /* If there is no "=MODE" part of the pragma, do a query for the - ** current mode */ - eMode = PAGER_JOURNALMODE_QUERY; - }else{ - const char *zMode; - int n = sqlite3Strlen30(zRight); - for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){ - if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break; - } - if( !zMode ){ - /* If the "=MODE" part does not match any known journal mode, - ** then do a query */ - eMode = PAGER_JOURNALMODE_QUERY; - } - if( eMode==PAGER_JOURNALMODE_OFF && (db->flags & SQLITE_Defensive)!=0 ){ - /* Do not allow journal-mode "OFF" in defensive since the database - ** can become corrupted using ordinary SQL when the journal is off */ - eMode = PAGER_JOURNALMODE_QUERY; - } - } - if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ - /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ - iDb = 0; - pId2->n = 1; - } - for(ii=db->nDb-1; ii>=0; ii--){ - if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ - sqlite3VdbeUsesBtree(v, ii); - sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode); - } - } - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - break; - } - - /* - ** PRAGMA [schema.]journal_size_limit - ** PRAGMA [schema.]journal_size_limit=N - ** - ** Get or set the size limit on rollback journal files. - */ - case PragTyp_JOURNAL_SIZE_LIMIT: { - Pager *pPager = sqlite3BtreePager(pDb->pBt); - i64 iLimit = -2; - if( zRight ){ - sqlite3DecOrHexToI64(zRight, &iLimit); - if( iLimit<-1 ) iLimit = -1; - } - iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); - returnSingleInt(v, iLimit); - break; - } - -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - - /* - ** PRAGMA [schema.]auto_vacuum - ** PRAGMA [schema.]auto_vacuum=N - ** - ** Get or set the value of the database 'auto-vacuum' parameter. - ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - case PragTyp_AUTO_VACUUM: { - Btree *pBt = pDb->pBt; - assert( pBt!=0 ); - if( !zRight ){ - returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt)); - }else{ - int eAuto = getAutoVacuum(zRight); - assert( eAuto>=0 && eAuto<=2 ); - db->nextAutovac = (u8)eAuto; - /* Call SetAutoVacuum() to set initialize the internal auto and - ** incr-vacuum flags. This is required in case this connection - ** creates the database file. It is important that it is created - ** as an auto-vacuum capable db. - */ - rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); - if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ - /* When setting the auto_vacuum mode to either "full" or - ** "incremental", write the value of meta[6] in the database - ** file. Before writing to meta[6], check that meta[3] indicates - ** that this really is an auto-vacuum capable database. - */ - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList setMeta6[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, - { OP_If, 1, 0, 0}, /* 2 */ - { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ - { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ - }; - VdbeOp *aOp; - int iAddr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); - if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[2].p2 = iAddr+4; - aOp[4].p1 = iDb; - aOp[4].p3 = eAuto - 1; - sqlite3VdbeUsesBtree(v, iDb); - } - } - break; - } -#endif - - /* - ** PRAGMA [schema.]incremental_vacuum(N) - ** - ** Do N steps of incremental vacuuming on a database. - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - case PragTyp_INCREMENTAL_VACUUM: { - int iLimit = 0, addr; - if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ - iLimit = 0x7fffffff; - } - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); - addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_ResultRow, 1); - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr); - break; - } -#endif - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS - /* - ** PRAGMA [schema.]cache_size - ** PRAGMA [schema.]cache_size=N - ** - ** The first form reports the current local setting for the - ** page cache size. The second form sets the local - ** page cache size value. If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - */ - case PragTyp_CACHE_SIZE: { - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !zRight ){ - returnSingleInt(v, pDb->pSchema->cache_size); - }else{ - int size = sqlite3Atoi(zRight); - pDb->pSchema->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - break; - } - - /* - ** PRAGMA [schema.]cache_spill - ** PRAGMA cache_spill=BOOLEAN - ** PRAGMA [schema.]cache_spill=N - ** - ** The first form reports the current local setting for the - ** page cache spill size. The second form turns cache spill on - ** or off. When turning cache spill on, the size is set to the - ** current cache_size. The third form sets a spill size that - ** may be different form the cache size. - ** If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - ** - ** If the number of cache_spill pages is less then the number of - ** cache_size pages, no spilling occurs until the page count exceeds - ** the number of cache_size pages. - ** - ** The cache_spill=BOOLEAN setting applies to all attached schemas, - ** not just the schema specified. - */ - case PragTyp_CACHE_SPILL: { - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !zRight ){ - returnSingleInt(v, - (db->flags & SQLITE_CacheSpill)==0 ? 0 : - sqlite3BtreeSetSpillSize(pDb->pBt,0)); - }else{ - int size = 1; - if( sqlite3GetInt32(zRight, &size) ){ - sqlite3BtreeSetSpillSize(pDb->pBt, size); - } - if( sqlite3GetBoolean(zRight, size!=0) ){ - db->flags |= SQLITE_CacheSpill; - }else{ - db->flags &= ~(u64)SQLITE_CacheSpill; - } - setAllPagerFlags(db); - } - break; - } - - /* - ** PRAGMA [schema.]mmap_size(N) - ** - ** Used to set mapping size limit. The mapping size limit is - ** used to limit the aggregate size of all memory mapped regions of the - ** database file. If this parameter is set to zero, then memory mapping - ** is not used at all. If N is negative, then the default memory map - ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. - ** The parameter N is measured in bytes. - ** - ** This value is advisory. The underlying VFS is free to memory map - ** as little or as much as it wants. Except, if N is set to 0 then the - ** upper layers will never invoke the xFetch interfaces to the VFS. - */ - case PragTyp_MMAP_SIZE: { - sqlite3_int64 sz; -#if SQLITE_MAX_MMAP_SIZE>0 - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( zRight ){ - int ii; - sqlite3DecOrHexToI64(zRight, &sz); - if( sz<0 ) sz = sqlite3GlobalConfig.szMmap; - if( pId2->n==0 ) db->szMmap = sz; - for(ii=db->nDb-1; ii>=0; ii--){ - if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ - sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz); - } - } - } - sz = -1; - rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz); -#else - sz = 0; - rc = SQLITE_OK; -#endif - if( rc==SQLITE_OK ){ - returnSingleInt(v, sz); - }else if( rc!=SQLITE_NOTFOUND ){ - pParse->nErr++; - pParse->rc = rc; - } - break; - } - - /* - ** PRAGMA temp_store - ** PRAGMA temp_store = "default"|"memory"|"file" - ** - ** Return or set the local value of the temp_store flag. Changing - ** the local value does not make changes to the disk file and the default - ** value will be restored the next time the database is opened. - ** - ** Note that it is possible for the library compile-time options to - ** override this setting - */ - case PragTyp_TEMP_STORE: { - if( !zRight ){ - returnSingleInt(v, db->temp_store); - }else{ - changeTempStorage(pParse, zRight); - } - break; - } - - /* - ** PRAGMA temp_store_directory - ** PRAGMA temp_store_directory = ""|"directory_name" - ** - ** Return or set the local value of the temp_store_directory flag. Changing - ** the value sets a specific directory to be used for temporary files. - ** Setting to a null string reverts to the default temporary directory search. - ** If temporary directory is changed, then invalidateTempStorage. - ** - */ - case PragTyp_TEMP_STORE_DIRECTORY: { - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - if( !zRight ){ - returnSingleText(v, sqlite3_temp_directory); - }else{ -#ifndef SQLITE_OMIT_WSD - if( zRight[0] ){ - int res; - rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); - if( rc!=SQLITE_OK || res==0 ){ - sqlite3ErrorMsg(pParse, "not a writable directory"); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - goto pragma_out; - } - } - if( SQLITE_TEMP_STORE==0 - || (SQLITE_TEMP_STORE==1 && db->temp_store<=1) - || (SQLITE_TEMP_STORE==2 && db->temp_store==1) - ){ - invalidateTempStorage(pParse); - } - sqlite3_free(sqlite3_temp_directory); - if( zRight[0] ){ - sqlite3_temp_directory = sqlite3_mprintf("%s", zRight); - }else{ - sqlite3_temp_directory = 0; - } -#endif /* SQLITE_OMIT_WSD */ - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - break; - } - -#if SQLITE_OS_WIN - /* - ** PRAGMA data_store_directory - ** PRAGMA data_store_directory = ""|"directory_name" - ** - ** Return or set the local value of the data_store_directory flag. Changing - ** the value sets a specific directory to be used for database files that - ** were specified with a relative pathname. Setting to a null string reverts - ** to the default database directory, which for database files specified with - ** a relative path will probably be based on the current directory for the - ** process. Database file specified with an absolute path are not impacted - ** by this setting, regardless of its value. - ** - */ - case PragTyp_DATA_STORE_DIRECTORY: { - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - if( !zRight ){ - returnSingleText(v, sqlite3_data_directory); - }else{ -#ifndef SQLITE_OMIT_WSD - if( zRight[0] ){ - int res; - rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); - if( rc!=SQLITE_OK || res==0 ){ - sqlite3ErrorMsg(pParse, "not a writable directory"); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - goto pragma_out; - } - } - sqlite3_free(sqlite3_data_directory); - if( zRight[0] ){ - sqlite3_data_directory = sqlite3_mprintf("%s", zRight); - }else{ - sqlite3_data_directory = 0; - } -#endif /* SQLITE_OMIT_WSD */ - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - break; - } -#endif - -#if SQLITE_ENABLE_LOCKING_STYLE - /* - ** PRAGMA [schema.]lock_proxy_file - ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" - ** - ** Return or set the value of the lock_proxy_file flag. Changing - ** the value sets a specific file to be used for database access locks. - ** - */ - case PragTyp_LOCK_PROXY_FILE: { - if( !zRight ){ - Pager *pPager = sqlite3BtreePager(pDb->pBt); - char *proxy_file_path = NULL; - sqlite3_file *pFile = sqlite3PagerFile(pPager); - sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, - &proxy_file_path); - returnSingleText(v, proxy_file_path); - }else{ - Pager *pPager = sqlite3BtreePager(pDb->pBt); - sqlite3_file *pFile = sqlite3PagerFile(pPager); - int res; - if( zRight[0] ){ - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, - zRight); - } else { - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, - NULL); - } - if( res!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "failed to set lock proxy file"); - goto pragma_out; - } - } - break; - } -#endif /* SQLITE_ENABLE_LOCKING_STYLE */ - - /* - ** PRAGMA [schema.]synchronous - ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA - ** - ** Return or set the local value of the synchronous flag. Changing - ** the local value does not make changes to the disk file and the - ** default value will be restored the next time the database is - ** opened. - */ - case PragTyp_SYNCHRONOUS: { - if( !zRight ){ - returnSingleInt(v, pDb->safety_level-1); - }else{ - if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, - "Safety level may not be changed inside a transaction"); - }else if( iDb!=1 ){ - int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; - if( iLevel==0 ) iLevel = 1; - pDb->safety_level = iLevel; - pDb->bSyncSet = 1; - setAllPagerFlags(db); - } - } - break; - } -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_FLAG_PRAGMAS - case PragTyp_FLAG: { - if( zRight==0 ){ - setPragmaResultColumnNames(v, pPragma); - returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); - }else{ - u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ - if( db->autoCommit==0 ){ - /* Foreign key support may not be enabled or disabled while not - ** in auto-commit mode. */ - mask &= ~(SQLITE_ForeignKeys); - } - - if( sqlite3GetBoolean(zRight, 0) ){ - if( (mask & SQLITE_WriteSchema)==0 - || (db->flags & SQLITE_Defensive)==0 - ){ - db->flags |= mask; - } - }else{ - db->flags &= ~mask; - if( mask==SQLITE_DeferFKs ){ - db->nDeferredImmCons = 0; - db->nDeferredCons = 0; - } - if( (mask & SQLITE_WriteSchema)!=0 - && 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. */ - sqlite3ResetAllSchemasOfConnection(db); - } - } - - /* Many of the flag-pragmas modify the code generated by the SQL - ** compiler (eg. count_changes). So add an opcode to expire all - ** compiled SQL statements after modifying a pragma value. - */ - sqlite3VdbeAddOp0(v, OP_Expire); - setAllPagerFlags(db); - } - break; - } -#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ - -#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS - /* - ** PRAGMA table_info(
    ) - ** - ** Return a single row for each column of the named table. The columns of - ** the returned data set are: - ** - ** cid: Column id (numbered from left to right, starting at 0) - ** name: Column name - ** type: Column declaration type. - ** notnull: True if 'NOT NULL' is part of column declaration - ** dflt_value: The default value for the column, if any. - ** pk: Non-zero for PK fields. - */ - case PragTyp_TABLE_INFO: if( zRight ){ - Table *pTab; - sqlite3CodeVerifyNamedSchema(pParse, zDb); - pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); - if( pTab ){ - int i, k; - int nHidden = 0; - Column *pCol; - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem = 7; - sqlite3ViewGetColumnNames(pParse, pTab); - for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ - int isHidden = 0; - const Expr *pColExpr; - if( pCol->colFlags & COLFLAG_NOINSERT ){ - if( pPragma->iArg==0 ){ - nHidden++; - continue; - } - if( pCol->colFlags & COLFLAG_VIRTUAL ){ - isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */ - }else if( pCol->colFlags & COLFLAG_STORED ){ - isHidden = 3; /* GENERATED ALWAYS AS ... STORED */ - }else{ assert( pCol->colFlags & COLFLAG_HIDDEN ); - isHidden = 1; /* HIDDEN */ - } - } - if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ - k = 0; - }else if( pPk==0 ){ - k = 1; - }else{ - for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} - } - pColExpr = sqlite3ColumnExpr(pTab,pCol); - assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 ); - assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue) - || isHidden>=2 ); - sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", - i-nHidden, - pCol->zCnName, - sqlite3ColumnType(pCol,""), - pCol->notNull ? 1 : 0, - (isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken, - k, - isHidden); - } - } - } - 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; - sqlite3CodeVerifyNamedSchema(pParse, zDb); - for(ii=0; iinDb; ii++){ - HashElem *k; - Hash *pHash; - int initNCol; - if( zDb && 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 = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName); - if( zSql ){ - sqlite3_stmt *pDummy = 0; - (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG, - &pDummy, 0); - (void)sqlite3_finalize(pDummy); - sqlite3DbFree(db, zSql); - } - if( db->mallocFailed ){ - 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 && 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"; - } - sqlite3VdbeMultiLoad(v, 1, "sssiii", - db->aDb[ii].zDbSName, - 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; - HashElem *i; - pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse, iDb); - for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - sqlite3VdbeMultiLoad(v, 1, "ssiii", - sqlite3PreferredTableName(pTab->zName), - 0, - pTab->szTabRow, - pTab->nRowLogEst, - pTab->tabFlags); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeMultiLoad(v, 2, "siiiX", - pIdx->zName, - pIdx->szIdxRow, - pIdx->aiRowLogEst[0], - pIdx->hasStat1); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); - } - } - } - break; -#endif - - case PragTyp_INDEX_INFO: if( zRight ){ - Index *pIdx; - Table *pTab; - pIdx = sqlite3FindIndex(db, zRight, zDb); - if( pIdx==0 ){ - /* If there is no index named zRight, check to see if there is a - ** WITHOUT ROWID table named zRight, and if there is, show the - ** structure of the PRIMARY KEY index for that table. */ - pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); - if( pTab && !HasRowid(pTab) ){ - pIdx = sqlite3PrimaryKeyIndex(pTab); - } - } - if( pIdx ){ - int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); - int i; - int mx; - if( pPragma->iArg ){ - /* PRAGMA index_xinfo (newer version with more rows and columns) */ - mx = pIdx->nColumn; - pParse->nMem = 6; - }else{ - /* PRAGMA index_info (legacy version) */ - mx = pIdx->nKeyCol; - pParse->nMem = 3; - } - pTab = pIdx->pTable; - sqlite3CodeVerifySchema(pParse, iIdxDb); - assert( pParse->nMem<=pPragma->nPragCName ); - for(i=0; iaiColumn[i]; - sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum, - cnum<0 ? 0 : pTab->aCol[cnum].zCnName); - if( pPragma->iArg ){ - sqlite3VdbeMultiLoad(v, 4, "isiX", - pIdx->aSortOrder[i], - pIdx->azColl[i], - inKeyCol); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); - } - } - } - break; - - case PragTyp_INDEX_LIST: if( zRight ){ - Index *pIdx; - Table *pTab; - int i; - pTab = sqlite3FindTable(db, zRight, zDb); - if( pTab ){ - int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse, iTabDb); - for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ - const char *azOrigin[] = { "c", "u", "pk" }; - sqlite3VdbeMultiLoad(v, 1, "isisi", - i, - pIdx->zName, - IsUniqueIndex(pIdx), - azOrigin[pIdx->idxType], - pIdx->pPartIdxWhere!=0); - } - } - } - break; - - case PragTyp_DATABASE_LIST: { - int i; - pParse->nMem = 3; - for(i=0; inDb; i++){ - if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zDbSName!=0 ); - sqlite3VdbeMultiLoad(v, 1, "iss", - i, - db->aDb[i].zDbSName, - sqlite3BtreeGetFilename(db->aDb[i].pBt)); - } - } - break; - - case PragTyp_COLLATION_LIST: { - int i = 0; - HashElem *p; - pParse->nMem = 2; - for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ - CollSeq *pColl = (CollSeq *)sqliteHashData(p); - sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); - } - } - break; - -#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS - case PragTyp_FUNCTION_LIST: { - int i; - HashElem *j; - FuncDef *p; - int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0; - pParse->nMem = 6; - for(i=0; iu.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); - } - } - break; - -#ifndef SQLITE_OMIT_VIRTUALTABLE - case PragTyp_MODULE_LIST: { - HashElem *j; - pParse->nMem = 1; - for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){ - Module *pMod = (Module*)sqliteHashData(j); - sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName); - } - } - break; -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - - case PragTyp_PRAGMA_LIST: { - int i; - for(i=0; iu.tab.pFKey; - if( pFK ){ - int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); - int i = 0; - pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse, iTabDb); - while(pFK){ - int j; - for(j=0; jnCol; j++){ - sqlite3VdbeMultiLoad(v, 1, "iissssss", - i, - j, - pFK->zTo, - pTab->aCol[pFK->aCol[j].iFrom].zCnName, - pFK->aCol[j].zCol, - actionName(pFK->aAction[1]), /* ON UPDATE */ - actionName(pFK->aAction[0]), /* ON DELETE */ - "NONE"); - } - ++i; - pFK = pFK->pNextFrom; - } - } - } - } - break; -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY -#ifndef SQLITE_OMIT_TRIGGER - case PragTyp_FOREIGN_KEY_CHECK: { - FKey *pFK; /* A foreign key constraint */ - Table *pTab; /* Child table contain "REFERENCES" keyword */ - Table *pParent; /* Parent table that child points to */ - Index *pIdx; /* Index in the parent table */ - int i; /* Loop counter: Foreign key number for pTab */ - int j; /* Loop counter: Field of the foreign key */ - HashElem *k; /* Loop counter: Next table in schema */ - int x; /* result variable */ - int regResult; /* 3 registers to hold a result row */ - 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 */ - int *aiCols; /* child to parent column mapping */ - - regResult = pParse->nMem+1; - pParse->nMem += 4; - regRow = ++pParse->nMem; - k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); - while( k ){ - if( zRight ){ - pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); - k = 0; - }else{ - pTab = (Table*)sqliteHashData(k); - k = sqliteHashNext(k); - } - if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zDbSName; - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - sqlite3TouchRegister(pParse, pTab->nCol+regRow); - sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); - sqlite3VdbeLoadString(v, regResult, pTab->zName); - assert( IsOrdinaryTable(pTab) ); - for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ - pParent = sqlite3FindTable(db, pFK->zTo, zDb); - if( pParent==0 ) continue; - pIdx = 0; - sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); - if( x==0 ){ - if( pIdx==0 ){ - sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); - }else{ - sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - } - }else{ - k = 0; - break; - } - } - assert( pParse->nErr>0 || pFK==0 ); - if( pFK ) break; - if( pParse->nTabnTab = i; - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); - assert( IsOrdinaryTable(pTab) ); - for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ - pParent = sqlite3FindTable(db, pFK->zTo, zDb); - pIdx = 0; - aiCols = 0; - if( pParent ){ - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); - assert( x==0 || db->mallocFailed ); - } - addrOk = sqlite3VdbeMakeLabel(pParse); - - /* Generate code to read the child key values into registers - ** 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. */ - sqlite3TouchRegister(pParse, regRow + pFK->nCol); - for(j=0; jnCol; j++){ - int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom; - sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); - } - - /* Generate code to query the parent index for a matching parent - ** key. If a match is found, jump to addrOk. */ - if( pIdx ){ - sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0, - sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol); - VdbeCoverage(v); - }else if( pParent ){ - int jmp = sqlite3VdbeCurrentAddr(v)+2; - sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrOk); - assert( pFK->nCol==1 || db->mallocFailed ); - } - - /* Generate code to report an FK violation to the caller. */ - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1); - } - sqlite3VdbeMultiLoad(v, regResult+2, "siX", pFK->zTo, i-1); - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); - sqlite3VdbeResolveLabel(v, addrOk); - sqlite3DbFree(db, aiCols); - } - sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrTop); - } - } - break; -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - -#ifndef SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA - /* Reinstall the LIKE and GLOB functions. The variant of LIKE - ** used will be case sensitive or not depending on the RHS. - */ - case PragTyp_CASE_SENSITIVE_LIKE: { - if( zRight ){ - sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); - } - } - break; -#endif /* SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA */ - -#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX -# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 -#endif - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK - /* PRAGMA integrity_check - ** PRAGMA integrity_check(N) - ** PRAGMA quick_check - ** PRAGMA quick_check(N) - ** - ** Verify the integrity of the database. - ** - ** The "quick_check" is reduced version of - ** integrity_check designed to detect most database corruption - ** without the overhead of cross-checking indexes. Quick_check - ** is linear time whereas integrity_check is O(NlogN). - ** - ** The maximum number of errors is 100 by default. A different default - ** can be specified using a numeric parameter N. - ** - ** Or, the parameter N can be the name of a table. In that case, only - ** the one table named is verified. The freelist is only verified if - ** the named table is "sqlite_schema" (or one of its aliases). - ** - ** All schemas are checked by default. To check just a single - ** schema, use the form: - ** - ** PRAGMA schema.integrity_check; - */ - case PragTyp_INTEGRITY_CHECK: { - int i, j, addr, mxErr; - Table *pObjTab = 0; /* Check only this one table, if not NULL */ - - int isQuick = (sqlite3Tolower(zLeft[0])=='q'); - - /* If the PRAGMA command was of the form "PRAGMA .integrity_check", - ** then iDb is set to the index of the database identified by . - ** In this case, the integrity of database iDb only is verified by - ** the VDBE created below. - ** - ** Otherwise, if the command was simply "PRAGMA integrity_check" (or - ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb - ** to -1 here, to indicate that the VDBE should verify the integrity - ** of all attached databases. */ - assert( iDb>=0 ); - assert( iDb==0 || pId2->z ); - if( pId2->z==0 ) iDb = -1; - - /* Initialize the VDBE program */ - pParse->nMem = 6; - - /* Set the maximum error count */ - mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; - if( zRight ){ - if( sqlite3GetInt32(pValue->z, &mxErr) ){ - if( mxErr<=0 ){ - mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; - } - }else{ - pObjTab = sqlite3LocateTable(pParse, 0, zRight, - iDb>=0 ? db->aDb[iDb].zDbSName : 0); - } - } - sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */ - - /* Do an integrity check on each database file */ - for(i=0; inDb; i++){ - HashElem *x; /* For looping over tables in the schema */ - Hash *pTbls; /* Set of all tables in the schema */ - int *aRoot; /* Array of root page numbers of all btrees */ - int cnt = 0; /* Number of entries in aRoot[] */ - - if( OMIT_TEMPDB && i==1 ) continue; - if( iDb>=0 && i!=iDb ) continue; - - sqlite3CodeVerifySchema(pParse, i); - pParse->okConstFactor = 0; /* tag-20230327-1 */ - - /* Do an integrity check of the B-Tree - ** - ** Begin by finding the root pages numbers - ** for all tables and indices in the database. - */ - assert( sqlite3SchemaMutexHeld(db, i, 0) ); - pTbls = &db->aDb[i].pSchema->tblHash; - for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); /* Current table */ - Index *pIdx; /* An index on pTab */ - int nIdx; /* Number of indexes on pTab */ - if( pObjTab && pObjTab!=pTab ) continue; - if( HasRowid(pTab) ) cnt++; - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } - } - if( cnt==0 ) continue; - if( pObjTab ) cnt++; - aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1)); - if( aRoot==0 ) break; - cnt = 0; - if( pObjTab ) aRoot[++cnt] = 0; - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx; - if( pObjTab && pObjTab!=pTab ) continue; - if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - aRoot[++cnt] = pIdx->tnum; - } - } - aRoot[0] = cnt; - - /* Make sure sufficient number of registers have been allocated */ - sqlite3TouchRegister(pParse, 8+cnt); - sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt); - sqlite3ClearTempRegCache(pParse); - - /* Do the b-tree integrity checks */ - sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY); - sqlite3VdbeChangeP5(v, (u16)i); - addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), - P4_DYNAMIC); - sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, addr); - - /* Check that the indexes all have the right number of rows */ - cnt = pObjTab ? 1 : 0; - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - int iTab = 0; - Table *pTab = sqliteHashData(x); - Index *pIdx; - if( pObjTab && pObjTab!=pTab ) continue; - if( HasRowid(pTab) ){ - iTab = cnt++; - }else{ - iTab = cnt; - for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){ - if( IsPrimaryKeyIndex(pIdx) ) break; - iTab++; - } - } - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->pPartIdxWhere==0 ){ - addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab); - VdbeCoverageNeverNull(v); - sqlite3VdbeLoadString(v, 4, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, addr); - } - cnt++; - } - } - - /* Make sure all the indices are constructed correctly. - */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx, *pPk; - Index *pPrior = 0; /* Previous index */ - int loopTop; - int iDataCur, iIdxCur; - int r1 = -1; - int bStrict; /* True for a STRICT table */ - int r2; /* Previous key for WITHOUT ROWID tables */ - int mxCol; /* Maximum non-virtual column number */ - - if( pObjTab && pObjTab!=pTab ) continue; - if( !IsOrdinaryTable(pTab) ) continue; - if( isQuick || HasRowid(pTab) ){ - pPk = 0; - r2 = 0; - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol); - sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1); - } - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, - 1, 0, &iDataCur, &iIdxCur); - /* reg[7] counts the number of entries in the table. - ** reg[8+i] counts the number of entries in the i-th index - */ - sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ - } - assert( pParse->nMem>=8+j ); - assert( sqlite3NoTempsInRange(pParse,1,7+j) ); - sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); - loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); - - /* Fetch the right-most column from the table. This will cause - ** the entire record header to be parsed and sanity checked. It - ** will also prepopulate the cursor column cache that is used - ** by the OP_IsType code, so it is a required step. - */ - assert( !IsVirtual(pTab) ); - if( HasRowid(pTab) ){ - mxCol = -1; - for(j=0; jnCol; j++){ - if( (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)==0 ) mxCol++; - } - if( mxCol==pTab->iPKey ) mxCol--; - }else{ - /* COLFLAG_VIRTUAL columns are not included in the WITHOUT ROWID - ** PK index column-count, so there is no need to account for them - ** in this case. */ - mxCol = sqlite3PrimaryKeyIndex(pTab)->nColumn-1; - } - if( mxCol>=0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3); - sqlite3VdbeTypeofColumn(v, 3); - } - - if( !isQuick ){ - if( pPk ){ - /* Verify WITHOUT ROWID keys are in ascending order */ - int a1; - char *zErr; - a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol); - VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v); - zErr = sqlite3MPrintf(db, - "row not in PRIMARY KEY order for %s", - pTab->zName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, a1); - sqlite3VdbeJumpHere(v, a1+1); - for(j=0; jnKeyCol; j++){ - sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j); - } - } - } - /* Verify datatypes for all columns: - ** - ** (1) NOT NULL columns may not contain a NULL - ** (2) Datatype must be exact for non-ANY columns in STRICT tables - ** (3) Datatype for TEXT columns in non-STRICT tables must be - ** NULL, TEXT, or BLOB. - ** (4) Datatype for numeric columns in non-STRICT tables must not - ** be a TEXT value that can be losslessly converted to numeric. - */ - bStrict = (pTab->tabFlags & TF_Strict)!=0; - for(j=0; jnCol; j++){ - char *zErr; - Column *pCol = pTab->aCol + j; /* The column to be checked */ - int labelError; /* Jump here to report an error */ - int labelOk; /* Jump here if all looks ok */ - int p1, p3, p4; /* Operands to the OP_IsType opcode */ - int doTypeCheck; /* Check datatypes (besides NOT NULL) */ - - if( j==pTab->iPKey ) continue; - if( bStrict ){ - doTypeCheck = pCol->eCType>COLTYPE_ANY; - }else{ - doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB; - } - if( pCol->notNull==0 && !doTypeCheck ) continue; - - /* Compute the operands that will be needed for OP_IsType */ - p4 = SQLITE_NULL; - if( pCol->colFlags & COLFLAG_VIRTUAL ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); - p1 = -1; - p3 = 3; - }else{ - if( pCol->iDflt ){ - sqlite3_value *pDfltValue = 0; - sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db), - pCol->affinity, &pDfltValue); - if( pDfltValue ){ - p4 = sqlite3_value_type(pDfltValue); - sqlite3ValueFree(pDfltValue); - } - } - p1 = iDataCur; - if( !HasRowid(pTab) ){ - testcase( j!=sqlite3TableColumnToStorage(pTab, j) ); - p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j); - }else{ - p3 = sqlite3TableColumnToStorage(pTab,j); - testcase( p3!=j); - } - } - - labelError = sqlite3VdbeMakeLabel(pParse); - labelOk = sqlite3VdbeMakeLabel(pParse); - if( pCol->notNull ){ - /* (1) NOT NULL columns may not contain a NULL */ - int jmp3; - int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - VdbeCoverage(v); - if( p1<0 ){ - sqlite3VdbeChangeP5(v, 0x0f); /* INT, REAL, TEXT, or BLOB */ - jmp3 = jmp2; - }else{ - sqlite3VdbeChangeP5(v, 0x0d); /* INT, TEXT, or BLOB */ - /* OP_IsType does not detect NaN values in the database file - ** which should be treated as a NULL. So if the header type - ** is REAL, we have to load the actual data using OP_Column - ** to reliably determine if the value is a NULL. */ - sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3); - sqlite3ColumnDefault(v, pTab, j, 3); - jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk); - VdbeCoverage(v); - } - zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, - pCol->zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - if( doTypeCheck ){ - sqlite3VdbeGoto(v, labelError); - sqlite3VdbeJumpHere(v, jmp2); - sqlite3VdbeJumpHere(v, jmp3); - }else{ - /* VDBE byte code will fall thru */ - } - } - if( bStrict && doTypeCheck ){ - /* (2) Datatype must be exact for non-ANY columns in STRICT tables*/ - static unsigned char aStdTypeMask[] = { - 0x1f, /* ANY */ - 0x18, /* BLOB */ - 0x11, /* INT */ - 0x11, /* INTEGER */ - 0x13, /* REAL */ - 0x14 /* TEXT */ - }; - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) ); - sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]); - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "non-%s value in %s.%s", - sqlite3StdType[pCol->eCType-1], - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - }else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){ - /* (3) Datatype for TEXT columns in non-STRICT tables must be - ** NULL, TEXT, or BLOB. */ - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */ - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s", - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - }else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){ - /* (4) Datatype for numeric columns in non-STRICT tables must not - ** be a TEXT value that can be converted to numeric. */ - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */ - VdbeCoverage(v); - if( p1>=0 ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); - } - sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC); - sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4); - sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */ - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "TEXT value in %s.%s", - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - } - sqlite3VdbeResolveLabel(v, labelError); - integrityCheckResultRow(v); - sqlite3VdbeResolveLabel(v, labelOk); - } - /* Verify CHECK constraints */ - if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ - ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0); - if( db->mallocFailed==0 ){ - int addrCkFault = sqlite3VdbeMakeLabel(pParse); - int addrCkOk = sqlite3VdbeMakeLabel(pParse); - char *zErr; - int k; - pParse->iSelfTab = iDataCur + 1; - for(k=pCheck->nExpr-1; k>0; k--){ - sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); - } - sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, - SQLITE_JUMPIFNULL); - sqlite3VdbeResolveLabel(v, addrCkFault); - pParse->iSelfTab = 0; - zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", - pTab->zName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v); - sqlite3VdbeResolveLabel(v, addrCkOk); - } - sqlite3ExprListDelete(db, pCheck); - } - if( !isQuick ){ /* Omit the remaining tests for quick_check */ - /* Validate index entries for the current row */ - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int jmp2, jmp3, jmp4, jmp5, label6; - int kk; - int ckUniq = sqlite3VdbeMakeLabel(pParse); - if( pPk==pIdx ) continue; - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, - pPrior, r1); - pPrior = pIdx; - sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */ - /* Verify that an index entry exists for the current table row */ - jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, - pIdx->nColumn); VdbeCoverage(v); - sqlite3VdbeLoadString(v, 3, "row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " missing from index "); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp4 = integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, jmp2); - - /* The OP_IdxRowid opcode is an optimized version of OP_Column - ** that extracts the rowid off the end of the index record. - ** But it only works correctly if index record does not have - ** any extra bytes at the end. Verify that this is the case. */ - if( HasRowid(pTab) ){ - int jmp7; - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur+j, 3); - jmp7 = sqlite3VdbeAddOp3(v, OP_Eq, 3, 0, r1+pIdx->nColumn-1); - VdbeCoverageNeverNull(v); - sqlite3VdbeLoadString(v, 3, - "rowid not at end-of-record for row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " of index "); - sqlite3VdbeGoto(v, jmp5-1); - sqlite3VdbeJumpHere(v, jmp7); - } - - /* Any indexed columns with non-BINARY collations must still hold - ** the exact same text value as the table. */ - label6 = 0; - for(kk=0; kknKeyCol; kk++){ - if( pIdx->azColl[kk]==sqlite3StrBINARY ) continue; - if( label6==0 ) label6 = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur+j, kk, 3); - sqlite3VdbeAddOp3(v, OP_Ne, 3, label6, r1+kk); VdbeCoverage(v); - } - if( label6 ){ - int jmp6 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeResolveLabel(v, label6); - sqlite3VdbeLoadString(v, 3, "row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " values differ from index "); - sqlite3VdbeGoto(v, jmp5-1); - sqlite3VdbeJumpHere(v, jmp6); - } - - /* For UNIQUE indexes, verify that only one entry exists with the - ** current key. The entry is unique if (1) any column is NULL - ** or (2) the next entry has a different key */ - if( IsUniqueIndex(pIdx) ){ - int uniqOk = sqlite3VdbeMakeLabel(pParse); - int jmp6; - for(kk=0; kknKeyCol; kk++){ - int iCol = pIdx->aiColumn[kk]; - assert( iCol!=XN_ROWID && iColnCol ); - if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; - sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); - VdbeCoverage(v); - } - jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); - sqlite3VdbeGoto(v, uniqOk); - sqlite3VdbeJumpHere(v, jmp6); - sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, - pIdx->nKeyCol); VdbeCoverage(v); - sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); - sqlite3VdbeGoto(v, jmp5); - sqlite3VdbeResolveLabel(v, uniqOk); - } - sqlite3VdbeJumpHere(v, jmp4); - sqlite3ResolvePartIdxLabel(pParse, jmp3); - } - } - sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, loopTop-1); - if( pPk ){ - assert( !isQuick ); - sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); - } - } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Second pass to invoke the xIntegrity method on all virtual - ** tables. - */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - sqlite3_vtab *pVTab; - int a1; - if( pObjTab && pObjTab!=pTab ) continue; - if( IsOrdinaryTable(pTab) ) continue; - if( !IsVirtual(pTab) ) continue; - if( pTab->nCol<=0 ){ - const char *zMod = pTab->u.vtab.azArg[0]; - if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; - } - sqlite3ViewGetColumnNames(pParse, pTab); - if( pTab->u.vtab.p==0 ) continue; - pVTab = pTab->u.vtab.p->pVtab; - if( NEVER(pVTab==0) ) continue; - if( NEVER(pVTab->pModule==0) ) continue; - if( pVTab->pModule->iVersion<4 ) continue; - if( pVTab->pModule->xIntegrity==0 ) continue; - sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick); - pTab->nTabRef++; - sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF); - a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, a1); - continue; - } -#endif - } - { - static const int iLn = VDBE_OFFSET_LINENO(2); - static const VdbeOpList endCode[] = { - { OP_AddImm, 1, 0, 0}, /* 0 */ - { OP_IfNotZero, 1, 4, 0}, /* 1 */ - { OP_String8, 0, 3, 0}, /* 2 */ - { OP_ResultRow, 3, 1, 0}, /* 3 */ - { OP_Halt, 0, 0, 0}, /* 4 */ - { OP_String8, 0, 3, 0}, /* 5 */ - { OP_Goto, 0, 3, 0}, /* 6 */ - }; - VdbeOp *aOp; - - aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); - if( aOp ){ - aOp[0].p2 = 1-mxErr; - aOp[2].p4type = P4_STATIC; - aOp[2].p4.z = "ok"; - aOp[5].p4type = P4_STATIC; - aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT); - } - sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2); - } - } - break; -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_UTF16 - /* - ** PRAGMA encoding - ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" - ** - ** In its first form, this pragma returns the encoding of the main - ** database. If the database is not initialized, it is initialized now. - ** - ** The second form of this pragma is a no-op if the main database file - ** has not already been initialized. In this case it sets the default - ** encoding that will be used for the main database file if a new file - ** is created. If an existing main database file is opened, then the - ** default text encoding for the existing database is used. - ** - ** In all cases new databases created using the ATTACH command are - ** created to use the same default text encoding as the main database. If - ** the main database has not been initialized and/or created when ATTACH - ** is executed, this is done before the ATTACH operation. - ** - ** In the second form this pragma sets the text encoding to be used in - ** new database files created using this database handle. It is only - ** useful if invoked immediately after the main database i - */ - case PragTyp_ENCODING: { - static const struct EncName { - char *zName; - u8 enc; - } encnames[] = { - { "UTF8", SQLITE_UTF8 }, - { "UTF-8", SQLITE_UTF8 }, /* Must be element [1] */ - { "UTF-16le", SQLITE_UTF16LE }, /* Must be element [2] */ - { "UTF-16be", SQLITE_UTF16BE }, /* Must be element [3] */ - { "UTF16le", SQLITE_UTF16LE }, - { "UTF16be", SQLITE_UTF16BE }, - { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ - { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ - { 0, 0 } - }; - const struct EncName *pEnc; - if( !zRight ){ /* "PRAGMA encoding" */ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); - assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); - assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); - returnSingleText(v, encnames[ENC(pParse->db)].zName); - }else{ /* "PRAGMA encoding = XXX" */ - /* Only change the value of sqlite.enc if the database handle is not - ** initialized. If the main database exists, the new sqlite.enc value - ** will be overwritten when the schema is next loaded. If it does not - ** already exists, it will be created to use the new encoding value. - */ - if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){ - for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ - if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; - SCHEMA_ENC(db) = enc; - sqlite3SetTextEncoding(db, enc); - break; - } - } - if( !pEnc->zName ){ - sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); - } - } - } - } - break; -#endif /* SQLITE_OMIT_UTF16 */ - -#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - /* - ** PRAGMA [schema.]schema_version - ** PRAGMA [schema.]schema_version = - ** - ** PRAGMA [schema.]user_version - ** PRAGMA [schema.]user_version = - ** - ** PRAGMA [schema.]freelist_count - ** - ** PRAGMA [schema.]data_version - ** - ** PRAGMA [schema.]application_id - ** PRAGMA [schema.]application_id = - ** - ** The pragma's schema_version and user_version are used to set or get - ** the value of the schema-version and user-version, respectively. Both - ** the schema-version and the user-version are 32-bit signed integers - ** stored in the database header. - ** - ** The schema-cookie is usually only manipulated internally by SQLite. It - ** is incremented by SQLite whenever the database schema is modified (by - ** creating or dropping a table or index). The schema version is used by - ** SQLite each time a query is executed to ensure that the internal cache - ** of the schema used when compiling the SQL query matches the schema of - ** the database against which the compiled query is actually executed. - ** Subverting this mechanism by using "PRAGMA schema_version" to modify - ** the schema-version is potentially dangerous and may lead to program - ** crashes or database corruption. Use with caution! - ** - ** The user-version is not used internally by SQLite. It may be used by - ** applications for any purpose. - */ - case PragTyp_HEADER_VALUE: { - int iCookie = pPragma->iArg; /* Which cookie to read or write */ - sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){ - /* Write the specified cookie value */ - static const VdbeOpList setCookie[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_SetCookie, 0, 0, 0}, /* 1 */ - }; - VdbeOp *aOp; - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); - if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[1].p2 = iCookie; - aOp[1].p3 = sqlite3Atoi(zRight); - aOp[1].p5 = 1; - if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){ - /* Do not allow the use of PRAGMA schema_version=VALUE in defensive - ** mode. Change the OP_SetCookie opcode into a no-op. */ - aOp[1].opcode = OP_Noop; - } - }else{ - /* Read the specified cookie value */ - static const VdbeOpList readCookie[] = { - { OP_Transaction, 0, 0, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, 0}, /* 1 */ - { OP_ResultRow, 1, 1, 0} - }; - VdbeOp *aOp; - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(readCookie)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0); - if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[1].p3 = iCookie; - sqlite3VdbeReusable(v); - } - } - break; -#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - /* - ** PRAGMA compile_options - ** - ** Return the names of all compile-time options used in this build, - ** one option per row. - */ - case PragTyp_COMPILE_OPTIONS: { - int i = 0; - const char *zOpt; - pParse->nMem = 1; - while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ - sqlite3VdbeLoadString(v, 1, zOpt); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - sqlite3VdbeReusable(v); - } - break; -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -#ifndef SQLITE_OMIT_WAL - /* - ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate - ** - ** Checkpoint the database. - */ - case PragTyp_WAL_CHECKPOINT: { - int iBt = (pId2->z?iDb:SQLITE_MAX_DB); - int eMode = SQLITE_CHECKPOINT_PASSIVE; - if( zRight ){ - if( sqlite3StrICmp(zRight, "full")==0 ){ - eMode = SQLITE_CHECKPOINT_FULL; - }else if( sqlite3StrICmp(zRight, "restart")==0 ){ - eMode = SQLITE_CHECKPOINT_RESTART; - }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ - eMode = SQLITE_CHECKPOINT_TRUNCATE; - } - } - pParse->nMem = 3; - sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); - } - break; - - /* - ** PRAGMA wal_autocheckpoint - ** PRAGMA wal_autocheckpoint = N - ** - ** Configure a database connection to automatically checkpoint a database - ** after accumulating N frames in the log. Or query for the current value - ** of N. - */ - case PragTyp_WAL_AUTOCHECKPOINT: { - if( zRight ){ - sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); - } - returnSingleInt(v, - db->xWalCallback==sqlite3WalDefaultHook ? - SQLITE_PTR_TO_INT(db->pWalArg) : 0); - } - break; -#endif - - /* - ** PRAGMA shrink_memory - ** - ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database - ** connection on which it is invoked to free up as much memory as it - ** can, by calling sqlite3_db_release_memory(). - */ - case PragTyp_SHRINK_MEMORY: { - sqlite3_db_release_memory(db); - break; - } - - /* - ** PRAGMA optimize - ** PRAGMA optimize(MASK) - ** PRAGMA schema.optimize - ** PRAGMA schema.optimize(MASK) - ** - ** Attempt to optimize the database. All schemas are optimized in the first - ** two forms, and only the specified schema is optimized in the latter two. - ** - ** The details of optimizations performed by this pragma are expected - ** to change and improve over time. Applications should anticipate that - ** this pragma will perform new optimizations in future releases. - ** - ** The optional argument is a bitmask of optimizations to perform: - ** - ** 0x00001 Debugging mode. Do not actually perform any optimizations - ** but instead return one line of text for each optimization - ** that would have been done. Off by default. - ** - ** 0x00002 Run ANALYZE on tables that might benefit. On by default. - ** See below for additional information. - ** - ** 0x00010 Run all ANALYZE operations using an analysis_limit that - ** is the lessor of the current analysis_limit and the - ** SQLITE_DEFAULT_OPTIMIZE_LIMIT compile-time option. - ** The default value of SQLITE_DEFAULT_OPTIMIZE_LIMIT is - ** currently (2024-02-19) set to 2000, which is such that - ** the worst case run-time for PRAGMA optimize on a 100MB - ** database will usually be less than 100 milliseconds on - ** a RaspberryPI-4 class machine. On by default. - ** - ** 0x10000 Look at tables to see if they need to be reanalyzed - ** due to growth or shrinkage even if they have not been - ** queried during the current connection. Off by default. - ** - ** The default MASK is and always shall be 0x0fffe. In the current - ** implementation, the default mask only covers the 0x00002 optimization, - ** though additional optimizations that are covered by 0x0fffe might be - ** added in the future. Optimizations that are off by default and must - ** be explicitly requested have masks of 0x10000 or greater. - ** - ** DETERMINATION OF WHEN TO RUN ANALYZE - ** - ** In the current implementation, a table is analyzed if only if all of - ** the following are true: - ** - ** (1) MASK bit 0x00002 is set. - ** - ** (2) The table is an ordinary table, not a virtual table or view. - ** - ** (3) The table name does not begin with "sqlite_". - ** - ** (4) One or more of the following is true: - ** (4a) The 0x10000 MASK bit is set. - ** (4b) One or more indexes on the table lacks an entry - ** in the sqlite_stat1 table. - ** (4c) The query planner used sqlite_stat1-style statistics for one - ** or more indexes of the table at some point during the lifetime - ** of the current connection. - ** - ** (5) One or more of the following is true: - ** (5a) One or more indexes on the table lacks an entry - ** in the sqlite_stat1 table. (Same as 4a) - ** (5b) The number of rows in the table has increased or decreased by - ** 10-fold. In other words, the current size of the table is - ** 10 times larger than the size in sqlite_stat1 or else the - ** current size is less than 1/10th the size in sqlite_stat1. - ** - ** The rules for when tables are analyzed are likely to change in - ** future releases. Future versions of SQLite might accept a string - ** literal argument to this pragma that contains a mnemonic description - ** of the options rather than a bitmap. - */ - case PragTyp_OPTIMIZE: { - int iDbLast; /* Loop termination point for the schema loop */ - int iTabCur; /* Cursor for a table whose size needs checking */ - HashElem *k; /* Loop over tables of a schema */ - Schema *pSchema; /* The current schema */ - Table *pTab; /* A table in the schema */ - Index *pIdx; /* An index of the table */ - LogEst szThreshold; /* Size threshold above which reanalysis needed */ - char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ - u32 opMask; /* Mask of operations to perform */ - int nLimit; /* Analysis limit to use */ - int nCheck = 0; /* Number of tables to be optimized */ - int nBtree = 0; /* Number of btrees to scan */ - int nIndex; /* Number of indexes on the current table */ - - if( zRight ){ - opMask = (u32)sqlite3Atoi(zRight); - if( (opMask & 0x02)==0 ) break; - }else{ - opMask = 0xfffe; - } - if( (opMask & 0x10)==0 ){ - nLimit = 0; - }else if( db->nAnalysisLimit>0 - && db->nAnalysisLimitnTab++; - for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){ - if( iDb==1 ) continue; - sqlite3CodeVerifySchema(pParse, iDb); - pSchema = db->aDb[iDb].pSchema; - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - pTab = (Table*)sqliteHashData(k); - - /* This only works for ordinary tables */ - if( !IsOrdinaryTable(pTab) ) continue; - - /* Do not scan system tables */ - if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue; - - /* Find the size of the table as last recorded in sqlite_stat1. - ** If any index is unanalyzed, then the threshold is -1 to - ** indicate a new, unanalyzed index - */ - szThreshold = pTab->nRowLogEst; - nIndex = 0; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - nIndex++; - if( !pIdx->hasStat1 ){ - szThreshold = -1; /* Always analyze if any index lacks statistics */ - } - } - - /* If table pTab has not been used in a way that would benefit from - ** having analysis statistics during the current session, then skip it, - ** unless the 0x10000 MASK bit is set. */ - if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){ - /* Check for size change if stat1 has been used for a query */ - }else if( opMask & 0x10000 ){ - /* Check for size change if 0x10000 is set */ - }else if( pTab->pIndex!=0 && szThreshold<0 ){ - /* Do analysis if unanalyzed indexes exists */ - }else{ - /* Otherwise, we can skip this table */ - continue; - } - - nCheck++; - if( nCheck==2 ){ - /* If ANALYZE might be invoked two or more times, hold a write - ** transaction for efficiency */ - sqlite3BeginWriteOperation(pParse, 0, iDb); - } - nBtree += nIndex+1; - - /* Reanalyze if the table is 10 times larger or smaller than - ** the last analysis. Unconditional reanalysis if there are - ** unanalyzed indexes. */ - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - if( szThreshold>=0 ){ - const LogEst iRange = 33; /* 10x size change */ - sqlite3VdbeAddOp4Int(v, OP_IfSizeBetween, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1), - szThreshold>=iRange ? szThreshold-iRange : -1, - szThreshold+iRange); - VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Rewind, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1)); - VdbeCoverage(v); - } - zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"", - db->aDb[iDb].zDbSName, pTab->zName); - if( opMask & 0x01 ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1); - }else{ - sqlite3VdbeAddOp4(v, OP_SqlExec, nLimit ? 0x02 : 00, nLimit, 0, - zSubSql, P4_DYNAMIC); - } - } - } - sqlite3VdbeAddOp0(v, OP_Expire); - - /* In a schema with a large number of tables and indexes, scale back - ** the analysis_limit to avoid excess run-time in the worst case. - */ - if( !db->mallocFailed && nLimit>0 && nBtree>100 ){ - int iAddr, iEnd; - VdbeOp *aOp; - nLimit = 100*nLimit/nBtree; - if( nLimit<100 ) nLimit = 100; - aOp = sqlite3VdbeGetOp(v, 0); - iEnd = sqlite3VdbeCurrentAddr(v); - for(iAddr=0; iAddrePragTyp==PragTyp_BUSY_TIMEOUT ); - if( zRight ){ - sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); - } - returnSingleInt(v, db->busyTimeout); - break; - } - - /* - ** PRAGMA soft_heap_limit - ** PRAGMA soft_heap_limit = N - ** - ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the - ** sqlite3_soft_heap_limit64() interface with the argument N, if N is - ** specified and is a non-negative integer. - ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always - ** returns the same integer that would be returned by the - ** sqlite3_soft_heap_limit64(-1) C-language function. - */ - case PragTyp_SOFT_HEAP_LIMIT: { - sqlite3_int64 N; - if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ - sqlite3_soft_heap_limit64(N); - } - returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); - break; - } - - /* - ** PRAGMA hard_heap_limit - ** PRAGMA hard_heap_limit = N - ** - ** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap - ** limit. The hard heap limit can be activated or lowered by this - ** pragma, but not raised or deactivated. Only the - ** sqlite3_hard_heap_limit64() C-language API can raise or deactivate - ** the hard heap limit. This allows an application to set a heap limit - ** constraint that cannot be relaxed by an untrusted SQL script. - */ - case PragTyp_HARD_HEAP_LIMIT: { - sqlite3_int64 N; - if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ - sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1); - if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N); - } - returnSingleInt(v, sqlite3_hard_heap_limit64(-1)); - break; - } - - /* - ** PRAGMA threads - ** PRAGMA threads = N - ** - ** Configure the maximum number of worker threads. Return the new - ** maximum, which might be less than requested. - */ - case PragTyp_THREADS: { - sqlite3_int64 N; - if( zRight - && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK - && N>=0 - ){ - sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); - } - returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); - break; - } - - /* - ** PRAGMA analysis_limit - ** PRAGMA analysis_limit = N - ** - ** Configure the maximum number of rows that ANALYZE will examine - ** in each index that it looks at. Return the new limit. - */ - case PragTyp_ANALYSIS_LIMIT: { - sqlite3_int64 N; - if( zRight - && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */ - && N>=0 - ){ - db->nAnalysisLimit = (int)(N&0x7fffffff); - } - returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */ - break; - } - -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* - ** Report the current state of file logs for all databases - */ - case PragTyp_LOCK_STATUS: { - static const char *const azLockName[] = { - "unlocked", "shared", "reserved", "pending", "exclusive" - }; - int i; - pParse->nMem = 2; - for(i=0; inDb; i++){ - Btree *pBt; - const char *zState = "unknown"; - int j; - if( db->aDb[i].zDbSName==0 ) continue; - pBt = db->aDb[i].pBt; - if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ - zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, - SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ - zState = azLockName[j]; - } - sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); - } - break; - } -#endif - -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - /* Pragma iArg - ** ---------- ------ - ** key 0 - ** rekey 1 - ** hexkey 2 - ** hexrekey 3 - ** textkey 4 - ** textrekey 5 - */ - case PragTyp_KEY: { - if( zRight ){ - char zBuf[40]; - const char *zKey = zRight; - int n; - if( pPragma->iArg==2 || pPragma->iArg==3 ){ - u8 iByte; - int i; - for(i=0, iByte=0; iiArg<4 ? sqlite3Strlen30(zRight) : -1; - } - if( (pPragma->iArg & 1)==0 ){ - rc = sqlite3_key_v2(db, zDb, zKey, n); - }else{ - rc = sqlite3_rekey_v2(db, zDb, zKey, n); - } - if( rc==SQLITE_OK && n!=0 ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "ok", SQLITE_STATIC); - returnSingleText(v, "ok"); - } else { - sqlite3ErrorMsg(pParse, "An error occurred with PRAGMA key or rekey. " - "PRAGMA key requires a key of one or more characters. " - "PRAGMA rekey can only be run on an existing encrypted database. " - "Use sqlcipher_export() and ATTACH to convert encrypted/plaintext databases."); - goto pragma_out; - } - } - break; - } -#endif -/* END SQLCIPHER */ -#if defined(SQLITE_ENABLE_CEROD) - case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){ - if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ - sqlite3_activate_cerod(&zRight[6]); - } - } - break; -#endif - - } /* End of the PRAGMA switch */ - - /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only - ** purpose is to execute assert() statements to verify that if the - ** PragFlg_NoColumns1 flag is set and the caller specified an argument - ** to the PRAGMA, the implementation has not added any OP_ResultRow - ** instructions to the VM. */ - if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){ - sqlite3VdbeVerifyNoResultRow(v); - } - -pragma_out: - sqlite3DbFree(db, zLeft); - sqlite3DbFree(db, zRight); -} -#ifndef SQLITE_OMIT_VIRTUALTABLE -/***************************************************************************** -** Implementation of an eponymous virtual table that runs a pragma. -** -*/ -typedef struct PragmaVtab PragmaVtab; -typedef struct PragmaVtabCursor PragmaVtabCursor; -struct PragmaVtab { - sqlite3_vtab base; /* Base class. Must be first */ - sqlite3 *db; /* The database connection to which it belongs */ - const PragmaName *pName; /* Name of the pragma */ - u8 nHidden; /* Number of hidden columns */ - u8 iHidden; /* Index of the first hidden column */ -}; -struct PragmaVtabCursor { - sqlite3_vtab_cursor base; /* Base class. Must be first */ - sqlite3_stmt *pPragma; /* The pragma statement to run */ - sqlite_int64 iRowid; /* Current rowid */ - char *azArg[2]; /* Value of the argument and schema */ -}; - -/* -** Pragma virtual table module xConnect method. -*/ -static int pragmaVtabConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - const PragmaName *pPragma = (const PragmaName*)pAux; - PragmaVtab *pTab = 0; - int rc; - int i, j; - char cSep = '('; - StrAccum acc; - char zBuf[200]; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3_str_appendall(&acc, "CREATE TABLE x"); - for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){ - sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); - cSep = ','; - } - if( i==0 ){ - sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); - i++; - } - j = 0; - if( pPragma->mPragFlg & PragFlg_Result1 ){ - sqlite3_str_appendall(&acc, ",arg HIDDEN"); - j++; - } - if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ - sqlite3_str_appendall(&acc, ",schema HIDDEN"); - j++; - } - sqlite3_str_append(&acc, ")", 1); - sqlite3StrAccumFinish(&acc); - assert( strlen(zBuf) < sizeof(zBuf)-1 ); - rc = sqlite3_declare_vtab(db, zBuf); - if( rc==SQLITE_OK ){ - pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pTab, 0, sizeof(PragmaVtab)); - pTab->pName = pPragma; - pTab->db = db; - pTab->iHidden = i; - pTab->nHidden = j; - } - }else{ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - - *ppVtab = (sqlite3_vtab*)pTab; - return rc; -} - -/* -** Pragma virtual table module xDisconnect method. -*/ -static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){ - PragmaVtab *pTab = (PragmaVtab*)pVtab; - sqlite3_free(pTab); - return SQLITE_OK; -} - -/* Figure out the best index to use to search a pragma virtual table. -** -** There are not really any index choices. But we want to encourage the -** query planner to give == constraints on as many hidden parameters as -** possible, and especially on the first hidden parameter. So return a -** high cost if hidden parameters are unconstrained. -*/ -static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - PragmaVtab *pTab = (PragmaVtab*)tab; - const struct sqlite3_index_constraint *pConstraint; - int i, j; - int seen[2]; - - pIdxInfo->estimatedCost = (double)1; - if( pTab->nHidden==0 ){ return SQLITE_OK; } - pConstraint = pIdxInfo->aConstraint; - seen[0] = 0; - seen[1] = 0; - for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->iColumn < pTab->iHidden ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT; - j = pConstraint->iColumn - pTab->iHidden; - assert( j < 2 ); - seen[j] = i+1; - } - if( seen[0]==0 ){ - pIdxInfo->estimatedCost = (double)2147483647; - pIdxInfo->estimatedRows = 2147483647; - return SQLITE_OK; - } - j = seen[0]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 1; - pIdxInfo->aConstraintUsage[j].omit = 1; - pIdxInfo->estimatedCost = (double)20; - pIdxInfo->estimatedRows = 20; - if( seen[1] ){ - j = seen[1]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 2; - pIdxInfo->aConstraintUsage[j].omit = 1; - } - return SQLITE_OK; -} - -/* Create a new cursor for the pragma virtual table */ -static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ - PragmaVtabCursor *pCsr; - pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr)); - if( pCsr==0 ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(PragmaVtabCursor)); - pCsr->base.pVtab = pVtab; - *ppCursor = &pCsr->base; - return SQLITE_OK; -} - -/* Clear all content from pragma virtual table cursor. */ -static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ - int i; - sqlite3_finalize(pCsr->pPragma); - pCsr->pPragma = 0; - pCsr->iRowid = 0; - for(i=0; iazArg); i++){ - sqlite3_free(pCsr->azArg[i]); - pCsr->azArg[i] = 0; - } -} - -/* Close a pragma virtual table cursor */ -static int pragmaVtabClose(sqlite3_vtab_cursor *cur){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur; - pragmaVtabCursorClear(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* Advance the pragma virtual table cursor to the next row */ -static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - int rc = SQLITE_OK; - - /* Increment the xRowid value */ - pCsr->iRowid++; - assert( pCsr->pPragma ); - if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){ - rc = sqlite3_finalize(pCsr->pPragma); - pCsr->pPragma = 0; - pragmaVtabCursorClear(pCsr); - } - return rc; -} - -/* -** Pragma virtual table module xFilter method. -*/ -static int pragmaVtabFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); - int rc; - int i, j; - StrAccum acc; - char *zSql; - - UNUSED_PARAMETER(idxNum); - UNUSED_PARAMETER(idxStr); - pragmaVtabCursorClear(pCsr); - j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1; - for(i=0; iazArg) ); - assert( pCsr->azArg[j]==0 ); - if( zText ){ - pCsr->azArg[j] = sqlite3_mprintf("%s", zText); - if( pCsr->azArg[j]==0 ){ - return SQLITE_NOMEM; - } - } - } - sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); - sqlite3_str_appendall(&acc, "PRAGMA "); - if( pCsr->azArg[1] ){ - sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]); - } - sqlite3_str_appendall(&acc, pTab->pName->zName); - if( pCsr->azArg[0] ){ - sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]); - } - zSql = sqlite3StrAccumFinish(&acc); - if( zSql==0 ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0); - sqlite3_free(zSql); - if( rc!=SQLITE_OK ){ - pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); - return rc; - } - return pragmaVtabNext(pVtabCursor); -} - -/* -** Pragma virtual table module xEof method. -*/ -static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - return (pCsr->pPragma==0); -} - -/* The xColumn method simply returns the corresponding column from -** the PRAGMA. -*/ -static int pragmaVtabColumn( - sqlite3_vtab_cursor *pVtabCursor, - sqlite3_context *ctx, - int i -){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); - if( iiHidden ){ - sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i)); - }else{ - sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT); - } - return SQLITE_OK; -} - -/* -** Pragma virtual table module xRowid method. -*/ -static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - *p = pCsr->iRowid; - return SQLITE_OK; -} - -/* The pragma virtual table object */ -static const sqlite3_module pragmaVtabModule = { - 0, /* iVersion */ - 0, /* xCreate - create a table */ - pragmaVtabConnect, /* xConnect - connect to an existing table */ - pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */ - pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */ - 0, /* xDestroy - Drop a table */ - pragmaVtabOpen, /* xOpen - open a cursor */ - pragmaVtabClose, /* xClose - close a cursor */ - pragmaVtabFilter, /* xFilter - configure scan constraints */ - pragmaVtabNext, /* xNext - advance a cursor */ - pragmaVtabEof, /* xEof */ - pragmaVtabColumn, /* xColumn - read data */ - pragmaVtabRowid, /* xRowid - read data */ - 0, /* xUpdate - write data */ - 0, /* xBegin - begin transaction */ - 0, /* xSync - sync transaction */ - 0, /* xCommit - commit transaction */ - 0, /* xRollback - rollback transaction */ - 0, /* xFindFunction - function overloading */ - 0, /* xRename - rename the table */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ -}; - -/* -** Check to see if zTabName is really the name of a pragma. If it is, -** then register an eponymous virtual table for that pragma and return -** a pointer to the Module object for the new virtual table. -*/ -SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){ - const PragmaName *pName; - assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 ); - pName = pragmaLocate(zName+7); - if( pName==0 ) return 0; - if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0; - assert( sqlite3HashFind(&db->aModule, zName)==0 ); - return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0); -} - -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#endif /* SQLITE_OMIT_PRAGMA */ - -/************** End of pragma.c **********************************************/ -/************** Begin file prepare.c *****************************************/ -/* -** 2005 May 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the implementation of the sqlite3_prepare() -** interface, and routines that contribute to loading the database schema -** from disk. -*/ -/* #include "sqliteInt.h" */ - -/* -** Fill the InitData structure with an error message that indicates -** that the database is corrupt. -*/ -static void corruptSchema( - InitData *pData, /* Initialization context */ - char **azObj, /* Type and name of object being parsed */ - const char *zExtra /* Error information */ -){ - sqlite3 *db = pData->db; - if( db->mallocFailed ){ - 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_AlterMask) ){ - static const char *azAlterType[] = { - "rename", - "drop column", - "add column" - }; - *pData->pzErrMsg = 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; - const char *zObj = azObj[1] ? azObj[1] : "?"; - z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); - if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); - *pData->pzErrMsg = z; - pData->rc = SQLITE_CORRUPT_BKPT; - } -} - -/* -** Check to see if any sibling index (another index on the same table) -** of pIndex has the same root page number, and if it does, return true. -** This would indicate a corrupt schema. -*/ -SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index *pIndex){ - Index *p; - for(p=pIndex->pTable->pIndex; p; p=p->pNext){ - if( p->tnum==pIndex->tnum && p!=pIndex ) return 1; - } - return 0; -} - -/* forward declaration */ -static int sqlite3Prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - Vdbe *pReprepare, /* VM being reprepared */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -); - - -/* -** This is the callback routine for the code that initializes the -** database. See sqlite3Init() below for additional information. -** This routine is also called from the OP_ParseSchema opcode of the VDBE. -** -** Each callback contains the following information: -** -** argv[0] = type of object: "table", "index", "trigger", or "view". -** argv[1] = name of thing being created -** argv[2] = associated table if an index or trigger -** argv[3] = root page number for table or index. 0 for trigger or view. -** argv[4] = SQL text for the CREATE statement. -** -*/ -SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ - InitData *pData = (InitData*)pInit; - sqlite3 *db = pData->db; - int iDb = pData->iDb; - - assert( argc==5 ); - UNUSED_PARAMETER2(NotUsed, argc); - assert( 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, 0); - return 1; - } - - assert( iDb>=0 && iDbnDb ); - if( argv[3]==0 ){ - corruptSchema(pData, argv, 0); - }else if( argv[4] - && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]] - && 'r'==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; - sqlite3_stmt *pStmt; - TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ - - assert( db->init.busy ); - db->init.iDb = iDb; - if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0 - || (db->init.newTnum>pData->mxPage && pData->mxPage>0) - ){ - if( sqlite3Config.bExtraSchemaChecks ){ - corruptSchema(pData, argv, "invalid rootpage"); - } - } - db->init.orphanTrigger = 0; - db->init.azInit = (const char**)argv; - pStmt = 0; - TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0); - rc = db->errCode; - assert( (rc&0xFF)==(rcp&0xFF) ); - db->init.iDb = saved_iDb; - /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ - if( SQLITE_OK!=rc ){ - if( db->init.orphanTrigger ){ - assert( iDb==1 ); - }else{ - if( rc > pData->rc ) pData->rc = rc; - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(db); - }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ - corruptSchema(pData, argv, sqlite3_errmsg(db)); - } - } - } - db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */ - sqlite3_finalize(pStmt); - }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=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 - ** constraint for a CREATE TABLE. The index should have already - ** been created when we processed the CREATE TABLE. All we have - ** to do here is record the root page number for that index. - */ - Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName); - if( pIndex==0 ){ - corruptSchema(pData, argv, "orphan index"); - }else - if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0 - || pIndex->tnum<2 - || pIndex->tnum>pData->mxPage - || sqlite3IndexHasDuplicateRootPage(pIndex) - ){ - if( sqlite3Config.bExtraSchemaChecks ){ - corruptSchema(pData, argv, "invalid rootpage"); - } - } - } - return 0; -} - -/* -** Attempt to read the database schema and initialize internal -** data structures for a single database file. The index of the -** database file is given by iDb. iDb==0 is used for the main -** database. iDb==1 should never be used. iDb>=2 is used for -** auxiliary databases. Return one of the SQLITE_ error codes to -** indicate success or failure. -*/ -SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ - int rc; - int i; -#ifndef SQLITE_OMIT_DEPRECATED - int size; -#endif - Db *pDb; - char const *azArg[6]; - int meta[5]; - InitData initData; - const char *zSchemaTabName; - int openedTransaction = 0; - int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed); - - assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pSchema ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); - - db->init.busy = 1; - - /* Construct the in-memory representation schema tables (sqlite_schema or - ** sqlite_temp_schema) by invoking the parser directly. The appropriate - ** table name will be inserted automatically by the parser so we can just - ** use the abbreviation "x" here. The parser will also automatically tag - ** the schema table as read-only. */ - azArg[0] = "table"; - azArg[1] = zSchemaTabName = SCHEMA_TABLE(iDb); - azArg[2] = azArg[1]; - azArg[3] = "1"; - azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text," - "rootpage int,sql text)"; - azArg[5] = 0; - initData.db = db; - initData.iDb = iDb; - initData.rc = SQLITE_OK; - initData.pzErrMsg = pzErrMsg; - initData.mInitFlags = mFlags; - initData.nInitRow = 0; - initData.mxPage = 0; - sqlite3InitCallback(&initData, 5, (char **)azArg, 0); - db->mDbFlags &= mask; - if( initData.rc ){ - rc = initData.rc; - goto error_out; - } - - /* Create a cursor to hold the database open - */ - pDb = &db->aDb[iDb]; - if( pDb->pBt==0 ){ - assert( iDb==1 ); - DbSetProperty(db, 1, DB_SchemaLoaded); - rc = SQLITE_OK; - goto error_out; - } - - /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it - ** will be closed before this function returns. */ - sqlite3BtreeEnter(pDb->pBt); - if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){ - rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0); - if( rc!=SQLITE_OK ){ - sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); - goto initone_error_out; - } - openedTransaction = 1; - } - - /* Get the database meta information. - ** - ** Meta values are as follows: - ** meta[0] Schema cookie. Changes with each schema change. - ** meta[1] File format of schema layer. - ** meta[2] Size of the page cache. - ** meta[3] Largest rootpage (auto/incr_vacuum mode) - ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE - ** meta[5] User version - ** meta[6] Incremental vacuum mode - ** meta[7] unused - ** meta[8] unused - ** meta[9] unused - ** - ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to - ** the possible values of meta[4]. - */ - for(i=0; ipBt, i+1, (u32 *)&meta[i]); - } - if( (db->flags & SQLITE_ResetDatabase)!=0 ){ - memset(meta, 0, sizeof(meta)); - } - pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; - - /* If opening a non-empty database, check the text encoding. For the - ** main database, set sqlite3.enc to the encoding of the main database. - ** For an attached db, it is an error if the encoding is not the same - ** as sqlite3.enc. - */ - if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ - if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){ - u8 encoding; -#ifndef SQLITE_OMIT_UTF16 - /* If opening the main database, set ENC(db). */ - encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; - if( encoding==0 ) encoding = SQLITE_UTF8; -#else - encoding = SQLITE_UTF8; -#endif - sqlite3SetTextEncoding(db, encoding); - }else{ - /* If opening an attached database, the encoding much match ENC(db) */ - if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){ - sqlite3SetString(pzErrMsg, db, "attached databases must use the same" - " text encoding as main database"); - rc = SQLITE_ERROR; - goto initone_error_out; - } - } - } - pDb->pSchema->enc = ENC(db); - - if( pDb->pSchema->cache_size==0 ){ -#ifndef SQLITE_OMIT_DEPRECATED - size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]); - if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } - pDb->pSchema->cache_size = size; -#else - pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE; -#endif - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - - /* - ** file_format==1 Version 3.0.0. - ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN - ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults - ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants - */ - pDb->pSchema->file_format = (u8)meta[BTREE_FILE_FORMAT-1]; - if( pDb->pSchema->file_format==0 ){ - pDb->pSchema->file_format = 1; - } - if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ - sqlite3SetString(pzErrMsg, db, "unsupported file format"); - rc = SQLITE_ERROR; - goto initone_error_out; - } - - /* Ticket #2804: When we open a database in the newer file format, - ** clear the legacy_file_format pragma flag so that a VACUUM will - ** not downgrade the database and thus invalidate any descending - ** indices that the user might have created. - */ - if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){ - db->flags &= ~(u64)SQLITE_LegacyFileFmt; - } - - /* Read the schema information out of the schema tables - */ - assert( db->init.busy ); - initData.mxPage = sqlite3BtreeLastPage(pDb->pBt); - { - char *zSql; - zSql = sqlite3MPrintf(db, - "SELECT*FROM\"%w\".%s ORDER BY rowid", - db->aDb[iDb].zDbSName, zSchemaTabName); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - sqlite3_xauth xAuth; - xAuth = db->xAuth; - db->xAuth = 0; -#endif - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; - } -#endif - if( rc==SQLITE_OK ) rc = initData.rc; - sqlite3DbFree(db, zSql); -#ifndef SQLITE_OMIT_ANALYZE - if( rc==SQLITE_OK ){ - sqlite3AnalysisLoad(db, iDb); - } -#endif - } - assert( pDb == &(db->aDb[iDb]) ); - if( db->mallocFailed ){ - rc = SQLITE_NOMEM_BKPT; - sqlite3ResetAllSchemasOfConnection(db); - 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 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; - } - - /* Jump here for an error that occurs after successfully allocating - ** curMain and calling sqlite3BtreeEnter(). For an error that occurs - ** before that point, jump to error_out. - */ -initone_error_out: - if( openedTransaction ){ - sqlite3BtreeCommit(pDb->pBt); - } - sqlite3BtreeLeave(pDb->pBt); - -error_out: - if( rc ){ - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - } - sqlite3ResetOneSchema(db, iDb); - } - db->init.busy = 0; - return rc; -} - -/* -** Initialize all database files - the main database file, the file -** used to store temporary tables, and any additional database files -** created using ATTACH statements. Return a success code. If an -** error occurs, write an error message into *pzErrMsg. -** -** After a database is initialized, the DB_SchemaLoaded bit is set -** bit is set in the flags field of the Db structure. -*/ -SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ - int i, rc; - int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange); - - assert( sqlite3_mutex_held(db->mutex) ); - assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); - assert( db->init.busy==0 ); - ENC(db) = SCHEMA_ENC(db); - assert( db->nDb>0 ); - /* Do the main schema first */ - if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, 0, pzErrMsg, 0); - if( rc ) return rc; - } - /* All other schemas after the main schema. The "temp" schema must be last */ - for(i=db->nDb-1; i>0; i--){ - assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); - if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, i, pzErrMsg, 0); - if( rc ) return rc; - } - } - if( commit_internal ){ - sqlite3CommitInternalChanges(db); - } - return SQLITE_OK; -} - -/* -** This routine is a no-op if the database schema is already initialized. -** Otherwise, the schema is loaded. An error code is returned. -*/ -SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){ - int rc = SQLITE_OK; - sqlite3 *db = pParse->db; - assert( sqlite3_mutex_held(db->mutex) ); - if( !db->init.busy ){ - rc = sqlite3Init(db, &pParse->zErrMsg); - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; - }else if( db->noSharedCache ){ - db->mDbFlags |= DBFLAG_SchemaKnownOk; - } - } - return rc; -} - - -/* -** Check schema cookies in all databases. If any cookie is out -** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies -** make no changes to pParse->rc. -*/ -static void schemaIsValid(Parse *pParse){ - sqlite3 *db = pParse->db; - int iDb; - int rc; - int cookie; - - assert( pParse->checkSchema ); - assert( sqlite3_mutex_held(db->mutex) ); - for(iDb=0; iDbnDb; iDb++){ - int openedTransaction = 0; /* True if a transaction is opened */ - Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */ - if( pBt==0 ) continue; - - /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it - ** will be closed immediately after reading the meta-value. */ - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - pParse->rc = SQLITE_NOMEM; - } - if( rc!=SQLITE_OK ) return; - openedTransaction = 1; - } - - /* Read the schema cookie from the database. If it does not match the - ** value stored as part of the in-memory schema representation, - ** set Parse.rc to SQLITE_SCHEMA. */ - sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - if( DbHasProperty(db, iDb, DB_SchemaLoaded) ) pParse->rc = SQLITE_SCHEMA; - sqlite3ResetOneSchema(db, iDb); - } - - /* Close the transaction, if one was opened. */ - if( openedTransaction ){ - sqlite3BtreeCommit(pBt); - } - } -} - -/* -** Convert a schema pointer into the iDb index that indicates -** which database file in db->aDb[] the schema refers to. -** -** If the same database is attached more than once, the first -** attached database is returned. -*/ -SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ - int i = -32768; - - /* If pSchema is NULL, then return -32768. This happens when code in - ** expr.c is trying to resolve a reference to a transient table (i.e. one - ** created by a sub-select). In this case the return value of this - ** function should never be used. - ** - ** We return -32768 instead of the more usual -1 simply because using - ** -32768 as the incorrect index into db->aDb[] is much - ** more likely to cause a segfault than -1 (of course there are assert() - ** statements too, but it never hurts to play the odds) and - ** -32768 will still fit into a 16-bit signed integer. - */ - assert( sqlite3_mutex_held(db->mutex) ); - if( pSchema ){ - for(i=0; 1; i++){ - assert( inDb ); - if( db->aDb[i].pSchema==pSchema ){ - break; - } - } - assert( i>=0 && inDb ); - } - return i; -} - -/* -** Free all memory allocations in the pParse object -*/ -SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ - sqlite3 *db = pParse->db; - assert( db!=0 ); - assert( db->pParse==pParse ); - assert( pParse->nested==0 ); -#ifndef SQLITE_OMIT_SHARED_CACHE - if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock); -#endif - while( pParse->pCleanup ){ - ParseCleanup *pCleanup = pParse->pCleanup; - pParse->pCleanup = pCleanup->pNext; - pCleanup->xCleanup(db, pCleanup->pPtr); - sqlite3DbNNFreeNN(db, pCleanup); - } - if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel); - if( pParse->pConstExpr ){ - 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; -} - -/* -** 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 mechanism (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 -** 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 = sqlite3ParserAddCleanup(pParse, destructor, pObj); -*/ -SQLITE_PRIVATE void *sqlite3ParserAddCleanup( - Parse *pParse, /* Destroy when this Parser finishes */ - void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ - void *pPtr /* Pointer to object to be cleaned up */ -){ - ParseCleanup *pCleanup; - if( sqlite3FaultSim(300) ){ - pCleanup = 0; - sqlite3OomFault(pParse->db); - }else{ - pCleanup = 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 sqlite3ParseObjectReset() to undo this operation. -** -** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which -** is generated by Lemon. -*/ -SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, 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 ) 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 sqlite3Prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - Vdbe *pReprepare, /* VM being reprepared */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc = SQLITE_OK; /* Result code */ - int i; /* Loop counter */ - Parse sParse; /* Parsing context */ - - /* 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; - if( pReprepare ){ - sParse.pReprepare = pReprepare; - sParse.explain = sqlite3_stmt_isexplain((sqlite3_stmt*)pReprepare); - }else{ - assert( sParse.pReprepare==0 ); - } - assert( ppStmt && *ppStmt==0 ); - if( db->mallocFailed ){ - sqlite3ErrorMsg(&sParse, "out of memory"); - db->errCode = rc = SQLITE_NOMEM; - goto end_prepare; - } - assert( sqlite3_mutex_held(db->mutex) ); - - /* For a long-term use prepared statement avoid the use of - ** lookaside memory. - */ - if( prepFlags & SQLITE_PREPARE_PERSISTENT ){ - sParse.disableLookaside++; - DisableLookaside; - } - sParse.prepFlags = prepFlags & 0xff; - - /* Check to verify that it is possible to get a read lock on all - ** database schemas. The inability to get a read lock indicates that - ** some other database connection is holding a write-lock, which in - ** turn means that the other connection has made uncommitted changes - ** to the schema. - ** - ** Were we to proceed and prepare the statement against the uncommitted - ** schema changes and if those schema changes are subsequently rolled - ** back and different changes are made in their place, then when this - ** prepared statement goes to run the schema cookie would fail to detect - ** the schema change. Disaster would follow. - ** - ** This thread is currently holding mutexes on all Btrees (because - ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it - ** is not possible for another thread to start a new schema change - ** while this routine is running. Hence, we do not need to hold - ** locks on the schema, we just need to make sure nobody else is - ** holding them. - ** - ** Note that setting READ_UNCOMMITTED overrides most lock detection, - ** but it does *not* override schema lock detection, so this all still - ** works even if READ_UNCOMMITTED is set. - */ - if( !db->noSharedCache ){ - for(i=0; inDb; i++) { - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - assert( sqlite3BtreeHoldsMutex(pBt) ); - rc = sqlite3BtreeSchemaLocked(pBt); - if( rc ){ - const char *zDb = db->aDb[i].zDbSName; - sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); - testcase( db->flags & SQLITE_ReadUncommit ); - goto end_prepare; - } - } - } - } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( db->pDisconnect ) sqlite3VtabUnlockList(db); -#endif - - if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ - char *zSqlCopy; - int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; - testcase( nBytes==mxLen ); - testcase( nBytes==mxLen+1 ); - if( nBytes>mxLen ){ - sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); - rc = sqlite3ApiExit(db, SQLITE_TOOBIG); - goto end_prepare; - } - zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); - if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy); - sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; - sqlite3DbFree(db, zSqlCopy); - }else{ - sParse.zTail = &zSql[nBytes]; - } - }else{ - sqlite3RunParser(&sParse, zSql); - } - assert( 0==sParse.nQueryLoop ); - - if( pzTail ){ - *pzTail = sParse.zTail; - } - - if( db->init.busy==0 ){ - sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags); - } - if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM_BKPT; - sParse.checkSchema = 0; - } - if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){ - if( sParse.checkSchema && db->init.busy==0 ){ - schemaIsValid(&sParse); - } - if( sParse.pVdbe ){ - sqlite3VdbeFinalize(sParse.pVdbe); - } - assert( 0==(*ppStmt) ); - rc = sParse.rc; - if( sParse.zErrMsg ){ - sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg); - sqlite3DbFree(db, sParse.zErrMsg); - }else{ - sqlite3Error(db, rc); - } - }else{ - assert( sParse.zErrMsg==0 ); - *ppStmt = (sqlite3_stmt*)sParse.pVdbe; - rc = SQLITE_OK; - sqlite3ErrorClear(db); - } - - - /* Delete any TriggerPrg structures allocated while parsing this statement. */ - while( sParse.pTriggerPrg ){ - TriggerPrg *pT = sParse.pTriggerPrg; - sParse.pTriggerPrg = pT->pNext; - sqlite3DbFree(db, pT); - } - -end_prepare: - - sqlite3ParseObjectReset(&sParse); - return rc; -} -static int sqlite3LockAndPrepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - Vdbe *pOld, /* VM being reprepared */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - int cnt = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif - *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - do{ - /* Make multiple attempts to compile the SQL, until it either succeeds - ** or encounters a permanent error. A schema problem after one schema - ** reset is considered a permanent error. */ - rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); - assert( rc==SQLITE_OK || *ppStmt==0 ); - if( rc==SQLITE_OK || db->mallocFailed ) break; - }while( (rc==SQLITE_ERROR_RETRY && (cnt++)errMask)==rc ); - db->busyHandler.nBusy = 0; - sqlite3_mutex_leave(db->mutex); - assert( rc==SQLITE_OK || (*ppStmt)==0 ); - return rc; -} - - -/* -** Rerun the compilation of a statement after a schema change. -** -** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, -** if the statement cannot be recompiled because another connection has -** locked the sqlite3_schema table, return SQLITE_LOCKED. If any other error -** occurs, return SQLITE_SCHEMA. -*/ -SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ - int rc; - sqlite3_stmt *pNew; - const char *zSql; - sqlite3 *db; - u8 prepFlags; - - assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) ); - zSql = sqlite3_sql((sqlite3_stmt *)p); - assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */ - db = sqlite3VdbeDb(p); - assert( sqlite3_mutex_held(db->mutex) ); - prepFlags = sqlite3VdbePrepareFlags(p); - rc = sqlite3LockAndPrepare(db, zSql, -1, prepFlags, p, &pNew, 0); - if( rc ){ - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(db); - } - assert( pNew==0 ); - return rc; - }else{ - assert( pNew!=0 ); - } - sqlite3VdbeSwap((Vdbe*)pNew, p); - sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); - sqlite3VdbeResetStepResult((Vdbe*)pNew); - sqlite3VdbeFinalize((Vdbe*)pNew); - return SQLITE_OK; -} - - -/* -** Two versions of the official API. Legacy and new use. In the legacy -** version, the original SQL text is not saved in the prepared statement -** and so if a schema change occurs, SQLITE_SCHEMA is returned by -** sqlite3_step(). In the new version, the original SQL text is retained -** and the statement is automatically recompiled if an schema change -** occurs. -*/ -SQLITE_API int sqlite3_prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} -SQLITE_API int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - /* EVIDENCE-OF: R-37923-12173 The sqlite3_prepare_v2() interface works - ** exactly the same as sqlite3_prepare_v3() with a zero prepFlags - ** parameter. - ** - ** Proof in that the 5th parameter to sqlite3LockAndPrepare is 0 */ - rc = sqlite3LockAndPrepare(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,0, - ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); - return rc; -} -SQLITE_API int sqlite3_prepare_v3( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - /* EVIDENCE-OF: R-56861-42673 sqlite3_prepare_v3() differs from - ** sqlite3_prepare_v2() only in having the extra prepFlags parameter, - ** which is a bit array consisting of zero or more of the - ** SQLITE_PREPARE_* flags. - ** - ** Proof by comparison to the implementation of sqlite3_prepare_v2() - ** directly above. */ - rc = sqlite3LockAndPrepare(db,zSql,nBytes, - SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), - 0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); - return rc; -} - - -#ifndef SQLITE_OMIT_UTF16 -/* -** Compile the UTF-16 encoded SQL statement zSql into a statement handle. -*/ -static int sqlite3Prepare16( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - /* This function currently works by first transforming the UTF-16 - ** encoded string to UTF-8, then invoking sqlite3_prepare(). The - ** tricky bit is figuring out the pointer to return in *pzTail. - */ - char *zSql8; - const char *zTail8 = 0; - int rc = SQLITE_OK; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif - *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ - return SQLITE_MISUSE_BKPT; - } - - /* Make sure nBytes is non-negative and correct. It should be the - ** number of bytes until the end of the input buffer or until the first - ** U+0000 character. If the input nBytes is odd, convert it into - ** an even number. If the input nBytes is negative, then the input - ** must be terminated by at least one U+0000 character */ - if( nBytes>=0 ){ - int sz; - const char *z = (const char*)zSql; - for(sz=0; szmutex); - zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); - if( zSql8 ){ - rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8); - } - - if( zTail8 && pzTail ){ - /* If sqlite3_prepare returns a tail pointer, we calculate the - ** equivalent pointer into the UTF-16 string by counting the unicode - ** characters between zSql8 and zTail8, and then returning a pointer - ** the same number of characters into the UTF-16 string. - */ - int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8)); - *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed); - } - sqlite3DbFree(db, zSql8); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Two versions of the official API. Legacy and new use. In the legacy -** version, the original SQL text is not saved in the prepared statement -** and so if a schema change occurs, SQLITE_SCHEMA is returned by -** sqlite3_step(). In the new version, the original SQL text is retained -** and the statement is automatically recompiled if an schema change -** occurs. -*/ -SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} -SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} -SQLITE_API int sqlite3_prepare16_v3( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3Prepare16(db,zSql,nBytes, - SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), - ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} - -#endif /* SQLITE_OMIT_UTF16 */ - -/************** End of prepare.c *********************************************/ -/************** Begin file select.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle SELECT statements in SQLite. -*/ -/* #include "sqliteInt.h" */ - -/* -** An instance of the following object is used to record information about -** how to process the DISTINCT keyword, to simplify passing that information -** into the selectInnerLoop() routine. -*/ -typedef struct DistinctCtx DistinctCtx; -struct DistinctCtx { - u8 isTnct; /* 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 */ -}; - -/* -** An instance of the following object is used to record information about -** the ORDER BY (or GROUP BY) clause of query is being coded. -** -** The aDefer[] array is used by the sorter-references optimization. For -** example, assuming there is no index that can be used for the ORDER BY, -** for the query: -** -** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10; -** -** it may be more efficient to add just the "a" values to the sorter, and -** retrieve the associated "bigblob" values directly from table t1 as the -** 10 smallest "a" values are extracted from the sorter. -** -** When the sorter-reference optimization is used, there is one entry in the -** aDefer[] array for each database table that may be read as values are -** extracted from the sorter. -*/ -typedef struct SortCtx SortCtx; -struct SortCtx { - ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */ - int nOBSat; /* Number of ORDER BY terms satisfied by indices */ - int iECursor; /* Cursor number for the sorter */ - int regReturn; /* Register holding block-output return address */ - int labelBkOut; /* Start label for the block-output subroutine */ - int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ - int labelDone; /* Jump here when done, ex: LIMIT reached */ - int labelOBLopt; /* Jump here when sorter is full */ - u8 sortFlags; /* Zero or more SORTFLAG_* bits */ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - u8 nDefer; /* Number of valid entries in aDefer[] */ - struct DeferredCsr { - Table *pTab; /* Table definition */ - int iCsr; /* Cursor number for table */ - int nKey; /* Number of PK columns for table pTab (>=1) */ - } aDefer[4]; -#endif - struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrPush; /* First instruction to push data into sorter */ - int addrPushEnd; /* Last instruction that pushes data into sorter */ -#endif -}; -#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ - -/* -** Delete all the content of a Select structure. Deallocate the structure -** itself depending on the value of bFree -** -** If bFree==1, call sqlite3DbFree() on the p object. -** If bFree==0, Leave the first Select object unfreed -*/ -static void clearSelect(sqlite3 *db, Select *p, int bFree){ - assert( db!=0 ); - while( p ){ - Select *pPrior = p->pPrior; - sqlite3ExprListDelete(db, p->pEList); - sqlite3SrcListDelete(db, p->pSrc); - sqlite3ExprDelete(db, p->pWhere); - sqlite3ExprListDelete(db, p->pGroupBy); - sqlite3ExprDelete(db, p->pHaving); - sqlite3ExprListDelete(db, p->pOrderBy); - sqlite3ExprDelete(db, p->pLimit); - if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ - sqlite3WindowListDelete(db, p->pWinDefn); - } - while( p->pWin ){ - assert( p->pWin->ppThis==&p->pWin ); - sqlite3WindowUnlinkFromSelect(p->pWin); - } -#endif - if( bFree ) sqlite3DbNNFreeNN(db, p); - p = pPrior; - bFree = 1; - } -} - -/* -** Initialize a SelectDest structure. -*/ -SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ - pDest->eDest = (u8)eDest; - pDest->iSDParm = iParm; - pDest->iSDParm2 = 0; - pDest->zAffSdst = 0; - pDest->iSdst = 0; - pDest->nSdst = 0; -} - - -/* -** Allocate a new Select structure and return a pointer to that -** structure. -*/ -SQLITE_PRIVATE Select *sqlite3SelectNew( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* which columns to include in the result */ - SrcList *pSrc, /* the FROM clause -- which tables to scan */ - Expr *pWhere, /* the WHERE clause */ - ExprList *pGroupBy, /* the GROUP BY clause */ - Expr *pHaving, /* the HAVING clause */ - ExprList *pOrderBy, /* the ORDER BY clause */ - u32 selFlags, /* Flag parameters, such as SF_Distinct */ - Expr *pLimit /* LIMIT value. NULL means not used */ -){ - Select *pNew, *pAllocated; - Select standin; - pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) ); - if( pNew==0 ){ - assert( pParse->db->mallocFailed ); - pNew = &standin; - } - if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, - sqlite3Expr(pParse->db,TK_ASTERISK,0)); - } - pNew->pEList = pEList; - pNew->op = TK_SELECT; - pNew->selFlags = selFlags; - pNew->iLimit = 0; - pNew->iOffset = 0; - pNew->selId = ++pParse->nSelect; - pNew->addrOpenEphm[0] = -1; - pNew->addrOpenEphm[1] = -1; - pNew->nSelectRow = 0; - if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); - pNew->pSrc = pSrc; - pNew->pWhere = pWhere; - pNew->pGroupBy = pGroupBy; - pNew->pHaving = pHaving; - pNew->pOrderBy = pOrderBy; - pNew->pPrior = 0; - pNew->pNext = 0; - pNew->pLimit = pLimit; - pNew->pWith = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - pNew->pWin = 0; - pNew->pWinDefn = 0; -#endif - if( pParse->db->mallocFailed ) { - clearSelect(pParse->db, pNew, pNew!=&standin); - pAllocated = 0; - }else{ - assert( pNew->pSrc!=0 || pParse->nErr>0 ); - } - return pAllocated; -} - - -/* -** Delete the given Select structure and all of its substructures. -*/ -SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); -} -SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){ - if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1); -} - -/* -** Return a pointer to the right-most SELECT statement in a compound. -*/ -static Select *findRightmost(Select *p){ - while( p->pNext ) p = p->pNext; - return p; -} - -/* -** Given 1 to 3 identifiers preceding the JOIN keyword, determine the -** type of join. Return an integer constant that expresses that type -** in terms of the following bit values: -** -** JT_INNER -** JT_CROSS -** JT_OUTER -** JT_NATURAL -** JT_LEFT -** JT_RIGHT -** -** A full outer join is the combination of JT_LEFT and JT_RIGHT. -** -** 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 nonsensical 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 sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ - int jointype = 0; - Token *apAll[3]; - Token *p; - /* 0123456789 123456789 123456789 123 */ - static const char zKeyText[] = "naturaleftouterightfullinnercross"; - static const struct { - u8 i; /* Beginning of keyword text in zKeyText[] */ - u8 nChar; /* Length of the keyword in characters */ - u8 code; /* Join type mask */ - } aKeyword[] = { - /* (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; - apAll[1] = pB; - apAll[2] = pC; - for(i=0; i<3 && apAll[i]; i++){ - p = apAll[i]; - for(j=0; jn==aKeyword[j].nChar - && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){ - jointype |= aKeyword[j].code; - break; - } - } - testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 ); - if( j>=ArraySize(aKeyword) ){ - jointype |= JT_ERROR; - break; - } - } - if( - (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 || - (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER - ){ - const char *zSp1 = " "; - const char *zSp2 = " "; - if( pB==0 ){ zSp1++; } - if( pC==0 ){ zSp2++; } - sqlite3ErrorMsg(pParse, "unknown join type: " - "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); - jointype = JT_INNER; - } - return jointype; -} - -/* -** Return the index of a column in a table. Return -1 if the column -** is not contained in the table. -*/ -SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ - int i; - u8 h; - const Column *aCol; - int nCol; - - h = sqlite3StrIHash(zCol); - aCol = pTab->aCol; - nCol = pTab->nCol; - - /* See if the aHx gives us a lucky match */ - i = pTab->aHx[h % sizeof(pTab->aHx)]; - assert( i=nCol ) break; - } - return -1; -} - -/* -** Mark a subquery result column as having been used. -*/ -SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){ - assert( pItem!=0 ); - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) ); - if( pItem->fg.isNestedFrom ){ - ExprList *pResults; - assert( pItem->fg.isSubquery ); - assert( pItem->u4.pSubq!=0 ); - assert( pItem->u4.pSubq->pSelect!=0 ); - pResults = pItem->u4.pSubq->pSelect->pEList; - assert( pResults!=0 ); - assert( iCol>=0 && iColnExpr ); - 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. -** -** If not found, return FALSE. -*/ -static int tableAndColumnIndex( - SrcList *pSrc, /* Array of tables 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 /* Ignore hidden columns */ -){ - int i; /* For looping over tables in pSrc */ - int iCol; /* Index of column matching zCol */ - - assert( iEndnSrc ); - assert( iStart>=0 ); - assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ - - for(i=iStart; i<=iEnd; i++){ - iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol); - if( iCol>=0 - && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0) - ){ - if( piTab ){ - sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol); - *piTab = i; - *piCol = iCol; - } - return 1; - } - } - return 0; -} - -/* -** 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_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.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: -** -** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 -** -** The where clause needs to defer the handling of the t1.x=5 -** term until after the t2 loop of the join. In that way, a -** NULL t2 row will be inserted whenever t1.x!=5. If we do not -** defer the handling of t1.x=5, it will be processed immediately -** after the t1 loop and rows with t1.x!=5 will never appear in -** the output, which is incorrect. -*/ -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){ - assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON ); - while( p ){ - ExprSetProperty(p, joinFlag); - assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); - ExprSetVVAProperty(p, EP_NoReduce); - p->w.iJoin = iTable; - if( p->op==TK_FUNCTION ){ - assert( ExprUseXList(p) ); - if( p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag); - } - } - } - sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag); - p = p->pRight; - } -} - -/* Undo the work of 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. -** -** 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, int nullable){ - while( p ){ - 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_COLUMN && p->iTable==iTable && !nullable ){ - ExprClearProperty(p, EP_CanBeNull); - } - if( p->op==TK_FUNCTION ){ - assert( ExprUseXList(p) ); - assert( p->pLeft==0 ); - if( p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable); - } - } - } - unsetJoinExpr(p->pLeft, iTable, nullable); - p = p->pRight; - } -} - -/* -** This routine processes the join information for a SELECT statement. -** -** * 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 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 right entry. -** -** This routine returns the number of errors encountered. -*/ -static int sqlite3ProcessJoin(Parse *pParse, Select *p){ - SrcList *pSrc; /* All tables in the FROM clause */ - int i, j; /* Loop counters */ - 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; inSrc-1; i++, pRight++, pLeft++){ - Table *pRightTab = pRight->pSTab; - u32 joinType; - - if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue; - joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; - - /* If this is a NATURAL join, synthesize an appropriate USING clause - ** to specify which columns should be joined. - */ - if( pRight->fg.jointype & JT_NATURAL ){ - IdList *pUsing = 0; - if( pRight->fg.isUsing || pRight->u3.pOn ){ - sqlite3ErrorMsg(pParse, "a NATURAL join may not have " - "an ON or USING clause", 0); - return 1; - } - for(j=0; jnCol; j++){ - char *zName; /* Name of column in the right table */ - - if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue; - zName = pRightTab->aCol[j].zCnName; - if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){ - pUsing = sqlite3IdListAppend(pParse, pUsing, 0); - if( pUsing ){ - assert( pUsing->nId>0 ); - assert( pUsing->a[pUsing->nId-1].zName==0 ); - pUsing->a[pUsing->nId-1].zName = sqlite3DbStrDup(pParse->db, zName); - } - } - } - 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 - ** in the USING clause. Example: If the two tables to be joined are - ** A and B and the USING clause names X, Y, and Z, then add this - ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z - ** Report an error if any column mentioned in the USING clause is - ** not contained in both tables to be joined. - */ - if( pRight->fg.isUsing ){ - IdList *pList = pRight->u3.pUsing; - sqlite3 *db = pParse->db; - assert( pList!=0 ); - for(j=0; jnId; 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 = sqlite3ColumnIndex(pRightTab, zName); - if( iRightCol<0 - || tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol, - pRight->fg.isSynthUsing)==0 - ){ - sqlite3ErrorMsg(pParse, "cannot join using column %s - column " - "not present in both tables", zName); - return 1; - } - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); - sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); - if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==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 }; - assert( pE1!=0 ); - ExprSetProperty(pE1, EP_CanBeNull); - while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol, - pRight->fg.isSynthUsing)!=0 ){ - if( pSrc->a[iLeft].fg.isUsing==0 - || sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0 - ){ - sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()", - zName); - break; - } - pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); - sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); - } - if( pFuncArgs ){ - pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); - pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0); - if( pE1 ){ - pE1->affExpr = SQLITE_AFF_DEFER; - } - } - }else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){ - assert( pE1!=0 ); - ExprSetProperty(pE1, EP_CanBeNull); - } - pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol); - sqlite3SrcItemColumnUsed(pRight, iRightCol); - pEq = 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 = 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 ){ - sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType); - p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); - pRight->u3.pOn = 0; - pRight->fg.isOn = 1; - } - } - return 0; -} - -/* -** An instance of this object holds information (beyond pParse and pSelect) -** needed to load the next result row that is to be added to the sorter. -*/ -typedef struct RowLoadInfo RowLoadInfo; -struct RowLoadInfo { - int regResult; /* Store results in array of registers here */ - u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - ExprList *pExtra; /* Extra columns needed by sorter refs */ - int regExtraResult; /* Where to load the extra columns */ -#endif -}; - -/* -** This routine does the work of loading query data into an array of -** registers so that it can be added to the sorter. -*/ -static void innerLoopLoadRow( - Parse *pParse, /* Statement under construction */ - Select *pSelect, /* The query being coded */ - RowLoadInfo *pInfo /* Info needed to complete the row load */ -){ - sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, - 0, pInfo->ecelFlags); -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pInfo->pExtra ){ - sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); - sqlite3ExprListDelete(pParse->db, pInfo->pExtra); - } -#endif -} - -/* -** Code the OP_MakeRecord instruction that generates the entry to be -** added into the sorter. -** -** Return the register in which the result is stored. -*/ -static int makeSorterRecord( - Parse *pParse, - SortCtx *pSort, - Select *pSelect, - int regBase, - int nBase -){ - int nOBSat = pSort->nOBSat; - Vdbe *v = pParse->pVdbe; - int regOut = ++pParse->nMem; - if( pSort->pDeferredRowLoad ){ - innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); - return regOut; -} - -/* -** Generate code that will push the record in registers regData -** through regData+nData-1 onto the sorter. -*/ -static void pushOntoSorter( - Parse *pParse, /* Parser context */ - SortCtx *pSort, /* Information about the ORDER BY clause */ - Select *pSelect, /* The whole SELECT statement */ - int regData, /* First register holding data to be sorted */ - int regOrigData, /* First register holding data before packing */ - int nData, /* Number of elements in the regData data array */ - int nPrefixReg /* No. of reg prior to regData available for use */ -){ - Vdbe *v = pParse->pVdbe; /* Stmt under construction */ - int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0); - int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ - int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ - int regBase; /* Regs for sorter record */ - int regRecord = 0; /* Assembled sorter record */ - int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ - int op; /* Opcode to add sorter record to sorter */ - int iLimit; /* LIMIT counter */ - int iSkip = 0; /* End of the sorter insert loop */ - - assert( bSeq==0 || bSeq==1 ); - - /* Three cases: - ** (1) The data to be sorted has already been packed into a Record - ** by a prior OP_MakeRecord. In this case nData==1 and regData - ** will be completely unrelated to regOrigData. - ** (2) All output columns are included in the sort record. In that - ** case regData==regOrigData. - ** (3) Some output columns are omitted from the sort record due to - ** the SQLITE_ENABLE_SORTER_REFERENCES optimization, or due to the - ** SQLITE_ECEL_OMITREF optimization, or due to the - ** SortCtx.pDeferredRowLoad optimization. In any of these cases - ** regOrigData is 0 to prevent this routine from trying to copy - ** values that might not yet exist. - */ - assert( nData==1 || regData==regOrigData || regOrigData==0 ); - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pSort->addrPush = sqlite3VdbeCurrentAddr(v); -#endif - - if( nPrefixReg ){ - assert( nPrefixReg==nExpr+bSeq ); - regBase = regData - nPrefixReg; - }else{ - regBase = pParse->nMem + 1; - pParse->nMem += nBase; - } - assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); - iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; - pSort->labelDone = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, - SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); - if( bSeq ){ - sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); - } - if( nPrefixReg==0 && nData>0 ){ - sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); - } - if( nOBSat>0 ){ - int regPrevKey; /* The first nOBSat columns of the previous row */ - int addrFirst; /* Address of the OP_IfNot opcode */ - int addrJmp; /* Address of the OP_Jump opcode */ - VdbeOp *pOp; /* Opcode that opens the sorter */ - int nKey; /* Number of sorting key columns, including OP_Sequence */ - KeyInfo *pKI; /* Original KeyInfo on the sorter table */ - - regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); - regPrevKey = pParse->nMem+1; - pParse->nMem += pSort->nOBSat; - nKey = nExpr - pSort->nOBSat + bSeq; - if( bSeq ){ - addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); - }else{ - addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor); - } - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat); - pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); - if( pParse->db->mallocFailed ) return; - pOp->p2 = nKey + nData; - pKI = pOp->p4.pKeyInfo; - memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */ - sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); - testcase( pKI->nAllField > pKI->nKeyField+2 ); - pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, - pKI->nAllField-pKI->nKeyField-1); - pOp = 0; /* Ensure pOp not used after sqlite3VdbeAddOp3() */ - addrJmp = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); - pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse); - pSort->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); - if( iLimit ){ - sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone); - VdbeCoverage(v); - } - sqlite3VdbeJumpHere(v, addrFirst); - sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); - sqlite3VdbeJumpHere(v, addrJmp); - } - if( iLimit ){ - /* At this point the values for the new sorter entry are stored - ** in an array of registers. They need to be composed into a record - ** and inserted into the sorter if either (a) there are currently - ** less than LIMIT+OFFSET items or (b) the new record is smaller than - ** the largest record currently in the sorter. If (b) is true and there - ** are already LIMIT+OFFSET items in the sorter, delete the largest - ** entry before inserting the new one. This way there are never more - ** than LIMIT+OFFSET items in the sorter. - ** - ** If the new record does not need to be inserted into the sorter, - ** jump to the next iteration of the loop. If the pSort->labelOBLopt - ** value is not zero, then it is a label of where to jump. Otherwise, - ** just bypass the row insert logic. See the header comment on the - ** sqlite3WhereOrderByLimitOptLabel() function for additional info. - */ - int iCsr = pSort->iECursor; - sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); - iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, - iCsr, 0, regBase+nOBSat, nExpr-nOBSat); - VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_Delete, iCsr); - } - if( regRecord==0 ){ - regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); - } - if( pSort->sortFlags & SORTFLAG_UseSorter ){ - op = OP_SorterInsert; - }else{ - op = OP_IdxInsert; - } - sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, - regBase+nOBSat, nBase-nOBSat); - if( iSkip ){ - sqlite3VdbeChangeP2(v, iSkip, - pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); - } -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1; -#endif -} - -/* -** Add code to implement the OFFSET -*/ -static void codeOffset( - Vdbe *v, /* Generate code into this VM */ - int iOffset, /* Register holding the offset counter */ - int iContinue /* Jump here to skip the current record */ -){ - if( iOffset>0 ){ - sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v); - VdbeComment((v, "OFFSET")); - } -} - -/* -** 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 ) ..."). Three strategies -** are available. Which is used depends on the value of parameter eTnctType, -** as follows: -** -** 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 ephemeral -** 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 */ - ExprList *pEList, /* Expression for each element */ - int regElem /* First element */ -){ - int iRet = 0; - int nResultCol = pEList->nExpr; - Vdbe *v = pParse->pVdbe; - - 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 = sqlite3VdbeCurrentAddr(v) + nResultCol; - for(i=0; ia[i].pExpr); - if( idb->mallocFailed ); - sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1); - break; - } - - case WHERE_DISTINCT_UNIQUE: { - /* nothing to do */ - break; - } - - default: { - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - 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; - sqlite3VdbeChangeToNoop(v, iOpenEphAddr); - if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){ - 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 = sqlite3VdbeGetOp(v, iOpenEphAddr); - pOp->opcode = OP_Null; - pOp->p1 = 1; - pOp->p2 = iVal; - } - } -} - -#ifdef SQLITE_ENABLE_SORTER_REFERENCES -/* -** This function is called as part of inner-loop generation for a SELECT -** statement with an ORDER BY that is not optimized by an index. It -** determines the expressions, if any, that the sorter-reference -** optimization should be used for. The sorter-reference optimization -** is used for SELECT queries like: -** -** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10 -** -** If the optimization is used for expression "bigblob", then instead of -** storing values read from that column in the sorter records, the PK of -** the row from table t1 is stored instead. Then, as records are extracted from -** the sorter to return to the user, the required value of bigblob is -** 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.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. -** output variable (*ppExtra) is set to an expression list containing -** expressions for all extra PK values that should be stored in the -** sorter records. -*/ -static void selectExprDefer( - Parse *pParse, /* Leave any error here */ - SortCtx *pSort, /* Sorter context */ - ExprList *pEList, /* Expressions destined for sorter */ - ExprList **ppExtra /* Expressions to append to sorter record */ -){ - int i; - int nDefer = 0; - ExprList *pExtra = 0; - for(i=0; inExpr; i++){ - struct ExprList_item *pItem = &pEList->a[i]; - if( pItem->u.x.iOrderByCol==0 ){ - Expr *pExpr = pItem->pExpr; - 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; jaDefer[j].iCsr==pExpr->iTable ) break; - } - if( j==nDefer ){ - if( nDefer==ArraySize(pSort->aDefer) ){ - continue; - }else{ - int nKey = 1; - int k; - Index *pPk = 0; - if( !HasRowid(pTab) ){ - pPk = sqlite3PrimaryKeyIndex(pTab); - nKey = pPk->nKeyCol; - } - for(k=0; kiTable = pExpr->iTable; - assert( ExprUseYTab(pNew) ); - pNew->y.pTab = pExpr->y.pTab; - pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; - pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); - } - } - pSort->aDefer[nDefer].pTab = pExpr->y.pTab; - pSort->aDefer[nDefer].iCsr = pExpr->iTable; - pSort->aDefer[nDefer].nKey = nKey; - nDefer++; - } - } - pItem->fg.bSorterRef = 1; - } - } - } - pSort->nDefer = (u8)nDefer; - *ppExtra = pExtra; -} -#endif - -/* -** This routine generates the code for the inside of the inner loop -** of a SELECT. -** -** If srcTab is negative, then the p->pEList expressions -** are evaluated in order to get the data for this row. If srcTab is -** zero or more, then data is pulled from srcTab and p->pEList is used only -** to get the number of columns and the collation sequence for each column. -*/ -static void selectInnerLoop( - Parse *pParse, /* The parser context */ - Select *p, /* The complete select statement being coded */ - int srcTab, /* Pull data from this table if non-negative */ - SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */ - DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ - SelectDest *pDest, /* How to dispose of the results */ - int iContinue, /* Jump here to continue with next row */ - int iBreak /* Jump here to break out of the inner loop */ -){ - Vdbe *v = pParse->pVdbe; - int i; - int hasDistinct; /* True if the DISTINCT keyword is present */ - int eDest = pDest->eDest; /* How to dispose of results */ - int iParm = pDest->iSDParm; /* First argument to disposal method */ - int nResultCol; /* Number of result columns */ - int nPrefixReg = 0; /* Number of extra registers before regResult */ - RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ - - /* Usually, regResult is the first cell in an array of memory cells - ** containing the current result row. In this case regOrig is set to the - ** same value. However, if the results are being sent to the sorter, the - ** values for any expressions that are also part of the sort-key are omitted - ** from this array. In this case regOrig is set to zero. */ - int regResult; /* Start of memory holding current results */ - int regOrig; /* Start of memory holding full result (or 0) */ - - assert( v ); - assert( p->pEList!=0 ); - hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; - if( pSort && pSort->pOrderBy==0 ) pSort = 0; - if( pSort==0 && !hasDistinct ){ - assert( iContinue!=0 ); - codeOffset(v, p->iOffset, iContinue); - } - - /* Pull the requested columns. - */ - nResultCol = p->pEList->nExpr; - - if( pDest->iSdst==0 ){ - if( pSort ){ - nPrefixReg = pSort->pOrderBy->nExpr; - if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++; - pParse->nMem += nPrefixReg; - } - pDest->iSdst = pParse->nMem+1; - pParse->nMem += nResultCol; - }else if( pDest->iSdst+nResultCol > pParse->nMem ){ - /* This is an error condition that can result, for example, when a SELECT - ** on the right-hand side of an INSERT contains more result columns than - ** there are columns in the table on the left. The error will be caught - ** and reported later. But we need to make sure enough memory is allocated - ** to avoid other spurious errors in the meantime. */ - pParse->nMem += nResultCol; - } - pDest->nSdst = nResultCol; - regOrig = regResult = pDest->iSdst; - if( srcTab>=0 ){ - for(i=0; ipEList->a[i].zEName)); - } - }else if( eDest!=SRT_Exists ){ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - ExprList *pExtra = 0; -#endif - /* If the destination is an EXISTS(...) expression, the actual - ** values returned by the SELECT are not required. - */ - u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ - ExprList *pEList; - if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ - ecelFlags = SQLITE_ECEL_DUP; - }else{ - ecelFlags = 0; - } - if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ - /* For each expression in p->pEList that is a copy of an expression in - ** the ORDER BY clause (pSort->pOrderBy), set the associated - ** iOrderByCol value to one more than the index of the ORDER BY - ** expression within the sort-key that pushOntoSorter() will generate. - ** This allows the p->pEList field to be omitted from the sorted record, - ** saving space and CPU cycles. */ - ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); - - for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){ - int j; - if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ - p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; - } - } -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - selectExprDefer(pParse, pSort, p->pEList, &pExtra); - if( pExtra && pParse->db->mallocFailed==0 ){ - /* If there are any extra PK columns to add to the sorter records, - ** allocate extra memory cells and adjust the OpenEphemeral - ** instruction to account for the larger records. This is only - ** required if there are one or more WITHOUT ROWID tables with - ** composite primary keys in the SortCtx.aDefer[] array. */ - VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); - pOp->p2 += (pExtra->nExpr - pSort->nDefer); - pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer); - pParse->nMem += pExtra->nExpr; - } -#endif - - /* Adjust nResultCol to account for columns that are omitted - ** from the sorter by the optimizations in this branch */ - pEList = p->pEList; - for(i=0; inExpr; i++){ - if( pEList->a[i].u.x.iOrderByCol>0 -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - || pEList->a[i].fg.bSorterRef -#endif - ){ - nResultCol--; - regOrig = 0; - } - } - - testcase( regOrig ); - testcase( eDest==SRT_Set ); - testcase( eDest==SRT_Mem ); - testcase( eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - assert( eDest==SRT_Set || eDest==SRT_Mem - || eDest==SRT_Coroutine || eDest==SRT_Output - || eDest==SRT_Upfrom ); - } - sRowLoadInfo.regResult = regResult; - sRowLoadInfo.ecelFlags = ecelFlags; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - sRowLoadInfo.pExtra = pExtra; - sRowLoadInfo.regExtraResult = regResult + nResultCol; - if( pExtra ) nResultCol += pExtra->nExpr; -#endif - if( p->iLimit - && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 - && nPrefixReg>0 - ){ - assert( pSort!=0 ); - assert( hasDistinct==0 ); - pSort->pDeferredRowLoad = &sRowLoadInfo; - regOrig = 0; - }else{ - innerLoopLoadRow(pParse, p, &sRowLoadInfo); - } - } - - /* If the DISTINCT keyword was present on the SELECT statement - ** and this row has been seen before, then do not make this row - ** part of the result. - */ - if( hasDistinct ){ - 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); - } - } - - switch( eDest ){ - /* In this mode, write each query result to the key of the temporary - ** table iParm. - */ -#ifndef SQLITE_OMIT_COMPOUND_SELECT - case SRT_Union: { - int r1; - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); - sqlite3ReleaseTempReg(pParse, r1); - break; - } - - /* Construct a record from the query result, but instead of - ** saving that record, use it as a key to delete elements from - ** the temporary table iParm. - */ - case SRT_Except: { - sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol); - break; - } -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ - - /* Store the result as data using a unique key. - */ - case SRT_Fifo: - case SRT_DistFifo: - case SRT_Table: - case SRT_EphemTab: { - int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); - testcase( eDest==SRT_Table ); - testcase( eDest==SRT_EphemTab ); - testcase( eDest==SRT_Fifo ); - testcase( eDest==SRT_DistFifo ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); -#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) - /* A destination of SRT_Table and a non-zero iSDParm2 parameter means - ** that this is an "UPDATE ... FROM" on a virtual table or view. In this - ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. - ** This does not affect operation in any way - it just allows MakeRecord - ** to process OPFLAG_NOCHANGE values without an assert() failing. */ - if( eDest==SRT_Table && pDest->iSDParm2 ){ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); - } -#endif -#ifndef SQLITE_OMIT_CTE - if( eDest==SRT_DistFifo ){ - /* If the destination is DistFifo, then cursor (iParm+1) is open - ** on an ephemeral index. If the current row is already present - ** in the index, do not write it to the output. If not, add the - ** current row to the index and proceed with writing it to the - ** output table as well. */ - int addr = sqlite3VdbeCurrentAddr(v) + 4; - sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); - VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); - assert( pSort==0 ); - } -#endif - if( pSort ){ - assert( regResult==regOrig ); - pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); - }else{ - int r2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3ReleaseTempReg(pParse, r2); - } - sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1); - break; - } - - case SRT_Upfrom: { - if( pSort ){ - pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); - }else{ - int i2 = pDest->iSDParm2; - int r1 = sqlite3GetTempReg(pParse); - - /* If the UPDATE FROM join is an aggregate that matches no rows, it - ** might still be trying to return one row, because that is what - ** aggregates do. Don't record that empty row in the output table. */ - sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v); - - sqlite3VdbeAddOp3(v, OP_MakeRecord, - regResult+(i2<0), nResultCol-(i2<0), r1); - if( i2<0 ){ - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult); - }else{ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2); - } - } - break; - } - -#ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. - */ - case SRT_Set: { - if( pSort ){ - /* At first glance you would think we could optimize out the - ** ORDER BY in this case since the order of entries in the set - ** does not matter. But there might be a LIMIT clause, in which - ** case the order does matter */ - pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); - pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */ - }else{ - int r1 = sqlite3GetTempReg(pParse); - assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, - r1, pDest->zAffSdst, nResultCol); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); - if( pDest->iSDParm2 ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, - regResult, nResultCol); - ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); - } - sqlite3ReleaseTempReg(pParse, r1); - } - break; - } - - - /* If any row exist in the result set, record that fact and abort. - */ - case SRT_Exists: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); - /* The LIMIT clause will terminate the loop for us */ - break; - } - - /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell or array of - ** memory cells and break out of the scan loop. - */ - case SRT_Mem: { - if( pSort ){ - assert( nResultCol<=pDest->nSdst ); - pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); - }else{ - assert( nResultCol==pDest->nSdst ); - assert( regResult==iParm ); - /* The LIMIT clause will jump out of the loop for us */ - } - break; - } -#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ - - case SRT_Coroutine: /* Send data to a co-routine */ - case SRT_Output: { /* Return the results */ - testcase( eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, - nPrefixReg); - }else if( eDest==SRT_Coroutine ){ - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - }else{ - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); - } - break; - } - -#ifndef SQLITE_OMIT_CTE - /* Write the results into a priority queue that is order according to - ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an - ** index with pSO->nExpr+2 columns. Build a key using pSO for the first - ** pSO->nExpr columns, then make sure all keys are unique by adding a - ** final OP_Sequence column. The last column is the record as a blob. - */ - case SRT_DistQueue: - case SRT_Queue: { - int nKey; - int r1, r2, r3; - int addrTest = 0; - ExprList *pSO; - pSO = pDest->pOrderBy; - assert( pSO ); - nKey = pSO->nExpr; - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempRange(pParse, nKey+2); - r3 = r2+nKey+1; - if( eDest==SRT_DistQueue ){ - /* If the destination is DistQueue, then cursor (iParm+1) is open - ** on a second ephemeral index that holds all values every previously - ** added to the queue. */ - addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, - regResult, nResultCol); - VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); - if( eDest==SRT_DistQueue ){ - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - } - for(i=0; ia[i].u.x.iOrderByCol - 1, - r2+i); - } - sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); - sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); - if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempRange(pParse, r2, nKey+2); - break; - } -#endif /* SQLITE_OMIT_CTE */ - - - -#if !defined(SQLITE_OMIT_TRIGGER) - /* Discard the results. This is used for SELECT statements inside - ** the body of a TRIGGER. The purpose of such selects is to call - ** user-defined functions that have side effects. We do not care - ** about the actual results of the select. - */ - default: { - assert( eDest==SRT_Discard ); - break; - } -#endif - } - - /* Jump to the end of the loop if the LIMIT is reached. Except, if - ** there is a sorter, in which case the sorter has already limited - ** the output for us. - */ - if( pSort==0 && p->iLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); - } -} - -/* -** Allocate a KeyInfo object sufficient for an index of N key columns and -** X extra columns. -*/ -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ - int nExtra = (N+X)*(sizeof(CollSeq*)+1); - KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); - if( p ){ - p->aSortFlags = (u8*)&p->aColl[N+X]; - p->nKeyField = (u16)N; - p->nAllField = (u16)(N+X); - p->enc = ENC(db); - p->db = db; - p->nRef = 1; - memset(p->aColl, 0, nExtra); - }else{ - return (KeyInfo*)sqlite3OomFault(db); - } - return p; -} - -/* -** Deallocate a KeyInfo object -*/ -SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){ - if( p ){ - assert( p->db!=0 ); - assert( p->nRef>0 ); - p->nRef--; - if( p->nRef==0 ) sqlite3DbNNFreeNN(p->db, p); - } -} - -/* -** Make a new pointer to a KeyInfo object -*/ -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){ - if( p ){ - assert( p->nRef>0 ); - p->nRef++; - } - return p; -} - -#ifdef SQLITE_DEBUG -/* -** Return TRUE if a KeyInfo object can be change. The KeyInfo object -** can only be changed if this is just a single reference to the object. -** -** This routine is used only inside of assert() statements. -*/ -SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; } -#endif /* SQLITE_DEBUG */ - -/* -** Given an expression list, generate a KeyInfo structure that records -** the collating sequence for each expression in that expression list. -** -** If the ExprList is an ORDER BY or GROUP BY clause then the resulting -** KeyInfo structure is appropriate for initializing a virtual index to -** implement that clause. If the ExprList is the result set of a SELECT -** then the KeyInfo structure is appropriate for initializing a virtual -** index to implement a DISTINCT test. -** -** Space to hold the KeyInfo structure is obtained from malloc. The calling -** function is responsible for seeing that this structure is eventually -** freed. -*/ -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* Form the KeyInfo object from this ExprList */ - int iStart, /* Begin with this column of pList */ - int nExtra /* Add this many extra columns to the end */ -){ - int nExpr; - KeyInfo *pInfo; - struct ExprList_item *pItem; - sqlite3 *db = pParse->db; - int i; - - nExpr = pList->nExpr; - pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); - if( pInfo ){ - assert( sqlite3KeyInfoIsWriteable(pInfo) ); - for(i=iStart, pItem=pList->a+iStart; iaColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); - pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags; - } - } - return pInfo; -} - -/* -** Name of the connection operator, used for error messages. -*/ -SQLITE_PRIVATE const char *sqlite3SelectOpName(int id){ - char *z; - switch( id ){ - case TK_ALL: z = "UNION ALL"; break; - case TK_INTERSECT: z = "INTERSECT"; break; - case TK_EXCEPT: z = "EXCEPT"; break; - default: z = "UNION"; break; - } - return z; -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function -** is a no-op. Otherwise, it adds a single row of output to the EQP result, -** where the caption is of the form: -** -** "USE TEMP B-TREE FOR xxx" -** -** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which -** is determined by the zUsage argument. -*/ -static void explainTempTable(Parse *pParse, const char *zUsage){ - ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); -} - -/* -** Assign expression b to lvalue a. A second, no-op, version of this macro -** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code -** in sqlite3Select() to assign values to structure member variables that -** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the -** code with #ifndef directives. -*/ -# define explainSetInteger(a, b) a = b - -#else -/* No-op versions of the explainXXX() functions and macros. */ -# define explainTempTable(y,z) -# define explainSetInteger(y,z) -#endif - - -/* -** If the inner loop was generated using a non-null pOrderBy argument, -** then the results were placed in a sorter. After the loop is terminated -** we need to run the sorter and output the results. The following -** routine generates the code needed to do that. -*/ -static void generateSortTail( - Parse *pParse, /* Parsing context */ - Select *p, /* The SELECT statement */ - SortCtx *pSort, /* Information on the ORDER BY clause */ - int nColumn, /* Number of columns of data */ - SelectDest *pDest /* Write the sorted results here */ -){ - Vdbe *v = pParse->pVdbe; /* The prepared statement */ - int addrBreak = pSort->labelDone; /* Jump here to exit loop */ - int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */ - int addr; /* Top of output loop. Jump for Next. */ - int addrOnce = 0; - int iTab; - ExprList *pOrderBy = pSort->pOrderBy; - int eDest = pDest->eDest; - int iParm = pDest->iSDParm; - int regRow; - int regRowid; - int iCol; - int nKey; /* Number of key columns in sorter record */ - int iSortTab; /* Sorter cursor to read from */ - int i; - int bSeq; /* True if sorter record includes seq. no. */ - int nRefKey = 0; - struct ExprList_item *aOutEx = p->pEList->a; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; /* Address of OP_Explain instruction */ -#endif - - nKey = pOrderBy->nExpr - pSort->nOBSat; - if( pSort->nOBSat==0 || nKey==1 ){ - ExplainQueryPlan2(addrExplain, (pParse, 0, - "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":"" - )); - }else{ - ExplainQueryPlan2(addrExplain, (pParse, 0, - "USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey - )); - } - sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd); - sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush); - - - assert( addrBreak<0 ); - if( pSort->labelBkOut ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); - sqlite3VdbeGoto(v, addrBreak); - sqlite3VdbeResolveLabel(v, pSort->labelBkOut); - } - -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - /* Open any cursors needed for sorter-reference expressions */ - for(i=0; inDefer; i++){ - Table *pTab = pSort->aDefer[i].pTab; - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); - nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); - } -#endif - - iTab = pSort->iECursor; - if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ - if( eDest==SRT_Mem && p->iOffset ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst); - } - regRowid = 0; - regRow = pDest->iSdst; - }else{ - regRowid = sqlite3GetTempReg(pParse); - if( eDest==SRT_EphemTab || eDest==SRT_Table ){ - regRow = sqlite3GetTempReg(pParse); - nColumn = 0; - }else{ - regRow = sqlite3GetTempRange(pParse, nColumn); - } - } - if( pSort->sortFlags & SORTFLAG_UseSorter ){ - int regSortOut = ++pParse->nMem; - iSortTab = pParse->nTab++; - if( pSort->labelBkOut ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, - nKey+1+nColumn+nRefKey); - if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); - addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); - VdbeCoverage(v); - assert( p->iLimit==0 && p->iOffset==0 ); - sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); - bSeq = 0; - }else{ - addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); - codeOffset(v, p->iOffset, addrContinue); - iSortTab = iTab; - bSeq = 1; - if( p->iOffset>0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); - } - } - for(i=0, iCol=nKey+bSeq-1; inDefer ){ - int iKey = iCol+1; - int regKey = sqlite3GetTempRange(pParse, nRefKey); - - for(i=0; inDefer; i++){ - int iCsr = pSort->aDefer[i].iCsr; - Table *pTab = pSort->aDefer[i].pTab; - int nKey = pSort->aDefer[i].nKey; - - sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey); - sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr, - sqlite3VdbeCurrentAddr(v)+1, regKey); - }else{ - int k; - int iJmp; - assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey ); - for(k=0; k=0; i--){ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( aOutEx[i].fg.bSorterRef ){ - sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); - }else -#endif - { - int iRead; - if( aOutEx[i].u.x.iOrderByCol ){ - iRead = aOutEx[i].u.x.iOrderByCol-1; - }else{ - iRead = iCol--; - } - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); - VdbeComment((v, "%s", aOutEx[i].zEName)); - } - } - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); - switch( eDest ){ - case SRT_Table: - case SRT_EphemTab: { - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq, regRow); - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case SRT_Set: { - assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, - pDest->zAffSdst, nColumn); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); - break; - } - case SRT_Mem: { - /* The LIMIT clause will terminate the loop for us */ - break; - } -#endif - case SRT_Upfrom: { - int i2 = pDest->iSDParm2; - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1); - if( i2<0 ){ - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow); - }else{ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2); - } - break; - } - default: { - assert( eDest==SRT_Output || eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - testcase( eDest==SRT_Coroutine ); - if( eDest==SRT_Output ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); - }else{ - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - } - break; - } - } - if( regRowid ){ - if( eDest==SRT_Set ){ - sqlite3ReleaseTempRange(pParse, regRow, nColumn); - }else{ - sqlite3ReleaseTempReg(pParse, regRow); - } - sqlite3ReleaseTempReg(pParse, regRowid); - } - /* The bottom of the loop - */ - sqlite3VdbeResolveLabel(v, addrContinue); - if( pSort->sortFlags & SORTFLAG_UseSorter ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); - } - sqlite3VdbeScanStatusRange(v, addrExplain, sqlite3VdbeCurrentAddr(v)-1, -1); - if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn); - sqlite3VdbeResolveLabel(v, addrBreak); -} - -/* -** Return a pointer to a string containing the 'declaration type' of the -** expression pExpr. The string may be treated as static by the caller. -** -** The declaration type is the exact datatype definition extracted from the -** original CREATE TABLE statement if the expression is a column. The -** declaration type for a ROWID field is INTEGER. Exactly when an expression -** is considered a column can be complex in the presence of subqueries. The -** result-set expression in all of the following SELECT statements is -** considered a column by this function. -** -** SELECT col FROM tbl; -** SELECT (SELECT col FROM tbl; -** SELECT (SELECT col FROM tbl); -** SELECT abc FROM (SELECT col AS abc FROM tbl); -** -** The declaration type for any expression other than a column is NULL. -** -** This routine has either 3 or 6 parameters depending on whether or not -** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. -*/ -#ifdef SQLITE_ENABLE_COLUMN_METADATA -# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E) -#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ -# define columnType(A,B,C,D,E) columnTypeImpl(A,B) -#endif -static const char *columnTypeImpl( - NameContext *pNC, -#ifndef SQLITE_ENABLE_COLUMN_METADATA - Expr *pExpr -#else - Expr *pExpr, - const char **pzOrigDb, - const char **pzOrigTab, - const char **pzOrigCol -#endif -){ - char const *zType = 0; - int j; -#ifdef SQLITE_ENABLE_COLUMN_METADATA - char const *zOrigDb = 0; - char const *zOrigTab = 0; - char const *zOrigCol = 0; -#endif - - assert( pExpr!=0 ); - assert( pNC->pSrcList!=0 ); - switch( pExpr->op ){ - case TK_COLUMN: { - /* The expression is a column. Locate the table the column is being - ** extracted from in NameContext.pSrcList. This table may be real - ** database table or a subquery. - */ - Table *pTab = 0; /* Table structure column is extracted from */ - Select *pS = 0; /* Select the column is extracted from */ - int iCol = pExpr->iColumn; /* Index of column in pTab */ - while( pNC && !pTab ){ - SrcList *pTabList = pNC->pSrcList; - for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); - if( jnSrc ){ - pTab = pTabList->a[j].pSTab; - if( pTabList->a[j].fg.isSubquery ){ - pS = pTabList->a[j].u4.pSubq->pSelect; - }else{ - pS = 0; - } - }else{ - pNC = pNC->pNext; - } - } - - if( pTab==0 ){ - /* At one time, code such as "SELECT new.x" within a trigger would - ** cause this condition to run. Since then, we have restructured how - ** trigger code is generated and so this condition is no longer - ** possible. However, it can still be true for statements like - ** the following: - ** - ** CREATE TABLE t1(col INTEGER); - ** SELECT (SELECT t1.col) FROM FROM t1; - ** - ** when columnType() is called on the expression "t1.col" in the - ** sub-select. In this case, set the column type to NULL, even - ** though it should really be "INTEGER". - ** - ** This is not a problem, as the column type of "t1.col" is never - ** used. When columnType() is called on the expression - ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT - ** branch below. */ - break; - } - - 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( iColpEList->nExpr - && (!ViewCanHaveRowid || iCol>=0) - ){ - /* 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. - */ - NameContext sNC; - Expr *p = pS->pEList->a[iCol].pExpr; - sNC.pSrcList = pS->pSrc; - sNC.pNext = pNC; - sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol); - } - }else{ - /* A real table or a CTE table */ - assert( !pS ); -#ifdef SQLITE_ENABLE_COLUMN_METADATA - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==XN_ROWID || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - zOrigCol = "rowid"; - }else{ - zOrigCol = pTab->aCol[iCol].zCnName; - zType = sqlite3ColumnType(&pTab->aCol[iCol],0); - } - zOrigTab = pTab->zName; - if( pNC->pParse && pTab->pSchema ){ - int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); - zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; - } -#else - assert( iCol==XN_ROWID || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - }else{ - zType = sqlite3ColumnType(&pTab->aCol[iCol],0); - } -#endif - } - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_SELECT: { - /* The expression is a sub-select. Return the declaration type and - ** origin info for the single column in the result set of the SELECT - ** statement. - */ - NameContext sNC; - 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; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); - break; - } -#endif - } - -#ifdef SQLITE_ENABLE_COLUMN_METADATA - if( pzOrigDb ){ - assert( pzOrigTab && pzOrigCol ); - *pzOrigDb = zOrigDb; - *pzOrigTab = zOrigTab; - *pzOrigCol = zOrigCol; - } -#endif - return zType; -} - -/* -** Generate code that will tell the VDBE the declaration types of columns -** in the result set. -*/ -static void generateColumnTypes( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* List of tables */ - ExprList *pEList /* Expressions defining the result set */ -){ -#ifndef SQLITE_OMIT_DECLTYPE - Vdbe *v = pParse->pVdbe; - int i; - NameContext sNC; - sNC.pSrcList = pTabList; - sNC.pParse = pParse; - sNC.pNext = 0; - for(i=0; inExpr; i++){ - Expr *p = pEList->a[i].pExpr; - const char *zType; -#ifdef SQLITE_ENABLE_COLUMN_METADATA - const char *zOrigDb = 0; - const char *zOrigTab = 0; - const char *zOrigCol = 0; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); - - /* The vdbe must make its own copy of the column-type and other - ** column specific strings, in case the schema is reset before this - ** virtual machine is deleted. - */ - sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); -#else - zType = columnType(&sNC, p, 0, 0, 0); -#endif - sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); - } -#endif /* !defined(SQLITE_OMIT_DECLTYPE) */ -} - - -/* -** Compute the column names for a SELECT statement. -** -** The only guarantee that SQLite makes about column names is that if the -** column has an AS clause assigning it a name, that will be the name used. -** That is the only documented guarantee. However, countless applications -** developed over the years have made baseless assumptions about column names -** and will break if those assumptions changes. Hence, use extreme caution -** when modifying this routine to avoid breaking legacy. -** -** See Also: sqlite3ColumnsFromExprList() -** -** The PRAGMA short_column_names and PRAGMA full_column_names settings are -** deprecated. The default setting is short=ON, full=OFF. 99.9% of all -** applications should operate this way. Nevertheless, we need to support the -** other modes for legacy: -** -** short=OFF, full=OFF: Column name is the text of the expression has it -** originally appears in the SELECT statement. In -** other words, the zSpan of the result expression. -** -** short=ON, full=OFF: (This is the default setting). If the result -** refers directly to a table column, then the -** result column name is just the table column -** name: COLUMN. Otherwise use zSpan. -** -** full=ON, short=ANY: If the result refers directly to a table column, -** then the result column name with the table name -** prefix, ex: TABLE.COLUMN. Otherwise use zSpan. -*/ -SQLITE_PRIVATE void sqlite3GenerateColumnNames( - Parse *pParse, /* Parser context */ - Select *pSelect /* Generate column names for this SELECT statement */ -){ - Vdbe *v = pParse->pVdbe; - int i; - Table *pTab; - SrcList *pTabList; - ExprList *pEList; - sqlite3 *db = pParse->db; - int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */ - int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */ - - if( pParse->colNamesSet ) return; - /* Column names are determined by the left-most term of a compound select */ - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - TREETRACE(0x80,pParse,pSelect,("generating column names\n")); - pTabList = pSelect->pSrc; - pEList = pSelect->pEList; - assert( v!=0 ); - assert( pTabList!=0 ); - pParse->colNamesSet = 1; - fullName = (db->flags & SQLITE_FullColNames)!=0; - srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName; - sqlite3VdbeSetNumCols(v, pEList->nExpr); - for(i=0; inExpr; i++){ - Expr *p = pEList->a[i].pExpr; - - assert( p!=0 ); - assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ - 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; - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( srcName && p->op==TK_COLUMN ){ - char *zCol; - int iCol = p->iColumn; - pTab = p->y.pTab; - assert( pTab!=0 ); - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zCol = "rowid"; - }else{ - zCol = pTab->aCol[iCol].zCnName; - } - if( fullName ){ - char *zName = 0; - zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); - }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); - } - }else{ - const char *z = pEList->a[i].zEName; - z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z); - sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC); - } - } - generateColumnTypes(pParse, pTabList, pEList); -} - -/* -** Given an expression list (which is really the list of expressions -** that form the result set of a SELECT statement) compute appropriate -** column names for a table that would hold the expression list. -** -** All column names will be unique. -** -** Only the column names are computed. Column.zType, Column.zColl, -** and other fields of Column are zeroed. -** -** Return SQLITE_OK on success. If a memory allocation error occurs, -** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. -** -** The only guarantee that SQLite makes about column names is that if the -** column has an AS clause assigning it a name, that will be the name used. -** That is the only documented guarantee. However, countless applications -** developed over the years have made baseless assumptions about column names -** and will break if those assumptions changes. Hence, use extreme caution -** when modifying this routine to avoid breaking legacy. -** -** See Also: sqlite3GenerateColumnNames() -*/ -SQLITE_PRIVATE int sqlite3ColumnsFromExprList( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* Expr list from which to derive column names */ - i16 *pnCol, /* Write the number of columns here */ - Column **paCol /* Write the new column list here */ -){ - sqlite3 *db = pParse->db; /* Database connection */ - int i, j; /* Loop counters */ - u32 cnt; /* Index added to make the name unique */ - Column *aCol, *pCol; /* For looping over result columns */ - int nCol; /* Number of columns in the result set */ - char *zName; /* Column name */ - int nName; /* Size of name in zName[] */ - Hash ht; /* Hash table of column names */ - Table *pTab; - - sqlite3HashInit(&ht); - if( pEList ){ - nCol = pEList->nExpr; - aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); - testcase( aCol==0 ); - if( NEVER(nCol>32767) ) nCol = 32767; - }else{ - nCol = 0; - aCol = 0; - } - assert( nCol==(i16)nCol ); - *pnCol = nCol; - *paCol = aCol; - - for(i=0, pCol=aCol; inErr; i++, pCol++){ - struct ExprList_item *pX = &pEList->a[i]; - struct ExprList_item *pCollide; - /* Get an appropriate name for the column - */ - if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){ - /* If the column contains an "AS " phrase, use as the name */ - }else{ - Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pX->pExpr); - while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){ - pColExpr = pColExpr->pRight; - assert( pColExpr!=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].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 */ - assert( zName==pX->zEName ); /* pointer comparison intended */ - } - } - if( zName && !sqlite3IsTrueOrFalse(zName) ){ - zName = sqlite3DbStrDup(db, zName); - }else{ - zName = sqlite3MPrintf(db,"column%d",i+1); - } - - /* Make sure the column name is unique. If the name is not unique, - ** append an integer to the name so that it becomes unique. - */ - cnt = 0; - while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){ - if( pCollide->fg.bUsingTerm ){ - pCol->colFlags |= COLFLAG_NOEXPAND; - } - nName = sqlite3Strlen30(zName); - if( nName>0 ){ - for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} - if( zName[j]==':' ) nName = j; - } - zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); - sqlite3ProgressCheck(pParse); - if( cnt>3 ){ - sqlite3_randomness(sizeof(cnt), &cnt); - } - } - pCol->zCnName = zName; - pCol->hName = sqlite3StrIHash(zName); - if( pX->fg.bNoExpand ){ - pCol->colFlags |= COLFLAG_NOEXPAND; - } - sqlite3ColumnPropertiesFromName(0, pCol); - if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){ - sqlite3OomFault(db); - } - } - sqlite3HashClear(&ht); - if( pParse->nErr ){ - for(j=0; jrc; - } - return SQLITE_OK; -} - -/* -** pTab is a transient Table object that represents a subquery of some -** kind (maybe a parenthesized subquery in the FROM clause of a larger -** query, or a VIEW, or a CTE). This routine computes type information -** for that Table object based on the Select object that implements the -** subquery. For the purposes of this routine, "type information" means: -** -** * The datatype name, as it might appear in a CREATE TABLE statement -** * Which collating sequence to use for the column -** * The affinity of the column -*/ -SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( - Parse *pParse, /* Parsing contexts */ - Table *pTab, /* Add column type information to this table */ - Select *pSelect, /* SELECT used to determine types and collations */ - char aff /* Default affinity. */ -){ - sqlite3 *db = pParse->db; - Column *pCol; - CollSeq *pColl; - int i,j; - Expr *p; - struct ExprList_item *a; - NameContext sNC; - - assert( pSelect!=0 ); - assert( (pSelect->selFlags & SF_Resolved)!=0 ); - assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); - assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); - if( db->mallocFailed || IN_RENAME_OBJECT ) return; - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - a = pSelect->pEList->a; - memset(&sNC, 0, sizeof(sNC)); - sNC.pSrcList = pSelect->pSrc; - for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ - const char *zType; - i64 n; - int m = 0; - Select *pS2 = pSelect; - pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); - p = a[i].pExpr; - /* pCol->szEst = ... // Column size est for SELECT tables never used */ - pCol->affinity = sqlite3ExprAffinity(p); - while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){ - m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); - pS2 = pS2->pNext; - pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr); - } - if( pCol->affinity<=SQLITE_AFF_NONE ){ - pCol->affinity = aff; - } - if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){ - for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){ - m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); - } - if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ - pCol->affinity = SQLITE_AFF_BLOB; - }else - if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ - pCol->affinity = SQLITE_AFF_BLOB; - } - if( pCol->affinity>=SQLITE_AFF_NUMERIC && p->op==TK_CAST ){ - pCol->affinity = SQLITE_AFF_FLEXNUM; - } - } - zType = columnType(&sNC, p, 0, 0, 0); - if( zType==0 || pCol->affinity!=sqlite3AffinityType(zType, 0) ){ - if( pCol->affinity==SQLITE_AFF_NUMERIC - || pCol->affinity==SQLITE_AFF_FLEXNUM - ){ - zType = "NUM"; - }else{ - zType = 0; - for(j=1; jaffinity ){ - zType = sqlite3StdType[j]; - break; - } - } - } - } - if( zType ){ - const i64 k = sqlite3Strlen30(zType); - n = sqlite3Strlen30(pCol->zCnName); - pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); - pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); - if( pCol->zCnName ){ - memcpy(&pCol->zCnName[n+1], zType, k+1); - pCol->colFlags |= COLFLAG_HASTYPE; - } - } - pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl ){ - assert( pTab->pIndex==0 ); - sqlite3ColumnSetColl(db, pCol, pColl->zName); - } - } - pTab->szTabRow = 1; /* Any non-zero value works */ -} - -/* -** Given a SELECT statement, generate a Table structure that describes -** the result set of that SELECT. -*/ -SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){ - Table *pTab; - sqlite3 *db = pParse->db; - u64 savedFlags; - - savedFlags = db->flags; - db->flags &= ~(u64)SQLITE_FullColNames; - db->flags |= SQLITE_ShortColNames; - sqlite3SelectPrep(pParse, pSelect, 0); - db->flags = savedFlags; - if( pParse->nErr ) return 0; - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - pTab = sqlite3DbMallocZero(db, sizeof(Table) ); - if( pTab==0 ){ - return 0; - } - pTab->nTabRef = 1; - pTab->zName = 0; - pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); - sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff); - pTab->iPKey = -1; - if( db->mallocFailed ){ - sqlite3DeleteTable(db, pTab); - return 0; - } - return pTab; -} - -/* -** Get a VDBE for the given parser context. Create a new one if necessary. -** If an error occurs, return NULL and leave a message in pParse. -*/ -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ - if( pParse->pVdbe ){ - return pParse->pVdbe; - } - if( pParse->pToplevel==0 - && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) - ){ - pParse->okConstFactor = 1; - } - return sqlite3VdbeCreate(pParse); -} - - -/* -** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions -** that appear in the original SQL statement after the LIMIT and OFFSET -** keywords. Or NULL if those keywords are omitted. iLimit and iOffset -** are the integer memory register numbers for counters used to compute -** the limit and offset. If there is no limit and/or offset, then -** iLimit and iOffset are negative. -** -** This routine changes the values of iLimit and iOffset only if -** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit -** and iOffset should have been preset to appropriate default values (zero) -** prior to calling this routine. -** -** The iOffset register (if it exists) is initialized to the value -** of the OFFSET. The iLimit register is initialized to LIMIT. Register -** iOffset+1 is initialized to LIMIT+OFFSET. -** -** Only if pLimit->pLeft!=0 do the limit registers get -** redefined. The UNION ALL operator uses this property to force -** the reuse of the same limit and offset registers across multiple -** SELECT statements. -*/ -static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ - Vdbe *v = 0; - int iLimit = 0; - int iOffset; - int n; - Expr *pLimit = p->pLimit; - - if( p->iLimit ) return; - - /* - ** "LIMIT -1" always shows all rows. There is some - ** controversy about what the correct behavior should be. - ** The current implementation interprets "LIMIT 0" to mean - ** no rows. - */ - if( pLimit ){ - assert( pLimit->op==TK_LIMIT ); - assert( pLimit->pLeft!=0 ); - p->iLimit = iLimit = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){ - sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); - VdbeComment((v, "LIMIT counter")); - if( n==0 ){ - sqlite3VdbeGoto(v, iBreak); - }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){ - p->nSelectRow = sqlite3LogEst((u64)n); - p->selFlags |= SF_FixedLimit; - } - }else{ - sqlite3ExprCode(pParse, pLimit->pLeft, iLimit); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); - VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); - } - if( pLimit->pRight ){ - p->iOffset = iOffset = ++pParse->nMem; - pParse->nMem++; /* Allocate an extra register for limit+offset */ - sqlite3ExprCode(pParse, pLimit->pRight, iOffset); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); - VdbeComment((v, "OFFSET counter")); - sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); - VdbeComment((v, "LIMIT+OFFSET")); - } - } -} - -#ifndef SQLITE_OMIT_COMPOUND_SELECT -/* -** Return the appropriate collating sequence for the iCol-th column of -** the result set for the compound-select statement "p". Return NULL if -** the column has no default collating sequence. -** -** The collating sequence for the compound select is taken from the -** left-most term of the select that has a collating sequence. -*/ -static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ - CollSeq *pRet; - if( p->pPrior ){ - pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); - }else{ - pRet = 0; - } - assert( iCol>=0 ); - /* iCol must be less than p->pEList->nExpr. Otherwise an error would - ** have been thrown during name resolution and we would not have gotten - ** this far */ - if( pRet==0 && ALWAYS(iColpEList->nExpr) ){ - pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); - } - return pRet; -} - -/* -** The select statement passed as the second parameter is a compound SELECT -** with an ORDER BY clause. This function allocates and returns a KeyInfo -** structure suitable for implementing the ORDER BY. -** -** Space to hold the KeyInfo structure is obtained from malloc. The calling -** function is responsible for ensuring that this structure is eventually -** freed. -*/ -static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ - ExprList *pOrderBy = p->pOrderBy; - int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; - sqlite3 *db = pParse->db; - KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); - if( pRet ){ - int i; - for(i=0; ia[i]; - Expr *pTerm = pItem->pExpr; - CollSeq *pColl; - - if( pTerm->flags & EP_Collate ){ - pColl = sqlite3ExprCollSeq(pParse, pTerm); - }else{ - pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1); - if( pColl==0 ) pColl = db->pDfltColl; - pOrderBy->a[i].pExpr = - sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); - } - assert( sqlite3KeyInfoIsWriteable(pRet) ); - pRet->aColl[i] = pColl; - pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags; - } - } - - return pRet; -} - -#ifndef SQLITE_OMIT_CTE -/* -** This routine generates VDBE code to compute the content of a WITH RECURSIVE -** query of the form: -** -** AS ( UNION [ALL] ) -** \___________/ \_______________/ -** p->pPrior p -** -** -** There is exactly one reference to the recursive-table in the FROM clause -** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag. -** -** The setup-query runs once to generate an initial set of rows that go -** into a Queue table. Rows are extracted from the Queue table one by -** one. Each row extracted from Queue is output to pDest. Then the single -** extracted row (now in the iCurrent table) becomes the content of the -** recursive-table for a recursive-query run. The output of the recursive-query -** is added back into the Queue table. Then another row is extracted from Queue -** and the iteration continues until the Queue table is empty. -** -** If the compound query operator is UNION then no duplicate rows are ever -** inserted into the Queue table. The iDistinct table keeps a copy of all rows -** that have ever been inserted into Queue and causes duplicates to be -** discarded. If the operator is UNION ALL, then duplicates are allowed. -** -** If the query has an ORDER BY, then entries in the Queue table are kept in -** ORDER BY order and the first entry is extracted for each cycle. Without -** an ORDER BY, the Queue table is just a FIFO. -** -** If a LIMIT clause is provided, then the iteration stops after LIMIT rows -** have been output to pDest. A LIMIT of zero means to output no rows and a -** negative LIMIT means to output all rows. If there is also an OFFSET clause -** with a positive value, then the first OFFSET outputs are discarded rather -** than being sent to pDest. The LIMIT count does not begin until after OFFSET -** rows have been skipped. -*/ -static void generateWithRecursiveQuery( - Parse *pParse, /* Parsing context */ - Select *p, /* The recursive SELECT to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */ - int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */ - Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ - Select *pSetup; /* The setup query */ - Select *pFirstRec; /* Left-most recursive term */ - int addrTop; /* Top of the loop */ - int addrCont, addrBreak; /* CONTINUE and BREAK addresses */ - int iCurrent = 0; /* The Current table */ - int regCurrent; /* Register holding Current table */ - int iQueue; /* The Queue table */ - int iDistinct = 0; /* To ensure unique results if UNION */ - int eDest = SRT_Fifo; /* How to write to Queue */ - SelectDest destQueue; /* SelectDest targeting the Queue table */ - int i; /* Loop counter */ - int rc; /* Result code */ - ExprList *pOrderBy; /* The ORDER BY clause */ - Expr *pLimit; /* Saved LIMIT and OFFSET */ - int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ){ - sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries"); - return; - } -#endif - - /* Obtain authorization to do a recursive query */ - if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; - - /* Process the LIMIT and OFFSET clauses, if they exist */ - addrBreak = sqlite3VdbeMakeLabel(pParse); - p->nSelectRow = 320; /* 4 billion rows */ - computeLimitRegisters(pParse, p, addrBreak); - pLimit = p->pLimit; - regLimit = p->iLimit; - regOffset = p->iOffset; - p->pLimit = 0; - p->iLimit = p->iOffset = 0; - pOrderBy = p->pOrderBy; - - /* Locate the cursor number of the Current table */ - for(i=0; ALWAYS(inSrc); i++){ - if( pSrc->a[i].fg.isRecursive ){ - iCurrent = pSrc->a[i].iCursor; - break; - } - } - - /* Allocate cursors numbers for Queue and Distinct. The cursor number for - ** the Distinct table must be exactly one greater than Queue in order - ** for the SRT_DistFifo and SRT_DistQueue destinations to work. */ - iQueue = pParse->nTab++; - if( p->op==TK_UNION ){ - eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo; - iDistinct = pParse->nTab++; - }else{ - eDest = pOrderBy ? SRT_Queue : SRT_Fifo; - } - sqlite3SelectDestInit(&destQueue, eDest, iQueue); - - /* Allocate cursors for Current, Queue, and Distinct. */ - regCurrent = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); - if( pOrderBy ){ - KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, - (char*)pKeyInfo, P4_KEYINFO); - destQueue.pOrderBy = pOrderBy; - }else{ - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol); - } - VdbeComment((v, "Queue table")); - if( iDistinct ){ - p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); - p->selFlags |= SF_UsesEphemeral; - } - - /* Detach the ORDER BY clause from the compound SELECT */ - p->pOrderBy = 0; - - /* Figure out how many elements of the compound SELECT are part of the - ** recursive query. Make sure no recursive elements use aggregate - ** functions. Mark the recursive elements as UNION ALL even if they - ** are really UNION because the distinctness will be enforced by the - ** iDistinct table. pFirstRec is left pointing to the left-most - ** recursive term of the CTE. - */ - for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){ - if( pFirstRec->selFlags & SF_Aggregate ){ - sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); - goto end_of_recursive_query; - } - pFirstRec->op = TK_ALL; - if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break; - } - - /* Store the results of the setup-query in Queue. */ - pSetup = pFirstRec->pPrior; - pSetup->pNext = 0; - ExplainQueryPlan((pParse, 1, "SETUP")); - rc = sqlite3Select(pParse, pSetup, &destQueue); - pSetup->pNext = p; - if( rc ) goto end_of_recursive_query; - - /* Find the next row in the Queue and output that row */ - addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v); - - /* Transfer the next row in Queue over to Current */ - sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */ - if( pOrderBy ){ - sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent); - }else{ - sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent); - } - sqlite3VdbeAddOp1(v, OP_Delete, iQueue); - - /* Output the single row in Current */ - addrCont = sqlite3VdbeMakeLabel(pParse); - codeOffset(v, regOffset, addrCont); - selectInnerLoop(pParse, p, iCurrent, - 0, 0, pDest, addrCont, addrBreak); - if( regLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); - VdbeCoverage(v); - } - sqlite3VdbeResolveLabel(v, addrCont); - - /* Execute the recursive SELECT taking the single row in Current as - ** the value for the recursive-table. Store the results in the Queue. - */ - pFirstRec->pPrior = 0; - ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); - sqlite3Select(pParse, p, &destQueue); - assert( pFirstRec->pPrior==0 ); - pFirstRec->pPrior = pSetup; - - /* Keep running the loop until the Queue is empty */ - sqlite3VdbeGoto(v, addrTop); - sqlite3VdbeResolveLabel(v, addrBreak); - -end_of_recursive_query: - sqlite3ExprListDelete(pParse->db, p->pOrderBy); - p->pOrderBy = pOrderBy; - p->pLimit = pLimit; - return; -} -#endif /* SQLITE_OMIT_CTE */ - -/* Forward references */ -static int multiSelectOrderBy( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -); - -/* -** Handle the special case of a compound-select that originates from a -** VALUES clause. By handling this as a special case, we avoid deep -** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT -** on a VALUES clause. -** -** Because the Select object originates from a VALUES clause: -** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1 -** (2) All terms are UNION ALL -** (3) There is no ORDER BY clause -** -** 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 sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case. -** Since the limit is exactly 1, we only need to evaluate the left-most VALUES. -*/ -static int multiSelectValues( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - int nRow = 1; - int rc = 0; - int bShowAll = p->pLimit==0; - assert( p->selFlags & SF_MultiValue ); - do{ - assert( p->selFlags & SF_Values ); - assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); - assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ) return -1; -#endif - if( p->pPrior==0 ) break; - assert( p->pPrior->pNext==p ); - p = p->pPrior; - nRow += bShowAll; - }while(1); - ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, - nRow==1 ? "" : "S")); - while( p ){ - selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); - if( !bShowAll ) break; - p->nSelectRow = nRow; - p = p->pNext; - } - return rc; -} - -/* -** Return true if the SELECT statement which is known to be the recursive -** part of a recursive CTE still has its anchor terms attached. If the -** anchor terms have already been removed, then return false. -*/ -static int hasAnchor(Select *p){ - while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; } - return p!=0; -} - -/* -** This routine is called to process a compound query form from -** two or more separate queries using UNION, UNION ALL, EXCEPT, or -** INTERSECT -** -** "p" points to the right-most of the two queries. the query on the -** left is p->pPrior. The left query could also be a compound query -** in which case this routine will be called recursively. -** -** The results of the total query are to be written into a destination -** of type eDest with parameter iParm. -** -** Example 1: Consider a three-way compound SQL statement. -** -** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 -** -** This statement is parsed up as follows: -** -** SELECT c FROM t3 -** | -** `-----> SELECT b FROM t2 -** | -** `------> SELECT a FROM t1 -** -** The arrows in the diagram above represent the Select.pPrior pointer. -** So if this routine is called with p equal to the t3 query, then -** pPrior will be the t2 query. p->op will be TK_UNION in this case. -** -** Notice that because of the way SQLite parses compound SELECTs, the -** individual selects always group from left to right. -*/ -static int multiSelect( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - int rc = SQLITE_OK; /* Success code from a subroutine */ - Select *pPrior; /* Another SELECT immediately to our left */ - Vdbe *v; /* Generate code to this VDBE */ - SelectDest dest; /* Alternative data destination */ - Select *pDelete = 0; /* Chain of simple selects to delete */ - sqlite3 *db; /* Database connection */ - - /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only - ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. - */ - assert( p && p->pPrior ); /* Calling function guarantees this much */ - assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION ); - assert( p->selFlags & SF_Compound ); - db = pParse->db; - pPrior = p->pPrior; - dest = *pDest; - assert( pPrior->pOrderBy==0 ); - assert( pPrior->pLimit==0 ); - - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); /* The VDBE already created by calling function */ - - /* Create the destination temporary table if necessary - */ - if( dest.eDest==SRT_EphemTab ){ - assert( p->pEList ); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr); - dest.eDest = SRT_Table; - } - - /* Special handling for a compound-select that originates as a VALUES clause. - */ - if( p->selFlags & SF_MultiValue ){ - rc = multiSelectValues(pParse, p, &dest); - if( rc>=0 ) goto multi_select_end; - rc = SQLITE_OK; - } - - /* Make sure all SELECTs in the statement have the same number of elements - ** in their result sets. - */ - assert( p->pEList && pPrior->pEList ); - assert( p->pEList->nExpr==pPrior->pEList->nExpr ); - -#ifndef SQLITE_OMIT_CTE - if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){ - generateWithRecursiveQuery(pParse, p, &dest); - }else -#endif - - /* Compound SELECTs that have an ORDER BY clause are handled separately. - */ - if( p->pOrderBy ){ - return multiSelectOrderBy(pParse, p, pDest); - }else{ - -#ifndef SQLITE_OMIT_EXPLAIN - if( pPrior->pPrior==0 ){ - ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); - ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); - } -#endif - - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - int addr = 0; - int nLimit = 0; /* Initialize to suppress harmless compiler warning */ - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = p->pLimit; - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); - rc = sqlite3Select(pParse, pPrior, &dest); - pPrior->pLimit = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); - } - } - ExplainQueryPlan((pParse, 1, "UNION ALL")); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( p->pLimit - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - } - break; - } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temp table holding result */ - u8 op = 0; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - Expr *pLimit; /* Saved values of p->nLimit */ - int addr; - SelectDest uniondest; - - testcase( p->op==TK_EXCEPT ); - testcase( p->op==TK_UNION ); - priorOp = SRT_Union; - if( dest.eDest==priorOp ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. - */ - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ - unionTab = dest.iSDParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. - */ - unionTab = pParse->nTab++; - assert( p->pOrderBy==0 ); - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - } - - - /* Code the SELECT statements to our left - */ - assert( !pPrior->pOrderBy ); - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); - rc = sqlite3Select(pParse, pPrior, &uniondest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT statement - */ - if( p->op==TK_EXCEPT ){ - op = SRT_Except; - }else{ - assert( p->op==TK_UNION ); - op = SRT_Union; - } - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - uniondest.eDest = op; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - sqlite3SelectOpName(p->op))); - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); - rc = sqlite3Select(pParse, p, &uniondest); - testcase( rc!=SQLITE_OK ); - assert( p->pOrderBy==0 ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->pOrderBy = 0; - if( p->op==TK_UNION ){ - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->iLimit = 0; - p->iOffset = 0; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); - assert( p->pEList || db->mallocFailed ); - if( dest.eDest!=priorOp && db->mallocFailed==0 ){ - int iCont, iBreak, iStart; - iBreak = sqlite3VdbeMakeLabel(pParse); - iCont = sqlite3VdbeMakeLabel(pParse); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); - iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, unionTab, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); - } - break; - } - default: assert( p->op==TK_INTERSECT ); { - int tab1, tab2; - int iCont, iBreak, iStart; - Expr *pLimit; - int addr; - SelectDest intersectdest; - int r1; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - assert( p->pOrderBy==0 ); - - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); - rc = sqlite3Select(pParse, pPrior, &intersectdest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT into temporary table "tab2" - */ - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); - assert( p->addrOpenEphm[1] == -1 ); - p->addrOpenEphm[1] = addr; - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - intersectdest.iSDParm = tab2; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - sqlite3SelectOpName(p->op))); - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); - rc = sqlite3Select(pParse, p, &intersectdest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - if( p->nSelectRow>pPrior->nSelectRow ){ - p->nSelectRow = pPrior->nSelectRow; - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - if( rc ) break; - assert( p->pEList ); - iBreak = sqlite3VdbeMakeLabel(pParse); - iCont = sqlite3VdbeMakeLabel(pParse); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); - r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, tab1, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); - break; - } - } - - #ifndef SQLITE_OMIT_EXPLAIN - if( p->pNext==0 ){ - ExplainQueryPlanPop(pParse); - } - #endif - } - if( pParse->nErr ) goto multi_select_end; - - /* Compute collating sequences used by - ** temporary tables needed to implement the compound select. - ** Attach the KeyInfo structure to all temporary tables. - ** - ** This section is run by the right-most SELECT statement only. - ** SELECT statements to the left always skip this part. The right-most - ** SELECT might also skip this part if it has no ORDER BY clause and - ** no temp tables are required. - */ - if( p->selFlags & SF_UsesEphemeral ){ - int i; /* Loop counter */ - KeyInfo *pKeyInfo; /* Collating sequence for the result set */ - Select *pLoop; /* For looping through SELECT statements */ - CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ - int nCol; /* Number of columns in result set */ - - assert( p->pNext==0 ); - assert( p->pEList!=0 ); - nCol = p->pEList->nExpr; - pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); - if( !pKeyInfo ){ - rc = SQLITE_NOMEM_BKPT; - goto multi_select_end; - } - for(i=0, apColl=pKeyInfo->aColl; ipDfltColl; - } - } - - for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ - for(i=0; i<2; i++){ - int addr = pLoop->addrOpenEphm[i]; - if( addr<0 ){ - /* If [0] is unused then [1] is also unused. So we can - ** always safely abort as soon as the first unused slot is found */ - assert( pLoop->addrOpenEphm[1]<0 ); - break; - } - sqlite3VdbeChangeP2(v, addr, nCol); - sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo), - P4_KEYINFO); - pLoop->addrOpenEphm[i] = -1; - } - } - sqlite3KeyInfoUnref(pKeyInfo); - } - -multi_select_end: - pDest->iSdst = dest.iSdst; - pDest->nSdst = dest.nSdst; - pDest->iSDParm2 = dest.iSDParm2; - if( pDelete ){ - sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete); - } - return rc; -} -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ - -/* -** Error message for when two or more terms of a compound select have different -** size result sets. -*/ -SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ - if( p->selFlags & SF_Values ){ - sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); - }else{ - sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", - sqlite3SelectOpName(p->op)); - } -} - -/* -** Code an output subroutine for a coroutine implementation of a -** SELECT statement. -** -** The data to be output is contained in pIn->iSdst. There are -** pIn->nSdst columns to be output. pDest is where the output should -** be sent. -** -** regReturn is the number of the register holding the subroutine -** return address. -** -** If regPrev>0 then it is the first register in a vector that -** records the previous output. mem[regPrev] is a flag that is false -** if there has been no previous output. If regPrev>0 then code is -** generated to suppress duplicates. pKeyInfo is used for comparing -** keys. -** -** If the LIMIT found in p->iLimit is reached, jump immediately to -** iBreak. -*/ -static int generateOutputSubroutine( - Parse *pParse, /* Parsing context */ - Select *p, /* The SELECT statement */ - SelectDest *pIn, /* Coroutine supplying data */ - SelectDest *pDest, /* Where to send the data */ - int regReturn, /* The return address register */ - int regPrev, /* Previous result register. No uniqueness if 0 */ - KeyInfo *pKeyInfo, /* For comparing with previous entry */ - int iBreak /* Jump here if we hit the LIMIT */ -){ - Vdbe *v = pParse->pVdbe; - int iContinue; - int addr; - - addr = sqlite3VdbeCurrentAddr(v); - iContinue = sqlite3VdbeMakeLabel(pParse); - - /* Suppress duplicates for UNION, EXCEPT, and INTERSECT - */ - if( regPrev ){ - int addr1, addr2; - addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); - addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, - (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); - } - if( pParse->db->mallocFailed ) return 0; - - /* Suppress the first OFFSET entries if there is an OFFSET clause - */ - codeOffset(v, p->iOffset, iContinue); - - assert( pDest->eDest!=SRT_Exists ); - assert( pDest->eDest!=SRT_Table ); - switch( pDest->eDest ){ - /* Store the result as data using a unique key. - */ - case SRT_EphemTab: { - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); - sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3ReleaseTempReg(pParse, r2); - sqlite3ReleaseTempReg(pParse, r1); - break; - } - -#ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)". - */ - case SRT_Set: { - int r1; - testcase( pIn->nSdst>1 ); - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, - r1, pDest->zAffSdst, pIn->nSdst); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, - pIn->iSdst, pIn->nSdst); - if( pDest->iSDParm2>0 ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, - pIn->iSdst, pIn->nSdst); - ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); - } - sqlite3ReleaseTempReg(pParse, r1); - break; - } - - /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. Note that the select might return multiple columns - ** if it is the RHS of a row-value IN operator. - */ - case SRT_Mem: { - testcase( pIn->nSdst>1 ); - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst); - /* The LIMIT clause will jump out of the loop for us */ - break; - } -#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ - - /* The results are stored in a sequence of registers - ** starting at pDest->iSdst. Then the co-routine yields. - */ - case SRT_Coroutine: { - if( pDest->iSdst==0 ){ - pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); - pDest->nSdst = pIn->nSdst; - } - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - break; - } - - /* If none of the above, then the result destination must be - ** SRT_Output. This routine is never called with any other - ** destination other than the ones handled above or SRT_Output. - ** - ** For SRT_Output, results are stored in a sequence of registers. - ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to - ** return the next row of result. - */ - default: { - assert( pDest->eDest==SRT_Output ); - sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); - break; - } - } - - /* Jump to the end of the loop if the LIMIT is reached. - */ - if( p->iLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); - } - - /* Generate the subroutine return - */ - sqlite3VdbeResolveLabel(v, iContinue); - sqlite3VdbeAddOp1(v, OP_Return, regReturn); - - return addr; -} - -/* -** Alternative compound select code generator for cases when there -** is an ORDER BY clause. -** -** We assume a query of the following form: -** -** ORDER BY -** -** is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea -** is to code both and with the ORDER BY clause as -** co-routines. Then run the co-routines in parallel and merge the results -** into the output. In addition to the two coroutines (called selectA and -** selectB) there are 7 subroutines: -** -** outA: Move the output of the selectA coroutine into the output -** of the compound query. -** -** outB: Move the output of the selectB coroutine into the output -** of the compound query. (Only generated for UNION and -** UNION ALL. EXCEPT and INSERTSECT never output a row that -** appears only in B.) -** -** AltB: Called when there is data from both coroutines and AB. -** -** EofA: Called when data is exhausted from selectA. -** -** EofB: Called when data is exhausted from selectB. -** -** The implementation of the latter five subroutines depend on which -** is used: -** -** -** UNION ALL UNION EXCEPT INTERSECT -** ------------- ----------------- -------------- ----------------- -** AltB: outA, nextA outA, nextA outA, nextA nextA -** -** AeqB: outA, nextA nextA nextA outA, nextA -** -** AgtB: outB, nextB outB, nextB nextB nextB -** -** EofA: outB, nextB outB, nextB halt halt -** -** EofB: outA, nextA outA, nextA outA, nextA halt -** -** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA -** causes an immediate jump to EofA and an EOF on B following nextB causes -** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or -** following nextX causes a jump to the end of the select processing. -** -** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled -** within the output subroutine. The regPrev register set holds the previously -** output value. A comparison is made against this value and the output -** is skipped if the next results would be the same as the previous. -** -** The implementation plan is to implement the two coroutines and seven -** subroutines first, then put the control logic at the bottom. Like this: -** -** goto Init -** coA: coroutine for left query (A) -** coB: coroutine for right query (B) -** outA: output one row of A -** outB: output one row of B (UNION and UNION ALL only) -** EofA: ... -** EofB: ... -** AltB: ... -** AeqB: ... -** AgtB: ... -** Init: initialize coroutine registers -** yield coA -** if eof(A) goto EofA -** yield coB -** if eof(B) goto EofB -** Cmpr: Compare A, B -** Jump AltB, AeqB, AgtB -** End: ... -** -** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not -** actually called using Gosub and they do not Return. EofA and EofB loop -** until all data is exhausted then jump to the "end" label. AltB, AeqB, -** and AgtB jump to either L2 or to one of EofA or EofB. -*/ -#ifndef SQLITE_OMIT_COMPOUND_SELECT -static int multiSelectOrderBy( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - 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 */ - int regAddrA; /* Address register for select-A coroutine */ - int regAddrB; /* Address register for select-B coroutine */ - int addrSelectA; /* Address of the select-A coroutine */ - int addrSelectB; /* Address of the select-B coroutine */ - int regOutA; /* Address register for the output-A subroutine */ - int regOutB; /* Address register for the output-B subroutine */ - int addrOutA; /* Address of the output-A subroutine */ - int addrOutB = 0; /* Address of the output-B subroutine */ - int addrEofA; /* Address of the select-A-exhausted subroutine */ - int addrEofA_noB; /* Alternate addrEofA if B is uninitialized */ - int addrEofB; /* Address of the select-B-exhausted subroutine */ - int addrAltB; /* Address of the AB subroutine */ - int regLimitA; /* Limit register for select-A */ - int regLimitB; /* Limit register for select-A */ - int regPrev; /* A range of registers to hold previous output */ - int savedLimit; /* Saved value of p->iLimit */ - int savedOffset; /* Saved value of p->iOffset */ - int labelCmpr; /* Label for the start of the merge algorithm */ - int labelEnd; /* Label for the end of the overall SELECT stmt */ - int addr1; /* Jump instructions that get retargeted */ - int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ - KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ - KeyInfo *pKeyMerge; /* Comparison information for merging rows */ - sqlite3 *db; /* Database connection */ - ExprList *pOrderBy; /* The ORDER BY clause */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - u32 *aPermute; /* Mapping from ORDER BY terms to result set columns */ - - assert( p->pOrderBy!=0 ); - assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ - db = pParse->db; - v = pParse->pVdbe; - assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */ - labelEnd = sqlite3VdbeMakeLabel(pParse); - labelCmpr = sqlite3VdbeMakeLabel(pParse); - - - /* Patch up the ORDER BY clause - */ - op = p->op; - assert( p->pPrior->pOrderBy==0 ); - pOrderBy = p->pOrderBy; - assert( pOrderBy ); - nOrderBy = pOrderBy->nExpr; - - /* For operators other than UNION ALL we have to make sure that - ** the ORDER BY clause covers every term of the result set. Add - ** terms to the ORDER BY clause as necessary. - */ - if( op!=TK_ALL ){ - for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){ - struct ExprList_item *pItem; - for(j=0, pItem=pOrderBy->a; ju.x.iOrderByCol>0 ); - if( pItem->u.x.iOrderByCol==i ) break; - } - if( j==nOrderBy ){ - Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); - if( pNew==0 ) return SQLITE_NOMEM_BKPT; - pNew->flags |= EP_IntValue; - pNew->u.iValue = i; - p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); - if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i; - } - } - } - - /* Compute the comparison permutation and keyinfo that is used with - ** the permutation used to determine if the next - ** row of results comes from selectA or selectB. Also add explicit - ** collations to the ORDER BY clause terms so that when the subqueries - ** to the right and the left are evaluated, they use the correct - ** collation. - */ - aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); - if( aPermute ){ - 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; - } - pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); - }else{ - pKeyMerge = 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). - */ - if( op==TK_ALL ){ - regPrev = 0; - }else{ - int nExpr = p->pEList->nExpr; - assert( nOrderBy>=nExpr || db->mallocFailed ); - regPrev = pParse->nMem+1; - pParse->nMem += nExpr+1; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); - pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1); - if( pKeyDup ){ - assert( sqlite3KeyInfoIsWriteable(pKeyDup) ); - for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); - pKeyDup->aSortFlags[i] = 0; - } - } - } - - /* Separate the left and the right query from one another - */ - 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; ipPrior; } - } - pPrior = pSplit->pPrior; - assert( pPrior!=0 ); - pSplit->pPrior = 0; - pPrior->pNext = 0; - assert( p->pOrderBy == pOrderBy ); - assert( pOrderBy!=0 || db->mallocFailed ); - pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); - sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); - sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); - - /* Compute the limit registers */ - computeLimitRegisters(pParse, p, labelEnd); - if( p->iLimit && op==TK_ALL ){ - regLimitA = ++pParse->nMem; - regLimitB = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit, - regLimitA); - sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB); - }else{ - regLimitA = regLimitB = 0; - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = 0; - - regAddrA = ++pParse->nMem; - regAddrB = ++pParse->nMem; - regOutA = ++pParse->nMem; - regOutB = ++pParse->nMem; - sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); - sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); - - ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op))); - - /* Generate a coroutine to evaluate the SELECT statement to the - ** left of the compound operator - the "A" select. - */ - addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; - addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); - VdbeComment((v, "left SELECT")); - pPrior->iLimit = regLimitA; - ExplainQueryPlan((pParse, 1, "LEFT")); - sqlite3Select(pParse, pPrior, &destA); - sqlite3VdbeEndCoroutine(v, regAddrA); - sqlite3VdbeJumpHere(v, addr1); - - /* Generate a coroutine to evaluate the SELECT statement on - ** the right - the "B" select - */ - addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; - addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); - VdbeComment((v, "right SELECT")); - savedLimit = p->iLimit; - savedOffset = p->iOffset; - p->iLimit = regLimitB; - p->iOffset = 0; - ExplainQueryPlan((pParse, 1, "RIGHT")); - sqlite3Select(pParse, p, &destB); - p->iLimit = savedLimit; - p->iOffset = savedOffset; - sqlite3VdbeEndCoroutine(v, regAddrB); - - /* Generate a subroutine that outputs the current row of the A - ** select as the next output row of the compound select. - */ - VdbeNoopComment((v, "Output routine for A")); - addrOutA = generateOutputSubroutine(pParse, - p, &destA, pDest, regOutA, - regPrev, pKeyDup, labelEnd); - - /* Generate a subroutine that outputs the current row of the B - ** select as the next output row of the compound select. - */ - if( op==TK_ALL || op==TK_UNION ){ - VdbeNoopComment((v, "Output routine for B")); - addrOutB = generateOutputSubroutine(pParse, - p, &destB, pDest, regOutB, - regPrev, pKeyDup, labelEnd); - } - sqlite3KeyInfoUnref(pKeyDup); - - /* Generate a subroutine to run when the results from select A - ** are exhausted and only data in select B remains. - */ - if( op==TK_EXCEPT || op==TK_INTERSECT ){ - addrEofA_noB = addrEofA = labelEnd; - }else{ - VdbeNoopComment((v, "eof-A subroutine")); - addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); - VdbeCoverage(v); - sqlite3VdbeGoto(v, addrEofA); - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - } - - /* Generate a subroutine to run when the results from select B - ** are exhausted and only data in select A remains. - */ - if( op==TK_INTERSECT ){ - addrEofB = addrEofA; - if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - }else{ - VdbeNoopComment((v, "eof-B subroutine")); - addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrEofB); - } - - /* Generate code to handle the case of AB - */ - VdbeNoopComment((v, "A-gt-B subroutine")); - addrAgtB = sqlite3VdbeCurrentAddr(v); - if( op==TK_ALL || op==TK_UNION ){ - sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - } - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - sqlite3VdbeGoto(v, labelCmpr); - - /* This code runs once to initialize everything. - */ - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - - /* Implement the main merge loop - */ - sqlite3VdbeResolveLabel(v, labelCmpr); - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); - sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, - (char*)pKeyMerge, P4_KEYINFO); - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); - - /* Jump to the this point in order to terminate the query. - */ - sqlite3VdbeResolveLabel(v, labelEnd); - - /* Make arrangements to free the 2nd and subsequent arms of the compound - ** after the parse has finished */ - if( pSplit->pPrior ){ - sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior); - } - pSplit->pPrior = pPrior; - pPrior->pNext = pSplit; - sqlite3ExprListDelete(db, pPrior->pOrderBy); - pPrior->pOrderBy = 0; - - /*** TBD: Insert subroutine calls to close cursors on incomplete - **** subqueries ****/ - ExplainQueryPlanPop(pParse); - return pParse->nErr!=0; -} -#endif - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - -/* An instance of the SubstContext object describes an substitution edit -** to be performed on a parse tree. -** -** 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 is an 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 isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ - ExprList *pEList; /* Replacement expressions */ - ExprList *pCList; /* Collation sequences for replacement expr */ -} SubstContext; - -/* Forward Declarations */ -static void substExprList(SubstContext*, ExprList*); -static void substSelect(SubstContext*, Select*, int); - -/* -** Scan through the expression pExpr. Replace every reference to -** a column in table number iTable with a copy of the iColumn-th -** entry in pEList. (But leave references to the ROWID column -** unchanged.) -** -** This routine is part of the flattening procedure. A subquery -** whose result set is defined by pEList appears as entry in the -** FROM clause of a SELECT such that the VDBE cursor assigned to that -** FORM clause entry is iTable. This routine makes the necessary -** changes to pExpr so that it refers directly to the source table -** of the subquery rather the result set of the subquery. -*/ -static Expr *substExpr( - SubstContext *pSubst, /* Description of the substitution */ - Expr *pExpr /* Expr in which substitution occurs */ -){ - if( pExpr==0 ) return 0; - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) - && pExpr->w.iJoin==pSubst->iTable - ){ - 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 -#endif - { - Expr *pNew; - int iColumn; - Expr *pCopy; - Expr ifNullRow; - iColumn = pExpr->iColumn; - assert( iColumn>=0 ); - assert( pSubst->pEList!=0 && iColumnpEList->nExpr ); - assert( pExpr->pRight==0 ); - pCopy = pSubst->pEList->a[iColumn].pExpr; - if( sqlite3ExprIsVector(pCopy) ){ - sqlite3VectorErrorMsg(pSubst->pParse, pCopy); - }else{ - sqlite3 *db = pSubst->pParse->db; - if( pSubst->isOuterJoin - && (pCopy->op!=TK_COLUMN || pCopy->iTable!=pSubst->iNewTable) - ){ - memset(&ifNullRow, 0, sizeof(ifNullRow)); - ifNullRow.op = TK_IF_NULL_ROW; - ifNullRow.pLeft = pCopy; - ifNullRow.iTable = pSubst->iNewTable; - ifNullRow.iColumn = -99; - ifNullRow.flags = EP_IfNullRow; - pCopy = &ifNullRow; - } - testcase( ExprHasProperty(pCopy, EP_Subquery) ); - pNew = sqlite3ExprDup(db, pCopy, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pNew); - return pExpr; - } - if( pSubst->isOuterJoin ){ - ExprSetProperty(pNew, EP_CanBeNull); - } - if( pNew->op==TK_TRUEFALSE ){ - pNew->u.iValue = sqlite3ExprTruthValue(pNew); - pNew->op = TK_INTEGER; - ExprSetProperty(pNew, 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. */ - { - CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew); - CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, - pSubst->pCList->a[iColumn].pExpr - ); - if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){ - pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew, - (pColl ? pColl->zName : "BINARY") - ); - } - } - ExprClearProperty(pNew, EP_Collate); - if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){ - sqlite3SetJoinExpr(pNew, pExpr->w.iJoin, - pExpr->flags & (EP_OuterON|EP_InnerON)); - } - sqlite3ExprDelete(db, pExpr); - pExpr = pNew; - } - } - }else{ - if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){ - pExpr->iTable = pSubst->iNewTable; - } - pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); - pExpr->pRight = substExpr(pSubst, pExpr->pRight); - if( ExprUseXSelect(pExpr) ){ - substSelect(pSubst, pExpr->x.pSelect, 1); - }else{ - substExprList(pSubst, pExpr->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window *pWin = pExpr->y.pWin; - pWin->pFilter = substExpr(pSubst, pWin->pFilter); - substExprList(pSubst, pWin->pPartition); - substExprList(pSubst, pWin->pOrderBy); - } -#endif - } - return pExpr; -} -static void substExprList( - SubstContext *pSubst, /* Description of the substitution */ - ExprList *pList /* List to scan and in which to make substitutes */ -){ - int i; - if( pList==0 ) return; - for(i=0; inExpr; i++){ - pList->a[i].pExpr = substExpr(pSubst, pList->a[i].pExpr); - } -} -static void substSelect( - SubstContext *pSubst, /* Description of the substitution */ - Select *p, /* SELECT statement in which to make substitutions */ - int doPrior /* Do substitutes on p->pPrior too */ -){ - SrcList *pSrc; - SrcItem *pItem; - int i; - if( !p ) return; - do{ - substExprList(pSubst, p->pEList); - substExprList(pSubst, p->pGroupBy); - substExprList(pSubst, p->pOrderBy); - p->pHaving = substExpr(pSubst, p->pHaving); - p->pWhere = substExpr(pSubst, p->pWhere); - pSrc = p->pSrc; - assert( pSrc!=0 ); - for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( pItem->fg.isSubquery ){ - substSelect(pSubst, pItem->u4.pSubq->pSelect, 1); - } - if( pItem->fg.isTabFunc ){ - substExprList(pSubst, pItem->u1.pFuncArg); - } - } - }while( doPrior && (p = p->pPrior)!=0 ); -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* -** pSelect is a SELECT statement and pSrcItem is one item in the FROM -** clause of that SELECT. -** -** This routine scans the entire SELECT statement and recomputes the -** pSrcItem->colUsed mask. -*/ -static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){ - SrcItem *pItem; - if( pExpr->op!=TK_COLUMN ) return WRC_Continue; - pItem = pWalker->u.pSrcItem; - if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue; - if( pExpr->iColumn<0 ) return WRC_Continue; - pItem->colUsed |= sqlite3ExprColUsed(pExpr); - return WRC_Continue; -} -static void recomputeColumnsUsed( - Select *pSelect, /* The complete SELECT statement */ - SrcItem *pSrcItem /* Which FROM clause item to recompute */ -){ - Walker w; - if( NEVER(pSrcItem->pSTab==0) ) return; - memset(&w, 0, sizeof(w)); - w.xExprCallback = recomputeColumnsUsedExpr; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.u.pSrcItem = pSrcItem; - pSrcItem->colUsed = 0; - sqlite3WalkSelect(&w, pSelect); -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -#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; inSrc; 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]; - if( pItem->fg.isSubquery ){ - for(p=pItem->u4.pSubq->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 = sqlite3SelectWalkNoop; - sqlite3WalkSelect(&w, p); -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -/* -** If pSel is not part of a compound SELECT, return a pointer to its -** expression list. Otherwise, return a pointer to the expression list -** of the leftmost SELECT in the compound. -*/ -static ExprList *findLeftmostExprlist(Select *pSel){ - while( pSel->pPrior ){ - pSel = pSel->pPrior; - } - return pSel->pEList; -} - -/* -** Return true if any of the result-set columns in the compound query -** have incompatible affinities on one or more arms of the compound. -*/ -static int compoundHasDifferentAffinities(Select *p){ - int ii; - ExprList *pList; - assert( p!=0 ); - assert( p->pEList!=0 ); - assert( p->pPrior!=0 ); - pList = p->pEList; - for(ii=0; iinExpr; ii++){ - char aff; - Select *pSub1; - assert( pList->a[ii].pExpr!=0 ); - aff = sqlite3ExprAffinity(pList->a[ii].pExpr); - for(pSub1=p->pPrior; pSub1; pSub1=pSub1->pPrior){ - assert( pSub1->pEList!=0 ); - assert( pSub1->pEList->nExpr>ii ); - assert( pSub1->pEList->a[ii].pExpr!=0 ); - if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){ - return 1; - } - } - } - return 0; -} - -#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. -** -** To understand the concept of flattening, consider the following -** query: -** -** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 -** -** The default way of implementing this query is to execute the -** subquery first and store the results in a temporary table, then -** run the outer query on that temporary table. This requires two -** passes over the data. Furthermore, because the temporary table -** has no indices, the WHERE clause on the outer query cannot be -** optimized. -** -** This routine attempts to rewrite queries such as the above into -** a single flat select, like this: -** -** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 -** -** The code generated for this simplification gives the same result -** but only has to scan the data once. And because indices might -** exist on the table t1, a complete scan of the data might be -** avoided. -** -** Flattening is subject to the following constraints: -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** The subquery and the outer query cannot both be aggregates. -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** (2) If the subquery is an aggregate then -** (2a) the outer query must not be a join and -** (2b) the outer query must not use subqueries -** other than the one FROM-clause subquery that is a candidate -** for flattening. (This is due to ticket [2f7170d73bf9abf80] -** from 2015-02-09.) -** -** (3) If the subquery is the right operand of a LEFT JOIN then -** (3a) the subquery may not be a join -** (**) Was (3b): "the FROM clause of the subquery may not contain -** a virtual table" -** (**) Was: "The outer query may not have a GROUP BY." This case -** is now managed correctly -** (3d) the outer query may not be DISTINCT. -** See also (26) for restrictions on RIGHT JOIN. -** -** (4) The subquery can not be DISTINCT. -** -** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT -** sub-queries that were excluded from this optimization. Restriction -** (4) has since been expanded to exclude all DISTINCT subqueries. -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** If the subquery is aggregate, the outer query may not be DISTINCT. -** -** (7) The subquery must have a FROM clause. TODO: For subqueries without -** A FROM clause, consider adding a FROM clause with the special -** table sqlite_once that consists of a single row containing a -** single NULL. -** -** (8) If the subquery uses LIMIT then the outer query may not be a join. -** -** (9) If the subquery uses LIMIT then the outer query may not be aggregate. -** -** (**) Restriction (10) was removed from the code on 2005-02-05 but we -** accidentally carried the comment forward until 2014-09-15. Original -** constraint: "If the subquery is aggregate then the outer query -** may not use LIMIT." -** -** (11) The subquery and the outer query may not both have ORDER BY clauses. -** -** (**) Not implemented. Subsumed into restriction (3). Was previously -** a separate restriction deriving from ticket #350. -** -** (13) The subquery and outer query may not both use LIMIT. -** -** (14) The subquery may not use OFFSET. -** -** (15) If the outer query is part of a compound select, then the -** subquery may not use LIMIT. -** (See ticket #2339 and ticket [02a8e81d44]). -** -** (16) If the outer query is aggregate, then the subquery may not -** use ORDER BY. (Ticket #2942) This used to not matter -** until we introduced the group_concat() function. -** -** (17) If the subquery is a compound select, then -** (17a) all compound operators must be a UNION ALL, and -** (17b) no terms within the subquery compound may be aggregate -** or DISTINCT, and -** (17c) every term within the subquery compound must have a FROM clause -** (17d) the outer query may not be -** (17d1) aggregate, or -** (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).) -** (17h) The corresponding result set expressions in all arms of the -** compound must have the same affinity. -** -** The parent and sub-query may contain WHERE clauses. Subject to -** rules (11), (13) and (14), they may also contain ORDER BY, -** LIMIT and OFFSET clauses. The subquery cannot use any compound -** operator other than UNION ALL because all the other compound -** operators have an implied DISTINCT which is disallowed by -** restriction (4). -** -** Also, each component of the sub-query must return the same number -** of result columns. This is actually a requirement for any compound -** SELECT statement, but all the code here does is make sure that no -** such (illegal) sub-query is flattened. The caller will detect the -** 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 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. -** -** (20) If the sub-query is a compound select, then it must not use -** an ORDER BY clause. Ticket #3773. We could relax this constraint -** somewhat by saying that the terms of the ORDER BY clause must -** appear as unmodified result columns in the outer query. But we -** have other optimizations in mind to deal with that case. -** -** (21) If the subquery uses LIMIT then the outer query may not be -** DISTINCT. (See ticket [752e1646fc]). -** -** (22) The subquery may not be a recursive CTE. -** -** (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(). -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** The subquery may not be an aggregate that uses the built-in min() or -** or max() functions. (Without this restriction, a query like: -** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily -** return the value X for which Y was maximal.) -** -** (25) If either the subquery or the parent query contains a window -** 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. Two subcases: -** (27a) the subquery is not a compound query. -** (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. (This is handled -** in the caller before ever reaching this routine.) -** -** -** In this routine, the "p" parameter is a pointer to the outer query. -** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query -** uses aggregates. -** -** If flattening is not attempted, this routine is a no-op and returns 0. -** If flattening is attempted this routine returns 1. -** -** All of the expression analysis must occur on both the outer query and -** the subquery before this routine runs. -*/ -static int flattenSubquery( - Parse *pParse, /* Parsing context */ - Select *p, /* The parent or outer SELECT statement */ - int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ - int isAgg /* True if outer SELECT uses aggregate functions */ -){ - const char *zSavedAuthContext = pParse->zAuthContext; - Select *pParent; /* Current UNION ALL term of the other query */ - Select *pSub; /* The inner query or "subquery" */ - Select *pSub1; /* Pointer to the rightmost select in sub-query */ - SrcList *pSrc; /* The FROM clause of the outer query */ - 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 isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ - int i; /* Loop counter */ - Expr *pWhere; /* The WHERE clause */ - SrcItem *pSubitem; /* The subquery */ - 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. - */ - assert( p!=0 ); - assert( p->pPrior==0 ); - if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; - pSrc = p->pSrc; - assert( pSrc && iFrom>=0 && iFromnSrc ); - pSubitem = &pSrc->a[iFrom]; - iParent = pSubitem->iCursor; - assert( pSubitem->fg.isSubquery ); - pSub = pSubitem->u4.pSubq->pSelect; - assert( pSub!=0 ); - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ -#endif - - pSubSrc = pSub->pSrc; - assert( pSubSrc ); - /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, - ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET - ** because they could be computed at compile-time. But when LIMIT and OFFSET - ** became arbitrary expressions, we were forced to add restrictions (13) - ** and (14). */ - if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ - if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */ - if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ - return 0; /* Restriction (15) */ - } - if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ - if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */ - if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ - return 0; /* Restrictions (8)(9) */ - } - if( p->pOrderBy && pSub->pOrderBy ){ - return 0; /* Restriction (11) */ - } - if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ - if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */ - if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ - return 0; /* Restriction (21) */ - } - if( pSub->selFlags & (SF_Recursive) ){ - return 0; /* Restrictions (22) */ - } - - /* - ** If the subquery is the right operand of a LEFT JOIN, then the - ** subquery may not be a join itself (3a). Example of why this is not - ** allowed: - ** - ** t1 LEFT OUTER JOIN (t2 JOIN t3) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) JOIN t3 - ** - ** which is not at all the same thing. - ** - ** See also tickets #306, #350, and #3300. - */ - if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ - if( pSubSrc->nSrc>1 /* (3a) */ - /**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */ - || (p->selFlags & SF_Distinct)!=0 /* (3d) */ - || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ - ){ - return 0; - } - isOuterJoin = 1; - } - - assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */ - if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ - return 0; /* Restriction (27a) */ - } - - /* Condition (28) is blocked by the caller */ - assert( !pSubitem->fg.isCte || pSubitem->u2.pCteUse->eM10d!=M10d_Yes ); - - /* 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 - ** queries. - */ - if( pSub->pPrior ){ - int ii; - if( pSub->pOrderBy ){ - return 0; /* Restriction (20) */ - } - 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) */ - || pSub1->pSrc->nSrc<1 /* (17c) */ -#ifndef SQLITE_OMIT_WINDOWFUNC - || pSub1->pWin /* (17e) */ -#endif - ){ - 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 ); - } - - /* Restriction (18). */ - if( p->pOrderBy ){ - for(ii=0; iipOrderBy->nExpr; ii++){ - if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0; - } - } - - /* Restriction (23) */ - if( (p->selFlags & SF_Recursive) ) return 0; - - /* Restriction (17h) */ - if( compoundHasDifferentAffinities(pSub) ) return 0; - - if( pSrc->nSrc>1 ){ - if( pParse->nSelect>500 ) return 0; - if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0; - aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int)); - if( aCsrMap ) aCsrMap[0] = pParse->nTab; - } - } - - /***** If we reach this point, flattening is permitted. *****/ - TREETRACE(0x4,pParse,p,("flatten %u.%p from term %d\n", - pSub->selId, pSub, iFrom)); - - /* Authorize the subquery */ - pParse->zAuthContext = pSubitem->zName; - TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); - testcase( i==SQLITE_DENY ); - pParse->zAuthContext = zSavedAuthContext; - - /* Delete the transient structures associated with the subquery */ - - if( ALWAYS(pSubitem->fg.isSubquery) ){ - pSub1 = sqlite3SubqueryDetach(db, pSubitem); - }else{ - pSub1 = 0; - } - assert( pSubitem->fg.isSubquery==0 ); - assert( pSubitem->fg.fixedSchema==0 ); - sqlite3DbFree(db, pSubitem->zName); - sqlite3DbFree(db, pSubitem->zAlias); - pSubitem->zName = 0; - pSubitem->zAlias = 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: - ** - ** SELECT FROM () - ** - ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block - ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or - ** OFFSET clauses and joins them to the left-hand-side of the original - ** using UNION ALL operators. In this case N is the number of simple - ** select statements in the compound sub-query. - ** - ** Example: - ** - ** SELECT a+1 FROM ( - ** SELECT x FROM tab - ** UNION ALL - ** SELECT y FROM tab - ** UNION ALL - ** SELECT abs(z*2) FROM tab2 - ** ) WHERE a!=5 ORDER BY 1 - ** - ** Transformed into: - ** - ** SELECT x+1 FROM tab WHERE x+1!=5 - ** UNION ALL - ** SELECT y+1 FROM tab WHERE y+1!=5 - ** UNION ALL - ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5 - ** ORDER BY 1 - ** - ** We call this the "compound-subquery flattening". - */ - for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ - Select *pNew; - ExprList *pOrderBy = p->pOrderBy; - Expr *pLimit = p->pLimit; - Select *pPrior = p->pPrior; - Table *pItemTab = pSubitem->pSTab; - pSubitem->pSTab = 0; - p->pOrderBy = 0; - p->pPrior = 0; - p->pLimit = 0; - pNew = sqlite3SelectDup(db, p, 0); - p->pLimit = pLimit; - p->pOrderBy = pOrderBy; - p->op = TK_ALL; - pSubitem->pSTab = 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; - p->pPrior = pNew; - TREETRACE(0x4,pParse,p,("compound-subquery flattener" - " creates %u as peer\n",pNew->selId)); - } - assert( pSubitem->fg.isSubquery==0 ); - } - sqlite3DbFree(db, aCsrMap); - if( db->mallocFailed ){ - assert( pSubitem->fg.fixedSchema==0 ); - assert( pSubitem->fg.isSubquery==0 ); - assert( pSubitem->u4.zDatabase==0 ); - sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0); - return 1; - } - - /* Defer deleting the Table object associated with the - ** subquery until code generation is - ** complete, since there may still exist Expr.pTab entries that - ** refer to the subquery even after flattening. Ticket #3346. - ** - ** pSubitem->pTab is always non-NULL by test restrictions and tests above. - */ - if( ALWAYS(pSubitem->pSTab!=0) ){ - Table *pTabToDel = pSubitem->pSTab; - if( pTabToDel->nTabRef==1 ){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel); - testcase( pToplevel->earlyCleanup ); - }else{ - pTabToDel->nTabRef--; - } - pSubitem->pSTab = 0; - } - - /* The following loop runs once for each term in a compound-subquery - ** flattening (as described above). If we are doing a different kind - ** of flattening - a flattening other than a compound-subquery flattening - - ** then this loop only runs once. - ** - ** This loop moves all of the FROM elements of the subquery into the - ** the FROM clause of the outer query. Before doing this, remember - ** the cursor number for the original outer query FROM element in - ** iParent. The iParent cursor will never be used. Subsequent code - ** will scan expressions looking for iParent references and replace - ** 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( pParent==p ){ - jointype = pSubitem->fg.jointype; /* First time through the loop */ - } - - /* The subquery uses a single slot of the FROM clause of the outer - ** query. If the subquery has more than one element in its FROM clause, - ** then expand the outer query to make space for it to hold all elements - ** of the subquery. - ** - ** Example: - ** - ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; - ** - ** The outer query has 3 slots in its FROM clause. One slot of the - ** outer query (the middle slot) is used by the subquery. The next - ** block of code will expand the outer query FROM clause to 4 slots. - ** The middle slot is expanded to two slots in order to make space - ** for the two elements in the FROM clause of the subquery. - */ - if( nSubSrc>1 ){ - pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1); - if( pSrc==0 ) break; - pParent->pSrc = pSrc; - } - - /* Transfer the FROM clause terms from the subquery into the - ** outer query. - */ - iNewParent = pSubSrc->a[0].iCursor; - for(i=0; ia[i+iFrom]; - assert( pItem->fg.isTabFunc==0 ); - assert( pItem->fg.isSubquery - || pItem->fg.fixedSchema - || pItem->u4.zDatabase==0 ); - if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing); - *pItem = pSubSrc->a[i]; - pItem->fg.jointype |= ltorj; - memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); - } - 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. - ** - ** Example: - ** - ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; - ** \ \_____________ subquery __________/ / - ** \_____________________ outer query ______________________________/ - ** - ** We look at every expression in the outer query and every place we see - ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". - */ - if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){ - /* At this point, any non-zero iOrderByCol values indicate that the - ** ORDER BY column expression is identical to the iOrderByCol'th - ** expression returned by SELECT statement pSub. Since these values - ** do not necessarily correspond to columns in SELECT statement pParent, - ** zero them before transferring the ORDER BY clause. - ** - ** Not doing this may cause an error if a subsequent call to this - ** function attempts to flatten a compound sub-query into pParent - ** (the only way this can happen is if the compound sub-query is - ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ - ExprList *pOrderBy = pSub->pOrderBy; - for(i=0; inExpr; i++){ - pOrderBy->a[i].u.x.iOrderByCol = 0; - } - assert( pParent->pOrderBy==0 ); - pParent->pOrderBy = pOrderBy; - pSub->pOrderBy = 0; - } - pWhere = pSub->pWhere; - pSub->pWhere = 0; - if( isOuterJoin>0 ){ - assert( pSubSrc->nSrc==1 ); - sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON); - } - if( pWhere ){ - if( pParent->pWhere ){ - pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere); - }else{ - pParent->pWhere = pWhere; - } - } - if( db->mallocFailed==0 ){ - SubstContext x; - x.pParse = pParse; - x.iTable = iParent; - x.iNewTable = iNewParent; - x.isOuterJoin = isOuterJoin; - x.pEList = pSub->pEList; - x.pCList = findLeftmostExprlist(pSub); - substSelect(&x, pParent, 0); - } - - /* The flattened query is a compound if either the inner or the - ** outer query is a compound. */ - pParent->selFlags |= pSub->selFlags & SF_Compound; - assert( (pSub->selFlags & SF_Distinct)==0 ); /* restriction (17b) */ - - /* - ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; - ** - ** One is tempted to try to add a and b to combine the limits. But this - ** does not work if either limit is negative. - */ - if( pSub->pLimit ){ - pParent->pLimit = pSub->pLimit; - pSub->pLimit = 0; - } - - /* Recompute the SrcItem.colUsed masks for the flattened - ** tables. */ - for(i=0; ia[i+iFrom]); - } - } - - /* Finally, delete what is left of the subquery and return success. - */ - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w,pSub1); - sqlite3SelectDelete(db, pSub1); - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4 ){ - TREETRACE(0x4,pParse,p,("After flattening:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - - return 1; -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -/* -** A structure to keep track of all of the column values that are fixed to -** a known value due to WHERE clause constraints of the form COLUMN=VALUE. -*/ -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 */ -}; - -/* -** Add a new entry to the pConst object. Except, do not add duplicate -** pColumn entries. Also, do not add if doing so would not be appropriate. -** -** The caller guarantees the pColumn is a column and pValue is a constant. -** This routine has to do some additional checks before completing the -** insert. -*/ -static void constInsert( - WhereConst *pConst, /* The WhereConst into which we are inserting */ - Expr *pColumn, /* The COLUMN part of the constraint */ - Expr *pValue, /* The VALUE part of the constraint */ - Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */ -){ - int i; - assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(pConst->pParse, pValue) ); - - if( ExprHasProperty(pColumn, EP_FixedCol) ) return; - if( sqlite3ExprAffinity(pValue)!=0 ) return; - if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){ - return; - } - - /* 2018-10-25 ticket [cf5ed20f] - ** Make sure the same pColumn is not inserted more than once */ - for(i=0; inConst; i++){ - const Expr *pE2 = pConst->apExpr[i*2]; - assert( pE2->op==TK_COLUMN ); - if( pE2->iTable==pColumn->iTable - && pE2->iColumn==pColumn->iColumn - ){ - return; /* Already present. Return without doing anything. */ - } - } - assert( SQLITE_AFF_NONEbHasAffBlob = 1; - } - - pConst->nConst++; - pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr, - pConst->nConst*2*sizeof(Expr*)); - if( pConst->apExpr==0 ){ - pConst->nConst = 0; - }else{ - pConst->apExpr[pConst->nConst*2-2] = pColumn; - pConst->apExpr[pConst->nConst*2-1] = pValue; - } -} - -/* -** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE -** is a constant expression and where the term must be true because it -** is part of the AND-connected terms of the expression. For each term -** found, add it to the pConst structure. -*/ -static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ - Expr *pRight, *pLeft; - 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); - return; - } - if( pExpr->op!=TK_EQ ) return; - pRight = pExpr->pRight; - pLeft = pExpr->pLeft; - assert( pRight!=0 ); - assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){ - constInsert(pConst,pRight,pLeft,pExpr); - } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){ - constInsert(pConst,pLeft,pRight,pExpr); - } -} - -/* -** 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 propagateConstantExprRewriteOne( - WhereConst *pConst, - Expr *pExpr, - int bIgnoreAffBlob -){ - int i; - if( pConst->pOomFault[0] ) return WRC_Prune; - if( pExpr->op!=TK_COLUMN ) return WRC_Continue; - if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){ - testcase( ExprHasProperty(pExpr, EP_FixedCol) ); - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - testcase( ExprHasProperty(pExpr, EP_InnerON) ); - return WRC_Continue; - } - for(i=0; inConst; i++){ - Expr *pColumn = pConst->apExpr[i*2]; - if( pColumn==pExpr ) continue; - if( pColumn->iTable!=pExpr->iTable ) continue; - if( pColumn->iColumn!=pExpr->iColumn ) continue; - assert( SQLITE_AFF_NONEnChng++; - ExprClearProperty(pExpr, EP_Leaf); - ExprSetProperty(pExpr, EP_FixedCol); - assert( pExpr->pLeft==0 ); - pExpr->pLeft = 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( 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 -** CONSTANT=COLUMN that are top-level AND-connected terms that are not -** part of a ON clause from a LEFT JOIN, then throughout the query -** replace all other occurrences of COLUMN with CONSTANT. -** -** For example, the query: -** -** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b -** -** Is transformed into -** -** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=39 AND t3.c=39 -** -** Return true if any transformations where made and false if not. -** -** Implementation note: Constant propagation is tricky due to affinity -** and collating sequence interactions. Consider this example: -** -** CREATE TABLE t1(a INT,b TEXT); -** INSERT INTO t1 VALUES(123,'0123'); -** SELECT * FROM t1 WHERE a=123 AND b=a; -** SELECT * FROM t1 WHERE a=123 AND b=123; -** -** The two SELECT statements above should return different answers. b=a -** is always true because the comparison uses numeric affinity, but b=123 -** is false because it uses text affinity and '0123' is not the same as '123'. -** To work around this, the expression tree is not actually changed from -** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol -** and the "123" value is hung off of the pLeft pointer. Code generator -** 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 */ - Select *p /* The query in which to propagate constants */ -){ - WhereConst x; - 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)); - w.pParse = pParse; - w.xExprCallback = propagateConstantExprRewrite; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.xSelectCallback2 = 0; - w.walkerDepth = 0; - w.u.pConst = &x; - sqlite3WalkExpr(&w, p->pWhere); - sqlite3DbFree(x.pParse->db, x.apExpr); - nChng += x.nChng; - } - }while( x.nChng ); - return nChng; -} - -#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 clause. -*/ -static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ - assert( pSubq->pWin->pPartition ); - assert( (pSubq->selFlags & SF_MultiPart)==0 ); - assert( pSubq->pPrior==0 ); - return 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: -** -** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10; -** -** Transformed into: -** -** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) -** WHERE x=5 AND y=10; -** -** The hope is that the terms added to the inner query will make it more -** efficient. -** -** NAME AMBIGUITY -** -** This optimization is called the "WHERE-clause push-down optimization" -** or sometimes the "predicate push-down optimization". -** -** Do not confuse this optimization with another unrelated optimization -** with a similar name: The "MySQL push-down optimization" causes WHERE -** clause terms that can be evaluated using only the index and without -** reference to the table are run first, so that if they are false, -** unnecessary table seeks are avoided. -** -** RULES -** -** Do not attempt this optimization if: -** -** (1) (** This restriction was removed on 2017-09-29. We used to -** disallow this optimization for aggregate subqueries, but now -** it is allowed by putting the extra terms on the HAVING clause. -** The added HAVING clause is pointless if the subquery lacks -** a GROUP BY clause. But such a HAVING clause is also harmless -** so there does not appear to be any reason to add extra logic -** to suppress it. **) -** -** (2) The inner query is the recursive part of a common table expression. -** -** (3) The inner query has a LIMIT clause (since the changes to the WHERE -** clause would change the meaning of the LIMIT). -** -** (4) The inner query is the right operand of a LEFT JOIN and the -** expression to be pushed down does not come from the ON clause -** on that LEFT JOIN. -** -** (5) The WHERE clause expression originates in the ON or USING clause -** of a LEFT JOIN where iCursor is not the right-hand table of that -** left join. An example: -** -** SELECT * -** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa -** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) -** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); -** -** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). -** 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) 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.) -** -** (8) If the subquery is a compound that uses UNION, INTERSECT, -** or EXCEPT, then all of the result set columns for all arms of -** the compound must use the BINARY collating sequence. -** -** (9) All three of the following are true: -** -** (9a) The WHERE clause expression originates in the ON or USING clause -** of a join (either an INNER or an OUTER join), and -** -** (9b) The subquery is to the right of the ON/USING clause -** -** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING -** clause and the subquery. -** -** Without this restriction, the WHERE-clause push-down optimization -** might move the ON/USING filter expression from the left side of a -** RIGHT JOIN over to the right side, which leads to incorrect answers. -** See also restriction (6) in sqlite3ExprIsSingleTableConstraint(). -** -** (10) The inner query is not the right-hand table of a RIGHT JOIN. -** -** (11) The subquery is not a VALUES clause -** -** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This -** case only comes up if SQLite is compiled using -** SQLITE_ALLOW_ROWID_IN_VIEW. -** -** Return 0 if no changes are made and non-zero if one or more WHERE clause -** terms are duplicated into the subquery. -*/ -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 */ - SrcList *pSrcList, /* The complete from clause of the outer query */ - int iSrc /* Which FROM clause term to try to push into */ -){ - Expr *pNew; - SrcItem *pSrc; /* The subquery FROM term into which WHERE is pushed */ - int nChng = 0; - pSrc = &pSrcList->a[iSrc]; - if( pWhere==0 ) return 0; - if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ){ - return 0; /* restrictions (2) and (11) */ - } - if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ){ - return 0; /* restrictions (10) */ - } - - if( pSubq->pPrior ){ - Select *pSel; - int notUnionAll = 0; - for(pSel=pSubq; pSel; pSel=pSel->pPrior){ - u8 op = pSel->op; - assert( op==TK_ALL || op==TK_SELECT - || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); - if( op!=TK_ALL && op!=TK_SELECT ){ - notUnionAll = 1; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSel->pWin ) return 0; /* restriction (6b) */ -#endif - } - if( notUnionAll ){ - /* If any of the compound arms are connected using UNION, INTERSECT, - ** or EXCEPT, then we must ensure that none of the columns use a - ** non-BINARY collating sequence. */ - for(pSel=pSubq; pSel; pSel=pSel->pPrior){ - int ii; - const ExprList *pList = pSel->pEList; - assert( pList!=0 ); - for(ii=0; iinExpr; ii++){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[ii].pExpr); - if( !sqlite3IsBinary(pColl) ){ - return 0; /* Restriction (8) */ - } - } - } - } - }else{ -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0; -#endif - } - -#ifdef SQLITE_DEBUG - /* Only the first term of a compound can have a WITH clause. But make - ** sure no other terms are marked SF_Recursive in case something changes - ** in the future. - */ - { - Select *pX; - for(pX=pSubq; pX; pX=pX->pPrior){ - assert( (pX->selFlags & (SF_Recursive))==0 ); - } - } -#endif - - if( pSubq->pLimit!=0 ){ - return 0; /* restriction (3) */ - } - while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrcList, iSrc); - pWhere = pWhere->pLeft; - } - -#if 0 /* These checks now done by sqlite3ExprIsSingleTableConstraint() */ - if( ExprHasProperty(pWhere, EP_OuterON|EP_InnerON) /* (9a) */ - && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (9c) */ - ){ - int jj; - for(jj=0; jjw.iJoin==pSrcList->a[jj].iCursor ){ - /* If we reach this point, both (9a) and (9b) are satisfied. - ** The following loop checks (9c): - */ - for(jj++; jja[jj].fg.jointype & JT_RIGHT)!=0 ){ - return 0; /* restriction (9) */ - } - } - } - } - } - if( isLeftJoin - && (ExprHasProperty(pWhere,EP_OuterON)==0 - || pWhere->w.iJoin!=iCursor) - ){ - return 0; /* restriction (4) */ - } - if( ExprHasProperty(pWhere,EP_OuterON) - && pWhere->w.iJoin!=iCursor - ){ - return 0; /* restriction (5) */ - } -#endif - -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){ - Expr *pLeft = pWhere->pLeft; - if( ALWAYS(pLeft) - && pLeft->op==TK_COLUMN - && pLeft->iColumn < 0 - ){ - return 0; /* Restriction (12) */ - } - } -#endif - - if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){ - nChng++; - pSubq->selFlags |= SF_PushDown; - while( pSubq ){ - SubstContext x; - pNew = sqlite3ExprDup(pParse->db, pWhere, 0); - unsetJoinExpr(pNew, -1, 1); - x.pParse = pParse; - x.iTable = pSrc->iCursor; - x.iNewTable = pSrc->iCursor; - x.isOuterJoin = 0; - x.pEList = pSubq->pEList; - x.pCList = findLeftmostExprlist(pSubq); - 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 */ - sqlite3ExprDelete(pParse->db, pNew); - nChng--; - break; - } -#endif - if( pSubq->selFlags & SF_Aggregate ){ - pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew); - }else{ - pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew); - } - pSubq = pSubq->pPrior; - } - } - return nChng; -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -/* -** Check to see if a subquery contains result-set columns that are -** never used. If it does, change the value of those result-set columns -** to NULL so that they do not cause unnecessary work to compute. -** -** Return the number of column that were changed to NULL. -*/ -static int disableUnusedSubqueryResultColumns(SrcItem *pItem){ - int nCol; - Select *pSub; /* The subquery to be simplified */ - Select *pX; /* For looping over compound elements of pSub */ - Table *pTab; /* The table that describes the subquery */ - int j; /* Column number */ - int nChng = 0; /* Number of columns converted to NULL */ - Bitmask colUsed; /* Columns that may not be NULLed out */ - - assert( pItem!=0 ); - if( pItem->fg.isCorrelated || pItem->fg.isCte ){ - return 0; - } - assert( pItem->pSTab!=0 ); - pTab = pItem->pSTab; - assert( pItem->fg.isSubquery ); - pSub = pItem->u4.pSubq->pSelect; - assert( pSub->pEList->nExpr==pTab->nCol ); - for(pX=pSub; pX; pX=pX->pPrior){ - if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){ - testcase( pX->selFlags & SF_Distinct ); - testcase( pX->selFlags & SF_Aggregate ); - return 0; - } - if( pX->pPrior && pX->op!=TK_ALL ){ - /* This optimization does not work for compound subqueries that - ** use UNION, INTERSECT, or EXCEPT. Only UNION ALL is allowed. */ - return 0; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pX->pWin ){ - /* This optimization does not work for subqueries that use window - ** functions. */ - return 0; - } -#endif - } - colUsed = pItem->colUsed; - if( pSub->pOrderBy ){ - ExprList *pList = pSub->pOrderBy; - for(j=0; jnExpr; j++){ - u16 iCol = pList->a[j].u.x.iOrderByCol; - if( iCol>0 ){ - iCol--; - colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); - } - } - } - nCol = pTab->nCol; - for(j=0; jpPrior) { - Expr *pY = pX->pEList->a[j].pExpr; - if( pY->op==TK_NULL ) continue; - pY->op = TK_NULL; - ExprClearProperty(pY, EP_Skip|EP_Unlikely); - pX->selFlags |= SF_PushDown; - nChng++; - } - } - return nChng; -} - - -/* -** The pFunc is the only aggregate function in the query. Check to see -** if the query is a candidate for the min/max optimization. -** -** If the query is a candidate for the min/max optimization, then set -** *ppMinMax to be an ORDER BY clause to be used for the optimization -** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on -** whether pFunc is a min() or max() function. -** -** If the query is not a candidate for the min/max optimization, return -** WHERE_ORDERBY_NORMAL (which must be zero). -** -** This routine must be called after aggregate functions have been -** located but before their arguments have been subjected to aggregate -** analysis. -*/ -static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ - int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ - ExprList *pEList; /* Arguments to agg function */ - const char *zFunc; /* Name of aggregate function pFunc */ - ExprList *pOrderBy; - u8 sortFlags = 0; - - assert( *ppMinMax==0 ); - assert( pFunc->op==TK_AGG_FUNCTION ); - assert( !IsWindowFunc(pFunc) ); - 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( sqlite3StrICmp(zFunc, "min")==0 ){ - eRet = WHERE_ORDERBY_MIN; - if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){ - sortFlags = KEYINFO_ORDER_BIGNULL; - } - }else if( sqlite3StrICmp(zFunc, "max")==0 ){ - eRet = WHERE_ORDERBY_MAX; - sortFlags = KEYINFO_ORDER_DESC; - }else{ - return eRet; - } - *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); - assert( pOrderBy!=0 || db->mallocFailed ); - if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags; - return eRet; -} - -/* -** The select statement passed as the first argument is an aggregate query. -** The second argument is the associated aggregate-info object. This -** function tests if the SELECT is of the form: -** -** SELECT count(*) FROM -** -** 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 -** 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; - Expr *pExpr; - - assert( !p->pGroupBy ); - - if( p->pWhere - || p->pEList->nExpr!=1 - || p->pSrc->nSrc!=1 - || p->pSrc->a[0].fg.isSubquery - || pAggInfo->nFunc!=1 - || p->pHaving - ){ - return 0; - } - pTab = p->pSrc->a[0].pSTab; - assert( pTab!=0 ); - assert( !IsView(pTab) ); - if( !IsOrdinaryTable(pTab) ) return 0; - pExpr = p->pEList->a[0].pExpr; - assert( pExpr!=0 ); - if( pExpr->op!=TK_AGG_FUNCTION ) 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; -} - -/* -** If the source-list item passed as an argument was augmented with an -** INDEXED BY clause, then try to locate the specified index. If there -** was such a clause and the named index cannot be found, return -** SQLITE_ERROR and leave an error in pParse. Otherwise, populate -** pFrom->pIndex and return SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){ - Table *pTab = pFrom->pSTab; - char *zIndexedBy = pFrom->u1.zIndexedBy; - Index *pIdx; - assert( pTab!=0 ); - assert( pFrom->fg.isIndexedBy!=0 ); - - for(pIdx=pTab->pIndex; - pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); - pIdx=pIdx->pNext - ); - if( !pIdx ){ - 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. -** -** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ... -** -** These are rewritten as a subquery: -** -** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) -** ORDER BY ... COLLATE ... -** -** This transformation is necessary because the multiSelectOrderBy() routine -** above that generates the code for a compound SELECT with an ORDER BY clause -** uses a merge algorithm that requires the same collating sequence on the -** result columns as on the ORDER BY clause. See ticket -** http://sqlite.org/src/info/6709574d2a -** -** This transformation is only needed for EXCEPT, INTERSECT, and UNION. -** The UNION ALL operator works fine with multiSelectOrderBy() even when -** there are COLLATE terms in the ORDER BY. -*/ -static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ - int i; - Select *pNew; - Select *pX; - sqlite3 *db; - struct ExprList_item *a; - SrcList *pNewSrc; - Parse *pParse; - Token dummy; - - if( p->pPrior==0 ) return WRC_Continue; - if( p->pOrderBy==0 ) return WRC_Continue; - for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){} - if( pX==0 ) return WRC_Continue; - a = p->pOrderBy->a; -#ifndef SQLITE_OMIT_WINDOWFUNC - /* If iOrderByCol is already non-zero, then it has already been matched - ** to a result column of the SELECT statement. This occurs when the - ** SELECT is rewritten for window-functions processing and then passed - ** to sqlite3SelectPrep() and similar a second time. The rewriting done - ** by this function is not required in this case. */ - if( a[0].u.x.iOrderByCol ) return WRC_Continue; -#endif - for(i=p->pOrderBy->nExpr-1; i>=0; i--){ - if( a[i].pExpr->flags & EP_Collate ) break; - } - if( i<0 ) return WRC_Continue; - - /* If we reach this point, that means the transformation is required. */ - - pParse = pWalker->pParse; - db = pParse->db; - pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - if( pNew==0 ) return WRC_Abort; - memset(&dummy, 0, sizeof(dummy)); - pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0); - assert( pNewSrc!=0 || pParse->nErr ); - if( pParse->nErr ){ - sqlite3SrcListDelete(db, pNewSrc); - return WRC_Abort; - } - *pNew = *p; - p->pSrc = pNewSrc; - p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); - p->op = TK_SELECT; - p->pWhere = 0; - pNew->pGroupBy = 0; - pNew->pHaving = 0; - pNew->pOrderBy = 0; - p->pPrior = 0; - p->pNext = 0; - p->pWith = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - p->pWinDefn = 0; -#endif - p->selFlags &= ~(u32)SF_Compound; - assert( (p->selFlags & SF_Converted)==0 ); - p->selFlags |= SF_Converted; - assert( pNew->pPrior!=0 ); - pNew->pPrior->pNext = pNew; - pNew->pLimit = 0; - return WRC_Continue; -} - -/* -** Check to see if the FROM clause term pFrom has table-valued function -** 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, SrcItem *pFrom){ - if( pFrom->fg.isTabFunc ){ - sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName); - return 1; - } - return 0; -} - -#ifndef SQLITE_OMIT_CTE -/* -** Argument pWith (which may be NULL) points to a linked list of nested -** WITH contexts, from inner to outermost. If the table identified by -** FROM clause element pItem is really a common-table-expression (CTE) -** then return a pointer to the CTE definition for that table. Otherwise -** return NULL. -** -** If a non-NULL value is returned, set *ppContext to point to the With -** object that the returned CTE belongs to. -*/ -static struct Cte *searchWith( - With *pWith, /* Current innermost WITH clause */ - SrcItem *pItem, /* FROM clause element to resolve */ - With **ppContext /* OUT: WITH clause return value belongs to */ -){ - const char *zName = pItem->zName; - With *p; - assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 ); - assert( zName!=0 ); - for(p=pWith; p; p=p->pOuter){ - int i; - for(i=0; inCte; i++){ - if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ - *ppContext = p; - return &p->a[i]; - } - } - if( p->bView ) break; - } - return 0; -} - -/* The code generator maintains a stack of active WITH clauses -** with the inner-most WITH clause being at the top of the stack. -** -** This routine pushes the WITH clause passed as the second argument -** onto the top of the stack. If argument bFree is true, then this -** WITH clause will never be popped from the stack 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 With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ - if( pWith ){ - if( bFree ){ - pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric, - 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 (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 matches a CTE according to either of these two above, pFrom->pTab -** and other fields are populated accordingly. -** -** Return 0 if no match is found. -** Return 1 if a match is found. -** Return 2 if an error condition is detected. -*/ -static int resolveFromTermToCte( - Parse *pParse, /* The parsing context */ - Walker *pWalker, /* Current tree walker */ - SrcItem *pFrom /* The FROM clause term to check */ -){ - Cte *pCte; /* Matched CTE (or NULL if no match) */ - With *pWith; /* The matching WITH */ - - assert( pFrom->pSTab==0 ); - if( pParse->pWith==0 ){ - /* There are no WITH clauses in the stack. No match is possible */ - return 0; - } - if( pParse->nErr ){ - /* Prior errors might have left pParse->pWith in a goofy state, so - ** go no further. */ - return 0; - } - assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 ); - if( pFrom->fg.fixedSchema==0 && pFrom->u4.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 sqlite3FixTriggerStep(). - ** (2) This is the first term in the FROM clause of an UPDATE. - */ - return 0; - } - pCte = searchWith(pParse->pWith, pFrom, &pWith); - if( pCte ){ - sqlite3 *db = pParse->db; - Table *pTab; - ExprList *pEList; - Select *pSel; - Select *pLeft; /* Left-most SELECT statement */ - Select *pRecTerm; /* Left-most recursive term */ - 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 - ** early. If pCte->zCteErr is NULL, then this is not a recursive reference. - ** In this case, proceed. */ - if( pCte->zCteErr ){ - sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName); - return 2; - } - if( cannotBeFunction(pParse, pFrom) ) return 2; - - assert( pFrom->pSTab==0 ); - pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ) return 2; - pCteUse = pCte->pUse; - if( pCteUse==0 ){ - pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0])); - if( pCteUse==0 - || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0 - ){ - sqlite3DbFree(db, pTab); - return 2; - } - pCteUse->eM10d = pCte->eM10d; - } - pFrom->pSTab = pTab; - pTab->nTabRef = 1; - pTab->zName = sqlite3DbStrDup(db, pCte->zName); - pTab->iPKey = -1; - pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); - pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; - sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1); - if( db->mallocFailed ) return 2; - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq ); - pSel = pFrom->u4.pSubq->pSelect; - assert( pSel!=0 ); - pSel->selFlags |= SF_CopyCte; - if( pFrom->fg.isIndexedBy ){ - sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy); - return 2; - } - assert( !pFrom->fg.isIndexedBy ); - pFrom->fg.isCte = 1; - pFrom->u2.pCteUse = pCteUse; - pCteUse->nUse++; - - /* Check if this is a recursive CTE. */ - pRecTerm = pSel; - bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); - while( bMayRecursive && pRecTerm->op==pSel->op ){ - int i; - SrcList *pSrc = pRecTerm->pSrc; - assert( pRecTerm->pPrior!=0 ); - for(i=0; inSrc; i++){ - SrcItem *pItem = &pSrc->a[i]; - if( pItem->zName!=0 - && !pItem->fg.hadSchema - && ALWAYS( !pItem->fg.isSubquery ) - && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0) - && 0==sqlite3StrICmp(pItem->zName, pCte->zName) - ){ - pItem->pSTab = pTab; - pTab->nTabRef++; - pItem->fg.isRecursive = 1; - if( pRecTerm->selFlags & SF_Recursive ){ - sqlite3ErrorMsg(pParse, - "multiple references to recursive table: %s", pCte->zName - ); - return 2; - } - pRecTerm->selFlags |= SF_Recursive; - if( iRecTab<0 ) iRecTab = pParse->nTab++; - pItem->iCursor = iRecTab; - } - } - if( (pRecTerm->selFlags & SF_Recursive)==0 ) break; - pRecTerm = pRecTerm->pPrior; - } - - pCte->zCteErr = "circular reference: %s"; - 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; - rc = sqlite3WalkSelect(pWalker, pRecTerm); - pRecTerm->pWith = 0; - if( rc ){ - pParse->pWith = pSavedWith; - return 2; - } - }else{ - if( sqlite3WalkSelect(pWalker, pSel) ){ - pParse->pWith = pSavedWith; - return 2; - } - } - pParse->pWith = pWith; - - for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); - pEList = pLeft->pEList; - if( pCte->pCols ){ - if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ - sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", - pCte->zName, pEList->nExpr, pCte->pCols->nExpr - ); - pParse->pWith = pSavedWith; - return 2; - } - pEList = pCte->pCols; - } - - sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); - if( bMayRecursive ){ - if( pSel->selFlags & SF_Recursive ){ - pCte->zCteErr = "multiple recursive references: %s"; - }else{ - pCte->zCteErr = "recursive reference in a subquery: %s"; - } - sqlite3WalkSelect(pWalker, pSel); - } - pCte->zCteErr = 0; - pParse->pWith = pSavedWith; - return 1; /* Success */ - } - return 0; /* No match */ -} -#endif - -#ifndef SQLITE_OMIT_CTE -/* -** If the SELECT passed as the second argument has an associated WITH -** clause, pop it from the stack stored as part of the Parse object. -** -** This function is used as the xSelectCallback2() callback by -** sqlite3SelectExpand() when walking a SELECT tree to resolve table -** names and other FROM clause elements. -*/ -SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){ - Parse *pParse = pWalker->pParse; - if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){ - With *pWith = findRightmost(p)->pWith; - if( pWith!=0 ){ - assert( pParse->pWith==pWith || pParse->nErr ); - pParse->pWith = pWith->pOuter; - } - } -} -#endif - -/* -** The SrcItem structure passed as the second argument represents a -** sub-query in the FROM clause of a SELECT statement. This function -** allocates and populates the SrcItem.pTab object. If successful, -** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, -** SQLITE_NOMEM. -*/ -SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){ - Select *pSel; - Table *pTab; - - assert( pFrom->fg.isSubquery ); - assert( pFrom->u4.pSubq!=0 ); - pSel = pFrom->u4.pSubq->pSelect; - assert( pSel ); - pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); - if( pTab==0 ) return SQLITE_NOMEM; - pTab->nTabRef = 1; - if( pFrom->zAlias ){ - pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); - }else{ - pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); - } - while( pSel->pPrior ){ pSel = pSel->pPrior; } - sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); - pTab->iPKey = -1; - pTab->eTabType = TABTYP_VIEW; - pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW - /* The usual case - do not allow ROWID on a subquery */ - pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; -#else - /* Legacy compatibility mode */ - pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid; -#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( 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: -** -** (1) Make sure VDBE cursor numbers have been assigned to every -** element of the FROM clause. -** -** (2) Fill in the pTabList->a[].pTab fields in the SrcList that -** defines FROM clause. When views appear in the FROM clause, -** fill pTabList->a[].pSelect with a copy of the SELECT statement -** that implements the view. A copy is made of the view's SELECT -** statement so that we can freely modify or delete that statement -** without worrying about messing up the persistent representation -** of the view. -** -** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword -** on joins and the ON and USING clause of joins. -** -** (4) Scan the list of columns in the result set (pEList) looking -** for instances of the "*" operator or the TABLE.* operator. -** If found, expand each "*" to be every column in every table -** and TABLE.* to be every column in TABLE. -** -*/ -static int selectExpander(Walker *pWalker, Select *p){ - Parse *pParse = pWalker->pParse; - int i, j, k, rc; - SrcList *pTabList; - ExprList *pEList; - SrcItem *pFrom; - sqlite3 *db = pParse->db; - Expr *pE, *pRight, *pExpr; - u16 selFlags = p->selFlags; - u32 elistFlags = 0; - - p->selFlags |= SF_Expanded; - if( db->mallocFailed ){ - return WRC_Abort; - } - assert( p->pSrc!=0 ); - if( (selFlags & SF_Expanded)!=0 ){ - return WRC_Prune; - } - if( pWalker->eCode ){ - /* Renumber selId because it has been copied from a view */ - p->selId = ++pParse->nSelect; - } - pTabList = p->pSrc; - pEList = p->pEList; - if( pParse->pWith && (p->selFlags & SF_View) ){ - if( p->pWith==0 ){ - p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) ); - if( p->pWith==0 ){ - return WRC_Abort; - } - } - p->pWith->bView = 1; - } - sqlite3WithPush(pParse, p->pWith, 0); - - /* Make sure cursor numbers have been assigned to all entries in - ** the FROM clause of the SELECT statement. - */ - sqlite3SrcListAssignCursors(pParse, pTabList); - - /* Look up every table named in the FROM clause of the select. If - ** an entry of the FROM clause is a subquery instead of a table or view, - ** then create a transient table structure to describe the subquery. - */ - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab; - assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 ); - if( pFrom->pSTab ) continue; - assert( pFrom->fg.isRecursive==0 ); - if( pFrom->zName==0 ){ -#ifndef SQLITE_OMIT_SUBQUERY - Select *pSel; - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 ); - pSel = pFrom->u4.pSubq->pSelect; - /* A sub-query in the FROM clause of a SELECT */ - assert( pSel!=0 ); - assert( pFrom->pSTab==0 ); - if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; - if( 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->pSTab; - assert( pTab!=0 ); -#endif - }else{ - /* An ordinary table or view name in the FROM clause */ - assert( pFrom->pSTab==0 ); - pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); - if( pTab==0 ) return WRC_Abort; - if( pTab->nTabRef>=0xffff ){ - sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", - pTab->zName); - pFrom->pSTab = 0; - return WRC_Abort; - } - pTab->nTabRef++; - if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ - return WRC_Abort; - } -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) - if( !IsOrdinaryTable(pTab) ){ - i16 nCol; - u8 eCodeOrig = pWalker->eCode; - if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; - assert( pFrom->fg.isSubquery==0 ); - if( IsView(pTab) ){ - if( (db->flags & SQLITE_EnableView)==0 - && pTab->pSchema!=db->aDb[1].pSchema - ){ - sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", - pTab->zName); - } - sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( ALWAYS(IsVirtual(pTab)) - && pFrom->fg.fromDDL - && ALWAYS(pTab->u.vtab.p!=0) - && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) - ){ - sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", - pTab->zName); - } - assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 ); -#endif - nCol = pTab->nCol; - pTab->nCol = -1; - pWalker->eCode = 1; /* Turn on Select.selId renumbering */ - if( pFrom->fg.isSubquery ){ - sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect); - } - pWalker->eCode = eCodeOrig; - pTab->nCol = nCol; - } -#endif - } - - /* Locate the index named by the INDEXED BY clause, if any. */ - if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){ - return WRC_Abort; - } - } - - /* Process NATURAL keywords, and ON and USING clauses of joins. - */ - assert( db->mallocFailed==0 || pParse->nErr!=0 ); - if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){ - return WRC_Abort; - } - - /* For every "*" that occurs in the column list, insert the names of - ** all columns in all tables. And for every TABLE.* insert the names - ** of all columns in TABLE. The parser inserted a special expression - ** with the TK_ASTERISK operator for each "*" that it found in the column - ** list. The following code just has to locate the TK_ASTERISK - ** expressions and expand each one to the list of all columns in - ** all tables. - ** - ** The first loop just checks to see if there are any "*" operators - ** that need expanding. - */ - for(k=0; knExpr; k++){ - pE = pEList->a[k].pExpr; - if( pE->op==TK_ASTERISK ) break; - assert( pE->op!=TK_DOT || pE->pRight!=0 ); - assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); - if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; - elistFlags |= pE->flags; - } - if( knExpr ){ - /* - ** If we get here it means the result set contains one or more "*" - ** operators that need to be expanded. Loop through each expression - ** in the result set and expand them one by one. - */ - struct ExprList_item *a = pEList->a; - ExprList *pNew = 0; - int flags = pParse->db->flags; - int longNames = (flags & SQLITE_FullColNames)!=0 - && (flags & SQLITE_ShortColNames)==0; - - for(k=0; knExpr; k++){ - pE = a[k].pExpr; - elistFlags |= pE->flags; - pRight = pE->pRight; - assert( pE->op!=TK_DOT || pRight!=0 ); - if( pE->op!=TK_ASTERISK - && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) - ){ - /* This particular expression does not need to be expanded. - */ - pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); - if( pNew ){ - pNew->a[pNew->nExpr-1].zEName = a[k].zEName; - pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName; - a[k].zEName = 0; - } - a[k].pExpr = 0; - }else{ - /* This expression is a "*" or a "TABLE.*" and needs to be - ** expanded. */ - int tableSeen = 0; /* Set to 1 when TABLE matches */ - char *zTName = 0; /* text of name of TABLE */ - int iErrOfst; - if( pE->op==TK_DOT ){ - assert( (selFlags & SF_NestedFrom)==0 ); - assert( pE->pLeft!=0 ); - assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); - zTName = pE->pLeft->u.zToken; - assert( ExprUseWOfst(pE->pLeft) ); - iErrOfst = pE->pRight->w.iOfst; - }else{ - assert( ExprUseWOfst(pE) ); - iErrOfst = pE->w.iOfst; - } - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - int nAdd; /* Number of cols including rowid */ - Table *pTab = pFrom->pSTab; /* 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; - assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) ); - if( pFrom->fg.isNestedFrom ){ - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq ); - assert( pFrom->u4.pSubq->pSelect!=0 ); - pNestedFrom = pFrom->u4.pSubq->pSelect->pEList; - assert( pNestedFrom!=0 ); - assert( pNestedFrom->nExpr==pTab->nCol ); - assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid ); - }else{ - if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ - continue; - } - pNestedFrom = 0; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; - } - if( i+1nSrc - && pFrom[1].fg.isUsing - && (selFlags & SF_NestedFrom)!=0 - ){ - int ii; - pUsing = pFrom[1].u3.pUsing; - for(ii=0; iinId; ii++){ - const char *zUName = pUsing->a[ii].zName; - pRight = sqlite3Expr(db, TK_ID, zUName); - sqlite3ExprSetErrorOffset(pRight, iErrOfst); - pNew = sqlite3ExprListAppend(pParse, pNew, pRight); - if( pNew ){ - struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; - assert( pX->zEName==0 ); - pX->zEName = sqlite3MPrintf(db,"..%s", zUName); - pX->fg.eEName = ENAME_TAB; - pX->fg.bUsingTerm = 1; - } - } - }else{ - pUsing = 0; - } - - nAdd = pTab->nCol; - if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++; - for(j=0; jnCol ){ - zName = sqlite3RowidAlias(pTab); - if( zName==0 ) continue; - }else{ - zName = pTab->aCol[j].zCnName; - - /* If pTab is actually an SF_NestedFrom sub-select, do not - ** expand any ENAME_ROWID columns. */ - if( pNestedFrom && pNestedFrom->a[j].fg.eEName==ENAME_ROWID ){ - continue; - } - - if( zTName - && pNestedFrom - && sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0, 0)==0 - ){ - continue; - } - - /* If a column is marked as 'hidden', omit it from the expanded - ** result-set list unless the SELECT has the SF_IncludeHidden - ** bit set. - */ - if( (p->selFlags & SF_IncludeHidden)==0 - && IsHiddenColumn(&pTab->aCol[j]) - ){ - continue; - } - if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 - && zTName==0 - && (selFlags & (SF_NestedFrom))==0 - ){ - continue; - } - } - assert( zName ); - tableSeen = 1; - - if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){ - if( pFrom->fg.isUsing - && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0 - ){ - /* In a join with a USING clause, omit columns in the - ** using clause from the table on the right. */ - continue; - } - } - pRight = sqlite3Expr(db, TK_ID, zName); - 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 = sqlite3Expr(db, TK_ID, zTabName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - if( IN_RENAME_OBJECT && pE->pLeft ){ - sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft); - } - if( zSchemaName ){ - pLeft = sqlite3Expr(db, TK_ID, zSchemaName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); - } - }else{ - pExpr = pRight; - } - sqlite3ExprSetErrorOffset(pExpr, iErrOfst); - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); - 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 && (!ViewCanHaveRowid || jnExpr) ){ - assert( jnExpr ); - pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); - testcase( pX->zEName==0 ); - }else{ - pX->zEName = sqlite3MPrintf(db, "%s.%s.%s", - zSchemaName, zTabName, zName); - testcase( pX->zEName==0 ); - } - pX->fg.eEName = (j==pTab->nCol ? ENAME_ROWID : ENAME_TAB); - if( (pFrom->fg.isUsing - && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0) - || (pUsing && sqlite3IdListIndex(pUsing, zName)>=0) - || (jnCol && (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)) - ){ - pX->fg.bNoExpand = 1; - } - }else if( longNames ){ - pX->zEName = sqlite3MPrintf(db, "%s.%s", zTabName, zName); - pX->fg.eEName = ENAME_NAME; - }else{ - pX->zEName = sqlite3DbStrDup(db, zName); - pX->fg.eEName = ENAME_NAME; - } - } - } - if( !tableSeen ){ - if( zTName ){ - sqlite3ErrorMsg(pParse, "no such table: %s", zTName); - }else{ - sqlite3ErrorMsg(pParse, "no tables specified"); - } - } - } - } - sqlite3ExprListDelete(db, pEList); - p->pEList = pNew; - } - if( p->pEList ){ - if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns in result set"); - return WRC_Abort; - } - if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){ - p->selFlags |= SF_ComplexResult; - } - } -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x8 ){ - TREETRACE(0x8,pParse,p,("After result-set wildcard expansion:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - return WRC_Continue; -} - -#if SQLITE_DEBUG -/* -** Always assert. This xSelectCallback2 implementation proves that the -** xSelectCallback2 is never invoked. -*/ -SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - assert( 0 ); -} -#endif -/* -** This routine "expands" a SELECT statement and all of its subqueries. -** For additional information on what it means to "expand" a SELECT -** statement, see the comment on the selectExpand worker callback above. -** -** Expanding a SELECT statement is the first step in processing a -** SELECT statement. The SELECT statement must be expanded before -** name resolution is performed. -** -** If anything goes wrong, an error message is written into pParse. -** The calling function can detect the problem by looking at pParse->nErr -** and/or pParse->db->mallocFailed. -*/ -static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ - Walker w; - w.xExprCallback = sqlite3ExprWalkNoop; - w.pParse = pParse; - if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){ - w.xSelectCallback = convertCompoundSelectToSubquery; - w.xSelectCallback2 = 0; - sqlite3WalkSelect(&w, pSelect); - } - w.xSelectCallback = selectExpander; - w.xSelectCallback2 = sqlite3SelectPopWith; - w.eCode = 0; - sqlite3WalkSelect(&w, pSelect); -} - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() -** interface. -** -** For each FROM-clause subquery, add Column.zType, Column.zColl, and -** Column.affinity information to the Table structure that represents -** the result set of that subquery. -** -** The Table structure that represents the result set was constructed -** by selectExpander() but the type and collation and affinity information -** was omitted at that point because identifiers had not yet been resolved. -** This routine is called after identifier resolution. -*/ -static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ - Parse *pParse; - int i; - SrcList *pTabList; - SrcItem *pFrom; - - if( p->selFlags & SF_HasTypeInfo ) return; - p->selFlags |= SF_HasTypeInfo; - pParse = pWalker->pParse; - assert( (p->selFlags & SF_Resolved) ); - pTabList = p->pSrc; - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pSTab; - assert( pTab!=0 ); - if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){ - /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->u4.pSubq->pSelect; - sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE); - } - } -} -#endif - - -/* -** This routine adds datatype and collating sequence information to -** the Table structures of all FROM-clause subqueries in a -** SELECT statement. -** -** Use this routine after name resolution. -*/ -static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ -#ifndef SQLITE_OMIT_SUBQUERY - Walker w; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.xSelectCallback2 = selectAddSubqueryTypeInfo; - w.xExprCallback = sqlite3ExprWalkNoop; - w.pParse = pParse; - sqlite3WalkSelect(&w, pSelect); -#endif -} - - -/* -** This routine sets up a SELECT statement for processing. The -** following is accomplished: -** -** * VDBE Cursor numbers are assigned to all FROM-clause terms. -** * Ephemeral Table objects are created for all FROM-clause subqueries. -** * ON and USING clauses are shifted into WHERE statements -** * Wildcards "*" and "TABLE.*" in result sets are expanded. -** * Identifiers in expression are matched to tables. -** -** This routine acts recursively on all subqueries within the SELECT. -*/ -SQLITE_PRIVATE void sqlite3SelectPrep( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - NameContext *pOuterNC /* Name context for container */ -){ - assert( p!=0 || pParse->db->mallocFailed ); - assert( pParse->db->pParse==pParse ); - if( pParse->db->mallocFailed ) return; - if( p->selFlags & SF_HasTypeInfo ) return; - sqlite3SelectExpand(pParse, p); - if( pParse->nErr ) return; - sqlite3ResolveSelectNames(pParse, p, pOuterNC); - if( pParse->nErr ) return; - sqlite3SelectAddTypeInfo(pParse, p); -} - -#if TREETRACE_ENABLED -/* -** Display all information about an AggInfo object -*/ -static void printAggInfo(AggInfo *pAggInfo){ - int ii; - sqlite3DebugPrintf("AggInfo %d/%p:\n", - pAggInfo->selId, pAggInfo); - for(ii=0; iinColumn; ii++){ - struct AggInfo_col *pCol = &pAggInfo->aCol[ii]; - sqlite3DebugPrintf( - "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d" - " iSorterColumn=%d %s\n", - ii, pCol->pTab ? pCol->pTab->zName : "NULL", - pCol->iTable, pCol->iColumn, pAggInfo->iFirstReg+ii, - pCol->iSorterColumn, - ii>=pAggInfo->nAccumulator ? "" : " Accumulator"); - sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0); - } - for(ii=0; iinFunc; ii++){ - sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n", - ii, pAggInfo->iFirstReg+pAggInfo->nColumn+ii); - sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0); - } -} -#endif /* TREETRACE_ENABLED */ - -/* -** Analyze the arguments to aggregate functions. Create new pAggInfo->aCol[] -** entries for columns that are arguments to aggregate functions but which -** are not otherwise used. -** -** The aCol[] entries in AggInfo prior to nAccumulator are columns that -** are referenced outside of aggregate functions. These might be columns -** that are part of the GROUP by clause, for example. Other database engines -** would throw an error if there is a column reference that is not in the -** GROUP BY clause and that is not part of an aggregate function argument. -** But SQLite allows this. -** -** The aCol[] entries beginning with the aCol[nAccumulator] and following -** are column references that are used exclusively as arguments to -** aggregate functions. This routine is responsible for computing -** (or recomputing) those aCol[] entries. -*/ -static void analyzeAggFuncArgs( - AggInfo *pAggInfo, - NameContext *pNC -){ - int i; - assert( pAggInfo!=0 ); - assert( pAggInfo->iFirstReg==0 ); - pNC->ncFlags |= NC_InAggFunc; - for(i=0; inFunc; i++){ - Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( pExpr->op==TK_FUNCTION || pExpr->op==TK_AGG_FUNCTION ); - assert( ExprUseXList(pExpr) ); - sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList); - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - sqlite3ExprAnalyzeAggList(pNC, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( !IsWindowFunc(pExpr) ); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3ExprAnalyzeAggregates(pNC, pExpr->y.pWin->pFilter); - } -#endif - } - pNC->ncFlags &= ~NC_InAggFunc; -} - -/* -** An index on expressions is being used in the inner loop of an -** aggregate query with a GROUP BY clause. This routine attempts -** to adjust the AggInfo object to take advantage of index and to -** perhaps use the index as a covering index. -** -*/ -static void optimizeAggregateUseOfIndexedExpr( - Parse *pParse, /* Parsing context */ - Select *pSelect, /* The SELECT statement being processed */ - AggInfo *pAggInfo, /* The aggregate info */ - NameContext *pNC /* Name context used to resolve agg-func args */ -){ - assert( pAggInfo->iFirstReg==0 ); - assert( pSelect!=0 ); - assert( pSelect->pGroupBy!=0 ); - pAggInfo->nColumn = pAggInfo->nAccumulator; - if( ALWAYS(pAggInfo->nSortingColumn>0) ){ - int mx = pSelect->pGroupBy->nExpr - 1; - int j, k; - for(j=0; jnColumn; j++){ - k = pAggInfo->aCol[j].iSorterColumn; - if( k>mx ) mx = k; - } - pAggInfo->nSortingColumn = mx+1; - } - analyzeAggFuncArgs(pAggInfo, pNC); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - IndexedExpr *pIEpr; - TREETRACE(0x20, pParse, pSelect, - ("AggInfo (possibly) adjusted for Indexed Exprs\n")); - sqlite3TreeViewSelect(0, pSelect, 0); - for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ - printf("data-cursor=%d index={%d,%d}\n", - pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol); - sqlite3TreeViewExpr(0, pIEpr->pExpr, 0); - } - printAggInfo(pAggInfo); - } -#else - UNUSED_PARAMETER(pSelect); - UNUSED_PARAMETER(pParse); -#endif -} - -/* -** Walker callback for aggregateConvertIndexedExprRefToColumn(). -*/ -static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){ - AggInfo *pAggInfo; - struct AggInfo_col *pCol; - UNUSED_PARAMETER(pWalker); - if( pExpr->pAggInfo==0 ) return WRC_Continue; - if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue; - if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue; - if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue; - pAggInfo = pExpr->pAggInfo; - if( NEVER(pExpr->iAgg>=pAggInfo->nColumn) ) return WRC_Continue; - assert( pExpr->iAgg>=0 ); - pCol = &pAggInfo->aCol[pExpr->iAgg]; - pExpr->op = TK_AGG_COLUMN; - pExpr->iTable = pCol->iTable; - pExpr->iColumn = pCol->iColumn; - ExprClearProperty(pExpr, EP_Skip|EP_Collate|EP_Unlikely); - return WRC_Prune; -} - -/* -** Convert every pAggInfo->aFunc[].pExpr such that any node within -** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN -** opcode. -*/ -static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){ - int i; - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = aggregateIdxEprRefToColCallback; - for(i=0; inFunc; i++){ - sqlite3WalkExpr(&w, pAggInfo->aFunc[i].pFExpr); - } -} - - -/* -** Allocate a block of registers so that there is one register for each -** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo. The first -** register in this block is stored in pAggInfo->iFirstReg. -** -** This routine may only be called once for each AggInfo object. Prior -** to calling this routine: -** -** * The aCol[] and aFunc[] arrays may be modified -** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used -** -** After calling this routine: -** -** * The aCol[] and aFunc[] arrays are fixed -** * The AggInfoColumnReg() and AggInfoFuncReg() macros may be used -** -*/ -static void assignAggregateRegisters(Parse *pParse, AggInfo *pAggInfo){ - assert( pAggInfo!=0 ); - assert( pAggInfo->iFirstReg==0 ); - pAggInfo->iFirstReg = pParse->nMem + 1; - pParse->nMem += pAggInfo->nColumn + pAggInfo->nFunc; -} - -/* -** Reset the aggregate accumulator. -** -** The aggregate accumulator is a set of memory cells that hold -** intermediate results while calculating an aggregate. This -** routine generates code that stores NULLs in all of those memory -** cells. -*/ -static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ - Vdbe *v = pParse->pVdbe; - int i; - struct AggInfo_func *pFunc; - int nReg = pAggInfo->nFunc + pAggInfo->nColumn; - assert( pAggInfo->iFirstReg>0 ); - assert( pParse->db->pParse==pParse ); - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); - if( nReg==0 ) return; - if( pParse->nErr ) return; - sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->iFirstReg, - pAggInfo->iFirstReg+nReg-1); - for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ - if( pFunc->iDistinct>=0 ){ - Expr *pE = pFunc->pFExpr; - assert( ExprUseXList(pE) ); - if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ - sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " - "argument"); - pFunc->iDistinct = -1; - }else{ - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); - pFunc->iDistAddr = 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)); - } - } - if( pFunc->iOBTab>=0 ){ - ExprList *pOBList; - KeyInfo *pKeyInfo; - int nExtra = 0; - assert( pFunc->pFExpr->pLeft!=0 ); - assert( pFunc->pFExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pFunc->pFExpr->pLeft) ); - assert( pFunc->pFunc!=0 ); - pOBList = pFunc->pFExpr->pLeft->x.pList; - if( !pFunc->bOBUnique ){ - nExtra++; /* One extra column for the OP_Sequence */ - } - if( pFunc->bOBPayload ){ - /* extra columns for the function arguments */ - assert( ExprUseXList(pFunc->pFExpr) ); - nExtra += pFunc->pFExpr->x.pList->nExpr; - } - if( pFunc->bUseSubtype ){ - nExtra += pFunc->pFExpr->x.pList->nExpr; - } - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra); - if( !pFunc->bOBUnique && pParse->nErr==0 ){ - pKeyInfo->nKeyField++; - } - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - pFunc->iOBTab, pOBList->nExpr+nExtra, 0, - (char*)pKeyInfo, P4_KEYINFO); - ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(ORDER BY)", - pFunc->pFunc->zName)); - } - } -} - -/* -** Invoke the OP_AggFinalize opcode for every aggregate function -** in the AggInfo structure. -*/ -static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ - Vdbe *v = pParse->pVdbe; - int i; - struct AggInfo_func *pF; - for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - ExprList *pList; - assert( ExprUseXList(pF->pFExpr) ); - if( pParse->nErr ) return; - pList = pF->pFExpr->x.pList; - if( pF->iOBTab>=0 ){ - /* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs - ** were stored in emphermal table pF->iOBTab. Here, we extract those - ** inputs (in ORDER BY order) and make all calls to OP_AggStep - ** before doing the OP_AggFinal call. */ - int iTop; /* Start of loop for extracting columns */ - int nArg; /* Number of columns to extract */ - int nKey; /* Key columns to be skipped */ - int regAgg; /* Extract into this array */ - int j; /* Loop counter */ - - assert( pF->pFunc!=0 ); - nArg = pList->nExpr; - regAgg = sqlite3GetTempRange(pParse, nArg); - - if( pF->bOBPayload==0 ){ - nKey = 0; - }else{ - assert( pF->pFExpr->pLeft!=0 ); - assert( ExprUseXList(pF->pFExpr->pLeft) ); - assert( pF->pFExpr->pLeft->x.pList!=0 ); - nKey = pF->pFExpr->pLeft->x.pList->nExpr; - if( ALWAYS(!pF->bOBUnique) ) nKey++; - } - iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v); - for(j=nArg-1; j>=0; j--){ - sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j); - } - if( pF->bUseSubtype ){ - int regSubtype = sqlite3GetTempReg(pParse); - int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0); - for(j=nArg-1; j>=0; j--){ - sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype); - sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j); - } - sqlite3ReleaseTempReg(pParse, regSubtype); - } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, iTop); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); - } - sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i), - pList ? pList->nExpr : 0); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - } -} - -/* -** Generate code that will update the accumulator memory cells for an -** aggregate based on the current cursor position. -** -** If regAcc is non-zero and there are no min() or max() aggregates -** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator -** registers if register regAcc contains 0. The caller will take care -** of setting and clearing regAcc. -** -** For an ORDER BY aggregate, the actual accumulator memory cell update -** is deferred until after all input rows have been received, so that they -** can be run in the requested order. In that case, instead of invoking -** OP_AggStep to update the accumulator, just add the arguments that would -** have been passed into OP_AggStep into the sorting ephemeral table -** (along with the appropriate sort key). -*/ -static void updateAccumulator( - Parse *pParse, - int regAcc, - AggInfo *pAggInfo, - int eDistinctType -){ - Vdbe *v = pParse->pVdbe; - int i; - int regHit = 0; - int addrHitTest = 0; - struct AggInfo_func *pF; - struct AggInfo_col *pC; - - assert( pAggInfo->iFirstReg>0 ); - if( pParse->nErr ) return; - pAggInfo->directMode = 1; - for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - int nArg; - int addrNext = 0; - int regAgg; - int regAggSz = 0; - int regDistinct = 0; - ExprList *pList; - assert( ExprUseXList(pF->pFExpr) ); - assert( !IsWindowFunc(pF->pFExpr) ); - assert( pF->pFunc!=0 ); - pList = pF->pFExpr->x.pList; - if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ - Expr *pFilter = pF->pFExpr->y.pWin->pFilter; - if( pAggInfo->nAccumulator - && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) - && regAcc - ){ - /* If regAcc==0, there there exists some min() or max() function - ** without a FILTER clause that will ensure the magnet registers - ** are populated. */ - if( regHit==0 ) regHit = ++pParse->nMem; - /* If this is the first row of the group (regAcc contains 0), clear the - ** "magnet" register regHit so that the accumulator registers - ** are populated if the FILTER clause jumps over the the - ** invocation of min() or max() altogether. Or, if this is not - ** the first row (regAcc contains 1), set the magnet register so that - ** the accumulators are not populated unless the min()/max() is invoked - ** and indicates that they should be. */ - sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit); - } - addrNext = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL); - } - if( pF->iOBTab>=0 ){ - /* Instead of invoking AggStep, we must push the arguments that would - ** have been passed to AggStep onto the sorting table. */ - int jj; /* Registered used so far in building the record */ - ExprList *pOBList; /* The ORDER BY clause */ - assert( pList!=0 ); - nArg = pList->nExpr; - assert( nArg>0 ); - assert( pF->pFExpr->pLeft!=0 ); - assert( pF->pFExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pF->pFExpr->pLeft) ); - pOBList = pF->pFExpr->pLeft->x.pList; - assert( pOBList!=0 ); - assert( pOBList->nExpr>0 ); - regAggSz = pOBList->nExpr; - if( !pF->bOBUnique ){ - regAggSz++; /* One register for OP_Sequence */ - } - if( pF->bOBPayload ){ - regAggSz += nArg; - } - if( pF->bUseSubtype ){ - regAggSz += nArg; - } - regAggSz++; /* One extra register to hold result of MakeRecord */ - regAgg = sqlite3GetTempRange(pParse, regAggSz); - regDistinct = regAgg; - sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP); - jj = pOBList->nExpr; - if( !pF->bOBUnique ){ - sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj); - jj++; - } - if( pF->bOBPayload ){ - regDistinct = regAgg+jj; - sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP); - jj += nArg; - } - if( pF->bUseSubtype ){ - int kk; - int regBase = pF->bOBPayload ? regDistinct : regAgg; - for(kk=0; kknExpr; - regAgg = sqlite3GetTempRange(pParse, nArg); - regDistinct = regAgg; - sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); - }else{ - nArg = 0; - regAgg = 0; - } - if( pF->iDistinct>=0 && pList ){ - if( addrNext==0 ){ - addrNext = sqlite3VdbeMakeLabel(pParse); - } - pF->iDistinct = codeDistinct(pParse, eDistinctType, - pF->iDistinct, addrNext, pList, regDistinct); - } - if( pF->iOBTab>=0 ){ - /* Insert a new record into the ORDER BY table */ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regAgg, regAggSz-1, - regAgg+regAggSz-1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pF->iOBTab, regAgg+regAggSz-1, - regAgg, regAggSz-1); - sqlite3ReleaseTempRange(pParse, regAgg, regAggSz); - }else{ - /* Invoke the AggStep function */ - if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl = 0; - struct ExprList_item *pItem; - int j; - assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ - for(j=0, pItem=pList->a; !pColl && jpExpr); - } - if( !pColl ){ - pColl = pParse->db->pDfltColl; - } - if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, - (char *)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); - } - if( addrNext ){ - sqlite3VdbeResolveLabel(v, addrNext); - } - if( pParse->nErr ) return; - } - if( regHit==0 && pAggInfo->nAccumulator ){ - regHit = regAcc; - } - if( regHit ){ - addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); - } - for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ - sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i)); - if( pParse->nErr ) return; - } - - pAggInfo->directMode = 0; - if( addrHitTest ){ - sqlite3VdbeJumpHereOrPopInst(v, addrHitTest); - } -} - -/* -** Add a single OP_Explain instruction to the VDBE to explain a simple -** count(*) query ("SELECT count(*) FROM pTab"). -*/ -#ifndef SQLITE_OMIT_EXPLAIN -static void explainSimpleCount( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being queried */ - Index *pIdx /* Index used to optimize scan, or NULL */ -){ - if( pParse->explain==2 ){ - int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); - sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s", - pTab->zName, - bCover ? " USING COVERING INDEX " : "", - bCover ? pIdx->zName : "" - ); - } -} -#else -# define explainSimpleCount(a,b,c) -#endif - -/* -** sqlite3WalkExpr() callback used by havingToWhere(). -** -** If the node passed to the callback is a TK_AND node, return -** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes. -** -** Otherwise, return WRC_Prune. In this case, also check if the -** sub-expression matches the criteria for being moved to the WHERE -** clause. If so, add it to the WHERE clause and replace the sub-expression -** within the HAVING expression with a constant "1". -*/ -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( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) - && ExprAlwaysFalse(pExpr)==0 - && pExpr->pAggInfo==0 - ){ - sqlite3 *db = pWalker->pParse->db; - Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); - if( pNew ){ - Expr *pWhere = pS->pWhere; - SWAP(Expr, *pNew, *pExpr); - pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew); - pS->pWhere = pNew; - pWalker->eCode = 1; - } - } - return WRC_Prune; - } - return WRC_Continue; -} - -/* -** Transfer eligible terms from the HAVING clause of a query, which is -** processed after grouping, to the WHERE clause, which is processed before -** grouping. For example, the query: -** -** SELECT * FROM WHERE a=? GROUP BY b HAVING b=? AND c=? -** -** can be rewritten as: -** -** SELECT * FROM WHERE a=? AND b=? GROUP BY b HAVING c=? -** -** A term of the HAVING expression is eligible for transfer if it consists -** entirely of constants and expressions that are also GROUP BY terms that -** use the "BINARY" collation sequence. -*/ -static void havingToWhere(Parse *pParse, Select *p){ - Walker sWalker; - memset(&sWalker, 0, sizeof(sWalker)); - sWalker.pParse = pParse; - sWalker.xExprCallback = havingToWhereExprCb; - sWalker.u.pSelect = p; - sqlite3WalkExpr(&sWalker, p->pHaving); -#if TREETRACE_ENABLED - if( sWalker.eCode && (sqlite3TreeTrace & 0x100)!=0 ){ - TREETRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif -} - -/* -** Check to see if the pThis entry of pTabList is a self-join of another view. -** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst -** but stopping before iEnd. -** -** If pThis is a self-join, then return the SrcItem for the first other -** instance of that view found. If pThis is not a self-join then return 0. -*/ -static SrcItem *isSelfJoinView( - SrcList *pTabList, /* Search for self-joins in this FROM clause */ - SrcItem *pThis, /* Search for prior reference to this subquery */ - int iFirst, int iEnd /* Range of FROM-clause entries to search. */ -){ - SrcItem *pItem; - Select *pSel; - assert( pThis->fg.isSubquery ); - pSel = pThis->u4.pSubq->pSelect; - assert( pSel!=0 ); - if( pSel->selFlags & SF_PushDown ) return 0; - while( iFirsta[iFirst++]; - if( !pItem->fg.isSubquery ) continue; - if( pItem->fg.viaCoroutine ) continue; - if( pItem->zName==0 ) continue; - assert( pItem->pSTab!=0 ); - assert( pThis->pSTab!=0 ); - if( pItem->pSTab->pSchema!=pThis->pSTab->pSchema ) continue; - if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue; - pS1 = pItem->u4.pSubq->pSelect; - if( pItem->pSTab->pSchema==0 && pSel->selId!=pS1->selId ){ - /* The query flattener left two different CTE tables with identical - ** names in the same FROM clause. */ - continue; - } - if( pS1->selFlags & SF_PushDown ){ - /* The view was modified by some other optimization such as - ** pushDownWhereTerms() */ - continue; - } - return pItem; - } - return 0; -} - -/* -** Deallocate a single AggInfo object -*/ -static void agginfoFree(sqlite3 *db, void *pArg){ - AggInfo *p = (AggInfo*)pArg; - sqlite3DbFree(db, p->aCol); - sqlite3DbFree(db, p->aFunc); - sqlite3DbFreeNN(db, p); -} - -/* -** Attempt to transform a query of the form -** -** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) -** -** Into this: -** -** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) -** -** The transformation only works if all of the following are true: -** -** * The subquery is a UNION ALL of two or more terms -** * The subquery does not have a LIMIT clause -** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries -** * The outer query is a simple count(*) with no WHERE clause or other -** extraneous syntax. -** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10) -** -** Return TRUE if the optimization is undertaken. -*/ -static int countOfViewOptimization(Parse *pParse, Select *p){ - Select *pSub, *pPrior; - Expr *pExpr; - Expr *pCount; - sqlite3 *db; - SrcItem *pFrom; - if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ - if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ - if( p->pWhere ) return 0; - if( p->pHaving ) return 0; - if( p->pGroupBy ) return 0; - if( p->pOrderBy ) return 0; - pExpr = p->pEList->a[0].pExpr; - if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ - assert( ExprUseUToken(pExpr) ); - if( 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 */ - if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */ - pFrom = p->pSrc->a; - if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */ - pSub = pFrom->u4.pSubq->pSelect; - if( pSub->pPrior==0 ) return 0; /* Must be a compound */ - if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */ - do{ - if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ - if( pSub->pWhere ) return 0; /* No WHERE clause */ - if( pSub->pLimit ) return 0; /* No LIMIT clause */ - if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){ - testcase( pSub->selFlags & SF_Aggregate ); - testcase( pSub->selFlags & SF_Distinct ); - return 0; /* Not an aggregate nor DISTINCT */ - } - assert( pSub->pHaving==0 ); /* Due to the previous */ - pSub = pSub->pPrior; /* Repeat over compound */ - }while( pSub ); - - /* If we reach this point then it is OK to perform the transformation */ - - db = pParse->db; - pCount = pExpr; - pExpr = 0; - pSub = sqlite3SubqueryDetach(db, pFrom); - sqlite3SrcListDelete(db, p->pSrc); - p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); - while( pSub ){ - Expr *pTerm; - pPrior = pSub->pPrior; - pSub->pPrior = 0; - pSub->pNext = 0; - pSub->selFlags |= SF_Aggregate; - pSub->selFlags &= ~(u32)SF_Compound; - pSub->nSelectRow = 0; - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList); - pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; - pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); - pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, pTerm, pSub); - if( pExpr==0 ){ - pExpr = pTerm; - }else{ - pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr); - } - pSub = pPrior; - } - p->pEList->a[0].pExpr = pExpr; - p->selFlags &= ~(u32)SF_Aggregate; - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x200 ){ - TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - return 1; -} - -/* -** 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; inSrc; i++){ - SrcItem *p1 = &pSrc->a[i]; - if( p1==p0 ) continue; - if( p0->pSTab==p1->pSTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){ - return 1; - } - if( p1->fg.isSubquery - && (p1->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 - && sameSrcAlias(p0, p1->u4.pSubq->pSelect->pSrc) - ){ - return 1; - } - } - return 0; -} - -/* -** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can -** be implemented as a co-routine. The i-th entry is guaranteed to be -** a subquery. -** -** The subquery is implemented as a co-routine if all of the following are -** true: -** -** (1) The subquery will likely be implemented in the outer loop of -** the query. This will be the case if any one of the following -** conditions hold: -** (a) The subquery is the only term in the FROM clause -** (b) The subquery is the left-most term and a CROSS JOIN or similar -** requires it to be the outer loop -** (c) All of the following are true: -** (i) The subquery is the left-most subquery in the FROM clause -** (ii) There is nothing that would prevent the subquery from -** being used as the outer loop if the sqlite3WhereBegin() -** routine nominates it to that position. -** (iii) The query is not a UPDATE ... FROM -** (2) The subquery is not a CTE that should be materialized because -** (a) the AS MATERIALIZED keyword is used, or -** (b) the CTE is used multiple times and does not have the -** NOT MATERIALIZED keyword -** (3) The subquery is not part of a left operand for a RIGHT JOIN -** (4) The SQLITE_Coroutine optimization disable flag is not set -** (5) The subquery is not self-joined -*/ -static int fromClauseTermCanBeCoroutine( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* FROM clause */ - int i, /* Which term of the FROM clause holds the subquery */ - int selFlags /* Flags on the SELECT statement */ -){ - SrcItem *pItem = &pTabList->a[i]; - if( pItem->fg.isCte ){ - const CteUse *pCteUse = pItem->u2.pCteUse; - if( pCteUse->eM10d==M10d_Yes ) return 0; /* (2a) */ - if( pCteUse->nUse>=2 && pCteUse->eM10d!=M10d_No ) return 0; /* (2b) */ - } - if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ - if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ - if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ - return 0; /* (5) */ - } - if( i==0 ){ - if( pTabList->nSrc==1 ) return 1; /* (1a) */ - if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1b) */ - if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ - return 1; - } - if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ - while( 1 /*exit-by-break*/ ){ - if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; /* (1c-ii) */ - if( i==0 ) break; - i--; - pItem--; - if( pItem->fg.isSubquery ) return 0; /* (1c-i) */ - } - return 1; -} - -/* -** Generate byte-code for the SELECT statement given in the p argument. -** -** The results are returned according to the SelectDest structure. -** See comments in sqliteInt.h for further information. -** -** This routine returns the number of errors. If any errors are -** encountered, then an appropriate error message is left in -** pParse->zErrMsg. -** -** This routine does NOT free the Select structure passed in. The -** calling function needs to do that. -** -** This is a long function. The following is an outline of the processing -** steps, with tags referencing various milestones: -** -** * Resolve names and similar preparation tag-select-0100 -** * Scan of the FROM clause tag-select-0200 -** + OUTER JOIN strength reduction tag-select-0220 -** + Sub-query ORDER BY removal tag-select-0230 -** + Query flattening tag-select-0240 -** * Separate subroutine for compound-SELECT tag-select-0300 -** * WHERE-clause constant propagation tag-select-0330 -** * Count()-of-VIEW optimization tag-select-0350 -** * Scan of the FROM clause again tag-select-0400 -** + Authorize unreferenced tables tag-select-0410 -** + Predicate push-down optimization tag-select-0420 -** + Omit unused subquery columns optimization tag-select-0440 -** + Generate code to implement subqueries tag-select-0480 -** - Co-routines tag-select-0482 -** - Reuse previously computed CTE tag-select-0484 -** - REuse previously computed VIEW tag-select-0486 -** - Materialize a VIEW or CTE tag-select-0488 -** * DISTINCT ORDER BY -> GROUP BY optimization tag-select-0500 -** * Set up for ORDER BY tag-select-0600 -** * Create output table tag-select-0630 -** * Prepare registers for LIMIT tag-select-0650 -** * Setup for DISTINCT tag-select-0680 -** * Generate code for non-aggregate and non-GROUP BY tag-select-0700 -** * Generate code for aggregate and/or GROUP BY tag-select-0800 -** + GROUP BY queries tag-select-0810 -** + non-GROUP BY queries tag-select-0820 -** - Special case of count() w/o GROUP BY tag-select-0821 -** - General case of non-GROUP BY aggregates tag-select-0822 -** * Sort results, as needed tag-select-0900 -** * Internal self-checks tag-select-1000 -*/ -SQLITE_PRIVATE int sqlite3Select( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - SelectDest *pDest /* What to do with the query results */ -){ - int i, j; /* Loop counters */ - WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ - Vdbe *v; /* The virtual machine under construction */ - int isAgg; /* True for select lists like "count(*)" */ - ExprList *pEList = 0; /* List of columns to extract. */ - SrcList *pTabList; /* List of tables to select from */ - Expr *pWhere; /* The WHERE clause. May be NULL */ - ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ - Expr *pHaving; /* The HAVING clause. May be NULL */ - AggInfo *pAggInfo = 0; /* Aggregate information */ - int rc = 1; /* Value to return from this function */ - DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ - SortCtx sSort; /* Info on how to code the ORDER BY clause */ - int iEnd; /* Address of the end of the query */ - sqlite3 *db; /* The database connection */ - ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ - u8 minMaxFlag; /* Flag for min/max queries */ - - db = pParse->db; - assert( pParse==db->pParse ); - v = sqlite3GetVdbe(pParse); - if( p==0 || pParse->nErr ){ - return 1; - } - assert( db->mallocFailed==0 ); - if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; -#if TREETRACE_ENABLED - TREETRACE(0x1,pParse,p, ("begin processing:\n", pParse->addrExplain)); - if( sqlite3TreeTrace & 0x10000 ){ - if( (sqlite3TreeTrace & 0x10001)==0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Select() at %s:%d", - __FILE__, __LINE__); - } - sqlite3ShowSelect(p); - } -#endif - - /* tag-select-0100 */ - assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); - if( IgnorableDistinct(pDest) ){ - assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || - 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 */ - if( p->pOrderBy ){ -#if TREETRACE_ENABLED - TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n")); - if( sqlite3TreeTrace & 0x800 ){ - sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY"); - } -#endif - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, - p->pOrderBy); - testcase( pParse->earlyCleanup ); - p->pOrderBy = 0; - } - p->selFlags &= ~(u32)SF_Distinct; - p->selFlags |= SF_NoopOrderBy; - } - sqlite3SelectPrep(pParse, p, 0); - if( pParse->nErr ){ - goto select_end; - } - assert( db->mallocFailed==0 ); - assert( p->pEList!=0 ); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10 ){ - TREETRACE(0x10,pParse,p, ("after name resolution:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - - /* 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]). - ** - ** 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) ){ - sqlite3ErrorMsg(pParse, - "target object/alias may not appear in FROM clause: %s", - p0->zAlias ? p0->zAlias : p0->pSTab->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 &= ~(u32)SF_UFSrcCheck; - } - - if( pDest->eDest==SRT_Output ){ - sqlite3GenerateColumnNames(pParse, p); - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( sqlite3WindowRewrite(pParse, p) ){ - assert( pParse->nErr ); - goto select_end; - } -#if TREETRACE_ENABLED - if( p->pWin && (sqlite3TreeTrace & 0x40)!=0 ){ - TREETRACE(0x40,pParse,p, ("after window rewrite:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif -#endif /* SQLITE_OMIT_WINDOWFUNC */ - pTabList = p->pSrc; - isAgg = (p->selFlags & SF_Aggregate)!=0; - memset(&sSort, 0, sizeof(sSort)); - sSort.pOrderBy = p->pOrderBy; - - /* Try to do various optimizations (flattening subqueries, and strength - ** reduction of join operators) in the FROM clause up into the main query - ** tag-select-0200 - */ -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - for(i=0; !p->pPrior && inSrc; i++){ - SrcItem *pItem = &pTabList->a[i]; - Select *pSub = pItem->fg.isSubquery ? pItem->u4.pSubq->pSelect : 0; - Table *pTab = pItem->pSTab; - - /* The expander should have already created transient Table objects - ** even for FROM clause elements such as subqueries that do not correspond - ** to a real table */ - assert( pTab!=0 ); - - /* Try to simplify joins: - ** - ** LEFT JOIN -> JOIN - ** RIGHT JOIN -> JOIN - ** FULL JOIN -> RIGHT JOIN - ** - ** If terms of the i-th table are used in the WHERE clause in such a - ** way that the i-th table cannot be the NULL row of a join, then - ** perform the appropriate simplification. This is called - ** "OUTER JOIN strength reduction" in the SQLite documentation. - ** tag-select-0220 - */ - if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 - && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor, - pItem->fg.jointype & JT_LTORJ) - && OptimizationEnabled(db, SQLITE_SimplifyJoin) - ){ - if( pItem->fg.jointype & JT_LEFT ){ - if( pItem->fg.jointype & JT_RIGHT ){ - TREETRACE(0x1000,pParse,p, - ("FULL-JOIN simplifies to RIGHT-JOIN on term %d\n",i)); - pItem->fg.jointype &= ~JT_LEFT; - }else{ - TREETRACE(0x1000,pParse,p, - ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); - pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); - unsetJoinExpr(p->pWhere, pItem->iCursor, 0); - } - } - if( pItem->fg.jointype & JT_LTORJ ){ - for(j=i+1; jnSrc; j++){ - SrcItem *pI2 = &pTabList->a[j]; - if( pI2->fg.jointype & JT_RIGHT ){ - if( pI2->fg.jointype & JT_LEFT ){ - TREETRACE(0x1000,pParse,p, - ("FULL-JOIN simplifies to LEFT-JOIN on term %d\n",j)); - pI2->fg.jointype &= ~JT_RIGHT; - }else{ - TREETRACE(0x1000,pParse,p, - ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); - pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); - unsetJoinExpr(p->pWhere, pI2->iCursor, 1); - } - } - } - for(j=pTabList->nSrc-1; j>=0; j--){ - pTabList->a[j].fg.jointype &= ~JT_LTORJ; - if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; - } - } - } - - /* No further action if this term of the FROM clause is not a subquery */ - if( pSub==0 ) continue; - - /* Catch mismatch in the declared columns of a view and the number of - ** columns in the SELECT on the RHS */ - if( pTab->nCol!=pSub->pEList->nExpr ){ - sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", - pTab->nCol, pTab->zName, pSub->pEList->nExpr); - goto select_end; - } - - /* Do not attempt the usual optimizations (flattening and ORDER BY - ** elimination) on a MATERIALIZED common table expression because - ** a MATERIALIZED common table expression is an optimization fence. - */ - if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ - continue; - } - - /* Do not try to flatten an aggregate subquery. - ** - ** Flattening an aggregate subquery is only possible if the outer query - ** is not a join. But if the outer query is not a join, then the subquery - ** will be implemented as a co-routine and there is no advantage to - ** flattening in that case. - */ - if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; - assert( pSub->pGroupBy==0 ); - - /* tag-select-0230: - ** 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 - ** (6) The subquery is not a recursive CTE. ORDER BY has a different - ** meaning for recursive CTEs and this optimization does not - ** apply. - ** - ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. - */ - if( pSub->pOrderBy!=0 - && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ - && pSub->pLimit==0 /* Condition (1) */ - && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */ - && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */ - && OptimizationEnabled(db, SQLITE_OmitOrderBy) - ){ - TREETRACE(0x800,pParse,p, - ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, - 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 - ** it will be implemented as a co-routine, then do not flatten. This - ** restriction allows SQL constructs like this: - ** - ** SELECT expensive_function(x) - ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10); - ** - ** The expensive_function() is only computed on the 10 rows that - ** are output, rather than every row of the table. - ** - ** The requirement that the outer query have a complex result set - ** means that flattening does occur on simpler SQL constraints without - ** the expensive_function() like: - ** - ** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10); - */ - if( pSub->pOrderBy!=0 - && i==0 - && (p->selFlags & SF_ComplexResult)!=0 - && (pTabList->nSrc==1 - || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) - ){ - continue; - } - - /* tag-select-0240 */ - if( flattenSubquery(pParse, p, i, isAgg) ){ - if( pParse->nErr ) goto select_end; - /* This subquery can be absorbed into its parent. */ - i = -1; - } - pTabList = p->pSrc; - if( db->mallocFailed ) goto select_end; - if( !IgnorableOrderby(pDest) ){ - sSort.pOrderBy = p->pOrderBy; - } - } -#endif - -#ifndef SQLITE_OMIT_COMPOUND_SELECT - /* Handle compound SELECT statements using the separate multiSelect() - ** procedure. tag-select-0300 - */ - if( p->pPrior ){ - rc = multiSelect(pParse, p, pDest); -#if TREETRACE_ENABLED - TREETRACE(0x400,pParse,p,("end compound-select processing\n")); - if( (sqlite3TreeTrace & 0x400)!=0 && ExplainQueryPlanParent(pParse)==0 ){ - sqlite3TreeViewSelect(0, p, 0); - } -#endif - if( p->pNext==0 ) ExplainQueryPlanPop(pParse); - return rc; - } -#endif - - /* Do the WHERE-clause constant propagation optimization if this is - ** a join. No need to spend time on this operation for non-join queries - ** as the equivalent optimization will be handled by query planner in - ** sqlite3WhereBegin(). tag-select-0330 - */ - if( p->pWhere!=0 - && p->pWhere->op==TK_AND - && OptimizationEnabled(db, SQLITE_PropagateConst) - && propagateConstants(pParse, p) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x2000 ){ - TREETRACE(0x2000,pParse,p,("After constant propagation:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - }else{ - TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n")); - } - - /* tag-select-0350 */ - if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) - && countOfViewOptimization(pParse, p) - ){ - if( db->mallocFailed ) goto select_end; - pTabList = p->pSrc; - } - - /* Loop over all terms in the FROM clause and do two things for each term: - ** - ** (1) Authorize unreferenced tables - ** (2) Generate code for all sub-queries - ** - ** tag-select-0400 - */ - for(i=0; inSrc; i++){ - SrcItem *pItem = &pTabList->a[i]; - SrcItem *pPrior; - SelectDest dest; - Subquery *pSubq; - Select *pSub; -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - const char *zSavedAuthContext; -#endif - - /* Authorized unreferenced tables. tag-select-0410 - ** - ** Issue SQLITE_READ authorizations with a fake column name for any - ** tables that are referenced but from which no values are extracted. - ** Examples of where these kinds of null SQLITE_READ authorizations - ** would occur: - ** - ** SELECT count(*) FROM t1; -- SQLITE_READ t1."" - ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2."" - ** - ** The fake column name is an empty string. It is possible for a table to - ** have a column named by the empty string, in which case there is no way to - ** distinguish between an unreferenced table and an actual reference to the - ** "" column. The original design was for the fake column name to be a NULL, - ** which would be unambiguous. But legacy authorization callbacks might - ** assume the column name is non-NULL and segfault. The use of an empty - ** string for the fake column name seems safer. - */ - if( pItem->colUsed==0 && pItem->zName!=0 ){ - const char *zDb; - if( pItem->fg.fixedSchema ){ - int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema); - zDb = db->aDb[iDb].zDbSName; - }else if( pItem->fg.isSubquery ){ - zDb = 0; - }else{ - zDb = pItem->u4.zDatabase; - } - sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", zDb); - } - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - /* Generate code for all sub-queries in the FROM clause - */ - if( pItem->fg.isSubquery==0 ) continue; - pSubq = pItem->u4.pSubq; - assert( pSubq!=0 ); - pSub = pSubq->pSelect; - - /* The code for a subquery should only be generated once. */ - if( pSubq->addrFillSub!=0 ) continue; - - /* Increment Parse.nHeight by the height of the largest expression - ** tree referred to by this, the parent select. The child select - ** may contain expression trees of at most - ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit - ** more conservative than necessary, but much easier than enforcing - ** an exact limit. - */ - pParse->nHeight += sqlite3SelectExprHeight(p); - - /* Make copies of constant WHERE-clause terms in the outer query down - ** inside the subquery. This can help the subquery to run more efficiently. - ** This is the "predicate push-down optimization". tag-select-0420 - */ - if( OptimizationEnabled(db, SQLITE_PushDown) - && (pItem->fg.isCte==0 - || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2)) - && pushDownWhereTerms(pParse, pSub, p->pWhere, pTabList, i) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4000 ){ - TREETRACE(0x4000,pParse,p, - ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 ); - }else{ - TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n")); - } - - /* Convert unused result columns of the subquery into simple NULL - ** expressions, to avoid unneeded searching and computation. - ** tag-select-0440 - */ - if( OptimizationEnabled(db, SQLITE_NullUnusedCols) - && disableUnusedSubqueryResultColumns(pItem) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4000 ){ - TREETRACE(0x4000,pParse,p, - ("Change unused result columns to NULL for subquery %d:\n", - pSub->selId)); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - } - - zSavedAuthContext = pParse->zAuthContext; - pParse->zAuthContext = pItem->zName; - - /* Generate byte-code to implement the subquery tag-select-0480 - */ - if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){ - /* Implement a co-routine that will return a single row of the result - ** set on each invocation. tag-select-0482 - */ - int addrTop = sqlite3VdbeCurrentAddr(v)+1; - - pSubq->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, pSubq->regReturn, 0, addrTop); - VdbeComment((v, "%!S", pItem)); - pSubq->addrFillSub = addrTop; - sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn); - ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem)); - sqlite3Select(pParse, pSub, &dest); - pItem->pSTab->nRowLogEst = pSub->nSelectRow; - pItem->fg.viaCoroutine = 1; - pSubq->regResult = dest.iSdst; - sqlite3VdbeEndCoroutine(v, pSubq->regReturn); - VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeJumpHere(v, addrTop-1); - sqlite3ClearTempRegCache(pParse); - }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, - ** then make the pItem->iCursor be a copy of the ephemeral table that - ** holds the result of the materialization. tag-select-0484 */ - CteUse *pCteUse = pItem->u2.pCteUse; - sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e); - if( pItem->iCursor!=pCteUse->iCur ){ - sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur); - VdbeComment((v, "%!S", pItem)); - } - pSub->nSelectRow = pCteUse->nRowEst; - }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){ - /* This view has already been materialized by a prior entry in - ** this same FROM clause. Reuse it. tag-select-0486 */ - Subquery *pPriorSubq; - assert( pPrior->fg.isSubquery ); - pPriorSubq = pPrior->u4.pSubq; - assert( pPriorSubq!=0 ); - if( pPriorSubq->addrFillSub ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pPriorSubq->regReturn, - pPriorSubq->addrFillSub); - } - sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); - pSub->nSelectRow = pPriorSubq->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. tag-select-0488 */ - int topAddr; - int onceAddr = 0; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; -#endif - - pSubq->regReturn = ++pParse->nMem; - topAddr = sqlite3VdbeAddOp0(v, OP_Goto); - pSubq->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 = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - VdbeComment((v, "materialize %!S", pItem)); - }else{ - VdbeNoopComment((v, "materialize %!S", pItem)); - } - sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - - ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem)); - sqlite3Select(pParse, pSub, &dest); - pItem->pSTab->nRowLogEst = pSub->nSelectRow; - if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); - sqlite3VdbeAddOp2(v, OP_Return, pSubq->regReturn, topAddr+1); - VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); - sqlite3VdbeJumpHere(v, topAddr); - sqlite3ClearTempRegCache(pParse); - if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){ - CteUse *pCteUse = pItem->u2.pCteUse; - pCteUse->addrM9e = pSubq->addrFillSub; - pCteUse->regRtn = pSubq->regReturn; - pCteUse->iCur = pItem->iCursor; - pCteUse->nRowEst = pSub->nSelectRow; - } - } - if( db->mallocFailed ) goto select_end; - pParse->nHeight -= sqlite3SelectExprHeight(p); - pParse->zAuthContext = zSavedAuthContext; -#endif - } - - /* Various elements of the SELECT copied into local variables for - ** convenience */ - pEList = p->pEList; - pWhere = p->pWhere; - pGroupBy = p->pGroupBy; - pHaving = p->pHaving; - sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x8000 ){ - TREETRACE(0x8000,pParse,p,("After all FROM-clause analysis:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - - /* tag-select-0500 - ** - ** If the query is DISTINCT with an ORDER BY but is not an aggregate, and - ** if the select-list is the same as the ORDER BY list, then this query - ** can be rewritten as a GROUP BY. In other words, this: - ** - ** SELECT DISTINCT xyz FROM ... ORDER BY xyz - ** - ** is transformed to: - ** - ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz - ** - ** The second form is preferred as a single index (or temp-table) may be - ** used for both the ORDER BY and DISTINCT processing. As originally - ** written the query must use a temp-table for at least one of the ORDER - ** BY and DISTINCT, and an index or separate temp-table for the other. - */ - if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct - && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 - && OptimizationEnabled(db, SQLITE_GroupByOrder) -#ifndef SQLITE_OMIT_WINDOWFUNC - && p->pWin==0 -#endif - ){ - p->selFlags &= ~(u32)SF_Distinct; - pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); - if( pGroupBy ){ - for(i=0; inExpr; i++){ - pGroupBy->a[i].u.x.iOrderByCol = i+1; - } - } - p->selFlags |= SF_Aggregate; - /* Notice that even thought SF_Distinct has been cleared from p->selFlags, - ** the sDistinct.isTnct is still set. Hence, isTnct represents the - ** original setting of the SF_Distinct flag, not the current setting */ - assert( sDistinct.isTnct ); - sDistinct.isTnct = 2; - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20000 ){ - TREETRACE(0x20000,pParse,p,("Transform DISTINCT into GROUP BY:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - } - - /* If there is an ORDER BY clause, then create an ephemeral index to - ** do the sorting. But this sorting ephemeral index might end up - ** being unused if the data can be extracted in pre-sorted order. - ** If that is the case, then the OP_OpenEphemeral instruction will be - ** changed to an OP_Noop once we figure out that the sorting index is - ** not needed. The sSort.addrSortIndex variable is used to facilitate - ** that change. tag-select-0600 - */ - if( sSort.pOrderBy ){ - KeyInfo *pKeyInfo; - pKeyInfo = sqlite3KeyInfoFromExprList( - pParse, sSort.pOrderBy, 0, pEList->nExpr); - sSort.iECursor = pParse->nTab++; - sSort.addrSortIndex = - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, - (char*)pKeyInfo, P4_KEYINFO - ); - }else{ - sSort.addrSortIndex = -1; - } - - /* If the output is destined for a temporary table, open that table. - ** tag-select-0630 - */ - if( pDest->eDest==SRT_EphemTab ){ - 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--){ - sqlite3ExprDelete(db, pEList->a[ii].pExpr); - sqlite3DbFree(db, pEList->a[ii].zEName); - pEList->nExpr--; - } - for(ii=0; iinExpr; ii++){ - if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL; - } - } - } - - /* Set the limiter. tag-select-0650 - */ - iEnd = sqlite3VdbeMakeLabel(pParse); - if( (p->selFlags & SF_FixedLimit)==0 ){ - p->nSelectRow = 320; /* 4 billion rows */ - } - if( p->pLimit ) computeLimitRegisters(pParse, p, iEnd); - if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ - sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); - sSort.sortFlags |= SORTFLAG_UseSorter; - } - - /* Open an ephemeral index to use for the distinct set. tag-select-0680 - */ - if( p->selFlags & SF_Distinct ){ - sDistinct.tabTnct = pParse->nTab++; - sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sDistinct.tabTnct, 0, 0, - (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0), - P4_KEYINFO); - sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; - }else{ - sDistinct.eTnctType = WHERE_DISTINCT_NOOP; - } - - if( !isAgg && pGroupBy==0 ){ - /* No aggregate functions and no GROUP BY clause. tag-select-0700 */ - u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) - | (p->selFlags & SF_FixedLimit); -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin = p->pWin; /* Main window object (or NULL) */ - if( pWin ){ - sqlite3WindowCodeInit(pParse, p); - } -#endif - assert( WHERE_USE_LIMIT==SF_FixedLimit ); - - - /* Begin the database scan. */ - TREETRACE(0x2,pParse,p,("WhereBegin\n")); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, - p->pEList, p, wctrlFlags, p->nSelectRow); - if( pWInfo==0 ) goto select_end; - if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ - p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); - if( pDest->eDest<=SRT_DistQueue && pDest->eDest>=SRT_DistFifo ){ - /* TUNING: For a UNION CTE, because UNION is implies DISTINCT, - ** reduce the estimated output row count by 8 (LogEst 30). - ** Search for tag-20250414a to see other cases */ - p->nSelectRow -= 30; - } - } - if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){ - sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo); - } - if( sSort.pOrderBy ){ - sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); - sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); - if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ - sSort.pOrderBy = 0; - } - } - TREETRACE(0x2,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 - ** into an OP_Noop. - */ - if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ - sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); - } - - assert( p->pEList==pEList ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ - int addrGosub = sqlite3VdbeMakeLabel(pParse); - int iCont = sqlite3VdbeMakeLabel(pParse); - int iBreak = sqlite3VdbeMakeLabel(pParse); - int regGosub = ++pParse->nMem; - - sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub); - - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); - sqlite3VdbeResolveLabel(v, addrGosub); - VdbeNoopComment((v, "inner-loop subroutine")); - sSort.labelOBLopt = 0; - selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp1(v, OP_Return, regGosub); - VdbeComment((v, "end inner-loop subroutine")); - sqlite3VdbeResolveLabel(v, iBreak); - }else -#endif /* SQLITE_OMIT_WINDOWFUNC */ - { - /* Use the standard inner loop. */ - selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, - sqlite3WhereContinueLabel(pWInfo), - sqlite3WhereBreakLabel(pWInfo)); - - /* End the database scan loop. - */ - TREETRACE(0x2,pParse,p,("WhereEnd\n")); - sqlite3WhereEnd(pWInfo); - } - }else{ - /* This case is for when there exist aggregate functions or a GROUP BY - ** clause or both. tag-select-0800 */ - NameContext sNC; /* Name context for processing aggregate information */ - int iAMem; /* First Mem address for storing current GROUP BY */ - int iBMem; /* First Mem address for previous GROUP BY */ - int iUseFlag; /* Mem address holding flag indicating that at least - ** one row of the input to the aggregator has been - ** processed */ - int iAbortFlag; /* Mem address which causes query abort if positive */ - int groupBySort; /* Rows come from source in GROUP BY order */ - int addrEnd; /* End of processing for this SELECT */ - int sortPTab = 0; /* Pseudotable used to decode sorting results */ - int sortOut = 0; /* Output register from the sorter */ - int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */ - - /* Remove any and all aliases between the result set and the - ** GROUP BY clause. - */ - if( pGroupBy ){ - int k; /* Loop counter */ - struct ExprList_item *pItem; /* For looping over expression in a list */ - - for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){ - pItem->u.x.iAlias = 0; - } - for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){ - pItem->u.x.iAlias = 0; - } - assert( 66==sqlite3LogEst(100) ); - if( p->nSelectRow>66 ) p->nSelectRow = 66; - - /* If there is both a GROUP BY and an ORDER BY clause and they are - ** identical, then it may be possible to disable the ORDER BY clause - ** on the grounds that the GROUP BY will cause elements to come out - ** in the correct order. It also may not - the GROUP BY might use a - ** database index that causes rows to be grouped together as required - ** but not actually sorted. Either way, record the fact that the - ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp - ** variable. */ - if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){ - int ii; - /* The GROUP BY processing doesn't care whether rows are delivered in - ** ASC or DESC order - only that each group is returned contiguously. - ** So set the ASC/DESC flags in the GROUP BY to match those in the - ** ORDER BY to maximize the chances of rows being delivered in an - ** order that makes the ORDER BY redundant. */ - for(ii=0; iinExpr; ii++){ - u8 sortFlags; - sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; - pGroupBy->a[ii].fg.sortFlags = sortFlags; - } - if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ - orderByGrp = 1; - } - } - }else{ - assert( 0==sqlite3LogEst(1) ); - p->nSelectRow = 0; - } - - /* Create a label to jump to when we want to abort the query */ - addrEnd = sqlite3VdbeMakeLabel(pParse); - - /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in - ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the - ** SELECT statement. - */ - pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); - if( pAggInfo ){ - sqlite3ParserAddCleanup(pParse, agginfoFree, pAggInfo); - testcase( pParse->earlyCleanup ); - } - if( db->mallocFailed ){ - goto select_end; - } - pAggInfo->selId = p->selId; -#ifdef SQLITE_DEBUG - pAggInfo->pSelect = p; -#endif - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - sNC.uNC.pAggInfo = pAggInfo; - VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) - pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; - pAggInfo->pGroupBy = pGroupBy; - sqlite3ExprAnalyzeAggList(&sNC, pEList); - sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); - if( pHaving ){ - if( pGroupBy ){ - assert( pWhere==p->pWhere ); - assert( pHaving==p->pHaving ); - assert( pGroupBy==p->pGroupBy ); - havingToWhere(pParse, p); - pWhere = p->pWhere; - } - sqlite3ExprAnalyzeAggregates(&sNC, pHaving); - } - pAggInfo->nAccumulator = pAggInfo->nColumn; - if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){ - minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy); - }else{ - minMaxFlag = WHERE_ORDERBY_NORMAL; - } - analyzeAggFuncArgs(pAggInfo, &sNC); - if( db->mallocFailed ) goto select_end; -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20,pParse,p,("After aggregate analysis %p:\n", pAggInfo)); - sqlite3TreeViewSelect(0, p, 0); - if( minMaxFlag ){ - sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag); - sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY"); - } - printAggInfo(pAggInfo); - } -#endif - - - /* Processing for aggregates with GROUP BY is very different and - ** much more complex than aggregates without a GROUP BY. tag-select-0810 - */ - if( pGroupBy ){ - KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int addr1; /* A-vs-B comparison jump */ - int addrOutputRow; /* Start of subroutine that outputs a result row */ - int regOutputRow; /* Return address register for output subroutine */ - int addrSetAbort; /* Set the abort flag and return */ - int addrTopOfLoop; /* Top of the input loop */ - 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 = sqlite3ExprDup(db, pExpr, 0); - pDistinct = sqlite3ExprListDup(db, pGroupBy, 0); - pDistinct = 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 - ** that we do not need it after all, the OP_SorterOpen instruction - ** will be converted into a Noop. - */ - pAggInfo->sortingIdx = pParse->nTab++; - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy, - 0, pAggInfo->nColumn); - addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, - pAggInfo->sortingIdx, pAggInfo->nSortingColumn, - 0, (char*)pKeyInfo, P4_KEYINFO); - - /* Initialize memory locations used by GROUP BY aggregate processing - */ - iUseFlag = ++pParse->nMem; - iAbortFlag = ++pParse->nMem; - regOutputRow = ++pParse->nMem; - addrOutputRow = sqlite3VdbeMakeLabel(pParse); - regReset = ++pParse->nMem; - addrReset = sqlite3VdbeMakeLabel(pParse); - iAMem = pParse->nMem + 1; - pParse->nMem += pGroupBy->nExpr; - iBMem = pParse->nMem + 1; - pParse->nMem += pGroupBy->nExpr; - sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); - VdbeComment((v, "clear abort flag")); - sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); - sqlite3ExprNullRegisterRange(pParse, iAMem, pGroupBy->nExpr); - - /* Begin a loop that will extract all source rows in GROUP BY order. - ** This might involve two separate loops with an OP_Sort in between, or - ** it might be a single loop that uses an index to extract information - ** in the right order to begin with. - */ - sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - TREETRACE(0x2,pParse,p,("WhereBegin\n")); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct, - p, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY) - | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0 - ); - if( pWInfo==0 ){ - sqlite3ExprListDelete(db, pDistinct); - goto select_end; - } - if( pParse->pIdxEpr ){ - optimizeAggregateUseOfIndexedExpr(pParse, p, pAggInfo, &sNC); - } - assignAggregateRegisters(pParse, pAggInfo); - eDist = sqlite3WhereIsDistinct(pWInfo); - TREETRACE(0x2,pParse,p,("WhereBegin returns\n")); - if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ - /* The optimizer is able to deliver rows in group by order so - ** we do not have to sort. The OP_OpenEphemeral table will be - ** cancelled later because we still need to use the pKeyInfo - */ - groupBySort = 0; - }else{ - /* Rows are coming out in undetermined order. We have to push - ** each row into a sorting index, terminate the first loop, - ** then loop over the sorting index in order to get the output - ** in sorted order - */ - int regBase; - int regRecord; - int nCol; - int nGroupBy; - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExp; /* Address of OP_Explain instruction */ -#endif - ExplainQueryPlan2(addrExp, (pParse, 0, "USE TEMP B-TREE FOR %s", - (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? - "DISTINCT" : "GROUP BY" - )); - - groupBySort = 1; - nGroupBy = pGroupBy->nExpr; - nCol = nGroupBy; - j = nGroupBy; - for(i=0; inColumn; i++){ - if( pAggInfo->aCol[i].iSorterColumn>=j ){ - nCol++; - j++; - } - } - regBase = sqlite3GetTempRange(pParse, nCol); - sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); - j = nGroupBy; - pAggInfo->directMode = 1; - for(i=0; inColumn; i++){ - struct AggInfo_col *pCol = &pAggInfo->aCol[i]; - if( pCol->iSorterColumn>=j ){ - sqlite3ExprCode(pParse, pCol->pCExpr, j + regBase); - j++; - } - } - pAggInfo->directMode = 0; - regRecord = sqlite3GetTempReg(pParse); - sqlite3VdbeScanStatusCounters(v, addrExp, 0, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); - sqlite3VdbeScanStatusRange(v, addrExp, sqlite3VdbeCurrentAddr(v)-2, -1); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3ReleaseTempRange(pParse, regBase, nCol); - TREETRACE(0x2,pParse,p,("WhereEnd\n")); - sqlite3WhereEnd(pWInfo); - pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; - sortOut = sqlite3GetTempReg(pParse); - sqlite3VdbeScanStatusCounters(v, addrExp, sqlite3VdbeCurrentAddr(v), 0); - sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); - sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); - VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); - pAggInfo->useSortingIdx = 1; - sqlite3VdbeScanStatusRange(v, addrExp, -1, sortPTab); - sqlite3VdbeScanStatusRange(v, addrExp, -1, pAggInfo->sortingIdx); - } - - /* If there are entries in pAgggInfo->aFunc[] that contain subexpressions - ** that are indexed (and that were previously identified and tagged - ** in optimizeAggregateUseOfIndexedExpr()) then those subexpressions - ** must now be converted into a TK_AGG_COLUMN node so that the value - ** is correctly pulled from the index rather than being recomputed. */ - if( pParse->pIdxEpr ){ - aggregateConvertIndexedExprRefToColumn(pAggInfo); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20, pParse, p, - ("AggInfo function expressions converted to reference index\n")); - sqlite3TreeViewSelect(0, p, 0); - printAggInfo(pAggInfo); - } -#endif - } - - /* If the index or temporary table used by the GROUP BY sort - ** will naturally deliver rows in the order required by the ORDER BY - ** clause, cancel the ephemeral table open coded earlier. - ** - ** This is an optimization - the correct answer should result regardless. - ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to - ** disable this optimization for testing purposes. */ - if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) - && (groupBySort || sqlite3WhereIsSorted(pWInfo)) - ){ - sSort.pOrderBy = 0; - sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); - } - - /* Evaluate the current GROUP BY terms and store in b0, b1, b2... - ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) - ** Then compare the current GROUP BY terms against the GROUP BY terms - ** from the previous row currently stored in a0, a1, a2... - */ - addrTopOfLoop = sqlite3VdbeCurrentAddr(v); - if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx, - sortOut, sortPTab); - } - for(j=0; jnExpr; j++){ - int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol; - - if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); - }else{ - pAggInfo->directMode = 1; - sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); - } - - if( iOrderByCol ){ - Expr *pX = p->pEList->a[iOrderByCol-1].pExpr; - Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX); - while( ALWAYS(pBase!=0) && pBase->op==TK_IF_NULL_ROW ){ - pX = pBase->pLeft; - pBase = sqlite3ExprSkipCollateAndLikely(pX); - } - if( ALWAYS(pBase!=0) - && pBase->op!=TK_AGG_COLUMN - && pBase->op!=TK_REGISTER - ){ - sqlite3ExprToRegister(pX, iAMem+j); - } - } - } - sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, - (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - addr1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v); - - /* Generate code that runs whenever the GROUP BY changes. - ** Changes in the GROUP BY are detected by the previous code - ** block. If there were no changes, this block is skipped. - ** - ** This code copies current group by terms in b0,b1,b2,... - ** over to a0,a1,a2. It then calls the output subroutine - ** and resets the aggregate accumulator registers in preparation - ** for the next GROUP BY batch. - */ - sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output one row")); - sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); - sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v); - VdbeComment((v, "check abort flag")); - sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - VdbeComment((v, "reset accumulator")); - - /* Update the aggregate accumulators based on the content of - ** the current row - */ - sqlite3VdbeJumpHere(v, addr1); - updateAccumulator(pParse, iUseFlag, pAggInfo, eDist); - sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); - VdbeComment((v, "indicate data in accumulator")); - - /* End of the loop - */ - if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); - VdbeCoverage(v); - }else{ - TREETRACE(0x2,pParse,p,("WhereEnd\n")); - sqlite3WhereEnd(pWInfo); - sqlite3VdbeChangeToNoop(v, addrSortingIdx); - } - sqlite3ExprListDelete(db, pDistinct); - - /* Output the final row of result - */ - sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output final row")); - - /* Jump over the subroutines - */ - sqlite3VdbeGoto(v, addrEnd); - - /* Generate a subroutine that outputs a single row of the result - ** set. This subroutine first looks at the iUseFlag. If iUseFlag - ** is less than or equal to zero, the subroutine is a no-op. If - ** the processing calls for the query to abort, this subroutine - ** increments the iAbortFlag memory location before returning in - ** order to signal the caller to abort. - */ - addrSetAbort = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag); - VdbeComment((v, "set abort flag")); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - sqlite3VdbeResolveLabel(v, addrOutputRow); - addrOutputRow = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); - VdbeCoverage(v); - VdbeComment((v, "Groupby result generator entry point")); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - finalizeAggFunctions(pParse, pAggInfo); - sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, -1, &sSort, - &sDistinct, pDest, - addrOutputRow+1, addrSetAbort); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - VdbeComment((v, "end groupby result generator")); - - /* Generate a subroutine that will reset the group-by accumulator - */ - sqlite3VdbeResolveLabel(v, addrReset); - resetAccumulator(pParse, pAggInfo); - sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); - VdbeComment((v, "indicate accumulator empty")); - 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 { - /* Aggregate functions without GROUP BY. tag-select-0820 */ - Table *pTab; - if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){ - /* tag-select-0821 - ** - ** If isSimpleCount() returns a pointer to a Table structure, then - ** the SQL statement is of the form: - ** - ** SELECT count(*) FROM - ** - ** where the Table structure returned represents table . - ** - ** This statement is so common that it is optimized specially. The - ** OP_Count instruction is executed either on the intkey table that - ** contains the data for table or on one of its indexes. It - ** is better to execute the op on an index, as indexes are almost - ** always spread across less pages than their corresponding tables. - */ - const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ - Index *pIdx; /* Iterator variable */ - KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ - Index *pBest = 0; /* Best index found so far */ - Pgno iRoot = pTab->tnum; /* Root page of scanned b-tree */ - - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - - /* Search for the index that has the lowest scan cost. - ** - ** (2011-04-15) Do not do a full scan of an unordered index. - ** - ** (2013-10-03) Do not count the entries in a partial index. - ** - ** In practice the KeyInfo structure will not be used. It is only - ** passed to keep OP_OpenRead happy. - */ - if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab); - if( !p->pSrc->a[0].fg.notIndexed ){ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->bUnordered==0 - && pIdx->szIdxRowszTabRow - && pIdx->pPartIdxWhere==0 - && (!pBest || pIdx->szIdxRowszIdxRow) - ){ - pBest = pIdx; - } - } - } - if( pBest ){ - iRoot = pBest->tnum; - pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest); - } - - /* Open a read-only cursor, execute the OP_Count, close the cursor. */ - sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1); - if( pKeyInfo ){ - sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); - } - assignAggregateRegisters(pParse, pAggInfo); - sqlite3VdbeAddOp2(v, OP_Count, iCsr, AggInfoFuncReg(pAggInfo,0)); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); - explainSimpleCount(pParse, pTab, pBest); - }else{ - /* The general case of an aggregate query without GROUP BY - ** tag-select-0822 */ - int regAcc = 0; /* "populate accumulators" flag */ - 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 - ** will contain 0 the first time the inner loop runs, and 1 thereafter. - ** The code generated by updateAccumulator() uses this to ensure - ** that the accumulator registers are (a) updated only once if - ** there are no min() or max functions or (b) always updated for the - ** first row visited by the aggregate, so that they are updated at - ** least once even if the FILTER clause means the min() or max() - ** function visits zero rows. */ - if( pAggInfo->nAccumulator ){ - for(i=0; inFunc; i++){ - if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){ - continue; - } - if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){ - break; - } - } - if( i==pAggInfo->nFunc ){ - regAcc = ++pParse->nMem; - 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; - } - assignAggregateRegisters(pParse, pAggInfo); - - /* This case runs if the aggregate has no GROUP BY clause. The - ** processing is much simpler since there is only a single row - ** of output. - */ - assert( p->pGroupBy==0 ); - resetAccumulator(pParse, pAggInfo); - - /* If this query is a candidate for the min/max optimization, then - ** minMaxFlag will have been previously set to either - ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will - ** be an appropriate ORDER BY expression for the optimization. - */ - assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); - assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); - - TREETRACE(0x2,pParse,p,("WhereBegin\n")); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, - pDistinct, p, minMaxFlag|distFlag, 0); - if( pWInfo==0 ){ - goto select_end; - } - TREETRACE(0x2,pParse,p,("WhereBegin returns\n")); - eDist = 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 ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); - if( minMaxFlag ){ - sqlite3WhereMinMaxOptEarlyOut(v, pWInfo); - } - TREETRACE(0x2,pParse,p,("WhereEnd\n")); - sqlite3WhereEnd(pWInfo); - finalizeAggFunctions(pParse, pAggInfo); - } - - sSort.pOrderBy = 0; - sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, -1, 0, 0, - pDest, addrEnd, addrEnd); - } - sqlite3VdbeResolveLabel(v, addrEnd); - - } /* endif aggregate query */ - - if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){ - explainTempTable(pParse, "DISTINCT"); - } - - /* If there is an ORDER BY clause, then we need to sort the results - ** and send them to the callback one by one. tag-select-0900 - */ - if( sSort.pOrderBy ){ - assert( p->pEList==pEList ); - generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); - } - - /* Jump here to skip this query - */ - sqlite3VdbeResolveLabel(v, iEnd); - - /* The SELECT has been coded. If there is an error in the Parse structure, - ** set the return code to 1. Otherwise 0. */ - rc = (pParse->nErr>0); - - /* Control jumps to here if an error is encountered above, or upon - ** successful coding of the SELECT. - */ -select_end: - assert( db->mallocFailed==0 || db->mallocFailed==1 ); - assert( db->mallocFailed==0 || pParse->nErr!=0 ); - sqlite3ExprListDelete(db, pMinMaxOrderBy); -#ifdef SQLITE_DEBUG - /* Internal self-checks. tag-select-1000 */ - if( pAggInfo && !db->mallocFailed ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20,pParse,p,("Finished with AggInfo\n")); - printAggInfo(pAggInfo); - } -#endif - for(i=0; inColumn; i++){ - Expr *pExpr = pAggInfo->aCol[i].pCExpr; - if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); - } - for(i=0; inFunc; i++){ - Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( pExpr!=0 ); - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); - } - } -#endif - -#if TREETRACE_ENABLED - TREETRACE(0x1,pParse,p,("end processing\n")); - if( (sqlite3TreeTrace & 0x40000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ - sqlite3TreeViewSelect(0, p, 0); - } -#endif - ExplainQueryPlanPop(pParse); - return rc; -} - -/************** End of select.c **********************************************/ -/************** Begin file table.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the sqlite3_get_table() and sqlite3_free_table() -** interface routines. These are just wrappers around the main -** interface routine of sqlite3_exec(). -** -** These routines are in a separate files so that they will not be linked -** if they are not used. -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_GET_TABLE - -/* -** This structure is used to pass data from sqlite3_get_table() through -** to the callback function is uses to build the result. -*/ -typedef struct TabResult { - char **azResult; /* Accumulated output */ - char *zErrMsg; /* Error message text, if an error occurs */ - u32 nAlloc; /* Slots allocated for azResult[] */ - u32 nRow; /* Number of rows in the result */ - u32 nColumn; /* Number of columns in the result */ - u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */ - int rc; /* Return code from sqlite3_exec() */ -} TabResult; - -/* -** This routine is called once for each row in the result table. Its job -** is to fill in the TabResult structure appropriately, allocating new -** memory as necessary. -*/ -static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ - TabResult *p = (TabResult*)pArg; /* Result accumulator */ - int need; /* Slots needed in p->azResult[] */ - int i; /* Loop counter */ - char *z; /* A single column of result */ - - /* Make sure there is enough space in p->azResult to hold everything - ** we need to remember from this invocation of the callback. - */ - if( p->nRow==0 && argv!=0 ){ - need = nCol*2; - }else{ - need = nCol; - } - if( p->nData + need > p->nAlloc ){ - char **azNew; - p->nAlloc = p->nAlloc*2 + need; - azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc ); - if( azNew==0 ) goto malloc_failed; - p->azResult = azNew; - } - - /* If this is the first row, then generate an extra row containing - ** the names of all columns. - */ - if( p->nRow==0 ){ - p->nColumn = nCol; - for(i=0; iazResult[p->nData++] = z; - } - }else if( (int)p->nColumn!=nCol ){ - sqlite3_free(p->zErrMsg); - p->zErrMsg = sqlite3_mprintf( - "sqlite3_get_table() called with two or more incompatible queries" - ); - p->rc = SQLITE_ERROR; - return 1; - } - - /* Copy over the row data - */ - if( argv!=0 ){ - for(i=0; iazResult[p->nData++] = z; - } - p->nRow++; - } - return 0; - -malloc_failed: - p->rc = SQLITE_NOMEM_BKPT; - return 1; -} - -/* -** Query the database. But instead of invoking a callback for each row, -** malloc() for space to hold the result and return the entire results -** at the conclusion of the call. -** -** The result that is written to ***pazResult is held in memory obtained -** from malloc(). But the caller cannot free this memory directly. -** Instead, the entire table should be passed to sqlite3_free_table() when -** the calling procedure is finished using it. -*/ -SQLITE_API int sqlite3_get_table( - sqlite3 *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - char ***pazResult, /* Write the result table here */ - int *pnRow, /* Write the number of rows in the result here */ - int *pnColumn, /* Write the number of columns of result here */ - char **pzErrMsg /* Write error messages here */ -){ - int rc; - TabResult res; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; -#endif - *pazResult = 0; - if( pnColumn ) *pnColumn = 0; - if( pnRow ) *pnRow = 0; - if( pzErrMsg ) *pzErrMsg = 0; - res.zErrMsg = 0; - res.nRow = 0; - res.nColumn = 0; - res.nData = 1; - res.nAlloc = 20; - res.rc = SQLITE_OK; - res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); - if( res.azResult==0 ){ - db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM_BKPT; - } - res.azResult[0] = 0; - rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); - assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); - res.azResult[0] = SQLITE_INT_TO_PTR(res.nData); - if( (rc&0xff)==SQLITE_ABORT ){ - sqlite3_free_table(&res.azResult[1]); - if( res.zErrMsg ){ - if( pzErrMsg ){ - sqlite3_free(*pzErrMsg); - *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg); - } - sqlite3_free(res.zErrMsg); - } - db->errCode = res.rc; /* Assume 32-bit assignment is atomic */ - return res.rc; - } - sqlite3_free(res.zErrMsg); - if( rc!=SQLITE_OK ){ - sqlite3_free_table(&res.azResult[1]); - return rc; - } - if( res.nAlloc>res.nData ){ - char **azNew; - azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData ); - if( azNew==0 ){ - sqlite3_free_table(&res.azResult[1]); - db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM_BKPT; - } - res.azResult = azNew; - } - *pazResult = &res.azResult[1]; - if( pnColumn ) *pnColumn = res.nColumn; - if( pnRow ) *pnRow = res.nRow; - return rc; -} - -/* -** This routine frees the space the sqlite3_get_table() malloced. -*/ -SQLITE_API void sqlite3_free_table( - char **azResult /* Result returned from sqlite3_get_table() */ -){ - if( azResult ){ - int i, n; - azResult--; - assert( azResult!=0 ); - n = SQLITE_PTR_TO_INT(azResult[0]); - for(i=1; ipNext; - - sqlite3ExprDelete(db, pTmp->pWhere); - sqlite3ExprListDelete(db, pTmp->pExprList); - sqlite3SelectDelete(db, pTmp->pSelect); - sqlite3IdListDelete(db, pTmp->pIdList); - sqlite3UpsertDelete(db, pTmp->pUpsert); - sqlite3SrcListDelete(db, pTmp->pFrom); - sqlite3DbFree(db, pTmp->zSpan); - - sqlite3DbFree(db, pTmp); - } -} - -/* -** Given table pTab, return a list of all the triggers attached to -** the table. The list is connected by Trigger.pNext pointers. -** -** All of the triggers on pTab that are in the same database as pTab -** are already attached to pTab->pTrigger. But there might be additional -** triggers on pTab in the TEMP schema. This routine prepends all -** TEMP triggers on pTab to the beginning of the pTab->pTrigger list -** and returns the combined list. -** -** To state it another way: This routine returns a list of all triggers -** that fire off of pTab. The list will include any TEMP triggers on -** pTab as well as the triggers lised in pTab->pTrigger. -*/ -SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ - 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==sqlite3StrICmp(pTrig->table, pTab->zName) - && (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning) - ){ - 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->isCreate ); - assert( &(pParse->u1.d.pReturning->retTrig) == pTrig ); - pTrig->table = pTab->zName; - pTrig->pTabSchema = pTab->pSchema; - pTrig->pNext = pList; - pList = pTrig; - } - p = sqliteHashNext(p); - } -#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); - } -#endif - return pList; -} - -/* -** This is called by the parser when it sees a CREATE TRIGGER statement -** up to the point of the BEGIN before the trigger actions. A Trigger -** structure is generated based on the information available and stored -** in pParse->pNewTrigger. After the trigger actions have been parsed, the -** sqlite3FinishTrigger() function is called to complete the trigger -** construction process. -*/ -SQLITE_PRIVATE void sqlite3BeginTrigger( - Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ - Token *pName1, /* The name of the trigger */ - Token *pName2, /* The name of the trigger */ - int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ - int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ - IdList *pColumns, /* column list if this is an UPDATE OF trigger */ - SrcList *pTableName,/* The name of the table/view the trigger applies to */ - Expr *pWhen, /* WHEN clause */ - int isTemp, /* True if the TEMPORARY keyword is present */ - int noErr /* Suppress errors if the trigger already exists */ -){ - Trigger *pTrigger = 0; /* The new trigger */ - Table *pTab; /* Table that the trigger fires off of */ - char *zName = 0; /* Name of the trigger */ - sqlite3 *db = pParse->db; /* The database connection */ - int iDb; /* The database to store the trigger in */ - Token *pName; /* The unqualified db name */ - DbFixer sFix; /* State vector for the DB fixer */ - - assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ - assert( pName2!=0 ); - assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); - assert( op>0 && op<0xff ); - if( isTemp ){ - /* If TEMP was specified, then the trigger name may not be qualified. */ - if( pName2->n>0 ){ - sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); - goto trigger_cleanup; - } - iDb = 1; - pName = pName1; - }else{ - /* Figure out the db that the trigger will be created in */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ){ - goto trigger_cleanup; - } - } - if( !pTableName || db->mallocFailed ){ - goto trigger_cleanup; - } - - /* A long-standing parser bug is that this syntax was allowed: - ** - ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... - ** ^^^^^^^^ - ** - ** To maintain backwards compatibility, ignore the database - ** name on pTableName if we are reparsing out of the schema table - */ - if( db->init.busy && iDb!=1 ){ - assert( pTableName->a[0].fg.fixedSchema==0 ); - assert( pTableName->a[0].fg.isSubquery==0 ); - sqlite3DbFree(db, pTableName->a[0].u4.zDatabase); - pTableName->a[0].u4.zDatabase = 0; - } - - /* If the trigger name was unqualified, and the table is a temp table, - ** then set iDb to 1 to create the trigger in the temporary database. - ** If sqlite3SrcListLookup() returns 0, indicating the table does not - ** exist, the error is caught by the block below. - */ - pTab = sqlite3SrcListLookup(pParse, pTableName); - if( db->init.busy==0 && pName2->n==0 && pTab - && pTab->pSchema==db->aDb[1].pSchema ){ - iDb = 1; - } - - /* Ensure the table name matches database name and that the table exists */ - if( db->mallocFailed ) goto trigger_cleanup; - assert( pTableName->nSrc==1 ); - sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName); - if( sqlite3FixSrcList(&sFix, pTableName) ){ - goto trigger_cleanup; - } - pTab = sqlite3SrcListLookup(pParse, pTableName); - if( !pTab ){ - /* The table does not exist. */ - goto trigger_orphan_error; - } - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); - goto trigger_orphan_error; - } - if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){ - sqlite3ErrorMsg(pParse, "cannot create triggers on shadow tables"); - goto trigger_orphan_error; - } - - /* Check that the trigger name is not reserved and that no trigger of the - ** specified name exists */ - zName = sqlite3NameFromToken(db, pName); - if( zName==0 ){ - assert( db->mallocFailed ); - goto trigger_cleanup; - } - if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){ - goto trigger_cleanup; - } - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !IN_RENAME_OBJECT ){ - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - VVA_ONLY( pParse->ifNotExists = 1; ) - } - goto trigger_cleanup; - } - } - - /* Do not create a trigger on a system table */ - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ - sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); - goto trigger_cleanup; - } - - /* INSTEAD of triggers are only for views and views only support INSTEAD - ** of triggers. - */ - if( IsView(pTab) && tr_tm!=TK_INSTEAD ){ - sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", - (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a); - goto trigger_orphan_error; - } - if( !IsView(pTab) && tr_tm==TK_INSTEAD ){ - sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" - " trigger on table: %S", pTableName->a); - goto trigger_orphan_error; - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( !IN_RENAME_OBJECT ){ - int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); - int code = SQLITE_CREATE_TRIGGER; - const char *zDb = db->aDb[iTabDb].zDbSName; - const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; - if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; - if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ - goto trigger_cleanup; - } - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ - goto trigger_cleanup; - } - } -#endif - - /* INSTEAD OF triggers can only appear on views and BEFORE triggers - ** cannot appear on views. So we might as well translate every - ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code - ** elsewhere. - */ - if (tr_tm == TK_INSTEAD){ - tr_tm = TK_BEFORE; - } - - /* Build the Trigger object */ - pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); - if( pTrigger==0 ) goto trigger_cleanup; - pTrigger->zName = zName; - zName = 0; - pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); - pTrigger->pSchema = db->aDb[iDb].pSchema; - pTrigger->pTabSchema = pTab->pSchema; - pTrigger->op = (u8)op; - pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName); - pTrigger->pWhen = pWhen; - pWhen = 0; - }else{ - pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); - } - pTrigger->pColumns = pColumns; - pColumns = 0; - assert( pParse->pNewTrigger==0 ); - pParse->pNewTrigger = pTrigger; - -trigger_cleanup: - sqlite3DbFree(db, zName); - sqlite3SrcListDelete(db, pTableName); - sqlite3IdListDelete(db, pColumns); - sqlite3ExprDelete(db, pWhen); - if( !pParse->pNewTrigger ){ - sqlite3DeleteTrigger(db, pTrigger); - }else{ - assert( pParse->pNewTrigger==pTrigger ); - } - return; - -trigger_orphan_error: - if( db->init.iDb==1 ){ - /* Ticket #3810. - ** Normally, whenever a table is dropped, all associated triggers are - ** dropped too. But if a TEMP trigger is created on a non-TEMP table - ** and the table is dropped by a different database connection, the - ** trigger is not visible to the database connection that does the - ** drop so the trigger cannot be dropped. This results in an - ** "orphaned trigger" - a trigger whose associated table is missing. - ** - ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df - */ - db->init.orphanTrigger = 1; - } - goto trigger_cleanup; -} - -/* -** This routine is called after all of the trigger actions have been parsed -** in order to complete the process of building the trigger. -*/ -SQLITE_PRIVATE void sqlite3FinishTrigger( - Parse *pParse, /* Parser context */ - TriggerStep *pStepList, /* The triggered program */ - Token *pAll /* Token that describes the complete CREATE TRIGGER */ -){ - Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ - char *zName; /* Name of trigger */ - sqlite3 *db = pParse->db; /* The database */ - DbFixer sFix; /* Fixer object */ - int iDb; /* Database containing the trigger */ - Token nameToken; /* Trigger name for error reporting */ - - pParse->pNewTrigger = 0; - if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; - zName = pTrig->zName; - iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); - pTrig->step_list = pStepList; - while( pStepList ){ - pStepList->pTrig = pTrig; - pStepList = pStepList->pNext; - } - sqlite3TokenInit(&nameToken, pTrig->zName); - sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); - if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) - || sqlite3FixExpr(&sFix, pTrig->pWhen) - ){ - goto triggerfinish_cleanup; - } - -#ifndef SQLITE_OMIT_ALTERTABLE - if( IN_RENAME_OBJECT ){ - assert( !db->init.busy ); - pParse->pNewTrigger = pTrig; - pTrig = 0; - }else -#endif - - /* if we are not initializing, - ** build the sqlite_schema entry - */ - if( !db->init.busy ){ - 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( sqlite3ReadOnlyShadowTables(db) ){ - TriggerStep *pStep; - for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget!=0 - && sqlite3ShadowTableName(db, pStep->zTarget) - ){ - 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 = sqlite3GetVdbe(pParse); - if( v==0 ) goto triggerfinish_cleanup; - sqlite3BeginWriteOperation(pParse, 0, iDb); - z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); - testcase( z==0 ); - sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE - " VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zDbSName, zName, - pTrig->table, z); - sqlite3DbFree(db, z); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0); - } - - if( db->init.busy ){ - Trigger *pLink = pTrig; - Hash *pHash = &db->aDb[iDb].pSchema->trigHash; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pLink!=0 ); - pTrig = sqlite3HashInsert(pHash, zName, pTrig); - if( pTrig ){ - sqlite3OomFault(db); - }else if( pLink->pSchema==pLink->pTabSchema ){ - Table *pTab; - pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); - assert( pTab!=0 ); - pLink->pNext = pTab->pTrigger; - pTab->pTrigger = pLink; - } - } - -triggerfinish_cleanup: - sqlite3DeleteTrigger(db, pTrig); - assert( IN_RENAME_OBJECT || !pParse->pNewTrigger ); - sqlite3DeleteTriggerStep(db, pStepList); -} - -/* -** Duplicate a range of text from an SQL statement, then convert all -** whitespace characters into ordinary space characters. -*/ -static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ - char *z = sqlite3DbSpanDup(db, zStart, zEnd); - int i; - if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' '; - return z; -} - -/* -** Turn a SELECT statement (that the pSelect parameter points to) into -** a trigger step. Return a pointer to a TriggerStep structure. -** -** The parser calls this routine when it finds a SELECT statement in -** body of a TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( - sqlite3 *db, /* Database connection */ - Select *pSelect, /* The SELECT statement */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep==0 ) { - sqlite3SelectDelete(db, pSelect); - return 0; - } - pTriggerStep->op = TK_SELECT; - pTriggerStep->pSelect = pSelect; - pTriggerStep->orconf = OE_Default; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); - return pTriggerStep; -} - -/* -** Allocate space to hold a new trigger step. The allocated space -** holds both the TriggerStep object and the TriggerStep.target.z string. -** -** If an OOM error occurs, NULL is returned and db->mallocFailed is set. -*/ -static TriggerStep *triggerStepAllocate( - Parse *pParse, /* Parser context */ - u8 op, /* Trigger opcode */ - Token *pName, /* The target name */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ - sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep; - - if( pParse->nErr ) return 0; - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); - if( pTriggerStep ){ - char *z = (char*)&pTriggerStep[1]; - memcpy(z, pName->z, pName->n); - sqlite3Dequote(z); - pTriggerStep->zTarget = z; - pTriggerStep->op = op; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); - } - } - return pTriggerStep; -} - -/* -** Build a trigger step out of an INSERT statement. Return a pointer -** to the new trigger step. -** -** The parser calls this routine when it sees an INSERT inside the -** body of a trigger. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( - Parse *pParse, /* Parser */ - Token *pTableName, /* Name of the table into which we insert */ - IdList *pColumn, /* List of columns in pTableName to insert into */ - Select *pSelect, /* A SELECT statement that supplies values */ - u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ - Upsert *pUpsert, /* ON CONFLICT clauses for upsert */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ - sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep; - - assert(pSelect != 0 || db->mallocFailed); - - pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); - if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pSelect = pSelect; - pSelect = 0; - }else{ - pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - } - pTriggerStep->pIdList = pColumn; - pTriggerStep->pUpsert = pUpsert; - pTriggerStep->orconf = orconf; - if( pUpsert ){ - sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget); - } - }else{ - testcase( pColumn ); - sqlite3IdListDelete(db, pColumn); - testcase( pUpsert ); - sqlite3UpsertDelete(db, pUpsert); - } - sqlite3SelectDelete(db, pSelect); - - return pTriggerStep; -} - -/* -** Construct a trigger step that implements an UPDATE statement and return -** a pointer to that trigger step. The parser calls this routine when it -** sees an UPDATE statement inside the body of a CREATE TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( - Parse *pParse, /* Parser */ - Token *pTableName, /* Name of the table to be updated */ - 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) */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ - sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep; - - pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); - if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pExprList = pEList; - pTriggerStep->pWhere = pWhere; - pTriggerStep->pFrom = pFrom; - pEList = 0; - pWhere = 0; - pFrom = 0; - }else{ - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); - } - pTriggerStep->orconf = orconf; - } - sqlite3ExprListDelete(db, pEList); - sqlite3ExprDelete(db, pWhere); - sqlite3SrcListDelete(db, pFrom); - return pTriggerStep; -} - -/* -** Construct a trigger step that implements a DELETE statement and return -** a pointer to that trigger step. The parser calls this routine when it -** sees a DELETE statement inside the body of a CREATE TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( - Parse *pParse, /* Parser */ - Token *pTableName, /* The table from which rows are deleted */ - Expr *pWhere, /* The WHERE clause */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ - sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep; - - pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); - if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pWhere = pWhere; - pWhere = 0; - }else{ - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - } - pTriggerStep->orconf = OE_Default; - } - sqlite3ExprDelete(db, pWhere); - return pTriggerStep; -} - -/* -** Recursively delete a Trigger structure -*/ -SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ - if( pTrigger==0 || pTrigger->bReturning ) return; - sqlite3DeleteTriggerStep(db, pTrigger->step_list); - sqlite3DbFree(db, pTrigger->zName); - sqlite3DbFree(db, pTrigger->table); - sqlite3ExprDelete(db, pTrigger->pWhen); - sqlite3IdListDelete(db, pTrigger->pColumns); - sqlite3DbFree(db, pTrigger); -} - -/* -** This function is called to drop a trigger from the database schema. -** -** This may be called directly from the parser and therefore identifies -** the trigger by name. The sqlite3DropTriggerPtr() routine does the -** same job as this routine except it takes a pointer to the trigger -** instead of the trigger name. -**/ -SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ - Trigger *pTrigger = 0; - int i; - const char *zDb; - const char *zName; - sqlite3 *db = pParse->db; - - if( db->mallocFailed ) goto drop_trigger_cleanup; - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto drop_trigger_cleanup; - } - - assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 ); - zDb = pName->a[0].u4.zDatabase; - zName = pName->a[0].zName; - assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); - if( pTrigger ) break; - } - if( !pTrigger ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a); - }else{ - sqlite3CodeVerifyNamedSchema(pParse, zDb); - } - pParse->checkSchema = 1; - goto drop_trigger_cleanup; - } - sqlite3DropTriggerPtr(pParse, pTrigger); - -drop_trigger_cleanup: - sqlite3SrcListDelete(db, pName); -} - -/* -** Return a pointer to the Table structure for the table that a trigger -** is set on. -*/ -static Table *tableOfTrigger(Trigger *pTrigger){ - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); -} - - -/* -** Drop a trigger given a pointer to that trigger. -*/ -SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ - Table *pTable; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); - assert( iDb>=0 && iDbnDb ); - pTable = tableOfTrigger(pTrigger); - assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 ); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pTable ){ - int code = SQLITE_DROP_TRIGGER; - const char *zDb = db->aDb[iDb].zDbSName; - const char *zTab = SCHEMA_TABLE(iDb); - if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; - if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || - sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - return; - } - } -#endif - - /* Generate code to destroy the database record of the trigger. - */ - if( (v = sqlite3GetVdbe(pParse))!=0 ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zDbSName, pTrigger->zName - ); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); - } -} - -/* -** Remove a trigger from the hash tables of the sqlite* pointer. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ - Trigger *pTrigger; - Hash *pHash; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pHash = &(db->aDb[iDb].pSchema->trigHash); - pTrigger = sqlite3HashInsert(pHash, zName, 0); - if( ALWAYS(pTrigger) ){ - if( pTrigger->pSchema==pTrigger->pTabSchema ){ - Table *pTab = tableOfTrigger(pTrigger); - if( pTab ){ - Trigger **pp; - for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){ - if( *pp==pTrigger ){ - *pp = (*pp)->pNext; - break; - } - } - } - } - sqlite3DeleteTrigger(db, pTrigger); - db->mDbFlags |= DBFLAG_SchemaChange; - } -} - -/* -** pEList is the SET clause of an UPDATE statement. Each entry -** in pEList is of the format =. If any of the entries -** in pEList have an which matches an identifier in pIdList, -** then return TRUE. If pIdList==NULL, then it is considered a -** wildcard that matches anything. Likewise if pEList==NULL then -** it matches anything so always return true. Return false only -** if there is no match. -*/ -static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ - int e; - if( pIdList==0 || NEVER(pEList==0) ) return 1; - for(e=0; enExpr; e++){ - if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1; - } - return 0; -} - -/* -** Return true if any TEMP triggers exist -*/ -static int tempTriggersExist(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. -*/ -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 */ - ExprList *pChanges, /* Columns that change in an UPDATE statement */ - int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ -){ - int mask = 0; - Trigger *pList = 0; - Trigger *p; - - pList = 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( sqlite3IsToplevel(pParse) ); - p->op = op; - if( IsVirtual(pTab) ){ - if( op!=TK_INSERT ){ - 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 - && 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 *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 -** to that SrcList. -** -** This routine adds a specific database name, if needed, to the target when -** forming the SrcList. This prevents a trigger in one database from -** referring to a target in another database. An exception is when the -** trigger is in TEMP in which case it can refer to any other database it -** wants. -*/ -SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc( - Parse *pParse, /* The parsing context */ - TriggerStep *pStep /* The trigger containing the target token */ -){ - sqlite3 *db = pParse->db; - SrcList *pSrc; /* SrcList to be returned */ - char *zName = sqlite3DbStrDup(db, pStep->zTarget); - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - assert( pSrc==0 || pSrc->nSrc==1 ); - assert( zName || pSrc==0 ); - if( pSrc ){ - Schema *pSchema = pStep->pTrig->pSchema; - pSrc->a[0].zName = zName; - if( pSchema!=db->aDb[1].pSchema ){ - assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 ); - pSrc->a[0].u4.pSchema = pSchema; - pSrc->a[0].fg.fixedSchema = 1; - } - if( pStep->pFrom ){ - SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0); - if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){ - Select *pSubquery; - Token as; - pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0); - as.n = 0; - as.z = 0; - pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); - } - pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup); - } - }else{ - sqlite3DbFree(db, zName); - } - return pSrc; -} - -/* -** 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; - 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 *sqlite3ExpandReturning( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* The arguments to RETURNING */ - Table *pTab /* The table being updated */ -){ - ExprList *pNew = 0; - sqlite3 *db = pParse->db; - int i; - - for(i=0; inExpr; i++){ - Expr *pOldExpr = pList->a[i].pExpr; - if( NEVER(pOldExpr==0) ) continue; - if( isAsteriskTerm(pParse, pOldExpr) ){ - int jj; - for(jj=0; jjnCol; jj++){ - Expr *pNewExpr; - if( IsHiddenColumn(pTab->aCol+jj) ) continue; - pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName); - pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); - if( !db->mallocFailed ){ - struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; - pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName); - pItem->fg.eEName = ENAME_NAME; - } - } - }else{ - Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0); - pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); - if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){ - struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; - pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName); - pItem->fg.eEName = pList->a[i].fg.eEName; - } - } - } - return pNew; -} - -/* If the Expr node is a subquery or an EXISTS operator or an IN operator that -** uses a subquery, and if the subquery is SF_Correlated, then mark the -** expression as EP_VarSelect. -*/ -static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){ - UNUSED_PARAMETER(NotUsed); - if( ExprUseXSelect(pExpr) - && (pExpr->x.pSelect->selFlags & SF_Correlated)!=0 - ){ - testcase( ExprHasProperty(pExpr, EP_VarSelect) ); - ExprSetProperty(pExpr, EP_VarSelect); - } - return WRC_Continue; -} - - -/* -** If the SELECT references the table pWalker->u.pTab, then do two things: -** -** (1) Mark the SELECT as as SF_Correlated. -** (2) Set pWalker->eCode to non-zero so that the caller will know -** that (1) has happened. -*/ -static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){ - int i; - SrcList *pSrc; - assert( pSelect!=0 ); - pSrc = pSelect->pSrc; - assert( pSrc!=0 ); - for(i=0; inSrc; i++){ - if( pSrc->a[i].pSTab==pWalker->u.pTab ){ - testcase( pSelect->selFlags & SF_Correlated ); - pSelect->selFlags |= SF_Correlated; - pWalker->eCode = 1; - break; - } - } - return WRC_Continue; -} - -/* -** Scan the expression list that is the argument to RETURNING looking -** for subqueries that depend on the table which is being modified in the -** statement that is hosting the RETURNING clause (pTab). Mark all such -** subqueries as SF_Correlated. If the subqueries are part of an -** expression, mark the expression as EP_VarSelect. -** -** https://sqlite.org/forum/forumpost/2c83569ce8945d39 -*/ -static void sqlite3ProcessReturningSubqueries( - ExprList *pEList, - Table *pTab -){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = sqlite3ReturningSubqueryCorrelated; - w.u.pTab = pTab; - sqlite3WalkExprList(&w, pEList); - if( w.eCode ){ - w.xExprCallback = sqlite3ReturningSubqueryVarSelect; - w.xSelectCallback = sqlite3SelectWalkNoop; - sqlite3WalkExprList(&w, pEList); - } -} - -/* -** 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; - sqlite3 *db = pParse->db; - ExprList *pNew; - Returning *pReturning; - Select sSelect; - SrcList *pFrom; - u8 fromSpace[SZ_SRCLIST_1]; - - assert( v!=0 ); - if( !pParse->bReturning ){ - /* This RETURNING trigger must be for a different statement as - ** this statement lacks a RETURNING clause. */ - return; - } - assert( db->pParse==pParse ); - assert( !pParse->isCreate ); - pReturning = pParse->u1.d.pReturning; - if( pTrigger != &(pReturning->retTrig) ){ - /* This RETURNING trigger is for a different statement */ - return; - } - memset(&sSelect, 0, sizeof(sSelect)); - pFrom = (SrcList*)fromSpace; - memset(pFrom, 0, SZ_SRCLIST_1); - sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); - sSelect.pSrc = pFrom; - pFrom->nSrc = 1; - pFrom->a[0].pSTab = pTab; - pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */ - pFrom->a[0].iCursor = -1; - sqlite3SelectPrep(pParse, &sSelect, 0); - if( pParse->nErr==0 ){ - assert( db->mallocFailed==0 ); - sqlite3GenerateColumnNames(pParse, &sSelect); - } - sqlite3ExprListDelete(db, sSelect.pEList); - pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); - if( pParse->nErr==0 ){ - 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( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK - && ALWAYS(!db->mallocFailed) - ){ - int i; - int nCol = pNew->nExpr; - int reg = pParse->nMem+1; - sqlite3ProcessReturningSubqueries(pNew, pTab); - pParse->nMem += nCol+2; - pReturning->iRetReg = reg; - for(i=0; ia[i].pExpr; - assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */ - sqlite3ExprCodeFactorable(pParse, pCol, reg+i); - if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); - } - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i); - sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1); - sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1); - } - } - sqlite3ExprListDelete(db, pNew); - pParse->eTriggerOp = 0; - pParse->pTriggerTab = 0; -} - - - -/* -** Generate VDBE code for the statements inside the body of a single -** trigger. -*/ -static int codeTriggerProgram( - Parse *pParse, /* The parser context */ - TriggerStep *pStepList, /* List of statements inside the trigger body */ - int orconf /* Conflict algorithm. (OE_Abort, etc) */ -){ - TriggerStep *pStep; - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - - assert( pParse->pTriggerTab && pParse->pToplevel ); - assert( pStepList ); - assert( v!=0 ); - for(pStep=pStepList; pStep; pStep=pStep->pNext){ - /* Figure out the ON CONFLICT policy that will be used for this step - ** of the trigger program. If the statement that caused this trigger - ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use - ** the ON CONFLICT policy that was specified as part of the trigger - ** step statement. Example: - ** - ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN; - ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); - ** END; - ** - ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy - ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy - */ - pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; - assert( pParse->okConstFactor==0 ); - -#ifndef SQLITE_OMIT_TRACE - if( pStep->zSpan ){ - sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, - sqlite3MPrintf(db, "-- %s", pStep->zSpan), - P4_DYNAMIC); - } -#endif - - switch( pStep->op ){ - case TK_UPDATE: { - sqlite3Update(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3ExprListDup(db, pStep->pExprList, 0), - sqlite3ExprDup(db, pStep->pWhere, 0), - pParse->eOrconf, 0, 0, 0 - ); - sqlite3VdbeAddOp0(v, OP_ResetCount); - break; - } - case TK_INSERT: { - sqlite3Insert(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3SelectDup(db, pStep->pSelect, 0), - sqlite3IdListDup(db, pStep->pIdList), - pParse->eOrconf, - sqlite3UpsertDup(db, pStep->pUpsert) - ); - sqlite3VdbeAddOp0(v, OP_ResetCount); - break; - } - case TK_DELETE: { - sqlite3DeleteFrom(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 - ); - sqlite3VdbeAddOp0(v, OP_ResetCount); - break; - } - default: assert( pStep->op==TK_SELECT ); { - SelectDest sDest; - Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); - sqlite3SelectDestInit(&sDest, SRT_Discard, 0); - sqlite3Select(pParse, pSelect, &sDest); - sqlite3SelectDelete(db, pSelect); - break; - } - } - } - - return 0; -} - -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS -/* -** This function is used to add VdbeComment() annotations to a VDBE -** program. It is not used in production code, only for debugging. -*/ -static const char *onErrorText(int onError){ - switch( onError ){ - case OE_Abort: return "abort"; - case OE_Rollback: return "rollback"; - case OE_Fail: return "fail"; - case OE_Replace: return "replace"; - case OE_Ignore: return "ignore"; - case OE_Default: return "default"; - } - return "n/a"; -} -#endif - -/* -** Parse context structure pFrom has just been used to create a sub-vdbe -** (trigger program). If an error has occurred, transfer error information -** from pFrom to pTo. -*/ -static void transferParseError(Parse *pTo, Parse *pFrom){ - assert( pFrom->zErrMsg==0 || pFrom->nErr ); - assert( pTo->zErrMsg==0 || pTo->nErr ); - if( pTo->nErr==0 ){ - pTo->zErrMsg = pFrom->zErrMsg; - pTo->nErr = pFrom->nErr; - pTo->rc = pFrom->rc; - }else{ - sqlite3DbFree(pFrom->db, pFrom->zErrMsg); - } -} - -/* -** Create and populate a new TriggerPrg object with a sub-program -** implementing trigger pTrigger with ON CONFLICT policy orconf. -*/ -static TriggerPrg *codeRowTrigger( - Parse *pParse, /* Current parse context */ - Trigger *pTrigger, /* Trigger to code */ - Table *pTab, /* The table pTrigger is attached to */ - int orconf /* ON CONFLICT policy to code trigger program with */ -){ - Parse *pTop = sqlite3ParseToplevel(pParse); - sqlite3 *db = pParse->db; /* Database handle */ - TriggerPrg *pPrg; /* Value to return */ - Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ - Vdbe *v; /* Temporary VM */ - NameContext sNC; /* Name context for sub-vdbe */ - SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ - 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 ); - - /* Allocate the TriggerPrg and SubProgram objects. To ensure that they - ** are freed if an error occurs, link them into the Parse.pTriggerPrg - ** list of the top-level Parse object sooner rather than later. */ - pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg)); - if( !pPrg ) return 0; - pPrg->pNext = pTop->pTriggerPrg; - pTop->pTriggerPrg = pPrg; - pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); - if( !pProgram ) return 0; - sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram); - pPrg->pTrigger = pTrigger; - pPrg->orconf = orconf; - pPrg->aColmask[0] = 0xffffffff; - pPrg->aColmask[1] = 0xffffffff; - - /* Allocate and populate a new Parse context to use for coding the - ** trigger sub-program. */ - sqlite3ParseObjectInit(&sSubParse, db); - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sSubParse; - sSubParse.pTriggerTab = pTab; - sSubParse.pToplevel = pTop; - sSubParse.zAuthContext = pTrigger->zName; - sSubParse.eTriggerOp = pTrigger->op; - sSubParse.nQueryLoop = pParse->nQueryLoop; - sSubParse.prepFlags = pParse->prepFlags; - sSubParse.oldmask = 0; - sSubParse.newmask = 0; - - v = sqlite3GetVdbe(&sSubParse); - if( v ){ - VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", - pTrigger->zName, onErrorText(orconf), - (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), - (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), - (pTrigger->op==TK_INSERT ? "INSERT" : ""), - (pTrigger->op==TK_DELETE ? "DELETE" : ""), - pTab->zName - )); -#ifndef SQLITE_OMIT_TRACE - if( pTrigger->zName ){ - sqlite3VdbeChangeP4(v, -1, - sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC - ); - } -#endif - - /* If one was specified, code the WHEN clause. If it evaluates to false - ** (or NULL) the sub-vdbe is immediately halted by jumping to the - ** OP_Halt inserted at the end of the program. */ - if( pTrigger->pWhen ){ - pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); - if( db->mallocFailed==0 - && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) - ){ - iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse); - sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); - } - sqlite3ExprDelete(db, pWhen); - } - - /* Code the trigger program into the sub-vdbe. */ - codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf); - - /* Insert an OP_Halt at the end of the sub-program. */ - if( iEndTrigger ){ - sqlite3VdbeResolveLabel(v, iEndTrigger); - } - sqlite3VdbeAddOp0(v, OP_Halt); - VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); - transferParseError(pParse, &sSubParse); - - if( pParse->nErr==0 ){ - assert( db->mallocFailed==0 ); - pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); - } - pProgram->nMem = sSubParse.nMem; - pProgram->nCsr = sSubParse.nTab; - pProgram->token = (void *)pTrigger; - pPrg->aColmask[0] = sSubParse.oldmask; - pPrg->aColmask[1] = sSubParse.newmask; - sqlite3VdbeDelete(v); - }else{ - transferParseError(pParse, &sSubParse); - } - - assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg ); - sqlite3ParseObjectReset(&sSubParse); - return pPrg; -} - -/* -** Return a pointer to a TriggerPrg object containing the sub-program for -** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such -** TriggerPrg object exists, a new object is allocated and populated before -** being returned. -*/ -static TriggerPrg *getRowTrigger( - Parse *pParse, /* Current parse context */ - Trigger *pTrigger, /* Trigger to code */ - Table *pTab, /* The table trigger pTrigger is attached to */ - int orconf /* ON CONFLICT algorithm. */ -){ - Parse *pRoot = sqlite3ParseToplevel(pParse); - TriggerPrg *pPrg; - - assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); - - /* It may be that this trigger has already been coded (or is in the - ** process of being coded). If this is the case, then an entry with - ** a matching TriggerPrg.pTrigger field will be present somewhere - ** in the Parse.pTriggerPrg list. Search for such an entry. */ - for(pPrg=pRoot->pTriggerPrg; - pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); - pPrg=pPrg->pNext - ); - - /* 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; -} - -/* -** Generate code for the trigger program associated with trigger p on -** table pTab. The reg, orconf and ignoreJump parameters passed to this -** function are the same as those described in the header function for -** sqlite3CodeRowTrigger() -*/ -SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect( - Parse *pParse, /* Parse context */ - Trigger *p, /* Trigger to code */ - Table *pTab, /* The table to code triggers from */ - int reg, /* Reg array containing OLD.* and NEW.* values */ - int orconf, /* ON CONFLICT policy */ - int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ -){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - 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. */ - if( pPrg ){ - int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); - - sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, - (const char *)pPrg->pProgram, P4_SUBPROGRAM); - VdbeComment( - (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); - - /* Set the P5 operand of the OP_Program instruction to non-zero if - ** recursive invocation of this trigger program is disallowed. Recursive - ** invocation is disallowed if (a) the sub-program is really a trigger, - ** not a foreign key action, and (b) the flag to enable recursive triggers - ** is clear. */ - sqlite3VdbeChangeP5(v, (u16)bRecursive); - } -} - -/* -** This is called to code the required FOR EACH ROW triggers for an operation -** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE) -** is given by the op parameter. The tr_tm parameter determines whether the -** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then -** parameter pChanges is passed the list of columns being modified. -** -** If there are no triggers that fire at the specified time for the specified -** operation on pTab, this function is a no-op. -** -** The reg argument is the address of the first in an array of registers -** that contain the values substituted for the new.* and old.* references -** in the trigger program. If N is the number of columns in table pTab -** (a copy of pTab->nCol), then registers are populated as follows: -** -** Register Contains -** ------------------------------------------------------ -** reg+0 OLD.rowid -** reg+1 OLD.* value of left-most column of pTab -** ... ... -** reg+N OLD.* value of right-most column of pTab -** reg+N+1 NEW.rowid -** reg+N+2 NEW.* value of left-most column of pTab -** ... ... -** reg+N+N+1 NEW.* value of right-most column of pTab -** -** For ON DELETE triggers, the registers containing the NEW.* values will -** never be accessed by the trigger program, so they are not allocated or -** populated by the caller (there is no data to populate them with anyway). -** Similarly, for ON INSERT triggers the values stored in the OLD.* registers -** are never accessed, and so are not allocated by the caller. So, for an -** ON INSERT trigger, the value passed to this function as parameter reg -** is not a readable register, although registers (reg+N) through -** (reg+N+N+1) are. -** -** Parameter orconf is the default conflict resolution algorithm for the -** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump -** is the instruction that control should jump to if a trigger program -** raises an IGNORE exception. -*/ -SQLITE_PRIVATE void sqlite3CodeRowTrigger( - Parse *pParse, /* Parse context */ - Trigger *pTrigger, /* List of triggers on table pTab */ - int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ - ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ - int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ - Table *pTab, /* The table to code triggers from */ - int reg, /* The first in an array of registers (see above) */ - int orconf, /* ON CONFLICT policy */ - int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ -){ - Trigger *p; /* Used to iterate through pTrigger list */ - - assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE ); - assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER ); - assert( (op==TK_UPDATE)==(pChanges!=0) ); - - for(p=pTrigger; p; p=p->pNext){ - - /* Sanity checking: The schema for the trigger and for the table are - ** always defined. The trigger must be in the same schema as the table - ** or else it must be a TEMP trigger. */ - assert( p->pSchema!=0 ); - assert( p->pTabSchema!=0 ); - assert( p->pSchema==p->pTabSchema - || p->pSchema==pParse->db->aDb[1].pSchema ); - - /* 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) - ){ - if( !p->bReturning ){ - sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump); - }else if( sqlite3IsToplevel(pParse) ){ - codeReturningTrigger(pParse, p, pTab, reg); - } - } - } -} - -/* -** Triggers may access values stored in the old.* or new.* pseudo-table. -** This function returns a 32-bit bitmask indicating which columns of the -** old.* or new.* tables actually are used by triggers. This information -** may be used by the caller, for example, to avoid having to load the entire -** old.* record into memory when executing an UPDATE or DELETE command. -** -** Bit 0 of the returned mask is set if the left-most column of the -** table may be accessed using an [old|new].reference. Bit 1 is set if -** the second leftmost column value is required, and so on. If there -** are more than 32 columns in the table, and at least one of the columns -** with an index greater than 32 may be accessed, 0xffffffff is returned. -** -** It is not possible to determine if the old.rowid or new.rowid column is -** accessed by triggers. The caller must always assume that it is. -** -** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned -** applies to the old.* table. If 1, the new.* table. -** -** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE -** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only -** included in the returned mask if the TRIGGER_BEFORE bit is set in the -** tr_tm parameter. Similarly, values accessed by AFTER triggers are only -** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. -*/ -SQLITE_PRIVATE u32 sqlite3TriggerColmask( - Parse *pParse, /* Parse context */ - Trigger *pTrigger, /* List of triggers on table pTab */ - ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ - int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ - int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ - Table *pTab, /* The table to code triggers from */ - int orconf /* Default ON CONFLICT policy for trigger steps */ -){ - const int op = pChanges ? TK_UPDATE : TK_DELETE; - u32 mask = 0; - Trigger *p; - - assert( isNew==1 || isNew==0 ); - if( IsView(pTab) ){ - return 0xffffffff; - } - for(p=pTrigger; p; p=p->pNext){ - if( p->op==op - && (tr_tm&p->tr_tm) - && checkColumnOverlap(p->pColumns,pChanges) - ){ - if( p->bReturning ){ - mask = 0xffffffff; - }else{ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - if( pPrg ){ - mask |= pPrg->aColmask[isNew]; - } - } - } - } - - return mask; -} - -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ - -/************** End of trigger.c *********************************************/ -/************** Begin file update.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle UPDATE statements. -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Forward declaration */ -static void updateVirtualTable( - Parse *pParse, /* The parsing context */ - SrcList *pSrc, /* The virtual table to be modified */ - Table *pTab, /* The virtual table */ - ExprList *pChanges, /* The columns to change in the UPDATE statement */ - Expr *pRowidExpr, /* Expression used to recompute the rowid */ - int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ - Expr *pWhere, /* WHERE clause of the UPDATE statement */ - int onError /* ON CONFLICT strategy */ -); -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** The most recently coded instruction was an OP_Column to retrieve the -** i-th column of table pTab. This routine sets the P4 parameter of the -** OP_Column to the default value, if any. -** -** The default value of a column is specified by a DEFAULT clause in the -** column definition. This was either supplied by the user when the table -** was created, or added later to the table definition by an ALTER TABLE -** command. If the latter, then the row-records in the table btree on disk -** may not contain a value for the column and the default value, taken -** from the P4 parameter of the OP_Column instruction, is returned instead. -** If the former, then all row-records are guaranteed to include a value -** for the column and the P4 value is not required. -** -** Column definitions created by an ALTER TABLE command may only have -** literal default values specified: a number, null or a string. (If a more -** complicated default expression value was provided, it is evaluated -** when the ALTER TABLE is executed and one of the literal values written -** into the sqlite_schema table.) -** -** Therefore, the P4 parameter is only required if the default value for -** the column is a literal number, string or null. The sqlite3ValueFromExpr() -** function is capable of transforming these types of expressions into -** sqlite3_value objects. -** -** If column as REAL affinity and the table is an ordinary b-tree table -** (not a virtual table) then the value might have been stored as an -** integer. In that case, add an OP_RealAffinity opcode to make sure -** it has been converted into REAL. -*/ -SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ - Column *pCol; - assert( pTab!=0 ); - assert( pTab->nCol>i ); - pCol = &pTab->aCol[i]; - if( pCol->iDflt ){ - sqlite3_value *pValue = 0; - u8 enc = ENC(sqlite3VdbeDb(v)); - assert( !IsView(pTab) ); - VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName)); - assert( inCol ); - sqlite3ValueFromExpr(sqlite3VdbeDb(v), - sqlite3ColumnExpr(pTab,pCol), enc, - pCol->affinity, &pValue); - if( pValue ){ - sqlite3VdbeAppendP4(v, pValue, P4_MEM); - } - } -#ifndef SQLITE_OMIT_FLOATING_POINT - if( pCol->affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); - } -#endif -} - -/* -** Check to see if column iCol of index pIdx references any of the -** columns defined by aXRef and chngRowid. Return true if it does -** and false if not. This is an optimization. False-positives are a -** performance degradation, but false-negatives can result in a corrupt -** index and incorrect answers. -** -** aXRef[j] will be non-negative if column j of the original table is -** being updated. chngRowid will be true if the rowid of the table is -** being updated. -*/ -static int indexColumnIsBeingUpdated( - Index *pIdx, /* The index to check */ - int iCol, /* Which column of the index to check */ - int *aXRef, /* aXRef[j]>=0 if column j is being updated */ - int chngRowid /* true if the rowid is being updated */ -){ - i16 iIdxCol = pIdx->aiColumn[iCol]; - assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ - if( iIdxCol>=0 ){ - return aXRef[iIdxCol]>=0; - } - assert( iIdxCol==XN_EXPR ); - assert( pIdx->aColExpr!=0 ); - assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); - return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, - aXRef,chngRowid); -} - -/* -** Check to see if index pIdx is a partial index whose conditional -** expression might change values due to an UPDATE. Return true if -** the index is subject to change and false if the index is guaranteed -** to be unchanged. This is an optimization. False-positives are a -** performance degradation, but false-negatives can result in a corrupt -** index and incorrect answers. -** -** aXRef[j] will be non-negative if column j of the original table is -** being updated. chngRowid will be true if the rowid of the table is -** being updated. -*/ -static int indexWhereClauseMightChange( - Index *pIdx, /* The index to check */ - int *aXRef, /* aXRef[j]>=0 if column j is being updated */ - int chngRowid /* true if the rowid is being updated */ -){ - if( pIdx->pPartIdxWhere==0 ) return 0; - return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, - aXRef, chngRowid); -} - -/* -** Allocate and return a pointer to an expression of type TK_ROW with -** Expr.iColumn set to value (iCol+1). The resolver will modify the -** expression to be a TK_COLUMN reading column iCol of the first -** table in the source-list (pSrc->a[0]). -*/ -static Expr *exprRowColumn(Parse *pParse, int iCol){ - Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0); - if( pRet ) pRet->iColumn = iCol+1; - return pRet; -} - -/* -** Assuming both the pLimit and pOrderBy parameters are NULL, this function -** generates VM code to run the query: -** -** SELECT , pChanges FROM pTabList WHERE pWhere -** -** and write the results to the ephemeral table already opened as cursor -** iEph. None of pChanges, pTabList or pWhere are modified or consumed by -** this function, they must be deleted by the caller. -** -** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view: -** -** SELECT , pChanges FROM pTabList -** WHERE pWhere -** GROUP BY -** ORDER BY pOrderBy LIMIT pLimit -** -** If pTab is a view, the GROUP BY clause is omitted. -** -** Exactly how results are written to table iEph, and exactly what -** the in the query above are is determined by the type -** of table pTabList->a[0].pTab. -** -** If the table is a WITHOUT ROWID table, then argument pPk must be its -** PRIMARY KEY. In this case are the primary key columns -** of the table, in order. The results of the query are written to ephemeral -** table iEph as index keys, using OP_IdxInsert. -** -** If the table is actually a view, then are all columns of -** the view. The results are written to the ephemeral table iEph as records -** with automatically assigned integer keys. -** -** If the table is a virtual or ordinary intkey table, then -** is its rowid. For a virtual table, the results are written to iEph as -** records with automatically assigned integer keys For intkey tables, the -** rowid value in is used as the integer key, and the -** remaining fields make up the table record. -*/ -static void updateFromSelect( - Parse *pParse, /* Parse context */ - int iEph, /* Cursor for open eph. table */ - Index *pPk, /* PK if table 0 is WITHOUT ROWID */ - ExprList *pChanges, /* List of expressions to return */ - SrcList *pTabList, /* List of tables to select from */ - Expr *pWhere, /* WHERE clause for query */ - ExprList *pOrderBy, /* ORDER BY clause */ - Expr *pLimit /* LIMIT clause */ -){ - int i; - SelectDest dest; - Select *pSelect = 0; - ExprList *pList = 0; - ExprList *pGrp = 0; - Expr *pLimit2 = 0; - ExprList *pOrderBy2 = 0; - sqlite3 *db = pParse->db; - Table *pTab = pTabList->a[0].pSTab; - SrcList *pSrc; - Expr *pWhere2; - int eDest; - -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pOrderBy && pLimit==0 ) { - sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE"); - return; - } - pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0); - pLimit2 = sqlite3ExprDup(db, pLimit, 0); -#else - UNUSED_PARAMETER(pOrderBy); - UNUSED_PARAMETER(pLimit); -#endif - - pSrc = sqlite3SrcListDup(db, pTabList, 0); - pWhere2 = sqlite3ExprDup(db, pWhere, 0); - - assert( pTabList->nSrc>1 ); - if( pSrc ){ - assert( pSrc->a[0].fg.notCte ); - pSrc->a[0].iCursor = -1; - pSrc->a[0].pSTab->nTabRef--; - pSrc->a[0].pSTab = 0; - } - if( pPk ){ - for(i=0; inKeyCol; i++){ - Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]); -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pLimit ){ - pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0)); - } -#endif - pList = sqlite3ExprListAppend(pParse, pList, pNew); - } - eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; - }else if( IsView(pTab) ){ - for(i=0; inCol; i++){ - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); - } - eDest = SRT_Table; - }else{ - eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; - pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0)); -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pLimit ){ - pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0)); - } -#endif - } - assert( pChanges!=0 || pParse->db->mallocFailed ); - if( pChanges ){ - for(i=0; inExpr; i++){ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3ExprDup(db, pChanges->a[i].pExpr, 0) - ); - } - } - pSelect = sqlite3SelectNew(pParse, pList, - pSrc, pWhere2, pGrp, 0, pOrderBy2, - SF_UFSrcCheck|SF_IncludeHidden|SF_UpdateFrom, pLimit2 - ); - if( pSelect ) pSelect->selFlags |= SF_OrderByReqd; - sqlite3SelectDestInit(&dest, eDest, iEph); - dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); - sqlite3Select(pParse, pSelect, &dest); - sqlite3SelectDelete(db, pSelect); -} - -/* -** Process an UPDATE statement. -** -** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL; -** \_______/ \_/ \______/ \_____/ \________________/ -** onError | pChanges | pWhere -** \_______________________/ -** pTabList -*/ -SQLITE_PRIVATE void sqlite3Update( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* The table in which we should change things */ - ExprList *pChanges, /* Things to be changed */ - Expr *pWhere, /* The WHERE clause. May be null */ - int onError, /* How to handle constraint errors */ - ExprList *pOrderBy, /* ORDER BY clause. May be null */ - Expr *pLimit, /* LIMIT clause. May be null */ - Upsert *pUpsert /* ON CONFLICT clause, or null */ -){ - int i, j, k; /* Loop counters */ - Table *pTab; /* The table to be updated */ - int addrTop = 0; /* VDBE instruction address of the start of the loop */ - WhereInfo *pWInfo = 0; /* Information about the WHERE clause */ - Vdbe *v; /* The virtual database engine */ - Index *pIdx; /* For looping over indices */ - Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ - int nIdx; /* Number of indices that need updating */ - int nAllIdx; /* Total number of indexes */ - int iBaseCur; /* Base cursor number */ - int iDataCur; /* Cursor for the canonical data btree */ - int iIdxCur; /* Cursor for the first index */ - sqlite3 *db; /* The database structure */ - int *aRegIdx = 0; /* Registers for to each index and the main table */ - int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the - ** an expression for the i-th column of the table. - ** aXRef[i]==-1 if the i-th column is not changed. */ - u8 *aToOpen; /* 1 for tables and indices to be opened */ - u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ - u8 chngRowid; /* Rowid changed in a normal table */ - u8 chngKey; /* Either chngPk or chngRowid */ - Expr *pRowidExpr = 0; /* Expression defining the new record number */ - int iRowidExpr = -1; /* Index of "rowid=" (or IPK) assignment in pChanges */ - AuthContext sContext; /* The authorization context */ - NameContext sNC; /* The name-context to resolve expressions in */ - int iDb; /* Database containing the table being updated */ - int eOnePass; /* ONEPASS_XXX value from where.c */ - int hasFK; /* True if foreign key processing is required */ - int labelBreak; /* Jump here to break out of UPDATE loop */ - int labelContinue; /* Jump here to continue next step of UPDATE loop */ - int flags; /* Flags for sqlite3WhereBegin() */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True when updating a view (INSTEAD OF trigger) */ - Trigger *pTrigger; /* List of triggers on pTab, if required */ - int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ -#endif - int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ - int iEph = 0; /* Ephemeral table holding all primary key values */ - int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ - int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ - int addrOpen = 0; /* Address of OP_OpenEphemeral */ - int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */ - i16 nPk = 0; /* Number of components of the PRIMARY KEY */ - int bReplace = 0; /* True if REPLACE conflict resolution might happen */ - int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */ - int nChangeFrom = 0; /* If there is a FROM, pChanges->nExpr, else 0 */ - - /* Register Allocations */ - int regRowCount = 0; /* A count of rows changed */ - int regOldRowid = 0; /* The old rowid */ - int regNewRowid = 0; /* The new rowid */ - int regNew = 0; /* Content of the NEW.* table in triggers */ - int regOld = 0; /* Content of OLD.* table in triggers */ - int regRowSet = 0; /* Rowset of rows to be updated */ - int regKey = 0; /* composite PRIMARY KEY value */ - - memset(&sContext, 0, sizeof(sContext)); - db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ){ - goto update_cleanup; - } - assert( db->mallocFailed==0 ); - - /* Locate the table which we want to update. - */ - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ) goto update_cleanup; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - - /* Figure out if we have any triggers and if the table being - ** updated is a view. - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); - isView = IsView(pTab); - assert( pTrigger || tmask==0 ); -#else -# define pTrigger 0 -# define isView 0 -# define tmask 0 -#endif -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__); - 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 - ** an UPSERT statement. */ - nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0; - assert( nChangeFrom==0 || pUpsert==0 ); - -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( !isView && nChangeFrom==0 ){ - pWhere = sqlite3LimitWhere( - pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" - ); - pOrderBy = 0; - pLimit = 0; - } -#endif - - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto update_cleanup; - } - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ - goto update_cleanup; - } - - /* Allocate a cursors for the main database table and for all indices. - ** The index cursors might not be used, but if they are used they - ** need to occur right after the database cursor. So go ahead and - ** allocate enough space, just in case. - */ - iBaseCur = iDataCur = pParse->nTab++; - iIdxCur = iDataCur+1; - pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); - testcase( pPk!=0 && pPk!=pTab->pIndex ); - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ - if( pPk==pIdx ){ - iDataCur = pParse->nTab; - } - pParse->nTab++; - } - if( pUpsert ){ - /* On an UPSERT, reuse the same cursors already opened by INSERT */ - iDataCur = pUpsert->iDataCur; - iIdxCur = pUpsert->iIdxCur; - pParse->nTab = iBaseCur; - } - pTabList->a[0].iCursor = iDataCur; - - /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. - ** Initialize aXRef[] and aToOpen[] to their default values. - */ - aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 ); - if( aXRef==0 ) goto update_cleanup; - aRegIdx = aXRef+pTab->nCol; - aToOpen = (u8*)(aRegIdx+nIdx+1); - memset(aToOpen, 1, nIdx+1); - aToOpen[nIdx+1] = 0; - for(i=0; inCol; i++) aXRef[i] = -1; - - /* Initialize the name-context */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - sNC.uNC.pUpsert = pUpsert; - sNC.ncFlags = NC_UUpsert; - - /* Begin generating code. */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto update_cleanup; - - /* Resolve the column names in all the expressions of the - ** of the UPDATE statement. Also find the column index - ** for each column to be updated in the pChanges array. For each - ** column to be updated, make sure we have authorization to change - ** that column. - */ - chngRowid = chngPk = 0; - for(i=0; inExpr; i++){ - /* If this is an UPDATE with a FROM clause, do not resolve expressions - ** here. The call to sqlite3Select() below will do that. */ - if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ - goto update_cleanup; - } - j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName); - if( j>=0 ){ - if( j==pTab->iPKey ){ - chngRowid = 1; - pRowidExpr = pChanges->a[i].pExpr; - iRowidExpr = i; - }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ - chngPk = 1; - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[j].colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, - "cannot UPDATE generated column \"%s\"", - pTab->aCol[j].zCnName); - goto update_cleanup; - } -#endif - aXRef[j] = i; - }else{ - if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){ - j = -1; - chngRowid = 1; - pRowidExpr = pChanges->a[i].pExpr; - iRowidExpr = i; - }else{ - sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName); - pParse->checkSchema = 1; - goto update_cleanup; - } - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int rc; - rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, - j<0 ? "ROWID" : pTab->aCol[j].zCnName, - db->aDb[iDb].zDbSName); - if( rc==SQLITE_DENY ){ - goto update_cleanup; - }else if( rc==SQLITE_IGNORE ){ - aXRef[j] = -1; - } - } -#endif - } - assert( (chngRowid & chngPk)==0 ); - assert( chngRowid==0 || chngRowid==1 ); - assert( chngPk==0 || chngPk==1 ); - chngKey = chngRowid + chngPk; - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Mark generated columns as changing if their generator expressions - ** reference any changing column. The actual aXRef[] value for - ** generated expressions is not used, other than to check to see that it - ** is non-negative, so the value of aXRef[] for generated columns can be - ** set to any non-negative number. We use 99999 so that the value is - ** obvious when looking at aXRef[] in a symbolic debugger. - */ - if( pTab->tabFlags & TF_HasGenerated ){ - int bProgress; - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - do{ - bProgress = 0; - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ) continue; - if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue; - if( sqlite3ExprReferencesUpdatedColumn( - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - aXRef, chngRowid) - ){ - aXRef[i] = 99999; - bProgress = 1; - } - } - }while( bProgress ); - } -#endif - - /* The SET expressions are not actually used inside the WHERE loop. - ** So reset the colUsed mask. Unless this is a virtual table. In that - ** case, set all bits of the colUsed mask (to ensure that the virtual - ** table implementation makes all columns available). - */ - pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0; - - hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); - - /* There is one entry in the aRegIdx[] array for each index on the table - ** being updated. Fill in aRegIdx[] with a register number that will hold - ** the key for accessing each index. - */ - if( onError==OE_Replace ) bReplace = 1; - for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){ - int reg; - if( chngKey || hasFK>1 || pIdx==pPk - || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) - ){ - reg = ++pParse->nMem; - pParse->nMem += pIdx->nColumn; - }else{ - reg = 0; - for(i=0; inKeyCol; i++){ - if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ - reg = ++pParse->nMem; - pParse->nMem += pIdx->nColumn; - if( onError==OE_Default && pIdx->onError==OE_Replace ){ - bReplace = 1; - } - break; - } - } - } - if( reg==0 ) aToOpen[nAllIdx+1] = 0; - aRegIdx[nAllIdx] = reg; - } - aRegIdx[nAllIdx] = ++pParse->nMem; /* Register storing the table record */ - if( bReplace ){ - /* If REPLACE conflict resolution might be invoked, open cursors on all - ** indexes in case they are needed to delete records. */ - memset(aToOpen, 1, nIdx+1); - } - - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); - - /* Allocate required registers. */ - if( !IsVirtual(pTab) ){ - /* For now, regRowSet and aRegIdx[nAllIdx] share the same register. - ** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be - ** reallocated. aRegIdx[nAllIdx] is the register in which the main - ** table record is written. regRowSet holds the RowSet for the - ** two-pass update algorithm. */ - assert( aRegIdx[nAllIdx]==pParse->nMem ); - regRowSet = aRegIdx[nAllIdx]; - regOldRowid = regNewRowid = ++pParse->nMem; - if( chngPk || pTrigger || hasFK ){ - regOld = pParse->nMem + 1; - pParse->nMem += pTab->nCol; - } - if( chngKey || pTrigger || hasFK ){ - regNewRowid = ++pParse->nMem; - } - regNew = pParse->nMem + 1; - pParse->nMem += pTab->nCol; - } - - /* Start the view context. */ - if( isView ){ - sqlite3AuthContextPush(pParse, &sContext, pTab->zName); - } - - /* If we are trying to update a view, realize that view into - ** an ephemeral table. - */ -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) - if( nChangeFrom==0 && isView ){ - sqlite3MaterializeView(pParse, pTab, - pWhere, pOrderBy, pLimit, iDataCur - ); - pOrderBy = 0; - pLimit = 0; - } -#endif - - /* Resolve the column names in all the expressions in the - ** WHERE clause. - */ - if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pWhere) ){ - goto update_cleanup; - } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Virtual tables must be handled separately */ - if( IsVirtual(pTab) ){ - updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, - pWhere, onError); - goto update_cleanup; - } -#endif - - /* Jump to labelBreak to abandon further processing of this UPDATE */ - labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse); - - /* Not an UPSERT. Normal processing. Begin by - ** initialize the count of updated rows */ - if( (db->flags&SQLITE_CountRows)!=0 - && !pParse->pTriggerTab - && !pParse->nested - && !pParse->bReturning - && pUpsert==0 - ){ - regRowCount = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); - } - - if( nChangeFrom==0 && HasRowid(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); - iEph = pParse->nTab++; - addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet); - }else{ - assert( pPk!=0 || HasRowid(pTab) ); - nPk = pPk ? pPk->nKeyCol : 0; - iPk = pParse->nMem+1; - pParse->nMem += nPk; - pParse->nMem += nChangeFrom; - regKey = ++pParse->nMem; - if( pUpsert==0 ){ - int nEphCol = nPk + nChangeFrom + (isView ? pTab->nCol : 0); - iEph = pParse->nTab++; - if( pPk ) sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); - addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol); - if( pPk ){ - KeyInfo *pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pPk); - if( pKeyInfo ){ - pKeyInfo->nAllField = nEphCol; - sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); - } - } - if( nChangeFrom ){ - updateFromSelect( - pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit - ); -#ifndef SQLITE_OMIT_SUBQUERY - if( isView ) iDataCur = iEph; -#endif - } - } - } - - if( nChangeFrom ){ - sqlite3MultiWrite(pParse); - eOnePass = ONEPASS_OFF; - nKey = nPk; - regKey = iPk; - }else{ - if( pUpsert ){ - /* If this is an UPSERT, then all cursors have already been opened by - ** the outer INSERT and the data cursor should be pointing at the row - ** that is to be updated. So bypass the code that searches for the - ** row(s) to be updated. - */ - pWInfo = 0; - eOnePass = ONEPASS_SINGLE; - sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); - bFinishSeek = 0; - }else{ - /* Begin the database scan. - ** - ** Do not consider a single-pass strategy for a multi-row update if - ** there is anything that might disrupt the cursor being used to do - ** the UPDATE: - ** (1) This is a nested UPDATE - ** (2) There are triggers - ** (3) There are FOREIGN KEY constraints - ** (4) There are REPLACE conflict handlers - ** (5) There are subqueries in the WHERE clause - */ - flags = WHERE_ONEPASS_DESIRED; - if( !pParse->nested - && !pTrigger - && !hasFK - && !chngKey - && !bReplace - && (pWhere==0 || !ExprHasProperty(pWhere, EP_Subquery)) - ){ - flags |= WHERE_ONEPASS_MULTIROW; - } - pWInfo = 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 - ** be used if any column of the index used for the scan is being - ** updated. Otherwise, if there is an index on "b", statements like - ** the following could create an infinite loop: - ** - ** UPDATE t1 SET b=b+1 WHERE b>? - ** - ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI - ** strategy that uses an index for which one or more columns are being - ** updated. */ - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo); - if( eOnePass!=ONEPASS_SINGLE ){ - sqlite3MultiWrite(pParse); - if( eOnePass==ONEPASS_MULTI ){ - int iCur = aiCurOnePass[1]; - if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ - eOnePass = ONEPASS_OFF; - } - assert( iCur!=iDataCur || !HasRowid(pTab) ); - } - } - } - - if( HasRowid(pTab) ){ - /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF - ** mode, write the rowid into the FIFO. In either of the one-pass modes, - ** leave it in register regOldRowid. */ - sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); - if( eOnePass==ONEPASS_OFF ){ - aRegIdx[nAllIdx] = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid); - }else{ - if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen); - } - }else{ - /* Read the PK of the current row into an array of registers. In - ** ONEPASS_OFF mode, serialize the array into a record and store it in - ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change - ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table - ** is not required) and leave the PK fields in the array of registers. */ - for(i=0; iaiColumn[i]>=0 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, - pPk->aiColumn[i], iPk+i); - } - if( eOnePass ){ - if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); - nKey = nPk; - regKey = iPk; - }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(db, pPk), nPk); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); - } - } - } - - if( pUpsert==0 ){ - if( nChangeFrom==0 && eOnePass!=ONEPASS_MULTI ){ - sqlite3WhereEnd(pWInfo); - } - - if( !isView ){ - int addrOnce = 0; - int iNotUsed1 = 0; - int iNotUsed2 = 0; - - /* Open every index that needs updating. */ - if( eOnePass!=ONEPASS_OFF ){ - if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; - if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; - } - - if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, - aToOpen, &iNotUsed1, &iNotUsed2); - if( addrOnce ){ - sqlite3VdbeJumpHereOrPopInst(v, addrOnce); - } - } - - /* Top of the update loop */ - if( eOnePass!=ONEPASS_OFF ){ - if( aiCurOnePass[0]!=iDataCur - && aiCurOnePass[1]!=iDataCur -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - && !isView -#endif - ){ - assert( pPk ); - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); - VdbeCoverage(v); - } - if( eOnePass!=ONEPASS_SINGLE ){ - labelContinue = sqlite3VdbeMakeLabel(pParse); - } - sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); - VdbeCoverageIf(v, pPk==0); - VdbeCoverageIf(v, pPk!=0); - }else if( pPk || nChangeFrom ){ - labelContinue = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); - addrTop = sqlite3VdbeCurrentAddr(v); - if( nChangeFrom ){ - if( !isView ){ - if( pPk ){ - for(i=0; i=0 ); - if( nChangeFrom==0 ){ - sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iEph, iRowidExpr, regNewRowid); - } - sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); - } - - /* Compute the old pre-UPDATE content of the row being changed, if that - ** information is needed */ - if( chngPk || hasFK || pTrigger ){ - u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); - oldmask |= sqlite3TriggerColmask(pParse, - pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError - ); - for(i=0; inCol; i++){ - u32 colFlags = pTab->aCol[i].colFlags; - k = sqlite3TableColumnToStorage(pTab, i) + regOld; - if( oldmask==0xffffffff - || (i<32 && (oldmask & MASKBIT32(i))!=0) - || (colFlags & COLFLAG_PRIMKEY)!=0 - ){ - testcase( oldmask!=0xffffffff && i==31 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); - } - } - if( chngRowid==0 && pPk==0 ){ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); -#endif - sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); - } - } - - /* Populate the array of registers beginning at regNew with the new - ** row data. This array is used to check constants, create the new - ** table and index records, and as the values for any new.* references - ** made by triggers. - ** - ** If there are one or more BEFORE triggers, then do not populate the - ** registers associated with columns that are (a) not modified by - ** this UPDATE statement and (b) not accessed by new.* references. The - ** values for registers not modified by the UPDATE must be reloaded from - ** the database after the BEFORE triggers are fired anyway (as the trigger - ** may have modified them). So not loading those that are not going to - ** be used eliminates some redundant opcodes. - */ - newmask = sqlite3TriggerColmask( - pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError - ); - for(i=0, k=regNew; inCol; i++, k++){ - if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); - }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--; - }else{ - j = aXRef[i]; - if( j>=0 ){ - if( nChangeFrom ){ - int nOff = (isView ? pTab->nCol : nPk); - assert( eOnePass==ONEPASS_OFF ); - sqlite3VdbeAddOp3(v, OP_Column, iEph, nOff+j, k); - }else{ - sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k); - } - }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ - /* This branch loads the value of a column that will not be changed - ** into a register. This is done if there are no BEFORE triggers, or - ** if there are one or more BEFORE triggers that use this value via - ** a new.* reference in a trigger program. - */ - testcase( i==31 ); - testcase( i==32 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); - bFinishSeek = 0; - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); - } - } - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regNew, pTab); - } -#endif - - /* Fire any BEFORE UPDATE triggers. This happens before constraints are - ** verified. One could argue that this is wrong. - */ - if( tmask&TRIGGER_BEFORE ){ - sqlite3TableAffinity(v, pTab, regNew); - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); - - if( !isView ){ - /* The row-trigger may have deleted the row being updated. In this - ** case, jump to the next row. No updates or AFTER triggers are - ** required. This behavior - what happens when the row being updated - ** is deleted or renamed by a BEFORE trigger - is left undefined in the - ** documentation. - */ - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); - VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); - VdbeCoverage(v); - } - - /* After-BEFORE-trigger-reload-loop: - ** If it did not delete it, the BEFORE trigger may still have modified - ** some of the columns of the row being updated. Load the values for - ** all columns not modified by the update statement into their registers - ** in case this has happened. Only unmodified columns are reloaded. - ** The values computed for modified columns use the values before the - ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) - ** for an example. - */ - for(i=0, k=regNew; inCol; i++, k++){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--; - }else if( aXRef[i]<0 && i!=pTab->iPKey ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); - } - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regNew, pTab); - } -#endif - } - } - - if( !isView ){ - /* Do constraint checks. */ - assert( regOldRowid>0 ); - sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, - aXRef, 0); - - /* If REPLACE conflict handling may have been used, or if the PK of the - ** row is changing, then the GenerateConstraintChecks() above may have - ** moved cursor iDataCur. Reseek it. */ - if( bReplace || chngKey ){ - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); - }else{ - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); - } - VdbeCoverage(v); - } - - /* Do FK constraint checks. */ - if( hasFK ){ - sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); - } - - /* Delete the index entries associated with the current record. */ - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); - - /* We must run the OP_FinishSeek opcode to resolve a prior - ** OP_DeferredSeek if there is any possibility that there have been - ** no OP_Column opcodes since the OP_DeferredSeek was issued. But - ** we want to avoid the OP_FinishSeek if possible, as running it - ** costs CPU cycles. */ - if( bFinishSeek ){ - sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur); - } - - /* If changing the rowid value, or if there are foreign key constraints - ** to process, delete the old record. Otherwise, add a noop OP_Delete - ** to invoke the pre-update hook. - ** - ** That (regNew==regnewRowid+1) is true is also important for the - ** pre-update hook. If the caller invokes preupdate_new(), the returned - ** value is copied from memory cell (regNewRowid+1+iCol), where iCol - ** is the column index supplied by the user. - */ - assert( regNew==regNewRowid+1 ); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, - OPFLAG_ISUPDATE | ((hasFK>1 || chngKey) ? 0 : OPFLAG_ISNOOP), - regNewRowid - ); - if( eOnePass==ONEPASS_MULTI ){ - assert( hasFK==0 && chngKey==0 ); - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - } - if( !pParse->nested ){ - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - } -#else - if( hasFK>1 || chngKey ){ - sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); - } -#endif - - if( hasFK ){ - sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); - } - - /* Insert the new index entries and the new record. */ - sqlite3CompleteInsertion( - pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, - OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), - 0, 0 - ); - - /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to - ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just updated. */ - if( hasFK ){ - sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); - } - } - - /* Increment the row counter - */ - if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); - } - - if( pTrigger ){ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); - } - - /* Repeat the above with the next record to be updated, until - ** all record selected by the WHERE clause have been updated. - */ - if( eOnePass==ONEPASS_SINGLE ){ - /* Nothing to do at end-of-loop for a single-pass */ - }else if( eOnePass==ONEPASS_MULTI ){ - sqlite3VdbeResolveLabel(v, labelContinue); - sqlite3WhereEnd(pWInfo); - }else{ - sqlite3VdbeResolveLabel(v, labelContinue); - sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); - } - sqlite3VdbeResolveLabel(v, labelBreak); - - /* Update the sqlite_sequence table by storing the content of the - ** maximum rowid counter values recorded while inserting into - ** autoincrement tables. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* - ** Return the number of rows that were changed, if we are tracking - ** that information. - */ - if( regRowCount ){ - sqlite3CodeChangeCount(v, regRowCount, "rows updated"); - } - -update_cleanup: - sqlite3AuthContextPop(&sContext); - sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */ - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprListDelete(db, pChanges); - sqlite3ExprDelete(db, pWhere); -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) - sqlite3ExprListDelete(db, pOrderBy); - sqlite3ExprDelete(db, pLimit); -#endif - return; -} -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Generate code for an UPDATE of a virtual table. -** -** There are two possible strategies - the default and the special -** "onepass" strategy. Onepass is only used if the virtual table -** implementation indicates that pWhere may match at most one row. -** -** The default strategy is to create an ephemeral table that contains -** for each row to be changed: -** -** (A) The original rowid of that row. -** (B) The revised rowid for the row. -** (C) The content of every column in the row. -** -** Then loop through the contents of this ephemeral table executing a -** VUpdate for each row. When finished, drop the ephemeral table. -** -** The "onepass" strategy does not use an ephemeral table. Instead, it -** stores the same values (A, B and C above) in a register array and -** makes a single invocation of VUpdate. -*/ -static void updateVirtualTable( - Parse *pParse, /* The parsing context */ - SrcList *pSrc, /* The virtual table to be modified */ - Table *pTab, /* The virtual table */ - ExprList *pChanges, /* The columns to change in the UPDATE statement */ - Expr *pRowid, /* Expression used to recompute the rowid */ - int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ - Expr *pWhere, /* WHERE clause of the UPDATE statement */ - int onError /* ON CONFLICT strategy */ -){ - Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ - int ephemTab; /* Table holding the result of the SELECT */ - int i; /* Loop counter */ - sqlite3 *db = pParse->db; /* Database connection */ - const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); - WhereInfo *pWInfo = 0; - int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ - int regArg; /* First register in VUpdate arg array */ - int regRec; /* Register in which to assemble record */ - int regRowid; /* Register for ephemeral table rowid */ - int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ - int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ - int eOnePass; /* True to use onepass strategy */ - int addr; /* Address of OP_OpenEphemeral */ - - /* Allocate nArg registers in which to gather the arguments for VUpdate. Then - ** create and open the ephemeral table in which the records created from - ** these arguments will be temporarily stored. */ - assert( v ); - ephemTab = pParse->nTab++; - addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); - regArg = pParse->nMem + 1; - pParse->nMem += nArg; - if( pSrc->nSrc>1 ){ - Index *pPk = 0; - Expr *pRow; - ExprList *pList; - if( HasRowid(pTab) ){ - if( pRowid ){ - pRow = sqlite3ExprDup(db, pRowid, 0); - }else{ - pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0); - } - }else{ - i16 iPk; /* PRIMARY KEY column */ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->nKeyCol==1 ); - iPk = pPk->aiColumn[0]; - if( aXRef[iPk]>=0 ){ - pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0); - }else{ - pRow = exprRowColumn(pParse, iPk); - } - } - pList = sqlite3ExprListAppend(pParse, 0, pRow); - - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ){ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) - ); - }else{ - Expr *pRowExpr = exprRowColumn(pParse, i); - if( pRowExpr ) pRowExpr->op2 = OPFLAG_NOCHNG; - pList = sqlite3ExprListAppend(pParse, pList, pRowExpr); - } - } - - updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0); - sqlite3ExprListDelete(db, pList); - eOnePass = ONEPASS_OFF; - }else{ - regRec = ++pParse->nMem; - regRowid = ++pParse->nMem; - - /* Start scanning the virtual table */ - pWInfo = sqlite3WhereBegin( - pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0 - ); - if( pWInfo==0 ) return; - - /* Populate the argument registers. */ - for(i=0; inCol; i++){ - assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ); - if( aXRef[i]>=0 ){ - sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); - }else{ - sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* For sqlite3_vtab_nochange() */ - } - } - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); - if( pRowid ){ - sqlite3ExprCode(pParse, pRowid, regArg+1); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); - } - }else{ - Index *pPk; /* PRIMARY KEY index */ - i16 iPk; /* PRIMARY KEY column */ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->nKeyCol==1 ); - iPk = pPk->aiColumn[0]; - sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg); - sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); - } - - eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); - - /* There is no ONEPASS_MULTI on virtual tables */ - assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); - - if( eOnePass ){ - /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded - ** above. */ - sqlite3VdbeChangeToNoop(v, addr); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); - }else{ - /* Create a record from the argument register contents and insert it into - ** the ephemeral table. */ - sqlite3MultiWrite(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); -#if defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_NULL_TRIM) - /* Signal an assert() within OP_MakeRecord that it is allowed to - ** accept no-change records with serial_type 10 */ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); -#endif - sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); - } - } - - - if( eOnePass==ONEPASS_OFF ){ - /* End the virtual table scan */ - if( pSrc->nSrc==1 ){ - sqlite3WhereEnd(pWInfo); - } - - /* Begin scanning through the ephemeral table. */ - addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); - - /* Extract arguments from the current row of the ephemeral table and - ** invoke the VUpdate method. */ - for(i=0; ipNextUpsert; - sqlite3ExprListDelete(db, p->pUpsertTarget); - sqlite3ExprDelete(db, p->pUpsertTargetWhere); - sqlite3ExprListDelete(db, p->pUpsertSet); - sqlite3ExprDelete(db, p->pUpsertWhere); - sqlite3DbFree(db, p->pToFree); - sqlite3DbFree(db, p); - p = pNext; - }while( p ); -} -SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){ - if( p ) upsertDelete(db, p); -} - - -/* -** Duplicate an Upsert object. -*/ -SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){ - if( p==0 ) return 0; - return sqlite3UpsertNew(db, - sqlite3ExprListDup(db, p->pUpsertTarget, 0), - sqlite3ExprDup(db, p->pUpsertTargetWhere, 0), - sqlite3ExprListDup(db, p->pUpsertSet, 0), - sqlite3ExprDup(db, p->pUpsertWhere, 0), - sqlite3UpsertDup(db, p->pNextUpsert) - ); -} - -/* -** Create a new Upsert object. -*/ -SQLITE_PRIVATE Upsert *sqlite3UpsertNew( - sqlite3 *db, /* Determines which memory allocator to use */ - 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 */ - Upsert *pNext /* Next ON CONFLICT clause in the list */ -){ - Upsert *pNew; - pNew = sqlite3DbMallocZero(db, sizeof(Upsert)); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pTarget); - sqlite3ExprDelete(db, pTargetWhere); - sqlite3ExprListDelete(db, pSet); - sqlite3ExprDelete(db, pWhere); - sqlite3UpsertDelete(db, pNext); - return 0; - }else{ - pNew->pUpsertTarget = pTarget; - pNew->pUpsertTargetWhere = pTargetWhere; - pNew->pUpsertSet = pSet; - pNew->pUpsertWhere = pWhere; - pNew->isDoUpdate = pSet!=0; - pNew->pNextUpsert = pNext; - } - return pNew; -} - -/* -** Analyze the ON CONFLICT clause described by pUpsert. Resolve all -** symbols in the conflict-target. -** -** Return SQLITE_OK if everything works, or an error code is something -** is wrong. -*/ -SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( - Parse *pParse, /* The parsing context */ - SrcList *pTabList, /* Table into which we are inserting */ - Upsert *pUpsert, /* The ON CONFLICT clauses */ - Upsert *pAll /* Complete list of all ON CONFLICT clauses */ -){ - Table *pTab; /* That table into which we are inserting */ - int rc; /* Result code */ - int iCursor; /* Cursor used by pTab */ - Index *pIdx; /* One of the indexes of pTab */ - ExprList *pTarget; /* The conflict-target clause */ - 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].pSTab!=0 ); - assert( pUpsert!=0 ); - assert( pUpsert->pUpsertTarget!=0 ); - - /* Resolve all symbolic names in the conflict-target clause, which - ** includes both the list of columns and the optional partial-index - ** WHERE clause. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - for(; pUpsert && pUpsert->pUpsertTarget; - pUpsert=pUpsert->pNextUpsert, nClause++){ - rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); - if( rc ) return rc; - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); - if( rc ) return rc; - - /* Check to see if the conflict target matches the rowid. */ - pTab = pTabList->a[0].pSTab; - 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; - - /* 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( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere, - pIdx->pPartIdxWhere, iCursor)!=0 ){ - continue; - } - } - nn = pIdx->nKeyCol; - for(ii=0; iiazColl[ii]; - if( pIdx->aiColumn[ii]==XN_EXPR ){ - assert( pIdx->aColExpr!=0 ); - assert( pIdx->aColExpr->nExpr>ii ); - assert( pIdx->bHasExpr ); - 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]; - } - for(jj=0; jja[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( iipUpsertIdx = pIdx; - if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){ - /* Really this should be an error. The isDup ON CONFLICT clause will - ** never fire. But this problem was not discovered until three years - ** after multi-CONFLICT upsert was added, and so we silently ignore - ** the problem to prevent breaking applications that might actually - ** have redundant ON CONFLICT clauses. */ - pUpsert->isDup = 1; - } - break; - } - if( pUpsert->pUpsertIdx==0 ){ - char zWhich[16]; - if( nClause==0 && pUpsert->pNextUpsert==0 ){ - zWhich[0] = 0; - }else{ - sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1); - } - sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any " - "PRIMARY KEY or UNIQUE constraint", zWhich); - 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 sqlite3UpsertNextIsIPK(Upsert *pUpsert){ - Upsert *pNext; - if( NEVER(pUpsert==0) ) return 0; - pNext = pUpsert->pNextUpsert; - while( 1 /*exit-by-return*/ ){ - if( pNext==0 ) return 1; - if( pNext->pUpsertTarget==0 ) return 1; - if( pNext->pUpsertIdx==0 ) return 1; - if( !pNext->isDup ) return 0; - pNext = pNext->pNextUpsert; - } - 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 *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){ - while( - pUpsert - && pUpsert->pUpsertTarget!=0 - && pUpsert->pUpsertIdx!=pIdx - ){ - pUpsert = pUpsert->pNextUpsert; - } - return pUpsert; -} - -/* -** Generate bytecode that does an UPDATE as part of an upsert. -** -** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK. -** In this case parameter iCur is a cursor open on the table b-tree that -** currently points to the conflicting table row. Otherwise, if pIdx -** is not NULL, then pIdx is the constraint that failed and iCur is a -** cursor points to the conflicting row. -*/ -SQLITE_PRIVATE void sqlite3UpsertDoUpdate( - Parse *pParse, /* The parsing and code-generating context */ - Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */ - Table *pTab, /* The table being updated */ - Index *pIdx, /* The UNIQUE constraint that failed */ - int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ -){ - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - SrcList *pSrc; /* FROM clause for the UPDATE */ - int iDataCur; - int i; - Upsert *pTop = pUpsert; - - assert( v!=0 ); - assert( pUpsert!=0 ); - iDataCur = pUpsert->iDataCur; - pUpsert = sqlite3UpsertOfIndex(pTop, pIdx); - VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); - if( pIdx && iCur!=iDataCur ){ - if( HasRowid(pTab) ){ - int regRowid = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); - sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, regRowid); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - int nPk = pPk->nKeyCol; - int iPk = pParse->nMem+1; - pParse->nMem += nPk; - for(i=0; iaiColumn[i]>=0 ); - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); - sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); - VdbeComment((v, "%s.%s", pIdx->zName, - pTab->aCol[pPk->aiColumn[i]].zCnName)); - } - sqlite3VdbeVerifyAbortable(v, OE_Abort); - i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); - VdbeCoverage(v); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, - "corrupt database", P4_STATIC); - sqlite3MayAbort(pParse); - sqlite3VdbeJumpHere(v, i); - } - } - /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does. - ** So we have to make a copy before passing it down into sqlite3Update() */ - pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0); - /* excluded.* columns of type REAL need to be converted to a hard real */ - for(i=0; inCol; i++){ - if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i); - } - } - sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0), - sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert); - VdbeNoopComment((v, "End DO UPDATE of UPSERT")); -} - -#endif /* SQLITE_OMIT_UPSERT */ - -/************** End of upsert.c **********************************************/ -/************** Begin file vacuum.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the VACUUM command. -** -** Most of the code in this file may be omitted by defining the -** SQLITE_OMIT_VACUUM macro. -*/ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ - -#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) - -/* -** Execute zSql on database db. -** -** If zSql returns rows, then each row will have exactly one -** column. (This will only happen if zSql begins with "SELECT".) -** Take each row of result and call execSql() again recursively. -** -** The execSqlF() routine does the same thing, except it accepts -** a format string as its third argument -*/ -static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - int rc; - - /* printf("SQL: [%s]\n", zSql); fflush(stdout); */ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ - const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); - assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); - /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, - ** or INSERT. Historically there have been attacks that first - ** corrupt the sqlite_schema.sql field with other kinds of statements - ** then run VACUUM to get those statements to execute at inappropriate - ** times. */ - if( zSubSql - && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) - ){ - rc = execSql(db, pzErrMsg, zSubSql); - if( rc!=SQLITE_OK ) break; - } - } - assert( rc!=SQLITE_ROW ); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - if( rc ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - } - (void)sqlite3_finalize(pStmt); - return rc; -} -static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){ - char *z; - va_list ap; - int rc; - va_start(ap, zSql); - z = sqlite3VMPrintf(db, zSql, ap); - va_end(ap); - if( z==0 ) return SQLITE_NOMEM; - rc = execSql(db, pzErrMsg, z); - sqlite3DbFree(db, z); - return rc; -} - -/* -** The VACUUM command is used to clean up the database, -** collapse free space, etc. It is modelled after the VACUUM command -** in PostgreSQL. The VACUUM command works as follows: -** -** (1) Create a new transient database file -** (2) Copy all content from the database being vacuumed into -** the new transient database file -** (3) Copy content from the transient database back into the -** original database. -** -** The transient database requires temporary disk space approximately -** equal to the size of the original database. The copy operation of -** step (3) requires additional temporary disk space approximately equal -** to the size of the original database for the rollback journal. -** Hence, temporary disk space that is approximately 2x the size of the -** original database is required. Every page of the database is written -** approximately 3 times: Once for step (2) and twice for step (3). -** Two writes per page are required in step (3) because the original -** database content must be written into the rollback journal prior to -** overwriting the database with the vacuumed content. -** -** Only 1x temporary space and only 1x writes would be required if -** the copy of step (3) were replaced by deleting the original database -** and renaming the transient database as the original. But that will -** not work if other processes are attached to the original database. -** And a power loss in between deleting the original and renaming the -** transient would cause the database file to appear to be deleted -** following reboot. -*/ -SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){ - Vdbe *v = sqlite3GetVdbe(pParse); - int iDb = 0; - if( v==0 ) goto build_vacuum_end; - if( pParse->nErr ) goto build_vacuum_end; - if( pNm ){ -#ifndef SQLITE_BUG_COMPATIBLE_20160819 - /* Default behavior: Report an error if the argument to VACUUM is - ** not recognized */ - iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm); - if( iDb<0 ) goto build_vacuum_end; -#else - /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments - ** to VACUUM are silently ignored. This is a back-out of a bug fix that - ** occurred on 2016-08-19 (https://sqlite.org/src/info/083f9e6270). - ** The buggy behavior is required for binary compatibility with some - ** legacy applications. */ - iDb = sqlite3FindDb(pParse->db, pNm); - if( iDb<0 ) iDb = 0; -#endif - } - if( iDb!=1 ){ - int iIntoReg = 0; - if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){ - iIntoReg = ++pParse->nMem; - sqlite3ExprCode(pParse, pInto, iIntoReg); - } - sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg); - sqlite3VdbeUsesBtree(v, iDb); - } -build_vacuum_end: - sqlite3ExprDelete(pParse->db, pInto); - return; -} - -/* -** This routine implements the OP_Vacuum opcode of the VDBE. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( - char **pzErrMsg, /* Write error message here */ - sqlite3 *db, /* Database connection */ - int iDb, /* Which attached DB to vacuum */ - sqlite3_value *pOut /* Write results here, if not NULL. VACUUM INTO */ -){ - int rc = SQLITE_OK; /* Return code from service routines */ - Btree *pMain; /* The database being vacuumed */ - Btree *pTemp; /* The temporary database we vacuum into */ - u32 saved_mDbFlags; /* Saved value of db->mDbFlags */ - u64 saved_flags; /* Saved value of db->flags */ - 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 */ - int isMemDb; /* True if vacuuming a :memory: database */ - int nRes; /* Bytes of reserved space at the end of each page */ - int nDb; /* Number of attached databases */ - const char *zDbMain; /* Schema name of database to vacuum */ - const char *zOut; /* Name of output file */ - u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */ - u64 iRandom; /* Random value used for zDbVacuum[] */ - char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */ - - - if( !db->autoCommit ){ - sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); - return SQLITE_ERROR; /* IMP: R-12218-18073 */ - } - if( db->nVdbeActive>1 ){ - sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); - return SQLITE_ERROR; /* IMP: R-15610-35227 */ - } - saved_openFlags = db->openFlags; - if( pOut ){ - if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){ - sqlite3SetString(pzErrMsg, db, "non-text filename"); - return SQLITE_ERROR; - } - zOut = (const char*)sqlite3_value_text(pOut); - db->openFlags &= ~SQLITE_OPEN_READONLY; - db->openFlags |= SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; - }else{ - zOut = ""; - } - - /* Save the current value of the database flags so that it can be - ** restored before returning. Then set the writable-schema flag, and - ** disable CHECK and foreign key constraints. */ - saved_flags = db->flags; - saved_mDbFlags = db->mDbFlags; - saved_nChange = db->nChange; - saved_nTotalChange = db->nTotalChange; - saved_mTrace = db->mTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments; - db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; - db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder - | SQLITE_Defensive | SQLITE_CountRows); - db->mTrace = 0; - - zDbMain = db->aDb[iDb].zDbSName; - pMain = db->aDb[iDb].pBt; - isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); - - /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma - ** can be set to 'off' for this file, as it is not recovered if a crash - ** occurs anyway. The integrity of the database is maintained by a - ** (possibly synchronous) transaction opened on the main database before - ** sqlite3BtreeCopyFile() is called. - ** - ** An optimization would be to use a non-journaled pager. - ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but - ** that actually made the VACUUM run slower. Very little journalling - ** actually occurs when doing a vacuum since the vacuum_db is initially - ** empty. Only the journal header is written. Apparently it takes more - ** time to parse and run the PRAGMA to turn journalling off than it does - ** to write the journal header file. - */ - sqlite3_randomness(sizeof(iRandom),&iRandom); - sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom); - nDb = db->nDb; - rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum); - db->openFlags = saved_openFlags; - if( rc!=SQLITE_OK ) goto end_of_vacuum; - assert( (db->nDb-1)==nDb ); - pDb = &db->aDb[nDb]; - assert( strcmp(pDb->zDbSName,zDbVacuum)==0 ); - pTemp = pDb->pBt; - if( pOut ){ - sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp)); - i64 sz = 0; - if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){ - rc = SQLITE_ERROR; - sqlite3SetString(pzErrMsg, db, "output file already exists"); - goto end_of_vacuum; - } - db->mDbFlags |= DBFLAG_VacuumInto; - - /* For a VACUUM INTO, the pager-flags are set to the same values as - ** they are for the database being vacuumed, except that PAGER_CACHESPILL - ** is always set. */ - pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK); - } - nRes = sqlite3BtreeGetRequestedReserve(pMain); - - /* A VACUUM cannot change the pagesize of an encrypted database. */ -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC - if( db->nextPagesize ){ - extern void sqlcipherCodecGetKey(sqlite3*, int, void**, int*); - extern void sqlcipher_free(void*, sqlite3_uint64); - int nKey; - char *zKey; - sqlcipherCodecGetKey(db, iDb, (void**)&zKey, &nKey); - if( nKey ) db->nextPagesize = 0; - if(nKey) sqlcipher_free(zKey, nKey); - } -#endif -/* END SQLCIPHER */ - - sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); - sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); - sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL); - - /* Begin a transaction and take an exclusive lock on the main database - ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, - ** to ensure that we do not try to change the page-size on a WAL database. - */ - rc = execSql(db, pzErrMsg, "BEGIN"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Do not attempt to change the page size for a WAL database */ - if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) - ==PAGER_JOURNALMODE_WAL - && pOut==0 - ){ - db->nextPagesize = 0; - } - - if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0) - || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) - || NEVER(db->mallocFailed) - ){ - rc = SQLITE_NOMEM_BKPT; - goto end_of_vacuum; - } - -#ifndef SQLITE_OMIT_AUTOVACUUM - sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : - sqlite3BtreeGetAutoVacuum(pMain)); -#endif - - /* Query the schema of the main database. Create a mirror schema - ** in the temporary database. - */ - db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ - rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_schema" - " WHERE type='table'AND name<>'sqlite_sequence'" - " AND coalesce(rootpage,1)>0", - zDbMain - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_schema" - " WHERE type='index'", - zDbMain - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - db->init.iDb = 0; - - /* Loop through the tables in the main database. For each, do - ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy - ** the contents to the temporary database. - */ - rc = execSqlF(db, pzErrMsg, - "SELECT'INSERT INTO %s.'||quote(name)" - "||' SELECT*FROM\"%w\".'||quote(name)" - "FROM %s.sqlite_schema " - "WHERE type='table'AND coalesce(rootpage,1)>0", - zDbVacuum, zDbMain, zDbVacuum - ); - assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 ); - db->mDbFlags &= ~DBFLAG_Vacuum; - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* 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 schema table. - */ - rc = execSqlF(db, pzErrMsg, - "INSERT INTO %s.sqlite_schema" - " SELECT*FROM \"%w\".sqlite_schema" - " WHERE type IN('view','trigger')" - " OR(type='table'AND rootpage=0)", - zDbVacuum, zDbMain - ); - if( rc ) goto end_of_vacuum; - - /* At this point, there is a write transaction open on both the - ** vacuum database and the main database. Assuming no error occurs, - ** both transactions are closed by this block - the main database - ** transaction by sqlite3BtreeCopyFile() and the other by an explicit - ** call to sqlite3BtreeCommit(). - */ - { - u32 meta; - int i; - - /* This array determines which meta meta values are preserved in the - ** vacuum. Even entries are the meta value number and odd entries - ** are an increment to apply to the meta value after the vacuum. - ** The increment is used to increase the schema cookie so that other - ** connections to the same database will know to reread the schema. - */ - static const unsigned char aCopy[] = { - BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ - BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ - BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ - BTREE_USER_VERSION, 0, /* Preserve the user version */ - BTREE_APPLICATION_ID, 0, /* Preserve the application id */ - }; - - assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) ); - assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) ); - - /* Copy Btree meta values */ - for(i=0; iflags */ - db->init.iDb = 0; - db->mDbFlags = saved_mDbFlags; - db->flags = saved_flags; - db->nChange = saved_nChange; - db->nTotalChange = saved_nTotalChange; - db->mTrace = saved_mTrace; - sqlite3BtreeSetPageSize(pMain, -1, 0, 1); - - /* Currently there is an SQL level transaction open on the vacuum - ** database. No locks are held on any other files (since the main file - ** was committed at the btree level). So it safe to end the transaction - ** by manually setting the autoCommit flag to true and detaching the - ** vacuum database. The vacuum_db journal file is deleted when the pager - ** is closed by the DETACH. - */ - db->autoCommit = 1; - - if( pDb ){ - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - } - - /* This both clears the schemas and reduces the size of the db->aDb[] - ** array. */ - sqlite3ResetAllSchemasOfConnection(db); - - return rc; -} - -#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ - -/************** End of vacuum.c **********************************************/ -/************** Begin file vtab.c ********************************************/ -/* -** 2006 June 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to help implement virtual tables. -*/ -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* #include "sqliteInt.h" */ - -/* -** Before a virtual table xCreate() or xConnect() method is invoked, the -** sqlite3.pVtabCtx member variable is set to point to an instance of -** this struct allocated on the stack. It is used by the implementation of -** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which -** are invoked only from within xCreate and xConnect methods. -*/ -struct VtabCtx { - VTable *pVTable; /* The virtual table being constructed */ - Table *pTab; /* The Table object to which the virtual table belongs */ - VtabCtx *pPrior; /* Parent context (if any) */ - int bDeclared; /* True after sqlite3_declare_vtab() is called */ -}; - -/* -** Construct and install a Module object for a virtual table. When this -** routine is called, it is guaranteed that all appropriate locks are held -** and the module is not already part of the connection. -** -** If there already exists a module with zName, replace it with the new one. -** If pModule==0, then delete the module zName if it exists. -*/ -SQLITE_PRIVATE Module *sqlite3VtabCreateModule( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ - Module *pMod; - Module *pDel; - char *zCopy; - if( pModule==0 ){ - zCopy = (char*)zName; - pMod = 0; - }else{ - int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); - if( pMod==0 ){ - sqlite3OomFault(db); - return 0; - } - zCopy = (char *)(&pMod[1]); - memcpy(zCopy, zName, nName+1); - pMod->zName = zCopy; - pMod->pModule = pModule; - pMod->pAux = pAux; - pMod->xDestroy = xDestroy; - pMod->pEpoTab = 0; - pMod->nRefModule = 1; - } - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - if( pDel ){ - if( pDel==pMod ){ - sqlite3OomFault(db); - sqlite3DbFree(db, pDel); - pMod = 0; - }else{ - sqlite3VtabEponymousTableClear(db, pDel); - sqlite3VtabModuleUnref(db, pDel); - } - } - return pMod; -} - -/* -** The actual function that does the work of creating a new module. -** This function implements the sqlite3_create_module() and -** sqlite3_create_module_v2() interfaces. -*/ -static int createModule( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ - int rc = SQLITE_OK; - - sqlite3_mutex_enter(db->mutex); - (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); - rc = sqlite3ApiExit(db, rc); - if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); - sqlite3_mutex_leave(db->mutex); - return rc; -} - - -/* -** External API function used to create a new virtual-table module. -*/ -SQLITE_API int sqlite3_create_module( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux /* Context pointer for xCreate/xConnect */ -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif - return createModule(db, zName, pModule, pAux, 0); -} - -/* -** External API function used to create a new virtual-table module. -*/ -SQLITE_API int sqlite3_create_module_v2( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif - return createModule(db, zName, pModule, pAux, xDestroy); -} - -/* -** External API to drop all virtual-table modules, except those named -** on the azNames list. -*/ -SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ - HashElem *pThis, *pNext; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ - Module *pMod = (Module*)sqliteHashData(pThis); - pNext = sqliteHashNext(pThis); - if( azNames ){ - int ii; - for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} - if( azNames[ii]!=0 ) continue; - } - createModule(db, pMod->zName, 0, 0, 0); - } - return SQLITE_OK; -} - -/* -** Decrement the reference count on a Module object. Destroy the -** module when the reference count reaches zero. -*/ -SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){ - assert( pMod->nRefModule>0 ); - pMod->nRefModule--; - if( pMod->nRefModule==0 ){ - if( pMod->xDestroy ){ - pMod->xDestroy(pMod->pAux); - } - assert( pMod->pEpoTab==0 ); - sqlite3DbFree(db, pMod); - } -} - -/* -** Lock the virtual table so that it cannot be disconnected. -** Locks nest. Every lock should have a corresponding unlock. -** If an unlock is omitted, resources leaks will occur. -** -** If a disconnect is attempted while a virtual table is locked, -** the disconnect is deferred until all locks have been removed. -*/ -SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){ - pVTab->nRef++; -} - - -/* -** pTab is a pointer to a Table structure representing a virtual-table. -** Return a pointer to the VTable object used by connection db to access -** this virtual-table, if one has been created, or NULL otherwise. -*/ -SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ - VTable *pVtab; - assert( IsVirtual(pTab) ); - for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); - return pVtab; -} - -/* -** Decrement the ref-count on a virtual table object. When the ref-count -** reaches zero, call the xDisconnect() method to delete the object. -*/ -SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){ - sqlite3 *db = pVTab->db; - - assert( db ); - assert( pVTab->nRef>0 ); - assert( db->eOpenState==SQLITE_STATE_OPEN - || db->eOpenState==SQLITE_STATE_ZOMBIE ); - - pVTab->nRef--; - if( pVTab->nRef==0 ){ - sqlite3_vtab *p = pVTab->pVtab; - if( p ){ - p->pModule->xDisconnect(p); - } - sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); - sqlite3DbFree(db, pVTab); - } -} - -/* -** Table p is a virtual table. This function moves all elements in the -** p->u.vtab.p list to the 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->u.vtab.p list. -*/ -static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ - VTable *pRet = 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 sqlite3VtabUnlockList() for an explanation of why - ** this makes it safe to access the sqlite3.pDisconnect list of any - ** database connection that may have an entry in the p->u.vtab.p list. - */ - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); - - while( pVTable ){ - sqlite3 *db2 = pVTable->db; - VTable *pNext = pVTable->pNext; - assert( db2 ); - if( db2==db ){ - pRet = pVTable; - p->u.vtab.p = pRet; - pRet->pNext = 0; - }else{ - pVTable->pNext = db2->pDisconnect; - db2->pDisconnect = pVTable; - } - pVTable = pNext; - } - - assert( !db || pRet ); - return pRet; -} - -/* -** Table *p is a virtual table. This function removes the VTable object -** for table *p associated with database connection db from the linked -** list in p->pVTab. It also decrements the VTable ref count. This is -** used when closing database connection db to free all of its VTable -** objects without disturbing the rest of the Schema object (which may -** be being used by other shared-cache connections). -*/ -SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ - VTable **ppVTab; - - assert( IsVirtual(p) ); - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3_mutex_held(db->mutex) ); - - for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){ - if( (*ppVTab)->db==db ){ - VTable *pVTab = *ppVTab; - *ppVTab = pVTab->pNext; - sqlite3VtabUnlock(pVTab); - break; - } - } -} - - -/* -** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. -** -** This function may only be called when the mutexes associated with all -** shared b-tree databases opened using connection db are held by the -** caller. This is done to protect the sqlite3.pDisconnect list. The -** sqlite3.pDisconnect list is accessed only as follows: -** -** 1) By this function. In this case, all BtShared mutexes and the mutex -** associated with the database handle itself must be held. -** -** 2) By function vtabDisconnectAll(), when it adds a VTable entry to -** the sqlite3.pDisconnect list. In this case either the BtShared mutex -** associated with the database the virtual table is stored in is held -** or, if the virtual table is stored in a non-sharable database, then -** the database handle mutex is held. -** -** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously -** by multiple threads. It is thread-safe. -*/ -SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ - VTable *p = db->pDisconnect; - - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3_mutex_held(db->mutex) ); - - if( p ){ - db->pDisconnect = 0; - do { - VTable *pNext = p->pNext; - sqlite3VtabUnlock(p); - p = pNext; - }while( p ); - } -} - -/* -** Clear any and all virtual-table information from the Table record. -** This routine is called, for example, just before deleting the Table -** record. -** -** Since it is a virtual-table, the Table structure contains a pointer -** to the head of a linked list of VTable structures. Each VTable -** structure is associated with a single sqlite3* user of the schema. -** The reference count of the VTable structure associated with database -** connection db is decremented immediately (which may lead to the -** structure being xDisconnected and free). Any other VTable structures -** in the list are moved to the sqlite3.pDisconnect list of the associated -** database connection. -*/ -SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ - assert( IsVirtual(p) ); - assert( db!=0 ); - if( db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); - if( p->u.vtab.azArg ){ - int i; - for(i=0; iu.vtab.nArg; i++){ - if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]); - } - sqlite3DbFree(db, p->u.vtab.azArg); - } -} - -/* -** 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){ - sqlite3_int64 nBytes; - char **azModuleArg; - sqlite3 *db = pParse->db; - - assert( IsVirtual(pTable) ); - nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg); - if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); - } - azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes); - if( azModuleArg==0 ){ - sqlite3DbFree(db, zArg); - }else{ - int i = pTable->u.vtab.nArg++; - azModuleArg[i] = zArg; - azModuleArg[i+1] = 0; - pTable->u.vtab.azArg = azModuleArg; - } -} - -/* -** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE -** statement. The module name has been parsed, but the optional list -** of parameters that follow the module name are still pending. -*/ -SQLITE_PRIVATE void sqlite3VtabBeginParse( - Parse *pParse, /* Parsing context */ - Token *pName1, /* Name of new table, or database name */ - Token *pName2, /* Name of new table or NULL */ - Token *pModuleName, /* Name of the module for the virtual table */ - int ifNotExists /* No error if the table already exists */ -){ - Table *pTable; /* The new virtual table */ - sqlite3 *db; /* Database connection */ - - sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); - pTable = pParse->pNewTable; - if( pTable==0 ) return; - assert( 0==pTable->pIndex ); - pTable->eTabType = TABTYP_VTAB; - - db = pParse->db; - - assert( pTable->u.vtab.nArg==0 ); - addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); - addModuleArgument(pParse, pTable, 0); - addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); - assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) - || (pParse->sNameToken.z==pName1->z && pName2->z==0) - ); - pParse->sNameToken.n = (int)( - &pModuleName->z[pModuleName->n] - pParse->sNameToken.z - ); - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Creating a virtual table invokes the authorization callback twice. - ** The first invocation, to obtain permission to INSERT a row into the - ** sqlite_schema table, has already been made by sqlite3StartTable(). - ** The second call, to obtain permission to create the table, is made now. - */ - if( pTable->u.vtab.azArg ){ - int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); /* The database the table is being created in */ - sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName); - } -#endif -} - -/* -** This routine takes the module argument that has been accumulating -** in pParse->zArg[] and appends it to the list of arguments on the -** virtual table currently under construction in pParse->pTable. -*/ -static void addArgumentToVtab(Parse *pParse){ - if( pParse->sArg.z && pParse->pNewTable ){ - const char *z = (const char*)pParse->sArg.z; - int n = pParse->sArg.n; - sqlite3 *db = pParse->db; - addModuleArgument(pParse, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); - } -} - -/* -** The parser calls this routine after the CREATE VIRTUAL TABLE statement -** has been completely parsed. -*/ -SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ - Table *pTab = pParse->pNewTable; /* The table being constructed */ - sqlite3 *db = pParse->db; /* The database connection */ - - if( pTab==0 ) return; - assert( IsVirtual(pTab) ); - addArgumentToVtab(pParse); - pParse->sArg.z = 0; - 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 - ** created now instead of just being read out of sqlite_schema) then - ** do additional initialization work and store the statement text - ** in the sqlite_schema table. - */ - if( !db->init.busy ){ - char *zStmt; - char *zWhere; - int iDb; - int iReg; - Vdbe *v; - - sqlite3MayAbort(pParse); - - /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ - if( pEnd ){ - pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n; - } - zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken); - - /* A slot for the record has already been allocated in the - ** schema table. We just need to update that slot with all - ** the information we've collected. - ** - ** The VM register number pParse->u1.cr.regRowid holds the rowid of an - ** entry in the sqlite_schema table that was created for this vtab - ** by sqlite3StartTable(). - */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( pParse->isCreate ); - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE " " - "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " - "WHERE rowid=#%d", - db->aDb[iDb].zDbSName, - pTab->zName, - pTab->zName, - zStmt, - pParse->u1.cr.regRowid - ); - v = sqlite3GetVdbe(pParse); - sqlite3ChangeCookie(pParse, iDb); - - sqlite3VdbeAddOp0(v, OP_Expire); - zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt); - sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0); - sqlite3DbFree(db, zStmt); - - iReg = ++pParse->nMem; - sqlite3VdbeLoadString(v, iReg, pTab->zName); - sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); - }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( zName!=0 ); - sqlite3MarkAllShadowTablesOf(db, pTab); - pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); - if( pOld ){ - sqlite3OomFault(db); - assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ - return; - } - pParse->pNewTable = 0; - } -} - -/* -** The parser calls this routine when it sees the first token -** of an argument to the module name in a CREATE VIRTUAL TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3VtabArgInit(Parse *pParse){ - addArgumentToVtab(pParse); - pParse->sArg.z = 0; - pParse->sArg.n = 0; -} - -/* -** The parser calls this routine for each token after the first token -** in an argument to the module name in a CREATE VIRTUAL TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){ - Token *pArg = &pParse->sArg; - if( pArg->z==0 ){ - pArg->z = p->z; - pArg->n = p->n; - }else{ - assert(pArg->z <= p->z); - pArg->n = (int)(&p->z[p->n] - pArg->z); - } -} - -/* -** Invoke a virtual table constructor (either xCreate or xConnect). The -** pointer to the function to invoke is passed as the fourth parameter -** to this procedure. -*/ -static int vtabCallConstructor( - sqlite3 *db, - Table *pTab, - Module *pMod, - int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), - char **pzErr -){ - VtabCtx sCtx; - VTable *pVTable; - int rc; - 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 ){ - *pzErr = sqlite3MPrintf(db, - "vtable constructor called recursively: %s", pTab->zName - ); - return SQLITE_LOCKED; - } - } - - zModuleName = sqlite3DbStrDup(db, pTab->zName); - if( !zModuleName ){ - return SQLITE_NOMEM_BKPT; - } - - pVTable = sqlite3MallocZero(sizeof(VTable)); - if( !pVTable ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zModuleName); - return SQLITE_NOMEM_BKPT; - } - pVTable->db = db; - pVTable->pMod = pMod; - pVTable->eVtabRisk = SQLITE_VTABRISK_Normal; - - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName; - - /* Invoke the virtual table constructor */ - assert( &db->pVtabCtx ); - assert( xConstruct ); - sCtx.pTab = pTab; - sCtx.pVTable = pVTable; - sCtx.pPrior = db->pVtabCtx; - sCtx.bDeclared = 0; - db->pVtabCtx = &sCtx; - pTab->nTabRef++; - rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - assert( pTab!=0 ); - assert( pTab->nTabRef>1 || rc!=SQLITE_OK ); - sqlite3DeleteTable(db, pTab); - db->pVtabCtx = sCtx.pPrior; - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - assert( sCtx.pTab==pTab ); - - if( SQLITE_OK!=rc ){ - if( zErr==0 ){ - *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); - }else { - *pzErr = sqlite3MPrintf(db, "%s", zErr); - sqlite3_free(zErr); - } - sqlite3DbFree(db, pVTable); - }else if( ALWAYS(pVTable->pVtab) ){ - /* Justification of ALWAYS(): A correct vtab constructor must allocate - ** the sqlite3_vtab object if successful. */ - memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); - pVTable->pVtab->pModule = pMod->pModule; - pMod->nRefModule++; - pVTable->nRef = 1; - if( sCtx.bDeclared==0 ){ - const char *zFormat = "vtable constructor did not declare schema: %s"; - *pzErr = sqlite3MPrintf(db, zFormat, zModuleName); - sqlite3VtabUnlock(pVTable); - rc = SQLITE_ERROR; - }else{ - int iCol; - u16 oooHidden = 0; - /* If everything went according to plan, link the new VTable structure - ** 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->u.vtab.p; - pTab->u.vtab.p = pVTable; - - for(iCol=0; iColnCol; iCol++){ - char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); - int nType; - int i = 0; - nType = sqlite3Strlen30(zType); - for(i=0; i0 ){ - assert(zType[i-1]==' '); - zType[i-1] = '\0'; - } - pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; - pTab->tabFlags |= TF_HasHidden; - oooHidden = TF_OOOHidden; - }else{ - pTab->tabFlags |= oooHidden; - } - } - } - } - - sqlite3DbFree(db, zModuleName); - return rc; -} - -/* -** This function is invoked by the parser to call the xConnect() method -** of the virtual table pTab. If an error occurs, an error code is returned -** and an error left in pParse. -** -** This call is a no-op if table pTab is not a virtual table. -*/ -SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ - sqlite3 *db = pParse->db; - const char *zMod; - Module *pMod; - int rc; - - assert( pTab ); - assert( IsVirtual(pTab) ); - if( sqlite3GetVTable(db, pTab) ){ - return SQLITE_OK; - } - - /* Locate the required virtual table module */ - zMod = pTab->u.vtab.azArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); - - if( !pMod ){ - const char *zModule = pTab->u.vtab.azArg[0]; - sqlite3ErrorMsg(pParse, "no such module: %s", zModule); - rc = SQLITE_ERROR; - }else{ - char *zErr = 0; - rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "%s", zErr); - pParse->rc = rc; - } - sqlite3DbFree(db, zErr); - } - - return rc; -} -/* -** Grow the db->aVTrans[] array so that there is room for at least one -** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise. -*/ -static int growVTrans(sqlite3 *db){ - const int ARRAY_INCR = 5; - - /* Grow the sqlite3.aVTrans array if required */ - if( (db->nVTrans%ARRAY_INCR)==0 ){ - VTable **aVTrans; - sqlite3_int64 nBytes = sizeof(sqlite3_vtab*)* - ((sqlite3_int64)db->nVTrans + ARRAY_INCR); - aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); - if( !aVTrans ){ - return SQLITE_NOMEM_BKPT; - } - memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); - db->aVTrans = aVTrans; - } - - return SQLITE_OK; -} - -/* -** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should -** have already been reserved using growVTrans(). -*/ -static void addToVTrans(sqlite3 *db, VTable *pVTab){ - /* Add pVtab to the end of sqlite3.aVTrans */ - db->aVTrans[db->nVTrans++] = pVTab; - sqlite3VtabLock(pVTab); -} - -/* -** This function is invoked by the vdbe to call the xCreate method -** of the virtual table named zTab in database iDb. -** -** If an error occurs, *pzErr is set to point to an English language -** description of the error and an SQLITE_XXX error code is returned. -** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. -*/ -SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ - int rc = SQLITE_OK; - Table *pTab; - Module *pMod; - const char *zMod; - - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); - assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p ); - - /* Locate the required virtual table module */ - zMod = pTab->u.vtab.azArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); - - /* If the module has been registered and includes a Create method, - ** invoke it now. If the module has not been registered, return an - ** error. Otherwise, do nothing. - */ - if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ - *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); - rc = SQLITE_ERROR; - }else{ - rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); - } - - /* Justification of ALWAYS(): The xConstructor method is required to - ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ - if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){ - rc = growVTrans(db); - if( rc==SQLITE_OK ){ - addToVTrans(db, sqlite3GetVTable(db, pTab)); - } - } - - return rc; -} - -/* -** This function is used to set the schema of a virtual table. It is only -** valid to call this function from within the xCreate() or xConnect() of a -** virtual table module. -*/ -SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ - VtabCtx *pCtx; - int rc = SQLITE_OK; - Table *pTab; - Parse sParse; - int initBusy; - int i; - const unsigned char *z; - static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 }; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - - /* Verify that the first two keywords in the CREATE TABLE statement - ** really are "CREATE" and "TABLE". If this is not the case, then - ** sqlite3_declare_vtab() is being misused. - */ - z = (const unsigned char*)zCreateTable; - for(i=0; aKeyword[i]; i++){ - int tokenType = 0; - do{ - z += sqlite3GetToken(z, &tokenType); - }while( tokenType==TK_SPACE || tokenType==TK_COMMENT ); - if( tokenType!=aKeyword[i] ){ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error"); - return SQLITE_ERROR; - } - } - - sqlite3_mutex_enter(db->mutex); - pCtx = db->pVtabCtx; - if( !pCtx || pCtx->bDeclared ){ - sqlite3Error(db, SQLITE_MISUSE_BKPT); - sqlite3_mutex_leave(db->mutex); - return SQLITE_MISUSE_BKPT; - } - - pTab = pCtx->pTab; - assert( IsVirtual(pTab) ); - - sqlite3ParseObjectInit(&sParse, db); - sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; - 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==sqlite3RunParser(&sParse, zCreateTable) ){ - assert( sParse.pNewTable!=0 ); - assert( !db->mallocFailed ); - assert( IsOrdinaryTable(sParse.pNewTable) ); - assert( sParse.zErrMsg==0 ); - if( !pTab->aCol ){ - Table *pNew = sParse.pNewTable; - Index *pIdx; - pTab->aCol = pNew->aCol; - assert( IsOrdinaryTable(pNew) ); - 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; - assert( pTab->pIndex==0 ); - assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); - if( !HasRowid(pNew) - && pCtx->pVTable->pMod->pModule->xUpdate!=0 - && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1 - ){ - /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0) - ** or else must have a single-column PRIMARY KEY */ - rc = SQLITE_ERROR; - } - pIdx = pNew->pIndex; - if( pIdx ){ - assert( pIdx->pNext==0 ); - pTab->pIndex = pIdx; - pNew->pIndex = 0; - pIdx->pTable = pTab; - } - } - pCtx->bDeclared = 1; - }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, - (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg); - sqlite3DbFree(db, sParse.zErrMsg); - rc = SQLITE_ERROR; - } - sParse.eParseMode = PARSE_MODE_NORMAL; - - if( sParse.pVdbe ){ - sqlite3VdbeFinalize(sParse.pVdbe); - } - sqlite3DeleteTable(db, sParse.pNewTable); - sqlite3ParseObjectReset(&sParse); - db->init.busy = initBusy; - - assert( (rc&0xff)==rc ); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** This function is invoked by the vdbe to call the xDestroy method -** of the virtual table named zTab in database iDb. This occurs -** when a DROP TABLE is mentioned. -** -** This call is a no-op if zTab is not a virtual table. -*/ -SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ - int rc = SQLITE_OK; - Table *pTab; - - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); - if( ALWAYS(pTab!=0) - && ALWAYS(IsVirtual(pTab)) - && ALWAYS(pTab->u.vtab.p!=0) - ){ - VTable *p; - int (*xDestroy)(sqlite3_vtab *); - for(p=pTab->u.vtab.p; p; p=p->pNext){ - assert( p->pVtab ); - if( p->pVtab->nRef>0 ){ - return SQLITE_LOCKED; - } - } - p = vtabDisconnectAll(db, pTab); - xDestroy = p->pMod->pModule->xDestroy; - if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect; - assert( xDestroy!=0 ); - pTab->nTabRef++; - rc = xDestroy(p->pVtab); - /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ - if( rc==SQLITE_OK ){ - assert( pTab->u.vtab.p==p && p->pNext==0 ); - p->pVtab = 0; - pTab->u.vtab.p = 0; - sqlite3VtabUnlock(p); - } - sqlite3DeleteTable(db, pTab); - } - - return rc; -} - -/* -** This function invokes either the xRollback or xCommit method -** of each of the virtual tables in the sqlite3.aVTrans array. The method -** called is identified by the second argument, "offset", which is -** the offset of the method to call in the sqlite3_module structure. -** -** The array is cleared after invoking the callbacks. -*/ -static void callFinaliser(sqlite3 *db, int offset){ - int i; - if( db->aVTrans ){ - VTable **aVTrans = db->aVTrans; - db->aVTrans = 0; - for(i=0; inVTrans; i++){ - VTable *pVTab = aVTrans[i]; - sqlite3_vtab *p = pVTab->pVtab; - if( p ){ - int (*x)(sqlite3_vtab *); - x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset); - if( x ) x(p); - } - pVTab->iSavepoint = 0; - sqlite3VtabUnlock(pVTab); - } - sqlite3DbFree(db, aVTrans); - db->nVTrans = 0; - } -} - -/* -** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans -** array. Return the error code for the first error that occurs, or -** SQLITE_OK if all xSync operations are successful. -** -** If an error message is available, leave it in p->zErrMsg. -*/ -SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){ - int i; - int rc = SQLITE_OK; - VTable **aVTrans = db->aVTrans; - - db->aVTrans = 0; - for(i=0; rc==SQLITE_OK && inVTrans; i++){ - int (*x)(sqlite3_vtab *); - sqlite3_vtab *pVtab = aVTrans[i]->pVtab; - if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ - rc = x(pVtab); - sqlite3VtabImportErrmsg(p, pVtab); - } - } - db->aVTrans = aVTrans; - return rc; -} - -/* -** Invoke the xRollback method of all virtual tables in the -** sqlite3.aVTrans array. Then clear the array itself. -*/ -SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){ - callFinaliser(db, offsetof(sqlite3_module,xRollback)); - return SQLITE_OK; -} - -/* -** Invoke the xCommit method of all virtual tables in the -** sqlite3.aVTrans array. Then clear the array itself. -*/ -SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){ - callFinaliser(db, offsetof(sqlite3_module,xCommit)); - return SQLITE_OK; -} - -/* -** If the virtual table pVtab supports the transaction interface -** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is -** not currently open, invoke the xBegin method now. -** -** If the xBegin call is successful, place the sqlite3_vtab pointer -** in the sqlite3.aVTrans array. -*/ -SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ - int rc = SQLITE_OK; - const sqlite3_module *pModule; - - /* Special case: If db->aVTrans is NULL and db->nVTrans is greater - ** than zero, then this function is being called from within a - ** virtual module xSync() callback. It is illegal to write to - ** virtual module tables in this case, so return SQLITE_LOCKED. - */ - if( sqlite3VtabInSync(db) ){ - return SQLITE_LOCKED; - } - if( !pVTab ){ - return SQLITE_OK; - } - pModule = pVTab->pVtab->pModule; - - if( pModule->xBegin ){ - int i; - - /* If pVtab is already in the aVTrans array, return early */ - for(i=0; inVTrans; i++){ - if( db->aVTrans[i]==pVTab ){ - return SQLITE_OK; - } - } - - /* Invoke the xBegin method. If successful, add the vtab to the - ** sqlite3.aVTrans[] array. */ - rc = growVTrans(db); - if( rc==SQLITE_OK ){ - rc = pModule->xBegin(pVTab->pVtab); - if( rc==SQLITE_OK ){ - int iSvpt = db->nStatement + db->nSavepoint; - addToVTrans(db, pVTab); - if( iSvpt && pModule->xSavepoint ){ - pVTab->iSavepoint = iSvpt; - rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1); - } - } - } - } - return rc; -} - -/* -** Invoke either the xSavepoint, xRollbackTo or xRelease method of all -** virtual tables that currently have an open transaction. Pass iSavepoint -** as the second argument to the virtual table method invoked. -** -** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is -** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is -** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with -** an open transaction is invoked. -** -** If any virtual table method returns an error code other than SQLITE_OK, -** processing is abandoned and the error returned to the caller of this -** function immediately. If all calls to virtual table methods are successful, -** SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ - int rc = SQLITE_OK; - - assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); - assert( iSavepoint>=-1 ); - if( db->aVTrans ){ - int i; - for(i=0; rc==SQLITE_OK && inVTrans; i++){ - VTable *pVTab = db->aVTrans[i]; - const sqlite3_module *pMod = pVTab->pMod->pModule; - if( pVTab->pVtab && pMod->iVersion>=2 ){ - int (*xMethod)(sqlite3_vtab *, int); - sqlite3VtabLock(pVTab); - switch( op ){ - case SAVEPOINT_BEGIN: - xMethod = pMod->xSavepoint; - pVTab->iSavepoint = iSavepoint+1; - break; - case SAVEPOINT_ROLLBACK: - xMethod = pMod->xRollbackTo; - break; - default: - xMethod = pMod->xRelease; - break; - } - if( xMethod && pVTab->iSavepoint>iSavepoint ){ - u64 savedFlags = (db->flags & SQLITE_Defensive); - db->flags &= ~(u64)SQLITE_Defensive; - rc = xMethod(pVTab->pVtab, iSavepoint); - db->flags |= savedFlags; - } - sqlite3VtabUnlock(pVTab); - } - } - } - return rc; -} - -/* -** The first parameter (pDef) is a function implementation. The -** second parameter (pExpr) is the first argument to this function. -** If pExpr is a column in a virtual table, then let the virtual -** table implementation have an opportunity to overload the function. -** -** This routine is used to allow virtual table implementations to -** overload MATCH, LIKE, GLOB, and REGEXP operators. -** -** Return either the pDef argument (indicating no change) or a -** new FuncDef structure that is marked as ephemeral using the -** SQLITE_FUNC_EPHEM flag. -*/ -SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( - sqlite3 *db, /* Database connection for reporting malloc problems */ - FuncDef *pDef, /* Function to possibly overload */ - int nArg, /* Number of arguments to the function */ - Expr *pExpr /* First argument to the function */ -){ - Table *pTab; - sqlite3_vtab *pVtab; - sqlite3_module *pMod; - void (*xSFunc)(sqlite3_context*,int,sqlite3_value**) = 0; - void *pArg = 0; - FuncDef *pNew; - int rc = 0; - - /* 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( NEVER(pTab==0) ) return pDef; - if( !IsVirtual(pTab) ) return pDef; - pVtab = sqlite3GetVTable(db, pTab)->pVtab; - assert( pVtab!=0 ); - assert( pVtab->pModule!=0 ); - pMod = (sqlite3_module *)pVtab->pModule; - if( pMod->xFindFunction==0 ) return pDef; - - /* Call the xFindFunction method on the virtual table implementation - ** to see if the implementation wants to overload this function. - ** - ** Though undocumented, we have historically always invoked xFindFunction - ** with an all lower-case function name. Continue in this tradition to - ** avoid any chance of an incompatibility. - */ -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; pDef->zName[i]; i++){ - unsigned char x = (unsigned char)pDef->zName[i]; - assert( x==sqlite3UpperToLower[x] ); - } - } -#endif - rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg); - if( rc==0 ){ - return pDef; - } - - /* Create a new ephemeral function definition for the overloaded - ** function */ - pNew = sqlite3DbMallocZero(db, sizeof(*pNew) - + sqlite3Strlen30(pDef->zName) + 1); - if( pNew==0 ){ - return pDef; - } - *pNew = *pDef; - pNew->zName = (const char*)&pNew[1]; - memcpy((char*)&pNew[1], pDef->zName, sqlite3Strlen30(pDef->zName)+1); - pNew->xSFunc = xSFunc; - pNew->pUserData = pArg; - pNew->funcFlags |= SQLITE_FUNC_EPHEM; - return pNew; -} - -/* -** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] -** array so that an OP_VBegin will get generated for it. Add pTab to the -** array if it is missing. If pTab is already in the array, this routine -** is a no-op. -*/ -SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - int i, n; - Table **apVtabLock; - - assert( IsVirtual(pTab) ); - for(i=0; inVtabLock; i++){ - if( pTab==pToplevel->apVtabLock[i] ) return; - } - n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n); - if( apVtabLock ){ - pToplevel->apVtabLock = apVtabLock; - pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; - }else{ - sqlite3OomFault(pToplevel->db); - } -} - -/* -** 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 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 -** statement in order to come into existence. Eponymous virtual table -** instances always exist. They cannot be DROP-ed. -** -** Any virtual table module for which xConnect and xCreate are the same -** method can have an eponymous virtual table instance. -*/ -SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ - const sqlite3_module *pModule = pMod->pModule; - Table *pTab; - char *zErr = 0; - int rc; - sqlite3 *db = pParse->db; - if( pMod->pEpoTab ) return 1; - if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; - pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ) return 0; - pTab->zName = sqlite3DbStrDup(db, pMod->zName); - if( pTab->zName==0 ){ - sqlite3DbFree(db, pTab); - return 0; - } - pMod->pEpoTab = pTab; - pTab->nTabRef = 1; - pTab->eTabType = TABTYP_VTAB; - pTab->pSchema = db->aDb[0].pSchema; - assert( pTab->u.vtab.nArg==0 ); - pTab->iPKey = -1; - pTab->tabFlags |= TF_Eponymous; - addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); - addModuleArgument(pParse, pTab, 0); - addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); - rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); - if( rc ){ - sqlite3ErrorMsg(pParse, "%s", zErr); - sqlite3DbFree(db, zErr); - sqlite3VtabEponymousTableClear(db, pMod); - } - return 1; -} - -/* -** Erase the eponymous virtual table instance associated with -** virtual table module pMod, if it exists. -*/ -SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ - Table *pTab = pMod->pEpoTab; - if( pTab!=0 ){ - /* Mark the table as Ephemeral prior to deleting it, so that the - ** sqlite3DeleteTable() routine will know that it is not stored in - ** the schema. */ - pTab->tabFlags |= TF_Ephemeral; - sqlite3DeleteTable(db, pTab); - pMod->pEpoTab = 0; - } -} - -/* -** Return the ON CONFLICT resolution mode in effect for the virtual -** table update operation currently in progress. -** -** The results of this routine are undefined unless it is called from -** within an xUpdate method. -*/ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ - static const unsigned char aMap[] = { - SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE - }; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 ); - assert( OE_Ignore==4 && OE_Replace==5 ); - assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 ); - return (int)aMap[db->vtabOnConflict-1]; -} - -/* -** Call from within the xCreate() or xConnect() methods to provide -** the SQLite core with additional information about the behavior -** of the virtual table being implemented. -*/ -SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ - va_list ap; - int rc = SQLITE_OK; - VtabCtx *p; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - p = db->pVtabCtx; - if( !p ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - assert( p->pTab==0 || IsVirtual(p->pTab) ); - va_start(ap, op); - switch( op ){ - case SQLITE_VTAB_CONSTRAINT_SUPPORT: { - p->pVTable->bConstraint = (u8)va_arg(ap, int); - break; - } - case SQLITE_VTAB_INNOCUOUS: { - p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low; - break; - } - case SQLITE_VTAB_DIRECTONLY: { - p->pVTable->eVtabRisk = SQLITE_VTABRISK_High; - break; - } - case SQLITE_VTAB_USES_ALL_SCHEMAS: { - p->pVTable->bAllSchemas = 1; - break; - } - default: { - rc = SQLITE_MISUSE_BKPT; - break; - } - } - va_end(ap); - } - - if( rc!=SQLITE_OK ) sqlite3Error(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/************** End of vtab.c ************************************************/ -/************** Begin file wherecode.c ***************************************/ -/* -** 2015-06-06 -** -** 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 module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. -** -** This file was split off from where.c on 2015-06-06 in order to reduce the -** size of where.c and make it easier to edit. This file contains the routines -** that actually generate the bulk of the WHERE loop code. The original where.c -** file retains the code that does query planning and analysis. -*/ -/* #include "sqliteInt.h" */ -/************** Include whereInt.h in the middle of wherecode.c **************/ -/************** Begin file whereInt.h ****************************************/ -/* -** 2013-11-12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains structure and macro definitions for the query -** planner logic in "where.c". These definitions are broken out into -** a separate source file for easier editing. -*/ -#ifndef SQLITE_WHEREINT_H -#define SQLITE_WHEREINT_H - - -/* Forward references -*/ -typedef struct WhereClause WhereClause; -typedef struct WhereMaskSet WhereMaskSet; -typedef struct WhereOrInfo WhereOrInfo; -typedef struct WhereAndInfo WhereAndInfo; -typedef struct WhereLevel WhereLevel; -typedef struct WhereLoop WhereLoop; -typedef struct WherePath WherePath; -typedef struct WhereTerm WhereTerm; -typedef struct WhereLoopBuilder WhereLoopBuilder; -typedef struct WhereScan WhereScan; -typedef struct WhereOrCost WhereOrCost; -typedef struct WhereOrSet WhereOrSet; -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 object 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 -** loop in WHERE clause. -** -** Contrast this object with WhereLoop. This object describes the -** implementation of the loop. WhereLoop describes the algorithm. -** This object contains a pointer to the WhereLoop algorithm as one of -** its elements. -** -** The WhereInfo object contains a single instance of this object for -** each term in the FROM clause (which is to say, for each of the -** nested loops as implemented). The order of WhereLevel objects determines -** the loop nested order, with WhereInfo.a[0] being the outer loop and -** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop. -*/ -struct WhereLevel { - int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ - int iTabCur; /* The VDBE cursor used to access the table */ - int iIdxCur; /* The VDBE cursor used to access pIdx */ - int addrBrk; /* Jump here to break out of the loop */ - int addrNxt; /* Jump here to start the next IN combination */ - int addrSkip; /* Jump here for next iteration of skip-scan */ - int addrCont; /* Jump here to continue with the next loop cycle */ - int addrFirst; /* First instruction of interior of the loop */ - int addrBody; /* Beginning of the body of this loop */ - int regBignull; /* big-null flag reg. True if a NULL-scan is needed */ - int addrBignull; /* Jump here for next part of big-null scan */ -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - 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 */ - union { /* Information that depends on pWLoop->wsFlags */ - struct { - int nIn; /* Number of entries in aInLoop[] */ - struct InLoop { - int iCur; /* The VDBE cursor used by this IN operator */ - int addrInTop; /* Top of the IN loop */ - int iBase; /* Base register of multi-key index record */ - int nPrefix; /* Number of prior entries in the key */ - 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 *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 */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrVisit; /* Address at which row is visited */ -#endif -}; - -/* -** Each instance of this object represents an algorithm for evaluating one -** term of a join. Every term of the FROM clause will have at least -** one corresponding WhereLoop object (unless INDEXED BY constraints -** prevent a query solution - which is an error) and many terms of the -** FROM clause will have multiple WhereLoop objects, each describing a -** potential way of implementing that FROM-clause term, together with -** dependencies and cost estimates for using the chosen algorithm. -** -** Query planning consists of building up a collection of these WhereLoop -** objects, then computing a particular sequence of WhereLoop objects, with -** one WhereLoop object per FROM clause term, that satisfy all dependencies -** and that minimize the overall cost. -*/ -struct WhereLoop { - Bitmask prereq; /* Bitmask of other loops that must run first */ - Bitmask maskSelf; /* Bitmask identifying table iTab */ -#ifdef SQLITE_DEBUG - char cId; /* Symbolic ID of this loop for debugging use */ -#endif - u8 iTab; /* Position in FROM clause of table for this loop */ - u8 iSortIdx; /* Sorting index number. 0==None */ - LogEst rSetup; /* One-time setup cost (ex: create transient index) */ - LogEst rRun; /* Cost of running each loop */ - LogEst nOut; /* Estimated number of output rows */ - union { - struct { /* Information for internal btree tables */ - u16 nEq; /* Number of equality constraints */ - u16 nBtm; /* Size of BTM vector */ - u16 nTop; /* Size of TOP vector */ - u16 nDistinctCol; /* Index columns used to sort for DISTINCT */ - Index *pIndex; /* Index used, or NULL */ - ExprList *pOrderBy; /* ORDER BY clause if this is really a subquery */ - } btree; - struct { /* Information for virtual tables */ - int idxNum; /* Index number */ - u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */ - u32 bOmitOffset : 1; /* True to let virtual table handle offset */ - u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */ - 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 */ - u16 nLTerm; /* Number of entries in aLTerm[] */ - u16 nSkip; /* Number of NULL aLTerm[] entries */ - /**** whereLoopXfer() copies fields above ***********************/ -# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) - u16 nLSlot; /* Number of slots allocated for aLTerm[] */ -#ifdef WHERETRACE_ENABLED - LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not - ** initialized unless pWInfo->bStarUsed */ -#endif - WhereTerm **aLTerm; /* WhereTerms used */ - WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ - WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */ -}; - -/* This object holds the prerequisites and the cost of running a -** subquery on one operand of an OR operator in the WHERE clause. -** See WhereOrSet for additional information -*/ -struct WhereOrCost { - Bitmask prereq; /* Prerequisites */ - LogEst rRun; /* Cost of running this subquery */ - LogEst nOut; /* Number of outputs for this subquery */ -}; - -/* The WhereOrSet object holds a set of possible WhereOrCosts that -** correspond to the subquery(s) of OR-clause processing. Only the -** best N_OR_COST elements are retained. -*/ -#define N_OR_COST 3 -struct WhereOrSet { - u16 n; /* Number of valid a[] entries */ - WhereOrCost a[N_OR_COST]; /* Set of best costs */ -}; - -/* -** Each instance of this object holds a sequence of WhereLoop objects -** that implement some or all of a query plan. -** -** Think of each WhereLoop object as a node in a graph with arcs -** showing dependencies and costs for travelling between nodes. (That is -** not a completely accurate description because WhereLoop costs are a -** vector, not a scalar, and because dependencies are many-to-one, not -** one-to-one as are graph nodes. But it is a useful visualization aid.) -** Then a WherePath object is a path through the graph that visits some -** or all of the WhereLoop objects once. -** -** The "solver" works by creating the N best WherePath objects of length -** 1. Then using those as a basis to compute the N best WherePath objects -** of length 2. And so forth until the length of WherePaths equals the -** number of nodes in the FROM clause. The best (lowest cost) WherePath -** at the end is the chosen query plan. -*/ -struct WherePath { - Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ - Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ - LogEst nRow; /* Estimated number of rows generated by this path */ - LogEst rCost; /* Total cost of this path */ - LogEst rUnsort; /* Total cost of this path ignoring sorting costs */ - i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */ - WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ -}; - -/* -** The query generator uses an array of instances of this structure to -** help it analyze the subexpressions of the WHERE clause. Each WHERE -** clause subexpression is separated from the others by AND operators, -** usually, or sometimes subexpressions separated by OR. -** -** All WhereTerms are collected into a single WhereClause structure. -** The following identity holds: -** -** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm -** -** When a term is of the form: -** -** X -** -** where X is a column name and is one of certain operators, -** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the -** cursor number and column number for X. WhereTerm.eOperator records -** the using a bitmask encoding defined by WO_xxx below. The -** use of a bitmask encoding for the operator allows us to search -** quickly for terms that match any of several different operators. -** -** A WhereTerm might also be two or more subterms connected by OR: -** -** (t1.X ) OR (t1.Y ) OR .... -** -** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR -** and the WhereTerm.u.pOrInfo field points to auxiliary information that -** is collected about the OR clause. -** -** If a term in the WHERE clause does not match either of the two previous -** categories, then eOperator==0. The WhereTerm.pExpr field is still set -** to the original subexpression content and wtFlags is set up appropriately -** but no other fields in the WhereTerm object are meaningful. -** -** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers, -** but they do so indirectly. A single WhereMaskSet structure translates -** cursor number into bits and the translated bit is stored in the prereq -** fields. The translation is used in order to maximize the number of -** bits that will fit in a Bitmask. The VDBE cursor numbers might be -** spread out over the non-negative integers. For example, the cursor -** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet -** translates these sparse cursor numbers into consecutive integers -** beginning with 0 in order to make the best possible use of the available -** bits in the Bitmask. So, in the example above, the cursor numbers -** would be mapped into integers 0 through 7. -** -** The number of terms in a join is limited by the number of bits -** in prereqRight and prereqAll. The default is 64 bits, hence SQLite -** is only able to process joins with 64 or fewer tables. -*/ -struct WhereTerm { - Expr *pExpr; /* Pointer to the subexpression that is this term */ - WhereClause *pWC; /* The clause this term is part of */ - LogEst truthProb; /* Probability of truth for this expression */ - u16 wtFlags; /* TERM_xxx bit flags. See below */ - u16 eOperator; /* A WO_xx value describing */ - u8 nChild; /* Number of children that must disable us */ - u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ - int iParent; /* Disable pWC->a[iParent] when this term disabled */ - int leftCursor; /* Cursor number of X in "X " */ - union { - struct { - int leftColumn; /* Column number of X in "X " */ - int iField; /* Field in (?,?,?) IN (SELECT...) vector */ - } x; /* Opcode other than OP_OR or OP_AND */ - WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ - WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ - } u; - Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ - Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ -}; - -/* -** Allowed values of WhereTerm.wtFlags -*/ -#define TERM_DYNAMIC 0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */ -#define TERM_VIRTUAL 0x0002 /* Added by the optimizer. Do not code */ -#define TERM_CODED 0x0004 /* This term is already coded */ -#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_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 */ -#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */ -#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ -#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */ -#ifdef SQLITE_ENABLE_STAT4 -# define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */ -#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 -** terms in the WHERE clause that are useful to the query planner. -*/ -struct WhereScan { - WhereClause *pOrigWC; /* Original, innermost WhereClause */ - WhereClause *pWC; /* WhereClause currently being scanned */ - const char *zCollName; /* Required collating sequence, if not NULL */ - Expr *pIdxExpr; /* Search for this index expression */ - 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 */ -}; - -/* -** An instance of the following structure holds all information about a -** WHERE clause. Mostly this is a container for one or more WhereTerms. -** -** Explanation of pOuter: For a WHERE clause of the form -** -** a AND ((b AND c) OR (d AND e)) AND f -** -** There are separate WhereClause objects for the whole clause and for -** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the -** subclauses points to the WhereClause object for the whole clause. -*/ -struct WhereClause { - WhereInfo *pWInfo; /* WHERE clause processing context */ - WhereClause *pOuter; /* Outer conjunction */ - u8 op; /* Split operator. TK_AND or TK_OR */ - 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 clause */ -#if defined(SQLITE_SMALL_STACK) - WhereTerm aStatic[1]; /* Initial static space for a[] */ -#else - WhereTerm aStatic[8]; /* Initial static space for a[] */ -#endif -}; - -/* -** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to -** a dynamically allocated instance of the following structure. -*/ -struct WhereOrInfo { - WhereClause wc; /* Decomposition into subterms */ - Bitmask indexable; /* Bitmask of all indexable tables in the clause */ -}; - -/* -** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to -** a dynamically allocated instance of the following structure. -*/ -struct WhereAndInfo { - WhereClause wc; /* The subexpression broken out */ -}; - -/* -** An instance of the following structure keeps track of a mapping -** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. -** -** The VDBE cursor numbers are small integers contained in -** SrcItem.iCursor and Expr.iTable fields. For any given WHERE -** clause, the cursor numbers might not begin with 0 and they might -** contain gaps in the numbering sequence. But we want to make maximum -** use of the bits in our bitmasks. This structure provides a mapping -** from the sparse cursor numbers into consecutive integers beginning -** with 0. -** -** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask -** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<3, 5->1, 8->2, 29->0, -** 57->5, 73->4. Or one of 719 other combinations might be used. It -** does not really matter. What is important is that sparse cursor -** numbers all get mapped into bit numbers that begin with 0 and contain -** no gaps. -*/ -struct WhereMaskSet { - int bVarSelect; /* Used by sqlite3WhereExprUsage() */ - int n; /* Number of assigned cursor values */ - int ix[BMS]; /* Cursor assigned to each bit */ -}; - -/* -** 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 */ - WhereLoop *pNew; /* Template WhereLoop */ - WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ -#ifdef SQLITE_ENABLE_STAT4 - UnpackedRecord *pRec; /* Probe for stat4 (if required) */ - int nRecValid; /* Number of valid fields currently in pRec */ -#endif - unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */ - unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */ - unsigned int iPlanLimit; /* Search limiter */ -}; - -/* Allowed values for WhereLoopBuider.bldFlags */ -#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */ -#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ - -#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */ - -/* The WhereLoopBuilder.iPlanLimit is used to limit the number of -** index+constraint combinations the query planner will consider for a -** particular query. If this parameter is unlimited, then certain -** pathological queries can spend excess time in the sqlite3WhereBegin() -** routine. The limit is high enough that is should not impact real-world -** queries. -** -** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is -** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM -** clause is processed, so that every table in a join is guaranteed to be -** able to propose a some index+constraint combinations even if the initial -** baseline limit was exhausted by prior tables of the join. -*/ -#ifndef SQLITE_QUERY_PLANNER_LIMIT -# define SQLITE_QUERY_PLANNER_LIMIT 20000 -#endif -#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR -# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 -#endif - -/* -** The WHERE clause processing routine has two halves. The -** first part does the start of the WHERE loop and the second -** half does the tail of the WHERE loop. An instance of -** this structure is returned by the first half and passed -** into the second half to give some continuity. -** -** An instance of this object holds the complete state of the query -** planner. -*/ -struct WhereInfo { - Parse *pParse; /* Parsing and code generating context */ - SrcList *pTabList; /* List of tables in the join */ - ExprList *pOrderBy; /* The ORDER BY clause or NULL */ - ExprList *pResultSet; /* Result set of the query */ -#if WHERETRACE_ENABLED - Expr *pWhere; /* The complete WHERE clause */ -#endif - Select *pSelect; /* The entire SELECT statement containing WHERE */ - 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 */ - int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ - u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ - LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ - u8 nLevel; /* Number of nested loop */ - i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ - u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ - u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ - unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */ - unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */ - unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */ - unsigned sorted :1; /* True if really sorted (not just grouped) */ - unsigned bStarDone :1; /* True if check for star-query is complete */ - unsigned bStarUsed :1; /* True if star-query heuristic is used */ - LogEst nRowOut; /* Estimated number of output rows */ -#ifdef WHERETRACE_ENABLED - LogEst rTotalCost; /* Total cost of the solution */ -#endif - int iTop; /* The very beginning of the WHERE loop */ - int iEndWhere; /* End of the WHERE clause itself */ - WhereLoop *pLoops; /* List of all WhereLoop objects */ - 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 */ - WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */ -}; - -/* -** The size (in bytes) of a WhereInfo object that holds N WhereLevels. -*/ -#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel)) - -/* -** Private interfaces - callable only by other where.c routines. -** -** where.c: -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); -#ifdef WHERETRACE_ENABLED -SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC); -SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); -SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC); -#endif -SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -); -SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte); -SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte); - -/* wherecode.c: */ -#ifndef SQLITE_OMIT_EXPLAIN -SQLITE_PRIVATE int sqlite3WhereExplainOneScan( - Parse *pParse, /* Parse context */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -); -SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( - const Parse *pParse, /* Parse context */ - const WhereInfo *pWInfo, /* WHERE clause */ - const WhereLevel *pLevel /* Bloom filter on this level */ -); -SQLITE_PRIVATE void sqlite3WhereAddExplainText( - Parse *pParse, /* Parse context */ - int addr, - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -); -#else -# define sqlite3WhereExplainOneScan(u,v,w,x) 0 -# define sqlite3WhereExplainBloomFilter(u,v,w) 0 -# define sqlite3WhereAddExplainText(u,v,w,x,y) -#endif /* SQLITE_OMIT_EXPLAIN */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -SQLITE_PRIVATE void sqlite3WhereAddScanStatus( - Vdbe *v, /* Vdbe to add scanstatus entry to */ - SrcList *pSrclist, /* FROM clause pLvl reads data from */ - WhereLevel *pLvl, /* Level to add scanstatus() entry for */ - int addrExplain /* Address of OP_Explain (or 0) */ -); -#else -# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d) -#endif -SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( - Parse *pParse, /* Parsing context */ - Vdbe *v, /* Prepared statement under construction */ - WhereInfo *pWInfo, /* Complete information about the WHERE clause */ - int iLevel, /* Which level of pWInfo->a[] should be coded */ - WhereLevel *pLevel, /* The current level pointer */ - Bitmask notReady /* Which tables are currently available */ -); -SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( - WhereInfo *pWInfo, - int iLevel, - WhereLevel *pLevel -); - -/* whereexpr.c: */ -SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); -SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); -SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); -SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); -SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); -SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); -SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); - - - - - -/* -** Bitmasks for the operators on WhereTerm objects. These are all -** operators that are of interest to the query planner. An -** OR-ed combination of these values can be used when searching for -** particular WhereTerms within a WhereClause. -** -** Value constraints: -** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ -** WO_LT == SQLITE_INDEX_CONSTRAINT_LT -** WO_LE == SQLITE_INDEX_CONSTRAINT_LE -** WO_GT == SQLITE_INDEX_CONSTRAINT_GT -** WO_GE == SQLITE_INDEX_CONSTRAINT_GE -*/ -#define WO_IN 0x0001 -#define WO_EQ 0x0002 -#define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) -#define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) -#define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) -#define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) -#define WO_AUX 0x0040 /* Op useful to virtual tables only */ -#define WO_IS 0x0080 -#define WO_ISNULL 0x0100 -#define WO_OR 0x0200 /* Two or more OR-connected terms */ -#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 0x3fff /* Mask of all possible WO_* values */ -#define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */ - -/* -** These are definitions of bits in the WhereLoop.wsFlags field. -** The particular combination of bits in each WhereLoop help to -** determine the algorithm that WhereLoop represents. -*/ -#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */ -#define WHERE_COLUMN_RANGE 0x00000002 /* xEXPR */ -#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */ -#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */ -#define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */ -#define WHERE_TOP_LIMIT 0x00000010 /* xEXPR or x>=EXPR constraint */ -#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and xaiColumn[i]; - if( i==XN_EXPR ) return ""; - if( i==XN_ROWID ) return "rowid"; - return pIdx->pTable->aCol[i].zCnName; -} - -/* -** This routine is a helper for explainIndexRange() below -** -** pStr holds the text of an expression that we are building up one term -** at a time. This routine adds a new term to the end of the expression. -** Terms are separated by AND so add the "AND" text for second and subsequent -** terms only. -*/ -static void explainAppendTerm( - StrAccum *pStr, /* The text expression being built */ - Index *pIdx, /* Index to read column names from */ - int nTerm, /* Number of terms */ - int iTerm, /* Zero-based index of first term. */ - int bAnd, /* Non-zero to append " AND " */ - const char *zOp /* Name of the operator */ -){ - int i; - - assert( nTerm>=1 ); - if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); - - if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); - for(i=0; i1 ) sqlite3_str_append(pStr, ")", 1); - - sqlite3_str_append(pStr, zOp, 1); - - if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); - for(i=0; i1 ) sqlite3_str_append(pStr, ")", 1); -} - -/* -** Argument pLevel describes a strategy for scanning table pTab. This -** function appends text to pStr that describes the subset of table -** rows scanned by the strategy in the form of an SQL expression. -** -** For example, if the query: -** -** SELECT * FROM t1 WHERE a=1 AND b>2; -** -** is run and there is an index on (a, b), then this function returns a -** string similar to: -** -** "a=? AND b>?" -*/ -static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ - Index *pIndex = pLoop->u.btree.pIndex; - u16 nEq = pLoop->u.btree.nEq; - u16 nSkip = pLoop->nSkip; - int i, j; - - if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; - sqlite3_str_append(pStr, " (", 2); - for(i=0; i=nSkip ? "%s=?" : "ANY(%s)", z); - } - - j = i; - if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ - explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">"); - i = 1; - } - if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ - explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); - } - sqlite3_str_append(pStr, ")", 1); -} - -/* -** This function sets the P4 value of an existing OP_Explain opcode to -** text describing the loop in pLevel. If the OP_Explain opcode already has -** a P4 value, it is freed before it is overwritten. -*/ -SQLITE_PRIVATE void sqlite3WhereAddExplainText( - Parse *pParse, /* Parse context */ - int addr, /* Address of OP_Explain opcode */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -){ -#if !defined(SQLITE_DEBUG) - if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) -#endif - { - VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr); - - SrcItem *pItem = &pTabList->a[pLevel->iFrom]; - sqlite3 *db = pParse->db; /* Database handle */ - int isSearch; /* True for a SEARCH. False for SCAN. */ - WhereLoop *pLoop; /* The controlling WhereLoop object */ - u32 flags; /* Flags that describe this loop */ -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) - char *zMsg; /* Text to add to EQP output */ -#endif - StrAccum str; /* EQP output string */ - char zBuf[100]; /* Initial space for EQP output string */ - - if( db->mallocFailed ) return; - - pLoop = pLevel->pWLoop; - flags = pLoop->wsFlags; - - isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) - || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem); - if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ - const char *zFmt = 0; - Index *pIdx; - - assert( pLoop->u.btree.pIndex!=0 ); - pIdx = pLoop->u.btree.pIndex; - assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); - if( !HasRowid(pItem->pSTab) && IsPrimaryKeyIndex(pIdx) ){ - if( isSearch ){ - zFmt = "PRIMARY KEY"; - } - }else if( flags & WHERE_PARTIALIDX ){ - zFmt = "AUTOMATIC PARTIAL COVERING INDEX"; - }else if( flags & WHERE_AUTO_INDEX ){ - zFmt = "AUTOMATIC COVERING INDEX"; - }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){ - zFmt = "COVERING INDEX %s"; - }else{ - zFmt = "INDEX %s"; - } - if( zFmt ){ - sqlite3_str_append(&str, " USING ", 7); - sqlite3_str_appendf(&str, zFmt, pIdx->zName); - explainIndexRange(&str, pLoop); - } - }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ - 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 - sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid); - if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ - cRangeOp = '='; - }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - sqlite3_str_appendf(&str, ">? AND %s", zRowid); - cRangeOp = '<'; - }else if( flags&WHERE_BTM_LIMIT ){ - cRangeOp = '>'; - }else{ - assert( flags&WHERE_TOP_LIMIT); - cRangeOp = '<'; - } - sqlite3_str_appendf(&str, "%c?)", cRangeOp); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX "); - sqlite3_str_appendf(&str, - pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s", - pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); - } -#endif - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&str, " LEFT-JOIN"); - } -#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS - if( pLoop->nOut>=10 ){ - sqlite3_str_appendf(&str, " (~%llu rows)", - sqlite3LogEstToInt(pLoop->nOut)); - }else{ - sqlite3_str_append(&str, " (~1 row)", 9); - } -#endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) - zMsg = sqlite3StrAccumFinish(&str); - sqlite3ExplainBreakpoint("",zMsg); -#endif - - assert( pOp->opcode==OP_Explain ); - assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 ); - sqlite3DbFree(db, pOp->p4.z); - pOp->p4type = P4_DYNAMIC; - pOp->p4.z = sqlite3StrAccumFinish(&str); - } -} - - -/* -** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN -** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG -** was defined at compile-time. If it is not a no-op, a single OP_Explain -** opcode is added to the output to describe the table scan strategy in pLevel. -** -** 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 sqlite3WhereExplainOneScan( - Parse *pParse, /* Parse context */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -){ - int ret = 0; -#if !defined(SQLITE_DEBUG) - if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) -#endif - { - if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - ){ - Vdbe *v = pParse->pVdbe; - int addr = sqlite3VdbeCurrentAddr(v); - ret = sqlite3VdbeAddOp3( - v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun - ); - sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags); - } - } - 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 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 */ - 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 */ - - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); - pLoop = pLevel->pWLoop; - if( pLoop->wsFlags & WHERE_IPK ){ - const Table *pTab = pItem->pSTab; - if( pTab->iPKey>=0 ){ - sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); - }else{ - sqlite3_str_appendf(&str, "rowid=?"); - } - }else{ - for(i=pLoop->nSkip; iu.btree.nEq; i++){ - const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); - if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); - sqlite3_str_appendf(&str, "%s=?", z); - } - } - sqlite3_str_append(&str, ")", 1); - zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), - pParse->addrExplain, 0, zMsg,P4_DYNAMIC); - - sqlite3VdbeScanStatus(v, sqlite3VdbeCurrentAddr(v)-1, 0, 0, 0, 0); - return ret; -} -#endif /* SQLITE_OMIT_EXPLAIN */ - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Configure the VM passed as the first argument with an -** sqlite3_stmt_scanstatus() entry corresponding to the scan used to -** implement level pLvl. Argument pSrclist is a pointer to the FROM -** clause that the scan reads data from. -** -** If argument addrExplain is not 0, it must be the address of an -** OP_Explain instruction that describes the same loop. -*/ -SQLITE_PRIVATE void sqlite3WhereAddScanStatus( - Vdbe *v, /* Vdbe to add scanstatus entry to */ - SrcList *pSrclist, /* FROM clause pLvl reads data from */ - WhereLevel *pLvl, /* Level to add scanstatus() entry for */ - int addrExplain /* Address of OP_Explain (or 0) */ -){ - if( IS_STMT_SCANSTATUS( sqlite3VdbeDb(v) ) ){ - const char *zObj = 0; - WhereLoop *pLoop = pLvl->pWLoop; - int wsFlags = pLoop->wsFlags; - int viaCoroutine = 0; - - if( (wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ - zObj = pLoop->u.btree.pIndex->zName; - }else{ - zObj = pSrclist->a[pLvl->iFrom].zName; - viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine; - } - sqlite3VdbeScanStatus( - v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj - ); - - if( viaCoroutine==0 ){ - if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){ - sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur); - } - if( wsFlags & WHERE_INDEXED ){ - sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur); - } - }else{ - int addr; - VdbeOp *pOp; - assert( pSrclist->a[pLvl->iFrom].fg.isSubquery ); - addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub; - pOp = sqlite3VdbeGetOp(v, addr-1); - assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine ); - assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr ); - sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1); - } - } -} -#endif - - -/* -** Disable a term in the WHERE clause. Except, do not disable the term -** if it controls a LEFT OUTER JOIN and it did not originate in the ON -** or USING clause of that join. -** -** Consider the term t2.z='ok' in the following queries: -** -** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' -** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' -** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' -** -** The t2.z='ok' is disabled in the in (2) because it originates -** in the ON clause. The term is disabled in (3) because it is not part -** of a LEFT OUTER JOIN. In (1), the term is not disabled. -** -** Disabling a term causes that term to not be tested in the inner loop -** of the join. Disabling is an optimization. When terms are satisfied -** by indices, we disable them to prevent redundant tests in the inner -** loop. We would get the correct results if nothing were ever disabled, -** but joins might run a little slower. The trick is to disable as much -** as we can without disabling too much. If we disabled in (1), we'd get -** the wrong answer. See ticket #813. -** -** If all the children of a term are disabled, then that term is also -** automatically disabled. In this way, terms get disabled if derived -** virtual terms are tested first. For example: -** -** x GLOB 'abc*' AND x>='abc' AND x<'acd' -** \___________/ \______/ \_____/ -** parent child1 child2 -** -** Only the parent term was in the original WHERE clause. The child1 -** and child2 terms were added by the LIKE optimization. If both of -** the virtual child terms are valid, then testing of the parent can be -** skipped. -** -** Usually the parent term is marked as TERM_CODED. But if the parent -** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. -** The TERM_LIKECOND marking indicates that the term should be coded inside -** a conditional such that is only evaluated on the second pass of a -** LIKE-optimization loop, when scanning BLOBs instead of strings. -*/ -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_OuterON)) - && (pLevel->notReady & pTerm->prereqAll)==0 - ){ - if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ - pTerm->wtFlags |= TERM_LIKECOND; - }else{ - pTerm->wtFlags |= TERM_CODED; - } -#ifdef WHERETRACE_ENABLED - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - sqlite3DebugPrintf("DISABLE-"); - sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a))); - } -#endif - if( pTerm->iParent<0 ) break; - pTerm = &pTerm->pWC->a[pTerm->iParent]; - assert( pTerm!=0 ); - pTerm->nChild--; - if( pTerm->nChild!=0 ) break; - nLoop++; - } -} - -/* -** Code an OP_Affinity opcode to apply the column affinity string zAff -** to the n registers starting at base. -** -** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which -** are no-ops) at the beginning and end of zAff are ignored. If all entries -** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated. -** -** This routine makes its own copy of zAff so that the caller is free -** to modify zAff after this routine returns. -*/ -static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ - Vdbe *v = pParse->pVdbe; - if( zAff==0 ){ - assert( pParse->db->mallocFailed ); - return; - } - assert( v!=0 ); - - /* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE - ** entries at the beginning and end of the affinity string. - */ - assert( SQLITE_AFF_NONE0 && zAff[0]<=SQLITE_AFF_BLOB ){ - n--; - base++; - zAff++; - } - while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){ - n--; - } - - /* Code the OP_Affinity opcode if there is anything left to do. */ - if( n>0 ){ - sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); - } -} - -/* -** Expression pRight, which is the RHS of a comparison operation, is -** either a vector of n elements or, if n==1, a scalar expression. -** Before the comparison operation, affinity zAff is to be applied -** to the pRight values. This function modifies characters within the -** affinity string to SQLITE_AFF_BLOB if either: -** -** * the comparison will be performed with no affinity, or -** * the affinity change in zAff is guaranteed not to change the value. -*/ -static void updateRangeAffinityStr( - Expr *pRight, /* RHS of comparison */ - int n, /* Number of vector elements in comparison */ - char *zAff /* Affinity string to modify */ -){ - int i; - for(i=0; ia[].u.x.iOrderByCol values might be incorrect because -** columns might have been rearranged in the result set. This routine -** fixes them up. -** -** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values -** contain the *old* locations of each expression. This is a temporary -** use of u.x.iOrderByCol, not its intended use. The caller must reset -** u.x.iOrderByCol back to zero for all entries in pEList before the -** caller returns. -** -** This routine changes pOrderBy->a[].u.x.iOrderByCol values from -** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based -** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero. -*/ -static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){ - int i, j; - if( pOrderBy==0 ) return; - for(i=0; inExpr; i++){ - int t = pOrderBy->a[i].u.x.iOrderByCol; - if( t==0 ) continue; - for(j=0; jnExpr; j++){ - if( pEList->a[j].u.x.iOrderByCol==t ){ - pOrderBy->a[i].u.x.iOrderByCol = j+1; - break; - } - } - if( j>=pEList->nExpr ){ - pOrderBy->a[i].u.x.iOrderByCol = 0; - } - } -} - - -/* -** pX is an expression of the form: (vector) IN (SELECT ...) -** In other words, it is a vector IN operator with a SELECT clause on the -** RHS. But not all terms in the vector are indexable and the terms might -** not be in the correct order for indexing. -** -** This routine makes a copy of the input pX expression and then adjusts -** the vector on the LHS with corresponding changes to the SELECT so that -** the vector contains only index terms and those terms are in the correct -** order. The modified IN expression is returned. The caller is responsible -** for deleting the returned expression. -** -** Example: -** -** CREATE TABLE t1(a,b,c,d,e,f); -** CREATE INDEX t1x1 ON t1(e,c); -** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2) -** \_______________________________________/ -** The pX expression -** -** Since only columns e and c can be used with the index, in that order, -** the modified IN expression that is returned will be: -** -** (e,c) IN (SELECT z,x FROM t2) -** -** The reduced pX is different from the original (obviously) and thus is -** only used for indexing, to improve performance. The original unaltered -** IN expression must also be run on each output row for correctness. -*/ -static Expr *removeUnindexableInClauseTerms( - Parse *pParse, /* The parsing context */ - int iEq, /* Look at loop terms starting here */ - WhereLoop *pLoop, /* The current loop */ - Expr *pX /* The IN expression to be reduced */ -){ - sqlite3 *db = pParse->db; - Select *pSelect; /* Pointer to the SELECT on the RHS */ - Expr *pNew; - pNew = sqlite3ExprDup(db, pX, 0); - if( db->mallocFailed==0 ){ - for(pSelect=pNew->x.pSelect; pSelect; pSelect=pSelect->pPrior){ - ExprList *pOrigRhs; /* Original unmodified RHS */ - ExprList *pOrigLhs = 0; /* Original unmodified LHS */ - ExprList *pRhs = 0; /* New RHS after modifications */ - ExprList *pLhs = 0; /* New LHS after mods */ - int i; /* Loop counter */ - - assert( ExprUseXSelect(pNew) ); - pOrigRhs = pSelect->pEList; - assert( pNew->pLeft!=0 ); - assert( ExprUseXList(pNew->pLeft) ); - if( pSelect==pNew->x.pSelect ){ - pOrigLhs = pNew->pLeft->x.pList; - } - for(i=iEq; inLTerm; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - int iField; - assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 ); - iField = pLoop->aLTerm[i]->u.x.iField - 1; - if( NEVER(pOrigRhs->a[iField].pExpr==0) ){ - continue; /* Duplicate PK column */ - } - pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); - pOrigRhs->a[iField].pExpr = 0; - if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1; - if( pOrigLhs ){ - assert( pOrigLhs->a[iField].pExpr!=0 ); - pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr); - pOrigLhs->a[iField].pExpr = 0; - } - } - } - sqlite3ExprListDelete(db, pOrigRhs); - if( pOrigLhs ){ - sqlite3ExprListDelete(db, pOrigLhs); - pNew->pLeft->x.pList = pLhs; - } - pSelect->pEList = pRhs; - pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */ - if( pLhs && pLhs->nExpr==1 ){ - /* Take care here not to generate a TK_VECTOR containing only a - ** single value. Since the parser never creates such a vector, some - ** of the subroutines do not handle this case. */ - Expr *p = pLhs->a[0].pExpr; - pLhs->a[0].pExpr = 0; - sqlite3ExprDelete(db, pNew->pLeft); - pNew->pLeft = p; - } - - /* If either the ORDER BY clause or the GROUP BY clause contains - ** references to result-set columns, those references might now be - ** obsolete. So fix them up. - */ - assert( pRhs!=0 || db->mallocFailed ); - if( pRhs ){ - adjustOrderByCol(pSelect->pOrderBy, pRhs); - adjustOrderByCol(pSelect->pGroupBy, pRhs); - for(i=0; inExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0; - } - -#if 0 - printf("For indexing, change the IN expr:\n"); - sqlite3TreeViewExpr(0, pX, 0); - printf("Into:\n"); - sqlite3TreeViewExpr(0, pNew, 0); -#endif - } - } - return pNew; -} - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code for a single X IN (....) term of the WHERE clause. -** -** This is a special-case of codeEqualityTerm() that works for IN operators -** only. It is broken out into a subroutine because this case is -** uncommon and by splitting it off into a subroutine, the common case -** runs faster. -** -** The current value for the constraint is left in register iTarget. -** This routine sets up a loop that will iterate over all values of X. -*/ -static SQLITE_NOINLINE void codeINTerm( - Parse *pParse, /* The parsing context */ - WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* The level of the FROM clause we are working on */ - int iEq, /* Index of the equality term within this level */ - int bRev, /* True for reverse-order IN operations */ - int iTarget /* Attempt to leave results in this register */ -){ - Expr *pX = pTerm->pExpr; - int eType = IN_INDEX_NOOP; - int iTab; - struct InLoop *pIn; - WhereLoop *pLoop = pLevel->pWLoop; - Vdbe *v = pParse->pVdbe; - int i; - int nEq = 0; - int *aiMap = 0; - - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 - && pLoop->u.btree.pIndex!=0 - && pLoop->u.btree.pIndex->aSortOrder[iEq] - ){ - testcase( iEq==0 ); - testcase( bRev ); - bRev = !bRev; - } - assert( pX->op==TK_IN ); - - for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){ - disableTerm(pLevel, pTerm); - return; - } - } - for(i=iEq; inLTerm; i++){ - assert( pLoop->aLTerm[i]!=0 ); - if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; - } - - iTab = 0; - if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){ - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab); - }else{ - sqlite3 *db = pParse->db; - Expr *pXMod = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); - if( !db->mallocFailed ){ - aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nEq); - eType = sqlite3FindInIndex(pParse, pXMod, IN_INDEX_LOOP, 0, aiMap, &iTab); - } - sqlite3ExprDelete(db, pXMod); - } - - if( eType==IN_INDEX_INDEX_DESC ){ - testcase( bRev ); - bRev = !bRev; - } - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); - VdbeCoverageIf(v, bRev); - VdbeCoverageIf(v, !bRev); - - assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - pLoop->wsFlags |= WHERE_IN_ABLE; - if( pLevel->u.in.nIn==0 ){ - pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); - } - if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){ - pLoop->wsFlags |= WHERE_IN_EARLYOUT; - } - - i = pLevel->u.in.nIn; - pLevel->u.in.nIn += nEq; - pLevel->u.in.aInLoop = - 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[] */ - pIn += i; - for(i=iEq; inLTerm; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - int iOut = iTarget + i - iEq; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); - }else{ - int iCol = aiMap ? aiMap[iMap++] : 0; - pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); - } - sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); - if( i==iEq ){ - pIn->iCur = iTab; - pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; - if( iEq>0 ){ - pIn->iBase = iTarget - i; - pIn->nPrefix = i; - }else{ - pIn->nPrefix = 0; - } - }else{ - pIn->eEndLoopOp = OP_Noop; - } - pIn++; - } - } - testcase( iEq>0 - && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 - && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ); - if( iEq>0 - && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0 - ){ - sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq); - } - }else{ - pLevel->u.in.nIn = 0; - } - sqlite3DbFree(pParse->db, aiMap); -} -#endif - - -/* -** Generate code for a single equality term of the WHERE clause. An equality -** term can be either X=expr or X IN (...). pTerm is the term to be -** coded. -** -** The current value for the constraint is left in a register, the index -** of which is returned. An attempt is made store the result in iTarget but -** this is only guaranteed for TK_ISNULL and TK_IN constraints. If the -** constraint is a TK_EQ or TK_IS, then the current value might be left in -** some other register and it is the caller's responsibility to compensate. -** -** For a constraint of the form X=expr, the expression is evaluated in -** straight-line code. For constraints of the form X IN (...) -** this routine sets up a loop that will iterate over all values of X. -*/ -static int codeEqualityTerm( - Parse *pParse, /* The parsing context */ - WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* The level of the FROM clause we are working on */ - int iEq, /* Index of the equality term within this level */ - int bRev, /* True for reverse-order IN operations */ - int iTarget /* Attempt to leave results in this register */ -){ - Expr *pX = pTerm->pExpr; - int iReg; /* Register holding results */ - - assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); - assert( iTarget>0 ); - if( pX->op==TK_EQ || pX->op==TK_IS ){ - iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); - }else if( pX->op==TK_ISNULL ){ - iReg = iTarget; - sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg); -#ifndef SQLITE_OMIT_SUBQUERY - }else{ - assert( pX->op==TK_IN ); - iReg = iTarget; - codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget); -#endif - } - - /* 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; -} - -/* -** Generate code that will evaluate all == and IN constraints for an -** index scan. -** -** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). -** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 -** The index has as many as three equality constraints, but in this -** example, the third "c" value is an inequality. So only two -** constraints are coded. This routine will generate code to evaluate -** a==5 and b IN (1,2,3). The current values for a and b will be stored -** in consecutive registers and the index of the first register is returned. -** -** In the example above nEq==2. But this subroutine works for any value -** of nEq including 0. If nEq==0, this routine is nearly a no-op. -** The only thing it does is allocate the pLevel->iMem memory cell and -** compute the affinity string. -** -** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints -** are == or IN and are covered by the nEq. nExtraReg is 1 if there is -** an inequality constraint (such as the "c>=5 AND c<10" in the example) that -** occurs after the nEq quality constraints. -** -** This routine allocates a range of nEq+nExtraReg memory cells and returns -** the index of the first memory cell in that range. The code that -** calls this routine will use that memory range to store keys for -** start and termination conditions of the loop. -** key value of the loop. If one or more IN operators appear, then -** this routine allocates an additional nEq memory cells for internal -** use. -** -** Before returning, *pzAff is set to point to a buffer containing a -** copy of the column affinity string of the index allocated using -** sqlite3DbMalloc(). Except, entries in the copy of the string associated -** with equality constraints that use BLOB or NONE affinity are set to -** SQLITE_AFF_BLOB. This is to deal with SQL such as the following: -** -** CREATE TABLE t1(a TEXT PRIMARY KEY, b); -** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b; -** -** In the example above, the index on t1(a) has TEXT affinity. But since -** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity, -** no conversion should be attempted before using a t2.b value as part of -** a key to search the index. Hence the first byte in the returned affinity -** string in this example would be set to SQLITE_AFF_BLOB. -*/ -static int codeAllEqualityTerms( - Parse *pParse, /* Parsing context */ - WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ - int bRev, /* Reverse the order of IN operators */ - int nExtraReg, /* Number of extra registers to allocate */ - char **pzAff /* OUT: Set to point to affinity string */ -){ - u16 nEq; /* The number of == or IN constraints to code */ - u16 nSkip; /* Number of left-most columns to skip */ - Vdbe *v = pParse->pVdbe; /* The vm under construction */ - Index *pIdx; /* The index being used for this loop */ - WhereTerm *pTerm; /* A single constraint term */ - WhereLoop *pLoop; /* The WhereLoop object */ - int j; /* Loop counter */ - int regBase; /* Base register */ - int nReg; /* Number of registers to allocate */ - char *zAff; /* Affinity string to return */ - - /* This module is only called on query plans that use an index. */ - pLoop = pLevel->pWLoop; - assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); - nEq = pLoop->u.btree.nEq; - nSkip = pLoop->nSkip; - pIdx = pLoop->u.btree.pIndex; - assert( pIdx!=0 ); - - /* Figure out how many memory cells we will need then allocate them. - */ - regBase = pParse->nMem + 1; - nReg = nEq + nExtraReg; - pParse->nMem += nReg; - - zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); - assert( zAff!=0 || pParse->db->mallocFailed ); - - if( nSkip ){ - int iIdxCur = pLevel->iIdxCur; - sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1); - sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); - VdbeCoverageIf(v, bRev==0); - VdbeCoverageIf(v, bRev!=0); - VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); - j = sqlite3VdbeAddOp0(v, OP_Goto); - assert( pLevel->addrSkip==0 ); - pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), - iIdxCur, 0, regBase, nSkip); - VdbeCoverageIf(v, bRev==0); - VdbeCoverageIf(v, bRev!=0); - sqlite3VdbeJumpHere(v, j); - for(j=0; jaiColumn[j]==XN_EXPR ); - VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); - } - } - - /* Evaluate the equality constraints - */ - assert( zAff==0 || (int)strlen(zAff)>=nEq ); - for(j=nSkip; jaLTerm[j]; - assert( pTerm!=0 ); - /* The following testcase is true for indices with redundant columns. - ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ - testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); - if( r1!=regBase+j ){ - if( nReg==1 ){ - sqlite3ReleaseTempReg(pParse, regBase); - regBase = r1; - }else{ - sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+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 - ** from the RHS of an "? IN (SELECT ...)" expression. The - ** sqlite3FindInIndex() routine has already ensured that the - ** affinity of the comparison has been applied to the value. */ - if( zAff ) zAff[j] = SQLITE_AFF_BLOB; - } - }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ - Expr *pRight = pTerm->pExpr->pRight; - if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); - VdbeCoverage(v); - } - if( pParse->nErr==0 ){ - assert( pParse->db->mallocFailed==0 ); - if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){ - zAff[j] = SQLITE_AFF_BLOB; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){ - zAff[j] = SQLITE_AFF_BLOB; - } - } - } - } - *pzAff = zAff; - return regBase; -} - -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS -/* -** If the most recently coded instruction is a constant range constraint -** (a string literal) that originated from the LIKE optimization, then -** set P3 and P5 on the OP_String opcode so that the string will be cast -** to a BLOB at appropriate times. -** -** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range -** expression: "x>='ABC' AND x<'abd'". But this requires that the range -** scan loop run twice, once for strings and a second time for BLOBs. -** The OP_String opcodes on the second pass convert the upper and lower -** bound string constants to blobs. This routine makes the necessary changes -** to the OP_String opcodes for that to happen. -** -** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then -** only the one pass through the string space is required, so this routine -** becomes a no-op. -*/ -static void whereLikeOptimizationStringFixup( - Vdbe *v, /* prepared statement under construction */ - WhereLevel *pLevel, /* The loop that contains the LIKE operator */ - WhereTerm *pTerm /* The upper or lower bound just coded */ -){ - if( pTerm->wtFlags & TERM_LIKEOPT ){ - VdbeOp *pOp; - assert( pLevel->iLikeRepCntr>0 ); - pOp = sqlite3VdbeGetLastOp(v); - assert( pOp!=0 ); - assert( pOp->opcode==OP_String8 - || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); - pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */ - pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */ - } -} -#else -# define whereLikeOptimizationStringFixup(A,B,C) -#endif - -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Information is passed from codeCursorHint() down to individual nodes of -** the expression tree (by sqlite3WalkExpr()) using an instance of this -** structure. -*/ -struct CCurHint { - int iTabCur; /* Cursor for the main table */ - int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */ - Index *pIdx; /* The index used to access the table */ -}; - -/* -** This function is called for every node of an expression that is a candidate -** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference -** the table CCurHint.iTabCur, verify that the same column can be -** accessed through the index. If it cannot, then set pWalker->eCode to 1. -*/ -static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ - struct CCurHint *pHint = pWalker->u.pCCurHint; - assert( pHint->pIdx!=0 ); - if( pExpr->op==TK_COLUMN - && pExpr->iTable==pHint->iTabCur - && sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0 - ){ - pWalker->eCode = 1; - } - return WRC_Continue; -} - -/* -** Test whether or not expression pExpr, which was part of a WHERE clause, -** should be included in the cursor-hint for a table that is on the rhs -** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the -** expression is not suitable. -** -** An expression is unsuitable if it might evaluate to non NULL even if -** a TK_COLUMN node that does affect the value of the expression is set -** to NULL. For example: -** -** col IS NULL -** col IS NOT NULL -** coalesce(col, 1) -** CASE WHEN col THEN 0 ELSE 1 END -*/ -static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_IS - || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT - || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE - ){ - pWalker->eCode = 1; - }else if( pExpr->op==TK_FUNCTION ){ - int d1; - char d2[4]; - if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ - pWalker->eCode = 1; - } - } - - return WRC_Continue; -} - - -/* -** This function is called on every node of an expression tree used as an -** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN -** that accesses any table other than the one identified by -** CCurHint.iTabCur, then do the following: -** -** 1) allocate a register and code an OP_Column instruction to read -** the specified column into the new register, and -** -** 2) transform the expression node to a TK_REGISTER node that reads -** from the newly populated register. -** -** Also, if the node is a TK_COLUMN that does access the table identified -** by pCCurHint.iTabCur, and an index is being used (which we will -** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into -** an access of the index rather than the original table. -*/ -static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ - int rc = WRC_Continue; - int reg; - struct CCurHint *pHint = pWalker->u.pCCurHint; - if( pExpr->op==TK_COLUMN ){ - if( pExpr->iTable!=pHint->iTabCur ){ - reg = ++pWalker->pParse->nMem; /* Register for column value */ - reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg); - pExpr->op = TK_REGISTER; - pExpr->iTable = reg; - }else if( pHint->pIdx!=0 ){ - pExpr->iTable = pHint->iIdxCur; - pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn); - assert( pExpr->iColumn>=0 ); - } - }else if( pExpr->pAggInfo ){ - rc = WRC_Prune; - reg = ++pWalker->pParse->nMem; /* Register for column value */ - reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg); - pExpr->op = TK_REGISTER; - pExpr->iTable = reg; - }else if( pExpr->op==TK_TRUEFALSE ){ - /* Do not walk disabled expressions. tag-20230504-1 */ - return WRC_Prune; - } - return rc; -} - -/* -** Insert an OP_CursorHint instruction if it is appropriate to do so. -*/ -static void codeCursorHint( - 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 */ -){ - Parse *pParse = pWInfo->pParse; - sqlite3 *db = pParse->db; - Vdbe *v = pParse->pVdbe; - Expr *pExpr = 0; - WhereLoop *pLoop = pLevel->pWLoop; - int iCur; - WhereClause *pWC; - WhereTerm *pTerm; - int i, j; - struct CCurHint sHint; - Walker sWalker; - - if( OptimizationDisabled(db, SQLITE_CursorHints) ) return; - iCur = pLevel->iTabCur; - assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor ); - sHint.iTabCur = iCur; - sHint.iIdxCur = pLevel->iIdxCur; - sHint.pIdx = pLoop->u.btree.pIndex; - memset(&sWalker, 0, sizeof(sWalker)); - sWalker.pParse = pParse; - sWalker.u.pCCurHint = &sHint; - pWC = &pWInfo->sWC; - for(i=0; inBase; i++){ - pTerm = &pWC->a[i]; - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( pTerm->prereqAll & pLevel->notReady ) continue; - - /* Any terms specified as part of the ON(...) clause for any LEFT - ** JOIN for which the current table is not the rhs are omitted - ** from the cursor-hint. - ** - ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms - ** that were specified as part of the WHERE clause must be excluded. - ** This is to address the following: - ** - ** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL; - ** - ** Say there is a single row in t2 that matches (t1.a=t2.b), but its - ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is - ** pushed down to the cursor, this row is filtered out, causing - ** SQLite to synthesize a row of NULL values. Which does match the - ** WHERE clause, and so the query returns a row. Which is incorrect. - ** - ** For the same reason, WHERE terms such as: - ** - ** WHERE 1 = (t2.c IS NULL) - ** - ** are also excluded. See codeCursorHintIsOrFunction() for details. - */ - if( pTabItem->fg.jointype & JT_LEFT ){ - Expr *pExpr = pTerm->pExpr; - if( !ExprHasProperty(pExpr, EP_OuterON) - || pExpr->w.iJoin!=pTabItem->iCursor - ){ - sWalker.eCode = 0; - sWalker.xExprCallback = codeCursorHintIsOrFunction; - sqlite3WalkExpr(&sWalker, pTerm->pExpr); - if( sWalker.eCode ) continue; - } - }else{ - if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue; - } - - /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize - ** the cursor. These terms are not needed as hints for a pure range - ** scan (that has no == terms) so omit them. */ - if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){ - for(j=0; jnLTerm && pLoop->aLTerm[j]!=pTerm; j++){} - if( jnLTerm ) continue; - } - - /* No subqueries or non-deterministic functions allowed */ - if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue; - - /* For an index scan, make sure referenced columns are actually in - ** the index. */ - if( sHint.pIdx!=0 ){ - sWalker.eCode = 0; - sWalker.xExprCallback = codeCursorHintCheckExpr; - sqlite3WalkExpr(&sWalker, pTerm->pExpr); - if( sWalker.eCode ) continue; - } - - /* If we survive all prior tests, that means this term is worth hinting */ - pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); - } - if( pExpr!=0 ){ - sWalker.xExprCallback = codeCursorHintFixExpr; - if( pParse->nErr==0 ) sqlite3WalkExpr(&sWalker, pExpr); - sqlite3VdbeAddOp4(v, OP_CursorHint, - (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, - (const char*)pExpr, P4_EXPR); - } -} -#else -# define codeCursorHint(A,B,C,D) /* No-op */ -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ - -/* -** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains -** a rowid value just read from cursor iIdxCur, open on index pIdx. This -** function generates code to do a deferred seek of cursor iCur to the -** rowid stored in register iRowid. -** -** Normally, this is just: -** -** 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 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 */ - Index *pIdx, /* Index scan is using */ - int iCur, /* Cursor for IPK b-tree */ - int iIdxCur /* Index cursor */ -){ - Parse *pParse = pWInfo->pParse; /* Parse context */ - Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ - - assert( iIdxCur>0 ); - assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); - - pWInfo->bDeferredSeek = 1; - sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); - if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) - && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) - ){ - int i; - Table *pTab = pIdx->pTable; - u32 *ai = (u32*)sqlite3DbMallocZero(pParse->db, sizeof(u32)*(pTab->nCol+1)); - if( ai ){ - ai[0] = pTab->nCol; - for(i=0; inColumn-1; i++){ - int x1, x2; - assert( pIdx->aiColumn[i]nCol ); - x1 = pIdx->aiColumn[i]; - x2 = sqlite3TableColumnToStorage(pTab, x1); - testcase( x1!=x2 ); - if( x1>=0 ) ai[x2+1] = i+1; - } - sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); - } - } -} - -/* -** If the expression passed as the second argument is a vector, generate -** code to write the first nReg elements of the vector into an array -** of registers starting with iReg. -** -** If the expression is not a vector, then nReg must be passed 1. In -** this case, generate code to evaluate the expression and leave the -** result in register iReg. -*/ -static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ - assert( nReg>0 ); - if( p && sqlite3ExprIsVector(p) ){ -#ifndef SQLITE_OMIT_SUBQUERY - if( ExprUseXSelect(p) ){ - Vdbe *v = pParse->pVdbe; - int iSelect; - assert( p->op==TK_SELECT ); - iSelect = sqlite3CodeSubselect(pParse, p); - sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); - }else -#endif - { - int i; - const ExprList *pList; - assert( ExprUseXList(p) ); - pList = p->x.pList; - assert( nReg<=pList->nExpr ); - for(i=0; ia[i].pExpr, iReg+i); - } - } - }else{ - assert( nReg==1 || pParse->nErr ); - sqlite3ExprCode(pParse, p, iReg); - } -} - -/* -** The pTruth expression is always true because it is the WHERE clause -** a partial index that is driving a query loop. Look through all of the -** WHERE clause terms on the query, and if any of those terms must be -** true because pTruth is true, then mark those WHERE clause terms as -** coded. -*/ -static void whereApplyPartialIndexConstraints( - Expr *pTruth, - int iTabCur, - WhereClause *pWC -){ - int i; - WhereTerm *pTerm; - while( pTruth->op==TK_AND ){ - whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC); - pTruth = pTruth->pRight; - } - for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr; - if( pTerm->wtFlags & TERM_CODED ) continue; - pExpr = pTerm->pExpr; - if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } -} - -/* -** 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 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 = sqlite3GetTempReg(pParse); - regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid); - sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt); - VdbeCoverage(pParse->pVdbe); - 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); - sqlite3DbFree(pParse->db, zStartAff); - sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, - addrNxt, r1, nEq); - VdbeCoverage(pParse->pVdbe); - } - pLevel->regFilter = 0; - pLevel->addrBrk = 0; - } -} - -/* -** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...) -** operator. Return true if level pLoop is guaranteed to visit only one -** row for each key generated for the index. -*/ -static int whereLoopIsOneRow(WhereLoop *pLoop){ - if( pLoop->u.btree.pIndex->onError - && pLoop->nSkip==0 - && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol - ){ - int ii; - for(ii=0; iiu.btree.nEq; ii++){ - if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){ - return 0; - } - } - return 1; - } - return 0; -} - -/* -** Generate code for the start of the iLevel-th loop in the WHERE clause -** implementation described by pWInfo. -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( - Parse *pParse, /* Parsing context */ - Vdbe *v, /* Prepared statement under construction */ - WhereInfo *pWInfo, /* Complete information about the WHERE clause */ - int iLevel, /* Which level of pWInfo->a[] should be coded */ - WhereLevel *pLevel, /* The current level pointer */ - Bitmask notReady /* Which tables are currently available */ -){ - int j, k; /* Loop counters */ - int iCur; /* The VDBE cursor for the table */ - int addrNxt; /* Where to jump to continue with the next IN case */ - int bRev; /* True if we need to scan in reverse order */ - WhereLoop *pLoop; /* The WhereLoop object being coded */ - WhereClause *pWC; /* Decomposition of the entire WHERE clause */ - WhereTerm *pTerm; /* A WHERE clause term */ - sqlite3 *db; /* Database connection */ - 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 */ - int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ - int iReleaseReg = 0; /* Temp register to free before returning */ - Index *pIdx = 0; /* Index used by loop (if any) */ - int iLoop; /* Iteration of constraint generator loop */ - - pWC = &pWInfo->sWC; - db = pParse->db; - pLoop = pLevel->pWLoop; - pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; - iCur = pTabItem->iCursor; - pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); - bRev = (pWInfo->revMask>>iLevel)&1; - VdbeModuleComment((v, "Begin WHERE-loop%d: %s", - iLevel, pTabItem->pSTab->zName)); -#if WHERETRACE_ENABLED /* 0x4001 */ - if( sqlite3WhereTrace & 0x1 ){ - sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n", - iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom); - if( sqlite3WhereTrace & 0x1000 ){ - sqlite3WhereLoopPrint(pLoop, pWC); - } - } - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - if( iLevel==0 ){ - sqlite3DebugPrintf("WHERE clause being coded:\n"); - sqlite3TreeViewExpr(0, pWInfo->pWhere, 0); - } - sqlite3DebugPrintf("All WHERE-clause terms before coding:\n"); - sqlite3WhereClausePrint(pWC); - } -#endif - - /* Create labels for the "break" and "continue" instructions - ** for the current loop. Jump to addrBrk to break out of a loop. - ** Jump to cont to go immediately to the next iteration of the - ** loop. - ** - ** When there is an IN operator, we also have a "addrNxt" label that - ** means to continue with the next IN value combination. When - ** there are no IN operators in the constraints, the "addrNxt" label - ** is the same as "addrBrk". - */ - addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); - addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse); - - /* If this is the right table of a LEFT OUTER JOIN, allocate and - ** initialize a memory cell that records if this table matches any - ** row of the left table of the join. - */ - 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 ){ - pLevel->iLeftJoin = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); - VdbeComment((v, "init LEFT JOIN match flag")); - } - - /* 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; 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 */ - if( pTabItem->fg.viaCoroutine ){ - int regYield; - Subquery *pSubq; - assert( pTabItem->fg.isSubquery && pTabItem->u4.pSubq!=0 ); - pSubq = pTabItem->u4.pSubq; - regYield = pSubq->regReturn; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub); - pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); - VdbeCoverage(v); - VdbeComment((v, "next row of %s", pTabItem->pSTab->zName)); - pLevel->op = OP_Goto; - }else - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - /* Case 1: The table is a virtual-table. Use the VFilter and VNext - ** to access the data. - */ - int iReg; /* P3 Value for OP_VFilter */ - int addrNotFound; - int nConstraint = pLoop->nLTerm; - - iReg = sqlite3GetTempRange(pParse, nConstraint+2); - addrNotFound = pLevel->addrBrk; - for(j=0; jaLTerm[j]; - if( NEVER(pTerm==0) ) continue; - if( pTerm->eOperator & WO_IN ){ - if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ - int iTab = pParse->nTab++; - int iCache = ++pParse->nMem; - sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); - 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->pSelect!=0 ); - assert( pWInfo->pSelect->iOffset>0 ); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pSelect->iOffset); - VdbeComment((v,"Zero OFFSET counter")); - } - } - } - sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); - sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); - /* The instruction immediately prior to OP_VFilter must be an OP_Integer - ** that sets the "argc" value for xVFilter. This is necessary for - ** resolveP2() to work correctly. See tag-20250207a. */ - sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, - pLoop->u.vtab.idxStr, - pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); - VdbeCoverage(v); - pLoop->u.vtab.needFree = 0; - /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed - ** the u.vtab.idxStr. NULL it out to prevent a use-after-free */ - if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0; - pLevel->p1 = iCur; - pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - - for(j=0; jaLTerm[j]; - if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ - disableTerm(pLevel, pTerm); - 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. - */ - for(iIn=0; ALWAYS(iInu.in.nIn); iIn++){ - pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop); - if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2) - || (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2) - ){ - testcase( pOp->opcode==OP_Rowid ); - 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 - */ - pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); - 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 = sqlite3Expr(db, TK_REGISTER, 0); - if( pRight ){ - pRight->iTable = iReg+j+2; - sqlite3ExprIfFalse( - pParse, pCompare, pLevel->addrCont, SQLITE_JUMPIFNULL - ); - } - pCompare->pLeft = 0; - } - sqlite3ExprDelete(db, pCompare); - } - } - - /* 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 - ** simpler and safer to simply not reuse the registers. - ** - ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); - */ - }else -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - - if( (pLoop->wsFlags & WHERE_IPK)!=0 - && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0 - ){ - /* Case 2: We can directly reference a single row using an - ** equality comparison against the ROWID field. Or - ** we reference multiple rows using a "rowid IN (...)" - ** construct. - */ - assert( pLoop->u.btree.nEq==1 ); - pTerm = pLoop->aLTerm[0]; - assert( pTerm!=0 ); - assert( pTerm->pExpr!=0 ); - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - iReleaseReg = ++pParse->nMem; - iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); - if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); - addrNxt = pLevel->addrNxt; - if( pLevel->regFilter ){ - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); - VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, - iRowidReg, 1); - VdbeCoverage(v); - filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); - } - sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); - VdbeCoverage(v); - pLevel->op = OP_Noop; - }else if( (pLoop->wsFlags & WHERE_IPK)!=0 - && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 - ){ - /* Case 3: We have an inequality comparison against the ROWID field. - */ - int testOp = OP_Noop; - int start; - int memEndValue = 0; - WhereTerm *pStart, *pEnd; - - j = 0; - pStart = pEnd = 0; - if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++]; - if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; - assert( pStart!=0 || pEnd!=0 ); - if( bRev ){ - pTerm = pStart; - pStart = pEnd; - pEnd = pTerm; - } - codeCursorHint(pTabItem, pWInfo, pLevel, pEnd); - if( pStart ){ - Expr *pX; /* The expression that defines the start bound */ - int r1, rTemp; /* Registers for holding the start boundary */ - int op; /* Cursor seek operation */ - - /* The following constant maps TK_xx codes into corresponding - ** seek opcodes. It depends on a particular ordering of TK_xx - */ - const u8 aMoveOp[] = { - /* TK_GT */ OP_SeekGT, - /* TK_LE */ OP_SeekLE, - /* TK_LT */ OP_SeekLT, - /* TK_GE */ OP_SeekGE - }; - assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ - assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ - assert( TK_GE==TK_GT+3 ); /* ... is correct. */ - - assert( (pStart->wtFlags & TERM_VNULL)==0 ); - testcase( pStart->wtFlags & TERM_VIRTUAL ); - pX = pStart->pExpr; - assert( pX!=0 ); - testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ - if( sqlite3ExprIsVector(pX->pRight) ){ - r1 = rTemp = sqlite3GetTempReg(pParse); - codeExprOrVector(pParse, pX->pRight, r1, 1); - testcase( pX->op==TK_GT ); - testcase( pX->op==TK_GE ); - testcase( pX->op==TK_LT ); - testcase( pX->op==TK_LE ); - op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; - assert( pX->op!=TK_GT || op==OP_SeekGE ); - assert( pX->op!=TK_GE || op==OP_SeekGE ); - assert( pX->op!=TK_LT || op==OP_SeekLE ); - assert( pX->op!=TK_LE || op==OP_SeekLE ); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); - disableTerm(pLevel, pStart); - op = aMoveOp[(pX->op - TK_GT)]; - } - sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); - VdbeComment((v, "pk")); - VdbeCoverageIf(v, pX->op==TK_GT); - VdbeCoverageIf(v, pX->op==TK_LE); - VdbeCoverageIf(v, pX->op==TK_LT); - VdbeCoverageIf(v, pX->op==TK_GE); - sqlite3ReleaseTempReg(pParse, rTemp); - }else{ - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); - VdbeCoverageIf(v, bRev==0); - VdbeCoverageIf(v, bRev!=0); - } - if( pEnd ){ - Expr *pX; - pX = pEnd->pExpr; - assert( pX!=0 ); - assert( (pEnd->wtFlags & TERM_VNULL)==0 ); - testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ - testcase( pEnd->wtFlags & TERM_VIRTUAL ); - memEndValue = ++pParse->nMem; - codeExprOrVector(pParse, pX->pRight, memEndValue, 1); - if( 0==sqlite3ExprIsVector(pX->pRight) - && (pX->op==TK_LT || pX->op==TK_GT) - ){ - testOp = bRev ? OP_Le : OP_Ge; - }else{ - testOp = bRev ? OP_Lt : OP_Gt; - } - if( 0==sqlite3ExprIsVector(pX->pRight) ){ - disableTerm(pLevel, pEnd); - } - } - start = sqlite3VdbeCurrentAddr(v); - pLevel->op = bRev ? OP_Prev : OP_Next; - pLevel->p1 = iCur; - pLevel->p2 = start; - assert( pLevel->p5==0 ); - if( testOp!=OP_Noop ){ - iRowidReg = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); - sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); - VdbeCoverageIf(v, testOp==OP_Le); - VdbeCoverageIf(v, testOp==OP_Lt); - VdbeCoverageIf(v, testOp==OP_Ge); - VdbeCoverageIf(v, testOp==OP_Gt); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); - } - }else if( pLoop->wsFlags & WHERE_INDEXED ){ - /* Case 4: A scan using an index. - ** - ** The WHERE clause may contain zero or more equality - ** terms ("==" or "IN" operators) that refer to the N - ** left-most columns of the index. It may also contain - ** inequality constraints (>, <, >= or <=) on the indexed - ** column that immediately follows the N equalities. Only - ** the right-most column can be an inequality - the rest must - ** use the "==" and "IN" operators. For example, if the - ** index is on (x,y,z), then the following clauses are all - ** optimized: - ** - ** x=5 - ** x=5 AND y=10 - ** x=5 AND y<10 - ** x=5 AND y>5 AND y<10 - ** x=5 AND y=5 AND z<=10 - ** - ** The z<10 term of the following cannot be used, only - ** the x=5 term: - ** - ** x=5 AND z<10 - ** - ** N may be zero if there are inequality constraints. - ** If there are no inequality constraints, then N is at - ** least one. - ** - ** This case is also used when there are no WHERE clause - ** constraints but an index is selected anyway, in order - ** to force the output order to conform to an ORDER BY. - */ - static const u8 aStartOp[] = { - 0, - 0, - OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ - OP_Last, /* 3: (!start_constraints && startEq && bRev) */ - OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */ - OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */ - OP_SeekGE, /* 6: (start_constraints && startEq && !bRev) */ - OP_SeekLE /* 7: (start_constraints && startEq && bRev) */ - }; - static const u8 aEndOp[] = { - OP_IdxGE, /* 0: (end_constraints && !bRev && !endEq) */ - OP_IdxGT, /* 1: (end_constraints && !bRev && endEq) */ - OP_IdxLE, /* 2: (end_constraints && bRev && !endEq) */ - OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ - }; - u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ - u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */ - u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */ - int regBase; /* Base register holding constraint values */ - WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ - WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ - int startEq; /* True if range start uses ==, >= or <= */ - int endEq; /* True if range end uses ==, >= or <= */ - int start_constraints; /* Start of range is constrained */ - int nConstraint; /* Number of constraint terms */ - int iIdxCur; /* The VDBE cursor for the index */ - int nExtraReg = 0; /* Number of extra registers needed */ - int op; /* Instruction opcode */ - char *zStartAff; /* Affinity for start of range constraint */ - char *zEndAff = 0; /* Affinity for end of range constraint */ - u8 bSeekPastNull = 0; /* True to seek past initial nulls */ - u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ - int omitTable; /* True if we use the index only */ - int regBignull = 0; /* big-null flag register */ - int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */ - - pIdx = pLoop->u.btree.pIndex; - iIdxCur = pLevel->iIdxCur; - assert( nEq>=pLoop->nSkip ); - - /* Find any inequality constraint terms for the start and end - ** of the range. - */ - j = nEq; - if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ - pRangeStart = pLoop->aLTerm[j++]; - nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm); - /* Like optimization range constraints always occur in pairs */ - assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || - (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); - } - if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ - pRangeEnd = pLoop->aLTerm[j++]; - nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop); -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ - assert( pRangeStart!=0 ); /* LIKE opt constraints */ - assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ - pLevel->iLikeRepCntr = (u32)++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr); - VdbeComment((v, "LIKE loop counter")); - pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); - /* iLikeRepCntr actually stores 2x the counter register number. The - ** bottom bit indicates whether the search order is ASC or DESC. */ - testcase( bRev ); - testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); - assert( (bRev & ~1)==0 ); - pLevel->iLikeRepCntr <<=1; - pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); - } -#endif - if( pRangeStart==0 ){ - j = pIdx->aiColumn[nEq]; - if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ - bSeekPastNull = 1; - } - } - } - assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); - - /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses - ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS - ** FIRST). In both cases separate ordered scans are made of those - ** index entries for which the column is null and for those for which - ** it is not. For an ASC sort, the non-NULL entries are scanned first. - ** For DESC, NULL entries are scanned first. - */ - if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0 - && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0 - ){ - assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 ); - assert( pRangeEnd==0 && pRangeStart==0 ); - testcase( pLoop->nSkip>0 ); - nExtraReg = 1; - bSeekPastNull = 1; - pLevel->regBignull = regBignull = ++pParse->nMem; - if( pLevel->iLeftJoin ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull); - } - pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse); - } - - /* If we are doing a reverse order scan on an ascending index, or - ** a forward order scan on a descending index, interchange the - ** start and end terms (pRangeStart and pRangeEnd). - */ - if( (nEqnColumn && 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. */ - 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. - */ - codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); - regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); - assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); - if( zStartAff && nTop ){ - zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); - } - addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt); - - testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); - testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); - testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); - testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); - startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); - endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); - start_constraints = pRangeStart || nEq>0; - - /* Seek the index cursor to the start of the range. */ - nConstraint = nEq; - if( pRangeStart ){ - Expr *pRight = pRangeStart->pExpr->pRight; - codeExprOrVector(pParse, pRight, regBase+nEq, nBtm); - whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); - if( (pRangeStart->wtFlags & TERM_VNULL)==0 - && sqlite3ExprCanBeNull(pRight) - ){ - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); - VdbeCoverage(v); - } - if( zStartAff ){ - updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); - } - nConstraint += nBtm; - testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); - if( sqlite3ExprIsVector(pRight)==0 ){ - disableTerm(pLevel, pRangeStart); - }else{ - startEq = 1; - } - bSeekPastNull = 0; - }else if( bSeekPastNull ){ - startEq = 0; - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - start_constraints = 1; - nConstraint++; - }else if( regBignull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - start_constraints = 1; - nConstraint++; - } - codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); - if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){ - /* The skip-scan logic inside the call to codeAllEqualityConstraints() - ** above has already left the cursor sitting on the correct row, - ** so no further seeking is needed */ - }else{ - if( regBignull ){ - sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); - VdbeComment((v, "NULL-scan pass ctr")); - } - if( pLevel->regFilter ){ - 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 ); - if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){ - assert( regBignull==0 ); - /* TUNING: The OP_SeekScan opcode seeks to reduce the number - ** of expensive seek operations by replacing a single seek with - ** 1 or more step operations. The question is, how many steps - ** should we try before giving up and going with a seek. The cost - ** of a seek is proportional to the logarithm of the of the number - ** of entries in the tree, so basing the number of steps to try - ** on the estimated number of rows in the btree seems like a good - ** guess. */ - addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, - (pIdx->aiRowLogEst[0]+9)/10); - if( pRangeStart || pRangeEnd ){ - sqlite3VdbeChangeP5(v, 1); - sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1); - addrSeekScan = 0; - } - VdbeCoverage(v); - } - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - VdbeCoverage(v); - VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); - VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); - VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); - VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); - VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); - VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); - - assert( bSeekPastNull==0 || bStopAtNull==0 ); - if( regBignull ){ - assert( bSeekPastNull==1 || bStopAtNull==1 ); - assert( bSeekPastNull==!bStopAtNull ); - assert( bStopAtNull==startEq ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - op = aStartOp[(nConstraint>1)*4 + 2 + bRev]; - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, - nConstraint-startEq); - VdbeCoverage(v); - VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); - VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); - VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); - VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); - assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE); - } - } - - /* Load the value for the inequality constraint at the end of the - ** range (if any). - */ - nConstraint = nEq; - assert( pLevel->p2==0 ); - if( pRangeEnd ){ - Expr *pRight = pRangeEnd->pExpr->pRight; - assert( addrSeekScan==0 ); - codeExprOrVector(pParse, pRight, regBase+nEq, nTop); - whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); - if( (pRangeEnd->wtFlags & TERM_VNULL)==0 - && sqlite3ExprCanBeNull(pRight) - ){ - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); - VdbeCoverage(v); - } - if( zEndAff ){ - updateRangeAffinityStr(pRight, nTop, zEndAff); - codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); - }else{ - assert( pParse->db->mallocFailed ); - } - nConstraint += nTop; - testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); - - if( sqlite3ExprIsVector(pRight)==0 ){ - disableTerm(pLevel, pRangeEnd); - }else{ - endEq = 1; - } - }else if( bStopAtNull ){ - if( regBignull==0 ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - endEq = 0; - } - nConstraint++; - } - if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff); - if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff); - - /* Top of the loop body */ - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - - /* Check if the index cursor is past the end of the range. */ - if( nConstraint ){ - if( regBignull ){ - /* Except, skip the end-of-range check while doing the NULL-scan */ - sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); - VdbeComment((v, "If NULL-scan 2nd pass")); - VdbeCoverage(v); - } - op = aEndOp[bRev*2 + endEq]; - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); - testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); - testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); - testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); - if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan); - } - if( regBignull ){ - /* During a NULL-scan, check to see if we have reached the end of - ** the NULLs */ - assert( bSeekPastNull==!bStopAtNull ); - assert( bSeekPastNull+bStopAtNull==1 ); - assert( nConstraint+bSeekPastNull>0 ); - sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2); - VdbeComment((v, "If NULL-scan 1st pass")); - VdbeCoverage(v); - op = aEndOp[bRev*2 + bSeekPastNull]; - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, - nConstraint+bSeekPastNull); - testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); - testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); - testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); - testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); - } - - if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){ - sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq); - } - - /* Seek the table cursor, if required */ - omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=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) ){ - codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); - }else if( iCur!=iIdxCur ){ - Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); - iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); - for(j=0; jnKeyCol; j++){ - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); - } - sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, - iRowidReg, pPk->nKeyCol); VdbeCoverage(v); - } - - if( pLevel->iLeftJoin==0 ){ - /* If a partial index is driving the loop, try to eliminate WHERE clause - ** terms from the query that must be true due to the WHERE clause of - ** the partial index. This optimization does not work on an outer join, - ** as shown by: - ** - ** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN) - ** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN) - */ - if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){ - whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC); - } - }else{ - testcase( pIdx->pPartIdxWhere ); - /* 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|WHERE_RIGHT_JOIN))==0 ); - } - - /* Record the instruction used to terminate the loop. */ - if( (pLoop->wsFlags & WHERE_ONEROW) - || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop)) - ){ - pLevel->op = OP_Noop; - }else if( bRev ){ - pLevel->op = OP_Prev; - }else{ - pLevel->op = OP_Next; - } - pLevel->p1 = iIdxCur; - pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0; - if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){ - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - }else{ - assert( pLevel->p5==0 ); - } - if( omitTable ) pIdx = 0; - }else - -#ifndef SQLITE_OMIT_OR_OPTIMIZATION - if( pLoop->wsFlags & WHERE_MULTI_OR ){ - /* Case 5: Two or more separately indexed terms connected by OR - ** - ** Example: - ** - ** CREATE TABLE t1(a,b,c,d); - ** CREATE INDEX i1 ON t1(a); - ** CREATE INDEX i2 ON t1(b); - ** CREATE INDEX i3 ON t1(c); - ** - ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13) - ** - ** In the example, there are three indexed terms connected by OR. - ** The top of the loop looks like this: - ** - ** Null 1 # Zero the rowset in reg 1 - ** - ** Then, for each indexed term, the following. The arguments to - ** RowSetTest are such that the rowid of the current row is inserted - ** into the RowSet. If it is already present, control skips the - ** Gosub opcode and jumps straight to the code generated by WhereEnd(). - ** - ** sqlite3WhereBegin() - ** RowSetTest # Insert rowid into rowset - ** Gosub 2 A - ** sqlite3WhereEnd() - ** - ** Following the above, code to terminate the loop. Label A, the target - ** of the Gosub above, jumps to the instruction right after the Goto. - ** - ** Null 1 # Zero the rowset in reg 1 - ** Goto B # The loop is finished. - ** - ** A: # Return data, whatever. - ** - ** Return 2 # Jump back to the Gosub - ** - ** B: - ** - ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then - ** use an ephemeral index instead of a RowSet to record the primary - ** keys of the rows we have already seen. - ** - */ - WhereClause *pOrWc; /* The OR-clause broken out into subterms */ - SrcList *pOrTab; /* Shortened table list or OR-clause generation */ - Index *pCov = 0; /* Potential covering index (or NULL) */ - int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ - - int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ - int regRowset = 0; /* Register for RowSet object */ - int regRowid = 0; /* Register holding rowid */ - int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */ - int iRetInit; /* Address of regReturn init */ - int untestedTerms = 0; /* Some terms not completely tested */ - int ii; /* Loop counter */ - Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ - Table *pTab = pTabItem->pSTab; - - pTerm = pLoop->aLTerm[0]; - assert( pTerm!=0 ); - assert( pTerm->eOperator & WO_OR ); - assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); - pOrWc = &pTerm->u.pOrInfo->wc; - pLevel->op = OP_Return; - pLevel->p1 = regReturn; - - /* Set up a new SrcList in pOrTab containing the table being scanned - ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. - ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). - */ - if( pWInfo->nLevel>1 ){ - int nNotReady; /* The number of notReady tables */ - SrcItem *origSrc; /* Original list of tables */ - nNotReady = pWInfo->nLevel - iLevel - 1; - pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1)); - if( pOrTab==0 ) return notReady; - pOrTab->nAlloc = (u8)(nNotReady + 1); - pOrTab->nSrc = pOrTab->nAlloc; - memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); - origSrc = pWInfo->pTabList->a; - for(k=1; k<=nNotReady; k++){ - memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); - } - }else{ - pOrTab = pWInfo->pTabList; - } - - /* Initialize the rowset register to contain NULL. An SQL NULL is - ** equivalent to an empty rowset. Or, create an ephemeral index - ** capable of holding primary keys in the case of a WITHOUT ROWID. - ** - ** Also initialize regReturn to contain the address of the instruction - ** immediately following the OP_Return at the bottom of the loop. This - ** is required in a few obscure LEFT JOIN cases where control jumps - ** over the top of the loop into the body of it. In this case the - ** correct response for the end-of-loop code (the OP_Return) is to - ** fall through to the next instruction, just as an OP_Next does if - ** called on an uninitialized cursor. - */ - if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - if( HasRowid(pTab) ){ - regRowset = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - regRowset = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol); - sqlite3VdbeSetP4KeyInfo(pParse, pPk); - } - regRowid = ++pParse->nMem; - } - iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); - - /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y - ** Then for every term xN, evaluate as the subexpression: xN AND y - ** That way, terms in y that are factored into the disjunction will - ** be picked up by the recursive calls to sqlite3WhereBegin() below. - ** - ** Actually, each subexpression is converted to "xN AND w" where w is - ** the "interesting" terms of z - terms that did not originate in the - ** ON or USING clause of a LEFT JOIN, and terms that are usable as - ** indices. - ** - ** This optimization also only applies if the (x1 OR x2 OR ...) term - ** is not contained in the ON clause of a LEFT JOIN. - ** See ticket http://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; - for(iTerm=0; iTermnTerm; iTerm++){ - Expr *pExpr = pWC->a[iTerm].pExpr; - if( &pWC->a[iTerm] == pTerm ) continue; - testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); - testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); - 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; - if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */ - pExpr = sqlite3ExprDup(db, pExpr, 0); - pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); - } - if( pAndExpr ){ - /* 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 sqlite3PExpr() false, and this - ** prevents sqlite3PExpr() from applying the AND short-circuit - ** optimization, which we do not want here. */ - pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr); - } - } - - /* Run a separate WHERE clause for each term of the OR clause. After - ** eliminating duplicates from other WHERE clauses, the action for each - ** sub-WHERE clause is to to invoke the main loop body as a subroutine. - */ - ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); - for(ii=0; iinTerm; ii++){ - WhereTerm *pOrTerm = &pOrWc->a[ii]; - if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ - WhereInfo *pSubWInfo; /* Info for single OR-term scan */ - Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ - 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_OuterON) - ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */ - pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDelete); - continue; - } - if( pAndExpr ){ - pAndExpr->pLeft = pOrExpr; - pOrExpr = pAndExpr; - } - /* Loop through table entries that match term pOrTerm. */ - ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1)); - WHERETRACE(0xffffffff, ("Subplan for OR-clause:\n")); - pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0, - WHERE_OR_SUBCLAUSE, iCovCur); - assert( pSubWInfo || pParse->nErr ); - if( pSubWInfo ){ - WhereLoop *pSubLoop; - int addrExplain = sqlite3WhereExplainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], 0 - ); - sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); - - /* This is the sub-WHERE clause body. First skip over - ** duplicate rows from prior sub-WHERE clauses, and record the - ** rowid (or PRIMARY KEY) for the current row so that the same - ** row will be skipped in subsequent sub-WHERE clauses. - */ - if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); - if( HasRowid(pTab) ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); - jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, - regRowid, iSet); - VdbeCoverage(v); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - int nPk = pPk->nKeyCol; - int iPk; - int r; - - /* Read the PK into an array of temp registers. */ - r = sqlite3GetTempRange(pParse, nPk); - for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); - } - - /* Check if the temp table already contains this key. If so, - ** the row has already been included in the result set and - ** can be ignored (by jumping past the Gosub below). Otherwise, - ** insert the key into the temp table and proceed with processing - ** the row. - ** - ** Use some of the same optimizations as OP_RowSetTest: If iSet - ** is zero, assume that the key cannot already be present in - ** the temp table. And if iSet is -1, assume that there is no - ** need to insert the key into the temp table, as it will never - ** be tested for. */ - if( iSet ){ - jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); - VdbeCoverage(v); - } - if( iSet>=0 ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid, - r, nPk); - if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - } - - /* Release the array of temp registers */ - sqlite3ReleaseTempRange(pParse, r, nPk); - } - } - - /* Invoke the main loop body as a subroutine */ - sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); - - /* Jump here (skipping the main loop body subroutine) if the - ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */ - if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1); - - /* The pSubWInfo->untestedTerms flag means that this OR term - ** contained one or more AND term from a notReady table. The - ** terms from the notReady table could not be tested and will - ** need to be tested later. - */ - if( pSubWInfo->untestedTerms ) untestedTerms = 1; - - /* If all of the OR-connected terms are optimized using the same - ** index, and the index is opened using the same cursor number - ** by each call to sqlite3WhereBegin() made by this loop, it may - ** be possible to use that index as a covering index. - ** - ** If the call to sqlite3WhereBegin() above resulted in a scan that - ** uses an index, and this is either the first OR-connected term - ** processed or the index is the same as that used by all previous - ** terms, set pCov to the candidate covering index. Otherwise, set - ** pCov to NULL to indicate that no candidate covering index will - ** be available. - */ - pSubLoop = pSubWInfo->a[0].pWLoop; - assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 - && (ii==0 || pSubLoop->u.btree.pIndex==pCov) - && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex)) - ){ - assert( pSubWInfo->a[0].iIdxCur==iCovCur ); - pCov = pSubLoop->u.btree.pIndex; - }else{ - pCov = 0; - } - if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){ - pWInfo->bDeferredSeek = 1; - } - - /* Finish the loop through table entries that match term pOrTerm. */ - sqlite3WhereEnd(pSubWInfo); - ExplainQueryPlanPop(pParse); - } - sqlite3ExprDelete(db, pDelete); - } - } - ExplainQueryPlanPop(pParse); - 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; - sqlite3ExprDelete(db, pAndExpr); - } - sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeGoto(v, pLevel->addrBrk); - 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 = sqlite3VdbeCurrentAddr(v); - - if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); } - if( !untestedTerms ) disableTerm(pLevel, pTerm); - }else -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - - { - /* Case 6: There is no usable index. We must do a complete - ** scan of the entire table. - */ - static const u8 aStep[] = { OP_Next, OP_Prev }; - static const u8 aStart[] = { OP_Rewind, OP_Last }; - assert( bRev==0 || bRev==1 ); - if( pTabItem->fg.isRecursive ){ - /* Tables marked isRecursive have only a single row that is stored in - ** a pseudo-cursor. No need to Rewind or Next such cursors. */ - pLevel->op = OP_Noop; - }else{ - codeCursorHint(pTabItem, pWInfo, pLevel, 0); - pLevel->op = aStep[bRev]; - pLevel->p1 = iCur; - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); - VdbeCoverageIf(v, bRev==0); - VdbeCoverageIf(v, bRev!=0); - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - } - } - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pLevel->addrVisit = sqlite3VdbeCurrentAddr(v); -#endif - - /* Insert code to test every subexpression that can be completely - ** computed using the current set of tables. - ** - ** This loop may run between one and three times, depending on the - ** constraints to be generated. The value of stack variable iLoop - ** determines the constraints coded by each iteration, as follows: - ** - ** iLoop==1: Code only expressions that are entirely covered by pIdx. - ** iLoop==2: Code remaining expressions that do not contain correlated - ** sub-queries. - ** iLoop==3: Code all remaining expressions. - ** - ** An effort is made to skip unnecessary iterations of the loop. - ** - ** This optimization of causing simple query restrictions to occur before - ** more complex one is call the "push-down" optimization in MySQL. Here - ** in SQLite, the name is "MySQL push-down", since there is also another - ** totally unrelated optimization called "WHERE-clause push-down". - ** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware. - */ - iLoop = (pIdx ? 1 : 2); - do{ - int iNext = 0; /* Next value for iLoop */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE; - int skipLikeAddr = 0; - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - testcase( pTerm->wtFlags & TERM_CODED ); - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ - testcase( pWInfo->untestedTerms==0 - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); - pWInfo->untestedTerms = 1; - continue; - } - pE = pTerm->pExpr; - assert( pE!=0 ); - 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 = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin); - if( m & pLevel->notReady ){ - /* An ON clause that is not ripe */ - continue; - } - } - } - if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ - iNext = 2; - continue; - } - if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){ - if( iNext==0 ) iNext = 3; - continue; - } - - if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){ - /* If the TERM_LIKECOND flag is set, that means that the range search - ** is sufficient to guarantee that the LIKE operator is true, so we - ** can skip the call to the like(A,B) function. But this only works - ** for strings. So do not skip the call to the function on the pass - ** that compares BLOBs. */ -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - continue; -#else - u32 x = pLevel->iLikeRepCntr; - if( x>0 ){ - skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); - VdbeCoverageIf(v, (x&1)==1); - VdbeCoverageIf(v, (x&1)==0); - } -#endif - } -#ifdef WHERETRACE_ENABLED /* 0xffffffff */ - if( sqlite3WhereTrace ){ - VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d", - pWC->nTerm-j, pTerm, iLoop)); - } - if( sqlite3WhereTrace & 0x4000 ){ - sqlite3DebugPrintf("Coding auxiliary constraint:\n"); - sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); - } -#endif - sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); - if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); - pTerm->wtFlags |= TERM_CODED; - } - iLoop = iNext; - }while( iLoop>0 ); - - /* Insert code to test for implied constraints based on transitivity - ** of the "==" operator. - ** - ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" - ** and we are coding the t1 loop and the t2 loop has not yet coded, - ** then we cannot use the "t1.a=t2.b" constraint, but we can code - ** the implied "t1.a=123" constraint. - */ - for(pTerm=pWC->a, j=pWC->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|JT_LTORJ|JT_RIGHT) ) continue; - pE = pTerm->pExpr; -#ifdef WHERETRACE_ENABLED /* 0x4001 */ - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - sqlite3DebugPrintf("Coding transitive constraint:\n"); - sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); - } -#endif - assert( !ExprHasProperty(pE, EP_OuterON) ); - assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - pAlt = 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) - && ExprUseXSelect(pAlt->pExpr) - && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) - ){ - continue; - } - testcase( pAlt->eOperator & WO_EQ ); - testcase( pAlt->eOperator & WO_IS ); - testcase( pAlt->eOperator & WO_IN ); - VdbeModuleComment((v, "begin transitive constraint")); - sEAlt = *pAlt->pExpr; - sEAlt.pLeft = pE->pLeft; - 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].pSTab; - if( HasRowid(pTab) ){ - r = sqlite3GetTempRange(pParse, 2); - sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1); - nPk = 1; - }else{ - int iPk; - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - nPk = pPk->nKeyCol; - r = sqlite3GetTempRange(pParse, nPk+1); - for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk); - } - } - jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk); - VdbeCoverage(v); - VdbeComment((v, "match against %s", pTab->zName)); - sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk); - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3VdbeJumpHere(v, jmp1); - sqlite3ReleaseTempRange(pParse, r, nPk+1); - } - - /* For a LEFT OUTER JOIN, generate code that will record the fact that - ** at least one row of the right table has matched the left table. - */ - if( pLevel->iLeftJoin ){ - pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); - VdbeComment((v, "record LEFT JOIN hit")); - 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; - sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn); - pRJ->addrSubrtn = 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; jnBase; j++, pTerm++){ - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - testcase( pTerm->wtFlags & TERM_CODED ); - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ - assert( pWInfo->untestedTerms ); - continue; - } - if( pTabItem->fg.jointype & JT_LTORJ ) continue; - assert( pTerm->pExpr ); - sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); - pTerm->wtFlags |= TERM_CODED; - } - } - -#if WHERETRACE_ENABLED /* 0x4001 */ - if( sqlite3WhereTrace & 0x4000 ){ - sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n", - iLevel); - sqlite3WhereClausePrint(pWC); - } - if( sqlite3WhereTrace & 0x1 ){ - sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n", - iLevel, (u64)pLevel->notReady); - } -#endif - return pLevel->notReady; -} - -/* -** Generate the code for the loop that finds all non-matched terms -** for a RIGHT JOIN. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE void 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 *pFrom; - u8 fromSpace[SZ_SRCLIST_1]; - Bitmask mAll = 0; - int k; - - ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName)); - sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, - pRJ->regReturn); - for(k=0; ka[k].pWLoop->iTab == pWInfo->a[k].iFrom ); - pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom]; - mAll |= pWInfo->a[k].pWLoop->maskSelf; - if( pRight->fg.viaCoroutine ){ - Subquery *pSubq; - assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 ); - pSubq = pRight->u4.pSubq; - assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 ); - sqlite3VdbeAddOp3( - v, OP_Null, 0, pSubq->regResult, - pSubq->regResult + pSubq->pSelect->pEList->nExpr-1 - ); - } - sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); - iIdxCur = pWInfo->a[k].iIdxCur; - if( iIdxCur ){ - sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); - } - } - if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){ - mAll |= pLoop->maskSelf; - for(k=0; knTerm; 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 = sqlite3ExprAnd(pParse, pSubWhere, - sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); - } - } - pFrom = (SrcList*)fromSpace; - pFrom->nSrc = 1; - pFrom->nAlloc = 1; - memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem)); - pFrom->a[0].fg.jointype = 0; - assert( pParse->withinRJSubrtn < 100 ); - pParse->withinRJSubrtn++; - pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0, - WHERE_RIGHT_JOIN, 0); - if( pSubWInfo ){ - int iCur = pLevel->iTabCur; - int r = ++pParse->nMem; - int nPk; - int jmp; - int addrCont = sqlite3WhereContinueLabel(pSubWInfo); - Table *pTab = pTabItem->pSTab; - if( HasRowid(pTab) ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r); - nPk = 1; - }else{ - int iPk; - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - nPk = pPk->nKeyCol; - pParse->nMem += nPk - 1; - for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); - } - } - jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); - VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, jmp); - sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn); - sqlite3WhereEnd(pSubWInfo); - } - sqlite3ExprDelete(pParse->db, pSubWhere); - ExplainQueryPlanPop(pParse); - assert( pParse->withinRJSubrtn>0 ); - pParse->withinRJSubrtn--; -} - -/************** End of wherecode.c *******************************************/ -/************** Begin file whereexpr.c ***************************************/ -/* -** 2015-06-08 -** -** 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 module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. -** -** This file was originally part of where.c but was split out to improve -** readability and editability. This file contains utility routines for -** analyzing Expr objects in the WHERE clause. -*/ -/* #include "sqliteInt.h" */ -/* #include "whereInt.h" */ - -/* Forward declarations */ -static void exprAnalyze(SrcList*, WhereClause*, int); - -/* -** Deallocate all memory associated with a WhereOrInfo object. -*/ -static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){ - sqlite3WhereClauseClear(&p->wc); - sqlite3DbFree(db, p); -} - -/* -** Deallocate all memory associated with a WhereAndInfo object. -*/ -static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){ - sqlite3WhereClauseClear(&p->wc); - sqlite3DbFree(db, p); -} - -/* -** Add a single new WhereTerm entry to the WhereClause object pWC. -** The new WhereTerm object is constructed from Expr p and with wtFlags. -** The index in pWC->a[] of the new WhereTerm is returned on success. -** 0 is returned if the new WhereTerm could not be added due to a memory -** allocation error. The memory allocation failure will be recorded in -** the db->mallocFailed flag so that higher-level functions can detect it. -** -** This routine will increase the size of the pWC->a[] array as necessary. -** -** If the wtFlags argument includes TERM_DYNAMIC, then responsibility -** for freeing the expression p is assumed by the WhereClause object pWC. -** This is true even if this routine fails to allocate a new WhereTerm. -** -** WARNING: This routine might reallocate the space used to store -** WhereTerms. All pointers to WhereTerms should be invalidated after -** calling this routine. Such pointers may be reinitialized by referencing -** the pWC->a[] array. -*/ -static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ - WhereTerm *pTerm; - int idx; - testcase( wtFlags & TERM_VIRTUAL ); - if( pWC->nTerm>=pWC->nSlot ){ - WhereTerm *pOld = pWC->a; - sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 ); - if( pWC->a==0 ){ - if( wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, p); - } - pWC->a = pOld; - return 0; - } - memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - 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 = sqlite3LogEst(p->iTable) - 270; - }else{ - pTerm->truthProb = 1; - } - pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p); - pTerm->wtFlags = wtFlags; - pTerm->pWC = pWC; - pTerm->iParent = -1; - memset(&pTerm->eOperator, 0, - sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); - return idx; -} - -/* -** Return TRUE if the given operator is one of the operators that is -** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", "IN", "IS", and "IS NULL" -*/ -static int allowedOp(int op){ - assert( TK_GT>TK_EQ && TK_GTTK_EQ && TK_LTTK_EQ && TK_LETK_GE ) return 0; - if( op>=TK_EQ ) return 1; - return op==TK_IN || op==TK_ISNULL || op==TK_IS; -} - -/* -** Commute a comparison operator. Expressions of the form "X op Y" -** are converted into "Y op X". -*/ -static u16 exprCommute(Parse *pParse, Expr *pExpr){ - if( pExpr->pLeft->op==TK_VECTOR - || pExpr->pRight->op==TK_VECTOR - || sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) != - sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft) - ){ - pExpr->flags ^= EP_Commuted; - } - SWAP(Expr*,pExpr->pRight,pExpr->pLeft); - if( pExpr->op>=TK_GT ){ - assert( TK_LT==TK_GT+2 ); - assert( TK_GE==TK_LE+2 ); - assert( TK_GT>TK_EQ ); - assert( TK_GTop>=TK_GT && pExpr->op<=TK_GE ); - pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; - } - return 0; -} - -/* -** Translate from TK_xx operator to WO_xx bitmask. -*/ -static u16 operatorMask(int op){ - u16 c; - assert( allowedOp(op) ); - if( op>=TK_EQ ){ - assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); - c = (u16)(WO_EQ<<(op-TK_EQ)); - }else if( op==TK_IN ){ - c = WO_IN; - }else if( op==TK_ISNULL ){ - c = WO_ISNULL; - }else{ - assert( op==TK_IS ); - c = WO_IS; - } - assert( op!=TK_ISNULL || c==WO_ISNULL ); - assert( op!=TK_IN || c==WO_IN ); - assert( op!=TK_EQ || c==WO_EQ ); - assert( op!=TK_LT || c==WO_LT ); - assert( op!=TK_LE || c==WO_LE ); - assert( op!=TK_GT || c==WO_GT ); - assert( op!=TK_GE || c==WO_GE ); - assert( op!=TK_IS || c==WO_IS ); - return c; -} - - -#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION -/* -** Check to see if the given expression is a LIKE or GLOB operator that -** can be optimized using inequality constraints. Return TRUE if it is -** so and false if not. -** -** In order for the operator to be optimizible, the RHS must be a string -** literal that does not begin with a wildcard. The LHS must be a column -** that may only be NULL, a string, or a BLOB, never a number. (This means -** that virtual tables cannot participate in the LIKE optimization.) The -** collating sequence for the column on the LHS must be appropriate for -** the operator. -*/ -static int isLikeOrGlob( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* Test this expression */ - Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */ - int *pisComplete, /* True if the only wildcard is % in the last character */ - int *pnoCase /* True if uppercase is equivalent to lowercase */ -){ - const u8 *z = 0; /* String on RHS of LIKE operator */ - Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ - ExprList *pList; /* List of operands to the LIKE operator */ - u8 c; /* One character in z[] */ - int cnt; /* Number of non-wildcard prefix characters */ - u8 wc[4]; /* Wildcard characters */ - sqlite3 *db = pParse->db; /* Database connection */ - sqlite3_value *pVal = 0; - int op; /* Opcode of pRight */ - int rc; /* Result code to return */ - - if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){ - return 0; - } -#ifdef SQLITE_EBCDIC - if( *pnoCase ) return 0; -#endif - assert( ExprUseXList(pExpr) ); - pList = pExpr->x.pList; - pLeft = pList->a[1].pExpr; - - pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); - op = pRight->op; - if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ - Vdbe *pReprepare = pParse->pReprepare; - int iCol = pRight->iColumn; - pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); - if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ - z = sqlite3_value_text(pVal); - } - sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); - assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); - }else if( op==TK_STRING ){ - assert( !ExprHasProperty(pRight, EP_IntValue) ); - z = (u8*)pRight->u.zToken; - } - if( z ){ - /* Count the number of prefix bytes prior to the first wildcard, - ** U+fffd character, or malformed utf-8. If the underlying database - ** has a UTF16LE encoding, then only consider ASCII characters. Note that - ** the encoding of z[] is UTF8 - we are dealing with only UTF8 here in this - ** code, but the database engine itself might be processing content using a - ** different encoding. */ - cnt = 0; - while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ - cnt++; - if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){ - cnt++; - }else if( c>=0x80 ){ - const u8 *z2 = z+cnt-1; - if( c==0xff || sqlite3Utf8Read(&z2)==0xfffd /* bad utf-8 */ - || ENC(db)==SQLITE_UTF16LE - ){ - cnt--; - break; - }else{ - cnt = (int)(z2-z); - } - } - } - - /* The optimization is possible only if (1) the pattern does not begin - ** with a wildcard and if (2) the non-wildcard prefix does not end with - ** an (illegal 0xff) character, or (3) the pattern does not consist of - ** a single escape character. The second condition is necessary so - ** that we can increment the prefix key to find an upper bound for the - ** range search. The third is because the caller assumes that the pattern - ** consists of at least one character after all escapes have been - ** removed. */ - if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){ - Expr *pPrefix; - - /* A "complete" match if the pattern ends with "*" or "%" */ - *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE; - - /* Get the pattern prefix. Remove all escapes from the prefix. */ - pPrefix = sqlite3Expr(db, TK_STRING, (char*)z); - if( pPrefix ){ - int iFrom, iTo; - char *zNew; - assert( !ExprHasProperty(pPrefix, EP_IntValue) ); - zNew = pPrefix->u.zToken; - zNew[cnt] = 0; - for(iFrom=iTo=0; iFrom0 ); - - /* If the LHS is not an ordinary column with TEXT affinity, then the - ** pattern prefix boundaries (both the start and end boundaries) must - ** not look like a number. Otherwise the pattern might be treated as - ** a number, which will invalidate the LIKE optimization. - ** - ** Getting this right has been a persistent source of bugs in the - ** LIKE optimization. See, for example: - ** 2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1 - ** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28 - ** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07 - ** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975 - ** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a - */ - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || (ALWAYS( ExprUseYTab(pLeft) ) - && ALWAYS(pLeft->y.pTab) - && IsVirtual(pLeft->y.pTab)) /* Might be numeric */ - ){ - int isNum; - double rDummy; - isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); - if( isNum<=0 ){ - if( iTo==1 && zNew[0]=='-' ){ - isNum = +1; - }else{ - zNew[iTo-1]++; - isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); - zNew[iTo-1]--; - } - } - if( isNum>0 ){ - sqlite3ExprDelete(db, pPrefix); - sqlite3ValueFree(pVal); - return 0; - } - } - } - *ppPrefix = pPrefix; - - /* If the RHS pattern is a bound parameter, make arrangements to - ** reprepare the statement when that parameter is rebound */ - if( op==TK_VARIABLE ){ - Vdbe *v = pParse->pVdbe; - 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 - ** function, then no OP_Variable will be added to the program. - ** This causes problems for the sqlite3_bind_parameter_name() - ** API. To work around them, add a dummy OP_Variable here. - */ - int r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCodeTarget(pParse, pRight, r1); - sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0); - sqlite3ReleaseTempReg(pParse, r1); - } - } - }else{ - z = 0; - } - } - - rc = (z!=0); - sqlite3ValueFree(pVal); - return rc; -} -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Check to see if the pExpr expression is a form that needs to be passed -** to the xBestIndex method of virtual tables. Forms of interest include: -** -** Expression Virtual Table Operator -** ----------------------- --------------------------------- -** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH -** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB -** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE -** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP -** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE -** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE -** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT -** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT -** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL -** -** In every case, "column" must be a column of a virtual table. If there -** is a match, set *ppLeft to the "column" expression, set *ppRight to the -** "expr" expression (even though in forms (6) and (8) the column is on the -** right and the expression is on the left). Also set *peOp2 to the -** appropriate virtual table operator. The return value is 1 or 2 if there -** is a match. The usual return is 1, but if the RHS is also a column -** of virtual table in forms (5) or (7) then return 2. -** -** If the expression matches none of the patterns above, return 0. -*/ -static int isAuxiliaryVtabOperator( - sqlite3 *db, /* Parsing context */ - Expr *pExpr, /* Test this expression */ - unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ - Expr **ppLeft, /* Column expression to left of MATCH/op2 */ - Expr **ppRight /* Expression to left of MATCH/op2 */ -){ - if( pExpr->op==TK_FUNCTION ){ - static const struct Op2 { - const char *zOp; - unsigned char eOp2; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - ExprList *pList; - Expr *pCol; /* Column reference */ - int i; - - assert( ExprUseXList(pExpr) ); - pList = pExpr->x.pList; - if( pList==0 || pList->nExpr!=2 ){ - return 0; - } - - /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a - ** virtual table on their second argument, which is the same as - ** the left-hand side operand in their in-fix form. - ** - ** vtab_column MATCH expression - ** MATCH(expression,vtab_column) - */ - pCol = pList->a[1].pExpr; - assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) ){ - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; - } - } - } - - /* We can also match against the first column of overloaded - ** functions where xFindFunction returns a value of at least - ** SQLITE_INDEX_CONSTRAINT_FUNCTION. - ** - ** OVERLOADED(vtab_column,expression) - ** - ** Historically, xFindFunction expected to see lower-case function - ** names. But for this use case, xFindFunction is expected to deal - ** with function names in an arbitrary case. - */ - pCol = pList->a[0].pExpr; - assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) ); - assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) ){ - sqlite3_vtab *pVtab; - sqlite3_module *pMod; - void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); - void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; - assert( pVtab!=0 ); - assert( pVtab->pModule!=0 ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pMod = (sqlite3_module *)pVtab->pModule; - if( pMod->xFindFunction!=0 ){ - i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); - if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ - *peOp2 = i; - *ppRight = pList->a[1].pExpr; - *ppLeft = pCol; - return 1; - } - } - } - }else if( pExpr->op>=TK_EQ ){ - /* Comparison operators are a common case. Save a few comparisons for - ** that common case by terminating early. */ - assert( TK_NE < TK_EQ ); - assert( TK_ISNOT < TK_EQ ); - assert( TK_NOTNULL < TK_EQ ); - return 0; - }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ - int res = 0; - Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) ); - if( ExprIsVtab(pLeft) ){ - res++; - } - assert( pRight==0 || pRight->op!=TK_COLUMN - || (ExprUseYTab(pRight) && pRight->y.pTab!=0) ); - if( pRight && ExprIsVtab(pRight) ){ - res++; - SWAP(Expr*, pLeft, pRight); - } - *ppLeft = pLeft; - *ppRight = pRight; - if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE; - if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT; - if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL; - return res; - } - return 0; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** If the pBase expression originated in the ON or USING clause of -** a join, then transfer the appropriate markings over to derived. -*/ -static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ - if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){ - pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON); - pDerived->w.iJoin = pBase->w.iJoin; - } -} - -/* -** Mark term iChild as being a child of term iParent -*/ -static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ - pWC->a[iChild].iParent = iParent; - pWC->a[iChild].truthProb = pWC->a[iParent].truthProb; - pWC->a[iParent].nChild++; -} - -/* -** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not -** a conjunction, then return just pTerm when N==0. If N is exceeds -** the number of available subterms, return NULL. -*/ -static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){ - if( pTerm->eOperator!=WO_AND ){ - return N==0 ? pTerm : 0; - } - if( Nu.pAndInfo->wc.nTerm ){ - return &pTerm->u.pAndInfo->wc.a[N]; - } - return 0; -} - -/* -** Subterms pOne and pTwo are contained within WHERE clause pWC. The -** two subterms are in disjunction - they are OR-ed together. -** -** If these two terms are both of the form: "A op B" with the same -** A and B values but different operators and if the operators are -** compatible (if one is = and the other is <, for example) then -** add a new virtual AND term to pWC that is the combination of the -** two. -** -** Some examples: -** -** x x<=y -** x=y OR x=y --> x=y -** x<=y OR x x<=y -** -** The following is NOT generated: -** -** xy --> x!=y -*/ -static void whereCombineDisjuncts( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* The complete WHERE clause */ - WhereTerm *pOne, /* First disjunct */ - WhereTerm *pTwo /* Second disjunct */ -){ - u16 eOp = pOne->eOperator | pTwo->eOperator; - sqlite3 *db; /* Database connection (for malloc) */ - Expr *pNew; /* New virtual expression */ - 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 - && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; - assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); - assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); - if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; - if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; - /* If we reach this point, it means the two subterms can be combined */ - if( (eOp & (eOp-1))!=0 ){ - if( eOp & (WO_LT|WO_LE) ){ - eOp = WO_LE; - }else{ - assert( eOp & (WO_GT|WO_GE) ); - eOp = WO_GE; - } - } - db = pWC->pWInfo->pParse->db; - pNew = sqlite3ExprDup(db, pOne->pExpr, 0); - if( pNew==0 ) return; - for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; - idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); - exprAnalyze(pSrc, pWC, idxNew); -} - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) -/* -** Analyze a term that consists of two or more OR-connected -** subterms. So in: -** -** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13) -** ^^^^^^^^^^^^^^^^^^^^ -** -** This routine analyzes terms such as the middle term in the above example. -** A WhereOrTerm object is computed and attached to the term under -** analysis, regardless of the outcome of the analysis. Hence: -** -** WhereTerm.wtFlags |= TERM_ORINFO -** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object -** -** The term being analyzed must have two or more of OR-connected subterms. -** A single subterm might be a set of AND-connected sub-subterms. -** Examples of terms under analysis: -** -** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5 -** (B) x=expr1 OR expr2=x OR x=expr3 -** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) -** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') -** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) -** (F) x>A OR (x=A AND y>=B) -** -** CASE 1: -** -** If all subterms are of the form T.C=expr for some single column of C and -** a single table T (as shown in example B above) then create a new virtual -** term that is an equivalent IN expression. In other words, if the term -** being analyzed is: -** -** x = expr1 OR expr2 = x OR x = expr3 -** -** then create a new virtual term like this: -** -** x IN (expr1,expr2,expr3) -** -** CASE 2: -** -** If there are exactly two disjuncts and one side has x>A and the other side -** has x=A (for the same x and A) then add a new virtual conjunct term to the -** WHERE clause of the form "x>=A". Example: -** -** x>A OR (x=A AND y>B) adds: x>=A -** -** The added conjunct can sometimes be helpful in query planning. -** -** CASE 3: -** -** If all subterms are indexable by a single table T, then set -** -** WhereTerm.eOperator = WO_OR -** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T -** -** A subterm is "indexable" if it is of the form -** "T.C " where C is any column of table T and -** is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN". -** A subterm is also indexable if it is an AND of two or more -** subsubterms at least one of which is indexable. Indexable AND -** subterms have their eOperator set to WO_AND and they have -** u.pAndInfo set to a dynamically allocated WhereAndTerm object. -** -** From another point of view, "indexable" means that the subterm could -** potentially be used with an index if an appropriate index exists. -** This analysis does not consider whether or not the index exists; that -** is decided elsewhere. This analysis only looks at whether subterms -** appropriate for indexing exist. -** -** All examples A through E above satisfy case 3. But if a term -** also satisfies case 1 (such as B) we know that the optimizer will -** always prefer case 1, so in that case we pretend that case 3 is not -** satisfied. -** -** It might be the case that multiple tables are indexable. For example, -** (E) above is indexable on tables P, Q, and R. -** -** Terms that satisfy case 3 are candidates for lookup by using -** separate indices to find rowids for each subterm and composing -** the union of all rowids using a RowSet object. This is similar -** to "bitmap indices" in other database engines. -** -** OTHERWISE: -** -** If none of cases 1, 2, or 3 apply, then leave the eOperator set to -** zero. This term is not useful for search. -*/ -static void exprAnalyzeOrTerm( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the complete WHERE clause */ - int idxTerm /* Index of the OR-term to be analyzed */ -){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ - Parse *pParse = pWInfo->pParse; /* Parser context */ - sqlite3 *db = pParse->db; /* Database connection */ - WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ - Expr *pExpr = pTerm->pExpr; /* The expression of the term */ - int i; /* Loop counters */ - WhereClause *pOrWc; /* Breakup of pTerm into subterms */ - WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ - WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ - Bitmask chngToIN; /* Tables that might satisfy case 1 */ - Bitmask indexable; /* Tables that are indexable, satisfying case 2 */ - - /* - ** Break the OR clause into its separate subterms. The subterms are - ** stored in a WhereClause structure containing within the WhereOrInfo - ** object that is attached to the original OR clause term. - */ - assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 ); - assert( pExpr->op==TK_OR ); - pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo)); - if( pOrInfo==0 ) return; - pTerm->wtFlags |= TERM_ORINFO; - pOrWc = &pOrInfo->wc; - memset(pOrWc->aStatic, 0, sizeof(pOrWc->aStatic)); - sqlite3WhereClauseInit(pOrWc, pWInfo); - sqlite3WhereSplit(pOrWc, pExpr, TK_OR); - sqlite3WhereExprAnalyze(pSrc, pOrWc); - if( db->mallocFailed ) return; - assert( pOrWc->nTerm>=2 ); - - /* - ** Compute the set of tables that might satisfy cases 1 or 3. - */ - indexable = ~(Bitmask)0; - chngToIN = ~(Bitmask)0; - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ - if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ - WhereAndInfo *pAndInfo; - assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); - chngToIN = 0; - pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); - if( pAndInfo ){ - WhereClause *pAndWC; - WhereTerm *pAndTerm; - int j; - Bitmask b = 0; - 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)); - sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); - sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); - sqlite3WhereExprAnalyze(pSrc, pAndWC); - pAndWC->pOuter = pWC; - if( !db->mallocFailed ){ - for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ - assert( pAndTerm->pExpr ); - if( allowedOp(pAndTerm->pExpr->op) - || pAndTerm->eOperator==WO_AUX - ){ - b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); - } - } - } - indexable &= b; - } - }else if( pOrTerm->wtFlags & TERM_COPIED ){ - /* Skip this term for now. We revisit it when we process the - ** corresponding TERM_VIRTUAL term */ - }else{ - Bitmask b; - b = sqlite3WhereGetMask(&pWInfo->sMaskSet, pOrTerm->leftCursor); - if( pOrTerm->wtFlags & TERM_VIRTUAL ){ - WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; - b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pOther->leftCursor); - } - indexable &= b; - if( (pOrTerm->eOperator & WO_EQ)==0 ){ - chngToIN = 0; - }else{ - chngToIN &= b; - } - } - } - - /* - ** Record the set of tables that satisfy case 3. The set might be - ** empty. - */ - pOrInfo->indexable = indexable; - pTerm->eOperator = WO_OR; - pTerm->leftCursor = -1; - if( indexable ){ - pWC->hasOr = 1; - } - - /* For a two-way OR, attempt to implementation case 2. - */ - if( indexable && pOrWc->nTerm==2 ){ - int iOne = 0; - WhereTerm *pOne; - while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){ - int iTwo = 0; - WhereTerm *pTwo; - while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){ - whereCombineDisjuncts(pSrc, pWC, pOne, pTwo); - } - } - } - - /* - ** chngToIN holds a set of tables that *might* satisfy case 1. But - ** we have to do some additional checking to see if case 1 really - ** is satisfied. - ** - ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means - ** that there is no possibility of transforming the OR clause into an - ** IN operator because one or more terms in the OR clause contain - ** something other than == on a column in the single table. The 1-bit - ** case means that every term of the OR clause is of the form - ** "table.column=expr" for some single table. The one bit that is set - ** will correspond to the common table. We still need to check to make - ** sure the same column is used on all terms. The 2-bit case is when - ** the all terms are of the form "table1.column=table2.column". It - ** might be possible to form an IN operator with either table1.column - ** or table2.column as the LHS if either is common to every term of - ** the OR clause. - ** - ** Note that terms of the form "table.column1=table.column2" (the - ** same table on both sizes of the ==) cannot be optimized. - */ - if( chngToIN ){ - int okToChngToIN = 0; /* True if the conversion to IN is valid */ - int iColumn = -1; /* Column index on lhs of IN operator */ - int iCursor = -1; /* Table cursor common to all terms */ - int j = 0; /* Loop counter */ - - /* Search for a table and column that appears on one side or the - ** other of the == operator in every subterm. That table and column - ** will be recorded in iCursor and iColumn. There might not be any - ** such table and column. Set okToChngToIN if an appropriate table - ** and column is found but leave okToChngToIN false if not found. - */ - for(j=0; j<2 && !okToChngToIN; j++){ - Expr *pLeft = 0; - pOrTerm = pOrWc->a; - for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); - 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. */ - assert( j==1 ); - continue; - } - if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet, - pOrTerm->leftCursor))==0 ){ - /* This term must be of the form t1.a==t2.b where t2 is in the - ** chngToIN set but t1 is not. This term will be either preceded - ** or followed by an inverted copy (t2.b==t1.a). Skip this term - ** and use its inversion. */ - testcase( pOrTerm->wtFlags & TERM_COPIED ); - testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); - 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; - break; - } - if( i<0 ){ - /* No candidate table+column was found. This can only occur - ** on the second iteration */ - assert( j==1 ); - assert( IsPowerOfTwo(chngToIN) ); - assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) ); - break; - } - testcase( j==1 ); - - /* We have found a candidate table and column. Check to see if that - ** table and column is common to every term in the OR clause */ - 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_OK; - }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR - && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1) - )){ - okToChngToIN = 0; - }else{ - int affLeft, affRight; - /* If the right-hand side is also a column, then the affinities - ** of both right and left sides must be such that no type - ** conversions are required on the right. (Ticket #2249) - */ - affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); - affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); - if( affRight!=0 && affRight!=affLeft ){ - okToChngToIN = 0; - }else{ - pOrTerm->wtFlags |= TERM_OK; - } - } - } - } - - /* At this point, okToChngToIN is true if original pTerm satisfies - ** case 1. In that case, construct a new virtual term that is - ** pTerm converted into an IN operator. - */ - if( okToChngToIN ){ - Expr *pDup; /* A transient duplicate expression */ - ExprList *pList = 0; /* The RHS of the IN operator */ - Expr *pLeft = 0; /* The LHS of the IN operator */ - Expr *pNew; /* The complete IN operator */ - - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - 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 = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); - pLeft = pOrTerm->pExpr->pLeft; - } - assert( pLeft!=0 ); - pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); - if( pNew ){ - int idxNew; - transferJoinMarkings(pNew, pExpr); - 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 reused */ - markTermAsChild(pWC, idxNew, idxTerm); - }else{ - sqlite3ExprListDelete(db, pList); - } - } - } -} -#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ - -/* -** We already know that pExpr is a binary operator where both operands are -** column references. This routine checks to see if pExpr is an equivalence -** relation: -** 1. The SQLITE_Transitive optimization must be enabled -** 2. Must be either an == or an IS operator -** 3. Not originating in the ON clause of an OUTER JOIN -** 4. The operator is not IS or else the query does not contain RIGHT JOIN -** 5. The affinities of A and B must be compatible -** 6a. Both operands use the same collating sequence OR -** 6b. The overall collating sequence is BINARY -** If this routine returns TRUE, that means that the RHS can be substituted -** for the LHS anyplace else in the WHERE clause where the LHS column occurs. -** This is an optimization. No harm comes from returning 0. But if 1 is -** returned when it should not be, then incorrect answers might result. -*/ -static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){ - char aff1, aff2; - CollSeq *pColl; - if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */ - if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */ - if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */ - assert( pSrc!=0 ); - if( pExpr->op==TK_IS - && pSrc->nSrc - && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 - ){ - return 0; /* (4) */ - } - aff1 = sqlite3ExprAffinity(pExpr->pLeft); - aff2 = sqlite3ExprAffinity(pExpr->pRight); - if( aff1!=aff2 - && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2)) - ){ - return 0; /* (5) */ - } - pColl = sqlite3ExprCompareCollSeq(pParse, pExpr); - if( !sqlite3IsBinary(pColl) - && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) - ){ - return 0; /* (6) */ - } - return 1; -} - -/* -** Recursively walk the expressions of a SELECT statement and generate -** a bitmask indicating which tables are used in that expression -** tree. -*/ -static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ - Bitmask mask = 0; - while( pS ){ - SrcList *pSrc = pS->pSrc; - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pEList); - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pGroupBy); - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy); - mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere); - mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving); - if( ALWAYS(pSrc!=0) ){ - int i; - for(i=0; inSrc; i++){ - if( pSrc->a[i].fg.isSubquery ){ - mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect); - } - if( pSrc->a[i].fg.isUsing==0 ){ - mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn); - } - if( pSrc->a[i].fg.isTabFunc ){ - mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); - } - } - } - pS = pS->pPrior; - } - return mask; -} - -/* -** Expression pExpr is one operand of a comparison operator that might -** be useful for indexing. This routine checks to see if pExpr appears -** in any index. Return TRUE (1) if pExpr is an indexed term and return -** FALSE (0) if not. If TRUE is returned, also set aiCurCol[0] to the cursor -** number of the table that is indexed and aiCurCol[1] to the column number -** of the column that is indexed, or XN_EXPR (-2) if an expression is being -** indexed. -** -** If pExpr is a TK_COLUMN column reference, then this routine always returns -** true even if that particular column is not indexed, because the column -** might be added to an automatic index later. -*/ -static SQLITE_NOINLINE int exprMightBeIndexed2( - SrcList *pFrom, /* The FROM clause */ - int *aiCurCol, /* Write the referenced table cursor and column here */ - Expr *pExpr, /* An operand of a comparison operator */ - int j /* Start looking with the j-th pFrom entry */ -){ - Index *pIdx; - int i; - int iCur; - do{ - iCur = pFrom->a[j].iCursor; - for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr==0 ) continue; - for(i=0; inKeyCol; i++){ - if( pIdx->aiColumn[i]!=XN_EXPR ) continue; - assert( pIdx->bHasExpr ); - if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 - && !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr) - ){ - aiCurCol[0] = iCur; - aiCurCol[1] = XN_EXPR; - return 1; - } - } - } - }while( ++j < pFrom->nSrc ); - return 0; -} -static int exprMightBeIndexed( - SrcList *pFrom, /* The FROM clause */ - int *aiCurCol, /* Write the referenced table cursor & column here */ - Expr *pExpr, /* An operand of a comparison operator */ - int op /* The specific comparison operator */ -){ - int i; - - /* If this expression is a vector to the left or right of a - ** inequality constraint (>, <, >= or <=), perform the processing - ** on the first element of the vector. */ - assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); - assert( TK_ISop==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ - assert( ExprUseXList(pExpr) ); - pExpr = pExpr->x.pList->a[0].pExpr; - } - - if( pExpr->op==TK_COLUMN ){ - aiCurCol[0] = pExpr->iTable; - aiCurCol[1] = pExpr->iColumn; - return 1; - } - - for(i=0; inSrc; i++){ - Index *pIdx; - for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr ){ - return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i); - } - } - } - return 0; -} - - -/* -** The input to this routine is an WhereTerm structure with only the -** "pExpr" field filled in. The job of this routine is to analyze the -** subexpression and populate all the other fields of the WhereTerm -** structure. -** -** If the expression is of the form " X" it gets commuted -** to the standard form of "X ". -** -** If the expression is of the form "X Y" where both X and Y are -** columns, then the original expression is unchanged and a new virtual -** term of the form "Y X" is added to the WHERE clause and -** analyzed separately. The original term is marked with TERM_COPIED -** and the new term is marked with TERM_DYNAMIC (because it's pExpr -** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it -** is a commuted copy of a prior term.) The original term has nChild=1 -** and the copy has idxParent set to the index of the original term. -*/ -static void exprAnalyze( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the WHERE clause */ - int idxTerm /* Index of the term to be analyzed */ -){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ - WhereTerm *pTerm; /* The term to be analyzed */ - WhereMaskSet *pMaskSet; /* Set of table index masks */ - Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequisites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequisites of pExpr */ - Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ - Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ - int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ - int noCase = 0; /* uppercase equivalent to lowercase */ - int op; /* Top-level operator. pExpr->op */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - sqlite3 *db = pParse->db; /* Database connection */ - unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */ - int nLeft; /* Number of elements on left side vector */ - - 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 = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); - op = pExpr->op; - if( op==TK_IN ){ - assert( pExpr->pRight==0 ); - if( sqlite3ExprCheckIN(pParse, pExpr) ) return; - if( ExprUseXSelect(pExpr) ){ - pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); - }else{ - pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); - } - prereqAll = prereqLeft | pTerm->prereqRight; - }else{ - pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); - if( pExpr->pLeft==0 - || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow) - || pExpr->x.pList!=0 - ){ - prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); - }else{ - prereqAll = prereqLeft | pTerm->prereqRight; - } - } - if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; - -#ifdef SQLITE_DEBUG - if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){ - printf("\n*** Incorrect prereqAll computed for:\n"); - sqlite3TreeViewExpr(0,pExpr,0); - assert( 0 ); - } -#endif - - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){ - Bitmask x = 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 ){ - 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 ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; - } - ExprClearProperty(pExpr, EP_InnerON); - } - } - pTerm->prereqAll = prereqAll; - pTerm->leftCursor = -1; - pTerm->iParent = -1; - pTerm->eOperator = 0; - if( allowedOp(op) ){ - int aiCurCol[2]; - Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); - u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - - 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, 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, aiCurCol, pRight, op) - && !ExprHasProperty(pRight, EP_FixedCol) - ){ - WhereTerm *pNew; - Expr *pDup; - u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ - assert( pTerm->u.x.iField==0 ); - if( pTerm->leftCursor>=0 ){ - int idxNew; - pDup = sqlite3ExprDup(db, pExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - return; - } - idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); - if( idxNew==0 ) return; - pNew = &pWC->a[idxNew]; - markTermAsChild(pWC, idxNew, idxTerm); - if( op==TK_IS ) pNew->wtFlags |= TERM_IS; - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - assert( pWInfo->pTabList!=0 ); - if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){ - pTerm->eOperator |= WO_EQUIV; - eExtraOp = WO_EQUIV; - } - }else{ - pDup = pExpr; - pNew = pTerm; - } - 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==sqlite3ExprCanBeNull(pLeft) - ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pExpr->op = TK_TRUEFALSE; /* See tag-20230504-1 */ - pExpr->u.zToken = "false"; - ExprSetProperty(pExpr, EP_IsFalse); - pTerm->prereqAll = 0; - pTerm->eOperator = 0; - } - } - -#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION - /* If a term is the BETWEEN operator, create two new virtual terms - ** that define the range that the BETWEEN implements. For example: - ** - ** a BETWEEN b AND c - ** - ** is converted into: - ** - ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c) - ** - ** The two new terms are added onto the end of the WhereClause object. - ** The new terms are "dynamic" and are children of the original BETWEEN - ** term. That means that if the BETWEEN term is coded, the children are - ** skipped. Or, if the children are satisfied by an index, the original - ** BETWEEN term is skipped. - */ - else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ - 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++){ - Expr *pNewExpr; - int idxNew; - pNewExpr = sqlite3PExpr(pParse, ops[i], - sqlite3ExprDup(db, pExpr->pLeft, 0), - sqlite3ExprDup(db, pList->a[i].pExpr, 0)); - transferJoinMarkings(pNewExpr, pExpr); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - exprAnalyze(pSrc, pWC, idxNew); - pTerm = &pWC->a[idxTerm]; - markTermAsChild(pWC, idxNew, idxTerm); - } - } -#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) - /* Analyze a term that is composed of two or more subterms connected by - ** an OR operator. - */ - else if( pExpr->op==TK_OR ){ - assert( pWC->op==TK_AND ); - exprAnalyzeOrTerm(pSrc, pWC, idxTerm); - 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 = sqlite3PExpr(pParse, TK_GT, - sqlite3ExprDup(db, pLeft, 0), - 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 - ** operator. - ** - ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints - ** - ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%' - ** - ** The last character of the prefix "abc" is incremented to form the - ** termination condition "abd". If case is not significant (the default - ** for LIKE) then the lower-bound is made all uppercase and the upper- - ** bound is made all lowercase so that the bounds also work when comparing - ** BLOBs. - */ - else if( pExpr->op==TK_FUNCTION - && pWC->op==TK_AND - && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) - ){ - Expr *pLeft; /* LHS of LIKE/GLOB operator */ - Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ - Expr *pNewExpr1; - Expr *pNewExpr2; - int idxNew1; - int idxNew2; - 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 = 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 - ** the range constraints also work for BLOBs - */ - if( noCase && !pParse->db->mallocFailed ){ - int i; - char c; - pTerm->wtFlags |= TERM_LIKE; - for(i=0; (c = pStr1->u.zToken[i])!=0; i++){ - pStr1->u.zToken[i] = sqlite3Toupper(c); - pStr2->u.zToken[i] = sqlite3Tolower(c); - } - } - - if( !db->mallocFailed ){ - u8 *pC; /* Last character before the first wildcard */ - pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; - if( noCase ){ - /* The point is to increment the last character before the first - ** wildcard. But if we increment '@', that will push it into the - ** alphabetic range where case conversions will mess up the - ** inequality. To avoid this, make sure to also run the full - ** LIKE on all candidate expressions by clearing the isComplete flag - */ - if( *pC=='A'-1 ) isComplete = 0; - *pC = sqlite3UpperToLower[*pC]; - } - - /* Increment the value of the last utf8 character in the prefix. */ - while( *pC==0xBF && pC>(u8*)pStr2->u.zToken ){ - *pC = 0x80; - pC--; - } - assert( *pC!=0xFF ); /* isLikeOrGlob() guarantees this */ - (*pC)++; - } - zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY; - pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, - sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), - pStr1); - transferJoinMarkings(pNewExpr1, pExpr); - idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); - testcase( idxNew1==0 ); - pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr2 = sqlite3PExpr(pParse, TK_LT, - sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), - pStr2); - transferJoinMarkings(pNewExpr2, pExpr); - idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); - testcase( idxNew2==0 ); - exprAnalyze(pSrc, pWC, idxNew1); - exprAnalyze(pSrc, pWC, idxNew2); - pTerm = &pWC->a[idxTerm]; - if( isComplete ){ - markTermAsChild(pWC, idxNew1, idxTerm); - markTermAsChild(pWC, idxNew2, idxTerm); - } - } -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - - /* 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. - ** - ** tag-20220128a - */ - if( (pExpr->op==TK_EQ || pExpr->op==TK_IS) - && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 - && 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; ipLeft, i, nLeft); - Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft); - - pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); - transferJoinMarkings(pNew, pExpr); - 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 = WO_ROWVAL; - } - - /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create - ** a virtual term for each vector component. The expression object - ** used by each such virtual term is pExpr (the full vector IN(...) - ** expression). The WhereTerm.u.x.iField variable identifies the index within - ** the vector on the LHS that the virtual term represents. - ** - ** This only works if the RHS is a simple SELECT (not a compound) that does - ** not use window functions. - */ - else if( pExpr->op==TK_IN - && pTerm->u.x.iField==0 - && pExpr->pLeft->op==TK_VECTOR - && ALWAYS( ExprUseXSelect(pExpr) ) - && (pExpr->x.pSelect->pPrior==0 || (pExpr->x.pSelect->selFlags & SF_Values)) -#ifndef SQLITE_OMIT_WINDOWFUNC - && pExpr->x.pSelect->pWin==0 -#endif - && pWC->op==TK_AND - ){ - int i; - for(i=0; ipLeft); i++){ - int idxNew; - idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE); - pWC->a[idxNew].u.x.iField = i+1; - exprAnalyze(pSrc, pWC, idxNew); - markTermAsChild(pWC, idxNew, idxTerm); - } - } - -#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. - */ - 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 = sqlite3WhereExprUsage(pMaskSet, pRight); - prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); - if( (prereqExpr & prereqColumn)==0 ){ - Expr *pNewExpr; - pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, 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_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. - */ - testcase( pTerm!=&pWC->a[idxTerm] ); - pTerm = &pWC->a[idxTerm]; - pTerm->prereqRight |= extraRight; -} - -/*************************************************************************** -** Routines with file scope above. Interface to the rest of the where.c -** subsystem follows. -***************************************************************************/ - -/* -** This routine identifies subexpressions in the WHERE clause where -** each subexpression is separated by the AND operator or some other -** operator specified in the op parameter. The WhereClause structure -** is filled with pointers to subexpressions. For example: -** -** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) -** \________/ \_______________/ \________________/ -** slot[0] slot[1] slot[2] -** -** The original WHERE clause in pExpr is unaltered. All this routine -** does is make slot[] entries point to substructure within pExpr. -** -** In the previous sentence and in the diagram, "slot[]" refers to -** the WhereClause.a[] array. The slot[] array grows as needed to contain -** all terms of the WHERE clause. -*/ -SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr); - pWC->op = op; - assert( pE2!=0 || pExpr==0 ); - if( pE2==0 ) return; - if( pE2->op!=op ){ - whereClauseInsert(pWC, pExpr, 0); - }else{ - sqlite3WhereSplit(pWC, pE2->pLeft, op); - sqlite3WhereSplit(pWC, pE2->pRight, op); - } -} - -/* -** 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 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; - sqlite3 *db = pParse->db; - Expr *pNew; - int iVal = 0; - - if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){ - Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); - if( pVal==0 ) return; - ExprSetProperty(pVal, EP_IntValue); - pVal->u.iValue = iVal; - pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); - }else{ - Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); - if( pVal==0 ) return; - pVal->iTable = iReg; - pNew = 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 SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){ - assert( p!=0 && p->pLimit!=0 ); /* 1 -- checked by caller */ - if( p->pGroupBy==0 - && (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */ - && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pSTab)) /* 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; iinTerm; 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].nChild ){ - /* If this term has child terms, then they are also part of the - ** pWC->a[] array. So this term can be ignored, as a LIMIT clause - ** will only be added if each of the child terms passes the - ** (leftCursor==iCsr) test below. */ - continue; - } - if( pWC->a[ii].leftCursor!=iCsr ) return; - if( pWC->a[ii].prereqRight!=0 ) return; - } - - /* Check condition (5). Return early if it is not met. */ - if( pOrderBy ){ - for(ii=0; iinExpr; 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 ); - if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){ - whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, - iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); - } - if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){ - whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, - iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); - } - } -} - -/* -** Initialize a preallocated WhereClause structure. -*/ -SQLITE_PRIVATE void sqlite3WhereClauseInit( - WhereClause *pWC, /* The WhereClause to be initialized */ - WhereInfo *pWInfo /* The WHERE processing context */ -){ - pWC->pWInfo = pWInfo; - pWC->hasOr = 0; - pWC->pOuter = 0; - pWC->nTerm = 0; - pWC->nBase = 0; - pWC->nSlot = ArraySize(pWC->aStatic); - pWC->a = pWC->aStatic; -} - -/* -** Deallocate a WhereClause structure. The WhereClause structure -** itself is not freed. This routine is the inverse of -** sqlite3WhereClauseInit(). -*/ -SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ - sqlite3 *db = pWC->pWInfo->pParse->db; - 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; inTerm; i++){ - assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); - } -#endif - while(1){ - assert( a->eMatchOp==0 || a->eOperator==WO_AUX ); - if( a->wtFlags & TERM_DYNAMIC ){ - 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++; - } - } -} - - -/* -** These routines walk (recursively) an expression tree and generate -** a bitmask indicating which tables are used in that expression -** tree. -** -** sqlite3WhereExprUsage(MaskSet, Expr) -> -** -** Return a Bitmask of all tables referenced by Expr. Expr can be -** be NULL, in which case 0 is returned. -** -** sqlite3WhereExprUsageNN(MaskSet, Expr) -> -** -** Same as sqlite3WhereExprUsage() except that Expr must not be -** NULL. The "NN" suffix on the name stands for "Not Null". -** -** 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. -** -** sqlite3WhereExprUsageFull(MaskSet, ExprList) -> -** -** Internal use only. Called only by sqlite3WhereExprUsageNN() for -** complex expressions that require pushing register values onto -** the stack. Many calls to 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. -*/ -static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull( - WhereMaskSet *pMaskSet, - Expr *p -){ - Bitmask mask; - mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; - if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); - if( p->pRight ){ - mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); - assert( p->x.pList==0 ); - }else if( ExprUseXSelect(p) ){ - if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; - mask |= exprSelectUsage(pMaskSet, p->x.pSelect); - }else if( p->x.pList ){ - mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && ExprUseYWin(p) ){ - assert( p->y.pWin!=0 ); - mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition); - mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy); - mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter); - } -#endif - return mask; -} -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ - if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return sqlite3WhereGetMask(pMaskSet, p->iTable); - }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - assert( p->op!=TK_IF_NULL_ROW ); - return 0; - } - return sqlite3WhereExprUsageFull(pMaskSet, p); -} -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ - return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; -} -SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){ - int i; - Bitmask mask = 0; - if( pList ){ - for(i=0; inExpr; i++){ - mask |= sqlite3WhereExprUsage(pMaskSet, pList->a[i].pExpr); - } - } - return mask; -} - - -/* -** Call exprAnalyze on all terms in a WHERE clause. -** -** Note that exprAnalyze() might add new virtual terms onto the -** end of the WHERE clause. We do not want to analyze these new -** virtual terms, so start analyzing at the end and work forward -** so that the added virtual terms are never processed. -*/ -SQLITE_PRIVATE void sqlite3WhereExprAnalyze( - SrcList *pTabList, /* the FROM clause */ - WhereClause *pWC /* the WHERE clause to be analyzed */ -){ - int i; - for(i=pWC->nTerm-1; i>=0; i--){ - exprAnalyze(pTabList, pWC, i); - } -} - -/* -** For table-valued-functions, transform the function arguments into -** new WHERE clause terms. -** -** Each function argument translates into an equality constraint against -** a HIDDEN column in the table. -*/ -SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( - Parse *pParse, /* Parsing context */ - SrcItem *pItem, /* The FROM clause term to process */ - WhereClause *pWC /* Xfer function arguments to here */ -){ - Table *pTab; - int j, k; - ExprList *pArgs; - Expr *pColRef; - Expr *pTerm; - if( pItem->fg.isTabFunc==0 ) return; - pTab = pItem->pSTab; - assert( pTab!=0 ); - pArgs = pItem->u1.pFuncArg; - if( pArgs==0 ) return; - for(j=k=0; jnExpr; j++){ - Expr *pRhs; - u32 joinType; - while( knCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} - if( k>=pTab->nCol ){ - sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", - pTab->zName, j); - return; - } - pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); - if( pColRef==0 ) return; - pColRef->iTable = pItem->iCursor; - pColRef->iColumn = k++; - assert( ExprUseYTab(pColRef) ); - pColRef->y.pTab = pTab; - pItem->colUsed |= sqlite3ExprColUsed(pColRef); - pRhs = sqlite3PExpr(pParse, TK_UPLUS, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); - pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); - if( pItem->fg.jointype & (JT_LEFT|JT_RIGHT) ){ - testcase( pItem->fg.jointype & JT_LEFT ); /* testtag-20230227a */ - testcase( pItem->fg.jointype & JT_RIGHT ); /* testtag-20230227b */ - joinType = EP_OuterON; - }else{ - testcase( pItem->fg.jointype & JT_LTORJ ); /* testtag-20230227c */ - joinType = EP_InnerON; - } - sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); - whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); - } -} - -/************** End of whereexpr.c *******************************************/ -/************** Begin file where.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. This module is responsible for -** generating the code that loops through a table looking for applicable -** rows. Indices are selected and used to speed the search when doing -** so is applicable. Because this module is responsible for selecting -** indices, you might also think of this module as the "query optimizer". -*/ -/* #include "sqliteInt.h" */ -/* #include "whereInt.h" */ - -/* -** Extra information appended to the end of sqlite3_index_info but not -** visible to the xBestIndex function, at least not directly. The -** sqlite3_vtab_collation() interface knows how to reach it, however. -** -** This object is not an API and can be changed from one release to the -** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() -** agree on the structure, all will be well. -*/ -typedef struct HiddenIndexInfo HiddenIndexInfo; -struct HiddenIndexInfo { - WhereClause *pWC; /* The Where clause being analyzed */ - Parse *pParse; /* The parsing context */ - int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ - u32 mIn; /* Mask of terms that are IN (...) */ - u32 mHandleIn; /* Terms that vtab will handle as IN (...) */ - sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST - ** Extra space is allocated to hold up - ** to nTerm such values */ -}; - -/* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as -** many as N constraints */ -#define SZ_HIDDENINDEXINFO(N) \ - (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*)) - -/* Forward declaration of methods */ -static int whereLoopResize(sqlite3*, WhereLoop*, int); - -/* -** Return the estimated number of output rows from a WHERE clause -*/ -SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ - return pWInfo->nRowOut; -} - -/* -** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this -** WHERE clause returns outputs for DISTINCT processing. -*/ -SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ - return pWInfo->eDistinct; -} - -/* -** Return the number of ORDER BY terms that are satisfied by the -** WHERE clause. A return of 0 means that the output must be -** completely sorted. A return equal to the number of ORDER BY -** terms means that no sorting is needed at all. A return that -** is positive but less than the number of ORDER BY terms means that -** block sorting is required. -*/ -SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ - return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat; -} - -/* -** In the ORDER BY LIMIT optimization, if the inner-most loop is known -** to emit rows in increasing order, and if the last row emitted by the -** inner-most loop did not fit within the sorter, then we can skip all -** subsequent rows for the current iteration of the inner loop (because they -** will not fit in the sorter either) and continue with the second inner -** loop - the loop immediately outside the inner-most. -** -** When a row does not fit in the sorter (because the sorter already -** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the -** label returned by this function. -** -** If the ORDER BY LIMIT optimization applies, the jump destination should -** be the continuation for the second-inner-most loop. If the ORDER BY -** LIMIT optimization does not apply, then the jump destination should -** be the continuation for the inner-most loop. -** -** It is always safe for this routine to return the continuation of the -** inner-most loop, in the sense that a correct answer will result. -** Returning the continuation the second inner loop is an optimization -** that might make the code run a little faster, but should not change -** the final answer. -*/ -SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ - WhereLevel *pInner; - if( !pWInfo->bOrderedInnerLoop ){ - /* The ORDER BY LIMIT optimization does not apply. Jump to the - ** continuation of the inner-most loop. */ - return pWInfo->iContinue; - } - pInner = &pWInfo->a[pWInfo->nLevel-1]; - assert( pInner->addrNxt!=0 ); - 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 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 ){ - sqlite3VdbeGoto(v, pInner->addrNxt); - return; - } - } - sqlite3VdbeGoto(v, pWInfo->iBreak); -} - -/* -** Return the VDBE address or label to jump to in order to continue -** immediately with the next row of a WHERE clause. -*/ -SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ - assert( pWInfo->iContinue!=0 ); - return pWInfo->iContinue; -} - -/* -** Return the VDBE address or label to jump to in order to break -** out of a WHERE loop. -*/ -SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ - return pWInfo->iBreak; -} - -/* -** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to -** operate directly on the rowids returned by a WHERE clause. Return -** ONEPASS_SINGLE (1) if the statement can operation directly because only -** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass -** optimization can be used on multiple -** -** If the ONEPASS optimization is used (if this routine returns true) -** then also write the indices of open cursors used by ONEPASS -** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data -** table and iaCur[1] gets the cursor used by an auxiliary index. -** Either value may be -1, indicating that cursor is not used. -** Any cursors returned will have been opened for writing. -** -** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is -** unable to use the ONEPASS optimization. -*/ -SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ - memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ - sqlite3DebugPrintf("%s cursors: %d %d\n", - pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", - aiCur[0], aiCur[1]); - } -#endif - return pWInfo->eOnePass; -} - -/* -** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move -** the data cursor to the row selected by the index cursor. -*/ -SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){ - return pWInfo->bDeferredSeek; -} - -/* -** Move the content of pSrc into pDest -*/ -static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ - pDest->n = pSrc->n; - memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); -} - -/* -** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. -** -** The new entry might overwrite an existing entry, or it might be -** appended, or it might be discarded. Do whatever is the right thing -** so that pSet keeps the N_OR_COST best entries seen so far. -*/ -static int whereOrInsert( - WhereOrSet *pSet, /* The WhereOrSet to be updated */ - Bitmask prereq, /* Prerequisites of the new entry */ - LogEst rRun, /* Run-cost of the new entry */ - LogEst nOut /* Number of outputs for the new entry */ -){ - u16 i; - WhereOrCost *p; - for(i=pSet->n, p=pSet->a; i>0; i--, p++){ - if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ - goto whereOrInsert_done; - } - if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ - return 0; - } - } - if( pSet->na[pSet->n++]; - p->nOut = nOut; - }else{ - p = pSet->a; - for(i=1; in; i++){ - if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; - } - if( p->rRun<=rRun ) return 0; - } -whereOrInsert_done: - p->prereq = prereq; - p->rRun = rRun; - if( p->nOut>nOut ) p->nOut = nOut; - return 1; -} - -/* -** Return the bitmask for the given cursor number. Return 0 if -** iCursor is not in the set. -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ - int i; - assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 ); - assert( iCursor>=-1 ); - if( pMaskSet->ix[0]==iCursor ){ - return 1; - } - for(i=1; in; i++){ - if( pMaskSet->ix[i]==iCursor ){ - return MASKBIT(i); - } - } - return 0; -} - -/* Allocate memory that is automatically freed when pWInfo is freed. -*/ -SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){ - WhereMemBlock *pBlock; - pBlock = 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 *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){ - void *pNew = sqlite3WhereMalloc(pWInfo, nByte); - if( pNew && pOld ){ - WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld; - pOldBlk--; - assert( pOldBlk->szsz); - } - return pNew; -} - -/* -** Create a new mask for cursor iCursor. -** -** There is one cursor per table in the FROM clause. The number of -** tables in the FROM clause is limited by a test early in the -** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[] -** array will never overflow. -*/ -static void createMask(WhereMaskSet *pMaskSet, int iCursor){ - assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); - pMaskSet->ix[pMaskSet->n++] = iCursor; -} - -/* -** If the right-hand branch of the expression is a TK_COLUMN, then return -** a pointer to the right-hand branch. Otherwise, return NULL. -*/ -static Expr *whereRightSubexprIsColumn(Expr *p){ - p = sqlite3ExprSkipCollateAndLikely(p->pRight); - if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return p; - } - return 0; -} - -/* -** Term pTerm is guaranteed to be a WO_IN term. It may be a component term -** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)". -** This function checks to see if the term is compatible with an index -** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so, -** it returns a pointer to the name of the collation sequence (e.g. "BINARY" -** or "NOCASE") used by the comparison in pTerm. If it is not compatible -** with affinity idxaff, NULL is returned. -*/ -static SQLITE_NOINLINE const char *indexInAffinityOk( - Parse *pParse, - WhereTerm *pTerm, - u8 idxaff -){ - Expr *pX = pTerm->pExpr; - Expr inexpr; - - assert( pTerm->eOperator & WO_IN ); - - if( sqlite3ExprIsVector(pX->pLeft) ){ - int iField = pTerm->u.x.iField - 1; - inexpr.flags = 0; - inexpr.op = TK_EQ; - inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr; - assert( ExprUseXSelect(pX) ); - inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr; - pX = &inexpr; - } - - if( sqlite3IndexAffinityOk(pX, idxaff) ){ - CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX); - return pRet ? pRet->zName : sqlite3StrBINARY; - } - return 0; -} - -/* -** Advance to the next WhereTerm that matches according to the criteria -** established when the pScan object was initialized by whereScanInit(). -** Return NULL if there are no more matching WhereTerms. -*/ -static WhereTerm *whereScanNext(WhereScan *pScan){ - int iCur; /* The cursor on the LHS of the term */ - i16 iColumn; /* The column on the LHS of the term. -1 for IPK */ - Expr *pX; /* An expression being tested */ - WhereClause *pWC; /* Shorthand for pScan->pWC */ - WhereTerm *pTerm; /* The term being tested */ - int k = pScan->k; /* Where to start scanning */ - - assert( pScan->iEquiv<=pScan->nEquiv ); - pWC = pScan->pWC; - while(1){ - iColumn = pScan->aiColumn[pScan->iEquiv-1]; - iCur = pScan->aiCur[pScan->iEquiv-1]; - assert( pWC!=0 ); - assert( iCur>=0 ); - do{ - for(pTerm=pWC->a+k; knTerm; 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 - || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, - pScan->pIdxExpr,iCur)==0) - && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON)) - ){ - if( (pTerm->eOperator & WO_EQUIV)!=0 - && pScan->nEquivaiCur) - && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0 - ){ - int j; - for(j=0; jnEquiv; j++){ - if( pScan->aiCur[j]==pX->iTable - && pScan->aiColumn[j]==pX->iColumn ){ - break; - } - } - if( j==pScan->nEquiv ){ - pScan->aiCur[j] = pX->iTable; - pScan->aiColumn[j] = pX->iColumn; - pScan->nEquiv++; - } - } - if( (pTerm->eOperator & pScan->opMask)!=0 ){ - /* Verify the affinity and collating sequence match */ - if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - const char *zCollName; - Parse *pParse = pWC->pWInfo->pParse; - pX = pTerm->pExpr; - - if( (pTerm->eOperator & WO_IN) ){ - zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff); - if( !zCollName ) continue; - }else{ - CollSeq *pColl; - if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ - continue; - } - assert(pX->pLeft); - pColl = sqlite3ExprCompareCollSeq(pParse, pX); - zCollName = pColl ? pColl->zName : sqlite3StrBINARY; - } - - if( sqlite3StrICmp(zCollName, pScan->zCollName) ){ - continue; - } - } - if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 - && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0)) - && pX->op==TK_COLUMN - && pX->iTable==pScan->aiCur[0] - && pX->iColumn==pScan->aiColumn[0] - ){ - testcase( pTerm->eOperator & WO_IS ); - continue; - } - pScan->pWC = pWC; - pScan->k = k+1; -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x20000 ){ - int ii; - sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d", - pTerm, pScan->nEquiv); - for(ii=0; iinEquiv; ii++){ - sqlite3DebugPrintf(" {%d:%d}", - pScan->aiCur[ii], pScan->aiColumn[ii]); - } - sqlite3DebugPrintf("\n"); - } -#endif - return pTerm; - } - } - } - pWC = pWC->pOuter; - k = 0; - }while( pWC!=0 ); - if( pScan->iEquiv>=pScan->nEquiv ) break; - pWC = pScan->pOrigWC; - k = 0; - pScan->iEquiv++; - } - return 0; -} - -/* -** This is whereScanInit() for the case of an index on an expression. -** It is factored out into a separate tail-recursion subroutine so that -** the normal whereScanInit() routine, which is a high-runner, does not -** need to push registers onto the stack as part of its prologue. -*/ -static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){ - pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr); - return whereScanNext(pScan); -} - -/* -** Initialize a WHERE clause scanner object. Return a pointer to the -** first match. Return NULL if there are no matches. -** -** The scanner will be searching the WHERE clause pWC. It will look -** for terms of the form "X " where X is column iColumn of table -** iCur. Or if pIdx!=0 then X is column iColumn of index pIdx. pIdx -** must be one of the indexes of table iCur. -** -** The must be one of the operators described by opMask. -** -** If the search is for X and the WHERE clause contains terms of the -** form X=Y then this routine might also return terms of the form -** "Y ". The number of levels of transitivity is limited, -** but is enough to handle most commonly occurring SQL statements. -** -** If X is not the INTEGER PRIMARY KEY then X must be compatible with -** index pIdx. -*/ -static WhereTerm *whereScanInit( - WhereScan *pScan, /* The WhereScan object being initialized */ - WhereClause *pWC, /* The WHERE clause to be scanned */ - int iCur, /* Cursor to scan for */ - int iColumn, /* Column to scan for */ - u32 opMask, /* Operator(s) to scan for */ - Index *pIdx /* Must be compatible with this index */ -){ - pScan->pOrigWC = pWC; - pScan->pWC = pWC; - pScan->pIdxExpr = 0; - pScan->idxaff = 0; - pScan->zCollName = 0; - pScan->opMask = opMask; - pScan->k = 0; - pScan->aiCur[0] = iCur; - pScan->nEquiv = 1; - pScan->iEquiv = 1; - if( pIdx ){ - int j = iColumn; - iColumn = pIdx->aiColumn[j]; - 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; - } - pScan->aiColumn[0] = iColumn; - return whereScanNext(pScan); -} - -/* -** Search for a term in the WHERE clause that is of the form "X " -** where X is a reference to the iColumn of table iCur or of index pIdx -** if pIdx!=0 and is one of the WO_xx operator codes specified by -** the op parameter. Return a pointer to the term. Return 0 if not found. -** -** If pIdx!=0 then it must be one of the indexes of table iCur. -** Search for terms matching the iColumn-th column of pIdx -** rather than the iColumn-th column of table iCur. -** -** The term returned might by Y= if there is another constraint in -** the WHERE clause that specifies that X=Y. Any such constraints will be -** identified by the WO_EQUIV bit in the pTerm->eOperator field. The -** aiCur[]/iaColumn[] arrays hold X and all its equivalents. There are 11 -** slots in aiCur[]/aiColumn[] so that means we can look for X plus up to 10 -** other equivalent values. Hence a search for X will return if X=A1 -** and A1=A2 and A2=A3 and ... and A9=A10 and A10=. -** -** If there are multiple terms in the WHERE clause of the form "X " -** then try for the one with no dependencies on - in other words where -** is a constant expression of some kind. Only return entries of -** the form "X Y" where Y is a column in another table if no terms of -** the form "X " exist. If no terms with a constant RHS -** exist, try to return a term that does not use WO_EQUIV. -*/ -SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -){ - WhereTerm *pResult = 0; - WhereTerm *p; - WhereScan scan; - - p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); - op &= WO_EQ|WO_IS; - while( p ){ - if( (p->prereqRight & notReady)==0 ){ - if( p->prereqRight==0 && (p->eOperator&op)!=0 ){ - testcase( p->eOperator & WO_IS ); - return p; - } - if( pResult==0 ) pResult = p; - } - p = whereScanNext(&scan); - } - return pResult; -} - -/* -** This function searches pList for an entry that matches the iCol-th column -** of index pIdx. -** -** If such an expression is found, its index in pList->a[] is returned. If -** no expression is found, -1 is returned. -*/ -static int findIndexCol( - Parse *pParse, /* Parse context */ - ExprList *pList, /* Expression list to search */ - int iBase, /* Cursor for table associated with pIdx */ - Index *pIdx, /* Index to match column of */ - int iCol /* Column of index to match */ -){ - int i; - const char *zColl = pIdx->azColl[iCol]; - - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr); - if( ALWAYS(p!=0) - && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) - && p->iColumn==pIdx->aiColumn[iCol] - && p->iTable==iBase - ){ - CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); - if( 0==sqlite3StrICmp(pColl->zName, zColl) ){ - return i; - } - } - } - - return -1; -} - -/* -** Return TRUE if the iCol-th column of index pIdx is NOT NULL -*/ -static int indexColumnNotNull(Index *pIdx, int iCol){ - int j; - assert( pIdx!=0 ); - assert( iCol>=0 && iColnColumn ); - j = pIdx->aiColumn[iCol]; - if( j>=0 ){ - return pIdx->pTable->aCol[j].notNull; - }else if( j==(-1) ){ - return 1; - }else{ - assert( j==(-2) ); - return 0; /* Assume an indexed expression can always yield a NULL */ - - } -} - -/* -** Return true if the DISTINCT expression-list passed as the third argument -** is redundant. -** -** A DISTINCT list is redundant if any subset of the columns in the -** DISTINCT list are collectively unique and individually non-null. -*/ -static int isDistinctRedundant( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* The FROM clause */ - WhereClause *pWC, /* The WHERE clause */ - ExprList *pDistinct /* The result set that needs to be DISTINCT */ -){ - Table *pTab; - Index *pIdx; - int i; - int iBase; - - /* If there is more than one table or sub-select in the FROM clause of - ** this query, then it will not be possible to show that the DISTINCT - ** clause is redundant. */ - if( pTabList->nSrc!=1 ) return 0; - iBase = pTabList->a[0].iCursor; - pTab = pTabList->a[0].pSTab; - - /* If any of the expressions is an IPK column on table iBase, then return - ** true. Note: The (p->iTable==iBase) part of this test may be false if the - ** current SELECT is a correlated sub-query. - */ - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr); - if( NEVER(p==0) ) continue; - 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 - ** the DISTINCT qualifier redundant. It does so if: - ** - ** 1. The index is itself UNIQUE, and - ** - ** 2. All of the columns in the index are either part of the pDistinct - ** list, or else the WHERE clause contains a term of the form "col=X", - ** where X is a constant value. The collation sequences of the - ** comparison and select-list expressions must match those of the index. - ** - ** 3. All of those index columns for which the WHERE clause does not - ** contain a "col=X" term are subject to a NOT NULL constraint. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( !IsUniqueIndex(pIdx) ) continue; - if( pIdx->pPartIdxWhere ) continue; - for(i=0; inKeyCol; i++){ - if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){ - if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break; - if( indexColumnNotNull(pIdx, i)==0 ) break; - } - } - if( i==pIdx->nKeyCol ){ - /* This index implies that the DISTINCT qualifier is redundant. */ - return 1; - } - } - - return 0; -} - - -/* -** Estimate the logarithm of the input value to base 2. -*/ -static LogEst estLog(LogEst N){ - return N<=10 ? 0 : sqlite3LogEst(N) - 33; -} - -/* -** Convert OP_Column opcodes to OP_Copy in previously generated code. -** -** This routine runs over generated VDBE code and translates OP_Column -** opcodes into OP_Copy when the table is being accessed via co-routine -** instead of via table lookup. -** -** If the iAutoidxCur is not zero, then any OP_Rowid instructions on -** cursor iTabCur are transformed into OP_Sequence opcode for the -** iAutoidxCur cursor, in order to generate unique rowids for the -** automatic index being generated. -*/ -static void translateColumnToCopy( - Parse *pParse, /* Parsing context */ - int iStart, /* Translate from this opcode to the end */ - int iTabCur, /* OP_Column/OP_Rowid references to this table */ - int iRegister, /* The first column is in this register */ - int iAutoidxCur /* If non-zero, cursor of autoindex being generated */ -){ - Vdbe *v = pParse->pVdbe; - VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); - int iEnd = sqlite3VdbeCurrentAddr(v); - if( pParse->db->mallocFailed ) return; -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("CHECKING for column-to-copy on cursor %d for %d..%d\n", - iTabCur, iStart, iEnd); - } -#endif - for(; iStartp1!=iTabCur ) continue; - if( pOp->opcode==OP_Column ){ -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart); - } -#endif - pOp->opcode = OP_Copy; - 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 ){ -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart); - } -#endif - pOp->opcode = OP_Sequence; - pOp->p1 = iAutoidxCur; -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( iAutoidxCur==0 ){ - pOp->opcode = OP_Null; - pOp->p3 = 0; - } -#endif - } - } -} - -/* -** Two routines for printing the content of an sqlite3_index_info -** structure. Used for testing and debugging only. If neither -** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines -** are no-ops. -*/ -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) -static void whereTraceIndexInfoInputs( - sqlite3_index_info *p, /* The IndexInfo object */ - Table *pTab /* The TABLE that is the virtual table */ -){ - int i; - if( (sqlite3WhereTrace & 0x10)==0 ) return; - sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName); - for(i=0; inConstraint; i++){ - 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, - sqlite3_vtab_collation(p,i)); - } - for(i=0; inOrderBy; i++){ - sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", - i, - p->aOrderBy[i].iColumn, - p->aOrderBy[i].desc); - } -} -static void whereTraceIndexInfoOutputs( - sqlite3_index_info *p, /* The IndexInfo object */ - Table *pTab /* The TABLE that is the virtual table */ -){ - int i; - if( (sqlite3WhereTrace & 0x10)==0 ) return; - sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName); - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", - i, - p->aConstraintUsage[i].argvIndex, - p->aConstraintUsage[i].omit); - } - sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); - sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); - sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); - sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); - sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); -} -#else -#define whereTraceIndexInfoInputs(A,B) -#define whereTraceIndexInfoOutputs(A,B) -#endif - -/* -** We know that pSrc is an operand of an outer join. Return true if -** pTerm is a constraint that is compatible with that join. -** -** pTerm must be EP_OuterON if pSrc is the right operand of an -** outer join. pTerm can be either EP_OuterON or EP_InnerON if pSrc -** is the left operand of a RIGHT join. -** -** 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. -*/ -static int constraintCompatibleWithOuterJoin( - const WhereTerm *pTerm, /* WHERE clause term to check */ - const SrcItem *pSrc /* Table we are trying to access */ -){ - assert( (pSrc->fg.jointype&(JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ); /* By caller */ - 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; - } - if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0 - && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON)) - ){ - return 0; - } - return 1; -} - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Return true if column iCol of table pTab seem like it might be a -** good column to use as part of a query-time index. -** -** Current algorithm (subject to improvement!): -** -** 1. If iCol is already the left-most column of some other index, -** then return false. -** -** 2. If iCol is part of an existing index that has an aiRowLogEst of -** more than 20, then return false. -** -** 3. If no disqualifying conditions above are found, return true. -** -** 2025-01-03: I experimented with a new rule that returns false if the -** the datatype of the column is "BOOLEAN". This did not improve -** performance on any queries at hand, but it did burn CPU cycles, so the -** idea was not committed. -*/ -static SQLITE_NOINLINE int columnIsGoodIndexCandidate( - const Table *pTab, - int iCol -){ - const Index *pIdx; - for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){ - int j; - for(j=0; jnKeyCol; j++){ - if( pIdx->aiColumn[j]==iCol ){ - if( j==0 ) return 0; - if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0; - break; - } - } - } - return 1; -} -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - - - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Return TRUE if the WHERE clause term pTerm is of a form where it -** could be used with an index to access pSrc, assuming an appropriate -** index existed. -*/ -static int termCanDriveIndex( - 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; - int leftCol; - - if( pTerm->leftCursor!=pSrc->iCursor ) return 0; - if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; - assert( (pSrc->fg.jointype & JT_RIGHT)==0 ); - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) - ){ - return 0; /* See https://sqlite.org/forum/forumpost/51e6959f61 */ - } - if( (pTerm->prereqRight & notReady)!=0 ) return 0; - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - leftCol = pTerm->u.x.leftColumn; - if( leftCol<0 ) return 0; - aff = pSrc->pSTab->aCol[leftCol].affinity; - if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; - testcase( pTerm->pExpr->op==TK_IS ); - return columnIsGoodIndexCandidate(pSrc->pSTab, leftCol); -} -#endif - - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Argument pIdx represents an automatic index that the current statement -** will create and populate. Add an OP_Explain with text of the form: -** -** CREATE AUTOMATIC INDEX ON
    () [WHERE ] -** -** This is only required if sqlite3_stmt_scanstatus() is enabled, to -** associate an SQLITE_SCANSTAT_NCYCLE and SQLITE_SCANSTAT_NLOOP -** values with. In order to avoid breaking legacy code and test cases, -** the OP_Explain is not added if this is an EXPLAIN QUERY PLAN command. -*/ -static void explainAutomaticIndex( - Parse *pParse, - Index *pIdx, /* Automatic index to explain */ - int bPartial, /* True if pIdx is a partial index */ - int *pAddrExplain /* OUT: Address of OP_Explain */ -){ - if( IS_STMT_SCANSTATUS(pParse->db) && pParse->explain!=2 ){ - Table *pTab = pIdx->pTable; - const char *zSep = ""; - char *zText = 0; - int ii = 0; - sqlite3_str *pStr = sqlite3_str_new(pParse->db); - sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName); - assert( pIdx->nColumn>1 ); - assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) ); - for(ii=0; ii<(pIdx->nColumn-1); ii++){ - const char *zName = 0; - int iCol = pIdx->aiColumn[ii]; - - zName = pTab->aCol[iCol].zCnName; - sqlite3_str_appendf(pStr, "%s%s", zSep, zName); - zSep = ", "; - } - zText = sqlite3_str_finish(pStr); - if( zText==0 ){ - sqlite3OomFault(pParse->db); - }else{ - *pAddrExplain = sqlite3VdbeExplain( - pParse, 0, "%s)%s", zText, (bPartial ? " WHERE " : "") - ); - sqlite3_free(zText); - } - } -} -#else -# define explainAutomaticIndex(a,b,c,d) -#endif - -/* -** Generate code to construct the Index object for an automatic index -** and to set up the WhereLevel object pLevel so that the code generator -** makes use of the automatic index. -*/ -static SQLITE_NOINLINE void constructAutomaticIndex( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - 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 */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - WhereTerm *pWCEnd; /* End of pWC->a[] */ - Index *pIdx; /* Object describing the transient index */ - Vdbe *v; /* Prepared statement under construction */ - int addrInit; /* Address of the initialization bypass jump */ - Table *pTable; /* The table being indexed */ - int addrTop; /* Top of the index fill loop */ - int regRecord; /* Register holding an index record */ - int n; /* Column counter */ - int i; /* Loop counter */ - int mxBitCol; /* Maximum column in pSrc->colUsed */ - CollSeq *pColl; /* Collating sequence to on a column */ - WhereLoop *pLoop; /* The Loop object */ - char *zNotUsed; /* Extra space on the end of pIdx */ - Bitmask idxCols; /* Bitmap of columns used for indexing */ - Bitmask extraCols; /* Bitmap of additional columns */ - u8 sentWarning = 0; /* True if a warning has been issued */ - u8 useBloomFilter = 0; /* True to also add a Bloom filter */ - Expr *pPartial = 0; /* Partial Index Expression */ - int iContinue = 0; /* Jump here to skip excluded rows */ - SrcList *pTabList; /* The complete FROM clause */ - SrcItem *pSrc; /* The FROM clause term to get the next index */ - int addrCounter = 0; /* Address where integer counter is initialized */ - int regBase; /* Array of registers where record is assembled */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExp = 0; /* Address of OP_Explain */ -#endif - - /* Generate code to skip over the creation and initialization of the - ** transient index on 2nd and subsequent iterations of the loop. */ - v = pParse->pVdbe; - assert( v!=0 ); - addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - - /* Count the number of columns that will be added to the index - ** and used to match WHERE clause constraints */ - nKeyCol = 0; - pTabList = pWC->pWInfo->pTabList; - pSrc = &pTabList->a[pLevel->iFrom]; - pTable = pSrc->pSTab; - pWCEnd = &pWC->a[pWC->nTerm]; - pLoop = pLevel->pWLoop; - idxCols = 0; - for(pTerm=pWC->a; pTermpExpr; - /* 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 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0) - ){ - pPartial = sqlite3ExprAnd(pParse, pPartial, - sqlite3ExprDup(pParse->db, pExpr, 0)); - } - if( termCanDriveIndex(pTerm, pSrc, notReady) ){ - 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 ){ - sqlite3_log(SQLITE_WARNING_AUTOINDEX, - "automatic index on %s(%s)", pTable->zName, - pTable->aCol[iCol].zCnName); - sentWarning = 1; - } - if( (idxCols & cMask)==0 ){ - if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){ - goto end_auto_index_create; - } - pLoop->aLTerm[nKeyCol++] = pTerm; - idxCols |= cMask; - } - } - } - 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; - - /* Count the number of additional columns needed to create a - ** covering index. A "covering index" is an index that contains all - ** columns that are needed by the query. With a covering index, the - ** original table never needs to be accessed. Automatic indices must - ** be a covering index because the index will not be updated if the - ** original table changes and the index and table cannot both be used - ** if they go out of sync. - */ - if( IsView(pTable) ){ - extraCols = ALLBITS & ~idxCols; - }else{ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); - } - if( !HasRowid(pTable) ){ - /* For WITHOUT ROWID tables, ensure that all PRIMARY KEY columns are - ** either in the idxCols mask or in the extraCols mask */ - for(i=0; inCol; i++){ - if( (pTable->aCol[i].colFlags & COLFLAG_PRIMKEY)==0 ) continue; - if( i>=BMS-1 ){ - extraCols |= MASKBIT(BMS-1); - break; - } - if( idxCols & MASKBIT(i) ) continue; - extraCols |= MASKBIT(i); - } - } - mxBitCol = MIN(BMS-1,pTable->nCol); - testcase( pTable->nCol==BMS-1 ); - testcase( pTable->nCol==BMS-2 ); - for(i=0; icolUsed & MASKBIT(BMS-1) ){ - nKeyCol += pTable->nCol - BMS + 1; - } - - /* Construct the Index object to describe this index */ - assert( nKeyCol <= pTable->nCol + MAX(0, pTable->nCol - BMS + 1) ); - /* ^-- This guarantees that the number of index columns will fit in the u16 */ - pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable), - 0, &zNotUsed); - if( pIdx==0 ) goto end_auto_index_create; - pLoop->u.btree.pIndex = pIdx; - pIdx->zName = "auto-index"; - pIdx->pTable = pTable; - n = 0; - idxCols = 0; - for(pTerm=pWC->a; pTermeOperator & (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 ){ - Expr *pX = pTerm->pExpr; - idxCols |= cMask; - pIdx->aiColumn[n] = pTerm->u.x.leftColumn; - pColl = sqlite3ExprCompareCollSeq(pParse, pX); - assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ - pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; - n++; - if( ALWAYS(pX->pLeft!=0) - && sqlite3ExprAffinity(pX->pLeft)!=SQLITE_AFF_TEXT - ){ - /* TUNING: only use a Bloom filter on an automatic index - ** if one or more key columns has the ability to hold numeric - ** values, since strings all have the same hash in the Bloom - ** filter implementation and hence a Bloom filter on a text column - ** is not usually helpful. */ - useBloomFilter = 1; - } - } - } - } - assert( (u32)n==pLoop->u.btree.nEq ); - - /* Add additional columns needed to make the automatic index into - ** a covering index */ - for(i=0; iaiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; - } - } - if( pSrc->colUsed & MASKBIT(BMS-1) ){ - for(i=BMS-1; inCol; i++){ - pIdx->aiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; - } - } - assert( n==nKeyCol ); - if( HasRowid(pTable) ){ - pIdx->aiColumn[n] = XN_ROWID; - pIdx->azColl[n] = sqlite3StrBINARY; - } - - /* Create the automatic index */ - explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp); - assert( pLevel->iIdxCur>=0 ); - pLevel->iIdxCur = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "for %s", pTable->zName)); - if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) && useBloomFilter ){ - sqlite3WhereExplainBloomFilter(pParse, pWC->pWInfo, pLevel); - pLevel->regFilter = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter); - } - - /* Fill the automatic index with content */ - assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] ); - if( pSrc->fg.viaCoroutine ){ - int regYield; - Subquery *pSubq; - assert( pSrc->fg.isSubquery ); - pSubq = pSrc->u4.pSubq; - assert( pSubq!=0 ); - regYield = pSubq->regReturn; - addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); - VdbeCoverage(v); - VdbeComment((v, "next row of %s", pSrc->pSTab->zName)); - }else{ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); - } - if( pPartial ){ - iContinue = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL); - pLoop->wsFlags |= WHERE_PARTIALIDX; - } - regRecord = sqlite3GetTempReg(pParse); - regBase = sqlite3GenerateIndexKey( - pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 - ); - if( pLevel->regFilter ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, - regBase, pLoop->u.btree.nEq); - } - sqlite3VdbeScanStatusCounters(v, addrExp, addrExp, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); - if( pSrc->fg.viaCoroutine ){ - assert( pSrc->fg.isSubquery && pSrc->u4.pSubq!=0 ); - sqlite3VdbeChangeP2(v, addrCounter, regBase+n); - testcase( pParse->db->mallocFailed ); - assert( pLevel->iIdxCur>0 ); - translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pSrc->u4.pSubq->regResult, pLevel->iIdxCur); - sqlite3VdbeGoto(v, addrTop); - pSrc->fg.viaCoroutine = 0; - }else{ - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); - } - sqlite3VdbeJumpHere(v, addrTop); - sqlite3ReleaseTempReg(pParse, regRecord); - - /* Jump here when skipping the initialization */ - sqlite3VdbeJumpHere(v, addrInit); - sqlite3VdbeScanStatusRange(v, addrExp, addrExp, -1); - -end_auto_index_create: - sqlite3ExprDelete(pParse->db, pPartial); -} -#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 -** 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 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 */ - IndexedExpr *saved_pIdxEpr; /* saved copy of Parse.pIdxEpr */ - IndexedExpr *saved_pIdxPartExpr; /* saved copy of Parse.pIdxPartExpr */ - - saved_pIdxEpr = pParse->pIdxEpr; - saved_pIdxPartExpr = pParse->pIdxPartExpr; - pParse->pIdxEpr = 0; - pParse->pIdxPartExpr = 0; - - assert( pLoop!=0 ); - assert( v!=0 ); - assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ); - - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - do{ - const SrcList *pTabList; - const SrcItem *pItem; - const Table *pTab; - u64 sz; - int iSrc; - sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); - addrCont = 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. - */ - pTabList = pWInfo->pTabList; - iSrc = pLevel->iFrom; - pItem = &pTabList->a[iSrc]; - assert( pItem!=0 ); - pTab = pItem->pSTab; - assert( pTab!=0 ); - sz = sqlite3LogEstToInt(pTab->nRowLogEst); - if( sz<10000 ){ - sz = 10000; - }else if( sz>10000000 ){ - sz = 10000000; - } - sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); - - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; - for(pTerm=pWInfo->sWC.a; pTermpExpr; - if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0) - ){ - sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); - } - } - if( pLoop->wsFlags & WHERE_IPK ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); - sqlite3ReleaseTempReg(pParse, r1); - }else{ - Index *pIdx = pLoop->u.btree.pIndex; - int n = pLoop->u.btree.nEq; - int r1 = sqlite3GetTempRange(pParse, n); - int jj; - for(jj=0; jjpTable==pItem->pSTab ); - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj); - } - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); - sqlite3ReleaseTempRange(pParse, r1, n); - } - sqlite3VdbeResolveLabel(v, addrCont); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); - VdbeCoverage(v); - 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 ); - sqlite3VdbeJumpHere(v, addrOnce); - pParse->pIdxEpr = saved_pIdxEpr; - pParse->pIdxPartExpr = saved_pIdxPartExpr; -} - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Return term iTerm of the WhereClause passed as the first argument. Terms -** are numbered from 0 upwards, starting with the terms in pWC->a[], then -** those in pWC->pOuter->a[] (if any), and so on. -*/ -static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){ - WhereClause *p; - for(p=pWC; p; p=p->pOuter){ - if( iTermnTerm ) return &p->a[iTerm]; - iTerm -= p->nTerm; - } - return 0; -} - -/* -** Allocate and populate an 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 freeIndexInfo(). -*/ -static sqlite3_index_info *allocateIndexInfo( - WhereInfo *pWInfo, /* The WHERE clause */ - WhereClause *pWC, /* The WHERE clause being analyzed */ - Bitmask mUnusable, /* Ignore terms with these prereqs */ - 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 sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_orderby *pIdxOrderBy; - struct sqlite3_index_constraint_usage *pUsage; - struct HiddenIndexInfo *pHidden; - WhereTerm *pTerm; - int nOrderBy; - sqlite3_index_info *pIdxInfo; - u16 mNoOmit = 0; - const Table *pTab; - int eDistinct = 0; - ExprList *pOrderBy = pWInfo->pOrderBy; - WhereClause *p; - - assert( pSrc!=0 ); - pTab = pSrc->pSTab; - 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(p=pWC, nTerm=0; p; p=p->pOuter){ - for(i=0, pTerm=p->a; inTerm; i++, pTerm++){ - pTerm->wtFlags &= ~TERM_OK; - 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_ISNULL ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=XN_ROWID ); - assert( pTerm->u.x.leftColumnnCol ); - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) - ){ - continue; - } - nTerm++; - pTerm->wtFlags |= TERM_OK; - } - } - - /* If the ORDER BY clause contains only columns in the current - ** virtual table then allocate space for the aOrderBy part of - ** the sqlite3_index_info structure. - */ - nOrderBy = 0; - if( pOrderBy ){ - int n = pOrderBy->nExpr; - for(i=0; ia[i].pExpr; - Expr *pE2; - - /* Skip over constant terms in the ORDER BY clause */ - if( sqlite3ExprIsConstant(0, 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->iColumnnCol ); - 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->iColumnnCol ); - pExpr->iColumn = pE2->iColumn; - if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */ - zColl = sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]); - if( zColl==0 ) zColl = sqlite3StrBINARY; - if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; - } - - /* No matches cause a break out of the loop */ - break; - } - if( i==n ){ - nOrderBy = n; - if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ - eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); - }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ - eDistinct = 1; - } - } - } - - /* Allocate the sqlite3_index_info structure - */ - pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) - + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy - + SZ_HIDDENINDEXINFO(nTerm) ); - if( pIdxInfo==0 ){ - sqlite3ErrorMsg(pParse, "out of memory"); - return 0; - } - pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; - pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm]; - pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; - pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - pIdxInfo->aConstraint = pIdxCons; - pIdxInfo->aOrderBy = pIdxOrderBy; - pIdxInfo->aConstraintUsage = pUsage; - pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; - if( HasRowid(pTab)==0 ){ - /* Ensure that all bits associated with PK columns are set. This is to - ** ensure they are available for cases like RIGHT joins or OR loops. */ - Index *pPk = sqlite3PrimaryKeyIndex((Table*)pTab); - assert( pPk!=0 ); - for(i=0; inKeyCol; i++){ - int iCol = pPk->aiColumn[i]; - assert( iCol>=0 ); - if( iCol>=BMS-1 ) iCol = BMS-1; - pIdxInfo->colUsed |= MASKBIT(iCol); - } - } - pHidden->pWC = pWC; - pHidden->pParse = pParse; - pHidden->eDistinct = eDistinct; - pHidden->mIn = 0; - for(p=pWC, i=j=0; p; p=p->pOuter){ - int nLast = i+p->nTerm;; - for(pTerm=p->a; iwtFlags & TERM_OK)==0 ) continue; - pIdxCons[j].iColumn = pTerm->u.x.leftColumn; - pIdxCons[j].iTermOffset = i; - op = pTerm->eOperator & WO_ALL; - 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) ){ - if( op==WO_ISNULL ){ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; - }else{ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; - } - }else{ - pIdxCons[j].op = (u8)op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) ); - - if( op & (WO_LT|WO_LE|WO_GT|WO_GE) - && sqlite3ExprIsVector(pTerm->pExpr->pRight) - ){ - testcase( j!=i ); - if( j<16 ) mNoOmit |= (1 << j); - if( op==WO_LT ) pIdxCons[j].op = WO_LE; - if( op==WO_GT ) pIdxCons[j].op = WO_GE; - } - } - - j++; - } - } - assert( j==nTerm ); - pIdxInfo->nConstraint = j; - for(i=j=0; ia[i].pExpr; - if( sqlite3ExprIsConstant(0, 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 and zero the sqlite3_index_info.idxStr value if needed. -*/ -static void freeIdxStr(sqlite3_index_info *pIdxInfo){ - if( pIdxInfo->needToFreeIdxStr ){ - sqlite3_free(pIdxInfo->idxStr); - pIdxInfo->idxStr = 0; - pIdxInfo->needToFreeIdxStr = 0; - } -} - -/* -** Free an sqlite3_index_info structure allocated by allocateIndexInfo() -** and possibly modified by xBestIndex methods. -*/ -static void freeIndexInfo(sqlite3 *db, 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; inConstraint; i++){ - sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */ - pHidden->aRhs[i] = 0; - } - freeIdxStr(pIdxInfo); - 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 sqlite3_index_info object that -** comes in as the 3rd argument to this function. -** -** If an error occurs, pParse is populated with an error message and an -** appropriate error code is returned. A return of SQLITE_CONSTRAINT from -** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that -** the current configuration of "unusable" flags in sqlite3_index_info can -** not result in a valid plan. -** -** Whether or not an error is returned, it is the responsibility of the -** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates -** that this is required. -*/ -static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ - int rc; - sqlite3_vtab *pVtab; - - assert( IsVirtual(pTab) ); - pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - whereTraceIndexInfoInputs(p, pTab); - pParse->db->nSchemaLock++; - rc = pVtab->pModule->xBestIndex(pVtab, p); - pParse->db->nSchemaLock--; - whereTraceIndexInfoOutputs(p, pTab); - - if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(pParse->db); - }else if( !pVtab->zErrMsg ){ - sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); - }else{ - sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); - } - } - if( pTab->u.vtab.p->bAllSchemas ){ - sqlite3VtabUsesAllSchemas(pParse); - } - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; - return rc; -} -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Estimate the location of a particular key among all keys in an -** index. Store the results in aStat as follows: -** -** aStat[0] Est. number of rows less than pRec -** aStat[1] Est. number of rows equal to pRec -** -** Return the index of the sample that is the smallest sample that -** is greater than or equal to pRec. Note that this index is not an index -** into the aSample[] array - it is an index into a virtual set of samples -** based on the contents of aSample[] and the number of fields in record -** pRec. -*/ -static int whereKeyStats( - Parse *pParse, /* Database connection */ - Index *pIdx, /* Index to consider domain of */ - UnpackedRecord *pRec, /* Vector of values to consider */ - int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ -){ - IndexSample *aSample = pIdx->aSample; - int iCol; /* Index of required stats in anEq[] etc. */ - int i; /* Index of first sample >= pRec */ - int iSample; /* Smallest sample larger than or equal to pRec */ - int iMin = 0; /* Smallest sample not yet tested */ - int iTest; /* Next sample to test */ - int res; /* Result of comparison operation */ - int nField; /* Number of fields in pRec */ - tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ - -#ifndef SQLITE_DEBUG - UNUSED_PARAMETER( pParse ); -#endif - assert( pRec!=0 ); - assert( pIdx->nSample>0 ); - 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 - ** is simply the aSample[] array. If the samples in aSample[] contain more - ** than one fields, all fields following the first are ignored. - ** - ** If pRec contains N fields, where N is more than one, then as well as the - ** samples in aSample[] (truncated to N fields), the search also has to - ** consider prefixes of those samples. For example, if the set of samples - ** in aSample is: - ** - ** aSample[0] = (a, 5) - ** aSample[1] = (a, 10) - ** aSample[2] = (b, 5) - ** aSample[3] = (c, 100) - ** aSample[4] = (c, 105) - ** - ** Then the search space should ideally be the samples above and the - ** unique prefixes [a], [b] and [c]. But since that is hard to organize, - ** the code actually searches this set: - ** - ** 0: (a) - ** 1: (a, 5) - ** 2: (a, 10) - ** 3: (a, 10) - ** 4: (b) - ** 5: (b, 5) - ** 6: (c) - ** 7: (c, 100) - ** 8: (c, 105) - ** 9: (c, 105) - ** - ** For each sample in the aSample[] array, N samples are present in the - ** effective sample array. In the above, samples 0 and 1 are based on - ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. - ** - ** Often, sample i of each block of N effective samples has (i+1) fields. - ** Except, each sample may be extended to ensure that it is greater than or - ** equal to the previous sample in the array. For example, in the above, - ** sample 2 is the first sample of a block of N samples, so at first it - ** appears that it should be 1 field in size. However, that would make it - ** smaller than sample 1, so the binary search would not work. As a result, - ** it is extended to two fields. The duplicates that this creates do not - ** cause any problems. - */ - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nField = pIdx->nKeyCol; - }else{ - nField = pIdx->nColumn; - } - nField = MIN(pRec->nField, nField); - iCol = 0; - iSample = pIdx->nSample * nField; - do{ - int iSamp; /* Index in aSample[] of test sample */ - int n; /* Number of fields in test sample */ - - iTest = (iMin+iSample)/2; - iSamp = iTest / nField; - if( iSamp>0 ){ - /* The proposed effective sample is a prefix of sample aSample[iSamp]. - ** Specifically, the shortest prefix of at least (1 + iTest%nField) - ** fields that is greater than the previous effective sample. */ - for(n=(iTest % nField) + 1; nnField = n; - res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); - if( res<0 ){ - iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; - iMin = iTest+1; - }else if( res==0 && ndb->mallocFailed==0 ){ - if( res==0 ){ - /* If (res==0) is true, then pRec must be equal to sample i. */ - assert( inSample ); - assert( iCol==nField-1 ); - pRec->nField = nField; - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed - ); - }else{ - /* Unless i==pIdx->nSample, indicating that pRec is larger than - ** all samples in the aSample[] array, pRec must be smaller than the - ** (iCol+1) field prefix of sample i. */ - assert( i<=pIdx->nSample && i>=0 ); - pRec->nField = iCol+1; - assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 - || pParse->db->mallocFailed ); - - /* if i==0 and iCol==0, then record pRec is smaller than all samples - ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must - ** be greater than or equal to the (iCol) field prefix of sample i. - ** If (i>0), then pRec must also be greater than sample (i-1). */ - if( iCol>0 ){ - pRec->nField = iCol; - assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 - || pParse->db->mallocFailed || CORRUPT_DB ); - } - if( i>0 ){ - pRec->nField = nField; - assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed || CORRUPT_DB ); - } - } - } -#endif /* ifdef SQLITE_DEBUG */ - - if( res==0 ){ - /* Record pRec is equal to sample i */ - assert( iCol==nField-1 ); - aStat[0] = aSample[i].anLt[iCol]; - aStat[1] = aSample[i].anEq[iCol]; - }else{ - /* At this point, the (iCol+1) field prefix of aSample[i] is the first - ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec - ** is larger than all samples in the array. */ - tRowcnt iUpper, iGap; - if( i>=pIdx->nSample ){ - iUpper = pIdx->nRowEst0; - }else{ - iUpper = aSample[i].anLt[iCol]; - } - - if( iLower>=iUpper ){ - iGap = 0; - }else{ - iGap = iUpper - iLower; - } - if( roundUp ){ - iGap = (iGap*2)/3; - }else{ - iGap = iGap/3; - } - aStat[0] = iLower + iGap; - aStat[1] = pIdx->aAvgEq[nField-1]; - } - - /* Restore the pRec->nField value before returning. */ - pRec->nField = nField; - return i; -} -#endif /* SQLITE_ENABLE_STAT4 */ - -/* -** If it is not NULL, pTerm is a term that provides an upper or lower -** bound on a range scan. Without considering pTerm, it is estimated -** that the scan will visit nNew rows. This function returns the number -** estimated to be visited after taking pTerm into account. -** -** If the user explicitly specified a likelihood() value for this term, -** then the return value is the likelihood multiplied by the number of -** input rows. Otherwise, this function assumes that an "IS NOT NULL" term -** has a likelihood of 0.50, and any other term a likelihood of 0.25. -*/ -static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ - LogEst nRet = nNew; - if( pTerm ){ - if( pTerm->truthProb<=0 ){ - nRet += pTerm->truthProb; - }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){ - nRet -= 20; assert( 20==sqlite3LogEst(4) ); - } - } - return nRet; -} - - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Return the affinity for a single column of an index. -*/ -SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ - assert( iCol>=0 && iColnColumn ); - if( !pIdx->zColAff ){ - if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; - } - assert( pIdx->zColAff[iCol]!=0 ); - return pIdx->zColAff[iCol]; -} -#endif - - -#ifdef SQLITE_ENABLE_STAT4 -/* -** This function is called to estimate the number of rows visited by a -** range-scan on a skip-scan index. For example: -** -** CREATE INDEX i1 ON t1(a, b, c); -** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?; -** -** Value pLoop->nOut is currently set to the estimated number of rows -** visited for scanning (a=? AND b=?). This function reduces that estimate -** by some factor to account for the (c BETWEEN ? AND ?) expression based -** on the stat4 data for the index. this scan will be performed multiple -** times (once for each (a,b) combination that matches a=?) is dealt with -** by the caller. -** -** It does this by scanning through all stat4 samples, comparing values -** extracted from pLower and pUpper with the corresponding column in each -** sample. If L and U are the number of samples found to be less than or -** equal to the values extracted from pLower and pUpper respectively, and -** N is the total number of samples, the pLoop->nOut value is adjusted -** as follows: -** -** nOut = nOut * ( min(U - L, 1) / N ) -** -** If pLower is NULL, or a value cannot be extracted from the term, L is -** set to zero. If pUpper is NULL, or a value cannot be extracted from it, -** U is set to N. -** -** Normally, this function sets *pbDone to 1 before returning. However, -** if no value can be extracted from either pLower or pUpper (and so the -** estimate of the number of rows delivered remains unchanged), *pbDone -** is left as is. -** -** If an error occurs, an SQLite error code is returned. Otherwise, -** SQLITE_OK. -*/ -static int whereRangeSkipScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop, /* Update the .nOut value of this loop */ - int *pbDone /* Set to true if at least one expr. value extracted */ -){ - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - sqlite3 *db = pParse->db; - int nLower = -1; - int nUpper = p->nSample+1; - int rc = SQLITE_OK; - u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); - CollSeq *pColl; - - sqlite3_value *p1 = 0; /* Value extracted from pLower */ - sqlite3_value *p2 = 0; /* Value extracted from pUpper */ - sqlite3_value *pVal = 0; /* Value extracted from record */ - - pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]); - if( pLower ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1); - nLower = 0; - } - if( pUpper && rc==SQLITE_OK ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2); - nUpper = p2 ? 0 : p->nSample; - } - - if( p1 || p2 ){ - int i; - int nDiff; - for(i=0; rc==SQLITE_OK && inSample; i++){ - rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal); - if( rc==SQLITE_OK && p1 ){ - int res = sqlite3MemCompare(p1, pVal, pColl); - if( res>=0 ) nLower++; - } - if( rc==SQLITE_OK && p2 ){ - int res = sqlite3MemCompare(p2, pVal, pColl); - if( res>=0 ) nUpper++; - } - } - nDiff = (nUpper - nLower); - if( nDiff<=0 ) nDiff = 1; - - /* If there is both an upper and lower bound specified, and the - ** comparisons indicate that they are close together, use the fallback - ** method (assume that the scan visits 1/64 of the rows) for estimating - ** the number of rows visited. Otherwise, estimate the number of rows - ** using the method described in the header comment for this function. */ - if( nDiff!=1 || pUpper==0 || pLower==0 ){ - int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff)); - pLoop->nOut -= nAdjust; - *pbDone = 1; - WHERETRACE(0x20, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", - nLower, nUpper, nAdjust*-1, pLoop->nOut)); - } - - }else{ - assert( *pbDone==0 ); - } - - sqlite3ValueFree(p1); - sqlite3ValueFree(p2); - sqlite3ValueFree(pVal); - - return rc; -} -#endif /* SQLITE_ENABLE_STAT4 */ - -/* -** This function is used to estimate the number of rows that will be visited -** by scanning an index for a range of values. The range may have an upper -** bound, a lower bound, or both. The WHERE clause terms that set the upper -** and lower bounds are represented by pLower and pUpper respectively. For -** example, assuming that index p is on t1(a): -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** |_____| |_____| -** | | -** pLower pUpper -** -** If either of the upper or lower bound is not present, then NULL is passed in -** place of the corresponding WhereTerm. -** -** The value in (pBuilder->pNew->u.btree.nEq) is the number of the index -** column subject to the range constraint. Or, equivalently, the number of -** equality constraints optimized by the proposed index scan. For example, -** assuming index p is on t1(a, b), and the SQL query is: -** -** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... -** -** then nEq is set to 1 (as the range restricted column, b, is the second -** left-most column of the index). Or, if the query is: -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** -** then nEq is set to 0. -** -** When this function is called, *pnOut is set to the sqlite3LogEst() of the -** number of rows that the index scan is expected to visit without -** considering the range constraints. If nEq is 0, then *pnOut is the number of -** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) -** to account for the range constraints pLower and pUpper. -** -** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be -** used, a single range inequality reduces the search space by a factor of 4. -** and a pair of constraints (x>? AND x123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ -){ - int rc = SQLITE_OK; - int nOut = pLoop->nOut; - LogEst nNew; - -#ifdef SQLITE_ENABLE_STAT4 - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - - if( p->nSample>0 && ALWAYS(nEqnSampleCol) - && OptimizationEnabled(pParse->db, SQLITE_Stat4) - ){ - if( nEq==pBuilder->nRecValid ){ - UnpackedRecord *pRec = pBuilder->pRec; - tRowcnt a[2]; - int nBtm = pLoop->u.btree.nBtm; - int nTop = pLoop->u.btree.nTop; - - /* Variable iLower will be set to the estimate of the number of rows in - ** the index that are less than the lower bound of the range query. The - ** lower bound being the concatenation of $P and $L, where $P is the - ** key-prefix formed by the nEq values matched against the nEq left-most - ** columns of the index, and $L is the value in pLower. - ** - ** Or, if pLower is NULL or $L cannot be extracted from it (because it - ** is not a simple variable or literal value), the lower bound of the - ** range is $P. Due to a quirk in the way whereKeyStats() works, even - ** if $L is available, whereKeyStats() is called for both ($P) and - ** ($P:$L) and the larger of the two returned values is used. - ** - ** Similarly, iUpper is to be set to the estimate of the number of rows - ** less than the upper bound of the range query. Where the upper bound - ** is either ($P) or ($P:$U). Again, even if $U is available, both values - ** of iUpper are requested of whereKeyStats() and the smaller used. - ** - ** The number of rows between the two bounds is then just iUpper-iLower. - */ - tRowcnt iLower; /* Rows less than the lower bound */ - tRowcnt iUpper; /* Rows less than the upper bound */ - int iLwrIdx = -2; /* aSample[] for the lower bound */ - int iUprIdx = -1; /* aSample[] for the upper bound */ - - if( pRec ){ - testcase( pRec->nField!=pBuilder->nRecValid ); - pRec->nField = pBuilder->nRecValid; - } - /* Determine iLower and iUpper using ($P) only. */ - if( nEq==0 ){ - iLower = 0; - iUpper = p->nRowEst0; - }else{ - /* Note: this call could be optimized away - since the same values must - ** have been requested when testing key $P in whereEqualScanEst(). */ - whereKeyStats(pParse, p, pRec, 0, a); - iLower = a[0]; - iUpper = a[0] + a[1]; - } - - assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 ); - assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); - assert( p->aSortOrder!=0 ); - if( p->aSortOrder[nEq] ){ - /* The roles of pLower and pUpper are swapped for a DESC index */ - SWAP(WhereTerm*, pLower, pUpper); - SWAP(int, nBtm, nTop); - } - - /* If possible, improve on the iLower estimate using ($P:$L). */ - if( pLower ){ - int n; /* Values extracted from pExpr */ - Expr *pExpr = pLower->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n); - if( rc==SQLITE_OK && n ){ - tRowcnt iNew; - u16 mask = WO_GT|WO_LE; - if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); - iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0); - if( iNew>iLower ) iLower = iNew; - nOut--; - pLower = 0; - } - } - - /* If possible, improve on the iUpper estimate using ($P:$U). */ - if( pUpper ){ - int n; /* Values extracted from pExpr */ - Expr *pExpr = pUpper->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n); - if( rc==SQLITE_OK && n ){ - tRowcnt iNew; - u16 mask = WO_GT|WO_LE; - if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); - iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0); - if( iNewpRec = pRec; - if( rc==SQLITE_OK ){ - if( iUpper>iLower ){ - nNew = sqlite3LogEst(iUpper - iLower); - /* TUNING: If both iUpper and iLower are derived from the same - ** sample, then assume they are 4x more selective. This brings - ** the estimated selectivity more in line with what it would be - ** if estimated without the use of STAT4 tables. */ - if( iLwrIdx==iUprIdx ){ nNew -= 20; } - assert( 20==sqlite3LogEst(4) ); - }else{ - nNew = 10; assert( 10==sqlite3LogEst(2) ); - } - if( nNewwtFlags & TERM_VNULL)==0 || pParse->nErr>0 ); - nNew = whereRangeAdjust(pLower, nOut); - nNew = whereRangeAdjust(pUpper, nNew); - - /* TUNING: If there is both an upper and lower limit and neither limit - ** has an application-defined likelihood(), assume the range is - ** reduced by an additional 75%. This means that, by default, an open-ended - ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the - ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to - ** match 1/64 of the index. */ - if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){ - nNew -= 20; - } - - nOut -= (pLower!=0) + (pUpper!=0); - if( nNew<10 ) nNew = 10; - if( nNewnOut>nOut ){ - WHERETRACE(0x20,("Range scan lowers nOut from %d to %d\n", - pLoop->nOut, nOut)); - } -#endif - pLoop->nOut = (LogEst)nOut; - return rc; -} - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Estimate the number of rows that will be returned based on -** an equality constraint x=VALUE and where that VALUE occurs in -** the histogram data. This only works when x is the left-most -** column of an index and sqlite_stat4 histogram data is available -** for that index. When pExpr==NULL that means the constraint is -** "x IS NULL" instead of "x=VALUE". -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereEqualScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - int nEq = pBuilder->pNew->u.btree.nEq; - UnpackedRecord *pRec = pBuilder->pRec; - int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ - int bOk; - - assert( nEq>=1 ); - assert( nEq<=p->nColumn ); - assert( p->aSample!=0 ); - assert( p->nSample>0 ); - assert( pBuilder->nRecValidnRecValid<(nEq-1) ){ - return SQLITE_NOTFOUND; - } - - /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue() - ** below would return the same value. */ - if( nEq>=p->nColumn ){ - *pnRow = 1; - return SQLITE_OK; - } - - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk); - pBuilder->pRec = pRec; - if( rc!=SQLITE_OK ) return rc; - if( bOk==0 ) return SQLITE_NOTFOUND; - pBuilder->nRecValid = nEq; - - whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x20,("equality scan regions %s(%d): %d\n", - p->zName, nEq-1, (int)a[1])); - *pnRow = a[1]; - - return rc; -} -#endif /* SQLITE_ENABLE_STAT4 */ - -#ifdef SQLITE_ENABLE_STAT4 -/* -** Estimate the number of rows that will be returned based on -** an IN constraint where the right-hand side of the IN operator -** is a list of values. Example: -** -** WHERE x IN (1,2,3,4) -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereInScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); - int nRecValid = pBuilder->nRecValid; - int rc = SQLITE_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ - int i; /* Loop counter */ - - assert( p->aSample!=0 ); - for(i=0; rc==SQLITE_OK && inExpr; i++){ - nEst = nRow0; - rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); - nRowEst += nEst; - pBuilder->nRecValid = nRecValid; - } - - if( rc==SQLITE_OK ){ - if( nRowEst > (tRowcnt)nRow0 ) nRowEst = nRow0; - *pnRow = nRowEst; - WHERETRACE(0x20,("IN row estimate: est=%d\n", nRowEst)); - } - assert( pBuilder->nRecValid==nRecValid ); - return rc; -} -#endif /* SQLITE_ENABLE_STAT4 */ - - -#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG) -/* -** Print the content of a WhereTerm object -*/ -SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){ - if( pTerm==0 ){ - sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); - }else{ - char zType[8]; - char zLeft[50]; - memcpy(zType, "....", 5); - if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; - if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; - 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 ); - 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 ){ - sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx", - pTerm->u.pOrInfo->indexable); - }else{ - sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); - } - sqlite3DebugPrintf( - "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x", - iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags); - /* The 0x10000 .wheretrace flag causes extra information to be - ** shown about each Term */ - if( sqlite3WhereTrace & 0x10000 ){ - sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx", - pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight); - } - if( (pTerm->eOperator & (WO_OR|WO_AND))==0 && pTerm->u.x.iField ){ - sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField); - } - if( pTerm->iParent>=0 ){ - sqlite3DebugPrintf(" iParent=%d", pTerm->iParent); - } - sqlite3DebugPrintf("\n"); - sqlite3TreeViewExpr(0, pTerm->pExpr, 0); - } -} -SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){ - sqlite3WhereTermPrint(pTerm, 0); -} -#endif - -#ifdef WHERETRACE_ENABLED -/* -** Show the complete content of a WhereClause -*/ -SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){ - int i; - for(i=0; inTerm; i++){ - sqlite3WhereTermPrint(&pWC->a[i], i); - } -} -#endif - -#ifdef WHERETRACE_ENABLED -/* -** Print a WhereLoop object for debugging purposes -** -** Format example: -** -** .--- Position in WHERE clause rSetup, rRun, nOut ---. -** | | -** | .--- selfMask nTerm ------. | -** | | | | -** | | .-- prereq Idx wsFlags----. | | -** | | | Name | | | -** | | | __|__ nEq ---. ___|__ | __|__ -** | / \ / \ / \ | / \ / \ / \ -** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31 -*/ -SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ - WhereInfo *pWInfo; - if( pWC ){ - pWInfo = pWC->pWInfo; - int nb = 1+(pWInfo->pTabList->nSrc+3)/4; - SrcItem *pItem = pWInfo->pTabList->a + p->iTab; - Table *pTab = pItem->pSTab; - Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; - sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); - sqlite3DebugPrintf(" %12s", - pItem->zAlias ? pItem->zAlias : pTab->zName); - }else{ - pWInfo = 0; - sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d", - p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab); - } - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - const char *zName; - if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ - if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ - int i = sqlite3Strlen30(zName) - 1; - while( zName[i]!='_' ) i--; - zName += i; - } - sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq); - }else{ - sqlite3DebugPrintf("%20s",""); - } - }else{ - char *z; - if( p->u.vtab.idxStr ){ - z = sqlite3_mprintf("(%d,\"%s\",%#x)", - p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); - }else{ - z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); - } - sqlite3DebugPrintf(" %-19s", z); - sqlite3_free(z); - } - if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); - }else{ - sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm); - } - if( pWInfo && pWInfo->bStarUsed && p->rStarDelta!=0 ){ - sqlite3DebugPrintf(" cost %d,%d,%d delta=%d\n", - p->rSetup, p->rRun, p->nOut, p->rStarDelta); - }else{ - sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); - } - if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){ - int i; - for(i=0; inLTerm; i++){ - sqlite3WhereTermPrint(p->aLTerm[i], i); - } - } -} -SQLITE_PRIVATE void sqlite3ShowWhereLoop(const WhereLoop *p){ - if( p ) sqlite3WhereLoopPrint(p, 0); -} -SQLITE_PRIVATE void sqlite3ShowWhereLoopList(const WhereLoop *p){ - while( p ){ - sqlite3ShowWhereLoop(p); - p = p->pNextLoop; - } -} -#endif - -/* -** Convert bulk memory into a valid WhereLoop that can be passed -** to whereLoopClear harmlessly. -*/ -static void whereLoopInit(WhereLoop *p){ - p->aLTerm = p->aLTermSpace; - p->nLTerm = 0; - p->nLSlot = ArraySize(p->aLTermSpace); - p->wsFlags = 0; -} - -/* -** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. -*/ -static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){ - if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){ - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){ - sqlite3_free(p->u.vtab.idxStr); - p->u.vtab.needFree = 0; - p->u.vtab.idxStr = 0; - }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ - sqlite3DbFree(db, p->u.btree.pIndex->zColAff); - sqlite3DbFreeNN(db, p->u.btree.pIndex); - p->u.btree.pIndex = 0; - } - } -} - -/* -** Deallocate internal memory used by a WhereLoop object. Leave the -** object in an initialized state, as if it had been newly allocated. -*/ -static void whereLoopClear(sqlite3 *db, WhereLoop *p){ - if( p->aLTerm!=p->aLTermSpace ){ - sqlite3DbFreeNN(db, p->aLTerm); - p->aLTerm = p->aLTermSpace; - p->nLSlot = ArraySize(p->aLTermSpace); - } - whereLoopClearUnion(db, p); - p->nLTerm = 0; - p->wsFlags = 0; -} - -/* -** Increase the memory allocation for pLoop->aLTerm[] to be at least n. -*/ -static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ - WhereTerm **paNew; - if( p->nLSlot>=n ) return SQLITE_OK; - n = (n+7)&~7; - paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); - if( paNew==0 ) return SQLITE_NOMEM_BKPT; - memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); - if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm); - p->aLTerm = paNew; - p->nLSlot = n; - return SQLITE_OK; -} - -/* -** Transfer content from the second pLoop into the first. -*/ -static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ - whereLoopClearUnion(db, pTo); - if( pFrom->nLTerm > pTo->nLSlot - && whereLoopResize(db, pTo, pFrom->nLTerm) - ){ - memset(pTo, 0, WHERE_LOOP_XFER_SZ); - return SQLITE_NOMEM_BKPT; - } - memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); - memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); - if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ - pFrom->u.vtab.needFree = 0; - }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - pFrom->u.btree.pIndex = 0; - } - return SQLITE_OK; -} - -/* -** Delete a WhereLoop object -*/ -static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ - assert( db!=0 ); - whereLoopClear(db, p); - sqlite3DbNNFreeNN(db, p); -} - -/* -** Free a WhereInfo structure -*/ -static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - assert( pWInfo!=0 ); - assert( db!=0 ); - sqlite3WhereClauseClear(&pWInfo->sWC); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - while( pWInfo->pMemToFree ){ - WhereMemBlock *pNext = pWInfo->pMemToFree->pNext; - sqlite3DbNNFreeNN(db, pWInfo->pMemToFree); - pWInfo->pMemToFree = pNext; - } - sqlite3DbNNFreeNN(db, pWInfo); -} - -/* -** Return TRUE if X is a proper subset of Y but is of equal or less cost. -** In other words, return true if all constraints of X are also part of Y -** and Y has additional constraints that might speed the search that X lacks -** but the cost of running X is not more than the cost of running Y. -** -** In other words, return true if the cost relationship between X and Y -** is inverted and needs to be adjusted. -** -** Case 1: -** -** (1a) X and Y use the same index. -** (1b) X has fewer == terms than Y -** (1c) Neither X nor Y use skip-scan -** (1d) X does not have a a greater cost than Y -** -** Case 2: -** -** (2a) X has the same or lower cost, or returns the same or fewer rows, -** than Y. -** (2b) X uses fewer WHERE clause terms than Y -** (2c) Every WHERE clause term used by X is also used by Y -** (2d) X skips at least as many columns as Y -** (2e) If X is a covering index, than Y is too -*/ -static int whereLoopCheaperProperSubset( - const WhereLoop *pX, /* First WhereLoop to compare */ - const WhereLoop *pY /* Compare against this WhereLoop */ -){ - int i, j; - if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; /* (1d) and (2a) */ - assert( (pX->wsFlags & WHERE_VIRTUALTABLE)==0 ); - assert( (pY->wsFlags & WHERE_VIRTUALTABLE)==0 ); - if( pX->u.btree.nEq < pY->u.btree.nEq /* (1b) */ - && pX->u.btree.pIndex==pY->u.btree.pIndex /* (1a) */ - && pX->nSkip==0 && pY->nSkip==0 /* (1c) */ - ){ - return 1; /* Case 1 is true */ - } - if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ - return 0; /* (2b) */ - } - if( pY->nSkip > pX->nSkip ) return 0; /* (2d) */ - for(i=pX->nLTerm-1; i>=0; i--){ - if( pX->aLTerm[i]==0 ) continue; - for(j=pY->nLTerm-1; j>=0; j--){ - if( pY->aLTerm[j]==pX->aLTerm[i] ) break; - } - if( j<0 ) return 0; /* (2c) */ - } - if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 - && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ - return 0; /* (2e) */ - } - return 1; /* Case 2 is true */ -} - -/* -** 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 -** -** (2) pTemplate costs more than any other WhereLoops for which pTemplate -** is a proper subset. -** -** To say "WhereLoop X is a proper subset of Y" means that X uses fewer -** WHERE clause terms than Y and that every WHERE clause term used by X is -** also used by Y. -*/ -static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ - if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; - for(; p; p=p->pNextLoop){ - if( p->iTab!=pTemplate->iTab ) continue; - if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; - if( whereLoopCheaperProperSubset(p, 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, - 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, - 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); - } - } -} - -/* -** Search the list of WhereLoops in *ppPrev looking for one that can be -** replaced by pTemplate. -** -** Return NULL if pTemplate does not belong on the WhereLoop list. -** In other words if pTemplate ought to be dropped from further consideration. -** -** If pX is a WhereLoop that pTemplate can replace, then return the -** link that points to pX. -** -** If pTemplate cannot replace any existing element of the list but needs -** to be added to the list as a new entry, then return a pointer to the -** tail of the list. -*/ -static WhereLoop **whereLoopFindLesser( - WhereLoop **ppPrev, - const WhereLoop *pTemplate -){ - WhereLoop *p; - for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){ - if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){ - /* If either the iTab or iSortIdx values for two WhereLoop are different - ** then those WhereLoops need to be considered separately. Neither is - ** a candidate to replace the other. */ - continue; - } - /* In the current implementation, the rSetup value is either zero - ** or the cost of building an automatic index (NlogN) and the NlogN - ** is the same for compatible WhereLoops. */ - assert( p->rSetup==0 || pTemplate->rSetup==0 - || p->rSetup==pTemplate->rSetup ); - - /* whereLoopAddBtree() always generates and inserts the automatic index - ** case first. Hence compatible candidate WhereLoops never have a larger - ** rSetup. Call this SETUP-INVARIANT */ - assert( p->rSetup>=pTemplate->rSetup ); - - /* Any loop using an application-defined index (or PRIMARY KEY or - ** UNIQUE constraint) with one or more == constraints is better - ** than an automatic index. Unless it is a skip-scan. */ - if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 - && (pTemplate->nSkip)==0 - && (pTemplate->wsFlags & WHERE_INDEXED)!=0 - && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0 - && (p->prereq & pTemplate->prereq)==pTemplate->prereq - ){ - break; - } - - /* If existing WhereLoop p is better than pTemplate, pTemplate can be - ** discarded. WhereLoop p is better if: - ** (1) p has no more dependencies than pTemplate, and - ** (2) p has an equal or lower cost than pTemplate - */ - if( (p->prereq & pTemplate->prereq)==p->prereq /* (1) */ - && p->rSetup<=pTemplate->rSetup /* (2a) */ - && p->rRun<=pTemplate->rRun /* (2b) */ - && p->nOut<=pTemplate->nOut /* (2c) */ - ){ - return 0; /* Discard pTemplate */ - } - - /* If pTemplate is always better than p, then cause p to be overwritten - ** with pTemplate. pTemplate is better than p if: - ** (1) pTemplate has no more dependencies than p, and - ** (2) pTemplate has an equal or lower cost than p. - */ - if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ - && p->rRun>=pTemplate->rRun /* (2a) */ - && p->nOut>=pTemplate->nOut /* (2b) */ - ){ - assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ - break; /* Cause p to be overwritten by pTemplate */ - } - } - return ppPrev; -} - -/* -** Insert or replace a WhereLoop entry using the template supplied. -** -** An existing WhereLoop entry might be overwritten if the new template -** is better and has fewer dependencies. Or the template will be ignored -** and no insert will occur if an existing WhereLoop is faster and has -** fewer dependencies than the template. Otherwise a new WhereLoop is -** added based on the template. -** -** If pBuilder->pOrSet is not NULL then we care about only the -** prerequisites and rRun and nOut costs of the N best loops. That -** information is gathered in the pBuilder->pOrSet object. This special -** processing mode is used only for OR clause processing. -** -** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we -** still might overwrite similar loops with the new template if the -** new template is better. Loops may be overwritten if the following -** conditions are met: -** -** (1) They have the same iTab. -** (2) They have the same iSortIdx. -** (3) The template has same or fewer dependencies than the current loop -** (4) The template has the same or lower cost than the current loop -*/ -static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ - WhereLoop **ppPrev, *p; - WhereInfo *pWInfo = pBuilder->pWInfo; - sqlite3 *db = pWInfo->pParse->db; - int rc; - - /* Stop the search once we hit the query planner search limit */ - if( pBuilder->iPlanLimit==0 ){ - WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); - if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; - return SQLITE_DONE; - } - pBuilder->iPlanLimit--; - - whereLoopAdjustCost(pWInfo->pLoops, pTemplate); - - /* If pBuilder->pOrSet is defined, then only keep track of the costs - ** and prereqs. - */ - if( pBuilder->pOrSet!=0 ){ - if( pTemplate->nLTerm ){ -#if WHERETRACE_ENABLED - u16 n = pBuilder->pOrSet->n; - int x = -#endif - whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, - pTemplate->nOut); -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - } - return SQLITE_OK; - } - - /* Look for an existing WhereLoop to replace with pTemplate - */ - ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); - - if( ppPrev==0 ){ - /* There already exists a WhereLoop on the list that is better - ** than pTemplate, so just ignore pTemplate */ -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" skip: "); - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - return SQLITE_OK; - }else{ - p = *ppPrev; - } - - /* If we reach this point it means that either p[] should be overwritten - ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new - ** WhereLoop and insert it. - */ -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - if( p!=0 ){ - sqlite3DebugPrintf("replace: "); - sqlite3WhereLoopPrint(p, pBuilder->pWC); - sqlite3DebugPrintf(" with: "); - }else{ - sqlite3DebugPrintf(" add: "); - } - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - if( p==0 ){ - /* Allocate a new WhereLoop to add to the end of the list */ - *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); - if( p==0 ) return SQLITE_NOMEM_BKPT; - whereLoopInit(p); - p->pNextLoop = 0; - }else{ - /* We will be overwriting WhereLoop p[]. But before we do, first - ** go through the rest of the list and delete any other entries besides - ** p[] that are also supplanted by pTemplate */ - WhereLoop **ppTail = &p->pNextLoop; - WhereLoop *pToDel; - while( *ppTail ){ - ppTail = whereLoopFindLesser(ppTail, pTemplate); - if( ppTail==0 ) break; - pToDel = *ppTail; - if( pToDel==0 ) break; - *ppTail = pToDel->pNextLoop; -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" delete: "); - sqlite3WhereLoopPrint(pToDel, pBuilder->pWC); - } -#endif - whereLoopDelete(db, pToDel); - } - } - rc = whereLoopXfer(db, p, pTemplate); - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - Index *pIndex = p->u.btree.pIndex; - if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){ - p->u.btree.pIndex = 0; - } - } - return rc; -} - -/* -** Adjust the WhereLoop.nOut value downward to account for terms of the -** WHERE clause that reference the loop but which are not used by an -** index. -* -** For every WHERE clause term that is not used by the index -** and which has a truth probability assigned by one of the likelihood(), -** likely(), or unlikely() SQL functions, reduce the estimated number -** of output rows by the probability specified. -** -** TUNING: For every WHERE clause term that is not used by the index -** and which does not have an assigned truth probability, heuristics -** described below are used to try to estimate the truth probability. -** TODO --> Perhaps this is something that could be improved by better -** table statistics. -** -** Heuristic 1: Estimate the truth probability as 93.75%. The 93.75% -** value corresponds to -1 in LogEst notation, so this means decrement -** the WhereLoop.nOut field for every such WHERE clause term. -** -** Heuristic 2: If there exists one or more WHERE clause terms of the -** form "x==EXPR" and EXPR is not a constant 0 or 1, then make sure the -** final output row estimate is no greater than 1/4 of the total number -** of rows in the table. In other words, assume that x==EXPR will filter -** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the -** "x" column is boolean or else -1 or 0 or 1 is a common default value -** on the "x" column and so in that case only cap the output row estimate -** at 1/2 instead of 1/4. -*/ -static void whereLoopOutputAdjust( - WhereClause *pWC, /* The WHERE clause */ - WhereLoop *pLoop, /* The loop to adjust downward */ - LogEst nRow /* Number of rows in the entire table */ -){ - WhereTerm *pTerm, *pX; - Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int i, j; - LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ - - assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){ - assert( pTerm!=0 ); - 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; - if( pX==pTerm ) break; - if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; - } - if( j<0 ){ - sqlite3ProgressCheck(pWC->pWInfo->pParse); - 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. */ - pLoop->nOut += pTerm->truthProb; - }else{ - /* In the absence of explicit truth probabilities, use heuristics to - ** guess a reasonable truth probability. */ - pLoop->nOut--; - if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 - && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */ - ){ - Expr *pRight = pTerm->pExpr->pRight; - int k = 0; - testcase( pTerm->pExpr->op==TK_IS ); - if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){ - k = 10; - }else{ - k = 20; - } - if( iReducewtFlags |= TERM_HEURTRUTH; - iReduce = k; - } - } - } - } - } - if( pLoop->nOut > nRow-iReduce ){ - pLoop->nOut = nRow - iReduce; - } -} - -/* -** Term pTerm is a vector range comparison operation. The first comparison -** in the vector can be optimized using column nEq of the index. This -** function returns the total number of vector elements that can be used -** as part of the range comparison. -** -** For example, if the query is: -** -** WHERE a = ? AND (b, c, d) > (?, ?, ?) -** -** and the index: -** -** CREATE INDEX ... ON (a, b, c, d, e) -** -** then this function would be invoked with nEq=1. The value returned in -** this case is 3. -*/ -static int whereRangeVectorLen( - Parse *pParse, /* Parsing context */ - int iCur, /* Cursor open on pIdx */ - Index *pIdx, /* The index to be used for a inequality constraint */ - int nEq, /* Number of prior equality constraints on same index */ - WhereTerm *pTerm /* The vector inequality constraint */ -){ - int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); - int i; - - nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); - for(i=1; ipExpr->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; - } - - /* Check that the LHS of the comparison is a column reference to - ** the right column of the right source table. And that the sort - ** order of the index column is the same as the sort order of the - ** leftmost index column. */ - if( pLhs->op!=TK_COLUMN - || pLhs->iTable!=iCur - || pLhs->iColumn!=pIdx->aiColumn[i+nEq] - || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] - ){ - break; - } - - testcase( pLhs->iColumn==XN_ROWID ); - aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); - idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); - if( aff!=idxaff ) break; - - pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); - if( pColl==0 ) break; - if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; - } - return i; -} - -/* -** Adjust the cost C by the costMult factor T. This only occurs if -** compiled with -DSQLITE_ENABLE_COSTMULT -*/ -#ifdef SQLITE_ENABLE_COSTMULT -# define ApplyCostMultiplier(C,T) C += T -#else -# define ApplyCostMultiplier(C,T) -#endif - -/* -** We have so far matched pBuilder->pNew->u.btree.nEq terms of the -** index pIndex. Try to match one more. -** -** When this function is called, pBuilder->pNew->nOut contains the -** number of rows expected to be visited by filtering using the nEq -** terms only. If it is modified, this value is restored before this -** function returns. -** -** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is -** a fake index used for the INTEGER PRIMARY KEY. -*/ -static int whereLoopAddBtreeIndex( - WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ - SrcItem *pSrc, /* FROM clause term being analyzed */ - Index *pProbe, /* An index on pSrc */ - LogEst nInMul /* log(Number of iterations due to IN) */ -){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyze context */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - sqlite3 *db = pParse->db; /* Database connection malloc context */ - WhereLoop *pNew; /* Template WhereLoop under construction */ - WhereTerm *pTerm; /* A WhereTerm under consideration */ - int opMask; /* Valid operators for constraints */ - WhereScan scan; /* Iterator for WHERE terms */ - Bitmask saved_prereq; /* Original value of pNew->prereq */ - u16 saved_nLTerm; /* Original value of pNew->nLTerm */ - u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ - u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */ - u16 saved_nTop; /* Original value of pNew->u.btree.nTop */ - u16 saved_nSkip; /* Original value of pNew->nSkip */ - u32 saved_wsFlags; /* Original value of pNew->wsFlags */ - LogEst saved_nOut; /* Original value of pNew->nOut */ - int rc = SQLITE_OK; /* Return code */ - LogEst rSize; /* Number of rows in the table */ - LogEst rLogSize; /* Logarithm of table size */ - WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ - - pNew = pBuilder->pNew; - assert( db->mallocFailed==0 || pParse->nErr>0 ); - if( pParse->nErr ){ - return pParse->rc; - } - WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n", - pProbe->pTable->zName,pProbe->zName, - pNew->u.btree.nEq, pNew->nSkip, pNew->rRun)); - - assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); - assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); - if( pNew->wsFlags & WHERE_BTM_LIMIT ){ - opMask = WO_LT|WO_LE; - }else{ - assert( pNew->u.btree.nBtm==0 ); - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; - } - if( pProbe->bUnordered ){ - opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); - } - - assert( pNew->u.btree.nEqnColumn ); - assert( pNew->u.btree.nEqnKeyCol - || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY ); - - saved_nEq = pNew->u.btree.nEq; - saved_nBtm = pNew->u.btree.nBtm; - saved_nTop = pNew->u.btree.nTop; - saved_nSkip = pNew->nSkip; - saved_nLTerm = pNew->nLTerm; - saved_wsFlags = pNew->wsFlags; - saved_prereq = pNew->prereq; - saved_nOut = pNew->nOut; - pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq, - opMask, pProbe); - pNew->rSetup = 0; - rSize = pProbe->aiRowLogEst[0]; - rLogSize = estLog(rSize); - for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ - u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ - LogEst rCostIdx; - LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ - int nIn = 0; -#ifdef SQLITE_ENABLE_STAT4 - int nRecValid = pBuilder->nRecValid; -#endif - if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) - && indexColumnNotNull(pProbe, saved_nEq) - ){ - continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */ - } - if( pTerm->prereqRight & pNew->maskSelf ) continue; - - /* Do not allow the upper bound of a LIKE optimization range constraint - ** to mix with a lower range bound from some other source */ - if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; - - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) - ){ - continue; - } - if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ - pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE; - }else{ - pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED; - } - pNew->wsFlags = saved_wsFlags; - pNew->u.btree.nEq = saved_nEq; - pNew->u.btree.nBtm = saved_nBtm; - pNew->u.btree.nTop = saved_nTop; - pNew->nLTerm = saved_nLTerm; - if( pNew->nLTerm>=pNew->nLSlot - && whereLoopResize(db, pNew, pNew->nLTerm+1) - ){ - break; /* OOM while trying to enlarge the pNew->aLTerm array */ - } - pNew->aLTerm[pNew->nLTerm++] = pTerm; - pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; - - assert( nInMul==0 - || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 - || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 - || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 - ); - - if( eOp & WO_IN ){ - Expr *pExpr = pTerm->pExpr; - if( ExprUseXSelect(pExpr) ){ - /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ - int i; - int bRedundant = 0; - nIn = 46; assert( 46==sqlite3LogEst(25) ); - - /* The expression may actually be of the form (x, y) IN (SELECT...). - ** In this case there is a separate term for each of (x) and (y). - ** However, the nIn multiplier should only be applied once, not once - ** for each such term. The following loop checks that pTerm is the - ** first such term in use, and sets nIn back to 0 if it is not. */ - for(i=0; inLTerm-1; i++){ - if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ){ - nIn = 0; - if( pNew->aLTerm[i]->u.x.iField == pTerm->u.x.iField ){ - /* Detect when two or more columns of an index match the same - ** column of a vector IN operater, and avoid adding the column - ** to the WhereLoop more than once. See tag-20250707-01 - ** in test/rowvalue.test */ - bRedundant = 1; - } - } - } - if( bRedundant ){ - pNew->nLTerm--; - continue; - } - }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ - /* "x IN (value, value, ...)" */ - nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - } - if( pProbe->hasStat1 && rLogSize>=10 ){ - 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 - ** M = the number of rows in the table that match terms to the - ** to the left in the same index. If the IN operator is on - ** the left-most index column, M==N. - ** - ** Given the definitions above, it is better to omit the IN operator - ** from the index lookup and instead do a scan of the M elements, - ** testing each scanned row against the IN operator separately, if: - ** - ** M*log(K) < K*log(N) - ** - ** Our estimates for M, K, and N might be inaccurate, so we build in - ** a safety margin of 2 (LogEst: 10) that favors using the IN operator - ** with the index, as using an index has better worst-case behavior. - ** If we do not have real sqlite_stat1 data, always prefer to use - ** the index. Do not bother with this optimization on very small - ** tables (less than 2 rows) as it is pointless in that case. - */ - M = pProbe->aiRowLogEst[saved_nEq]; - logK = estLog(nIn); - /* 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, - ("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 (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; - }else if( eOp & (WO_EQ|WO_IS) ){ - int iCol = pProbe->aiColumn[saved_nEq]; - pNew->wsFlags |= WHERE_COLUMN_EQ; - assert( saved_nEq==pNew->u.btree.nEq ); - if( iCol==XN_ROWID - || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) - ){ - if( iCol==XN_ROWID || pProbe->uniqNotNull - || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ)) - ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags |= WHERE_UNQ_WANTED; - } - } - if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS; - }else if( eOp & WO_ISNULL ){ - pNew->wsFlags |= WHERE_COLUMN_NULL; - }else{ - int nVecLen = whereRangeVectorLen( - pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm - ); - if( eOp & (WO_GT|WO_GE) ){ - testcase( eOp & WO_GT ); - testcase( eOp & WO_GE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; - pNew->u.btree.nBtm = nVecLen; - pBtm = pTerm; - pTop = 0; - if( pTerm->wtFlags & TERM_LIKEOPT ){ - /* Range constraints that come from the LIKE optimization are - ** always used in pairs. */ - pTop = &pTerm[1]; - assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); - assert( pTop->wtFlags & TERM_LIKEOPT ); - assert( pTop->eOperator==WO_LT ); - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTop; - pNew->wsFlags |= WHERE_TOP_LIMIT; - pNew->u.btree.nTop = 1; - } - }else{ - assert( eOp & (WO_LT|WO_LE) ); - testcase( eOp & WO_LT ); - testcase( eOp & WO_LE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; - pNew->u.btree.nTop = nVecLen; - pTop = pTerm; - pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? - pNew->aLTerm[pNew->nLTerm-2] : 0; - } - } - - /* At this point pNew->nOut is set to the number of rows expected to - ** be visited by the index scan before considering term pTerm, or the - ** values of nIn and nInMul. In other words, assuming that all - ** "x IN(...)" terms are replaced with "x = ?". This block updates - ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ - assert( pNew->nOut==saved_nOut ); - if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - /* Adjust nOut using stat4 data. Or, if there is no stat4 - ** data, using some other estimate. */ - whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); - }else{ - int nEq = ++pNew->u.btree.nEq; - assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) ); - - assert( pNew->nOut==saved_nOut ); - if( pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0 ){ - assert( (eOp & WO_IN) || nIn==0 ); - testcase( eOp & WO_IN ); - pNew->nOut += pTerm->truthProb; - pNew->nOut -= nIn; - }else{ -#ifdef SQLITE_ENABLE_STAT4 - tRowcnt nOut = 0; - if( nInMul==0 - && pProbe->nSample - && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol) - && ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr)) - && OptimizationEnabled(db, SQLITE_Stat4) - ){ - Expr *pExpr = pTerm->pExpr; - if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ - testcase( eOp & WO_EQ ); - testcase( eOp & WO_IS ); - testcase( eOp & WO_ISNULL ); - rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); - }else{ - rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); - } - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ - if( nOut ){ - pNew->nOut = sqlite3LogEst(nOut); - if( nEq==1 - /* TUNING: Mark terms as "low selectivity" if they seem likely - ** to be true for half or more of the rows in the table. - ** See tag-202002240-1 */ - && pNew->nOut+10 > pProbe->aiRowLogEst[0] - ){ -#if WHERETRACE_ENABLED /* 0x01 */ - if( sqlite3WhereTrace & 0x20 ){ - sqlite3DebugPrintf( - "STAT4 determines term has low selectivity:\n"); - sqlite3WhereTermPrint(pTerm, 999); - } -#endif - pTerm->wtFlags |= TERM_HIGHTRUTH; - if( pTerm->wtFlags & TERM_HEURTRUTH ){ - /* If the term has previously been used with an assumption of - ** higher selectivity, then set the flag to rerun the - ** loop computations. */ - pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS; - } - } - if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; - pNew->nOut -= nIn; - } - } - if( nOut==0 ) -#endif - { - pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]); - if( eOp & WO_ISNULL ){ - /* TUNING: If there is no likelihood() value, assume that a - ** "col IS NULL" expression matches twice as many rows - ** as (col=?). */ - pNew->nOut += 10; - } - } - } - } - - /* Set rCostIdx to the estimated cost of visiting selected rows in the - ** index. The estimate is the sum of two values: - ** 1. The cost of doing one search-by-key to find the first matching - ** entry - ** 2. Stepping forward in the index pNew->nOut times to find all - ** additional matching entries. - */ - assert( pSrc->pSTab->szTabRow>0 ); - if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ - /* The pProbe->szIdxRow is low for an IPK table since the interior - ** pages are small. Thus szIdxRow gives a good estimate of seek cost. - ** But the leaf pages are full-size, so pProbe->szIdxRow would badly - ** under-estimate the scanning cost. */ - rCostIdx = pNew->nOut + 16; - }else{ - rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pSTab->szTabRow; - } - rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx); - - /* Estimate the cost of running the loop. If all data is coming - ** from the index, then this is just the cost of doing the index - ** lookup and scan. But if some data is coming out of the main table, - ** we also have to add in the cost of doing pNew->nOut searches to - ** locate the row in the main table that corresponds to the index entry. - */ - pNew->rRun = rCostIdx; - if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){ - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); - } - ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); - - nOutUnadjusted = pNew->nOut; - pNew->rRun += nInMul + nIn; - pNew->nOut += nInMul + nIn; - whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); - rc = whereLoopInsert(pBuilder, pNew); - - if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - pNew->nOut = saved_nOut; - }else{ - pNew->nOut = nOutUnadjusted; - } - - if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 - && pNew->u.btree.nEqnColumn - && (pNew->u.btree.nEqnKeyCol || - pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY) - ){ - if( pNew->u.btree.nEq>3 ){ - sqlite3ProgressCheck(pParse); - } - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); - } - pNew->nOut = saved_nOut; -#ifdef SQLITE_ENABLE_STAT4 - pBuilder->nRecValid = nRecValid; -#endif - } - pNew->prereq = saved_prereq; - pNew->u.btree.nEq = saved_nEq; - pNew->u.btree.nBtm = saved_nBtm; - pNew->u.btree.nTop = saved_nTop; - pNew->nSkip = saved_nSkip; - pNew->wsFlags = saved_wsFlags; - pNew->nOut = saved_nOut; - pNew->nLTerm = saved_nLTerm; - - /* Consider using a skip-scan if there are no WHERE clause constraints - ** available for the left-most terms of the index, and if the average - ** number of repeats in the left-most terms is at least 18. - ** - ** The magic number 18 is selected on the basis that scanning 17 rows - ** is almost always quicker than an index seek (even though if the index - ** contains fewer than 2^17 rows we assume otherwise in other parts of - ** the code). And, even if it is not, it should not be too much slower. - ** On the other hand, the extra seeks could end up being significantly - ** more expensive. */ - assert( 42==sqlite3LogEst(18) ); - if( saved_nEq==saved_nSkip - && saved_nEq+1nKeyCol - && saved_nEq==pNew->nLTerm - && pProbe->noSkipScan==0 - && pProbe->hasStat1!=0 - && OptimizationEnabled(db, SQLITE_SkipScan) - && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ - && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK - ){ - LogEst nIter; - pNew->u.btree.nEq++; - pNew->nSkip++; - pNew->aLTerm[pNew->nLTerm++] = 0; - pNew->wsFlags |= WHERE_SKIPSCAN; - nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; - pNew->nOut -= nIter; - /* TUNING: Because uncertainties in the estimates for skip-scan queries, - ** add a 1.375 fudge factor to make skip-scan slightly less likely. */ - nIter += 5; - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); - pNew->nOut = saved_nOut; - pNew->u.btree.nEq = saved_nEq; - pNew->nSkip = saved_nSkip; - pNew->wsFlags = saved_wsFlags; - } - - WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", - pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); - return rc; -} - -/* -** Return True if it is possible that pIndex might be useful in -** implementing the ORDER BY clause in pBuilder. -** -** Return False if pBuilder does not contain an ORDER BY clause or -** if there is no way for pIndex to be useful in implementing that -** ORDER BY clause. -*/ -static int indexMightHelpWithOrderBy( - WhereLoopBuilder *pBuilder, - Index *pIndex, - int iCursor -){ - ExprList *pOB; - ExprList *aColExpr; - int ii, jj; - - if( pIndex->bUnordered ) return 0; - if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr); - if( NEVER(pExpr==0) ) continue; - if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) - && pExpr->iTable==iCursor - ){ - if( pExpr->iColumn<0 ) return 1; - for(jj=0; jjnKeyCol; jj++){ - if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; - } - }else if( (aColExpr = pIndex->aColExpr)!=0 ){ - for(jj=0; jjnKeyCol; jj++){ - if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ - return 1; - } - } - } - } - return 0; -} - -/* Check to see if a partial index with pPartIndexWhere can be used -** in the current query. Return true if it can be and false if not. -*/ -static int whereUsablePartialIndex( - int iTab, /* The table for which we want an index */ - 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; - - if( jointype & JT_LTORJ ) return 0; - pParse = pWC->pWInfo->pParse; - while( pWhere->op==TK_AND ){ - if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0; - pWhere = pWhere->pRight; - } - for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr; - pExpr = pTerm->pExpr; - if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab) - && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON)) - && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) - && !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1) - && (pTerm->wtFlags & TERM_VNULL)==0 - ){ - return 1; - } - } - return 0; -} - -/* -** pIdx is an index containing expressions. Check it see if any of the -** expressions in the index match the pExpr expression. -*/ -static int exprIsCoveredByIndex( - const Expr *pExpr, - const Index *pIdx, - int iTabCur -){ - int i; - for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]==XN_EXPR - && sqlite3ExprCompare(0, pExpr, pIdx->aColExpr->a[i].pExpr, iTabCur)==0 - ){ - return 1; - } - } - return 0; -} - -/* -** Structure passed to the whereIsCoveringIndex Walker callback. -*/ -typedef struct CoveringIndexCheck CoveringIndexCheck; -struct CoveringIndexCheck { - Index *pIdx; /* The index */ - int iTabCur; /* Cursor number for the corresponding table */ - u8 bExpr; /* Uses an indexed expression */ - u8 bUnidx; /* Uses an unindexed column not within an indexed expr */ -}; - -/* -** Information passed in is pWalk->u.pCovIdxCk. Call it pCk. -** -** If the Expr node references the table with cursor pCk->iTabCur, then -** make sure that column is covered by the index pCk->pIdx. We know that -** all columns less than 63 (really BMS-1) are covered, so we don't need -** to check them. But we do need to check any column at 63 or greater. -** -** If the index does not cover the column, then set pWalk->eCode to -** non-zero and return WRC_Abort to stop the search. -** -** If this node does not disprove that the index can be a covering index, -** then just return WRC_Continue, to continue the search. -** -** If pCk->pIdx contains indexed expressions and one of those expressions -** matches pExpr, then prune the search. -*/ -static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){ - int i; /* Loop counter */ - const Index *pIdx; /* The index of interest */ - const i16 *aiColumn; /* Columns contained in the index */ - u16 nColumn; /* Number of columns in the index */ - CoveringIndexCheck *pCk; /* Info about this search */ - - pCk = pWalk->u.pCovIdxCk; - pIdx = pCk->pIdx; - if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) ){ - /* if( pExpr->iColumn<(BMS-1) && pIdx->bHasExpr==0 ) return WRC_Continue;*/ - if( pExpr->iTable!=pCk->iTabCur ) return WRC_Continue; - pIdx = pWalk->u.pCovIdxCk->pIdx; - aiColumn = pIdx->aiColumn; - nColumn = pIdx->nColumn; - for(i=0; iiColumn ) return WRC_Continue; - } - pCk->bUnidx = 1; - return WRC_Abort; - }else if( pIdx->bHasExpr - && exprIsCoveredByIndex(pExpr, pIdx, pWalk->u.pCovIdxCk->iTabCur) ){ - pCk->bExpr = 1; - return WRC_Prune; - } - return WRC_Continue; -} - - -/* -** pIdx is an index that covers all of the low-number columns used by -** pWInfo->pSelect (columns from 0 through 62) or an index that has -** expressions terms. Hence, we cannot determine whether or not it is -** a covering index by using the colUsed bitmasks. We have to do a search -** to see if the index is covering. This routine does that search. -** -** The return value is one of these: -** -** 0 The index is definitely not a covering index -** -** WHERE_IDX_ONLY The index is definitely a covering index -** -** WHERE_EXPRIDX The index is likely a covering index, but it is -** difficult to determine precisely because of the -** expressions that are indexed. Score it as a -** covering index, but still keep the main table open -** just in case we need it. -** -** This routine is an optimization. It is always safe to return zero. -** But returning one of the other two values when zero should have been -** returned can lead to incorrect bytecode and assertion faults. -*/ -static SQLITE_NOINLINE u32 whereIsCoveringIndex( - WhereInfo *pWInfo, /* The WHERE clause context */ - Index *pIdx, /* Index that is being tested */ - int iTabCur /* Cursor for the table being indexed */ -){ - int i, rc; - struct CoveringIndexCheck ck; - Walker w; - if( pWInfo->pSelect==0 ){ - /* We don't have access to the full query, so we cannot check to see - ** if pIdx is covering. Assume it is not. */ - return 0; - } - if( pIdx->bHasExpr==0 ){ - for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]>=BMS-1 ) break; - } - if( i>=pIdx->nColumn ){ - /* pIdx does not index any columns greater than 62, but we know from - ** colMask that columns greater than 62 are used, so this is not a - ** covering index */ - return 0; - } - } - ck.pIdx = pIdx; - ck.iTabCur = iTabCur; - ck.bExpr = 0; - ck.bUnidx = 0; - memset(&w, 0, sizeof(w)); - w.xExprCallback = whereIsCoveringIndexWalkCallback; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.u.pCovIdxCk = &ck; - sqlite3WalkSelect(&w, pWInfo->pSelect); - if( ck.bUnidx ){ - rc = 0; - }else if( ck.bExpr ){ - rc = WHERE_EXPRIDX; - }else{ - rc = WHERE_IDX_ONLY; - } - return rc; -} - -/* -** This is an sqlite3ParserAddCleanup() callback that is invoked to -** free the Parse->pIdxEpr list when the Parse object is destroyed. -*/ -static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){ - IndexedExpr **pp = (IndexedExpr**)pObject; - while( *pp!=0 ){ - IndexedExpr *p = *pp; - *pp = p->pIENext; - sqlite3ExprDelete(db, p->pExpr); - sqlite3DbFreeNN(db, p); - } -} - -/* -** This function is called for a partial index - one with a WHERE clause - in -** two scenarios. In both cases, it determines whether or not the WHERE -** clause on the index implies that a column of the table may be safely -** replaced by a constant expression. For example, in the following -** SELECT: -** -** CREATE INDEX i1 ON t1(b, c) WHERE a=; -** SELECT a, b, c FROM t1 WHERE a= AND b=?; -** -** The "a" in the select-list may be replaced by , iff: -** -** (a) is a constant expression, and -** (b) The (a=) comparison uses the BINARY collation sequence, and -** (c) Column "a" has an affinity other than NONE or BLOB. -** -** If argument pItem is NULL, then pMask must not be NULL. In this case this -** function is being called as part of determining whether or not pIdx -** is a covering index. This function clears any bits in (*pMask) -** corresponding to columns that may be replaced by constants as described -** above. -** -** Otherwise, if pItem is not NULL, then this function is being called -** as part of coding a loop that uses index pIdx. In this case, add entries -** to the Parse.pIdxPartExpr list for each column that can be replaced -** by a constant. -*/ -static void wherePartIdxExpr( - Parse *pParse, /* Parse context */ - Index *pIdx, /* Partial index being processed */ - Expr *pPart, /* WHERE clause being processed */ - Bitmask *pMask, /* Mask to clear bits in */ - int iIdxCur, /* Cursor number for index */ - SrcItem *pItem /* The FROM clause entry for the table */ -){ - assert( pItem==0 || (pItem->fg.jointype & JT_RIGHT)==0 ); - assert( (pItem==0 || pMask==0) && (pMask!=0 || pItem!=0) ); - - if( pPart->op==TK_AND ){ - wherePartIdxExpr(pParse, pIdx, pPart->pRight, pMask, iIdxCur, pItem); - pPart = pPart->pLeft; - } - - if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ - Expr *pLeft = pPart->pLeft; - Expr *pRight = pPart->pRight; - u8 aff; - - if( pLeft->op!=TK_COLUMN ) return; - if( !sqlite3ExprIsConstant(0, pRight) ) return; - if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; - if( pLeft->iColumn<0 ) return; - aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; - if( aff>=SQLITE_AFF_TEXT ){ - if( pItem ){ - sqlite3 *db = pParse->db; - IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); - if( p ){ - int bNullRow = (pItem->fg.jointype&(JT_LEFT|JT_LTORJ))!=0; - p->pExpr = sqlite3ExprDup(db, pRight, 0); - p->iDataCur = pItem->iCursor; - p->iIdxCur = iIdxCur; - p->iIdxCol = pLeft->iColumn; - p->bMaybeNullRow = bNullRow; - p->pIENext = pParse->pIdxPartExpr; - p->aff = aff; - pParse->pIdxPartExpr = p; - if( p->pIENext==0 ){ - void *pArg = (void*)&pParse->pIdxPartExpr; - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); - } - } - }else if( pLeft->iColumn<(BMS-1) ){ - *pMask &= ~((Bitmask)1 << pLeft->iColumn); - } - } - } -} - - -/* -** Add all WhereLoop objects for a single table of the join where the table -** is identified by pBuilder->pNew->iTab. That table is guaranteed to be -** a b-tree table, not a virtual table. -** -** The costs (WhereLoop.rRun) of the b-tree loops added by this function -** are calculated as follows: -** -** For a full scan, assuming the table (or index) contains nRow rows: -** -** cost = nRow * 3.0 // full-table scan -** cost = nRow * K // scan of covering index -** cost = nRow * (K+3.0) // scan of non-covering index -** -** where K is a value between 1.1 and 3.0 set based on the relative -** estimated average size of the index and table records. -** -** For an index scan, where nVisit is the number of index rows visited -** by the scan, and nSeek is the number of seek operations required on -** the index b-tree: -** -** cost = nSeek * (log(nRow) + K * nVisit) // covering index -** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index -** -** Normally, nSeek is 1. nSeek values greater than 1 come about if the -** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when -** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans. -** -** The estimated values (nRow, nVisit, nSeek) often contain a large amount -** of uncertainty. For this reason, scoring is designed to pick plans that -** "do the least harm" if the estimates are inaccurate. For example, a -** log(nRow) factor is omitted from a non-covering index scan in order to -** bias the scoring in favor of using an index, since the worst-case -** performance of using an index is far better than the worst-case performance -** of a full table scan. -*/ -static int whereLoopAddBtree( - WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq /* Extra prerequisites for using this table */ -){ - WhereInfo *pWInfo; /* WHERE analysis context */ - Index *pProbe; /* An index we are evaluating */ - Index sPk; /* A fake index object for the primary key */ - LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */ - i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */ - SrcList *pTabList; /* The FROM clause */ - 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 */ - WhereClause *pWC; /* The parsed WHERE clause */ - Table *pTab; /* Table being queried */ - - pNew = pBuilder->pNew; - pWInfo = pBuilder->pWInfo; - pTabList = pWInfo->pTabList; - pSrc = pTabList->a + pNew->iTab; - pTab = pSrc->pSTab; - pWC = pBuilder->pWC; - assert( !IsVirtual(pSrc->pSTab) ); - - if( pSrc->fg.isIndexedBy ){ - assert( pSrc->fg.isCte==0 ); - /* An INDEXED BY clause specifies a particular index to use */ - pProbe = pSrc->u2.pIBIndex; - }else if( !HasRowid(pTab) ){ - pProbe = pTab->pIndex; - }else{ - /* There is no INDEXED BY clause. Create a fake Index object in local - ** variable sPk to represent the rowid primary key index. Make this - ** fake index the first in a chain of Index objects with all of the real - ** indices to follow */ - Index *pFirst; /* First of real indices on the table */ - memset(&sPk, 0, sizeof(Index)); - sPk.nKeyCol = 1; - sPk.nColumn = 1; - sPk.aiColumn = &aiColumnPk; - sPk.aiRowLogEst = aiRowEstPk; - sPk.onError = OE_Replace; - sPk.pTable = pTab; - sPk.szIdxRow = 3; /* TUNING: Interior rows of IPK table are very small */ - sPk.idxType = SQLITE_IDXTYPE_IPK; - aiRowEstPk[0] = pTab->nRowLogEst; - aiRowEstPk[1] = 0; - pFirst = pSrc->pSTab->pIndex; - if( pSrc->fg.notIndexed==0 ){ - /* The real indices of the table are only considered if the - ** NOT INDEXED qualifier is omitted from the FROM clause */ - sPk.pNext = pFirst; - } - pProbe = &sPk; - } - rSize = pTab->nRowLogEst; - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - /* Automatic indexes */ - if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0 - && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 - && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ - && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ - && !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 && pTermprereqRight & pNew->maskSelf ) continue; - if( termCanDriveIndex(pTerm, pSrc, 0) ){ - pNew->u.btree.nEq = 1; - pNew->nSkip = 0; - pNew->u.btree.pIndex = 0; - pNew->nLTerm = 1; - pNew->aLTerm[0] = pTerm; - /* TUNING: One-time cost for computing the automatic index is - ** estimated to be X*N*log2(N) where N is the number of rows in - ** the table being indexed and where X is 7 (LogEst=28) for normal - ** tables or 0.5 (LogEst=-10) for views and subqueries. The value - ** of X is smaller for views and subqueries so that the query planner - ** will be more aggressive about generating automatic indexes for - ** those objects, since there is no opportunity to add schema - ** indexes on subqueries and views. */ - pNew->rSetup = rLogSize + rSize; - if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){ - pNew->rSetup += 28; - }else{ - pNew->rSetup -= 25; /* Greatly reduced setup cost for auto indexes - ** on ephemeral materializations of views */ - } - ApplyCostMultiplier(pNew->rSetup, pTab->costMult); - if( pNew->rSetup<0 ) pNew->rSetup = 0; - /* TUNING: Each index lookup yields 20 rows in the table. This - ** is more than the usual guess of 10 rows, since we have no way - ** of knowing how selective the index will ultimately be. It would - ** not be unreasonable to make this value much larger. */ - pNew->nOut = 43; assert( 43==sqlite3LogEst(20) ); - pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); - pNew->wsFlags = WHERE_AUTO_INDEX; - pNew->prereq = mPrereq | pTerm->prereqRight; - rc = whereLoopInsert(pBuilder, pNew); - } - } - } -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - - /* Loop over all indices. If there was an INDEXED BY clause, then only - ** consider index pProbe. */ - for(; rc==SQLITE_OK && pProbe; - pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++ - ){ - if( pProbe->pPartIdxWhere!=0 - && !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC, - pProbe->pPartIdxWhere) - ){ - testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ - continue; /* Partial index inappropriate for this query */ - } - if( pProbe->bNoQuery ) continue; - rSize = pProbe->aiRowLogEst[0]; - pNew->u.btree.nEq = 0; - pNew->u.btree.nBtm = 0; - pNew->u.btree.nTop = 0; - pNew->u.btree.nDistinctCol = 0; - pNew->nSkip = 0; - pNew->nLTerm = 0; - pNew->iSortIdx = 0; - pNew->rSetup = 0; - pNew->prereq = mPrereq; - pNew->nOut = rSize; - pNew->u.btree.pIndex = pProbe; - pNew->u.btree.pOrderBy = 0; - b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); - - /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ - assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); - if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ - /* Integer primary key index */ - pNew->wsFlags = WHERE_IPK; - - /* Full table scan */ - pNew->iSortIdx = b ? iSortIdx : 0; - /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an - ** extra cost designed to discourage the use of full table scans, - ** since index lookups have better worst-case performance if our - ** stat guesses are wrong. Reduce the 3.0 penalty slightly - ** (to 2.75) if we have valid STAT4 information for the table. - ** At 2.75, a full table scan is preferred over using an index on - ** a column with just two distinct values where each value has about - ** an equal number of appearances. Without STAT4 data, we still want - ** to use an index in that case, since the constraint might be for - ** the scarcer of the two values, and in that case an index lookup is - ** better. - */ -#ifdef SQLITE_ENABLE_STAT4 - pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0); -#else - pNew->rRun = rSize + 16; -#endif - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); - if( pSrc->fg.isSubquery ){ - if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE; - pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy; - } - rc = whereLoopInsert(pBuilder, pNew); - pNew->nOut = rSize; - if( rc ) break; - }else{ - Bitmask m; - if( pProbe->isCovering ){ - m = 0; - pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; - }else{ - m = pSrc->colUsed & pProbe->colNotIdxed; - if( pProbe->pPartIdxWhere ){ - wherePartIdxExpr( - pWInfo->pParse, pProbe, pProbe->pPartIdxWhere, &m, 0, 0 - ); - } - pNew->wsFlags = WHERE_INDEXED; - if( m==TOPBIT || (pProbe->bHasExpr && !pProbe->bHasVCol && m!=0) ){ - u32 isCov = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor); - if( isCov==0 ){ - WHERETRACE(0x200, - ("-> %s is not a covering index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - assert( m!=0 ); - }else{ - m = 0; - pNew->wsFlags |= isCov; - if( isCov & WHERE_IDX_ONLY ){ - WHERETRACE(0x200, - ("-> %s is a covering expression index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - }else{ - assert( isCov==WHERE_EXPRIDX ); - WHERETRACE(0x200, - ("-> %s might be a covering expression index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - } - } - }else if( m==0 - && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700)) - ){ - WHERETRACE(0x200, - ("-> %s is a covering index according to bitmasks\n", - pProbe->zName, m==0 ? "is" : "is not")); - pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; - } - } - - /* Full scan via index */ - if( b - || !HasRowid(pTab) - || pProbe->pPartIdxWhere!=0 - || pSrc->fg.isIndexedBy - || ( m==0 - && pProbe->bUnordered==0 - && (pProbe->szIdxRowszTabRow) - && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 - && sqlite3GlobalConfig.bUseCis - && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) - ) - ){ - pNew->iSortIdx = b ? iSortIdx : 0; - - /* The cost of visiting the index rows is N*K, where K is - ** between 1.1 and 3.0, depending on the relative sizes of the - ** index and table rows. */ - pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; - if( m!=0 ){ - /* If this is a non-covering index scan, add in the cost of - ** doing table lookups. The cost will be 3x the number of - ** lookups. Take into account WHERE clause terms that can be - ** satisfied using just the index, and that do not require a - ** table lookup. */ - LogEst nLookup = rSize + 16; /* Base cost: N*3 */ - int ii; - int iCur = pSrc->iCursor; - WhereClause *pWC2 = &pWInfo->sWC; - for(ii=0; iinTerm; ii++){ - WhereTerm *pTerm = &pWC2->a[ii]; - if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){ - break; - } - /* pTerm can be evaluated using just the index. So reduce - ** the expected number of table lookups accordingly */ - if( pTerm->truthProb<=0 ){ - nLookup += pTerm->truthProb; - }else{ - nLookup--; - if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19; - } - } - - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup); - } - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); - 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; - } - } - - pBuilder->bldFlags1 = 0; - rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){ - /* If a non-unique index is used, or if a prefix of the key for - ** unique index is used (making the index functionally non-unique) - ** then the sqlite_stat1 data becomes important for scoring the - ** plan */ - pTab->tabFlags |= TF_MaybeReanalyze; - } -#ifdef SQLITE_ENABLE_STAT4 - sqlite3Stat4ProbeFree(pBuilder->pRec); - pBuilder->nRecValid = 0; - pBuilder->pRec = 0; -#endif - } - return rc; -} - -#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; -} - -/* -** Return true if the first nCons constraints in the pUsage array are -** marked as in-use (have argvIndex>0). False otherwise. -*/ -static int allConstraintsUsed( - struct sqlite3_index_constraint_usage *aUsage, - int nCons -){ - int ii; - for(ii=0; iipNew->iTab. This -** function marks a subset of those constraints usable, invokes the -** xBestIndex method and adds the returned plan to pBuilder. -** -** A constraint is marked usable if: -** -** * Argument mUsable indicates that its prerequisites are available, and -** -** * It is not one of the operators specified in the mExclude mask passed -** as the fourth argument (which in practice is either WO_IN or 0). -** -** Argument mPrereq is a mask of tables that must be scanned before the -** virtual table in question. These are added to the plans prerequisites -** before it is added to pBuilder. -** -** Output parameter *pbIn is set to true if the plan added to pBuilder -** uses one or more WO_IN terms, or false otherwise. -*/ -static int whereLoopAddVirtualOne( - WhereLoopBuilder *pBuilder, - Bitmask mPrereq, /* Mask of tables that must be used. */ - Bitmask mUsable, /* Mask of usable tables */ - u16 mExclude, /* Exclude terms using these operators */ - 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 *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */ -){ - WhereClause *pWC = pBuilder->pWC; - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; - int i; - int mxTerm; - int rc = SQLITE_OK; - WhereLoop *pNew = pBuilder->pNew; - Parse *pParse = pBuilder->pWInfo->pParse; - SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; - int nConstraint = pIdxInfo->nConstraint; - - assert( (mUsable & mPrereq)==mPrereq ); - *pbIn = 0; - pNew->prereq = mPrereq; - - /* Set the usable flag on the subset of constraints identified by - ** arguments mUsable and mExclude. */ - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; iiTermOffset); - pIdxCons->usable = 0; - if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight - && (pTerm->eOperator & mExclude)==0 - && (pbRetryLimit || !isLimitTerm(pTerm)) - ){ - pIdxCons->usable = 1; - } - } - - /* Initialize the output fields of the sqlite3_index_info structure */ - memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); - assert( pIdxInfo->needToFreeIdxStr==0 ); - pIdxInfo->idxStr = 0; - pIdxInfo->idxNum = 0; - pIdxInfo->orderByConsumed = 0; - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; - pIdxInfo->estimatedRows = 25; - pIdxInfo->idxFlags = 0; - pHidden->mHandleIn = 0; - - /* Invoke the virtual table xBestIndex() method */ - rc = vtabBestIndex(pParse, pSrc->pSTab, pIdxInfo); - if( rc ){ - if( rc==SQLITE_CONSTRAINT ){ - /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means - ** that the particular combination of parameters provided is unusable. - ** Make no entries in the loop table. - */ - WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n")); - freeIdxStr(pIdxInfo); - return SQLITE_OK; - } - return rc; - } - - mxTerm = -1; - assert( pNew->nLSlot>=nConstraint ); - memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint ); - memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab)); - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; i=0 ){ - WhereTerm *pTerm; - int j = pIdxCons->iTermOffset; - if( iTerm>=nConstraint - || j<0 - || (pTerm = termFromWhereClause(pWC, j))==0 - || pNew->aLTerm[iTerm]!=0 - || pIdxCons->usable==0 - ){ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName); - freeIdxStr(pIdxInfo); - return SQLITE_ERROR; - } - testcase( iTerm==nConstraint-1 ); - testcase( j==0 ); - testcase( j==pWC->nTerm-1 ); - pNew->prereq |= pTerm->prereqRight; - assert( iTermnLSlot ); - pNew->aLTerm[iTerm] = pTerm; - if( iTerm>mxTerm ) mxTerm = iTerm; - testcase( iTerm==15 ); - testcase( iTerm==16 ); - if( pUsage[i].omit ){ - if( i<16 && ((1<u.vtab.omitMask |= 1<eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){ - pNew->u.vtab.bOmitOffset = 1; - } - } - 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 - ** (2) Multiple outputs from a single IN value will not merge - ** together. */ - pIdxInfo->orderByConsumed = 0; - pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; - *pbIn = 1; assert( (mExclude & WO_IN)==0 ); - } - - /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET - ** terms. And if there are any, they should follow all other terms. */ - assert( pbRetryLimit || !isLimitTerm(pTerm) ); - assert( !isLimitTerm(pTerm) || i>=nConstraint-2 ); - assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) ); - - if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){ - /* 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. Similarly, - ** if there is a LIMIT/OFFSET and there are other unused terms, - ** the plan cannot be used. In these cases set variable *pbRetryLimit - ** to true to tell the caller to retry with LIMIT and OFFSET - ** disabled. */ - freeIdxStr(pIdxInfo); - *pbRetryLimit = 1; - return SQLITE_OK; - } - } - } - - pNew->nLTerm = mxTerm+1; - for(i=0; i<=mxTerm; i++){ - if( pNew->aLTerm[i]==0 ){ - /* The non-zero argvIdx values must be contiguous. Raise an - ** error if they are not */ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName); - freeIdxStr(pIdxInfo); - return SQLITE_ERROR; - } - } - assert( pNew->nLTerm<=pNew->nLSlot ); - pNew->u.vtab.idxNum = pIdxInfo->idxNum; - pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; - pIdxInfo->needToFreeIdxStr = 0; - pNew->u.vtab.idxStr = pIdxInfo->idxStr; - pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? - pIdxInfo->nOrderBy : 0); - pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0; - pNew->rSetup = 0; - pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); - pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); - - /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated - ** that the scan will visit at most one row. Clear it otherwise. */ - if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags &= ~WHERE_ONEROW; - } - rc = whereLoopInsert(pBuilder, pNew); - if( pNew->u.vtab.needFree ){ - sqlite3_free(pNew->u.vtab.idxStr); - pNew->u.vtab.needFree = 0; - } - WHERETRACE(0xffffffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", - *pbIn, (sqlite3_uint64)mPrereq, - (sqlite3_uint64)(pNew->prereq & ~mPrereq))); - - return rc; -} - -/* -** Return the collating sequence for a constraint passed into xBestIndex. -** -** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex. -** This routine depends on there being a HiddenIndexInfo structure immediately -** following the sqlite3_index_info structure. -** -** Return a pointer to the collation name: -** -** 1. If there is an explicit COLLATE operator on the constraint, return it. -** -** 2. Else, if the column has an alternative collation, return that. -** -** 3. Otherwise, return "BINARY". -*/ -SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - const char *zRet = 0; - if( iCons>=0 && iConsnConstraint ){ - CollSeq *pC = 0; - int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; - Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr; - if( pX->pLeft ){ - pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX); - } - zRet = (pC ? pC->zName : sqlite3StrBINARY); - } - return zRet; -} - -/* -** 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 sqlite3_vtab_in(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 sqlite3_vtab_rhs_value( - sqlite3_index_info *pIdxInfo, /* Copy of first argument to xBestIndex */ - int iCons, /* Constraint for which RHS is wanted */ - sqlite3_value **ppVal /* Write value extracted here */ -){ - HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1]; - sqlite3_value *pVal = 0; - int rc = SQLITE_OK; - if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ - rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */ - }else{ - if( pH->aRhs[iCons]==0 ){ - WhereTerm *pTerm = termFromWhereClause( - pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset - ); - rc = 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 sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 ); - return pHidden->eDistinct; -} - -/* -** Cause the prepared statement that is associated with a call to -** xBestIndex to potentially 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 sqlite3VtabUsesAllSchemas(Parse *pParse){ - int nDb = pParse->db->nDb; - int i; - for(i=0; iwriteMask) ){ - for(i=0; ipNew->iTab. That table is guaranteed to be a virtual table. -** -** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and -** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause -** entries that occur before the virtual table in the FROM clause and are -** separated from it by at least one LEFT or CROSS JOIN. Similarly, the -** mUnusable mask contains all FROM clause entries that occur after the -** virtual table and are separated from it by at least one LEFT or -** CROSS JOIN. -** -** For example, if the query were: -** -** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6; -** -** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6). -** -** All the tables in mPrereq must be scanned before the current virtual -** table. So any terms for which all prerequisites are satisfied by -** mPrereq may be specified as "usable" in all calls to xBestIndex. -** Conversely, all tables in mUnusable must be scanned after the current -** virtual table, so any terms for which the prerequisites overlap with -** mUnusable should always be configured as "not-usable" for xBestIndex. -*/ -static int whereLoopAddVirtual( - WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq, /* Tables that must be scanned before this one */ - Bitmask mUnusable /* Tables that must be scanned after this one */ -){ - int rc = SQLITE_OK; /* Return code */ - WhereInfo *pWInfo; /* WHERE analysis context */ - Parse *pParse; /* The parsing context */ - WhereClause *pWC; /* The WHERE clause */ - SrcItem *pSrc; /* The FROM clause term to search */ - 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; - pParse = pWInfo->pParse; - pWC = pBuilder->pWC; - pNew = pBuilder->pNew; - pSrc = &pWInfo->pTabList->a[pNew->iTab]; - assert( IsVirtual(pSrc->pSTab) ); - p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit); - if( p==0 ) return SQLITE_NOMEM_BKPT; - pNew->rSetup = 0; - pNew->wsFlags = WHERE_VIRTUALTABLE; - pNew->nLTerm = 0; - pNew->u.vtab.needFree = 0; - nConstraint = p->nConstraint; - if( whereLoopResize(pParse->db, pNew, nConstraint) ){ - freeIndexInfo(pParse->db, p); - return SQLITE_NOMEM_BKPT; - } - - /* First call xBestIndex() with all constraints usable. */ - WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pSTab->zName)); - WHERETRACE(0x800, (" VirtualOne: all usable\n")); - 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) - ** and does not use an IN(...) operator, then there is no point in making - ** any further calls to xBestIndex() since they will all return the same - ** result (if the xBestIndex() implementation is sane). */ - if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){ - int seenZero = 0; /* True if a plan with no prereqs seen */ - int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ - Bitmask mPrev = 0; - Bitmask mBestNoIn = 0; - - /* If the plan produced by the earlier call uses an IN(...) term, call - ** xBestIndex again, this time with IN(...) terms disabled. */ - if( bIn ){ - WHERETRACE(0x800, (" VirtualOne: all usable w/o IN\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0); - assert( bIn==0 ); - mBestNoIn = pNew->prereq & ~mPrereq; - if( mBestNoIn==0 ){ - seenZero = 1; - seenZeroNoIN = 1; - } - } - - /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) - ** in the set of terms that apply to the current virtual table. */ - while( rc==SQLITE_OK ){ - int i; - Bitmask mNext = ALLBITS; - assert( mNext>0 ); - for(i=0; iaConstraint[i].iTermOffset; - Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq; - if( mThis>mPrev && mThisprereq==mPrereq ){ - seenZero = 1; - if( bIn==0 ) seenZeroNoIN = 1; - } - } - - /* If the calls to xBestIndex() in the above loop did not find a plan - ** that requires no source tables at all (i.e. one guaranteed to be - ** usable), make a call here with all source tables disabled */ - if( rc==SQLITE_OK && seenZero==0 ){ - WHERETRACE(0x800, (" VirtualOne: all disabled\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0); - if( bIn==0 ) seenZeroNoIN = 1; - } - - /* If the calls to xBestIndex() have so far failed to find a plan - ** that requires no source tables at all and does not use an IN(...) - ** operator, make a final call to obtain one here. */ - if( rc==SQLITE_OK && seenZeroNoIN==0 ){ - WHERETRACE(0x800, (" VirtualOne: all disabled and w/o IN\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0); - } - } - - freeIndexInfo(pParse->db, p); - WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pSTab->zName, rc)); - return rc; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** Add WhereLoop entries to handle OR terms. This works for either -** btrees or virtual tables. -*/ -static int whereLoopAddOr( - WhereLoopBuilder *pBuilder, - Bitmask mPrereq, - Bitmask mUnusable -){ - WhereInfo *pWInfo = pBuilder->pWInfo; - WhereClause *pWC; - WhereLoop *pNew; - WhereTerm *pTerm, *pWCEnd; - int rc = SQLITE_OK; - int iCur; - WhereClause tempWC; - WhereLoopBuilder sSubBuild; - WhereOrSet sSum, sCur; - SrcItem *pItem; - - pWC = pBuilder->pWC; - pWCEnd = pWC->a + pWC->nTerm; - pNew = pBuilder->pNew; - memset(&sSum, 0, sizeof(sSum)); - 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; pTermeOperator & WO_OR)!=0 - && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 - ){ - WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; - WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; - WhereTerm *pOrTerm; - int once = 1; - int i, j; - - sSubBuild = *pBuilder; - sSubBuild.pOrSet = &sCur; - - WHERETRACE(0x400, ("Begin processing OR-clause %p\n", pTerm)); - for(pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0 ){ - sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; - }else if( pOrTerm->leftCursor==iCur ){ - tempWC.pWInfo = pWC->pWInfo; - tempWC.pOuter = pWC; - tempWC.op = TK_AND; - tempWC.nTerm = 1; - tempWC.nBase = 1; - tempWC.a = pOrTerm; - sSubBuild.pWC = &tempWC; - }else{ - continue; - } - sCur.n = 0; -#ifdef WHERETRACE_ENABLED - WHERETRACE(0x400, ("OR-term %d of %p has %d subterms:\n", - (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); - if( sqlite3WhereTrace & 0x20000 ){ - sqlite3WhereClausePrint(sSubBuild.pWC); - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pSTab) ){ - rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable); - }else -#endif - { - rc = whereLoopAddBtree(&sSubBuild, mPrereq); - } - if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); - } - testcase( rc==SQLITE_NOMEM && sCur.n>0 ); - testcase( rc==SQLITE_DONE ); - if( sCur.n==0 ){ - sSum.n = 0; - break; - }else if( once ){ - whereOrMove(&sSum, &sCur); - once = 0; - }else{ - WhereOrSet sPrev; - whereOrMove(&sPrev, &sSum); - sSum.n = 0; - for(i=0; inLTerm = 1; - pNew->aLTerm[0] = pTerm; - pNew->wsFlags = WHERE_MULTI_OR; - pNew->rSetup = 0; - pNew->iSortIdx = 0; - memset(&pNew->u, 0, sizeof(pNew->u)); - for(i=0; rc==SQLITE_OK && irRun = sSum.a[i].rRun + 1; - pNew->nOut = sSum.a[i].nOut; - pNew->prereq = sSum.a[i].prereq; - rc = whereLoopInsert(pBuilder, pNew); - } - WHERETRACE(0x400, ("End processing OR-clause %p\n", pTerm)); - } - } - return rc; -} - -/* -** Add all WhereLoop objects for all tables -*/ -static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo = pBuilder->pWInfo; - Bitmask mPrereq = 0; - Bitmask mPrior = 0; - int iTab; - SrcList *pTabList = pWInfo->pTabList; - SrcItem *pItem; - SrcItem *pEnd = &pTabList->a[pWInfo->nLevel]; - 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; - - /* Verify that pNew has already been initialized */ - assert( pNew->nLTerm==0 ); - assert( pNew->wsFlags==0 ); - assert( pNew->nLSlot>=ArraySize(pNew->aLTermSpace) ); - assert( pNew->aLTerm!=0 ); - - pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; - for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; - pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; - pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); - 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->pSTab) ){ - SrcItem *p; - for(p=&pItem[1]; pfg.jointype & (JT_OUTER|JT_CROSS)) ){ - mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); - } - } - rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); - }else -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - { - rc = whereLoopAddBtree(pBuilder, mPrereq); - } - if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){ - rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); - } - mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ){ - if( rc==SQLITE_DONE ){ - /* We hit the query planner search limit set by iPlanLimit */ - sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); - rc = SQLITE_OK; - }else{ - break; - } - } - } - - whereLoopClear(db, pNew); - return rc; -} - -/* Implementation of the order-by-subquery optimization: -** -** WhereLoop pLoop, which the iLoop-th term of the nested loop, is really -** a subquery or CTE that has an ORDER BY clause. See if any of the terms -** in the subquery ORDER BY clause will satisfy pOrderBy from the outer -** query. Mark off all satisfied terms (by setting bits in *pOBSat) and -** return TRUE if they do. If not, return false. -** -** Example: -** -** CREATE TABLE t1(a,b,c, PRIMARY KEY(a,b)); -** CREATE TABLE t2(x,y); -** WITH t3(p,q) AS MATERIALIZED (SELECT x+y, x-y FROM t2 ORDER BY x+y) -** SELECT * FROM t3 JOIN t1 ON a=q ORDER BY p, b; -** -** The CTE named "t3" comes out in the natural order of "p", so the first -** first them of "ORDER BY p,b" is satisfied by a sequential scan of "t3" -** and sorting only needs to occur on the second term "b". -** -** Limitations: -** -** (1) The optimization is not applied if the outer ORDER BY contains -** a COLLATE clause. The optimization might be applied if the -** outer ORDER BY uses NULLS FIRST, NULLS LAST, ASC, and/or DESC as -** long as the subquery ORDER BY does the same. But if the -** outer ORDER BY uses COLLATE, even a redundant COLLATE, the -** optimization is bypassed. -** -** (2) The subquery ORDER BY terms must exactly match subquery result -** columns, including any COLLATE annotations. This routine relies -** on iOrderByCol to do matching between order by terms and result -** columns, and iOrderByCol will not be set if the result column -** and ORDER BY collations differ. -** -** (3) The subquery and outer ORDER BY can be in opposite directions as -** long as the subquery is materialized. If the subquery is -** implemented as a co-routine, the sort orders must be in the same -** direction because there is no way to run a co-routine backwards. -*/ -static SQLITE_NOINLINE int wherePathMatchSubqueryOB( - WhereInfo *pWInfo, /* The WHERE clause */ - WhereLoop *pLoop, /* The nested loop term that is a subquery */ - int iLoop, /* Which level of the nested loop. 0==outermost */ - int iCur, /* Cursor used by the this loop */ - ExprList *pOrderBy, /* The ORDER BY clause on the whole query */ - Bitmask *pRevMask, /* When loops need to go in reverse order */ - Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */ -){ - int iOB; /* Index into pOrderBy->a[] */ - int jSub; /* Index into pSubOB->a[] */ - u8 rev = 0; /* True if iOB and jSub sort in opposite directions */ - u8 revIdx = 0; /* Sort direction for jSub */ - Expr *pOBExpr; /* Current term of outer ORDER BY */ - ExprList *pSubOB; /* Complete ORDER BY on the subquery */ - - pSubOB = pLoop->u.btree.pOrderBy; - assert( pSubOB!=0 ); - for(iOB=0; (MASKBIT(iOB) & *pOBSat)!=0; iOB++){} - for(jSub=0; jSubnExpr && iOBnExpr; jSub++, iOB++){ - if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break; - pOBExpr = pOrderBy->a[iOB].pExpr; - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break; - if( pOBExpr->iTable!=iCur ) break; - if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break; - if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ - u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */ - u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */ - if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){ - break; - } - revIdx = sfSub & KEYINFO_ORDER_DESC; - if( jSub>0 ){ - if( (rev^revIdx)!=(sfOB & KEYINFO_ORDER_DESC) ){ - break; - } - }else{ - rev = revIdx ^ (sfOB & KEYINFO_ORDER_DESC); - if( rev ){ - if( (pLoop->wsFlags & WHERE_COROUTINE)!=0 ){ - /* Cannot run a co-routine in reverse order */ - break; - } - *pRevMask |= MASKBIT(iLoop); - } - } - } - *pOBSat |= MASKBIT(iOB); - } - return jSub>0; -} - -/* -** Examine a WherePath (with the addition of the extra WhereLoop of the 6th -** parameters) to see if it outputs rows in the requested ORDER BY -** (or GROUP BY) without requiring a separate sort operation. Return N: -** -** N>0: N terms of the ORDER BY clause are satisfied -** N==0: No terms of the ORDER BY clause are satisfied -** N<0: Unknown yet how many terms of ORDER BY might be satisfied. -** -** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as -** strict. With GROUP BY and DISTINCT the only requirement is that -** equivalent rows appear immediately adjacent to one another. GROUP BY -** and DISTINCT do not require rows to appear in any particular order as long -** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT -** the pOrderBy terms can be matched in any order. With ORDER BY, the -** pOrderBy terms must be matched in strict left-to-right order. -*/ -static i8 wherePathSatisfiesOrderBy( - WhereInfo *pWInfo, /* The WHERE clause */ - ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ - WherePath *pPath, /* The WherePath to check */ - u16 wctrlFlags, /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */ - u16 nLoop, /* Number of entries in pPath->aLoop[] */ - WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ - Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ -){ - u8 revSet; /* True if rev is known */ - u8 rev; /* Composite sort order */ - u8 revIdx; /* Index sort order */ - u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ - u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */ - u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ - u16 eqOpMask; /* Allowed equality operators */ - u16 nKeyCol; /* Number of key columns in pIndex */ - u16 nColumn; /* Total number of ordered columns in the index */ - u16 nOrderBy; /* Number terms in the ORDER BY clause */ - int iLoop; /* Index of WhereLoop in pPath being processed */ - int i, j; /* Loop counters */ - int iCur; /* Cursor number for current WhereLoop */ - int iColumn; /* A column number within table iCur */ - WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - Expr *pOBExpr; /* An expression from the ORDER BY clause */ - CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */ - Index *pIndex; /* The index associated with pLoop */ - sqlite3 *db = pWInfo->pParse->db; /* Database connection */ - Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */ - Bitmask obDone; /* Mask of all ORDER BY terms */ - Bitmask orderDistinctMask; /* Mask of all well-ordered loops */ - Bitmask ready; /* Mask of inner loops */ - - /* - ** We say the WhereLoop is "one-row" if it generates no more than one - ** row of output. A WhereLoop is one-row if all of the following are true: - ** (a) All index columns match with WHERE_COLUMN_EQ. - ** (b) The index is unique - ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row. - ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags. - ** - ** We say the WhereLoop is "order-distinct" if the set of columns from - ** that WhereLoop that are in the ORDER BY clause are different for every - ** row of the WhereLoop. Every one-row WhereLoop is automatically - ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause - ** is not order-distinct. To be order-distinct is not quite the same as being - ** UNIQUE since a UNIQUE column or index can have multiple rows that - ** are NULL and NULL values are equivalent for the purpose of order-distinct. - ** To be order-distinct, the columns must be UNIQUE and NOT NULL. - ** - ** The rowid for a table is always UNIQUE and NOT NULL so whenever the - ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is - ** automatically order-distinct. - */ - - assert( pOrderBy!=0 ); - if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0; - - nOrderBy = pOrderBy->nExpr; - testcase( nOrderBy==BMS-1 ); - if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */ - isOrderDistinct = 1; - obDone = MASKBIT(nOrderBy)-1; - orderDistinctMask = 0; - ready = 0; - eqOpMask = WO_EQ | WO_IS | WO_ISNULL; - if( wctrlFlags & (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MAX|WHERE_ORDERBY_MIN) ){ - eqOpMask |= WO_IN; - } - for(iLoop=0; isOrderDistinct && obSat0 ) ready |= pLoop->maskSelf; - if( iLoopaLoop[iLoop]; - if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue; - }else{ - pLoop = pLast; - } - if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered - && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) - ){ - obSat = obDone; - } - break; - } - iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; - - /* Mark off any ORDER BY term X that is a column in the table of - ** the current loop for which there is term in the WHERE - ** clause of the form X IS NULL or X=? that reference only outer - ** loops. - */ - for(i=0; ia[i].pExpr); - if( NEVER(pOBExpr==0) ) continue; - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, - ~ready, eqOpMask, 0); - if( pTerm==0 ) continue; - if( pTerm->eOperator==WO_IN ){ - /* IN terms are only valid for sorting in the ORDER BY LIMIT - ** optimization, and then only if they are actually used - ** by the query plan */ - assert( wctrlFlags & - (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ); - for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){} - if( j>=pLoop->nLTerm ) continue; - } - if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ - Parse *pParse = pWInfo->pParse; - CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr); - CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr); - assert( pColl1 ); - if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){ - continue; - } - testcase( pTerm->pExpr->op==TK_IS ); - } - obSat |= MASKBIT(i); - } - - if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ - if( pLoop->wsFlags & WHERE_IPK ){ - if( pLoop->u.btree.pOrderBy - && OptimizationEnabled(db, SQLITE_OrderBySubq) - && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur, - pOrderBy,pRevMask, &obSat) - ){ - nColumn = 0; - isOrderDistinct = 0; - }else{ - nColumn = 1; - } - pIndex = 0; - nKeyCol = 0; - }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ - return 0; - }else{ - nKeyCol = pIndex->nKeyCol; - nColumn = pIndex->nColumn; - assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); - assert( pIndex->aiColumn[nColumn-1]==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 isOrderDistinct 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; - } - - /* Loop through all columns of the index and deal with the ones - ** that are not constrained by == or IN. - */ - rev = revSet = 0; - distinctColumns = 0; - for(j=0; j=pLoop->u.btree.nEq - || (pLoop->aLTerm[j]==0)==(jnSkip) - ); - if( ju.btree.nEq && j>=pLoop->nSkip ){ - u16 eOp = pLoop->aLTerm[j]->eOperator; - - /* Skip over == and IS and ISNULL terms. (Also skip IN terms when - ** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL - ** terms imply that the index is not UNIQUE NOT NULL in which case - ** the loop need to be marked as not order-distinct because it can - ** have repeated NULL rows. - ** - ** If the current term is a column of an ((?,?) IN (SELECT...)) - ** expression for which the SELECT returns more than one column, - ** check that it is the only column used by this loop. Otherwise, - ** if it is one of two or more, none of the columns can be - ** considered to match an ORDER BY term. - */ - if( (eOp & eqOpMask)!=0 ){ - if( eOp & (WO_ISNULL|WO_IS) ){ - testcase( eOp & WO_ISNULL ); - testcase( eOp & WO_IS ); - testcase( isOrderDistinct ); - isOrderDistinct = 0; - } - continue; - }else if( ALWAYS(eOp & WO_IN) ){ - /* ALWAYS() justification: eOp is an equality operator due to the - ** ju.btree.nEq constraint above. Any equality other - ** than WO_IN is captured by the previous "if". So this one - ** always has to be WO_IN. */ - Expr *pX = pLoop->aLTerm[j]->pExpr; - for(i=j+1; iu.btree.nEq; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - assert( (pLoop->aLTerm[i]->eOperator & WO_IN) ); - bOnce = 0; - break; - } - } - } - } - - /* Get the column number in the table (iColumn) and sort order - ** (revIdx) for the j-th column of the index. - */ - if( pIndex ){ - iColumn = pIndex->aiColumn[j]; - revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC; - if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; - }else{ - iColumn = XN_ROWID; - revIdx = 0; - } - - /* An unconstrained column that might be NULL means that this - ** WhereLoop is not well-ordered. tag-20210426-1 - */ - 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 - ** of the index and mark that ORDER BY term having been satisfied. - */ - isMatch = 0; - for(i=0; bOnce && ia[i].pExpr); - testcase( wctrlFlags & WHERE_GROUPBY ); - testcase( wctrlFlags & WHERE_DISTINCTBY ); - if( NEVER(pOBExpr==0) ) continue; - if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( iColumn>=XN_ROWID ){ - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; - }else{ - Expr *pIxExpr = pIndex->aColExpr->a[j].pExpr; - if( sqlite3ExprCompareSkip(pOBExpr, pIxExpr, iCur) ){ - continue; - } - } - if( iColumn!=XN_ROWID ){ - pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; - } - if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = j+1; - } - isMatch = 1; - break; - } - if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){ - /* Make sure the sort order is compatible in an ORDER BY clause. - ** Sort order is irrelevant for a GROUP BY clause. */ - if( revSet ){ - if( (rev ^ revIdx) - != (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC) - ){ - isMatch = 0; - } - }else{ - rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC); - if( rev ) *pRevMask |= MASKBIT(iLoop); - revSet = 1; - } - } - if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){ - if( j==pLoop->u.btree.nEq ){ - pLoop->wsFlags |= WHERE_BIGNULL_SORT; - }else{ - isMatch = 0; - } - } - if( isMatch ){ - if( iColumn==XN_ROWID ){ - testcase( distinctColumns==0 ); - distinctColumns = 1; - } - obSat |= MASKBIT(i); - }else{ - /* No match found */ - if( j==0 || jmaskSelf; - for(i=0; ia[i].pExpr; - mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue; - if( (mTerm&~orderDistinctMask)==0 ){ - obSat |= MASKBIT(i); - } - } - } - } /* End the loop over all WhereLoops from outer-most down to inner-most */ - if( obSat==obDone ) return (i8)nOrderBy; - if( !isOrderDistinct ){ - for(i=nOrderBy-1; i>0; i--){ - Bitmask m = ALWAYS(iwctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY) ); - assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); - return pWInfo->sorted; -} - -#ifdef WHERETRACE_ENABLED -/* For debugging use only: */ -static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ - static char zName[65]; - int i; - for(i=0; iaLoop[i]->cId; } - if( pLast ) zName[i++] = pLast->cId; - zName[i] = 0; - return zName; -} -#endif - -/* -** Return the cost of sorting nRow rows, assuming that the keys have -** nOrderby columns and that the first nSorted columns are already in -** order. -*/ -static LogEst whereSortingCost( - WhereInfo *pWInfo, /* Query planning context */ - LogEst nRow, /* Estimated number of rows to sort */ - int nOrderBy, /* Number of ORDER BY clause terms */ - int nSorted /* Number of initial ORDER BY terms naturally in order */ -){ - /* Estimated cost of a full external sort, where N is - ** the number of rows to sort is: - ** - ** cost = (K * N * log(N)). - ** - ** Or, if the order-by clause has X terms but only the last Y - ** terms are out of order, then block-sorting will reduce the - ** sorting cost to: - ** - ** cost = (K * N * log(N)) * (Y/X) - ** - ** The constant K is at least 2.0 but will be larger if there are a - ** large number of columns to be sorted, as the sorting time is - ** proportional to the amount of content to be sorted. The algorithm - ** does not currently distinguish between fat columns (BLOBs and TEXTs) - ** and skinny columns (INTs). It just uses the number of columns as - ** an approximation for the row width. - ** - ** And extra factor of 2.0 or 3.0 is added to the sorting cost if the sort - ** is built using OP_IdxInsert and OP_Sort rather than with OP_SorterInsert. - */ - LogEst rSortCost, nCol; - assert( pWInfo->pSelect!=0 ); - assert( pWInfo->pSelect->pEList!=0 ); - /* TUNING: sorting cost proportional to the number of output columns: */ - nCol = sqlite3LogEst((pWInfo->pSelect->pEList->nExpr+59)/30); - rSortCost = nRow + nCol; - if( nSorted>0 ){ - /* Scale the result by (Y/X) */ - rSortCost += sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; - } - - /* Multiple by log(M) where M is the number of output rows. - ** Use the LIMIT for M if it is smaller. Or if this sort is for - ** a DISTINCT operator, M will be the number of distinct output - ** rows, so fudge it downwards a bit. - */ - if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 ){ - rSortCost += 10; /* TUNING: Extra 2.0x if using LIMIT */ - if( nSorted!=0 ){ - rSortCost += 6; /* TUNING: Extra 1.5x if also using partial sort */ - } - if( pWInfo->iLimitiLimit; - } - }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==sqlite3LogEst(2) ); } - } - rSortCost += estLog(nRow); - return rSortCost; -} - -/* -** Compute the maximum number of paths in the solver algorithm, for -** queries that have three or more terms in the FROM clause. Queries with -** two or fewer FROM clause terms are handled by the caller. -** -** Query planning is NP-hard. We must limit the number of paths at -** each step of the solver search algorithm to avoid exponential behavior. -** -** The value returned is a tuning parameter. Currently the value is: -** -** 18 for star queries -** 12 otherwise -** -** For the purposes of this heuristic, a star-query is defined as a query -** with a large central table that is joined using an INNER JOIN, -** not CROSS or OUTER JOINs, against four or more smaller tables. -** The central table is called the "fact" table. The smaller tables -** that get joined are "dimension tables". Also, any table that is -** self-joined cannot be a dimension table; we assume that dimension -** tables may only be joined against fact tables. -** -** SIDE EFFECT: (and really the whole point of this subroutine) -** -** If pWInfo describes a star-query, then the cost for SCANs of dimension -** WhereLoops is increased to be slightly larger than the cost of a SCAN -** in the fact table. Only SCAN costs are increased. SEARCH costs are -** unchanged. This heuristic helps keep fact tables in outer loops. Without -** this heuristic, paths with fact tables in outer loops tend to get pruned -** by the mxChoice limit on the number of paths, resulting in poor query -** plans. See the starschema1.test test module for examples of queries -** that need this heuristic to find good query plans. -** -** This heuristic can be completely disabled, so that no query is -** considered a star-query, using SQLITE_TESTCTRL_OPTIMIZATION to -** disable the SQLITE_StarQuery optimization. In the CLI, the command -** to do that is: ".testctrl opt -starquery". -** -** HISTORICAL NOTES: -** -** This optimization was first added on 2024-05-09 by check-in 38db9b5c83d. -** The original optimization reduced the cost and output size estimate for -** fact tables to help them move to outer loops. But months later (as people -** started upgrading) performance regression reports started caming in, -** including: -** -** forum post b18ef983e68d06d1 (2024-12-21) -** forum post 0025389d0860af82 (2025-01-14) -** forum post d87570a145599033 (2025-01-17) -** -** To address these, the criteria for a star-query was tightened to exclude -** cases where the fact and dimensions are separated by an outer join, and -** the affect of star-schema detection was changed to increase the rRun cost -** on just full table scans of dimension tables, rather than reducing costs -** in the all access methods of the fact table. -*/ -static int computeMxChoice(WhereInfo *pWInfo){ - int nLoop = pWInfo->nLevel; /* Number of terms in the join */ - WhereLoop *pWLoop; /* For looping over WhereLoops */ - -#ifdef SQLITE_DEBUG - /* The star-query detection code below makes use of the following - ** properties of the WhereLoop list, so verify them before - ** continuing: - ** (1) .maskSelf is the bitmask corresponding to .iTab - ** (2) The WhereLoop list is in ascending .iTab order - */ - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - assert( pWLoop->maskSelf==MASKBIT(pWLoop->iTab) ); - assert( pWLoop->pNextLoop==0 || pWLoop->iTab<=pWLoop->pNextLoop->iTab ); - } -#endif /* SQLITE_DEBUG */ - - if( nLoop>=5 - && !pWInfo->bStarDone - && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery) - ){ - SrcItem *aFromTabs; /* All terms of the FROM clause */ - int iFromIdx; /* Term of FROM clause is the candidate fact-table */ - Bitmask m; /* Bitmask for candidate fact-table */ - Bitmask mSelfJoin = 0; /* Tables that cannot be dimension tables */ - WhereLoop *pStart; /* Where to start searching for dimension-tables */ - - pWInfo->bStarDone = 1; /* Only do this computation once */ - - /* Look for fact tables with four or more dimensions where the - ** dimension tables are not separately from the fact tables by an outer - ** or cross join. Adjust cost weights if found. - */ - assert( !pWInfo->bStarUsed ); - aFromTabs = pWInfo->pTabList->a; - pStart = pWInfo->pLoops; - for(iFromIdx=0, m=1; iFromIdxfg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - /* If the candidate fact-table is the right table of an outer join - ** restrict the search for dimension-tables to be tables to the right - ** of the fact-table. */ - if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */ - while( pStart && pStart->iTab<=iFromIdx ){ - pStart = pStart->pNextLoop; - } - } - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - /* Fact-tables and dimension-tables cannot be separated by an - ** outer join (at least for the definition of fact- and dimension- - ** used by this heuristic). */ - break; - } - if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */ - && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */ - && (pWLoop->maskSelf & mSelfJoin)==0 /* Not a self-join */ - ){ - if( aFromTabs[pWLoop->iTab].pSTab==pFactTab->pSTab ){ - mSelfJoin |= m; - }else{ - nDep++; - mSeen |= pWLoop->maskSelf; - } - } - } - if( nDep<=3 ) continue; - - /* If we reach this point, it means that pFactTab is a fact table - ** with four or more dimensions connected by inner joins. Proceed - ** to make cost adjustments. */ - -#ifdef WHERETRACE_ENABLED - /* Make sure rStarDelta values are initialized */ - if( !pWInfo->bStarUsed ){ - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - pWLoop->rStarDelta = 0; - } - } -#endif - pWInfo->bStarUsed = 1; - - /* Compute the maximum cost of any WhereLoop for the - ** fact table plus one epsilon */ - mxRun = LOGEST_MIN; - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( pWLoop->iTabiTab>iFromIdx ) break; - if( pWLoop->rRun>mxRun ) mxRun = pWLoop->rRun; - } - if( ALWAYS(mxRunpNextLoop){ - if( (pWLoop->maskSelf & mSeen)==0 ) continue; - if( pWLoop->nLTerm ) continue; - if( pWLoop->rRuniTab; - sqlite3DebugPrintf( - "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab, - pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, - iFromIdx, mxRun - ); - } - pWLoop->rStarDelta = mxRun - pWLoop->rRun; -#endif /* WHERETRACE_ENABLED */ - pWLoop->rRun = mxRun; - } - } - } -#ifdef WHERETRACE_ENABLED /* 0x80000 */ - if( (sqlite3WhereTrace & 0x80000)!=0 && pWInfo->bStarUsed ){ - sqlite3DebugPrintf("WhereLoops changed by star-query heuristic:\n"); - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( pWLoop->rStarDelta ){ - sqlite3WhereLoopPrint(pWLoop, &pWInfo->sWC); - } - } - } -#endif - } - return pWInfo->bStarUsed ? 18 : 12; -} - -/* -** Two WhereLoop objects, pCandidate and pBaseline, are known to have the -** same cost. Look deep into each to see if pCandidate is even slightly -** better than pBaseline. Return false if it is, if pCandidate is is preferred. -** Return true if pBaseline is preferred or if we cannot tell the difference. -** -** Result Meaning -** -------- ---------------------------------------------------------- -** true We cannot tell the difference in pCandidate and pBaseline -** false pCandidate seems like a better choice than pBaseline -*/ -static SQLITE_NOINLINE int whereLoopIsNoBetter( - const WhereLoop *pCandidate, - const WhereLoop *pBaseline -){ - if( (pCandidate->wsFlags & WHERE_INDEXED)==0 ) return 1; - if( (pBaseline->wsFlags & WHERE_INDEXED)==0 ) return 1; - if( pCandidate->u.btree.pIndex->szIdxRow < - pBaseline->u.btree.pIndex->szIdxRow ) return 0; - return 1; -} - -/* -** Given the list of WhereLoop objects at pWInfo->pLoops, this routine -** attempts to find the lowest cost path that visits each WhereLoop -** once. This path is then loaded into the pWInfo->a[].pWLoop fields. -** -** Assume that the total number of output rows that will need to be sorted -** will be nRowEst (in the 10*log2 representation). Or, ignore sorting -** costs if nRowEst==0. -** -** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation -** error occurs. -*/ -static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ - int mxChoice; /* Maximum number of simultaneous paths tracked */ - int nLoop; /* Number of terms in the join */ - Parse *pParse; /* Parsing context */ - int iLoop; /* Loop counter over the terms of the join */ - int ii, jj; /* Loop counters */ - int mxI = 0; /* Index of next entry to replace */ - int nOrderBy; /* Number of ORDER BY clause terms */ - LogEst mxCost = 0; /* Maximum cost of a set of paths */ - LogEst mxUnsort = 0; /* Maximum unsorted cost of a set of path */ - int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ - WherePath *aFrom; /* All nFrom paths at the previous level */ - WherePath *aTo; /* The nTo best paths at the current level */ - WherePath *pFrom; /* An element of aFrom[] that we are working on */ - WherePath *pTo; /* An element of aTo[] that we are working on */ - WhereLoop *pWLoop; /* One of the WhereLoop objects */ - WhereLoop **pX; /* Used to divy up the pSpace memory */ - LogEst *aSortCost = 0; /* Sorting and partial sorting costs */ - char *pSpace; /* Temporary memory used by this routine */ - int nSpace; /* Bytes of space allocated at pSpace */ - - pParse = pWInfo->pParse; - nLoop = pWInfo->nLevel; - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n", - nRowEst, pParse->nQueryLoop)); - /* TUNING: mxChoice is the maximum number of possible paths to preserve - ** at each step. Based on the number of loops in the FROM clause: - ** - ** nLoop mxChoice - ** ----- -------- - ** 1 1 // the most common case - ** 2 5 - ** 3+ 12 or 18 // see computeMxChoice() - */ - if( nLoop<=1 ){ - mxChoice = 1; - }else if( nLoop==2 ){ - mxChoice = 5; - }else if( pParse->nErr ){ - mxChoice = 1; - }else{ - mxChoice = computeMxChoice(pWInfo); - } - assert( nLoop<=pWInfo->pTabList->nSrc ); - - /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this - ** case the purpose of this call is to estimate the number of rows returned - ** by the overall query. Once this estimate has been obtained, the caller - ** will invoke this function a second time, passing the estimate as the - ** nRowEst parameter. */ - if( pWInfo->pOrderBy==0 || nRowEst==0 ){ - nOrderBy = 0; - }else{ - nOrderBy = pWInfo->pOrderBy->nExpr; - } - - /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ - nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; - nSpace += sizeof(LogEst) * nOrderBy; - pSpace = sqlite3StackAllocRawNN(pParse->db, nSpace); - if( pSpace==0 ) return SQLITE_NOMEM_BKPT; - aTo = (WherePath*)pSpace; - aFrom = aTo+mxChoice; - memset(aFrom, 0, sizeof(aFrom[0])); - pX = (WhereLoop**)(aFrom+mxChoice); - for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){ - pFrom->aLoop = pX; - } - if( nOrderBy ){ - /* If there is an ORDER BY clause and it is not being ignored, set up - ** space for the aSortCost[] array. Each element of the aSortCost array - ** is either zero - meaning it has not yet been initialized - or the - ** cost of sorting nRowEst rows of data where the first X terms of - ** the ORDER BY clause are already in order, where X is the array - ** index. */ - aSortCost = (LogEst*)pX; - memset(aSortCost, 0, sizeof(LogEst) * nOrderBy); - } - assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] ); - assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX ); - - /* Seed the search with a single WherePath containing zero WhereLoops. - ** - ** TUNING: Do not let the number of iterations go above 28. If the cost - ** of computing an automatic index is not paid back within the first 28 - ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) ); - nFrom = 1; - assert( aFrom[0].isOrdered==0 ); - if( nOrderBy ){ - /* If nLoop is zero, then there are no FROM terms in the query. Since - ** in this case the query may return a maximum of one row, the results - ** are already in the requested order. Set isOrdered to nOrderBy to - ** indicate this. Or, if nLoop is greater than zero, set isOrdered to - ** -1, indicating that the result set may or may not be ordered, - ** depending on the loops added to the current plan. */ - aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy; - } - - /* Compute successively longer WherePaths using the previous generation - ** of WherePaths as the basis for the next. Keep track of the mxChoice - ** best paths at each generation */ - for(iLoop=0; iLooppLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - LogEst nOut; /* Rows visited by (pFrom+pWLoop) */ - LogEst rCost; /* Cost of path (pFrom+pWLoop) */ - LogEst rUnsort; /* Unsorted cost of (pFrom+pWLoop) */ - i8 isOrdered; /* isOrdered for (pFrom+pWLoop) */ - Bitmask maskNew; /* Mask of src visited by (..) */ - Bitmask revMask; /* Mask of rev-order loops for (..) */ - - if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ - /* Do not use an automatic index if the this loop is expected - ** to run less than 1.25 times. It is tempting to also exclude - ** automatic index usage on an outer loop, but sometimes an automatic - ** index is useful in the outer loop of a correlated subquery. */ - assert( 10==sqlite3LogEst(2) ); - continue; - } - - /* At this point, pWLoop is a candidate to be the next loop. - ** Compute its cost */ - rUnsort = pWLoop->rRun + pFrom->nRow; - if( pWLoop->rSetup ){ - rUnsort = sqlite3LogEstAdd(pWLoop->rSetup, rUnsort); - } - rUnsort = sqlite3LogEstAdd(rUnsort, pFrom->rUnsort); - nOut = pFrom->nRow + pWLoop->nOut; - maskNew = pFrom->maskLoop | pWLoop->maskSelf; - isOrdered = pFrom->isOrdered; - if( isOrdered<0 ){ - revMask = 0; - isOrdered = wherePathSatisfiesOrderBy(pWInfo, - pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, - iLoop, pWLoop, &revMask); - }else{ - revMask = pFrom->revLoop; - } - if( isOrdered>=0 && isOrderedisOrdered^isOrdered)&0x80)==0" is equivalent - ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range - ** of legal values for isOrdered, -1..64. - */ - testcase( nTo==0 ); - for(jj=0, pTo=aTo; jjmaskLoop==maskNew - && ((pTo->isOrdered^isOrdered)&0x80)==0 - ){ - testcase( jj==nTo-1 ); - break; - } - } - if( jj>=nTo ){ - /* None of the existing best-so-far paths match the candidate. */ - if( nTo>=mxChoice - && (rCost>mxCost || (rCost==mxCost && rUnsort>=mxUnsort)) - ){ - /* The current candidate is no better than any of the mxChoice - ** paths currently in the best-so-far buffer. So discard - ** this candidate as not viable. */ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, - isOrdered>=0 ? isOrdered+'0' : '?'); - } -#endif - continue; - } - /* If we reach this points it means that the new candidate path - ** needs to be added to the set of best-so-far paths. */ - if( nTo=0 ? isOrdered+'0' : '?'); - } -#endif - }else{ - /* Control reaches here if best-so-far path pTo=aTo[jj] covers the - ** same set of loops and has the same isOrdered setting as the - ** candidate path. Check to see if the candidate should replace - ** pTo or if the candidate should be skipped. - ** - ** The conditional is an expanded vector comparison equivalent to: - ** (pTo->rCost,pTo->nRow,pTo->rUnsort) <= (rCost,nOut,rUnsort) - */ - if( (pTo->rCostrCost==rCost && pTo->nRowrCost==rCost && pTo->nRow==nOut && pTo->rUnsortrCost==rCost && pTo->nRow==nOut && pTo->rUnsort==rUnsort - && whereLoopIsNoBetter(pWLoop, pTo->aLoop[iLoop]) ) - ){ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf( - "Skip %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, - isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); - } -#endif - /* Discard the candidate path from further consideration */ - testcase( pTo->rCost==rCost ); - continue; - } - testcase( pTo->rCost==rCost+1 ); - /* Control reaches here if the candidate path is better than the - ** pTo path. Replace pTo with the candidate. */ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf( - "Update %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, - isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); - } -#endif - } - /* pWLoop is a winner. Add it to the set of best so far */ - pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; - pTo->revLoop = revMask; - pTo->nRow = nOut; - pTo->rCost = rCost; - pTo->rUnsort = rUnsort; - pTo->isOrdered = isOrdered; - memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); - pTo->aLoop[iLoop] = pWLoop; - if( nTo>=mxChoice ){ - mxI = 0; - mxCost = aTo[0].rCost; - mxUnsort = aTo[0].nRow; - for(jj=1, pTo=&aTo[1]; jjrCost>mxCost - || (pTo->rCost==mxCost && pTo->rUnsort>mxUnsort) - ){ - mxCost = pTo->rCost; - mxUnsort = pTo->rUnsort; - mxI = jj; - } - } - } - } - } - -#ifdef WHERETRACE_ENABLED /* >=2 */ - if( sqlite3WhereTrace & 0x02 ){ - LogEst rMin, rFloor = 0; - int nDone = 0; - int nProgress; - sqlite3DebugPrintf("---- after round %d ----\n", iLoop); - do{ - nProgress = 0; - rMin = 0x7fff; - for(ii=0, pTo=aTo; iirCost>rFloor && pTo->rCostrCost; - } - for(ii=0, pTo=aTo; iirCost==rMin ){ - sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?'); - if( pTo->isOrdered>0 ){ - sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop); - }else{ - sqlite3DebugPrintf("\n"); - } - nDone++; - nProgress++; - } - } - rFloor = rMin; - }while( nDone0 ); - } -#endif - - /* Swap the roles of aFrom and aTo for the next generation */ - pFrom = aTo; - aTo = aFrom; - aFrom = pFrom; - nFrom = nTo; - } - - if( nFrom==0 ){ - sqlite3ErrorMsg(pParse, "no query solution"); - sqlite3StackFreeNN(pParse->db, pSpace); - return SQLITE_ERROR; - } - - /* Find the lowest cost path. pFrom will be left pointing to that path */ - pFrom = aFrom; - for(ii=1; iirCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; - } - assert( pWInfo->nLevel==nLoop ); - /* Load the lowest cost path into pWInfo */ - for(iLoop=0; iLoopa + iLoop; - pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; - pLevel->iFrom = pWLoop->iTab; - pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor; - } - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 - && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 - && pWInfo->eDistinct==WHERE_DISTINCT_NOOP - && nRowEst - ){ - Bitmask notUsed; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, - WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); - if( rc==pWInfo->pResultSet->nExpr ){ - pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; - } - } - 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; - } - /* vvv--- See check-in [12ad822d9b827777] on 2023-03-16 ---vvv */ - assert( pWInfo->pSelect->pOrderBy==0 - || pWInfo->nOBSat <= pWInfo->pSelect->pOrderBy->nExpr ); - }else{ - pWInfo->revMask = pFrom->revLoop; - if( pWInfo->nOBSat<=0 ){ - pWInfo->nOBSat = 0; - if( nLoop>0 ){ - u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; - if( (wsFlags & WHERE_ONEROW)==0 - && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) - ){ - Bitmask m = 0; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, - WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); - testcase( wsFlags & WHERE_IPK ); - testcase( wsFlags & WHERE_COLUMN_IN ); - if( rc==pWInfo->pOrderBy->nExpr ){ - pWInfo->bOrderedInnerLoop = 1; - pWInfo->revMask = m; - } - } - } - }else if( nLoop - && pWInfo->nOBSat==1 - && (pWInfo->wctrlFlags & (WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX))!=0 - ){ - pWInfo->bOrderedInnerLoop = 1; - } - } - if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 - ){ - Bitmask revMask = 0; - int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, - pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask - ); - assert( pWInfo->sorted==0 ); - if( nOrder==pWInfo->pOrderBy->nExpr ){ - pWInfo->sorted = 1; - pWInfo->revMask = revMask; - } - } - } - - pWInfo->nRowOut = pFrom->nRow; -#ifdef WHERETRACE_ENABLED - pWInfo->rTotalCost = pFrom->rCost; -#endif - - /* Free temporary memory and return success */ - sqlite3StackFreeNN(pParse->db, pSpace); - return SQLITE_OK; -} - -/* -** This routine implements a heuristic designed to improve query planning. -** This routine is called in between the first and second call to -** wherePathSolver(). Hence the name "Interstage" "Heuristic". -** -** The first call to wherePathSolver() (hereafter just "solver()") computes -** the best path without regard to the order of the outputs. The second call -** to the solver() builds upon the first call to try to find an alternative -** path that satisfies the ORDER BY clause. -** -** This routine looks at the results of the first solver() run, and for -** every FROM clause term in the resulting query plan that uses an equality -** constraint against an index, disable other WhereLoops for that same -** FROM clause term that would try to do a full-table scan. This prevents -** an index search from being converted into a full-table scan in order to -** satisfy an ORDER BY clause, since even though we might get slightly better -** performance using the full-scan without sorting if the output size -** estimates are very precise, we might also get severe performance -** degradation using the full-scan if the output size estimate is too large. -** It is better to err on the side of caution. -** -** Except, if the first solver() call generated a full-table scan in an outer -** loop then stop this analysis at the first full-scan, since the second -** solver() run might try to swap that full-scan for another in order to -** get the output into the correct order. In other words, we allow a -** rewrite like this: -** -** First Solver() Second Solver() -** |-- SCAN t1 |-- SCAN t2 -** |-- SEARCH t2 `-- SEARCH t1 -** `-- SORT USING B-TREE -** -** The purpose of this routine is to disallow rewrites such as: -** -** First Solver() Second Solver() -** |-- SEARCH t1 |-- SCAN t2 <--- bad! -** |-- SEARCH t2 `-- SEARCH t1 -** `-- SORT USING B-TREE -** -** See test cases in test/whereN.test for the real-world query that -** originally provoked this heuristic. -*/ -static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){ - int i; -#ifdef WHERETRACE_ENABLED - int once = 0; -#endif - for(i=0; inLevel; i++){ - WhereLoop *p = pWInfo->a[i].pWLoop; - if( p==0 ) break; - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue; - if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ - u8 iTab = p->iTab; - WhereLoop *pLoop; - for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){ - if( pLoop->iTab!=iTab ) continue; - if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){ - /* Auto-index and index-constrained loops allowed to remain */ - continue; - } -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x80 ){ - if( once==0 ){ - sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n"); - once = 1; - } - sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC); - } -#endif /* WHERETRACE_ENABLED */ - pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */ - } - }else{ - break; - } - } -} - -/* -** Most queries use only a single table (they are not joins) and have -** simple == constraints against indexed fields. This routine attempts -** to plan those simple cases using much less ceremony than the -** general-purpose query planner, and thereby yield faster sqlite3_prepare() -** times for the common case. -** -** Return non-zero on success, if this query can be handled by this -** no-frills query planner. Return zero if this query needs the -** general-purpose query planner. -*/ -static int whereShortCut(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo; - SrcItem *pItem; - WhereClause *pWC; - WhereTerm *pTerm; - WhereLoop *pLoop; - int iCur; - int j; - Table *pTab; - Index *pIdx; - WhereScan scan; - - pWInfo = pBuilder->pWInfo; - if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0; - assert( pWInfo->pTabList->nSrc>=1 ); - pItem = pWInfo->pTabList->a; - pTab = pItem->pSTab; - if( IsVirtual(pTab) ) 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 = 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; - pLoop->aLTerm[0] = pTerm; - pLoop->nLTerm = 1; - pLoop->u.btree.nEq = 1; - /* TUNING: Cost of a rowid lookup is 10 */ - pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ - }else{ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int opMask; - assert( pLoop->aLTermSpace==pLoop->aLTerm ); - if( !IsUniqueIndex(pIdx) - || pIdx->pPartIdxWhere!=0 - || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) - ) continue; - opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ; - for(j=0; jnKeyCol; j++){ - 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; - } - if( j!=pIdx->nKeyCol ) continue; - pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; - if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){ - pLoop->wsFlags |= WHERE_IDX_ONLY; - } - pLoop->nLTerm = j; - pLoop->u.btree.nEq = j; - pLoop->u.btree.pIndex = pIdx; - /* TUNING: Cost of a unique index lookup is 15 */ - pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */ - break; - } - } - if( pLoop->wsFlags ){ - pLoop->nOut = (LogEst)1; - pWInfo->a[0].pWLoop = pLoop; - assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] ); - pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */ - pWInfo->a[0].iTabCur = iCur; - pWInfo->nRowOut = 1; - if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr; - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - } - if( scan.iEquiv>1 ) pLoop->wsFlags |= WHERE_TRANSCONS; -#ifdef SQLITE_DEBUG - pLoop->cId = '0'; -#endif -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x02 ){ - sqlite3DebugPrintf("whereShortCut() used to compute solution\n"); - } -#endif - return 1; - } - return 0; -} - -/* -** Helper function for exprIsDeterministic(). -*/ -static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Continue; -} - -/* -** Return true if the expression contains no non-deterministic SQL -** functions. Do not consider non-deterministic SQL functions that are -** part of sub-select statements. -*/ -static int exprIsDeterministic(Expr *p){ - Walker w; - memset(&w, 0, sizeof(w)); - w.eCode = 1; - w.xExprCallback = exprNodeIsDeterministic; - w.xSelectCallback = sqlite3SelectWalkFail; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - - -#ifdef WHERETRACE_ENABLED -/* -** Display all WhereLoops in pWInfo -*/ -static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){ - if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ - WhereLoop *p; - int i; - static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" - "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; - for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%(sizeof(zLabel)-1)]; - sqlite3WhereLoopPrint(p, pWC); - } - } -} -# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C) -#else -# 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. -** 5) The table must not have an inner-join ON or USING clause if there is -** a RIGHT JOIN anywhere in the query. Otherwise the ON/USING clause -** might move from the right side to the left side of the RIGHT JOIN. -** Note: Due to (2), this condition can only arise if the table is -** the right-most table of a subquery that was flattened into the -** main query and that subquery was the right-hand operand of an -** inner join that held an ON or USING clause. -** 6) The ORDER BY clause has 63 or fewer terms -** 7) The omit-noop-join optimization is enabled. -** -** Items (1), (6), and (7) are checked by the caller. -** -** 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; - int hasRightJoin; - - /* 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 = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet); - if( pWInfo->pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy); - } - hasRightJoin = (pWInfo->pTabList->a[0].fg.jointype & JT_LTORJ)!=0; - for(i=pWInfo->nLevel-1; i>=1; i--){ - WhereTerm *pTerm, *pEnd; - SrcItem *pItem; - WhereLoop *pLoop; - Bitmask m1; - 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; pTermprereqAll & pLoop->maskSelf)!=0 ){ - if( !ExprHasProperty(pTerm->pExpr, EP_OuterON) - || pTerm->pExpr->w.iJoin!=pItem->iCursor - ){ - break; - } - } - if( hasRightJoin - && ExprHasProperty(pTerm->pExpr, EP_InnerON) - && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor) - ){ - break; /* restriction (5) */ - } - } - if( pTerm omit unused FROM-clause term %c\n",pLoop->cId)); - m1 = MASKBIT(i)-1; - testcase( ((pWInfo->revMask>>1) & ~m1)!=0 ); - pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1); - notReady &= ~pLoop->maskSelf; - for(pTerm=pWInfo->sWC.a; pTermprereqAll & 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 = 0; - - assert( pWInfo->nLevel>=2 ); - assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) ); - for(i=0; inLevel; i++){ - WhereLoop *pLoop = pWInfo->a[i].pWLoop; - const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); - SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; - Table *pTab = pItem->pSTab; - if( (pTab->tabFlags & TF_HasStat1)==0 ) break; - pTab->tabFlags |= TF_MaybeReanalyze; - if( i>=1 - && (pLoop->wsFlags & reqFlags)==reqFlags - /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ - && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) - ){ - if( nSearch > pTab->nRowLogEst ){ - testcase( pItem->fg.jointype & JT_LEFT ); - pLoop->wsFlags |= WHERE_BLOOMFILTER; - pLoop->wsFlags &= ~WHERE_IDX_ONLY; - WHERETRACE(0xffffffff, ( - "-> use Bloom-filter on loop %c because there are ~%.1e " - "lookups into %s which has only ~%.1e rows\n", - pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, - (double)sqlite3LogEstToInt(pTab->nRowLogEst))); - } - } - nSearch += pLoop->nOut; - } -} - -/* -** The index pIdx is used by a query and contains one or more expressions. -** In other words pIdx is an index on an expression. iIdxCur is the cursor -** number for the index and iDataCur is the cursor number for the corresponding -** table. -** -** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for -** each of the expressions in the index so that the expression code generator -** will know to replace occurrences of the indexed expression with -** references to the corresponding column of the index. -*/ -static SQLITE_NOINLINE void whereAddIndexedExpr( - Parse *pParse, /* Add IndexedExpr entries to pParse->pIdxEpr */ - Index *pIdx, /* The index-on-expression that contains the expressions */ - int iIdxCur, /* Cursor number for pIdx */ - SrcItem *pTabItem /* The FROM clause entry for the table */ -){ - int i; - IndexedExpr *p; - Table *pTab; - assert( pIdx->bHasExpr ); - pTab = pIdx->pTable; - for(i=0; inColumn; i++){ - Expr *pExpr; - int j = pIdx->aiColumn[i]; - if( j==XN_EXPR ){ - pExpr = pIdx->aColExpr->a[i].pExpr; - }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ - pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); - }else{ - continue; - } - if( sqlite3ExprIsConstant(0,pExpr) ) continue; - p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); - if( p==0 ) break; - p->pIENext = pParse->pIdxEpr; -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x200 ){ - sqlite3DebugPrintf("New pParse->pIdxEpr term {%d,%d}\n", iIdxCur, i); - if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(pExpr); - } -#endif - p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - p->iDataCur = pTabItem->iCursor; - p->iIdxCur = iIdxCur; - p->iIdxCol = i; - p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; - if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){ - p->aff = pIdx->zColAff[i]; - } -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - p->zIdxName = pIdx->zName; -#endif - pParse->pIdxEpr = p; - if( p->pIENext==0 ){ - void *pArg = (void*)&pParse->pIdxEpr; - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); - } - } -} - -/* -** Set the reverse-scan order mask to one for all tables in the query -** with the exception of MATERIALIZED common table expressions that have -** their own internal ORDER BY clauses. -** -** This implements the PRAGMA reverse_unordered_selects=ON setting. -** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER). -*/ -static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){ - int ii; - for(ii=0; iipTabList->nSrc; ii++){ - SrcItem *pItem = &pWInfo->pTabList->a[ii]; - if( !pItem->fg.isCte - || pItem->u2.pCteUse->eM10d!=M10d_Yes - || NEVER(pItem->fg.isSubquery==0) - || pItem->u4.pSubq->pSelect->pOrderBy==0 - ){ - pWInfo->revMask |= MASKBIT(ii); - } - } -} - -/* -** Generate the beginning of the loop used for WHERE clause processing. -** The return value is a pointer to an opaque structure that contains -** information needed to terminate the loop. Later, the calling routine -** should invoke sqlite3WhereEnd() with the return value of this function -** in order to complete the WHERE clause processing. -** -** If an error occurs, this routine returns NULL. -** -** The basic idea is to do a nested loop, one loop for each table in -** the FROM clause of a select. (INSERT and UPDATE statements are the -** same as a SELECT with only a single table in the FROM clause.) For -** example, if the SQL is this: -** -** SELECT * FROM t1, t2, t3 WHERE ...; -** -** Then the code generated is conceptually like the following: -** -** foreach row1 in t1 do \ Code generated -** foreach row2 in t2 do |-- by sqlite3WhereBegin() -** foreach row3 in t3 do / -** ... -** end \ Code generated -** end |-- by sqlite3WhereEnd() -** end / -** -** Note that the loops might not be nested in the order in which they -** appear in the FROM clause if a different order is better able to make -** use of indices. Note also that when the IN operator appears in -** the WHERE clause, it might result in additional nested loops for -** scanning through all values on the right-hand side of the IN. -** -** There are Btree cursors associated with each table. t1 uses cursor -** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. -** And so forth. This routine generates code to open those VDBE cursors -** and sqlite3WhereEnd() generates the code to close them. -** -** The code that sqlite3WhereBegin() generates leaves the cursors named -** in pTabList pointing at their appropriate entries. The [...] code -** can use OP_Column and OP_Rowid opcodes on these cursors to extract -** data from the various tables of the loop. -** -** If the WHERE clause is empty, the foreach loops must each scan their -** entire tables. Thus a three-way join is an O(N^3) operation. But if -** the tables have indices and there are terms in the WHERE clause that -** refer to those indices, a complete table scan can be avoided and the -** code will run much faster. Most of the work of this routine is checking -** to see if there are indices that can be used to speed up the loop. -** -** Terms of the WHERE clause are also used to limit which rows actually -** make it to the "..." in the middle of the loop. After each "foreach", -** terms of the WHERE clause that use only terms in that loop and outer -** loops are evaluated and if false a jump is made around all subsequent -** inner loops (or around the "..." if the test occurs within the inner- -** most loop) -** -** OUTER JOINS -** -** An outer join of tables t1 and t2 is conceptually coded as follows: -** -** foreach row1 in t1 do -** flag = 0 -** foreach row2 in t2 do -** start: -** ... -** flag = 1 -** end -** if flag==0 then -** move the row2 cursor to a null row -** goto start -** fi -** end -** -** ORDER BY CLAUSE PROCESSING -** -** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause -** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement -** if there is one. If there is no ORDER BY clause or if this routine -** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. -** -** The iIdxCur parameter is the cursor number of an index. If -** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index -** to use for OR clause processing. The WHERE clause should use this -** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is -** the first cursor in an array of cursors for all indices. iIdxCur should -** be used to compute the appropriate cursor depending on which index is -** used. -*/ -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ - 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 *pSelect, /* The entire SELECT statement */ - 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 */ -){ - int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ - int nTabList; /* Number of elements in pTabList */ - WhereInfo *pWInfo; /* Will become the return value of this function */ - Vdbe *v = pParse->pVdbe; /* The virtual database engine */ - Bitmask notReady; /* Cursors that are not yet positioned */ - WhereLoopBuilder sWLB; /* The WhereLoop builder */ - WhereMaskSet *pMaskSet; /* The expression mask set */ - WhereLevel *pLevel; /* A single level in pWInfo->a[] */ - WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ - int ii; /* Loop counter */ - sqlite3 *db; /* Database connection */ - int rc; /* Return code */ - u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ - - assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( - (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - )); - - /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */ - assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - || (wctrlFlags & WHERE_USE_LIMIT)==0 ); - - /* Variable initialization */ - db = pParse->db; - memset(&sWLB, 0, sizeof(sWLB)); - - /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ - testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); - if( pOrderBy && pOrderBy->nExpr>=BMS ){ - pOrderBy = 0; - wctrlFlags &= ~WHERE_WANT_DISTINCT; - wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */ - } - - /* The number of tables in the FROM clause is limited by the number of - ** bits in a Bitmask - */ - testcase( pTabList->nSrc==BMS ); - if( pTabList->nSrc>BMS ){ - sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); - return 0; - } - - /* This function normally generates a nested loop for all tables in - ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should - ** only generate code for the first table in pTabList and assume that - ** any cursors associated with subsequent tables are uninitialized. - */ - nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc; - - /* Allocate and initialize the WhereInfo structure that will become the - ** return value. A single allocation is used to store the WhereInfo - ** struct, the contents of WhereInfo.a[], the WhereClause structure - ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte - ** field (type Bitmask) it must be aligned on an 8-byte boundary on - ** some architectures. Hence the ROUND8() below. - */ - nByteWInfo = SZ_WHEREINFO(nTabList); - pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); - if( db->mallocFailed ){ - sqlite3DbFree(db, pWInfo); - pWInfo = 0; - goto whereBeginError; - } - pWInfo->pParse = pParse; - pWInfo->pTabList = pTabList; - pWInfo->pOrderBy = pOrderBy; -#if WHERETRACE_ENABLED - pWInfo->pWhere = pWhere; -#endif - pWInfo->pResultSet = pResultSet; - pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; - pWInfo->nLevel = nTabList; - pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); - pWInfo->wctrlFlags = wctrlFlags; - pWInfo->iLimit = iAuxArg; - pWInfo->savedNQueryLoop = pParse->nQueryLoop; - pWInfo->pSelect = pSelect; - 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 sqlite3WhereGetMask() */ - sWLB.pWInfo = pWInfo; - sWLB.pWC = &pWInfo->sWC; - sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); - assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); - whereLoopInit(sWLB.pNew); -#ifdef SQLITE_DEBUG - sWLB.pNew->cId = '*'; -#endif - - /* Split the WHERE clause into separate subexpressions where each - ** subexpression is separated by an AND operator. - */ - sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); - sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); - - /* Special case: No FROM clause - */ - if( nTabList==0 ){ - if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; - if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 - && OptimizationEnabled(db, SQLITE_DistinctOpt) - ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - } - if( ALWAYS(pWInfo->pSelect) - && (pWInfo->pSelect->selFlags & SF_MultiValue)==0 - ){ - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); - } - }else{ - /* Assign a bit from the bitmask to every term in the FROM clause. - ** - ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in - ** pTabList, not just the first nTabList tables. nTabList is normally - ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_OR_SUBCLAUSE flag is set. - */ - ii = 0; - do{ - createMask(pMaskSet, pTabList->a[ii].iCursor); - sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); - }while( (++ii)nSrc ); - #ifdef SQLITE_DEBUG - { - Bitmask mx = 0; - for(ii=0; iinSrc; ii++){ - Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); - assert( m>=mx ); - mx = m; - } - } - #endif - } - - /* Analyze all of the subexpressions. */ - sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( pSelect && pSelect->pLimit ){ - sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); - } - if( pParse->nErr ) goto whereBeginError; - - /* The False-WHERE-Term-Bypass optimization: - ** - ** If there are WHERE terms that are false, then no rows will be output, - ** so skip over all of the code generated here. - ** - ** Conditions: - ** - ** (1) The WHERE term must not refer to any tables in the join. - ** (2) The term must not come from an ON clause on the - ** right-hand side of a LEFT or FULL JOIN. - ** (3) The term must not come from an ON clause, or there must be - ** no RIGHT or FULL OUTER joins in pTabList. - ** (4) If the expression contains non-deterministic functions - ** that are not within a sub-select. This is not required - ** for correctness but rather to preserves SQLite's legacy - ** behaviour in the following two cases: - ** - ** WHERE random()>0; -- eval random() once per row - ** WHERE (SELECT random())>0; -- eval random() just once overall - ** - ** Note that the Where term need not be a constant in order for this - ** optimization to apply, though it does need to be constant relative to - ** the current subquery (condition 1). The term might include variables - ** from outer queries so that the value of the term changes from one - ** invocation of the current subquery to the next. - */ - for(ii=0; iinBase; ii++){ - WhereTerm *pT = &sWLB.pWC->a[ii]; /* A term of the WHERE clause */ - Expr *pX; /* The expression of pT */ - if( pT->wtFlags & TERM_VIRTUAL ) continue; - pX = pT->pExpr; - assert( pX!=0 ); - assert( pT->prereqAll!=0 || !ExprHasProperty(pX, EP_OuterON) ); - if( pT->prereqAll==0 /* Conditions (1) and (2) */ - && (nTabList==0 || exprIsDeterministic(pX)) /* Condition (4) */ - && !(ExprHasProperty(pX, EP_InnerON) /* Condition (3) */ - && (pTabList->a[0].fg.jointype & JT_LTORJ)!=0 ) - ){ - sqlite3ExprIfFalse(pParse, pX, pWInfo->iBreak, SQLITE_JUMPIFNULL); - pT->wtFlags |= TERM_CODED; - } - } - - if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** 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 ){ - /* Try to ORDER BY the result set to make distinct processing easier */ - pWInfo->wctrlFlags |= WHERE_DISTINCTBY; - pWInfo->pOrderBy = pResultSet; - } - } - - /* Construct the WhereLoop objects */ -#if defined(WHERETRACE_ENABLED) - if( sqlite3WhereTrace & 0xffffffff ){ - sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags); - if( wctrlFlags & WHERE_USE_LIMIT ){ - sqlite3DebugPrintf(", limit: %d", iAuxArg); - } - sqlite3DebugPrintf(")\n"); - if( sqlite3WhereTrace & 0x8000 ){ - Select sSelect; - memset(&sSelect, 0, sizeof(sSelect)); - sSelect.selFlags = SF_WhereBegin; - sSelect.pSrc = pTabList; - sSelect.pWhere = pWhere; - sSelect.pOrderBy = pOrderBy; - sSelect.pEList = pResultSet; - sqlite3TreeViewSelect(0, &sSelect, 0); - } - if( sqlite3WhereTrace & 0x4000 ){ /* Display all WHERE clause terms */ - sqlite3DebugPrintf("---- WHERE clause at start of analysis:\n"); - sqlite3WhereClausePrint(sWLB.pWC); - } - } -#endif - - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ - rc = whereLoopAddAll(&sWLB); - if( rc ) goto whereBeginError; - -#ifdef SQLITE_ENABLE_STAT4 - /* If one or more WhereTerm.truthProb values were used in estimating - ** loop parameters, but then those truthProb values were subsequently - ** changed based on STAT4 information while computing subsequent loops, - ** then we need to rerun the whole loop building process so that all - ** loops will be built using the revised truthProb values. */ - if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){ - WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); - WHERETRACE(0xffffffff, - ("**** Redo all loop computations due to" - " TERM_HIGHTRUTH changes ****\n")); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - rc = whereLoopAddAll(&sWLB); - if( rc ) goto whereBeginError; - } -#endif - WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); - - wherePathSolver(pWInfo, 0); - if( db->mallocFailed ) goto whereBeginError; - if( pWInfo->pOrderBy ){ - whereInterstageHeuristic(pWInfo); - wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1); - if( db->mallocFailed ) goto whereBeginError; - } - - /* TUNING: Assume that a DISTINCT clause on a subquery reduces - ** the output size by a factor of 8 (LogEst -30). Search for - ** tag-20250414a to see other cases. - */ - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - WHERETRACE(0x0080,("nRowOut reduced from %d to %d due to DISTINCT\n", - pWInfo->nRowOut, pWInfo->nRowOut-30)); - pWInfo->nRowOut -= 30; - } - - } - assert( pWInfo->pTabList!=0 ); - if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - whereReverseScanOrder(pWInfo); - } - if( pParse->nErr ){ - goto whereBeginError; - } - assert( db->mallocFailed==0 ); -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace ){ - sqlite3DebugPrintf("---- Solution cost=%d, nRow=%d", - pWInfo->rTotalCost, pWInfo->nRowOut); - if( pWInfo->nOBSat>0 ){ - sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); - } - switch( pWInfo->eDistinct ){ - case WHERE_DISTINCT_UNIQUE: { - sqlite3DebugPrintf(" DISTINCT=unique"); - break; - } - case WHERE_DISTINCT_ORDERED: { - sqlite3DebugPrintf(" DISTINCT=ordered"); - break; - } - case WHERE_DISTINCT_UNORDERED: { - sqlite3DebugPrintf(" DISTINCT=unordered"); - break; - } - } - sqlite3DebugPrintf("\n"); - for(ii=0; iinLevel; ii++){ - sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); - } - } -#endif - - /* Attempt to omit tables from a join that do not affect the result. - ** See the comment on whereOmitNoopJoin() for further information. - ** - ** This query optimization is factored out into a separate "no-inline" - ** procedure to keep the sqlite3WhereBegin() procedure from becoming - ** too large. If sqlite3WhereBegin() becomes too large, that prevents - ** some C-compiler optimizers from in-lining the - ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to - ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. - */ - notReady = ~(Bitmask)0; - if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */ - && pResultSet!=0 /* Condition (1) */ - && 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */ - && OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */ - ){ - 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( sqlite3WhereTrace & 0x4000 ){ /* Display all terms of the WHERE clause */ - sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n"); - sqlite3WhereClausePrint(sWLB.pWC); - } - WHERETRACE(0xffffffff,("*** Optimizer Finished ***\n")); -#endif - pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; - - /* If the caller is an UPDATE or DELETE statement that is requesting - ** to use a one-pass algorithm, determine if this is appropriate. - ** - ** A one-pass approach can be used if the caller has requested one - ** and either (a) the scan visits at most one row or (b) each - ** of the following are true: - ** - ** * the caller has indicated that a one-pass approach can be used - ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and - ** * the table is not a virtual table, and - ** * either the scan does not use the OR optimization or the caller - ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified - ** for DELETE). - ** - ** The last qualification is because an UPDATE statement uses - ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can - ** use a one-pass approach, and this is not set accurately for scans - ** that use the OR optimization. - */ - assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); - if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ - int wsFlags = pWInfo->a[0].pWLoop->wsFlags; - int bOnerow = (wsFlags & WHERE_ONEROW)!=0; - assert( !(wsFlags&WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pSTab) ); - if( bOnerow || ( - 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) - && !IsVirtual(pTabList->a[0].pSTab) - && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) - && OptimizationEnabled(db, SQLITE_OnePass) - )){ - pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; - if( HasRowid(pTabList->a[0].pSTab) && (wsFlags & WHERE_IDX_ONLY) ){ - if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ - bFordelete = OPFLAG_FORDELETE; - } - pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY); - } - } - } - - /* Open all tables in the pTabList and any indices selected for - ** searching those tables. - */ - for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; - pTab = pTabItem->pSTab; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pLoop = pLevel->pWLoop; - if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){ - /* Do nothing */ - }else -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - int iCur = pTabItem->iCursor; - sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); - }else if( IsVirtual(pTab) ){ - /* noop */ - }else -#endif - 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; - pWInfo->aiCurOnePass[0] = pTabItem->iCursor; - }; - sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); - assert( pTabItem->iCursor==pLevel->iTabCur ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); - if( pWInfo->eOnePass==ONEPASS_OFF - && pTab->nColtabFlags & (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 - ** the P4 operand of the OP_OpenRead/Write opcode. */ - Bitmask b = pTabItem->colUsed; - int n = 0; - for(; b; b=b>>1, n++){} - sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32); - assert( n<=pTab->nCol ); - } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - if( pLoop->u.btree.pIndex!=0 && (pTab->tabFlags & TF_WithoutRowid)==0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); - }else -#endif - { - sqlite3VdbeChangeP5(v, bFordelete); - } -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, - (const u8*)&pTabItem->colUsed, P4_INT64); -#endif - }else{ - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - } - if( pLoop->wsFlags & WHERE_INDEXED ){ - Index *pIx = pLoop->u.btree.pIndex; - int iIndexCur; - int op = OP_OpenRead; - /* iAuxArg is always set to a positive value if ONEPASS is possible */ - assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) - && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 - ){ - /* This is one term of an OR-optimization using the PRIMARY KEY of a - ** WITHOUT ROWID table. No need for a separate index */ - iIndexCur = pLevel->iTabCur; - op = 0; - }else if( pWInfo->eOnePass!=ONEPASS_OFF ){ - Index *pJ = pTabItem->pSTab->pIndex; - iIndexCur = iAuxArg; - assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); - while( ALWAYS(pJ) && pJ!=pIx ){ - iIndexCur++; - pJ = pJ->pNext; - } - op = OP_OpenWrite; - pWInfo->aiCurOnePass[1] = iIndexCur; - }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ - iIndexCur = iAuxArg; - op = OP_ReopenIdx; - }else{ - iIndexCur = pParse->nTab++; - if( pIx->bHasExpr && OptimizationEnabled(db, SQLITE_IndexedExpr) ){ - whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem); - } - if( pIx->pPartIdxWhere && (pTabItem->fg.jointype & JT_RIGHT)==0 ){ - wherePartIdxExpr( - pParse, pIx, pIx->pPartIdxWhere, 0, iIndexCur, pTabItem - ); - } - } - pLevel->iIdxCur = iIndexCur; - assert( pIx!=0 ); - assert( pIx->pSchema==pTab->pSchema ); - assert( iIndexCur>=0 ); - if( op ){ - sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIx); - if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 - && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 - && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0 - && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 - && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 - && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED - ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); - } - VdbeComment((v, "%s", pIx->zName)); -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - { - u64 colUsed = 0; - int ii, jj; - for(ii=0; iinColumn; ii++){ - jj = pIx->aiColumn[ii]; - if( jj<0 ) continue; - if( jj>63 ) jj = 63; - if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue; - colUsed |= ((u64)1)<<(ii<63 ? ii : 63); - } - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0, - (u8*)&colUsed, P4_INT64); - } -#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ - } - } - if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); - if( (pTabItem->fg.jointype & JT_RIGHT)!=0 - && (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0 - ){ - WhereRightJoin *pRJ = pLevel->pRJ; - pRJ->iMatch = pParse->nTab++; - pRJ->regBloom = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom); - pRJ->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn); - assert( pTab==pTabItem->pSTab ); - if( HasRowid(pTab) ){ - KeyInfo *pInfo; - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1); - pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0); - if( pInfo ){ - pInfo->aColl[0] = 0; - pInfo->aSortFlags[0] = 0; - sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO); - } - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol); - 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 = sqlite3VdbeCurrentAddr(v); - if( db->mallocFailed ) goto whereBeginError; - - /* Generate the code to do the search. Each iteration of the for - ** loop below generates code for a single nested loop of the VM - ** program. - */ - for(ii=0; iinErr ) goto whereBeginError; - pLevel = &pWInfo->a[ii]; - wsFlags = pLevel->pWLoop->wsFlags; - pSrc = &pTabList->a[pLevel->iFrom]; - if( pSrc->fg.isMaterialized ){ - Subquery *pSubq; - int iOnce = 0; - assert( pSrc->fg.isSubquery ); - pSubq = pSrc->u4.pSubq; - if( pSrc->fg.isCorrelated==0 ){ - iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - }else{ - iOnce = 0; - } - sqlite3VdbeAddOp2(v, OP_Gosub, pSubq->regReturn, pSubq->addrFillSub); - VdbeComment((v, "materialize %!S", pSrc)); - if( iOnce ) sqlite3VdbeJumpHere(v, iOnce); - } - assert( pTabList == pWInfo->pTabList ); - if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){ - if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){ -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - constructAutomaticIndex(pParse, &pWInfo->sWC, notReady, pLevel); -#endif - }else{ - sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady); - } - if( db->mallocFailed ) goto whereBeginError; - } - addrExplain = sqlite3WhereExplainOneScan( - pParse, pTabList, pLevel, wctrlFlags - ); - pLevel->addrBody = sqlite3VdbeCurrentAddr(v); - notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady); - pWInfo->iContinue = pLevel->addrCont; - if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){ - sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); - } - } - - /* Done. */ - VdbeModuleComment((v, "Begin WHERE-core")); - pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v); - return pWInfo; - - /* Jump here if malloc fails */ -whereBeginError: - if( pWInfo ){ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - } -#ifdef WHERETRACE_ENABLED - /* Prevent harmless compiler warnings about debugging routines - ** being declared but never used */ - sqlite3ShowWhereLoopList(0); -#endif /* WHERETRACE_ENABLED */ - return 0; -} - -/* -** Part of sqlite3WhereEnd() will rewrite opcodes to reference the -** index rather than the main table. In SQLITE_DEBUG mode, we want -** to trace those changes if PRAGMA vdbe_addoptrace=on. This routine -** does that. -*/ -#ifndef SQLITE_DEBUG -# define OpcodeRewriteTrace(D,K,P) /* no-op */ -#else -# define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P) - static void sqlite3WhereOpcodeRewriteTrace( - sqlite3 *db, - int pc, - VdbeOp *pOp - ){ - if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return; - sqlite3VdbePrintOp(0, pc, pOp); - sqlite3ShowWhereTerm(0); /* So compiler won't complain about unused func */ - } -#endif - -/* -** Generate the end of the WHERE loop. See comments on -** sqlite3WhereBegin() for additional information. -*/ -SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ - Parse *pParse = pWInfo->pParse; - Vdbe *v = pParse->pVdbe; - int i; - WhereLevel *pLevel; - WhereLoop *pLoop; - SrcList *pTabList = pWInfo->pTabList; - sqlite3 *db = pParse->db; - int iEnd = sqlite3VdbeCurrentAddr(v); - int nRJ = 0; - - /* Generate loop termination code. - */ - VdbeModuleComment((v, "End WHERE-core")); - 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; - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - pLevel->addrCont = 0; - pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v); - 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 - int addrSeek = 0; - Index *pIdx; - int n; - if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED - && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ - && (pLoop->wsFlags & WHERE_INDEXED)!=0 - && (pIdx = pLoop->u.btree.pIndex)->hasStat1 - && (n = pLoop->u.btree.nDistinctCol)>0 - && pIdx->aiRowLogEst[n]>=36 - ){ - int r1 = pParse->nMem+1; - int j, op; - for(j=0; jiIdxCur, j, r1+j); - } - pParse->nMem += n+1; - op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT; - addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n); - VdbeCoverageIf(v, op==OP_SeekLT); - VdbeCoverageIf(v, op==OP_SeekGT); - sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); - } -#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ - /* The common case: Advance to the next row */ - if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont); - sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); - sqlite3VdbeChangeP5(v, pLevel->p5); - VdbeCoverage(v); - VdbeCoverageIf(v, pLevel->op==OP_Next); - VdbeCoverageIf(v, pLevel->op==OP_Prev); - VdbeCoverageIf(v, pLevel->op==OP_VNext); - if( pLevel->regBignull ){ - sqlite3VdbeResolveLabel(v, pLevel->addrBignull); - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1); - VdbeCoverage(v); - } -#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT - if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); -#endif - }else if( pLevel->addrCont ){ - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - } - if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){ - struct InLoop *pIn; - int j; - sqlite3VdbeResolveLabel(v, pLevel->addrNxt); - for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ - assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull - || pParse->db->mallocFailed ); - sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - if( pIn->eEndLoopOp!=OP_Noop ){ - if( pIn->nPrefix ){ - int bEarlyOut = - (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 - && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0; - if( pLevel->iLeftJoin ){ - /* For LEFT JOIN queries, cursor pIn->iCur may not have been - ** opened yet. This occurs for WHERE clauses such as - ** "a = ? AND b IN (...)", where the index is on (a, b). If - ** the RHS of the (a=?) is NULL, then the "b IN (...)" may - ** never have been coded, but the body of the loop run to - ** return the null-row. So, if the cursor is not open yet, - ** jump over the OP_Next or OP_Prev instruction about to - ** be coded. */ - sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur, - sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut); - VdbeCoverage(v); - } - if( bEarlyOut ){ - sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, - 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. */ - sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - } - } - sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); - VdbeCoverage(v); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); - } - sqlite3VdbeJumpHere(v, pIn->addrInTop-1); - } - } - sqlite3VdbeResolveLabel(v, pLevel->addrBrk); - if( pLevel->pRJ ){ - sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1); - VdbeCoverage(v); - } - if( pLevel->addrSkip ){ - sqlite3VdbeGoto(v, pLevel->addrSkip); - VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); - sqlite3VdbeJumpHere(v, pLevel->addrSkip); - sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); - } -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pLevel->addrLikeRep ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), - pLevel->addrLikeRep); - VdbeCoverage(v); - } -#endif - if( pLevel->iLeftJoin ){ - int ws = pLoop->wsFlags; - addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); - assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); - if( (ws & WHERE_IDX_ONLY)==0 ){ - SrcItem *pSrc = &pTabList->a[pLevel->iFrom]; - assert( pLevel->iTabCur==pSrc->iCursor ); - if( pSrc->fg.viaCoroutine ){ - int m, n; - assert( pSrc->fg.isSubquery ); - n = pSrc->u4.pSubq->regResult; - assert( pSrc->pSTab!=0 ); - m = pSrc->pSTab->nCol; - sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1); - } - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); - } - if( (ws & WHERE_INDEXED) - || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx) - ){ - if( ws & WHERE_MULTI_OR ){ - Index *pIx = pLevel->u.pCoveringIdx; - int iDb = sqlite3SchemaToIndex(db, pIx->pSchema); - sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIx); - } - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); - } - if( pLevel->op==OP_Return ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); - }else{ - sqlite3VdbeGoto(v, pLevel->addrFirst); - } - sqlite3VdbeJumpHere(v, addr); - } - VdbeModuleComment((v, "End WHERE-loop%d: %s", i, - pWInfo->pTabList->a[pLevel->iFrom].pSTab->zName)); - } - - assert( pWInfo->nLevel<=pTabList->nSrc ); - for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ - int k, last; - VdbeOp *pOp, *pLastOp; - Index *pIdx = 0; - SrcItem *pTabItem = &pTabList->a[pLevel->iFrom]; - Table *pTab = pTabItem->pSTab; - 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 ){ - 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. - */ - if( pTabItem->fg.viaCoroutine ){ - testcase( pParse->db->mallocFailed ); - assert( pTabItem->fg.isSubquery ); - assert( pTabItem->u4.pSubq->regResult>=0 ); - translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, - pTabItem->u4.pSubq->regResult, 0); - continue; - } - - /* If this scan uses an index, make VDBE code substitutions to read data - ** from the index instead of from the table where possible. In some cases - ** this optimization prevents the table from ever being read, which can - ** yield a significant performance boost. - ** - ** Calls to the code generator in between sqlite3WhereBegin and - ** sqlite3WhereEnd will have created code that references the table - ** directly. This loop scans all that code looking for opcodes - ** that reference the table and converts them into opcodes that - ** reference the index. - */ - if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){ - pIdx = pLoop->u.btree.pIndex; - }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ - pIdx = pLevel->u.pCoveringIdx; - } - if( pIdx - && !db->mallocFailed - ){ - if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){ - last = iEnd; - }else{ - last = pWInfo->iEndWhere; - } - if( pIdx->bHasExpr ){ - IndexedExpr *p = pParse->pIdxEpr; - while( p ){ - if( p->iIdxCur==pLevel->iIdxCur ){ -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x200 ){ - sqlite3DebugPrintf("Disable pParse->pIdxEpr term {%d,%d}\n", - p->iIdxCur, p->iIdxCol); - if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(p->pExpr); - } -#endif - p->iDataCur = -1; - p->iIdxCur = -1; - } - p = p->pIENext; - } - } - k = pLevel->addrBody + 1; -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE cursor %d->%d in opcode range %d..%d\n", - pLevel->iTabCur, pLevel->iIdxCur, k, last-1); - } - /* Proof that the "+1" on the k value above is safe */ - pOp = sqlite3VdbeGetOp(v, k - 1); - assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur ); - assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur ); - assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur ); -#endif - pOp = sqlite3VdbeGetOp(v, k); - pLastOp = pOp + (last - k); - assert( pOp<=pLastOp ); - do{ - if( pOp->p1!=pLevel->iTabCur ){ - /* no-op */ - }else if( pOp->opcode==OP_Column -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - || pOp->opcode==OP_Offset -#endif - ){ - 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 = sqlite3PrimaryKeyIndex(pTab); - x = pPk->aiColumn[x]; - assert( x>=0 ); - }else{ - testcase( x!=sqlite3StorageColumnToTable(pTab,x) ); - x = sqlite3StorageColumnToTable(pTab,x); - } - x = sqlite3TableColumnToIndex(pIdx, x); - if( x>=0 ){ - pOp->p2 = x; - pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); - }else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){ - if( pLoop->wsFlags & WHERE_IDX_ONLY ){ - /* An error. pLoop is supposed to be a covering index loop, - ** and yet the VM code refers to a column of the table that - ** is not part of the index. */ - sqlite3ErrorMsg(pParse, "internal query planner error"); - pParse->rc = SQLITE_INTERNAL; - }else{ - /* The WHERE_EXPRIDX flag is set by the planner when it is likely - ** that pLoop is a covering index loop, but it is not possible - ** to be 100% sure. In this case, any OP_Explain opcode - ** corresponding to this loop describes the index as a "COVERING - ** INDEX". But, pOp proves that pLoop is not actually a covering - ** index loop. So clear the WHERE_EXPRIDX flag and rewrite the - ** text that accompanies the OP_Explain opcode, if any. */ - pLoop->wsFlags &= ~WHERE_EXPRIDX; - sqlite3WhereAddExplainText(pParse, - pLevel->addrBody-1, - pTabList, - pLevel, - pWInfo->wctrlFlags - ); - } - } - }else if( pOp->opcode==OP_Rowid ){ - pOp->p1 = pLevel->iIdxCur; - pOp->opcode = OP_IdxRowid; - OpcodeRewriteTrace(db, k, pOp); - }else if( pOp->opcode==OP_IfNullRow ){ - pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); - } -#ifdef SQLITE_DEBUG - k++; -#endif - }while( (++pOp)flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); -#endif - } - } - - /* The "break" point is here, just past the end of the outer loop. - ** Set it. - */ - sqlite3VdbeResolveLabel(v, pWInfo->iBreak); - - /* Final cleanup - */ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - pParse->withinRJSubrtn -= nRJ; - return; -} - -/************** End of where.c ***********************************************/ -/************** Begin file window.c ******************************************/ -/* -** 2018 May 08 -** -** 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. -** -************************************************************************* -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_WINDOWFUNC - -/* -** SELECT REWRITING -** -** Any SELECT statement that contains one or more window functions in -** either the select list or ORDER BY clause (the only two places window -** functions may be used) is transformed by function sqlite3WindowRewrite() -** in order to support window function processing. For example, with the -** schema: -** -** CREATE TABLE t1(a, b, c, d, e, f, g); -** -** the statement: -** -** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e; -** -** is transformed to: -** -** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM ( -** SELECT a, e, c, d, b FROM t1 ORDER BY c, d -** ) ORDER BY e; -** -** The flattening optimization is disabled when processing this transformed -** SELECT statement. This allows the implementation of the window function -** (in this case max()) to process rows sorted in order of (c, d), which -** makes things easier for obvious reasons. More generally: -** -** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to -** the sub-query. -** -** * ORDER BY, LIMIT and OFFSET remain part of the parent query. -** -** * Terminals from each of the expression trees that make up the -** select-list and ORDER BY expressions in the parent query are -** selected by the sub-query. For the purposes of the transformation, -** terminals are column references and aggregate functions. -** -** If there is more than one window function in the SELECT that uses -** the same window declaration (the OVER bit), then a single scan may -** be used to process more than one window function. For example: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d), -** min(e) OVER (PARTITION BY c ORDER BY d) -** FROM t1; -** -** is transformed in the same way as the example above. However: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d), -** min(e) OVER (PARTITION BY a ORDER BY b) -** FROM t1; -** -** Must be transformed to: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM ( -** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM -** SELECT a, e, c, d, b FROM t1 ORDER BY a, b -** ) ORDER BY c, d -** ) ORDER BY e; -** -** so that both min() and max() may process rows in the order defined by -** their respective window declarations. -** -** INTERFACE WITH SELECT.C -** -** When processing the rewritten SELECT statement, code in select.c calls -** sqlite3WhereBegin() to begin iterating through the results of the -** sub-query, which is always implemented as a co-routine. It then calls -** sqlite3WindowCodeStep() to process rows and finish the scan by calling -** sqlite3WhereEnd(). -** -** sqlite3WindowCodeStep() generates VM code so that, for each row returned -** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked. -** When the sub-routine is invoked: -** -** * The results of all window-functions for the row are stored -** in the associated Window.regResult registers. -** -** * The required terminal values are stored in the current row of -** temp table Window.iEphCsr. -** -** In some cases, depending on the window frame and the specific window -** functions invoked, sqlite3WindowCodeStep() caches each entire partition -** in a temp table before returning any rows. In other cases it does not. -** This detail is encapsulated within this file, the code generated by -** select.c is the same in either case. -** -** BUILT-IN WINDOW FUNCTIONS -** -** This implementation features the following built-in window functions: -** -** row_number() -** rank() -** dense_rank() -** percent_rank() -** cume_dist() -** ntile(N) -** lead(expr [, offset [, default]]) -** lag(expr [, offset [, default]]) -** first_value(expr) -** last_value(expr) -** nth_value(expr, N) -** -** These are the same built-in window functions supported by Postgres. -** Although the behaviour of aggregate window functions (functions that -** can be used as either aggregates or window functions) allows them to -** be implemented using an API, built-in window functions are much more -** esoteric. Additionally, some window functions (e.g. nth_value()) -** may only be implemented by caching the entire partition in memory. -** As such, some built-in window functions use the same API as aggregate -** window functions and some are implemented directly using VDBE -** instructions. Additionally, for those functions that use the API, the -** window frame is sometimes modified before the SELECT statement is -** rewritten. For example, regardless of the specified window frame, the -** row_number() function always uses: -** -** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -** -** See sqlite3WindowUpdate() for details. -** -** As well as some of the built-in window functions, aggregate window -** functions min() and max() are implemented using VDBE instructions if -** the start of the window frame is declared as anything other than -** UNBOUNDED PRECEDING. -*/ - -/* -** Implementation of built-in window function row_number(). Assumes that the -** window frame has been coerced to: -** -** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void row_numberStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ) (*p)++; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void row_numberValueFunc(sqlite3_context *pCtx){ - i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - sqlite3_result_int64(pCtx, (p ? *p : 0)); -} - -/* -** Context object type used by rank(), dense_rank(), percent_rank() and -** cume_dist(). -*/ -struct CallCount { - i64 nValue; - i64 nStep; - i64 nTotal; -}; - -/* -** Implementation of built-in window function dense_rank(). Assumes that -** the window frame has been set to: -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void dense_rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ) p->nStep = 1; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void dense_rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - if( p->nStep ){ - p->nValue++; - p->nStep = 0; - } - sqlite3_result_int64(pCtx, p->nValue); - } -} - -/* -** Implementation of built-in window function nth_value(). This -** implementation is used in "slow mode" only - when the EXCLUDE clause -** is not set to the default value "NO OTHERS". -*/ -struct NthValueCtx { - i64 nStep; - sqlite3_value *pValue; -}; -static void nth_valueStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - i64 iVal; - switch( sqlite3_value_numeric_type(apArg[1]) ){ - case SQLITE_INTEGER: - iVal = sqlite3_value_int64(apArg[1]); - break; - case SQLITE_FLOAT: { - double fVal = sqlite3_value_double(apArg[1]); - if( ((i64)fVal)!=fVal ) goto error_out; - iVal = (i64)fVal; - break; - } - default: - goto error_out; - } - if( iVal<=0 ) goto error_out; - - p->nStep++; - if( iVal==p->nStep ){ - p->pValue = sqlite3_value_dup(apArg[0]); - if( !p->pValue ){ - sqlite3_result_error_nomem(pCtx); - } - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - return; - - error_out: - sqlite3_result_error( - pCtx, "second argument to nth_value must be a positive integer", -1 - ); -} -static void nth_valueFinalizeFunc(sqlite3_context *pCtx){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, 0); - if( p && p->pValue ){ - sqlite3_result_value(pCtx, p->pValue); - sqlite3_value_free(p->pValue); - p->pValue = 0; - } -} -#define nth_valueInvFunc noopStepFunc -#define nth_valueValueFunc noopValueFunc - -static void first_valueStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pValue==0 ){ - p->pValue = sqlite3_value_dup(apArg[0]); - if( !p->pValue ){ - sqlite3_result_error_nomem(pCtx); - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void first_valueFinalizeFunc(sqlite3_context *pCtx){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pValue ){ - sqlite3_result_value(pCtx, p->pValue); - sqlite3_value_free(p->pValue); - p->pValue = 0; - } -} -#define first_valueInvFunc noopStepFunc -#define first_valueValueFunc noopValueFunc - -/* -** Implementation of built-in window function rank(). Assumes that -** the window frame has been set to: -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nStep++; - if( p->nValue==0 ){ - p->nValue = p->nStep; - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - sqlite3_result_int64(pCtx, p->nValue); - p->nValue = 0; - } -} - -/* -** Implementation of built-in window function percent_rank(). Assumes that -** the window frame has been set to: -** -** GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -*/ -static void percent_rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nTotal++; - } -} -static void percent_rankInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->nStep++; -} -static void percent_rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nValue = p->nStep; - if( p->nTotal>1 ){ - double r = (double)p->nValue / (double)(p->nTotal-1); - sqlite3_result_double(pCtx, r); - }else{ - sqlite3_result_double(pCtx, 0.0); - } - } -} -#define percent_rankFinalizeFunc percent_rankValueFunc - -/* -** Implementation of built-in window function cume_dist(). Assumes that -** the window frame has been set to: -** -** GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING -*/ -static void cume_distStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nTotal++; - } -} -static void cume_distInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->nStep++; -} -static void cume_distValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, 0); - if( p ){ - double r = (double)(p->nStep) / (double)(p->nTotal); - sqlite3_result_double(pCtx, r); - } -} -#define cume_distFinalizeFunc cume_distValueFunc - -/* -** Context object for ntile() window function. -*/ -struct NtileCtx { - i64 nTotal; /* Total rows in partition */ - i64 nParam; /* Parameter passed to ntile(N) */ - i64 iRow; /* Current row */ -}; - -/* -** Implementation of ntile(). This assumes that the window frame has -** been coerced to: -** -** ROWS CURRENT ROW AND UNBOUNDED FOLLOWING -*/ -static void ntileStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NtileCtx *p; - assert( nArg==1 ); UNUSED_PARAMETER(nArg); - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - if( p->nTotal==0 ){ - p->nParam = sqlite3_value_int64(apArg[0]); - if( p->nParam<=0 ){ - sqlite3_result_error( - pCtx, "argument of ntile must be a positive integer", -1 - ); - } - } - p->nTotal++; - } -} -static void ntileInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NtileCtx *p; - assert( nArg==1 ); UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->iRow++; -} -static void ntileValueFunc(sqlite3_context *pCtx){ - struct NtileCtx *p; - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->nParam>0 ){ - int nSize = (p->nTotal / p->nParam); - if( nSize==0 ){ - sqlite3_result_int64(pCtx, p->iRow+1); - }else{ - i64 nLarge = p->nTotal - p->nParam*nSize; - i64 iSmall = nLarge*(nSize+1); - i64 iRow = p->iRow; - - assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); - - if( iRowpVal); - p->pVal = sqlite3_value_dup(apArg[0]); - if( p->pVal==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - p->nVal++; - } - } -} -static void last_valueInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct LastValueCtx *p; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( ALWAYS(p) ){ - p->nVal--; - if( p->nVal==0 ){ - sqlite3_value_free(p->pVal); - p->pVal = 0; - } - } -} -static void last_valueValueFunc(sqlite3_context *pCtx){ - struct LastValueCtx *p; - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, 0); - if( p && p->pVal ){ - sqlite3_result_value(pCtx, p->pVal); - } -} -static void last_valueFinalizeFunc(sqlite3_context *pCtx){ - struct LastValueCtx *p; - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pVal ){ - sqlite3_result_value(pCtx, p->pVal); - sqlite3_value_free(p->pVal); - p->pVal = 0; - } -} - -/* -** Static names for the built-in window function names. These static -** names are used, rather than string literals, so that FuncDef objects -** can be associated with a particular window function by direct -** comparison of the zName pointer. Example: -** -** if( pFuncDef->zName==row_valueName ){ ... } -*/ -static const char row_numberName[] = "row_number"; -static const char dense_rankName[] = "dense_rank"; -static const char rankName[] = "rank"; -static const char percent_rankName[] = "percent_rank"; -static const char cume_distName[] = "cume_dist"; -static const char ntileName[] = "ntile"; -static const char last_valueName[] = "last_value"; -static const char nth_valueName[] = "nth_value"; -static const char first_valueName[] = "first_value"; -static const char leadName[] = "lead"; -static const char lagName[] = "lag"; - -/* -** No-op implementations of xStep() and xFinalize(). Used as place-holders -** for built-in window functions that never call those interfaces. -** -** The noopValueFunc() is called but is expected to do nothing. The -** noopStepFunc() is never called, and so it is marked with NO_TEST to -** let the test coverage routine know not to expect this function to be -** invoked. -*/ -static void noopStepFunc( /*NO_TEST*/ - sqlite3_context *p, /*NO_TEST*/ - int n, /*NO_TEST*/ - sqlite3_value **a /*NO_TEST*/ -){ /*NO_TEST*/ - UNUSED_PARAMETER(p); /*NO_TEST*/ - UNUSED_PARAMETER(n); /*NO_TEST*/ - UNUSED_PARAMETER(a); /*NO_TEST*/ - assert(0); /*NO_TEST*/ -} /*NO_TEST*/ -static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ } - -/* Window functions that use all window interfaces: xStep, xFinal, -** xValue, and xInverse */ -#define WINDOWFUNCALL(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \ - name ## InvFunc, name ## Name, {0} \ -} - -/* Window functions that are implemented using bytecode and thus have -** no-op routines for their methods */ -#define WINDOWFUNCNOOP(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - noopStepFunc, noopValueFunc, noopValueFunc, \ - noopStepFunc, name ## Name, {0} \ -} - -/* Window functions that use all window interfaces: xStep, the -** same routine for xFinalize and xValue and which never call -** xInverse. */ -#define WINDOWFUNCX(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \ - noopStepFunc, name ## Name, {0} \ -} - - -/* -** Register those built-in window functions that are not also aggregates. -*/ -SQLITE_PRIVATE void sqlite3WindowFunctions(void){ - static FuncDef aWindowFuncs[] = { - WINDOWFUNCX(row_number, 0, 0), - WINDOWFUNCX(dense_rank, 0, 0), - WINDOWFUNCX(rank, 0, 0), - WINDOWFUNCALL(percent_rank, 0, 0), - WINDOWFUNCALL(cume_dist, 0, 0), - WINDOWFUNCALL(ntile, 1, 0), - WINDOWFUNCALL(last_value, 1, 0), - WINDOWFUNCALL(nth_value, 2, 0), - WINDOWFUNCALL(first_value, 1, 0), - WINDOWFUNCNOOP(lead, 1, 0), - WINDOWFUNCNOOP(lead, 2, 0), - WINDOWFUNCNOOP(lead, 3, 0), - WINDOWFUNCNOOP(lag, 1, 0), - WINDOWFUNCNOOP(lag, 2, 0), - WINDOWFUNCNOOP(lag, 3, 0), - }; - sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); -} - -static Window *windowFind(Parse *pParse, Window *pList, const char *zName){ - Window *p; - for(p=pList; p; p=p->pNextWin){ - if( sqlite3StrICmp(p->zName, zName)==0 ) break; - } - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such window: %s", zName); - } - return p; -} - -/* -** This function is called immediately after resolving the function name -** for a window function within a SELECT statement. Argument pList is a -** linked list of WINDOW definitions for the current SELECT statement. -** Argument pFunc is the function definition just resolved and pWin -** is the Window object representing the associated OVER clause. This -** function updates the contents of pWin as follows: -** -** * If the OVER clause referred to a named window (as in "max(x) OVER win"), -** search list pList for a matching WINDOW definition, and update pWin -** accordingly. If no such WINDOW clause can be found, leave an error -** in pParse. -** -** * If the function is a built-in window function that requires the -** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top -** of this file), pWin is updated here. -*/ -SQLITE_PRIVATE void sqlite3WindowUpdate( - Parse *pParse, - Window *pList, /* List of named windows for this SELECT */ - Window *pWin, /* Window frame to update */ - FuncDef *pFunc /* Window function definition */ -){ - if( pWin->zName && pWin->eFrmType==0 ){ - Window *p = windowFind(pParse, pList, pWin->zName); - if( p==0 ) return; - pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); - pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); - pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); - pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); - pWin->eStart = p->eStart; - pWin->eEnd = p->eEnd; - pWin->eFrmType = p->eFrmType; - pWin->eExclude = p->eExclude; - }else{ - sqlite3WindowChain(pParse, pWin, pList); - } - if( (pWin->eFrmType==TK_RANGE) - && (pWin->pStart || pWin->pEnd) - && (pWin->pOrderBy==0 || pWin->pOrderBy->nExpr!=1) - ){ - sqlite3ErrorMsg(pParse, - "RANGE with offset PRECEDING/FOLLOWING requires one ORDER BY expression" - ); - }else - if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ - sqlite3 *db = pParse->db; - if( pWin->pFilter ){ - sqlite3ErrorMsg(pParse, - "FILTER clause may only be used with aggregate window functions" - ); - }else{ - struct WindowUpdate { - const char *zFunc; - int eFrmType; - int eStart; - int eEnd; - } aUp[] = { - { row_numberName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, - { dense_rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, - { rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, - { percent_rankName, TK_GROUPS, TK_CURRENT, TK_UNBOUNDED }, - { cume_distName, TK_GROUPS, TK_FOLLOWING, TK_UNBOUNDED }, - { ntileName, TK_ROWS, TK_CURRENT, TK_UNBOUNDED }, - { leadName, TK_ROWS, TK_UNBOUNDED, TK_UNBOUNDED }, - { lagName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, - }; - int i; - for(i=0; izName==aUp[i].zFunc ){ - sqlite3ExprDelete(db, pWin->pStart); - sqlite3ExprDelete(db, pWin->pEnd); - pWin->pEnd = pWin->pStart = 0; - pWin->eFrmType = aUp[i].eFrmType; - pWin->eStart = aUp[i].eStart; - pWin->eEnd = aUp[i].eEnd; - pWin->eExclude = 0; - if( pWin->eStart==TK_FOLLOWING ){ - pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1"); - } - break; - } - } - } - } - pWin->pWFunc = pFunc; -} - -/* -** Context object passed through sqlite3WalkExprList() to -** selectWindowRewriteExprCb() by selectWindowRewriteEList(). -*/ -typedef struct WindowRewrite WindowRewrite; -struct WindowRewrite { - Window *pWin; - SrcList *pSrc; - ExprList *pSub; - Table *pTab; - Select *pSubSelect; /* Current sub-select, if any */ -}; - -/* -** Callback function used by selectWindowRewriteEList(). If necessary, -** this function appends to the output expression-list and updates -** expression (*ppExpr) in place. -*/ -static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ - struct WindowRewrite *p = pWalker->u.pRewrite; - Parse *pParse = pWalker->pParse; - assert( p!=0 ); - assert( p->pWin!=0 ); - - /* If this function is being called from within a scalar sub-select - ** that used by the SELECT statement being processed, only process - ** TK_COLUMN expressions that refer to it (the outer SELECT). Do - ** not process aggregates or window functions at all, as they belong - ** to the scalar sub-select. */ - if( p->pSubSelect ){ - if( pExpr->op!=TK_COLUMN ){ - return WRC_Continue; - }else{ - int nSrc = p->pSrc->nSrc; - int i; - for(i=0; iiTable==p->pSrc->a[i].iCursor ) break; - } - if( i==nSrc ) return WRC_Continue; - } - } - - switch( pExpr->op ){ - - case TK_FUNCTION: - if( !ExprHasProperty(pExpr, EP_WinFunc) ){ - break; - }else{ - Window *pWin; - for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ - if( pExpr->y.pWin==pWin ){ - assert( pWin->pOwner==pExpr ); - return WRC_Prune; - } - } - } - /* no break */ deliberate_fall_through - - case TK_IF_NULL_ROW: - 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; ipSub->nExpr; i++){ - if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){ - iCol = i; - break; - } - } - } - if( iCol<0 ){ - Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0); - if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION; - p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup); - } - if( p->pSub ){ - int f = pExpr->flags & EP_Collate; - assert( ExprHasProperty(pExpr, EP_Static)==0 ); - ExprSetProperty(pExpr, EP_Static); - sqlite3ExprDelete(pParse->db, pExpr); - ExprClearProperty(pExpr, EP_Static); - memset(pExpr, 0, sizeof(Expr)); - - pExpr->op = TK_COLUMN; - pExpr->iColumn = (iCol<0 ? p->pSub->nExpr-1: iCol); - pExpr->iTable = p->pWin->iEphCsr; - pExpr->y.pTab = p->pTab; - pExpr->flags = f; - } - if( pParse->db->mallocFailed ) return WRC_Abort; - break; - } - - default: /* no-op */ - break; - } - - return WRC_Continue; -} -static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){ - struct WindowRewrite *p = pWalker->u.pRewrite; - Select *pSave = p->pSubSelect; - if( pSave==pSelect ){ - return WRC_Continue; - }else{ - p->pSubSelect = pSelect; - sqlite3WalkSelect(pWalker, pSelect); - p->pSubSelect = pSave; - } - return WRC_Prune; -} - - -/* -** Iterate through each expression in expression-list pEList. For each: -** -** * TK_COLUMN, -** * aggregate function, or -** * window function with a Window object that is not a member of the -** Window list passed as the second argument (pWin). -** -** Append the node to output expression-list (*ppSub). And replace it -** with a TK_COLUMN that reads the (N-1)th element of table -** pWin->iEphCsr, where N is the number of elements in (*ppSub) after -** appending the new one. -*/ -static void selectWindowRewriteEList( - Parse *pParse, - Window *pWin, - SrcList *pSrc, - ExprList *pEList, /* Rewrite expressions in this list */ - Table *pTab, - ExprList **ppSub /* IN/OUT: Sub-select expression-list */ -){ - Walker sWalker; - WindowRewrite sRewrite; - - assert( pWin!=0 ); - memset(&sWalker, 0, sizeof(Walker)); - memset(&sRewrite, 0, sizeof(WindowRewrite)); - - sRewrite.pSub = *ppSub; - sRewrite.pWin = pWin; - sRewrite.pSrc = pSrc; - sRewrite.pTab = pTab; - - sWalker.pParse = pParse; - sWalker.xExprCallback = selectWindowRewriteExprCb; - sWalker.xSelectCallback = selectWindowRewriteSelectCb; - sWalker.u.pRewrite = &sRewrite; - - (void)sqlite3WalkExprList(&sWalker, pEList); - - *ppSub = sRewrite.pSub; -} - -/* -** Append a copy of each expression in expression-list pAppend to -** expression list pList. Return a pointer to the result list. -*/ -static ExprList *exprListAppendList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to append. Might be NULL */ - ExprList *pAppend, /* List of values to append. Might be NULL */ - int bIntToNull -){ - if( pAppend ){ - int i; - int nInit = pList ? pList->nExpr : 0; - for(i=0; inExpr; i++){ - sqlite3 *db = pParse->db; - Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - break; - } - if( bIntToNull ){ - int iDummy; - Expr *pSub; - pSub = sqlite3ExprSkipCollateAndLikely(pDup); - if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){ - pSub->op = TK_NULL; - pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); - pSub->u.zToken = 0; - } - } - pList = sqlite3ExprListAppend(pParse, pList, pDup); - if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags; - } - } - return pList; -} - -/* -** When rewriting a query, if the new subquery in the FROM clause -** contains TK_AGG_FUNCTION nodes that refer to an outer query, -** then we have to increase the Expr->op2 values of those nodes -** due to the extra subquery layer that was added. -** -** See also the incrAggDepth() routine in resolve.c -*/ -static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION - && pExpr->op2>=pWalker->walkerDepth - ){ - pExpr->op2++; - } - return WRC_Continue; -} - -static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - 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 -** rewrites the SELECT statement so that window function xStep functions -** are invoked in the correct order as described under "SELECT REWRITING" -** at the top of this file. -*/ -SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ - int rc = SQLITE_OK; - if( p->pWin - && p->pPrior==0 - && ALWAYS((p->selFlags & SF_WinRewrite)==0) - && ALWAYS(!IN_RENAME_OBJECT) - ){ - Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3 *db = pParse->db; - Select *pSub = 0; /* The subquery */ - SrcList *pSrc = p->pSrc; - Expr *pWhere = p->pWhere; - ExprList *pGroupBy = p->pGroupBy; - Expr *pHaving = p->pHaving; - ExprList *pSort = 0; - - ExprList *pSublist = 0; /* Expression list for sub-query */ - Window *pMWin = p->pWin; /* Main window object */ - Window *pWin; /* Window object iterator */ - Table *pTab; - Walker w; - - u32 selFlags = p->selFlags; - - pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ){ - return sqlite3ErrorToParser(db, SQLITE_NOMEM); - } - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w, p); - if( (p->selFlags & SF_Aggregate)==0 ){ - w.xExprCallback = disallowAggregatesInOrderByCb; - w.xSelectCallback = 0; - sqlite3WalkExprList(&w, p->pOrderBy); - } - - p->pSrc = 0; - p->pWhere = 0; - p->pGroupBy = 0; - p->pHaving = 0; - p->selFlags &= ~(u32)SF_Aggregate; - p->selFlags |= SF_WinRewrite; - - /* Create the ORDER BY clause for the sub-select. This is the concatenation - ** of the window PARTITION and ORDER BY clauses. Then, if this makes it - ** redundant, remove the ORDER BY from the parent SELECT. */ - pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1); - pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1); - if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){ - int nSave = pSort->nExpr; - pSort->nExpr = p->pOrderBy->nExpr; - if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ - sqlite3ExprListDelete(db, p->pOrderBy); - p->pOrderBy = 0; - } - pSort->nExpr = nSave; - } - - /* Assign a cursor number for the ephemeral table used to buffer rows. - ** The OpenEphemeral instruction is coded later, after it is known how - ** many columns the table will have. */ - pMWin->iEphCsr = pParse->nTab++; - pParse->nTab += 3; - - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, pTab, &pSublist); - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, pTab, &pSublist); - pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); - - /* Append the PARTITION BY and ORDER BY expressions to the to the - ** sub-select expression list. They are required to figure out where - ** boundaries for partitions and sets of peer rows lie. */ - pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition, 0); - pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0); - - /* Append the arguments passed to each window function to the - ** sub-select expression list. Also allocate two registers for each - ** window function - one for the accumulator, another for interim - ** results. */ - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - ExprList *pArgs; - assert( ExprUseXList(pWin->pOwner) ); - assert( pWin->pWFunc!=0 ); - pArgs = pWin->pOwner->x.pList; - if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){ - selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pWin->bExprArgs = 1; - }else{ - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pSublist = exprListAppendList(pParse, pSublist, pArgs, 0); - } - if( pWin->pFilter ){ - Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); - pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); - } - pWin->regAccum = ++pParse->nMem; - pWin->regResult = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - } - - /* If there is no ORDER BY or PARTITION BY clause, and the window - ** function accepts zero arguments, and there are no other columns - ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible - ** that pSublist is still NULL here. Add a constant expression here to - ** keep everything legal in this case. - */ - if( pSublist==0 ){ - pSublist = sqlite3ExprListAppend(pParse, 0, - sqlite3Expr(db, TK_INTEGER, "0") - ); - } - - pSub = sqlite3SelectNew( - pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0 - ); - TREETRACE(0x40,pParse,pSub, - ("New window-function subquery in FROM clause of (%u/%p)\n", - p->selId, p)); - p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside - ** of sqlite3DbMallocRawNN() called from - ** sqlite3SrcListAppend() */ - if( p->pSrc==0 ){ - sqlite3SelectDelete(db, pSub); - }else if( sqlite3SrcItemAttachSubquery(pParse, &p->pSrc->a[0], pSub, 0) ){ - Table *pTab2; - p->pSrc->a[0].fg.isCorrelated = 1; - sqlite3SrcListAssignCursors(pParse, p->pSrc); - pSub->selFlags |= SF_Expanded|SF_OrderByReqd; - pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); - pSub->selFlags |= (selFlags & SF_Aggregate); - if( pTab2==0 ){ - /* Might actually be some other kind of error, but in that case - ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get - ** the correct error message regardless. */ - rc = SQLITE_NOMEM; - }else{ - memcpy(pTab, pTab2, sizeof(Table)); - pTab->tabFlags |= TF_Ephemeral; - p->pSrc->a[0].pSTab = pTab; - pTab = pTab2; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3WindowExtraAggFuncDepth; - w.xSelectCallback = sqlite3WalkerDepthIncrease; - w.xSelectCallback2 = sqlite3WalkerDepthDecrease; - sqlite3WalkSelect(&w, pSub); - } - } - if( db->mallocFailed ) rc = 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. */ - sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab); - } - - assert( rc==SQLITE_OK || pParse->nErr!=0 ); - return rc; -} - -/* -** Unlink the Window object from the Select to which it is attached, -** if it is attached. -*/ -SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window *p){ - if( p->ppThis ){ - *p->ppThis = p->pNextWin; - if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis; - p->ppThis = 0; - } -} - -/* -** Free the Window object passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){ - if( p ){ - sqlite3WindowUnlinkFromSelect(p); - sqlite3ExprDelete(db, p->pFilter); - sqlite3ExprListDelete(db, p->pPartition); - sqlite3ExprListDelete(db, p->pOrderBy); - sqlite3ExprDelete(db, p->pEnd); - sqlite3ExprDelete(db, p->pStart); - sqlite3DbFree(db, p->zName); - sqlite3DbFree(db, p->zBase); - sqlite3DbFree(db, p); - } -} - -/* -** Free the linked list of Window objects starting at the second argument. -*/ -SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){ - while( p ){ - Window *pNext = p->pNextWin; - sqlite3WindowDelete(db, p); - p = pNext; - } -} - -/* -** The argument expression is an PRECEDING or FOLLOWING offset. The -** value should be a non-negative integer. If the value is not a -** constant, change it to NULL. The fact that it is then a non-negative -** integer will be caught later. But it is important not to leave -** variable values in the expression tree. -*/ -static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ - if( 0==sqlite3ExprIsConstant(0,pExpr) ){ - if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); - sqlite3ExprDelete(pParse->db, pExpr); - pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); - } - return pExpr; -} - -/* -** Allocate and return a new Window object describing a Window Definition. -*/ -SQLITE_PRIVATE Window *sqlite3WindowAlloc( - Parse *pParse, /* Parsing context */ - int eType, /* Frame type. TK_RANGE, TK_ROWS, TK_GROUPS, or 0 */ - int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ - Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ - int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ - Expr *pEnd, /* End window size if TK_FOLLOWING or PRECEDING */ - u8 eExclude /* EXCLUDE clause */ -){ - Window *pWin = 0; - int bImplicitFrame = 0; - - /* Parser assures the following: */ - assert( eType==0 || eType==TK_RANGE || eType==TK_ROWS || eType==TK_GROUPS ); - assert( eStart==TK_CURRENT || eStart==TK_PRECEDING - || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING ); - assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING - || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING ); - assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) ); - assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) ); - - if( eType==0 ){ - bImplicitFrame = 1; - eType = TK_RANGE; - } - - /* Additionally, the - ** starting boundary type may not occur earlier in the following list than - ** the ending boundary type: - ** - ** UNBOUNDED PRECEDING - ** PRECEDING - ** CURRENT ROW - ** FOLLOWING - ** UNBOUNDED FOLLOWING - ** - ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending - ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting - ** frame boundary. - */ - if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING) - || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT)) - ){ - sqlite3ErrorMsg(pParse, "unsupported frame specification"); - goto windowAllocErr; - } - - pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( pWin==0 ) goto windowAllocErr; - pWin->eFrmType = eType; - pWin->eStart = eStart; - pWin->eEnd = eEnd; - if( eExclude==0 && OptimizationDisabled(pParse->db, SQLITE_WindowFunc) ){ - eExclude = TK_NO; - } - pWin->eExclude = eExclude; - pWin->bImplicitFrame = bImplicitFrame; - pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd); - pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart); - return pWin; - -windowAllocErr: - sqlite3ExprDelete(pParse->db, pEnd); - sqlite3ExprDelete(pParse->db, pStart); - return 0; -} - -/* -** Attach PARTITION and ORDER BY clauses pPartition and pOrderBy to window -** pWin. Also, if parameter pBase is not NULL, set pWin->zBase to the -** equivalent nul-terminated string. -*/ -SQLITE_PRIVATE Window *sqlite3WindowAssemble( - Parse *pParse, - Window *pWin, - ExprList *pPartition, - ExprList *pOrderBy, - Token *pBase -){ - if( pWin ){ - pWin->pPartition = pPartition; - pWin->pOrderBy = pOrderBy; - if( pBase ){ - pWin->zBase = sqlite3DbStrNDup(pParse->db, pBase->z, pBase->n); - } - }else{ - sqlite3ExprListDelete(pParse->db, pPartition); - sqlite3ExprListDelete(pParse->db, pOrderBy); - } - return pWin; -} - -/* -** Window *pWin has just been created from a WINDOW clause. Token pBase -** is the base window. Earlier windows from the same WINDOW clause are -** stored in the linked list starting at pWin->pNextWin. This function -** either updates *pWin according to the base specification, or else -** leaves an error in pParse. -*/ -SQLITE_PRIVATE void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){ - if( pWin->zBase ){ - sqlite3 *db = pParse->db; - Window *pExist = windowFind(pParse, pList, pWin->zBase); - if( pExist ){ - const char *zErr = 0; - /* Check for errors */ - if( pWin->pPartition ){ - zErr = "PARTITION clause"; - }else if( pExist->pOrderBy && pWin->pOrderBy ){ - zErr = "ORDER BY clause"; - }else if( pExist->bImplicitFrame==0 ){ - zErr = "frame specification"; - } - if( zErr ){ - sqlite3ErrorMsg(pParse, - "cannot override %s of window: %s", zErr, pWin->zBase - ); - }else{ - pWin->pPartition = sqlite3ExprListDup(db, pExist->pPartition, 0); - if( pExist->pOrderBy ){ - assert( pWin->pOrderBy==0 ); - pWin->pOrderBy = sqlite3ExprListDup(db, pExist->pOrderBy, 0); - } - sqlite3DbFree(db, pWin->zBase); - pWin->zBase = 0; - } - } - } -} - -/* -** Attach window object pWin to expression p. -*/ -SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ - if( p ){ - assert( p->op==TK_FUNCTION ); - assert( pWin ); - assert( ExprIsFullSize(p) ); - p->y.pWin = pWin; - ExprSetProperty(p, EP_WinFunc|EP_FullSize); - pWin->pOwner = p; - if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){ - sqlite3ErrorMsg(pParse, - "DISTINCT is not supported for window functions" - ); - } - }else{ - sqlite3WindowDelete(pParse->db, pWin); - } -} - -/* -** Possibly link window pWin into the list at pSel->pWin (window functions -** to be processed as part of SELECT statement pSel). The window is linked -** in if either (a) there are no other windows already linked to this -** SELECT, or (b) the windows already linked use a compatible window frame. -*/ -SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){ - if( pSel ){ - if( 0==pSel->pWin || 0==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( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){ - pSel->selFlags |= SF_MultiPart; - } - } - } -} - -/* -** Return 0 if the two window objects are identical, 1 if they are -** 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 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; - if( p1->eStart!=p2->eStart ) return 1; - if( p1->eEnd!=p2->eEnd ) return 1; - if( p1->eExclude!=p2->eExclude ) return 1; - if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; - if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; - if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){ - return res; - } - if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){ - return res; - } - if( bFilter ){ - if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){ - return res; - } - } - return 0; -} - - -/* -** This is called by code in select.c before it calls sqlite3WhereBegin() -** to begin iterating through the sub-query results. It is used to allocate -** and initialize registers and cursors used by sqlite3WindowCodeStep(). -*/ -SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){ - Window *pWin; - int nEphExpr; - Window *pMWin; - Vdbe *v; - - assert( pSelect->pSrc->a[0].fg.isSubquery ); - nEphExpr = pSelect->pSrc->a[0].u4.pSubq->pSelect->pEList->nExpr; - pMWin = pSelect->pWin; - v = sqlite3GetVdbe(pParse); - - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr); - - /* Allocate registers to use for PARTITION BY values, if any. Initialize - ** said registers to NULL. */ - if( pMWin->pPartition ){ - int nExpr = pMWin->pPartition->nExpr; - pMWin->regPart = pParse->nMem+1; - pParse->nMem += nExpr; - sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1); - } - - pMWin->regOne = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regOne); - - if( pMWin->eExclude ){ - pMWin->regStartRowid = ++pParse->nMem; - pMWin->regEndRowid = ++pParse->nMem; - pMWin->csrApp = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->csrApp, pMWin->iEphCsr); - return; - } - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - 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: - ** - ** regApp+0: slot to copy min()/max() argument to for MakeRecord - ** regApp+1: integer value used to ensure keys are unique - ** regApp+2: output of MakeRecord - */ - ExprList *pList; - KeyInfo *pKeyInfo; - assert( ExprUseXList(pWin->pOwner) ); - pList = pWin->pOwner->x.pList; - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); - pWin->csrApp = pParse->nTab++; - pWin->regApp = pParse->nMem+1; - pParse->nMem += 3; - if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){ - assert( pKeyInfo->aSortFlags[0]==0 ); - pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC; - } - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); - sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - else if( p->zName==nth_valueName || p->zName==first_valueName ){ - /* Allocate two registers at pWin->regApp. These will be used to - ** store the start and end index of the current frame. */ - pWin->regApp = pParse->nMem+1; - pWin->csrApp = pParse->nTab++; - pParse->nMem += 2; - sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); - } - else if( p->zName==leadName || p->zName==lagName ){ - pWin->csrApp = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); - } - } -} - -#define WINDOW_STARTING_INT 0 -#define WINDOW_ENDING_INT 1 -#define WINDOW_NTH_VALUE_INT 2 -#define WINDOW_STARTING_NUM 3 -#define WINDOW_ENDING_NUM 4 - -/* -** A "PRECEDING " (eCond==0) or "FOLLOWING " (eCond==1) or the -** value of the second argument to nth_value() (eCond==2) has just been -** evaluated and the result left in register reg. This function generates VM -** code to check that the value is a non-negative integer and throws an -** exception if it is not. -*/ -static void windowCheckValue(Parse *pParse, int reg, int eCond){ - static const char *azErr[] = { - "frame starting offset must be a non-negative integer", - "frame ending offset must be a non-negative integer", - "second argument to nth_value must be a positive integer", - "frame starting offset must be a non-negative number", - "frame ending offset must be a non-negative number", - }; - static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge }; - Vdbe *v = sqlite3GetVdbe(pParse); - int regZero = sqlite3GetTempReg(pParse); - assert( eCond>=0 && eCond=WINDOW_STARTING_NUM ){ - int regString = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); - sqlite3VdbeAddOp3(v, OP_Ge, regString, sqlite3VdbeCurrentAddr(v)+2, reg); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC|SQLITE_JUMPIFNULL); - VdbeCoverage(v); - assert( eCond==3 || eCond==4 ); - VdbeCoverageIf(v, eCond==3); - VdbeCoverageIf(v, eCond==4); - }else{ - sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - assert( eCond==0 || eCond==1 || eCond==2 ); - VdbeCoverageIf(v, eCond==0); - VdbeCoverageIf(v, eCond==1); - VdbeCoverageIf(v, eCond==2); - } - sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC); - VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */ - VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */ - VdbeCoverageNeverNullIf(v, eCond==2); - VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */ - VdbeCoverageNeverNullIf(v, eCond==4); /* the OP_Ge */ - sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); - sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); - sqlite3ReleaseTempReg(pParse, regZero); -} - -/* -** Return the number of arguments passed to the window-function associated -** with the object passed as the only argument to this function. -*/ -static int windowArgCount(Window *pWin){ - const ExprList *pList; - assert( ExprUseXList(pWin->pOwner) ); - pList = pWin->pOwner->x.pList; - return (pList ? pList->nExpr : 0); -} - -typedef struct WindowCodeArg WindowCodeArg; -typedef struct WindowCsrAndReg WindowCsrAndReg; - -/* -** See comments above struct WindowCodeArg. -*/ -struct WindowCsrAndReg { - int csr; /* Cursor number */ - int reg; /* First in array of peer values */ -}; - -/* -** A single instance of this structure is allocated on the stack by -** sqlite3WindowCodeStep() and a pointer to it passed to the various helper -** routines. This is to reduce the number of arguments required by each -** helper function. -** -** regArg: -** Each window function requires an accumulator register (just as an -** ordinary aggregate function does). This variable is set to the first -** in an array of accumulator registers - one for each window function -** in the WindowCodeArg.pMWin list. -** -** eDelete: -** The window functions implementation sometimes caches the input rows -** that it processes in a temporary table. If it is not zero, this -** variable indicates when rows may be removed from the temp table (in -** order to reduce memory requirements - it would always be safe just -** to leave them there). Possible values for eDelete are: -** -** WINDOW_RETURN_ROW: -** An input row can be discarded after it is returned to the caller. -** -** WINDOW_AGGINVERSE: -** An input row can be discarded after the window functions xInverse() -** callbacks have been invoked in it. -** -** WINDOW_AGGSTEP: -** An input row can be discarded after the window functions xStep() -** callbacks have been invoked in it. -** -** start,current,end -** Consider a window-frame similar to the following: -** -** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) -** -** The windows functions implementation caches the input rows in a temp -** table, sorted by "a, b" (it actually populates the cache lazily, and -** aggressively removes rows once they are no longer required, but that's -** a mere detail). It keeps three cursors open on the temp table. One -** (current) that points to the next row to return to the query engine -** once its window function values have been calculated. Another (end) -** points to the next row to call the xStep() method of each window function -** on (so that it is 2 groups ahead of current). And a third (start) that -** points to the next row to call the xInverse() method of each window -** function on. -** -** Each cursor (start, current and end) consists of a VDBE cursor -** (WindowCsrAndReg.csr) and an array of registers (starting at -** WindowCodeArg.reg) that always contains a copy of the peer values -** read from the corresponding cursor. -** -** Depending on the window-frame in question, all three cursors may not -** be required. In this case both WindowCodeArg.csr and reg are set to -** 0. -*/ -struct WindowCodeArg { - Parse *pParse; /* Parse context */ - Window *pMWin; /* First in list of functions being processed */ - Vdbe *pVdbe; /* VDBE object */ - int addrGosub; /* OP_Gosub to this address to return one row */ - 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; - WindowCsrAndReg end; -}; - -/* -** Generate VM code to read the window frames peer values from cursor csr into -** an array of registers starting at reg. -*/ -static void windowReadPeerValues( - WindowCodeArg *p, - int csr, - int reg -){ - Window *pMWin = p->pMWin; - ExprList *pOrderBy = pMWin->pOrderBy; - if( pOrderBy ){ - Vdbe *v = sqlite3GetVdbe(p->pParse); - ExprList *pPart = pMWin->pPartition; - int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); - int i; - for(i=0; inExpr; i++){ - sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i); - } - } -} - -/* -** Generate VM code to invoke either xStep() (if bInverse is 0) or -** xInverse (if bInverse is non-zero) for each window function in the -** linked list starting at pMWin. Or, for built-in window functions -** that do not use the standard function API, generate the required -** inline VM code. -** -** If argument csr is greater than or equal to 0, then argument reg is -** the first register in an array of registers guaranteed to be large -** enough to hold the array of arguments for each function. In this case -** the arguments are extracted from the current row of csr into the -** array of registers before invoking OP_AggStep or OP_AggInverse -** -** Or, if csr is less than zero, then the array of registers at reg is -** already populated with all columns from the current row of the sub-query. -** -** If argument regPartSize is non-zero, then it is a register containing the -** number of rows in the current partition. -*/ -static void windowAggStep( - WindowCodeArg *p, - Window *pMWin, /* Linked list of window functions */ - int csr, /* Read arguments from this cursor */ - int bInverse, /* True to invoke xInverse instead of xStep */ - int reg /* Array of registers */ -){ - Parse *pParse = p->pParse; - Vdbe *v = sqlite3GetVdbe(pParse); - Window *pWin; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - int regArg; - int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin); - int i; - int addrIf = 0; - - assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED ); - - /* All OVER clauses in the same window function aggregate step must - ** be the same. */ - assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 ); - - for(i=0; izName!=nth_valueName ){ - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i); - } - } - regArg = reg; - - 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 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); - addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, regTmp); - } - - if( pMWin->regStartRowid==0 - && (pFunc->funcFlags & SQLITE_FUNC_MINMAX) - && (pWin->eStart!=TK_UNBOUNDED) - ){ - int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg); - VdbeCoverage(v); - if( bInverse==0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1); - sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp); - sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2); - }else{ - sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1); - VdbeCoverageNeverTaken(v); - sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - } - sqlite3VdbeJumpHere(v, addrIsNull); - }else if( pWin->regApp ){ - assert( pWin->pFilter==0 ); - assert( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ); - assert( bInverse==0 || bInverse==1 ); - sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); - }else if( pFunc->xSFunc!=noopStepFunc ){ - if( pWin->bExprArgs ){ - int iOp = sqlite3VdbeCurrentAddr(v); - int iEnd; - - assert( ExprUseXList(pWin->pOwner) ); - nArg = pWin->pOwner->x.pList->nExpr; - regArg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0); - - for(iEnd=sqlite3VdbeCurrentAddr(v); iOpopcode==OP_Column && pOp->p1==pMWin->iEphCsr ){ - pOp->p1 = csr; - } - } - } - if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl; - assert( nArg>0 ); - assert( ExprUseXList(pWin->pOwner) ); - pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); - sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, - bInverse, regArg, pWin->regAccum); - sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - if( pWin->bExprArgs ){ - sqlite3ReleaseTempRange(pParse, regArg, nArg); - } - } - - if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); - } -} - -/* -** Values that may be passed as the second argument to windowCodeOp(). -*/ -#define WINDOW_RETURN_ROW 1 -#define WINDOW_AGGINVERSE 2 -#define WINDOW_AGGSTEP 3 - -/* -** Generate VM code to invoke either xValue() (bFin==0) or xFinalize() -** (bFin==1) for each window function in the linked list starting at -** pMWin. Or, for built-in window-functions that do not use the standard -** API, generate the equivalent VM code. -*/ -static void windowAggFinal(WindowCodeArg *p, int bFin){ - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - Vdbe *v = sqlite3GetVdbe(pParse); - Window *pWin; - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - if( pMWin->regStartRowid==0 - && (pWin->pWFunc->funcFlags & SQLITE_FUNC_MINMAX) - && (pWin->eStart!=TK_UNBOUNDED) - ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - }else if( pWin->regApp ){ - assert( pMWin->regStartRowid==0 ); - }else{ - int nArg = windowArgCount(pWin); - if( bFin ){ - sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg); - sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); - sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - }else{ - sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult); - sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); - } - } - } -} - -/* -** Generate code to calculate the current values of all window functions in the -** p->pMWin list by doing a full scan of the current window frame. Store the -** results in the Window.regResult registers, ready to return the upper -** layer. -*/ -static void windowFullScan(WindowCodeArg *p){ - Window *pWin; - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - Vdbe *v = p->pVdbe; - - int regCRowid = 0; /* Current rowid value */ - int regCPeer = 0; /* Current peer values */ - int regRowid = 0; /* AggStep rowid value */ - int regPeer = 0; /* AggStep peer values */ - - int nPeer; - int lblNext; - int lblBrk; - int addrNext; - int csr; - - VdbeModuleComment((v, "windowFullScan begin")); - - assert( pMWin!=0 ); - csr = pMWin->csrApp; - nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - - lblNext = sqlite3VdbeMakeLabel(pParse); - lblBrk = sqlite3VdbeMakeLabel(pParse); - - regCRowid = sqlite3GetTempReg(pParse); - regRowid = sqlite3GetTempReg(pParse); - if( nPeer ){ - regCPeer = sqlite3GetTempRange(pParse, nPeer); - regPeer = sqlite3GetTempRange(pParse, nPeer); - } - - sqlite3VdbeAddOp2(v, OP_Rowid, pMWin->iEphCsr, regCRowid); - windowReadPeerValues(p, pMWin->iEphCsr, regCPeer); - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - } - - sqlite3VdbeAddOp3(v, OP_SeekGE, csr, lblBrk, pMWin->regStartRowid); - VdbeCoverage(v); - addrNext = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Rowid, csr, regRowid); - sqlite3VdbeAddOp3(v, OP_Gt, pMWin->regEndRowid, lblBrk, regRowid); - VdbeCoverageNeverNull(v); - - if( pMWin->eExclude==TK_CURRENT ){ - sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, lblNext, regRowid); - VdbeCoverageNeverNull(v); - }else if( pMWin->eExclude!=TK_NO ){ - int addr; - int addrEq = 0; - KeyInfo *pKeyInfo = 0; - - if( pMWin->pOrderBy ){ - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy, 0, 0); - } - if( pMWin->eExclude==TK_TIES ){ - addrEq = sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, 0, regRowid); - VdbeCoverageNeverNull(v); - } - if( pKeyInfo ){ - windowReadPeerValues(p, csr, regPeer); - sqlite3VdbeAddOp3(v, OP_Compare, regPeer, regCPeer, nPeer); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - addr = sqlite3VdbeCurrentAddr(v)+1; - sqlite3VdbeAddOp3(v, OP_Jump, addr, lblNext, addr); - VdbeCoverageEqNe(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblNext); - } - if( addrEq ) sqlite3VdbeJumpHere(v, addrEq); - } - - windowAggStep(p, pMWin, csr, 0, p->regArg); - - sqlite3VdbeResolveLabel(v, lblNext); - sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrNext-1); - sqlite3VdbeJumpHere(v, addrNext+1); - sqlite3ReleaseTempReg(pParse, regRowid); - sqlite3ReleaseTempReg(pParse, regCRowid); - if( nPeer ){ - sqlite3ReleaseTempRange(pParse, regPeer, nPeer); - sqlite3ReleaseTempRange(pParse, regCPeer, nPeer); - } - - windowAggFinal(p, 1); - VdbeModuleComment((v, "windowFullScan end")); -} - -/* -** Invoke the sub-routine at regGosub (generated by code in select.c) to -** return the current row of Window.iEphCsr. If all window functions are -** aggregate window functions that use the standard API, a single -** OP_Gosub instruction is all that this routine generates. Extra VM code -** for per-row processing is only generated for the following built-in window -** functions: -** -** nth_value() -** first_value() -** lag() -** lead() -*/ -static void windowReturnOneRow(WindowCodeArg *p){ - Window *pMWin = p->pMWin; - Vdbe *v = p->pVdbe; - - if( pMWin->regStartRowid ){ - windowFullScan(p); - }else{ - Parse *pParse = p->pParse; - Window *pWin; - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - assert( ExprUseXList(pWin->pOwner) ); - if( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ){ - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - - if( pFunc->zName==nth_valueName ){ - sqlite3VdbeAddOp3(v, OP_Column,pMWin->iEphCsr,pWin->iArgCol+1,tmpReg); - windowCheckValue(pParse, tmpReg, 2); - }else{ - sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); - } - sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); - sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); - VdbeCoverageNeverNull(v); - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); - VdbeCoverageNeverTaken(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); - } - else if( pFunc->zName==leadName || pFunc->zName==lagName ){ - int nArg = pWin->pOwner->x.pList->nExpr; - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); - int iEph = pMWin->iEphCsr; - - if( nArg<3 ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iEph,pWin->iArgCol+2,pWin->regResult); - } - sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); - if( nArg<2 ){ - int val = (pFunc->zName==leadName ? 1 : -1); - sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); - }else{ - int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); - int tmpReg2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); - sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); - sqlite3ReleaseTempReg(pParse, tmpReg2); - } - - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); - } - } - } - sqlite3VdbeAddOp2(v, OP_Gosub, p->regGosub, p->addrGosub); -} - -/* -** Generate code to set the accumulator register for each window function -** in the linked list passed as the second argument to NULL. And perform -** any equivalent initialization required by any built-in window functions -** in the list. -*/ -static int windowInitAccum(Parse *pParse, Window *pMWin){ - Vdbe *v = sqlite3GetVdbe(pParse); - int regArg; - int nArg = 0; - Window *pWin; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - assert( pWin->regAccum ); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - nArg = MAX(nArg, windowArgCount(pWin)); - if( pMWin->regStartRowid==0 ){ - if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - - if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ - assert( pWin->eStart!=TK_UNBOUNDED ); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - } - } - regArg = pParse->nMem+1; - pParse->nMem += nArg; - return regArg; -} - -/* -** Return true if the current frame should be cached in the ephemeral table, -** even if there are no xInverse() calls required. -*/ -static int windowCacheFrame(Window *pMWin){ - Window *pWin; - if( pMWin->regStartRowid ) return 1; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - if( (pFunc->zName==nth_valueName) - || (pFunc->zName==first_valueName) - || (pFunc->zName==leadName) - || (pFunc->zName==lagName) - ){ - return 1; - } - } - return 0; -} - -/* -** regOld and regNew are each the first register in an array of size -** pOrderBy->nExpr. This function generates code to compare the two -** arrays of registers using the collation sequences and other comparison -** parameters specified by pOrderBy. -** -** If the two arrays are not equal, the contents of regNew is copied to -** regOld and control falls through. Otherwise, if the contents of the arrays -** are equal, an OP_Goto is executed. The address of the OP_Goto is returned. -*/ -static void windowIfNewPeer( - Parse *pParse, - ExprList *pOrderBy, - int regNew, /* First in array of new values */ - int regOld, /* First in array of old values */ - int addr /* Jump here */ -){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( pOrderBy ){ - int nVal = pOrderBy->nExpr; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); - sqlite3VdbeAddOp3(v, OP_Compare, regOld, regNew, nVal); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, - sqlite3VdbeCurrentAddr(v)+1, addr, sqlite3VdbeCurrentAddr(v)+1 - ); - VdbeCoverageEqNe(v); - sqlite3VdbeAddOp3(v, OP_Copy, regNew, regOld, nVal-1); - }else{ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - } -} - -/* -** This function is called as part of generating VM programs for RANGE -** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for -** the ORDER BY term in the window, and that argument op is OP_Ge, it generates -** code equivalent to: -** -** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl; -** -** The value of parameter op may also be OP_Gt or OP_Le. In these cases the -** operator in the above pseudo-code is replaced with ">" or "<=", respectively. -** -** If the sort-order for the ORDER BY term in the window is DESC, then the -** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is -** subtracted. And the comparison operator is inverted to - ">=" becomes "<=", -** ">" becomes "<", and so on. So, with DESC sort order, if the argument op -** is OP_Ge, the generated code is equivalent to: -** -** 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 -** or subtraction is a a copy of csr1.peerVal. -*/ -static void windowCodeRangeTest( - WindowCodeArg *p, - int op, /* OP_Ge, OP_Gt, or OP_Le */ - int csr1, /* Cursor number for cursor 1 */ - int regVal, /* Register containing non-negative number */ - int csr2, /* Cursor number for cursor 2 */ - int lbl /* Jump destination if condition is true */ -){ - Parse *pParse = p->pParse; - Vdbe *v = sqlite3GetVdbe(pParse); - ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */ - int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */ - int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */ - int regString = ++pParse->nMem; /* Reg. for constant value '' */ - int arith = OP_Add; /* OP_Add or OP_Subtract */ - int addrGe; /* Jump destination */ - int addrDone = 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].fg.sortFlags & KEYINFO_ORDER_DESC ){ - switch( op ){ - case OP_Ge: op = OP_Le; break; - case OP_Gt: op = OP_Lt; break; - default: assert( op==OP_Le ); op = OP_Ge; break; - } - arith = OP_Subtract; - } - - 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 - )); - - /* 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 - ** (and adding that capability causes a performance regression), so - ** instead if the BIGNULL flag is set then cases where either reg1 or - ** reg2 are NULL are handled separately in the following block. The code - ** generated is equivalent to: - ** - ** if( reg1 IS NULL ){ - ** if( op==OP_Ge ) goto lbl; - ** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl; - ** if( op==OP_Le && reg2 IS NULL ) goto lbl; - ** }else if( reg2 IS NULL ){ - ** if( op==OP_Le ) goto lbl; - ** } - ** - ** 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].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){ - /* This block runs if reg1 contains a NULL. */ - int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v); - switch( op ){ - case OP_Ge: - sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl); - break; - case OP_Gt: - sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl); - VdbeCoverage(v); - break; - case OP_Le: - sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); - VdbeCoverage(v); - break; - default: assert( op==OP_Lt ); /* no-op */ break; - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone); - - /* This block runs if reg1 is not NULL, but reg2 is. */ - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_IsNull, reg2, - (op==OP_Gt || op==OP_Ge) ? addrDone : lbl); - VdbeCoverage(v); - } - - /* 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. */ - sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); - addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1); - VdbeCoverage(v); - if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){ - sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1); - 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. */ - sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); - pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr); - sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - 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); - 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); - sqlite3ReleaseTempReg(pParse, reg1); - sqlite3ReleaseTempReg(pParse, reg2); - - VdbeModuleComment((v, "CodeRangeTest: end")); -} - -/* -** Helper function for sqlite3WindowCodeStep(). Each call to this function -** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE -** operation. Refer to the header comment for sqlite3WindowCodeStep() for -** details. -*/ -static int windowCodeOp( - WindowCodeArg *p, /* Context object */ - int op, /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */ - int regCountdown, /* Register for OP_IfPos countdown */ - int jumpOnEof /* Jump here if stepped cursor reaches EOF */ -){ - int csr, reg; - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - int ret = 0; - Vdbe *v = p->pVdbe; - int addrContinue = 0; - int bPeer = (pMWin->eFrmType!=TK_ROWS); - - int lblDone = sqlite3VdbeMakeLabel(pParse); - int addrNextRange = 0; - - /* Special case - WINDOW_AGGINVERSE is always a no-op if the frame - ** starts with UNBOUNDED PRECEDING. */ - if( op==WINDOW_AGGINVERSE && pMWin->eStart==TK_UNBOUNDED ){ - assert( regCountdown==0 && jumpOnEof==0 ); - return 0; - } - - if( regCountdown>0 ){ - if( pMWin->eFrmType==TK_RANGE ){ - addrNextRange = sqlite3VdbeCurrentAddr(v); - assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP ); - if( op==WINDOW_AGGINVERSE ){ - if( pMWin->eStart==TK_FOLLOWING ){ - windowCodeRangeTest( - p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone - ); - }else{ - windowCodeRangeTest( - p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone - ); - } - }else{ - windowCodeRangeTest( - p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone - ); - } - }else{ - sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1); - VdbeCoverage(v); - } - } - - if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){ - windowAggFinal(p, 0); - } - addrContinue = sqlite3VdbeCurrentAddr(v); - - /* 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). 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 - ){ - int regRowid1 = sqlite3GetTempReg(pParse); - int regRowid2 = sqlite3GetTempReg(pParse); - if( op==WINDOW_AGGINVERSE ){ - sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1); - sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2); - sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1); - VdbeCoverage(v); - }else if( p->regRowid ){ - sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1); - sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1); - VdbeCoverageNeverNull(v); - } - sqlite3ReleaseTempReg(pParse, regRowid1); - sqlite3ReleaseTempReg(pParse, regRowid2); - assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ); - } - - switch( op ){ - case WINDOW_RETURN_ROW: - csr = p->current.csr; - reg = p->current.reg; - windowReturnOneRow(p); - break; - - case WINDOW_AGGINVERSE: - csr = p->start.csr; - reg = p->start.reg; - if( pMWin->regStartRowid ){ - assert( pMWin->regEndRowid ); - sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1); - }else{ - windowAggStep(p, pMWin, csr, 1, p->regArg); - } - break; - - default: - assert( op==WINDOW_AGGSTEP ); - csr = p->end.csr; - reg = p->end.reg; - if( pMWin->regStartRowid ){ - assert( pMWin->regEndRowid ); - sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1); - }else{ - windowAggStep(p, pMWin, csr, 0, p->regArg); - } - break; - } - - if( op==p->eDelete ){ - sqlite3VdbeAddOp1(v, OP_Delete, csr); - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - } - - if( jumpOnEof ){ - sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - ret = sqlite3VdbeAddOp0(v, OP_Goto); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer); - VdbeCoverage(v); - if( bPeer ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone); - } - } - - if( bPeer ){ - int nReg = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - int regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0); - windowReadPeerValues(p, csr, regTmp); - windowIfNewPeer(pParse, pMWin->pOrderBy, regTmp, reg, addrContinue); - sqlite3ReleaseTempRange(pParse, regTmp, nReg); - } - - if( addrNextRange ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange); - } - sqlite3VdbeResolveLabel(v, lblDone); - return ret; -} - - -/* -** Allocate and return a duplicate of the Window object indicated by the -** third argument. Set the Window.pOwner field of the new object to -** pOwner. -*/ -SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ - Window *pNew = 0; - if( ALWAYS(p) ){ - pNew = sqlite3DbMallocZero(db, sizeof(Window)); - if( pNew ){ - pNew->zName = sqlite3DbStrDup(db, p->zName); - pNew->zBase = sqlite3DbStrDup(db, p->zBase); - pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); - pNew->pWFunc = p->pWFunc; - pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); - pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); - pNew->eFrmType = p->eFrmType; - pNew->eEnd = p->eEnd; - pNew->eStart = p->eStart; - pNew->eExclude = p->eExclude; - pNew->regResult = p->regResult; - pNew->regAccum = p->regAccum; - pNew->iArgCol = p->iArgCol; - pNew->iEphCsr = p->iEphCsr; - pNew->bExprArgs = p->bExprArgs; - pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); - pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); - pNew->pOwner = pOwner; - pNew->bImplicitFrame = p->bImplicitFrame; - } - } - return pNew; -} - -/* -** Return a copy of the linked list of Window objects passed as the -** second argument. -*/ -SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ - Window *pWin; - Window *pRet = 0; - Window **pp = &pRet; - - for(pWin=p; pWin; pWin=pWin->pNextWin){ - *pp = sqlite3WindowDup(db, 0, pWin); - if( *pp==0 ) break; - pp = &((*pp)->pNextWin); - } - - return pRet; -} - -/* -** Return true if it can be determined at compile time that expression -** pExpr evaluates to a value that, when cast to an integer, is greater -** than zero. False otherwise. -** -** If an OOM error occurs, this function sets the Parse.db.mallocFailed -** flag and returns zero. -*/ -static int windowExprGtZero(Parse *pParse, Expr *pExpr){ - int ret = 0; - sqlite3 *db = pParse->db; - sqlite3_value *pVal = 0; - sqlite3ValueFromExpr(db, pExpr, db->enc, SQLITE_AFF_NUMERIC, &pVal); - if( pVal && sqlite3_value_int(pVal)>0 ){ - ret = 1; - } - sqlite3ValueFree(pVal); - return ret; -} - -/* -** sqlite3WhereBegin() has already been called for the SELECT statement -** passed as the second argument when this function is invoked. It generates -** code to populate the Window.regResult register for each window function -** and invoke the sub-routine at instruction addrGosub once for each row. -** sqlite3WhereEnd() is always called before returning. -** -** This function handles several different types of window frames, which -** require slightly different processing. The following pseudo code is -** used to implement window frames of the form: -** -** ROWS BETWEEN PRECEDING AND FOLLOWING -** -** Other window frame types use variants of the following: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** -** if( first row of partition ){ -** // Rewind three cursors, all open on the eph table. -** Rewind(csrEnd); -** Rewind(csrStart); -** Rewind(csrCurrent); -** -** regEnd = // FOLLOWING expression -** regStart = // PRECEDING expression -** }else{ -** // First time this branch is taken, the eph table contains two -** // rows. The first row in the partition, which all three cursors -** // currently point to, and the following row. -** AGGSTEP -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** RETURN ROW -** if( csrCurrent is EOF ) break; -** if( (regStart--)<=0 ){ -** AggInverse(csrStart) -** Next(csrStart) -** } -** } -** -** The pseudo-code above uses the following shorthand: -** -** AGGSTEP: invoke the aggregate xStep() function for each window function -** with arguments read from the current row of cursor csrEnd, then -** step cursor csrEnd forward one row (i.e. sqlite3BtreeNext()). -** -** RETURN_ROW: return a row to the caller based on the contents of the -** current row of csrCurrent and the current state of all -** aggregates. Then step cursor csrCurrent forward one row. -** -** AGGINVERSE: invoke the aggregate xInverse() function for each window -** functions with arguments read from the current row of cursor -** csrStart. Then step csrStart forward one row. -** -** There are two other ROWS window frames that are handled significantly -** differently from the above - "BETWEEN PRECEDING AND PRECEDING" -** and "BETWEEN FOLLOWING AND FOLLOWING". These are special -** cases because they change the order in which the three cursors (csrStart, -** csrCurrent and csrEnd) iterate through the ephemeral table. Cases that -** use UNBOUNDED or CURRENT ROW are much simpler variations on one of these -** three. -** -** ROWS BETWEEN PRECEDING AND PRECEDING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** if( (regEnd--)<=0 ){ -** AGGSTEP -** } -** RETURN_ROW -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** flush: -** if( (regEnd--)<=0 ){ -** AGGSTEP -** } -** RETURN_ROW -** -** -** ROWS BETWEEN FOLLOWING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = regEnd - -** }else{ -** AGGSTEP -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** } -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** if( eof ) break; -** } -** if( (regStart--)<=0 ){ -** AGGINVERSE -** if( eof ) break -** } -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** For the most part, the patterns above are adapted to support UNBOUNDED by -** assuming that it is equivalent to "infinity PRECEDING/FOLLOWING" and -** CURRENT ROW by assuming that it is equivalent to "0 PRECEDING/FOLLOWING". -** This is optimized of course - branches that will never be taken and -** conditions that are always true are omitted from the VM code. The only -** exceptional case is: -** -** ROWS BETWEEN FOLLOWING AND UNBOUNDED FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regStart = -** }else{ -** AGGSTEP -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** if( (regStart--)<=0 ){ -** AGGINVERSE -** if( eof ) break -** } -** RETURN_ROW -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** Also requiring special handling are the cases: -** -** ROWS BETWEEN PRECEDING AND PRECEDING -** ROWS BETWEEN FOLLOWING AND FOLLOWING -** -** when (expr1 < expr2). This is detected at runtime, not by this function. -** To handle this case, the pseudo-code programs depicted above are modified -** slightly to be: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** if( regEnd < regStart ){ -** RETURN_ROW -** delete eph table contents -** continue -** } -** ... -** -** The new "continue" statement in the above jumps to the next iteration -** of the outer loop - the one started by sqlite3WhereBegin(). -** -** The various GROUPS cases are implemented using the same patterns as -** ROWS. The VM code is modified slightly so that: -** -** 1. The else branch in the main loop is only taken if the row just -** added to the ephemeral table is the start of a new group. In -** other words, it becomes: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else if( new group ){ -** ... -** } -** } -** -** 2. Instead of processing a single row, each RETURN_ROW, AGGSTEP or -** AGGINVERSE step processes the current row of the relevant cursor and -** all subsequent rows belonging to the same group. -** -** RANGE window frames are a little different again. As for GROUPS, the -** main loop runs once per group only. And RETURN_ROW, AGGSTEP and AGGINVERSE -** deal in groups instead of rows. As for ROWS and GROUPS, there are three -** basic cases: -** -** RANGE BETWEEN PRECEDING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** AGGSTEP -** while( (csrCurrent.key + regEnd) < csrEnd.key ){ -** RETURN_ROW -** while( csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** RETURN ROW -** if( csrCurrent is EOF ) break; -** while( csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** } -** } -** -** In the above notation, "csr.key" means the current value of the ORDER BY -** expression (there is only ever 1 for a RANGE that uses an FOLLOWING -** or PRECEDING AND PRECEDING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ -** AGGSTEP -** } -** while( (csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** } -** } -** flush: -** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ -** AGGSTEP -** } -** while( (csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** -** RANGE BETWEEN FOLLOWING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** AGGSTEP -** while( (csrCurrent.key + regEnd) < csrEnd.key ){ -** while( (csrCurrent.key + regStart) > csrStart.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** while( (csrCurrent.key + regStart) > csrStart.key ){ -** AGGINVERSE -** if( eof ) break "while( 1 )" loop. -** } -** RETURN_ROW -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** The text above leaves out many details. Refer to the code and comments -** below for a more complete picture. -*/ -SQLITE_PRIVATE void sqlite3WindowCodeStep( - Parse *pParse, /* Parse context */ - Select *p, /* Rewritten SELECT statement */ - WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ - int regGosub, /* Register for OP_Gosub */ - int addrGosub /* OP_Gosub here to return each row */ -){ - Window *pMWin = p->pWin; - ExprList *pOrderBy = pMWin->pOrderBy; - Vdbe *v = sqlite3GetVdbe(pParse); - int csrWrite; /* Cursor used to write to eph. table */ - int csrInput = p->pSrc->a[0].iCursor; /* Cursor of sub-select */ - int nInput = p->pSrc->a[0].pSTab->nCol; /* Number of cols returned by sub */ - int iInput; /* To iterate through sub cols */ - int addrNe; /* Address of OP_Ne */ - int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ - int addrInteger = 0; /* Address of OP_Integer */ - 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 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" */ - WindowCodeArg s; /* Context object for sub-routines */ - int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */ - int regStart = 0; /* Value of PRECEDING */ - int regEnd = 0; /* Value of FOLLOWING */ - - assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT - || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED - ); - assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT - || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING - ); - assert( pMWin->eExclude==0 || pMWin->eExclude==TK_CURRENT - || pMWin->eExclude==TK_GROUP || pMWin->eExclude==TK_TIES - || pMWin->eExclude==TK_NO - ); - - lblWhereEnd = sqlite3VdbeMakeLabel(pParse); - - /* Fill in the context object */ - memset(&s, 0, sizeof(WindowCodeArg)); - s.pParse = pParse; - s.pMWin = pMWin; - s.pVdbe = v; - s.regGosub = regGosub; - s.addrGosub = addrGosub; - s.current.csr = pMWin->iEphCsr; - csrWrite = s.current.csr+1; - s.start.csr = s.current.csr+2; - s.end.csr = s.current.csr+3; - - /* Figure out when rows may be deleted from the ephemeral table. There - ** are four options - they may never be deleted (eDelete==0), they may - ** be deleted as soon as they are no longer part of the window frame - ** (eDelete==WINDOW_AGGINVERSE), they may be deleted as after the row - ** has been returned to the caller (WINDOW_RETURN_ROW), or they may - ** be deleted after they enter the frame (WINDOW_AGGSTEP). */ - switch( pMWin->eStart ){ - case TK_FOLLOWING: - if( pMWin->eFrmType!=TK_RANGE - && windowExprGtZero(pParse, pMWin->pStart) - ){ - s.eDelete = WINDOW_RETURN_ROW; - } - break; - case TK_UNBOUNDED: - if( windowCacheFrame(pMWin)==0 ){ - if( pMWin->eEnd==TK_PRECEDING ){ - if( pMWin->eFrmType!=TK_RANGE - && windowExprGtZero(pParse, pMWin->pEnd) - ){ - s.eDelete = WINDOW_AGGSTEP; - } - }else{ - s.eDelete = WINDOW_RETURN_ROW; - } - } - break; - default: - s.eDelete = WINDOW_AGGINVERSE; - break; - } - - /* Allocate registers for the array of values from the sub-query, the - ** same values in record form, and the rowid used to insert said record - ** into the ephemeral table. */ - regNew = pParse->nMem+1; - pParse->nMem += nInput; - regRecord = ++pParse->nMem; - s.regRowid = ++pParse->nMem; - - /* If the window frame contains an " PRECEDING" or " FOLLOWING" - ** clause, allocate registers to store the results of evaluating each - ** . */ - if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){ - regStart = ++pParse->nMem; - } - if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){ - regEnd = ++pParse->nMem; - } - - /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of - ** registers to store copies of the ORDER BY expressions (peer values) - ** for the main loop, and for each cursor (start, current and end). */ - if( pMWin->eFrmType!=TK_ROWS ){ - int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); - regNewPeer = regNew + pMWin->nBufferCol; - if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr; - regPeer = pParse->nMem+1; pParse->nMem += nPeer; - s.start.reg = pParse->nMem+1; pParse->nMem += nPeer; - s.current.reg = pParse->nMem+1; pParse->nMem += nPeer; - s.end.reg = pParse->nMem+1; pParse->nMem += nPeer; - } - - /* Load the column values for the row returned by the sub-select - ** into an array of registers starting at regNew. Assemble them into - ** a record in register regRecord. */ - for(iInput=0; iInputpPartition ){ - int addr; - ExprList *pPart = pMWin->pPartition; - int nPart = pPart->nExpr; - int regNewPart = regNew + pMWin->nBufferCol; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); - - regFlushPart = ++pParse->nMem; - addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart, nPart); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); - VdbeCoverageEqNe(v); - addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart); - VdbeComment((v, "call flush_partition")); - sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); - } - - /* Insert the new row into the ephemeral table */ - sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid); - addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid); - VdbeCoverageNeverNull(v); - - /* This block is run for the first row of each partition */ - s.regArg = windowInitAccum(pParse, pMWin); - - if( regStart ){ - sqlite3ExprCode(pParse, pMWin->pStart, regStart); - windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0)); - } - if( regEnd ){ - sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); - windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0)); - } - - if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){ - int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le); - int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd); - VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound */ - VdbeCoverageNeverNullIf(v, op==OP_Le); /* values previously checked */ - windowAggFinal(&s, 0); - sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr); - windowReturnOneRow(&s); - sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); - sqlite3VdbeJumpHere(v, addrGe); - } - if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){ - assert( pMWin->eEnd==TK_FOLLOWING ); - sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart); - } - - if( pMWin->eStart!=TK_UNBOUNDED ){ - sqlite3VdbeAddOp1(v, OP_Rewind, s.start.csr); - } - sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr); - sqlite3VdbeAddOp1(v, OP_Rewind, s.end.csr); - if( regPeer && pOrderBy ){ - sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1); - } - - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); - - sqlite3VdbeJumpHere(v, addrNe); - - /* Beginning of the block executed for the second and subsequent rows. */ - if( regPeer ){ - windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd); - } - if( pMWin->eStart==TK_FOLLOWING ){ - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eFrmType==TK_RANGE ){ - int lbl = sqlite3VdbeMakeLabel(pParse); - int addrNext = sqlite3VdbeCurrentAddr(v); - windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); - sqlite3VdbeResolveLabel(v, lbl); - }else{ - windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - } - } - }else - if( pMWin->eEnd==TK_PRECEDING ){ - int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); - windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); - if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - }else{ - int addr = 0; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eFrmType==TK_RANGE ){ - int lbl = 0; - addr = sqlite3VdbeCurrentAddr(v); - if( regEnd ){ - lbl = sqlite3VdbeMakeLabel(pParse); - windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); - } - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - if( regEnd ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - sqlite3VdbeResolveLabel(v, lbl); - } - }else{ - if( regEnd ){ - addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1); - VdbeCoverage(v); - } - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - if( regEnd ) sqlite3VdbeJumpHere(v, addr); - } - } - } - - /* End of the main input loop */ - sqlite3VdbeResolveLabel(v, lblWhereEnd); - sqlite3WhereEnd(pWInfo); - - /* Fall through */ - if( pMWin->pPartition ){ - addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart); - sqlite3VdbeJumpHere(v, addrGosubFlush); - } - - s.regRowid = 0; - addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite); - VdbeCoverage(v); - if( pMWin->eEnd==TK_PRECEDING ){ - int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); - windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); - if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - }else if( pMWin->eStart==TK_FOLLOWING ){ - int addrStart; - int addrBreak1; - int addrBreak2; - int addrBreak3; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eFrmType==TK_RANGE ){ - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - }else - if( pMWin->eEnd==TK_UNBOUNDED ){ - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); - }else{ - assert( pMWin->eEnd==TK_FOLLOWING ); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak2); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak1); - sqlite3VdbeJumpHere(v, addrBreak3); - }else{ - int addrBreak; - int addrStart; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak); - } - sqlite3VdbeJumpHere(v, addrEmpty); - - sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); - if( pMWin->pPartition ){ - if( pMWin->regStartRowid ){ - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); - } - sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); - } -} - -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/************** End of window.c **********************************************/ -/************** Begin file parse.c *******************************************/ -/* This file is automatically generated by Lemon from input grammar -** source file "parse.y". -*/ -/* -** 2001-09-15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains SQLite's SQL parser. -** -** The canonical source code to this file ("parse.y") is a Lemon grammar -** file that specifies the input grammar and actions to take while parsing. -** That input file is processed by Lemon to generate a C-language -** implementation of a parser for the given grammar. You might be reading -** this comment as part of the translated C-code. Edits should be made -** to the original parse.y sources. -*/ - -/* #include "sqliteInt.h" */ - -/* -** Verify that the pParse->isCreate field is set -*/ -#define ASSERT_IS_CREATE assert(pParse->isCreate) - -/* -** Disable all error recovery processing in the parser push-down -** automaton. -*/ -#define YYNOERRORRECOVERY 1 - -/* -** Make yytestcase() the same as testcase() -*/ -#define yytestcase(X) testcase(X) - -/* -** Indicate that sqlite3ParserFree() will never be called with a null -** pointer. -*/ -#define YYPARSEFREENEVERNULL 1 - -/* -** In the amalgamation, the parse.c file generated by lemon and the -** tokenize.c file are concatenated. In that case, sqlite3RunParser() -** has access to the the size of the yyParser object and so the parser -** engine can be allocated from stack. In that case, only the -** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked -** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be -** omitted. -*/ -#ifdef SQLITE_AMALGAMATION -# define sqlite3Parser_ENGINEALWAYSONSTACK 1 -#endif - -/* -** Alternative datatype for the argument to the malloc() routine passed -** into sqlite3ParserAlloc(). The default is size_t. -*/ -#define YYMALLOCARGTYPE u64 - -/* -** An instance of the following structure describes the event of a -** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, -** TK_DELETE, or TK_INSTEAD. If the event is of the form -** -** UPDATE ON (a,b,c) -** -** Then the "b" IdList records the list "a,b,c". -*/ -struct TrigEvent { int a; IdList * b; }; - -struct FrameBound { int eType; Expr *pExpr; }; - -/* -** Generate a syntax error -*/ -static void parserSyntaxError(Parse *pParse, Token *p){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p); -} - -/* -** Disable lookaside memory allocation for objects that might be -** shared across database connections. -*/ -static void disableLookaside(Parse *pParse){ - sqlite3 *db = pParse->db; - pParse->disableLookaside++; -#ifdef SQLITE_DEBUG - pParse->isCreate = 1; -#endif - memset(&pParse->u1.cr, 0, sizeof(pParse->u1.cr)); - DisableLookaside; -} - -#if !defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) \ - && defined(SQLITE_UDL_CAPABLE_PARSER) -/* -** Issue an error message if an ORDER BY or LIMIT clause occurs on an -** UPDATE or DELETE statement. -*/ -static void updateDeleteLimitError( - Parse *pParse, - ExprList *pOrderBy, - Expr *pLimit -){ - if( pOrderBy ){ - sqlite3ErrorMsg(pParse, "syntax error near \"ORDER BY\""); - }else{ - sqlite3ErrorMsg(pParse, "syntax error near \"LIMIT\""); - } - sqlite3ExprListDelete(pParse->db, pOrderBy); - sqlite3ExprDelete(pParse->db, pLimit); -} -#endif /* SQLITE_ENABLE_UPDATE_DELETE_LIMIT */ - - - /* - ** For a compound SELECT statement, make sure p->pPrior->pNext==p for - ** all elements in the list. And make sure list length does not exceed - ** SQLITE_LIMIT_COMPOUND_SELECT. - */ - static void parserDoubleLinkSelect(Parse *pParse, Select *p){ - assert( p!=0 ); - if( p->pPrior ){ - 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 ){ - sqlite3ErrorMsg(pParse,"%s clause should come after %s not before", - pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT", - sqlite3SelectOpName(pNext->op)); - break; - } - } - if( (p->selFlags & (SF_MultiValue|SF_Values))==0 - && (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 - && cnt>mxSelect - ){ - sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); - } - } - } - - /* 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{ - sqlite3WithDelete(pParse->db, pWith); - } - return pSelect; - } - - /* Memory allocator for parser stack resizing. This is a thin wrapper around - ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate - ** testing. - */ - static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){ - return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); - } - - - /* Construct a new Expr object from a single token */ - static Expr *tokenExpr(Parse *pParse, int op, Token t){ - Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); - if( p ){ - /* memset(p, 0, sizeof(Expr)); */ - p->op = (u8)op; - p->affExpr = 0; - p->flags = EP_Leaf; - ExprClearVVAProperties(p); - /* p->iAgg = -1; // Not required */ - p->pLeft = p->pRight = 0; - p->pAggInfo = 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( sqlite3Isquote(p->u.zToken[0]) ){ - sqlite3DequoteExpr(p); - } -#if SQLITE_MAX_EXPR_DEPTH>0 - p->nHeight = 1; -#endif - if( IN_RENAME_OBJECT ){ - return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t); - } - } - return p; - } - - - /* A routine to convert a binary TK_IS or TK_ISNOT expression into a - ** unary TK_ISNULL or TK_NOTNULL expression. */ - static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ - sqlite3 *db = pParse->db; - if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ - pA->op = (u8)op; - sqlite3ExprDelete(db, pA->pRight); - pA->pRight = 0; - } - } - - /* Add a single new term to an ExprList that is used to store a - ** list of identifiers. Report an error if the ID list contains - ** a COLLATE clause or an ASC or DESC keyword, except ignore the - ** error while parsing a legacy schema. - */ - static ExprList *parserAddExprIdListTerm( - Parse *pParse, - ExprList *pPrior, - Token *pIdToken, - int hasCollate, - int sortOrder - ){ - ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0); - if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED) - && pParse->db->init.busy==0 - ){ - sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"", - pIdToken->n, pIdToken->z); - } - sqlite3ExprListSetName(pParse, p, pIdToken, 1); - return p; - } - -#if TK_SPAN>255 -# error too many tokens in the grammar -#endif -/**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols. -***************** Begin token definitions *************************************/ -#ifndef TK_SEMI -#define TK_SEMI 1 -#define TK_EXPLAIN 2 -#define TK_QUERY 3 -#define TK_PLAN 4 -#define TK_BEGIN 5 -#define TK_TRANSACTION 6 -#define TK_DEFERRED 7 -#define TK_IMMEDIATE 8 -#define TK_EXCLUSIVE 9 -#define TK_COMMIT 10 -#define TK_END 11 -#define TK_ROLLBACK 12 -#define TK_SAVEPOINT 13 -#define TK_RELEASE 14 -#define TK_TO 15 -#define TK_TABLE 16 -#define TK_CREATE 17 -#define TK_IF 18 -#define TK_NOT 19 -#define TK_EXISTS 20 -#define TK_TEMP 21 -#define TK_LP 22 -#define TK_RP 23 -#define TK_AS 24 -#define TK_COMMA 25 -#define TK_WITHOUT 26 -#define TK_ABORT 27 -#define TK_ACTION 28 -#define TK_AFTER 29 -#define TK_ANALYZE 30 -#define TK_ASC 31 -#define TK_ATTACH 32 -#define TK_BEFORE 33 -#define TK_BY 34 -#define TK_CASCADE 35 -#define TK_CAST 36 -#define TK_CONFLICT 37 -#define TK_DATABASE 38 -#define TK_DESC 39 -#define TK_DETACH 40 -#define TK_EACH 41 -#define TK_FAIL 42 -#define TK_OR 43 -#define TK_AND 44 -#define TK_IS 45 -#define TK_ISNOT 46 -#define TK_MATCH 47 -#define TK_LIKE_KW 48 -#define TK_BETWEEN 49 -#define TK_IN 50 -#define TK_ISNULL 51 -#define TK_NOTNULL 52 -#define TK_NE 53 -#define TK_EQ 54 -#define TK_GT 55 -#define TK_LE 56 -#define TK_LT 57 -#define TK_GE 58 -#define TK_ESCAPE 59 -#define TK_ID 60 -#define TK_COLUMNKW 61 -#define TK_DO 62 -#define TK_FOR 63 -#define TK_IGNORE 64 -#define TK_INITIALLY 65 -#define TK_INSTEAD 66 -#define TK_NO 67 -#define TK_KEY 68 -#define TK_OF 69 -#define TK_OFFSET 70 -#define TK_PRAGMA 71 -#define TK_RAISE 72 -#define TK_RECURSIVE 73 -#define TK_REPLACE 74 -#define TK_RESTRICT 75 -#define TK_ROW 76 -#define TK_ROWS 77 -#define TK_TRIGGER 78 -#define TK_VACUUM 79 -#define TK_VIEW 80 -#define TK_VIRTUAL 81 -#define TK_WITH 82 -#define TK_NULLS 83 -#define TK_FIRST 84 -#define TK_LAST 85 -#define TK_CURRENT 86 -#define TK_FOLLOWING 87 -#define TK_PARTITION 88 -#define TK_PRECEDING 89 -#define TK_RANGE 90 -#define TK_UNBOUNDED 91 -#define TK_EXCLUDE 92 -#define TK_GROUPS 93 -#define TK_OTHERS 94 -#define TK_TIES 95 -#define TK_GENERATED 96 -#define TK_ALWAYS 97 -#define TK_MATERIALIZED 98 -#define TK_REINDEX 99 -#define TK_RENAME 100 -#define TK_CTIME_KW 101 -#define TK_ANY 102 -#define TK_BITAND 103 -#define TK_BITOR 104 -#define TK_LSHIFT 105 -#define TK_RSHIFT 106 -#define TK_PLUS 107 -#define TK_MINUS 108 -#define TK_STAR 109 -#define TK_SLASH 110 -#define TK_REM 111 -#define TK_CONCAT 112 -#define TK_PTR 113 -#define TK_COLLATE 114 -#define TK_BITNOT 115 -#define TK_ON 116 -#define TK_INDEXED 117 -#define TK_STRING 118 -#define TK_JOIN_KW 119 -#define TK_CONSTRAINT 120 -#define TK_DEFAULT 121 -#define TK_NULL 122 -#define TK_PRIMARY 123 -#define TK_UNIQUE 124 -#define TK_CHECK 125 -#define TK_REFERENCES 126 -#define TK_AUTOINCR 127 -#define TK_INSERT 128 -#define TK_DELETE 129 -#define TK_UPDATE 130 -#define TK_SET 131 -#define TK_DEFERRABLE 132 -#define TK_FOREIGN 133 -#define TK_DROP 134 -#define TK_UNION 135 -#define TK_ALL 136 -#define TK_EXCEPT 137 -#define TK_INTERSECT 138 -#define TK_SELECT 139 -#define TK_VALUES 140 -#define TK_DISTINCT 141 -#define TK_DOT 142 -#define TK_FROM 143 -#define TK_JOIN 144 -#define TK_USING 145 -#define TK_ORDER 146 -#define TK_GROUP 147 -#define TK_HAVING 148 -#define TK_LIMIT 149 -#define TK_WHERE 150 -#define TK_RETURNING 151 -#define TK_INTO 152 -#define TK_NOTHING 153 -#define TK_FLOAT 154 -#define TK_BLOB 155 -#define TK_INTEGER 156 -#define TK_VARIABLE 157 -#define TK_CASE 158 -#define TK_WHEN 159 -#define TK_THEN 160 -#define TK_ELSE 161 -#define TK_INDEX 162 -#define TK_ALTER 163 -#define TK_ADD 164 -#define TK_WINDOW 165 -#define TK_OVER 166 -#define TK_FILTER 167 -#define TK_COLUMN 168 -#define TK_AGG_FUNCTION 169 -#define TK_AGG_COLUMN 170 -#define TK_TRUEFALSE 171 -#define TK_FUNCTION 172 -#define TK_UPLUS 173 -#define TK_UMINUS 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_QNUMBER 183 -#define TK_SPACE 184 -#define TK_COMMENT 185 -#define TK_ILLEGAL 186 -#endif -/**************** End token definitions ***************************************/ - -/* The next sections is a series of control #defines. -** various aspects of the generated parser. -** YYCODETYPE is the data type used to store the integer codes -** that represent terminal and non-terminal symbols. -** "unsigned char" is used if there are fewer than -** 256 symbols. Larger types otherwise. -** YYNOCODE is a number of type YYCODETYPE that is not used for -** any terminal or nonterminal symbol. -** YYFALLBACK If defined, this indicates that one or more tokens -** (also known as: "terminal symbols") have fall-back -** values which should be used if the original symbol -** would not parse. This permits keywords to sometimes -** be used as identifiers, for example. -** YYACTIONTYPE is the data type used for "action codes" - numbers -** that indicate what to do in response to the next -** token. -** sqlite3ParserTOKENTYPE is the data type used for minor type for terminal -** symbols. Background: A "minor type" is a semantic -** value associated with a terminal or non-terminal -** symbols. For example, for an "ID" terminal symbol, -** the minor type might be the name of the identifier. -** Each non-terminal can have a different minor type. -** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal -** symbols. -** YYMINORTYPE is the data type used for all minor types. -** This is typically a union of many types, one of -** which is sqlite3ParserTOKENTYPE. The entry in the union -** for terminal symbols is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. If -** zero the stack is dynamically sized using realloc() -** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument -** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument -** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter -** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser -** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser -** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context -** YYREALLOC Name of the realloc() function to use -** YYFREE Name of the free() function to use -** YYDYNSTACK True if stack space should be extended on heap -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. -** YYNSTATE the combined number of states. -** YYNRULE the number of rules in the grammar -** YYNTOKEN Number of terminal symbols -** YY_MAX_SHIFT Maximum value for shift actions -** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions -** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_ERROR_ACTION The yy_action[] code for syntax error -** YY_ACCEPT_ACTION The yy_action[] code for accept -** YY_NO_ACTION The yy_action[] code for no-op -** YY_MIN_REDUCE Minimum value for reduce actions -** YY_MAX_REDUCE Maximum value for reduce actions -** YY_MIN_DSTRCTR Minimum symbol value that has a destructor -** YY_MAX_DSTRCTR Maximum symbol value that has a destructor -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/************* Begin control #defines *****************************************/ -#define YYCODETYPE unsigned short int -#define YYNOCODE 323 -#define YYACTIONTYPE unsigned short int -#define YYWILDCARD 102 -#define sqlite3ParserTOKENTYPE Token -typedef union { - int yyinit; - sqlite3ParserTOKENTYPE yy0; - u32 yy9; - struct TrigEvent yy28; - With* yy125; - IdList* yy204; - struct FrameBound yy205; - TriggerStep* yy319; - const char* yy342; - Cte* yy361; - ExprList* yy402; - Upsert* yy403; - OnOrUsing yy421; - u8 yy444; - struct {int value; int mask;} yy481; - Window* yy483; - int yy502; - SrcList* yy563; - Expr* yy590; - Select* yy637; -} YYMINORTYPE; -#ifndef YYSTACKDEPTH -#define YYSTACKDEPTH 100 -#endif -#define sqlite3ParserARG_SDECL -#define sqlite3ParserARG_PDECL -#define sqlite3ParserARG_PARAM -#define sqlite3ParserARG_FETCH -#define sqlite3ParserARG_STORE -#define YYREALLOC parserStackRealloc -#define YYFREE sqlite3_free -#define YYDYNSTACK 1 -#define sqlite3ParserCTX_SDECL Parse *pParse; -#define sqlite3ParserCTX_PDECL ,Parse *pParse -#define sqlite3ParserCTX_PARAM ,pParse -#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; -#define sqlite3ParserCTX_STORE yypParser->pParse=pParse; -#define YYFALLBACK 1 -#define YYNSTATE 583 -#define YYNRULE 409 -#define YYNRULE_WITH_ACTION 344 -#define YYNTOKEN 187 -#define YY_MAX_SHIFT 582 -#define YY_MIN_SHIFTREDUCE 845 -#define YY_MAX_SHIFTREDUCE 1253 -#define YY_ERROR_ACTION 1254 -#define YY_ACCEPT_ACTION 1255 -#define YY_NO_ACTION 1256 -#define YY_MIN_REDUCE 1257 -#define YY_MAX_REDUCE 1665 -#define YY_MIN_DSTRCTR 206 -#define YY_MAX_DSTRCTR 320 -/************* End control #defines *******************************************/ -#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) - -/* Define the yytestcase() macro to be a no-op if is not already defined -** otherwise. -** -** Applications can choose to define yytestcase() in the %include section -** to a macro that can assist in verifying code coverage. For production -** code the yytestcase() macro should be turned off. But it is useful -** for testing. -*/ -#ifndef yytestcase -# define yytestcase(X) -#endif - -/* Macro to determine if stack space has the ability to grow using -** heap memory. -*/ -#if YYSTACKDEPTH<=0 || YYDYNSTACK -# define YYGROWABLESTACK 1 -#else -# define YYGROWABLESTACK 0 -#endif - -/* Guarantee a minimum number of initial stack slots. -*/ -#if YYSTACKDEPTH<=0 -# undef YYSTACKDEPTH -# define YYSTACKDEPTH 2 /* Need a minimum stack size */ -#endif - - -/* Next are the tables used to determine what action to take based on the -** current state and lookahead token. These tables are used to implement -** functions that take a state number and lookahead value and return an -** action integer. -** -** Suppose the action integer is N. Then the action is determined as -** follows -** -** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead -** token onto the stack and goto state N. -** -** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then -** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. -** -** N == YY_ERROR_ACTION A syntax error has occurred. -** -** N == YY_ACCEPT_ACTION The parser accepts its input. -** -** N == YY_NO_ACTION No such action. Denotes unused -** slots in the yy_action[] table. -** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE -** -** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as either: -** -** (A) N = yy_action[ yy_shift_ofst[S] + X ] -** (B) N = yy_default[S] -** -** The (A) formula is preferred. The B formula is used instead if -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. -** -** The formulas above are for computing the action when the lookahead is -** a terminal symbol. If the lookahead is a non-terminal (as occurs after -** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array. -** -** The following are the tables generated in this section: -** -** yy_action[] A single table containing all actions. -** yy_lookahead[] A table containing the lookahead for each entry in -** yy_action. Used to detect hash collisions. -** yy_shift_ofst[] For each state, the offset into yy_action for -** shifting terminals. -** yy_reduce_ofst[] For each state, the offset into yy_action for -** shifting non-terminals after a reduce. -** yy_default[] Default action for each state. -** -*********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2207) -static const YYACTIONTYPE yy_action[] = { - /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289, - /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413, - /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82, - /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984, - /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063, - /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413, - /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130, - /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290, - /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063, - /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296, - /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132, - /* 110 */ 132, 132, 131, 128, 451, 451, 1050, 1050, 1064, 1067, - /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174, - /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 481, 1341, - /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132, - /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 498, 1228, - /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, - /* 170 */ 136, 1204, 862, 1281, 288, 288, 283, 288, 288, 523, - /* 180 */ 523, 1250, 139, 578, 7, 578, 1345, 573, 1169, 562, - /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 573, 547, - /* 200 */ 562, 1169, 245, 1541, 1169, 245, 133, 133, 132, 132, - /* 210 */ 132, 131, 128, 451, 302, 134, 134, 134, 134, 133, - /* 220 */ 133, 132, 132, 132, 131, 128, 451, 1575, 1204, 1205, - /* 230 */ 1204, 7, 470, 550, 455, 413, 550, 455, 130, 127, - /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132, - /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 483, 137, - /* 260 */ 138, 91, 1019, 1228, 1228, 1063, 1066, 1053, 1053, 135, - /* 270 */ 135, 136, 136, 136, 136, 1085, 576, 1204, 132, 132, - /* 280 */ 132, 131, 128, 451, 93, 214, 134, 134, 134, 134, - /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 401, 19, - /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132, - /* 310 */ 131, 128, 451, 1498, 426, 267, 344, 467, 332, 134, - /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128, - /* 330 */ 451, 1281, 576, 6, 1204, 1205, 1204, 257, 576, 413, - /* 340 */ 511, 508, 507, 1279, 94, 1019, 464, 1204, 551, 551, - /* 350 */ 506, 1224, 1571, 44, 38, 51, 51, 411, 576, 413, - /* 360 */ 45, 51, 51, 137, 138, 91, 530, 1228, 1228, 1063, - /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 398, - /* 380 */ 1148, 82, 82, 137, 138, 91, 39, 1228, 1228, 1063, - /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 344, - /* 400 */ 44, 288, 288, 375, 1204, 1205, 1204, 209, 1204, 1224, - /* 410 */ 320, 567, 471, 576, 573, 576, 562, 576, 316, 264, - /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132, - /* 430 */ 132, 132, 131, 128, 451, 303, 82, 82, 82, 82, - /* 440 */ 82, 82, 442, 134, 134, 134, 134, 133, 133, 132, - /* 450 */ 132, 132, 131, 128, 451, 1582, 544, 320, 567, 1250, - /* 460 */ 874, 1582, 380, 382, 413, 1204, 1205, 1204, 360, 182, - /* 470 */ 288, 288, 1576, 557, 1339, 557, 7, 557, 1277, 472, - /* 480 */ 346, 526, 531, 573, 556, 562, 439, 1511, 137, 138, - /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, - /* 500 */ 136, 136, 136, 136, 465, 1511, 1513, 532, 413, 288, - /* 510 */ 288, 423, 512, 288, 288, 411, 288, 288, 874, 130, - /* 520 */ 127, 234, 573, 1107, 562, 1204, 573, 1107, 562, 573, - /* 530 */ 560, 562, 137, 138, 91, 1293, 1228, 1228, 1063, 1066, - /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134, - /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, - /* 560 */ 493, 503, 1292, 1204, 257, 288, 288, 511, 508, 507, - /* 570 */ 1204, 1628, 1169, 123, 568, 275, 4, 506, 573, 1511, - /* 580 */ 562, 331, 1204, 1205, 1204, 1169, 548, 548, 1169, 261, - /* 590 */ 571, 7, 134, 134, 134, 134, 133, 133, 132, 132, - /* 600 */ 132, 131, 128, 451, 108, 533, 130, 127, 234, 1204, - /* 610 */ 448, 447, 413, 1451, 452, 983, 886, 96, 1598, 1233, - /* 620 */ 1204, 1205, 1204, 984, 1235, 1450, 565, 1204, 1205, 1204, - /* 630 */ 229, 522, 1234, 534, 1333, 1333, 137, 138, 91, 1449, - /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 650 */ 136, 136, 373, 1595, 971, 1040, 413, 1236, 418, 1236, - /* 660 */ 879, 121, 121, 948, 373, 1595, 1204, 1205, 1204, 122, - /* 670 */ 1204, 452, 577, 452, 363, 417, 1028, 882, 373, 1595, - /* 680 */ 137, 138, 91, 462, 1228, 1228, 1063, 1066, 1053, 1053, - /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134, - /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028, - /* 710 */ 1030, 1031, 35, 570, 570, 570, 197, 423, 1040, 198, - /* 720 */ 1204, 123, 568, 1204, 4, 320, 567, 1204, 1205, 1204, - /* 730 */ 40, 388, 576, 384, 882, 1029, 423, 1188, 571, 1028, - /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 750 */ 128, 451, 529, 1568, 1204, 19, 19, 1204, 575, 492, - /* 760 */ 413, 157, 452, 489, 1187, 1331, 1331, 5, 1204, 949, - /* 770 */ 431, 1028, 1028, 1030, 565, 22, 22, 1204, 1205, 1204, - /* 780 */ 1204, 1205, 1204, 477, 137, 138, 91, 212, 1228, 1228, - /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 800 */ 1188, 48, 111, 1040, 413, 1204, 213, 970, 1041, 121, - /* 810 */ 121, 1204, 1205, 1204, 1204, 1205, 1204, 122, 221, 452, - /* 820 */ 577, 452, 44, 487, 1028, 1204, 1205, 1204, 137, 138, - /* 830 */ 91, 378, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, - /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133, - /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031, - /* 860 */ 35, 461, 1204, 1205, 1204, 1569, 1040, 377, 214, 1149, - /* 870 */ 1657, 535, 1657, 437, 902, 320, 567, 1568, 364, 320, - /* 880 */ 567, 412, 329, 1029, 519, 1188, 3, 1028, 134, 134, - /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, - /* 900 */ 1659, 399, 1169, 307, 893, 307, 515, 576, 413, 214, - /* 910 */ 498, 944, 1024, 540, 903, 1169, 943, 392, 1169, 1028, - /* 920 */ 1028, 1030, 406, 298, 1204, 50, 1149, 1658, 413, 1658, - /* 930 */ 145, 145, 137, 138, 91, 293, 1228, 1228, 1063, 1066, - /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 1188, 1147, - /* 950 */ 514, 1568, 137, 138, 91, 1505, 1228, 1228, 1063, 1066, - /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 323, - /* 970 */ 435, 539, 111, 1506, 274, 291, 372, 517, 367, 516, - /* 980 */ 262, 1204, 1205, 1204, 1574, 481, 363, 576, 7, 1569, - /* 990 */ 1568, 377, 134, 134, 134, 134, 133, 133, 132, 132, - /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 576, 232, 576, - /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132, - /* 1020 */ 132, 131, 128, 451, 1169, 433, 576, 1207, 19, 19, - /* 1030 */ 19, 19, 19, 19, 1627, 576, 911, 1169, 47, 120, - /* 1040 */ 1169, 117, 413, 306, 498, 438, 1125, 206, 336, 19, - /* 1050 */ 19, 1435, 49, 449, 449, 449, 1368, 315, 81, 81, - /* 1060 */ 576, 304, 413, 1570, 207, 377, 137, 138, 91, 115, - /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 1080 */ 136, 136, 576, 82, 82, 1207, 137, 138, 91, 1340, - /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 1100 */ 136, 136, 1569, 386, 377, 82, 82, 463, 1126, 1552, - /* 1110 */ 333, 463, 335, 131, 128, 451, 1569, 161, 377, 16, - /* 1120 */ 317, 387, 428, 1127, 448, 447, 134, 134, 134, 134, - /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576, - /* 1140 */ 1105, 10, 445, 267, 576, 1554, 134, 134, 134, 134, - /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 532, 576, - /* 1160 */ 922, 576, 19, 19, 576, 1573, 576, 147, 147, 7, - /* 1170 */ 923, 1236, 498, 1236, 576, 487, 413, 552, 285, 1224, - /* 1180 */ 969, 215, 82, 82, 66, 66, 1435, 67, 67, 21, - /* 1190 */ 21, 1110, 1110, 495, 334, 297, 413, 53, 53, 297, - /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 1336, 1311, 446, - /* 1220 */ 137, 138, 91, 227, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1230 */ 135, 135, 136, 136, 136, 136, 574, 1224, 936, 936, - /* 1240 */ 137, 126, 91, 141, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1250 */ 135, 135, 136, 136, 136, 136, 533, 429, 472, 346, - /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1270 */ 128, 451, 576, 457, 233, 343, 1435, 403, 498, 1550, - /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1290 */ 128, 451, 576, 324, 576, 82, 82, 487, 576, 969, - /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1310 */ 128, 451, 288, 288, 546, 68, 68, 54, 54, 553, - /* 1320 */ 413, 69, 69, 351, 6, 573, 944, 562, 410, 409, - /* 1330 */ 1435, 943, 450, 545, 260, 259, 258, 576, 158, 576, - /* 1340 */ 413, 222, 1180, 479, 969, 138, 91, 430, 1228, 1228, - /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 1360 */ 70, 70, 71, 71, 576, 1126, 91, 576, 1228, 1228, - /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 1380 */ 1127, 166, 850, 851, 852, 1282, 419, 72, 72, 108, - /* 1390 */ 73, 73, 1310, 358, 1180, 1128, 576, 305, 576, 123, - /* 1400 */ 568, 494, 4, 488, 134, 134, 134, 134, 133, 133, - /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 55, - /* 1420 */ 55, 56, 56, 576, 134, 134, 134, 134, 133, 133, - /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 1104, 233, 1104, - /* 1440 */ 452, 1602, 582, 2, 1259, 576, 57, 57, 576, 321, - /* 1450 */ 576, 155, 565, 1435, 485, 353, 576, 356, 1341, 59, - /* 1460 */ 59, 576, 44, 969, 569, 419, 576, 238, 60, 60, - /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 576, 1366, 76, - /* 1480 */ 76, 1040, 420, 184, 20, 20, 576, 121, 121, 77, - /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 452, 577, 452, - /* 1500 */ 143, 143, 1028, 576, 520, 576, 573, 576, 562, 144, - /* 1510 */ 144, 474, 227, 1244, 478, 123, 568, 576, 4, 320, - /* 1520 */ 567, 245, 411, 576, 443, 411, 78, 78, 62, 62, - /* 1530 */ 79, 79, 571, 319, 1028, 1028, 1030, 1031, 35, 418, - /* 1540 */ 63, 63, 576, 290, 411, 9, 80, 80, 1144, 576, - /* 1550 */ 400, 576, 486, 455, 576, 1223, 452, 576, 325, 342, - /* 1560 */ 576, 111, 576, 1188, 242, 64, 64, 473, 565, 576, - /* 1570 */ 23, 576, 170, 170, 171, 171, 576, 87, 87, 328, - /* 1580 */ 65, 65, 542, 83, 83, 146, 146, 541, 123, 568, - /* 1590 */ 341, 4, 84, 84, 168, 168, 576, 1040, 576, 148, - /* 1600 */ 148, 576, 1380, 121, 121, 571, 1021, 576, 266, 576, - /* 1610 */ 424, 122, 576, 452, 577, 452, 576, 553, 1028, 142, - /* 1620 */ 142, 169, 169, 576, 162, 162, 528, 889, 371, 452, - /* 1630 */ 152, 152, 151, 151, 1379, 149, 149, 109, 370, 150, - /* 1640 */ 150, 565, 576, 480, 576, 266, 86, 86, 576, 1092, - /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 482, 576, 266, 466, - /* 1660 */ 543, 123, 568, 1616, 4, 88, 88, 85, 85, 475, - /* 1670 */ 1040, 52, 52, 222, 901, 900, 121, 121, 571, 1188, - /* 1680 */ 58, 58, 244, 1032, 122, 889, 452, 577, 452, 908, - /* 1690 */ 909, 1028, 300, 347, 504, 111, 263, 361, 165, 111, - /* 1700 */ 111, 1088, 452, 263, 974, 1153, 266, 1092, 986, 987, - /* 1710 */ 942, 939, 125, 125, 565, 1103, 872, 1103, 159, 941, - /* 1720 */ 1309, 125, 1557, 1028, 1028, 1030, 1031, 35, 542, 337, - /* 1730 */ 1530, 205, 1529, 541, 499, 1589, 490, 348, 1376, 352, - /* 1740 */ 355, 1032, 357, 1040, 359, 1324, 1308, 366, 563, 121, - /* 1750 */ 121, 376, 1188, 1389, 1434, 1362, 280, 122, 1374, 452, - /* 1760 */ 577, 452, 167, 1439, 1028, 1289, 1280, 1268, 1267, 1269, - /* 1770 */ 1609, 1359, 312, 313, 314, 397, 12, 237, 224, 1421, - /* 1780 */ 295, 1416, 1409, 1426, 339, 484, 340, 509, 1371, 1612, - /* 1790 */ 1372, 1425, 1244, 404, 301, 228, 1028, 1028, 1030, 1031, - /* 1800 */ 35, 1601, 1192, 454, 345, 1307, 292, 369, 1502, 1501, - /* 1810 */ 270, 396, 396, 395, 277, 393, 1370, 1369, 859, 1549, - /* 1820 */ 186, 123, 568, 235, 4, 1188, 391, 210, 211, 223, - /* 1830 */ 1547, 239, 1241, 327, 422, 96, 220, 195, 571, 180, - /* 1840 */ 188, 326, 468, 469, 190, 191, 502, 192, 193, 566, - /* 1850 */ 247, 109, 1430, 491, 199, 251, 102, 281, 402, 476, - /* 1860 */ 405, 1496, 452, 497, 253, 1422, 13, 1428, 14, 1427, - /* 1870 */ 203, 1507, 241, 500, 565, 354, 407, 92, 95, 1270, - /* 1880 */ 175, 254, 518, 43, 1327, 255, 1326, 1325, 436, 1518, - /* 1890 */ 350, 1318, 104, 229, 893, 1626, 440, 441, 1625, 408, - /* 1900 */ 240, 1296, 268, 1040, 310, 269, 1297, 527, 444, 121, - /* 1910 */ 121, 368, 1295, 1594, 1624, 311, 1394, 122, 1317, 452, - /* 1920 */ 577, 452, 374, 1580, 1028, 1393, 140, 553, 11, 90, - /* 1930 */ 568, 385, 4, 116, 318, 414, 1579, 110, 1483, 537, - /* 1940 */ 320, 567, 1350, 555, 42, 579, 571, 1349, 1198, 383, - /* 1950 */ 276, 390, 216, 389, 278, 279, 1028, 1028, 1030, 1031, - /* 1960 */ 35, 172, 580, 1265, 458, 1260, 415, 416, 185, 156, - /* 1970 */ 452, 1534, 1535, 173, 1533, 1532, 89, 308, 225, 226, - /* 1980 */ 846, 174, 565, 453, 217, 1188, 322, 236, 1102, 154, - /* 1990 */ 1100, 330, 187, 176, 1223, 243, 189, 925, 338, 246, - /* 2000 */ 1116, 194, 177, 425, 178, 427, 98, 196, 99, 100, - /* 2010 */ 101, 1040, 179, 1119, 1115, 248, 249, 121, 121, 163, - /* 2020 */ 24, 250, 349, 1238, 496, 122, 1108, 452, 577, 452, - /* 2030 */ 1192, 454, 1028, 266, 292, 200, 252, 201, 861, 396, - /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256, - /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239, - /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326, - /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309, - /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155, - /* 2090 */ 17, 1154, 230, 1188, 284, 286, 265, 204, 125, 1171, - /* 2100 */ 241, 28, 978, 972, 29, 41, 1175, 1179, 175, 1173, - /* 2110 */ 30, 43, 31, 8, 241, 1178, 32, 1160, 208, 549, - /* 2120 */ 33, 111, 175, 1083, 1070, 43, 1068, 1072, 240, 113, - /* 2130 */ 114, 34, 561, 118, 1124, 271, 1073, 36, 18, 572, - /* 2140 */ 1033, 873, 240, 124, 37, 935, 272, 273, 1617, 183, - /* 2150 */ 153, 394, 1194, 1193, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567, - /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256, - /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458, -}; -static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241, - /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19, - /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218, - /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39, - /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19, - /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277, - /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218, - /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271, - /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50, - /* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89, - /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206, - /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109, - /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47, - /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312, - /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256, - /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88, - /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110, - /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107, - /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118, - /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278, - /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43, - /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53, - /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110, - /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106, - /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218, - /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103, - /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19, - /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311, - /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19, - /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49, - /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22, - /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49, - /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128, - /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118, - /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259, - /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109, - /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219, - /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109, - /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102, - /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195, - /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129, - /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44, - /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54, - /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241, - /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277, - /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254, - /* 530 */ 206, 256, 43, 44, 45, 218, 47, 48, 49, 50, - /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104, - /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 560 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125, - /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287, - /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47, - /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110, - /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60, - /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116, - /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119, - /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276, - /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156, - /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115, - /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316, - /* 680 */ 43, 44, 45, 272, 47, 48, 49, 50, 51, 52, - /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106, - /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155, - /* 710 */ 156, 157, 158, 212, 213, 214, 22, 195, 101, 22, - /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119, - /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122, - /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284, - /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109, - /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119, - /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48, - /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107, - /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117, - /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44, - /* 830 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108, - /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157, - /* 860 */ 158, 121, 117, 118, 119, 307, 101, 309, 195, 22, - /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139, - /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104, - /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195, - /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154, - /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25, - /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50, - /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102, - /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50, - /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134, - /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125, - /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307, - /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195, - /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219, - /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159, - /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218, - /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219, - /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160, - /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240, - /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195, - /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24, - /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106, - /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195, - /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106, - /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195, - /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317, - /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60, - /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218, - /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267, - /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52, - /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255, - /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52, - /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138, - /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52, - /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130, - /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195, - /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144, - /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146, - /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108, - /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195, - /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48, - /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48, - /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116, - /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19, - /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108, - /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218, - /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108, - /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156, - /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197, - /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218, - /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219, - /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218, - /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218, - /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119, - /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218, - /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139, - /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219, - /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116, - /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195, - /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23, - /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195, - /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195, - /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20, - /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218, - /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195, - /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218, - /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60, - /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218, - /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60, - /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195, - /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130, - /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183, - /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7, - /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25, - /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85, - /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23, - /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195, - /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195, - /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107, - /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117, - /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195, - /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274, - /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198, - /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157, - /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221, - /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202, - /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245, - /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 43, - /* 1840 */ 236, 40, 18, 202, 239, 239, 18, 239, 239, 283, - /* 1850 */ 201, 150, 236, 202, 236, 201, 159, 202, 248, 248, - /* 1860 */ 248, 248, 60, 63, 201, 275, 273, 275, 273, 275, - /* 1870 */ 22, 286, 71, 223, 72, 202, 223, 297, 297, 202, - /* 1880 */ 79, 201, 116, 82, 220, 201, 220, 220, 65, 293, - /* 1890 */ 292, 229, 22, 166, 127, 226, 24, 114, 226, 223, - /* 1900 */ 99, 222, 202, 101, 285, 92, 220, 308, 83, 107, - /* 1910 */ 108, 220, 220, 316, 220, 285, 268, 115, 229, 117, - /* 1920 */ 118, 119, 223, 321, 122, 268, 149, 146, 22, 19, - /* 1930 */ 20, 202, 22, 159, 282, 134, 321, 148, 280, 147, - /* 1940 */ 139, 140, 252, 141, 25, 204, 36, 252, 13, 251, - /* 1950 */ 196, 248, 250, 249, 196, 6, 154, 155, 156, 157, - /* 1960 */ 158, 209, 194, 194, 163, 194, 306, 306, 303, 224, - /* 1970 */ 60, 215, 215, 209, 215, 215, 215, 224, 216, 216, - /* 1980 */ 4, 209, 72, 3, 22, 183, 164, 15, 23, 16, - /* 1990 */ 23, 140, 152, 131, 25, 24, 143, 20, 16, 145, - /* 2000 */ 1, 143, 131, 62, 131, 37, 54, 152, 54, 54, - /* 2010 */ 54, 101, 131, 117, 1, 34, 142, 107, 108, 5, - /* 2020 */ 22, 116, 162, 76, 41, 115, 69, 117, 118, 119, - /* 2030 */ 1, 2, 122, 25, 5, 69, 142, 116, 20, 10, - /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126, - /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30, - /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40, - /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68, - /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23, - /* 2090 */ 22, 98, 142, 183, 23, 23, 34, 22, 25, 89, - /* 2100 */ 71, 34, 117, 144, 34, 22, 76, 76, 79, 87, - /* 2110 */ 34, 82, 34, 44, 71, 94, 34, 23, 25, 24, - /* 2120 */ 34, 25, 79, 23, 23, 82, 23, 23, 99, 143, - /* 2130 */ 143, 22, 25, 25, 23, 22, 11, 22, 22, 25, - /* 2140 */ 23, 23, 99, 22, 22, 136, 142, 142, 142, 25, - /* 2150 */ 23, 15, 1, 1, 323, 323, 323, 323, 323, 323, - /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140, - /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323, - /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323, - /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323, - /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323, - /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2340 */ 323, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2390 */ 187, 187, 187, 187, -}; -#define YY_SHIFT_COUNT (582) -#define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2152) -static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642, - /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0, - /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702, - /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503, - /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736, - /* 50 */ 736, 40, 112, 320, 340, 445, 489, 593, 637, 741, - /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177, - /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, - /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554, - /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702, - /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198, - /* 150 */ 183, 99, 169, 549, 610, 151, 542, 610, 610, 1017, - /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1, - /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694, - /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610, - /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, - /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129, - /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207, - /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708, - /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610, - /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610, - /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839, - /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247, - /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610, - /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101, - /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487, - /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584, - /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530, - /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683, - /* 330 */ 1685, 1815, 1796, 1824, 1824, 1824, 1824, 1668, 1828, 1701, - /* 340 */ 1685, 1685, 1701, 1815, 1796, 1701, 1796, 1701, 1668, 1828, - /* 350 */ 1697, 1800, 1668, 1828, 1848, 1668, 1828, 1668, 1828, 1848, - /* 360 */ 1766, 1766, 1766, 1823, 1870, 1870, 1848, 1766, 1767, 1766, - /* 370 */ 1823, 1766, 1766, 1727, 1872, 1783, 1783, 1848, 1668, 1813, - /* 380 */ 1813, 1825, 1825, 1777, 1781, 1906, 1668, 1774, 1777, 1789, - /* 390 */ 1792, 1701, 1919, 1935, 1935, 1949, 1949, 1949, 2207, 2207, - /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, - /* 410 */ 2207, 2207, 2207, 69, 1032, 79, 357, 1377, 1206, 400, - /* 420 */ 1525, 835, 332, 1540, 1437, 1539, 1536, 1548, 1583, 1620, - /* 430 */ 1633, 1670, 1671, 1674, 1567, 1553, 1682, 1506, 1675, 1358, - /* 440 */ 1607, 1589, 1678, 1681, 1624, 1687, 1688, 1283, 1561, 1693, - /* 450 */ 1696, 1623, 1521, 1976, 1980, 1962, 1822, 1972, 1973, 1965, - /* 460 */ 1967, 1851, 1840, 1862, 1969, 1969, 1971, 1853, 1977, 1854, - /* 470 */ 1982, 1999, 1858, 1871, 1969, 1873, 1941, 1968, 1969, 1855, - /* 480 */ 1952, 1954, 1955, 1956, 1881, 1896, 1981, 1874, 2013, 2014, - /* 490 */ 1998, 1905, 1860, 1957, 2008, 1966, 1947, 1983, 1894, 1921, - /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047, - /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057, - /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1950, - /* 530 */ 2071, 2072, 1985, 2062, 2075, 1959, 2073, 2067, 2070, 2076, - /* 540 */ 2078, 2010, 2030, 2022, 2069, 2031, 2021, 2082, 2094, 2083, - /* 550 */ 2095, 2093, 2096, 2086, 1986, 1987, 2100, 2073, 2101, 2103, - /* 560 */ 2104, 2109, 2107, 2108, 2111, 2113, 2125, 2115, 2116, 2117, - /* 570 */ 2118, 2121, 2122, 2114, 2009, 2004, 2005, 2006, 2124, 2127, - /* 580 */ 2136, 2151, 2152, -}; -#define YY_REDUCE_COUNT (412) -#define YY_REDUCE_MIN (-277) -#define YY_REDUCE_MAX (1772) -static const short yy_reduce_ofst[] = { - /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137, - /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208, - /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814, - /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292, - /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238, - /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557, - /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142, - /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255, - /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328, - /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381, - /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449, - /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329, - /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501, - /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329, - /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790, - /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541, - /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102, - /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109, - /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258, - /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423, - /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098, - /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537, - /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164, - /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413, - /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575, - /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518, - /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538, - /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586, - /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579, - /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585, - /* 330 */ 1590, 1593, 1604, 1605, 1606, 1608, 1609, 1641, 1649, 1610, - /* 340 */ 1592, 1594, 1611, 1595, 1616, 1612, 1618, 1613, 1651, 1654, - /* 350 */ 1596, 1598, 1655, 1663, 1650, 1673, 1680, 1677, 1684, 1653, - /* 360 */ 1664, 1666, 1667, 1662, 1669, 1672, 1676, 1686, 1679, 1691, - /* 370 */ 1689, 1692, 1694, 1597, 1599, 1619, 1630, 1699, 1700, 1602, - /* 380 */ 1615, 1648, 1657, 1690, 1698, 1658, 1729, 1652, 1695, 1702, - /* 390 */ 1704, 1703, 1741, 1754, 1758, 1768, 1769, 1771, 1660, 1661, - /* 400 */ 1665, 1752, 1756, 1757, 1759, 1760, 1764, 1745, 1753, 1762, - /* 410 */ 1763, 1761, 1772, -}; -static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254, - /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397, - /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254, - /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254, - /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254, - /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420, - /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, - /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, - /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, - /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, - /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, - /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, - /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, - /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, - /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, - /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, - /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, - /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, - /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, - /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, - /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, - /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, - /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, - /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, - /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, - /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, - /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, - /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, - /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, - /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, - /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, - /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, - /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, - /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, - /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, - /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, - /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, - /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, - /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, - /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, - /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254, - /* 580 */ 1266, 1254, 1254, -}; -/********** End of lemon-generated parsing tables *****************************/ - -/* The next table maps tokens (terminal symbols) into fallback tokens. -** If a construct like the following: -** -** %fallback ID X Y Z. -** -** appears in the grammar, then ID becomes a fallback token for X, Y, -** and Z. Whenever one of the tokens X, Y, or Z is input to the parser -** but it does not parse, the type of the token is changed to ID and -** the parse is retried before an error is thrown. -** -** This feature can be used, for example, to cause some keywords in a language -** to revert to identifiers if they keyword does not apply in the context where -** it appears. -*/ -#ifdef YYFALLBACK -static const YYCODETYPE yyFallback[] = { - 0, /* $ => nothing */ - 0, /* SEMI => nothing */ - 60, /* EXPLAIN => ID */ - 60, /* QUERY => ID */ - 60, /* PLAN => ID */ - 60, /* BEGIN => ID */ - 0, /* TRANSACTION => nothing */ - 60, /* DEFERRED => ID */ - 60, /* IMMEDIATE => ID */ - 60, /* EXCLUSIVE => ID */ - 0, /* COMMIT => nothing */ - 60, /* END => ID */ - 60, /* ROLLBACK => ID */ - 60, /* SAVEPOINT => ID */ - 60, /* RELEASE => ID */ - 0, /* TO => nothing */ - 0, /* TABLE => nothing */ - 0, /* CREATE => nothing */ - 60, /* IF => ID */ - 0, /* NOT => nothing */ - 0, /* EXISTS => nothing */ - 60, /* TEMP => ID */ - 0, /* LP => nothing */ - 0, /* RP => nothing */ - 0, /* AS => nothing */ - 0, /* COMMA => nothing */ - 60, /* WITHOUT => ID */ - 60, /* ABORT => ID */ - 60, /* ACTION => ID */ - 60, /* AFTER => ID */ - 60, /* ANALYZE => ID */ - 60, /* ASC => ID */ - 60, /* ATTACH => ID */ - 60, /* BEFORE => ID */ - 60, /* BY => ID */ - 60, /* CASCADE => ID */ - 60, /* CAST => ID */ - 60, /* CONFLICT => ID */ - 60, /* DATABASE => ID */ - 60, /* DESC => ID */ - 60, /* DETACH => ID */ - 60, /* EACH => ID */ - 60, /* FAIL => ID */ - 0, /* OR => nothing */ - 0, /* AND => nothing */ - 0, /* IS => nothing */ - 0, /* ISNOT => nothing */ - 60, /* MATCH => ID */ - 60, /* LIKE_KW => ID */ - 0, /* BETWEEN => nothing */ - 0, /* IN => nothing */ - 0, /* ISNULL => nothing */ - 0, /* NOTNULL => nothing */ - 0, /* NE => nothing */ - 0, /* EQ => nothing */ - 0, /* GT => nothing */ - 0, /* LE => nothing */ - 0, /* LT => nothing */ - 0, /* GE => nothing */ - 0, /* ESCAPE => nothing */ - 0, /* ID => nothing */ - 60, /* COLUMNKW => ID */ - 60, /* DO => ID */ - 60, /* FOR => ID */ - 60, /* IGNORE => ID */ - 60, /* INITIALLY => ID */ - 60, /* INSTEAD => ID */ - 60, /* NO => ID */ - 60, /* KEY => ID */ - 60, /* OF => ID */ - 60, /* OFFSET => ID */ - 60, /* PRAGMA => ID */ - 60, /* RAISE => ID */ - 60, /* RECURSIVE => ID */ - 60, /* REPLACE => ID */ - 60, /* RESTRICT => ID */ - 60, /* ROW => ID */ - 60, /* ROWS => ID */ - 60, /* TRIGGER => ID */ - 60, /* VACUUM => ID */ - 60, /* VIEW => ID */ - 60, /* VIRTUAL => ID */ - 60, /* WITH => ID */ - 60, /* NULLS => ID */ - 60, /* FIRST => ID */ - 60, /* LAST => ID */ - 60, /* CURRENT => ID */ - 60, /* FOLLOWING => ID */ - 60, /* PARTITION => ID */ - 60, /* PRECEDING => ID */ - 60, /* RANGE => ID */ - 60, /* UNBOUNDED => ID */ - 60, /* EXCLUDE => ID */ - 60, /* GROUPS => ID */ - 60, /* OTHERS => ID */ - 60, /* TIES => ID */ - 60, /* GENERATED => ID */ - 60, /* ALWAYS => ID */ - 60, /* MATERIALIZED => ID */ - 60, /* REINDEX => ID */ - 60, /* RENAME => ID */ - 60, /* CTIME_KW => ID */ - 0, /* ANY => nothing */ - 0, /* BITAND => nothing */ - 0, /* BITOR => nothing */ - 0, /* LSHIFT => nothing */ - 0, /* RSHIFT => nothing */ - 0, /* PLUS => nothing */ - 0, /* MINUS => nothing */ - 0, /* STAR => nothing */ - 0, /* SLASH => nothing */ - 0, /* REM => nothing */ - 0, /* CONCAT => nothing */ - 0, /* PTR => nothing */ - 0, /* COLLATE => nothing */ - 0, /* BITNOT => nothing */ - 0, /* ON => nothing */ - 0, /* INDEXED => nothing */ - 0, /* STRING => nothing */ - 0, /* JOIN_KW => nothing */ - 0, /* CONSTRAINT => nothing */ - 0, /* DEFAULT => nothing */ - 0, /* NULL => nothing */ - 0, /* PRIMARY => nothing */ - 0, /* UNIQUE => nothing */ - 0, /* CHECK => nothing */ - 0, /* REFERENCES => nothing */ - 0, /* AUTOINCR => nothing */ - 0, /* INSERT => nothing */ - 0, /* DELETE => nothing */ - 0, /* UPDATE => nothing */ - 0, /* SET => nothing */ - 0, /* DEFERRABLE => nothing */ - 0, /* FOREIGN => nothing */ - 0, /* DROP => nothing */ - 0, /* UNION => nothing */ - 0, /* ALL => nothing */ - 0, /* EXCEPT => nothing */ - 0, /* INTERSECT => nothing */ - 0, /* SELECT => nothing */ - 0, /* VALUES => nothing */ - 0, /* DISTINCT => nothing */ - 0, /* DOT => nothing */ - 0, /* FROM => nothing */ - 0, /* JOIN => nothing */ - 0, /* USING => nothing */ - 0, /* ORDER => nothing */ - 0, /* GROUP => nothing */ - 0, /* HAVING => nothing */ - 0, /* LIMIT => nothing */ - 0, /* WHERE => nothing */ - 0, /* RETURNING => nothing */ - 0, /* INTO => nothing */ - 0, /* NOTHING => nothing */ - 0, /* FLOAT => nothing */ - 0, /* BLOB => nothing */ - 0, /* INTEGER => nothing */ - 0, /* VARIABLE => nothing */ - 0, /* CASE => nothing */ - 0, /* WHEN => nothing */ - 0, /* THEN => nothing */ - 0, /* ELSE => nothing */ - 0, /* INDEX => nothing */ - 0, /* ALTER => nothing */ - 0, /* ADD => nothing */ - 0, /* WINDOW => nothing */ - 0, /* OVER => nothing */ - 0, /* FILTER => nothing */ - 0, /* COLUMN => nothing */ - 0, /* AGG_FUNCTION => nothing */ - 0, /* AGG_COLUMN => nothing */ - 0, /* TRUEFALSE => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* UPLUS => nothing */ - 0, /* UMINUS => nothing */ - 0, /* TRUTH => nothing */ - 0, /* REGISTER => nothing */ - 0, /* VECTOR => nothing */ - 0, /* SELECT_COLUMN => nothing */ - 0, /* IF_NULL_ROW => nothing */ - 0, /* ASTERISK => nothing */ - 0, /* SPAN => nothing */ - 0, /* ERROR => nothing */ - 0, /* QNUMBER => nothing */ - 0, /* SPACE => nothing */ - 0, /* COMMENT => nothing */ - 0, /* ILLEGAL => nothing */ -}; -#endif /* YYFALLBACK */ - -/* The following structure represents a single element of the -** parser's stack. Information stored includes: -** -** + The state number for the parser at this level of the stack. -** -** + The value of the token stored at this level of the stack. -** (In other words, the "major" token.) -** -** + The semantic value stored at this level of the stack. This is -** the information used by the action routines in the grammar. -** It is sometimes called the "minor" token. -** -** After the "shift" half of a SHIFTREDUCE action, the stateno field -** actually contains the reduce action for the second half of the -** SHIFTREDUCE. -*/ -struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ - YYCODETYPE major; /* The major token value. This is the code - ** number for the token at this stack level */ - YYMINORTYPE minor; /* The user-supplied minor token value. This - ** is the value of the token */ -}; -typedef struct yyStackEntry yyStackEntry; - -/* The state of the parser is completely contained in an instance of -** the following structure */ -struct yyParser { - yyStackEntry *yytos; /* Pointer to top element of the stack */ -#ifdef YYTRACKMAXSTACKDEPTH - int yyhwm; /* High-water mark of the stack */ -#endif -#ifndef YYNOERRORRECOVERY - int yyerrcnt; /* Shifts left before out of the error */ -#endif - sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ - sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ - yyStackEntry *yystackEnd; /* Last entry in the stack */ - yyStackEntry *yystack; /* The parser stack */ - yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */ -}; -typedef struct yyParser yyParser; - -/* #include */ -#ifndef NDEBUG -/* #include */ -static FILE *yyTraceFILE = 0; -static char *yyTracePrompt = 0; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Turn parser tracing on by giving a stream to which to write the trace -** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL -** -** Inputs: -**
      -**
    • A FILE* to which trace output should be written. -** If NULL, then tracing is turned off. -**
    • A prefix string written at the beginning of every -** line of trace output. If NULL, then tracing is -** turned off. -**
    -** -** Outputs: -** None. -*/ -SQLITE_PRIVATE void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ - yyTraceFILE = TraceFILE; - yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; -} -#endif /* NDEBUG */ - -#if defined(YYCOVERAGE) || !defined(NDEBUG) -/* For tracing shifts, the names of all terminals and nonterminals -** are required. The following table supplies these names */ -static const char *const yyTokenName[] = { - /* 0 */ "$", - /* 1 */ "SEMI", - /* 2 */ "EXPLAIN", - /* 3 */ "QUERY", - /* 4 */ "PLAN", - /* 5 */ "BEGIN", - /* 6 */ "TRANSACTION", - /* 7 */ "DEFERRED", - /* 8 */ "IMMEDIATE", - /* 9 */ "EXCLUSIVE", - /* 10 */ "COMMIT", - /* 11 */ "END", - /* 12 */ "ROLLBACK", - /* 13 */ "SAVEPOINT", - /* 14 */ "RELEASE", - /* 15 */ "TO", - /* 16 */ "TABLE", - /* 17 */ "CREATE", - /* 18 */ "IF", - /* 19 */ "NOT", - /* 20 */ "EXISTS", - /* 21 */ "TEMP", - /* 22 */ "LP", - /* 23 */ "RP", - /* 24 */ "AS", - /* 25 */ "COMMA", - /* 26 */ "WITHOUT", - /* 27 */ "ABORT", - /* 28 */ "ACTION", - /* 29 */ "AFTER", - /* 30 */ "ANALYZE", - /* 31 */ "ASC", - /* 32 */ "ATTACH", - /* 33 */ "BEFORE", - /* 34 */ "BY", - /* 35 */ "CASCADE", - /* 36 */ "CAST", - /* 37 */ "CONFLICT", - /* 38 */ "DATABASE", - /* 39 */ "DESC", - /* 40 */ "DETACH", - /* 41 */ "EACH", - /* 42 */ "FAIL", - /* 43 */ "OR", - /* 44 */ "AND", - /* 45 */ "IS", - /* 46 */ "ISNOT", - /* 47 */ "MATCH", - /* 48 */ "LIKE_KW", - /* 49 */ "BETWEEN", - /* 50 */ "IN", - /* 51 */ "ISNULL", - /* 52 */ "NOTNULL", - /* 53 */ "NE", - /* 54 */ "EQ", - /* 55 */ "GT", - /* 56 */ "LE", - /* 57 */ "LT", - /* 58 */ "GE", - /* 59 */ "ESCAPE", - /* 60 */ "ID", - /* 61 */ "COLUMNKW", - /* 62 */ "DO", - /* 63 */ "FOR", - /* 64 */ "IGNORE", - /* 65 */ "INITIALLY", - /* 66 */ "INSTEAD", - /* 67 */ "NO", - /* 68 */ "KEY", - /* 69 */ "OF", - /* 70 */ "OFFSET", - /* 71 */ "PRAGMA", - /* 72 */ "RAISE", - /* 73 */ "RECURSIVE", - /* 74 */ "REPLACE", - /* 75 */ "RESTRICT", - /* 76 */ "ROW", - /* 77 */ "ROWS", - /* 78 */ "TRIGGER", - /* 79 */ "VACUUM", - /* 80 */ "VIEW", - /* 81 */ "VIRTUAL", - /* 82 */ "WITH", - /* 83 */ "NULLS", - /* 84 */ "FIRST", - /* 85 */ "LAST", - /* 86 */ "CURRENT", - /* 87 */ "FOLLOWING", - /* 88 */ "PARTITION", - /* 89 */ "PRECEDING", - /* 90 */ "RANGE", - /* 91 */ "UNBOUNDED", - /* 92 */ "EXCLUDE", - /* 93 */ "GROUPS", - /* 94 */ "OTHERS", - /* 95 */ "TIES", - /* 96 */ "GENERATED", - /* 97 */ "ALWAYS", - /* 98 */ "MATERIALIZED", - /* 99 */ "REINDEX", - /* 100 */ "RENAME", - /* 101 */ "CTIME_KW", - /* 102 */ "ANY", - /* 103 */ "BITAND", - /* 104 */ "BITOR", - /* 105 */ "LSHIFT", - /* 106 */ "RSHIFT", - /* 107 */ "PLUS", - /* 108 */ "MINUS", - /* 109 */ "STAR", - /* 110 */ "SLASH", - /* 111 */ "REM", - /* 112 */ "CONCAT", - /* 113 */ "PTR", - /* 114 */ "COLLATE", - /* 115 */ "BITNOT", - /* 116 */ "ON", - /* 117 */ "INDEXED", - /* 118 */ "STRING", - /* 119 */ "JOIN_KW", - /* 120 */ "CONSTRAINT", - /* 121 */ "DEFAULT", - /* 122 */ "NULL", - /* 123 */ "PRIMARY", - /* 124 */ "UNIQUE", - /* 125 */ "CHECK", - /* 126 */ "REFERENCES", - /* 127 */ "AUTOINCR", - /* 128 */ "INSERT", - /* 129 */ "DELETE", - /* 130 */ "UPDATE", - /* 131 */ "SET", - /* 132 */ "DEFERRABLE", - /* 133 */ "FOREIGN", - /* 134 */ "DROP", - /* 135 */ "UNION", - /* 136 */ "ALL", - /* 137 */ "EXCEPT", - /* 138 */ "INTERSECT", - /* 139 */ "SELECT", - /* 140 */ "VALUES", - /* 141 */ "DISTINCT", - /* 142 */ "DOT", - /* 143 */ "FROM", - /* 144 */ "JOIN", - /* 145 */ "USING", - /* 146 */ "ORDER", - /* 147 */ "GROUP", - /* 148 */ "HAVING", - /* 149 */ "LIMIT", - /* 150 */ "WHERE", - /* 151 */ "RETURNING", - /* 152 */ "INTO", - /* 153 */ "NOTHING", - /* 154 */ "FLOAT", - /* 155 */ "BLOB", - /* 156 */ "INTEGER", - /* 157 */ "VARIABLE", - /* 158 */ "CASE", - /* 159 */ "WHEN", - /* 160 */ "THEN", - /* 161 */ "ELSE", - /* 162 */ "INDEX", - /* 163 */ "ALTER", - /* 164 */ "ADD", - /* 165 */ "WINDOW", - /* 166 */ "OVER", - /* 167 */ "FILTER", - /* 168 */ "COLUMN", - /* 169 */ "AGG_FUNCTION", - /* 170 */ "AGG_COLUMN", - /* 171 */ "TRUEFALSE", - /* 172 */ "FUNCTION", - /* 173 */ "UPLUS", - /* 174 */ "UMINUS", - /* 175 */ "TRUTH", - /* 176 */ "REGISTER", - /* 177 */ "VECTOR", - /* 178 */ "SELECT_COLUMN", - /* 179 */ "IF_NULL_ROW", - /* 180 */ "ASTERISK", - /* 181 */ "SPAN", - /* 182 */ "ERROR", - /* 183 */ "QNUMBER", - /* 184 */ "SPACE", - /* 185 */ "COMMENT", - /* 186 */ "ILLEGAL", - /* 187 */ "input", - /* 188 */ "cmdlist", - /* 189 */ "ecmd", - /* 190 */ "cmdx", - /* 191 */ "explain", - /* 192 */ "cmd", - /* 193 */ "transtype", - /* 194 */ "trans_opt", - /* 195 */ "nm", - /* 196 */ "savepoint_opt", - /* 197 */ "create_table", - /* 198 */ "create_table_args", - /* 199 */ "createkw", - /* 200 */ "temp", - /* 201 */ "ifnotexists", - /* 202 */ "dbnm", - /* 203 */ "columnlist", - /* 204 */ "conslist_opt", - /* 205 */ "table_option_set", - /* 206 */ "select", - /* 207 */ "table_option", - /* 208 */ "columnname", - /* 209 */ "carglist", - /* 210 */ "typetoken", - /* 211 */ "typename", - /* 212 */ "signed", - /* 213 */ "plus_num", - /* 214 */ "minus_num", - /* 215 */ "scanpt", - /* 216 */ "scantok", - /* 217 */ "ccons", - /* 218 */ "term", - /* 219 */ "expr", - /* 220 */ "onconf", - /* 221 */ "sortorder", - /* 222 */ "autoinc", - /* 223 */ "eidlist_opt", - /* 224 */ "refargs", - /* 225 */ "defer_subclause", - /* 226 */ "generated", - /* 227 */ "refarg", - /* 228 */ "refact", - /* 229 */ "init_deferred_pred_opt", - /* 230 */ "conslist", - /* 231 */ "tconscomma", - /* 232 */ "tcons", - /* 233 */ "sortlist", - /* 234 */ "eidlist", - /* 235 */ "defer_subclause_opt", - /* 236 */ "orconf", - /* 237 */ "resolvetype", - /* 238 */ "raisetype", - /* 239 */ "ifexists", - /* 240 */ "fullname", - /* 241 */ "selectnowith", - /* 242 */ "oneselect", - /* 243 */ "wqlist", - /* 244 */ "multiselect_op", - /* 245 */ "distinct", - /* 246 */ "selcollist", - /* 247 */ "from", - /* 248 */ "where_opt", - /* 249 */ "groupby_opt", - /* 250 */ "having_opt", - /* 251 */ "orderby_opt", - /* 252 */ "limit_opt", - /* 253 */ "window_clause", - /* 254 */ "values", - /* 255 */ "nexprlist", - /* 256 */ "mvalues", - /* 257 */ "sclp", - /* 258 */ "as", - /* 259 */ "seltablist", - /* 260 */ "stl_prefix", - /* 261 */ "joinop", - /* 262 */ "on_using", - /* 263 */ "indexed_by", - /* 264 */ "exprlist", - /* 265 */ "xfullname", - /* 266 */ "idlist", - /* 267 */ "indexed_opt", - /* 268 */ "nulls", - /* 269 */ "with", - /* 270 */ "where_opt_ret", - /* 271 */ "setlist", - /* 272 */ "insert_cmd", - /* 273 */ "idlist_opt", - /* 274 */ "upsert", - /* 275 */ "returning", - /* 276 */ "filter_over", - /* 277 */ "likeop", - /* 278 */ "between_op", - /* 279 */ "in_op", - /* 280 */ "paren_exprlist", - /* 281 */ "case_operand", - /* 282 */ "case_exprlist", - /* 283 */ "case_else", - /* 284 */ "uniqueflag", - /* 285 */ "collate", - /* 286 */ "vinto", - /* 287 */ "nmnum", - /* 288 */ "trigger_decl", - /* 289 */ "trigger_cmd_list", - /* 290 */ "trigger_time", - /* 291 */ "trigger_event", - /* 292 */ "foreach_clause", - /* 293 */ "when_clause", - /* 294 */ "trigger_cmd", - /* 295 */ "trnm", - /* 296 */ "tridxby", - /* 297 */ "database_kw_opt", - /* 298 */ "key_opt", - /* 299 */ "add_column_fullname", - /* 300 */ "kwcolumn_opt", - /* 301 */ "create_vtab", - /* 302 */ "vtabarglist", - /* 303 */ "vtabarg", - /* 304 */ "vtabargtoken", - /* 305 */ "lp", - /* 306 */ "anylist", - /* 307 */ "wqitem", - /* 308 */ "wqas", - /* 309 */ "withnm", - /* 310 */ "windowdefn_list", - /* 311 */ "windowdefn", - /* 312 */ "window", - /* 313 */ "frame_opt", - /* 314 */ "part_opt", - /* 315 */ "filter_clause", - /* 316 */ "over_clause", - /* 317 */ "range_or_rows", - /* 318 */ "frame_bound", - /* 319 */ "frame_bound_s", - /* 320 */ "frame_bound_e", - /* 321 */ "frame_exclude_opt", - /* 322 */ "frame_exclude", -}; -#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ - -#ifndef NDEBUG -/* For tracing reduce actions, the names of all rules are required. -*/ -static const char *const yyRuleName[] = { - /* 0 */ "explain ::= EXPLAIN", - /* 1 */ "explain ::= EXPLAIN QUERY PLAN", - /* 2 */ "cmdx ::= cmd", - /* 3 */ "cmd ::= BEGIN transtype trans_opt", - /* 4 */ "transtype ::=", - /* 5 */ "transtype ::= DEFERRED", - /* 6 */ "transtype ::= IMMEDIATE", - /* 7 */ "transtype ::= EXCLUSIVE", - /* 8 */ "cmd ::= COMMIT|END trans_opt", - /* 9 */ "cmd ::= ROLLBACK trans_opt", - /* 10 */ "cmd ::= SAVEPOINT nm", - /* 11 */ "cmd ::= RELEASE savepoint_opt nm", - /* 12 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", - /* 13 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", - /* 14 */ "createkw ::= CREATE", - /* 15 */ "ifnotexists ::=", - /* 16 */ "ifnotexists ::= IF NOT EXISTS", - /* 17 */ "temp ::= TEMP", - /* 18 */ "temp ::=", - /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_option_set", - /* 20 */ "create_table_args ::= AS select", - /* 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 */ "oneselect ::= mvalues", - /* 96 */ "mvalues ::= values COMMA LP nexprlist RP", - /* 97 */ "mvalues ::= mvalues COMMA LP nexprlist RP", - /* 98 */ "distinct ::= DISTINCT", - /* 99 */ "distinct ::= ALL", - /* 100 */ "distinct ::=", - /* 101 */ "sclp ::=", - /* 102 */ "selcollist ::= sclp scanpt expr scanpt as", - /* 103 */ "selcollist ::= sclp scanpt STAR", - /* 104 */ "selcollist ::= sclp scanpt nm DOT STAR", - /* 105 */ "as ::= AS nm", - /* 106 */ "as ::=", - /* 107 */ "from ::=", - /* 108 */ "from ::= FROM seltablist", - /* 109 */ "stl_prefix ::= seltablist joinop", - /* 110 */ "stl_prefix ::=", - /* 111 */ "seltablist ::= stl_prefix nm dbnm as on_using", - /* 112 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", - /* 113 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", - /* 114 */ "seltablist ::= stl_prefix LP select RP as on_using", - /* 115 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", - /* 116 */ "dbnm ::=", - /* 117 */ "dbnm ::= DOT nm", - /* 118 */ "fullname ::= nm", - /* 119 */ "fullname ::= nm DOT nm", - /* 120 */ "xfullname ::= nm", - /* 121 */ "xfullname ::= nm DOT nm", - /* 122 */ "xfullname ::= nm DOT nm AS nm", - /* 123 */ "xfullname ::= nm AS nm", - /* 124 */ "joinop ::= COMMA|JOIN", - /* 125 */ "joinop ::= JOIN_KW JOIN", - /* 126 */ "joinop ::= JOIN_KW nm JOIN", - /* 127 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 128 */ "on_using ::= ON expr", - /* 129 */ "on_using ::= USING LP idlist RP", - /* 130 */ "on_using ::=", - /* 131 */ "indexed_opt ::=", - /* 132 */ "indexed_by ::= INDEXED BY nm", - /* 133 */ "indexed_by ::= NOT INDEXED", - /* 134 */ "orderby_opt ::=", - /* 135 */ "orderby_opt ::= ORDER BY sortlist", - /* 136 */ "sortlist ::= sortlist COMMA expr sortorder nulls", - /* 137 */ "sortlist ::= expr sortorder nulls", - /* 138 */ "sortorder ::= ASC", - /* 139 */ "sortorder ::= DESC", - /* 140 */ "sortorder ::=", - /* 141 */ "nulls ::= NULLS FIRST", - /* 142 */ "nulls ::= NULLS LAST", - /* 143 */ "nulls ::=", - /* 144 */ "groupby_opt ::=", - /* 145 */ "groupby_opt ::= GROUP BY nexprlist", - /* 146 */ "having_opt ::=", - /* 147 */ "having_opt ::= HAVING expr", - /* 148 */ "limit_opt ::=", - /* 149 */ "limit_opt ::= LIMIT expr", - /* 150 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 151 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 152 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", - /* 153 */ "where_opt ::=", - /* 154 */ "where_opt ::= WHERE expr", - /* 155 */ "where_opt_ret ::=", - /* 156 */ "where_opt_ret ::= WHERE expr", - /* 157 */ "where_opt_ret ::= RETURNING selcollist", - /* 158 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", - /* 159 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", - /* 160 */ "setlist ::= setlist COMMA nm EQ expr", - /* 161 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 162 */ "setlist ::= nm EQ expr", - /* 163 */ "setlist ::= LP idlist RP EQ expr", - /* 164 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", - /* 165 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", - /* 166 */ "upsert ::=", - /* 167 */ "upsert ::= RETURNING selcollist", - /* 168 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", - /* 169 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", - /* 170 */ "upsert ::= ON CONFLICT DO NOTHING returning", - /* 171 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", - /* 172 */ "returning ::= RETURNING selcollist", - /* 173 */ "insert_cmd ::= INSERT orconf", - /* 174 */ "insert_cmd ::= REPLACE", - /* 175 */ "idlist_opt ::=", - /* 176 */ "idlist_opt ::= LP idlist RP", - /* 177 */ "idlist ::= idlist COMMA nm", - /* 178 */ "idlist ::= nm", - /* 179 */ "expr ::= LP expr RP", - /* 180 */ "expr ::= ID|INDEXED|JOIN_KW", - /* 181 */ "expr ::= nm DOT nm", - /* 182 */ "expr ::= nm DOT nm DOT nm", - /* 183 */ "term ::= NULL|FLOAT|BLOB", - /* 184 */ "term ::= STRING", - /* 185 */ "term ::= INTEGER", - /* 186 */ "expr ::= VARIABLE", - /* 187 */ "expr ::= expr COLLATE ID|STRING", - /* 188 */ "expr ::= CAST LP expr AS typetoken RP", - /* 189 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP", - /* 190 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP", - /* 191 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP", - /* 192 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over", - /* 193 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over", - /* 194 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over", - /* 195 */ "term ::= CTIME_KW", - /* 196 */ "expr ::= LP nexprlist COMMA expr RP", - /* 197 */ "expr ::= expr AND expr", - /* 198 */ "expr ::= expr OR expr", - /* 199 */ "expr ::= expr LT|GT|GE|LE expr", - /* 200 */ "expr ::= expr EQ|NE expr", - /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 202 */ "expr ::= expr PLUS|MINUS expr", - /* 203 */ "expr ::= expr STAR|SLASH|REM expr", - /* 204 */ "expr ::= expr CONCAT expr", - /* 205 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 206 */ "expr ::= expr likeop expr", - /* 207 */ "expr ::= expr likeop expr ESCAPE expr", - /* 208 */ "expr ::= expr ISNULL|NOTNULL", - /* 209 */ "expr ::= expr NOT NULL", - /* 210 */ "expr ::= expr IS expr", - /* 211 */ "expr ::= expr IS NOT expr", - /* 212 */ "expr ::= expr IS NOT DISTINCT FROM expr", - /* 213 */ "expr ::= expr IS DISTINCT FROM expr", - /* 214 */ "expr ::= NOT expr", - /* 215 */ "expr ::= BITNOT expr", - /* 216 */ "expr ::= PLUS|MINUS expr", - /* 217 */ "expr ::= expr PTR expr", - /* 218 */ "between_op ::= BETWEEN", - /* 219 */ "between_op ::= NOT BETWEEN", - /* 220 */ "expr ::= expr between_op expr AND expr", - /* 221 */ "in_op ::= IN", - /* 222 */ "in_op ::= NOT IN", - /* 223 */ "expr ::= expr in_op LP exprlist RP", - /* 224 */ "expr ::= LP select RP", - /* 225 */ "expr ::= expr in_op LP select RP", - /* 226 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 227 */ "expr ::= EXISTS LP select RP", - /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 230 */ "case_exprlist ::= WHEN expr THEN expr", - /* 231 */ "case_else ::= ELSE expr", - /* 232 */ "case_else ::=", - /* 233 */ "case_operand ::=", - /* 234 */ "exprlist ::=", - /* 235 */ "nexprlist ::= nexprlist COMMA expr", - /* 236 */ "nexprlist ::= expr", - /* 237 */ "paren_exprlist ::=", - /* 238 */ "paren_exprlist ::= LP exprlist RP", - /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 240 */ "uniqueflag ::= UNIQUE", - /* 241 */ "uniqueflag ::=", - /* 242 */ "eidlist_opt ::=", - /* 243 */ "eidlist_opt ::= LP eidlist RP", - /* 244 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 245 */ "eidlist ::= nm collate sortorder", - /* 246 */ "collate ::=", - /* 247 */ "collate ::= COLLATE ID|STRING", - /* 248 */ "cmd ::= DROP INDEX ifexists fullname", - /* 249 */ "cmd ::= VACUUM vinto", - /* 250 */ "cmd ::= VACUUM nm vinto", - /* 251 */ "vinto ::= INTO expr", - /* 252 */ "vinto ::=", - /* 253 */ "cmd ::= PRAGMA nm dbnm", - /* 254 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 255 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 256 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 257 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 258 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 259 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 260 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 262 */ "trigger_time ::= BEFORE|AFTER", - /* 263 */ "trigger_time ::= INSTEAD OF", - /* 264 */ "trigger_time ::=", - /* 265 */ "trigger_event ::= DELETE|INSERT", - /* 266 */ "trigger_event ::= UPDATE", - /* 267 */ "trigger_event ::= UPDATE OF idlist", - /* 268 */ "when_clause ::=", - /* 269 */ "when_clause ::= WHEN expr", - /* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 272 */ "trnm ::= nm DOT nm", - /* 273 */ "tridxby ::= INDEXED BY nm", - /* 274 */ "tridxby ::= NOT INDEXED", - /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", - /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", - /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 278 */ "trigger_cmd ::= scanpt select scanpt", - /* 279 */ "expr ::= RAISE LP IGNORE RP", - /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP", - /* 281 */ "raisetype ::= ROLLBACK", - /* 282 */ "raisetype ::= ABORT", - /* 283 */ "raisetype ::= FAIL", - /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 286 */ "cmd ::= DETACH database_kw_opt expr", - /* 287 */ "key_opt ::=", - /* 288 */ "key_opt ::= KEY expr", - /* 289 */ "cmd ::= REINDEX", - /* 290 */ "cmd ::= REINDEX nm dbnm", - /* 291 */ "cmd ::= ANALYZE", - /* 292 */ "cmd ::= ANALYZE nm dbnm", - /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 296 */ "add_column_fullname ::= fullname", - /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 298 */ "cmd ::= create_vtab", - /* 299 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 301 */ "vtabarg ::=", - /* 302 */ "vtabargtoken ::= ANY", - /* 303 */ "vtabargtoken ::= lp anylist RP", - /* 304 */ "lp ::= LP", - /* 305 */ "with ::= WITH wqlist", - /* 306 */ "with ::= WITH RECURSIVE wqlist", - /* 307 */ "wqas ::= AS", - /* 308 */ "wqas ::= AS MATERIALIZED", - /* 309 */ "wqas ::= AS NOT MATERIALIZED", - /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", - /* 311 */ "withnm ::= nm", - /* 312 */ "wqlist ::= wqitem", - /* 313 */ "wqlist ::= wqlist COMMA wqitem", - /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 315 */ "windowdefn ::= nm AS LP window RP", - /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 318 */ "window ::= ORDER BY sortlist frame_opt", - /* 319 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 320 */ "window ::= nm frame_opt", - /* 321 */ "frame_opt ::=", - /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 325 */ "frame_bound_s ::= frame_bound", - /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 327 */ "frame_bound_e ::= frame_bound", - /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 330 */ "frame_bound ::= CURRENT ROW", - /* 331 */ "frame_exclude_opt ::=", - /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 333 */ "frame_exclude ::= NO OTHERS", - /* 334 */ "frame_exclude ::= CURRENT ROW", - /* 335 */ "frame_exclude ::= GROUP|TIES", - /* 336 */ "window_clause ::= WINDOW windowdefn_list", - /* 337 */ "filter_over ::= filter_clause over_clause", - /* 338 */ "filter_over ::= over_clause", - /* 339 */ "filter_over ::= filter_clause", - /* 340 */ "over_clause ::= OVER LP window RP", - /* 341 */ "over_clause ::= OVER nm", - /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 343 */ "term ::= QNUMBER", - /* 344 */ "input ::= cmdlist", - /* 345 */ "cmdlist ::= cmdlist ecmd", - /* 346 */ "cmdlist ::= ecmd", - /* 347 */ "ecmd ::= SEMI", - /* 348 */ "ecmd ::= cmdx SEMI", - /* 349 */ "ecmd ::= explain cmdx SEMI", - /* 350 */ "trans_opt ::=", - /* 351 */ "trans_opt ::= TRANSACTION", - /* 352 */ "trans_opt ::= TRANSACTION nm", - /* 353 */ "savepoint_opt ::= SAVEPOINT", - /* 354 */ "savepoint_opt ::=", - /* 355 */ "cmd ::= create_table create_table_args", - /* 356 */ "table_option_set ::= table_option", - /* 357 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 358 */ "columnlist ::= columnname carglist", - /* 359 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 360 */ "nm ::= STRING", - /* 361 */ "typetoken ::= typename", - /* 362 */ "typename ::= ID|STRING", - /* 363 */ "signed ::= plus_num", - /* 364 */ "signed ::= minus_num", - /* 365 */ "carglist ::= carglist ccons", - /* 366 */ "carglist ::=", - /* 367 */ "ccons ::= NULL onconf", - /* 368 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 369 */ "ccons ::= AS generated", - /* 370 */ "conslist_opt ::= COMMA conslist", - /* 371 */ "conslist ::= conslist tconscomma tcons", - /* 372 */ "conslist ::= tcons", - /* 373 */ "tconscomma ::=", - /* 374 */ "defer_subclause_opt ::= defer_subclause", - /* 375 */ "resolvetype ::= raisetype", - /* 376 */ "selectnowith ::= oneselect", - /* 377 */ "oneselect ::= values", - /* 378 */ "sclp ::= selcollist COMMA", - /* 379 */ "as ::= ID|STRING", - /* 380 */ "indexed_opt ::= indexed_by", - /* 381 */ "returning ::=", - /* 382 */ "expr ::= term", - /* 383 */ "likeop ::= LIKE_KW|MATCH", - /* 384 */ "case_operand ::= expr", - /* 385 */ "exprlist ::= nexprlist", - /* 386 */ "nmnum ::= plus_num", - /* 387 */ "nmnum ::= nm", - /* 388 */ "nmnum ::= ON", - /* 389 */ "nmnum ::= DELETE", - /* 390 */ "nmnum ::= DEFAULT", - /* 391 */ "plus_num ::= INTEGER|FLOAT", - /* 392 */ "foreach_clause ::=", - /* 393 */ "foreach_clause ::= FOR EACH ROW", - /* 394 */ "trnm ::= nm", - /* 395 */ "tridxby ::=", - /* 396 */ "database_kw_opt ::= DATABASE", - /* 397 */ "database_kw_opt ::=", - /* 398 */ "kwcolumn_opt ::=", - /* 399 */ "kwcolumn_opt ::= COLUMNKW", - /* 400 */ "vtabarglist ::= vtabarg", - /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 402 */ "vtabarg ::= vtabarg vtabargtoken", - /* 403 */ "anylist ::=", - /* 404 */ "anylist ::= anylist LP anylist RP", - /* 405 */ "anylist ::= anylist ANY", - /* 406 */ "with ::=", - /* 407 */ "windowdefn_list ::= windowdefn", - /* 408 */ "window ::= frame_opt", -}; -#endif /* NDEBUG */ - - -#if YYGROWABLESTACK -/* -** Try to increase the size of the parser stack. Return the number -** of errors. Return 0 on success. -*/ -static int yyGrowStack(yyParser *p){ - int oldSize = 1 + (int)(p->yystackEnd - p->yystack); - int newSize; - int idx; - yyStackEntry *pNew; - - newSize = oldSize*2 + 100; - idx = (int)(p->yytos - p->yystack); - if( p->yystack==p->yystk0 ){ - pNew = YYREALLOC(0, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; - memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0])); - }else{ - pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; - } - p->yystack = pNew; - p->yytos = &p->yystack[idx]; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", - yyTracePrompt, oldSize, newSize); - } -#endif - p->yystackEnd = &p->yystack[newSize-1]; - return 0; -} -#endif /* YYGROWABLESTACK */ - -#if !YYGROWABLESTACK -/* For builds that do no have a growable stack, yyGrowStack always -** returns an error. -*/ -# define yyGrowStack(X) 1 -#endif - -/* Datatype of the argument to the memory allocated passed as the -** second argument to sqlite3ParserAlloc() below. This can be changed by -** putting an appropriate #define in the %include section of the input -** grammar. -*/ -#ifndef YYMALLOCARGTYPE -# define YYMALLOCARGTYPE size_t -#endif - -/* Initialize a new parser that has already been allocated. -*/ -SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL){ - yyParser *yypParser = (yyParser*)yypRawParser; - sqlite3ParserCTX_STORE -#ifdef YYTRACKMAXSTACKDEPTH - yypParser->yyhwm = 0; -#endif - yypParser->yystack = yypParser->yystk0; - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yypParser->yytos = yypParser->yystack; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; -} - -#ifndef sqlite3Parser_ENGINEALWAYSONSTACK -/* -** This function allocates a new parser. -** The only argument is a pointer to a function which works like -** malloc. -** -** Inputs: -** A pointer to the function used to allocate memory. -** -** Outputs: -** A pointer to a parser. This pointer is used in subsequent calls -** to sqlite3Parser and sqlite3ParserFree. -*/ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) sqlite3ParserCTX_PDECL){ - yyParser *yypParser; - yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( yypParser ){ - sqlite3ParserCTX_STORE - sqlite3ParserInit(yypParser sqlite3ParserCTX_PARAM); - } - return (void*)yypParser; -} -#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ - - -/* The following function deletes the "minor type" or semantic value -** associated with a symbol. The symbol can be either a terminal -** or nonterminal. "yymajor" is the symbol code, and "yypminor" is -** a pointer to the value to be deleted. The code used to do the -** deletions is derived from the %destructor and/or %token_destructor -** directives of the input grammar. -*/ -static void yy_destructor( - yyParser *yypParser, /* The parser */ - YYCODETYPE yymajor, /* Type code for object to destroy */ - YYMINORTYPE *yypminor /* The object to be destroyed */ -){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH - switch( yymajor ){ - /* Here is inserted the actions which take place when a - ** terminal or non-terminal is destroyed. This can happen - ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is - ** being destroyed before it is finished parsing. - ** - ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are *not* used - ** inside the C code. - */ -/********* Begin destructor definitions ***************************************/ - case 206: /* select */ - case 241: /* selectnowith */ - case 242: /* oneselect */ - case 254: /* values */ - case 256: /* mvalues */ -{ -sqlite3SelectDelete(pParse->db, (yypminor->yy637)); -} - break; - case 218: /* term */ - case 219: /* expr */ - case 248: /* where_opt */ - case 250: /* having_opt */ - case 270: /* where_opt_ret */ - case 281: /* case_operand */ - case 283: /* case_else */ - case 286: /* vinto */ - case 293: /* when_clause */ - case 298: /* key_opt */ - case 315: /* filter_clause */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy590)); -} - break; - case 223: /* eidlist_opt */ - case 233: /* sortlist */ - case 234: /* eidlist */ - case 246: /* selcollist */ - case 249: /* groupby_opt */ - case 251: /* orderby_opt */ - case 255: /* nexprlist */ - case 257: /* sclp */ - case 264: /* exprlist */ - case 271: /* setlist */ - case 280: /* paren_exprlist */ - case 282: /* case_exprlist */ - case 314: /* part_opt */ -{ -sqlite3ExprListDelete(pParse->db, (yypminor->yy402)); -} - break; - case 240: /* fullname */ - case 247: /* from */ - case 259: /* seltablist */ - case 260: /* stl_prefix */ - case 265: /* xfullname */ -{ -sqlite3SrcListDelete(pParse->db, (yypminor->yy563)); -} - break; - case 243: /* wqlist */ -{ -sqlite3WithDelete(pParse->db, (yypminor->yy125)); -} - break; - case 253: /* window_clause */ - case 310: /* windowdefn_list */ -{ -sqlite3WindowListDelete(pParse->db, (yypminor->yy483)); -} - break; - case 266: /* idlist */ - case 273: /* idlist_opt */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy204)); -} - break; - case 276: /* filter_over */ - case 311: /* windowdefn */ - case 312: /* window */ - case 313: /* frame_opt */ - case 316: /* over_clause */ -{ -sqlite3WindowDelete(pParse->db, (yypminor->yy483)); -} - break; - case 289: /* trigger_cmd_list */ - case 294: /* trigger_cmd */ -{ -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319)); -} - break; - case 291: /* trigger_event */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy28).b); -} - break; - case 318: /* frame_bound */ - case 319: /* frame_bound_s */ - case 320: /* frame_bound_e */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr); -} - break; -/********* End destructor definitions *****************************************/ - default: break; /* If no destructor action specified: do nothing */ - } -} - -/* -** Pop the parser's stack once. -** -** If there is a destructor routine associated with the token which -** is popped from the stack, then call it. -*/ -static void yy_pop_parser_stack(yyParser *pParser){ - yyStackEntry *yytos; - assert( pParser->yytos!=0 ); - assert( pParser->yytos > pParser->yystack ); - yytos = pParser->yytos--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - yy_destructor(pParser, yytos->major, &yytos->minor); -} - -/* -** Clear all secondary memory allocations from the parser -*/ -SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ - yyParser *pParser = (yyParser*)p; - - /* In-lined version of calling yy_pop_parser_stack() for each - ** element left in the stack */ - yyStackEntry *yytos = pParser->yytos; - while( yytos>pParser->yystack ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - if( yytos->major>=YY_MIN_DSTRCTR ){ - yy_destructor(pParser, yytos->major, &yytos->minor); - } - yytos--; - } - -#if YYGROWABLESTACK - if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack); -#endif -} - -#ifndef sqlite3Parser_ENGINEALWAYSONSTACK -/* -** Deallocate and destroy a parser. Destructors are called for -** all stack elements before shutting the parser down. -** -** If the YYPARSEFREENEVERNULL macro exists (for example because it -** is defined in a %include section of the input grammar) then it is -** assumed that the input pointer is never NULL. -*/ -SQLITE_PRIVATE void sqlite3ParserFree( - void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ -){ -#ifndef YYPARSEFREENEVERNULL - if( p==0 ) return; -#endif - sqlite3ParserFinalize(p); - (*freeProc)(p); -} -#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ - -/* -** Return the peak depth of the stack for a parser. -*/ -#ifdef YYTRACKMAXSTACKDEPTH -SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){ - yyParser *pParser = (yyParser*)p; - return pParser->yyhwm; -} -#endif - -/* This array of booleans keeps track of the parser statement -** coverage. The element yycoverage[X][Y] is set when the parser -** is in state X and has a lookahead token Y. In a well-tested -** systems, every element of this matrix should end up being set. -*/ -#if defined(YYCOVERAGE) -static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; -#endif - -/* -** Write into out a description of every state/lookahead combination that -** -** (1) has not been used by the parser, and -** (2) is not a syntax error. -** -** Return the number of missed state/lookahead combinations. -*/ -#if defined(YYCOVERAGE) -SQLITE_PRIVATE int sqlite3ParserCoverage(FILE *out){ - int stateno, iLookAhead, i; - int nMissed = 0; - for(stateno=0; statenoYY_MAX_SHIFT ) return stateno; - assert( stateno <= YY_SHIFT_COUNT ); -#if defined(YYCOVERAGE) - yycoverage[stateno][iLookAhead] = 1; -#endif - do{ - i = yy_shift_ofst[stateno]; - assert( i>=0 ); - assert( i<=YY_ACTTAB_COUNT ); - assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); - assert( iLookAhead!=YYNOCODE ); - assert( iLookAhead < YYNTOKEN ); - i += iLookAhead; - assert( i<(int)YY_NLOOKAHEAD ); - if( yy_lookahead[i]!=iLookAhead ){ -#ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - assert( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); - if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; - } - } -#endif /* YYWILDCARD */ - return yy_default[stateno]; - }else{ - assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) ); - return yy_action[i]; - } - }while(1); -} - -/* -** Find the appropriate action for a parser given the non-terminal -** look-ahead token iLookAhead. -*/ -static YYACTIONTYPE yy_find_reduce_action( - YYACTIONTYPE stateno, /* Current state number */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; -#ifdef YYERRORSYMBOL - if( stateno>YY_REDUCE_COUNT ){ - return yy_default[stateno]; - } -#else - assert( stateno<=YY_REDUCE_COUNT ); -#endif - i = yy_reduce_ofst[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; -#ifdef YYERRORSYMBOL - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - return yy_default[stateno]; - } -#else - assert( i>=0 && iyytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ -/******** Begin %stack_overflow code ******************************************/ - - sqlite3OomFault(pParse->db); -/******** End %stack_overflow code ********************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ - sqlite3ParserCTX_STORE -} - -/* -** Print tracing information for a SHIFT action -*/ -#ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ - if( yyTraceFILE ){ - if( yyNewStateyytos->major], - yyNewState); - }else{ - fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", - yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], - yyNewState - YY_MIN_REDUCE); - } - } -} -#else -# define yyTraceShift(X,Y,Z) -#endif - -/* -** Perform a shift action. -*/ -static void yy_shift( - yyParser *yypParser, /* The parser to be shifted */ - YYACTIONTYPE yyNewState, /* The new state to shift in */ - YYCODETYPE yyMajor, /* The major token to shift in */ - sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ -){ - yyStackEntry *yytos; - yypParser->yytos++; -#ifdef YYTRACKMAXSTACKDEPTH - if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ - yypParser->yyhwm++; - assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); - } -#endif - yytos = yypParser->yytos; - if( yytos>yypParser->yystackEnd ){ - if( yyGrowStack(yypParser) ){ - yypParser->yytos--; - yyStackOverflow(yypParser); - return; - } - yytos = yypParser->yytos; - assert( yytos <= yypParser->yystackEnd ); - } - if( yyNewState > YY_MAX_SHIFT ){ - yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - } - yytos->stateno = yyNewState; - yytos->major = yyMajor; - yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState, "Shift"); -} - -/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side -** of that rule */ -static const YYCODETYPE yyRuleInfoLhs[] = { - 191, /* (0) explain ::= EXPLAIN */ - 191, /* (1) explain ::= EXPLAIN QUERY PLAN */ - 190, /* (2) cmdx ::= cmd */ - 192, /* (3) cmd ::= BEGIN transtype trans_opt */ - 193, /* (4) transtype ::= */ - 193, /* (5) transtype ::= DEFERRED */ - 193, /* (6) transtype ::= IMMEDIATE */ - 193, /* (7) transtype ::= EXCLUSIVE */ - 192, /* (8) cmd ::= COMMIT|END trans_opt */ - 192, /* (9) cmd ::= ROLLBACK trans_opt */ - 192, /* (10) cmd ::= SAVEPOINT nm */ - 192, /* (11) cmd ::= RELEASE savepoint_opt nm */ - 192, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - 197, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - 199, /* (14) createkw ::= CREATE */ - 201, /* (15) ifnotexists ::= */ - 201, /* (16) ifnotexists ::= IF NOT EXISTS */ - 200, /* (17) temp ::= TEMP */ - 200, /* (18) temp ::= */ - 198, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - 198, /* (20) create_table_args ::= AS select */ - 205, /* (21) table_option_set ::= */ - 205, /* (22) table_option_set ::= table_option_set COMMA table_option */ - 207, /* (23) table_option ::= WITHOUT nm */ - 207, /* (24) table_option ::= nm */ - 208, /* (25) columnname ::= nm typetoken */ - 210, /* (26) typetoken ::= */ - 210, /* (27) typetoken ::= typename LP signed RP */ - 210, /* (28) typetoken ::= typename LP signed COMMA signed RP */ - 211, /* (29) typename ::= typename ID|STRING */ - 215, /* (30) scanpt ::= */ - 216, /* (31) scantok ::= */ - 217, /* (32) ccons ::= CONSTRAINT nm */ - 217, /* (33) ccons ::= DEFAULT scantok term */ - 217, /* (34) ccons ::= DEFAULT LP expr RP */ - 217, /* (35) ccons ::= DEFAULT PLUS scantok term */ - 217, /* (36) ccons ::= DEFAULT MINUS scantok term */ - 217, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ - 217, /* (38) ccons ::= NOT NULL onconf */ - 217, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 217, /* (40) ccons ::= UNIQUE onconf */ - 217, /* (41) ccons ::= CHECK LP expr RP */ - 217, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ - 217, /* (43) ccons ::= defer_subclause */ - 217, /* (44) ccons ::= COLLATE ID|STRING */ - 226, /* (45) generated ::= LP expr RP */ - 226, /* (46) generated ::= LP expr RP ID */ - 222, /* (47) autoinc ::= */ - 222, /* (48) autoinc ::= AUTOINCR */ - 224, /* (49) refargs ::= */ - 224, /* (50) refargs ::= refargs refarg */ - 227, /* (51) refarg ::= MATCH nm */ - 227, /* (52) refarg ::= ON INSERT refact */ - 227, /* (53) refarg ::= ON DELETE refact */ - 227, /* (54) refarg ::= ON UPDATE refact */ - 228, /* (55) refact ::= SET NULL */ - 228, /* (56) refact ::= SET DEFAULT */ - 228, /* (57) refact ::= CASCADE */ - 228, /* (58) refact ::= RESTRICT */ - 228, /* (59) refact ::= NO ACTION */ - 225, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 225, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 229, /* (62) init_deferred_pred_opt ::= */ - 229, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 229, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 204, /* (65) conslist_opt ::= */ - 231, /* (66) tconscomma ::= COMMA */ - 232, /* (67) tcons ::= CONSTRAINT nm */ - 232, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 232, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ - 232, /* (70) tcons ::= CHECK LP expr RP onconf */ - 232, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 235, /* (72) defer_subclause_opt ::= */ - 220, /* (73) onconf ::= */ - 220, /* (74) onconf ::= ON CONFLICT resolvetype */ - 236, /* (75) orconf ::= */ - 236, /* (76) orconf ::= OR resolvetype */ - 237, /* (77) resolvetype ::= IGNORE */ - 237, /* (78) resolvetype ::= REPLACE */ - 192, /* (79) cmd ::= DROP TABLE ifexists fullname */ - 239, /* (80) ifexists ::= IF EXISTS */ - 239, /* (81) ifexists ::= */ - 192, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 192, /* (83) cmd ::= DROP VIEW ifexists fullname */ - 192, /* (84) cmd ::= select */ - 206, /* (85) select ::= WITH wqlist selectnowith */ - 206, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ - 206, /* (87) select ::= selectnowith */ - 241, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ - 244, /* (89) multiselect_op ::= UNION */ - 244, /* (90) multiselect_op ::= UNION ALL */ - 244, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ - 242, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 242, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 254, /* (94) values ::= VALUES LP nexprlist RP */ - 242, /* (95) oneselect ::= mvalues */ - 256, /* (96) mvalues ::= values COMMA LP nexprlist RP */ - 256, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ - 245, /* (98) distinct ::= DISTINCT */ - 245, /* (99) distinct ::= ALL */ - 245, /* (100) distinct ::= */ - 257, /* (101) sclp ::= */ - 246, /* (102) selcollist ::= sclp scanpt expr scanpt as */ - 246, /* (103) selcollist ::= sclp scanpt STAR */ - 246, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ - 258, /* (105) as ::= AS nm */ - 258, /* (106) as ::= */ - 247, /* (107) from ::= */ - 247, /* (108) from ::= FROM seltablist */ - 260, /* (109) stl_prefix ::= seltablist joinop */ - 260, /* (110) stl_prefix ::= */ - 259, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ - 259, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - 259, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - 259, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ - 259, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 202, /* (116) dbnm ::= */ - 202, /* (117) dbnm ::= DOT nm */ - 240, /* (118) fullname ::= nm */ - 240, /* (119) fullname ::= nm DOT nm */ - 265, /* (120) xfullname ::= nm */ - 265, /* (121) xfullname ::= nm DOT nm */ - 265, /* (122) xfullname ::= nm DOT nm AS nm */ - 265, /* (123) xfullname ::= nm AS nm */ - 261, /* (124) joinop ::= COMMA|JOIN */ - 261, /* (125) joinop ::= JOIN_KW JOIN */ - 261, /* (126) joinop ::= JOIN_KW nm JOIN */ - 261, /* (127) joinop ::= JOIN_KW nm nm JOIN */ - 262, /* (128) on_using ::= ON expr */ - 262, /* (129) on_using ::= USING LP idlist RP */ - 262, /* (130) on_using ::= */ - 267, /* (131) indexed_opt ::= */ - 263, /* (132) indexed_by ::= INDEXED BY nm */ - 263, /* (133) indexed_by ::= NOT INDEXED */ - 251, /* (134) orderby_opt ::= */ - 251, /* (135) orderby_opt ::= ORDER BY sortlist */ - 233, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ - 233, /* (137) sortlist ::= expr sortorder nulls */ - 221, /* (138) sortorder ::= ASC */ - 221, /* (139) sortorder ::= DESC */ - 221, /* (140) sortorder ::= */ - 268, /* (141) nulls ::= NULLS FIRST */ - 268, /* (142) nulls ::= NULLS LAST */ - 268, /* (143) nulls ::= */ - 249, /* (144) groupby_opt ::= */ - 249, /* (145) groupby_opt ::= GROUP BY nexprlist */ - 250, /* (146) having_opt ::= */ - 250, /* (147) having_opt ::= HAVING expr */ - 252, /* (148) limit_opt ::= */ - 252, /* (149) limit_opt ::= LIMIT expr */ - 252, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ - 252, /* (151) limit_opt ::= LIMIT expr COMMA expr */ - 192, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 248, /* (153) where_opt ::= */ - 248, /* (154) where_opt ::= WHERE expr */ - 270, /* (155) where_opt_ret ::= */ - 270, /* (156) where_opt_ret ::= WHERE expr */ - 270, /* (157) where_opt_ret ::= RETURNING selcollist */ - 270, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ - 192, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - 271, /* (160) setlist ::= setlist COMMA nm EQ expr */ - 271, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 271, /* (162) setlist ::= nm EQ expr */ - 271, /* (163) setlist ::= LP idlist RP EQ expr */ - 192, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 192, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 274, /* (166) upsert ::= */ - 274, /* (167) upsert ::= RETURNING selcollist */ - 274, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - 274, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - 274, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ - 274, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - 275, /* (172) returning ::= RETURNING selcollist */ - 272, /* (173) insert_cmd ::= INSERT orconf */ - 272, /* (174) insert_cmd ::= REPLACE */ - 273, /* (175) idlist_opt ::= */ - 273, /* (176) idlist_opt ::= LP idlist RP */ - 266, /* (177) idlist ::= idlist COMMA nm */ - 266, /* (178) idlist ::= nm */ - 219, /* (179) expr ::= LP expr RP */ - 219, /* (180) expr ::= ID|INDEXED|JOIN_KW */ - 219, /* (181) expr ::= nm DOT nm */ - 219, /* (182) expr ::= nm DOT nm DOT nm */ - 218, /* (183) term ::= NULL|FLOAT|BLOB */ - 218, /* (184) term ::= STRING */ - 218, /* (185) term ::= INTEGER */ - 219, /* (186) expr ::= VARIABLE */ - 219, /* (187) expr ::= expr COLLATE ID|STRING */ - 219, /* (188) expr ::= CAST LP expr AS typetoken RP */ - 219, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - 219, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ - 219, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - 219, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - 219, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ - 219, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - 218, /* (195) term ::= CTIME_KW */ - 219, /* (196) expr ::= LP nexprlist COMMA expr RP */ - 219, /* (197) expr ::= expr AND expr */ - 219, /* (198) expr ::= expr OR expr */ - 219, /* (199) expr ::= expr LT|GT|GE|LE expr */ - 219, /* (200) expr ::= expr EQ|NE expr */ - 219, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 219, /* (202) expr ::= expr PLUS|MINUS expr */ - 219, /* (203) expr ::= expr STAR|SLASH|REM expr */ - 219, /* (204) expr ::= expr CONCAT expr */ - 277, /* (205) likeop ::= NOT LIKE_KW|MATCH */ - 219, /* (206) expr ::= expr likeop expr */ - 219, /* (207) expr ::= expr likeop expr ESCAPE expr */ - 219, /* (208) expr ::= expr ISNULL|NOTNULL */ - 219, /* (209) expr ::= expr NOT NULL */ - 219, /* (210) expr ::= expr IS expr */ - 219, /* (211) expr ::= expr IS NOT expr */ - 219, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ - 219, /* (213) expr ::= expr IS DISTINCT FROM expr */ - 219, /* (214) expr ::= NOT expr */ - 219, /* (215) expr ::= BITNOT expr */ - 219, /* (216) expr ::= PLUS|MINUS expr */ - 219, /* (217) expr ::= expr PTR expr */ - 278, /* (218) between_op ::= BETWEEN */ - 278, /* (219) between_op ::= NOT BETWEEN */ - 219, /* (220) expr ::= expr between_op expr AND expr */ - 279, /* (221) in_op ::= IN */ - 279, /* (222) in_op ::= NOT IN */ - 219, /* (223) expr ::= expr in_op LP exprlist RP */ - 219, /* (224) expr ::= LP select RP */ - 219, /* (225) expr ::= expr in_op LP select RP */ - 219, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ - 219, /* (227) expr ::= EXISTS LP select RP */ - 219, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ - 282, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 282, /* (230) case_exprlist ::= WHEN expr THEN expr */ - 283, /* (231) case_else ::= ELSE expr */ - 283, /* (232) case_else ::= */ - 281, /* (233) case_operand ::= */ - 264, /* (234) exprlist ::= */ - 255, /* (235) nexprlist ::= nexprlist COMMA expr */ - 255, /* (236) nexprlist ::= expr */ - 280, /* (237) paren_exprlist ::= */ - 280, /* (238) paren_exprlist ::= LP exprlist RP */ - 192, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 284, /* (240) uniqueflag ::= UNIQUE */ - 284, /* (241) uniqueflag ::= */ - 223, /* (242) eidlist_opt ::= */ - 223, /* (243) eidlist_opt ::= LP eidlist RP */ - 234, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ - 234, /* (245) eidlist ::= nm collate sortorder */ - 285, /* (246) collate ::= */ - 285, /* (247) collate ::= COLLATE ID|STRING */ - 192, /* (248) cmd ::= DROP INDEX ifexists fullname */ - 192, /* (249) cmd ::= VACUUM vinto */ - 192, /* (250) cmd ::= VACUUM nm vinto */ - 286, /* (251) vinto ::= INTO expr */ - 286, /* (252) vinto ::= */ - 192, /* (253) cmd ::= PRAGMA nm dbnm */ - 192, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 192, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 192, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 192, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 213, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ - 214, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ - 192, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 288, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 290, /* (262) trigger_time ::= BEFORE|AFTER */ - 290, /* (263) trigger_time ::= INSTEAD OF */ - 290, /* (264) trigger_time ::= */ - 291, /* (265) trigger_event ::= DELETE|INSERT */ - 291, /* (266) trigger_event ::= UPDATE */ - 291, /* (267) trigger_event ::= UPDATE OF idlist */ - 293, /* (268) when_clause ::= */ - 293, /* (269) when_clause ::= WHEN expr */ - 289, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 289, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - 295, /* (272) trnm ::= nm DOT nm */ - 296, /* (273) tridxby ::= INDEXED BY nm */ - 296, /* (274) tridxby ::= NOT INDEXED */ - 294, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - 294, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 294, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 294, /* (278) trigger_cmd ::= scanpt select scanpt */ - 219, /* (279) expr ::= RAISE LP IGNORE RP */ - 219, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ - 238, /* (281) raisetype ::= ROLLBACK */ - 238, /* (282) raisetype ::= ABORT */ - 238, /* (283) raisetype ::= FAIL */ - 192, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ - 192, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 192, /* (286) cmd ::= DETACH database_kw_opt expr */ - 298, /* (287) key_opt ::= */ - 298, /* (288) key_opt ::= KEY expr */ - 192, /* (289) cmd ::= REINDEX */ - 192, /* (290) cmd ::= REINDEX nm dbnm */ - 192, /* (291) cmd ::= ANALYZE */ - 192, /* (292) cmd ::= ANALYZE nm dbnm */ - 192, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 192, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 192, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 299, /* (296) add_column_fullname ::= fullname */ - 192, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 192, /* (298) cmd ::= create_vtab */ - 192, /* (299) cmd ::= create_vtab LP vtabarglist RP */ - 301, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 303, /* (301) vtabarg ::= */ - 304, /* (302) vtabargtoken ::= ANY */ - 304, /* (303) vtabargtoken ::= lp anylist RP */ - 305, /* (304) lp ::= LP */ - 269, /* (305) with ::= WITH wqlist */ - 269, /* (306) with ::= WITH RECURSIVE wqlist */ - 308, /* (307) wqas ::= AS */ - 308, /* (308) wqas ::= AS MATERIALIZED */ - 308, /* (309) wqas ::= AS NOT MATERIALIZED */ - 307, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ - 309, /* (311) withnm ::= nm */ - 243, /* (312) wqlist ::= wqitem */ - 243, /* (313) wqlist ::= wqlist COMMA wqitem */ - 310, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 311, /* (315) windowdefn ::= nm AS LP window RP */ - 312, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 312, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 312, /* (318) window ::= ORDER BY sortlist frame_opt */ - 312, /* (319) window ::= nm ORDER BY sortlist frame_opt */ - 312, /* (320) window ::= nm frame_opt */ - 313, /* (321) frame_opt ::= */ - 313, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 313, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 317, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ - 319, /* (325) frame_bound_s ::= frame_bound */ - 319, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ - 320, /* (327) frame_bound_e ::= frame_bound */ - 320, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 318, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ - 318, /* (330) frame_bound ::= CURRENT ROW */ - 321, /* (331) frame_exclude_opt ::= */ - 321, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 322, /* (333) frame_exclude ::= NO OTHERS */ - 322, /* (334) frame_exclude ::= CURRENT ROW */ - 322, /* (335) frame_exclude ::= GROUP|TIES */ - 253, /* (336) window_clause ::= WINDOW windowdefn_list */ - 276, /* (337) filter_over ::= filter_clause over_clause */ - 276, /* (338) filter_over ::= over_clause */ - 276, /* (339) filter_over ::= filter_clause */ - 316, /* (340) over_clause ::= OVER LP window RP */ - 316, /* (341) over_clause ::= OVER nm */ - 315, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ - 218, /* (343) term ::= QNUMBER */ - 187, /* (344) input ::= cmdlist */ - 188, /* (345) cmdlist ::= cmdlist ecmd */ - 188, /* (346) cmdlist ::= ecmd */ - 189, /* (347) ecmd ::= SEMI */ - 189, /* (348) ecmd ::= cmdx SEMI */ - 189, /* (349) ecmd ::= explain cmdx SEMI */ - 194, /* (350) trans_opt ::= */ - 194, /* (351) trans_opt ::= TRANSACTION */ - 194, /* (352) trans_opt ::= TRANSACTION nm */ - 196, /* (353) savepoint_opt ::= SAVEPOINT */ - 196, /* (354) savepoint_opt ::= */ - 192, /* (355) cmd ::= create_table create_table_args */ - 205, /* (356) table_option_set ::= table_option */ - 203, /* (357) columnlist ::= columnlist COMMA columnname carglist */ - 203, /* (358) columnlist ::= columnname carglist */ - 195, /* (359) nm ::= ID|INDEXED|JOIN_KW */ - 195, /* (360) nm ::= STRING */ - 210, /* (361) typetoken ::= typename */ - 211, /* (362) typename ::= ID|STRING */ - 212, /* (363) signed ::= plus_num */ - 212, /* (364) signed ::= minus_num */ - 209, /* (365) carglist ::= carglist ccons */ - 209, /* (366) carglist ::= */ - 217, /* (367) ccons ::= NULL onconf */ - 217, /* (368) ccons ::= GENERATED ALWAYS AS generated */ - 217, /* (369) ccons ::= AS generated */ - 204, /* (370) conslist_opt ::= COMMA conslist */ - 230, /* (371) conslist ::= conslist tconscomma tcons */ - 230, /* (372) conslist ::= tcons */ - 231, /* (373) tconscomma ::= */ - 235, /* (374) defer_subclause_opt ::= defer_subclause */ - 237, /* (375) resolvetype ::= raisetype */ - 241, /* (376) selectnowith ::= oneselect */ - 242, /* (377) oneselect ::= values */ - 257, /* (378) sclp ::= selcollist COMMA */ - 258, /* (379) as ::= ID|STRING */ - 267, /* (380) indexed_opt ::= indexed_by */ - 275, /* (381) returning ::= */ - 219, /* (382) expr ::= term */ - 277, /* (383) likeop ::= LIKE_KW|MATCH */ - 281, /* (384) case_operand ::= expr */ - 264, /* (385) exprlist ::= nexprlist */ - 287, /* (386) nmnum ::= plus_num */ - 287, /* (387) nmnum ::= nm */ - 287, /* (388) nmnum ::= ON */ - 287, /* (389) nmnum ::= DELETE */ - 287, /* (390) nmnum ::= DEFAULT */ - 213, /* (391) plus_num ::= INTEGER|FLOAT */ - 292, /* (392) foreach_clause ::= */ - 292, /* (393) foreach_clause ::= FOR EACH ROW */ - 295, /* (394) trnm ::= nm */ - 296, /* (395) tridxby ::= */ - 297, /* (396) database_kw_opt ::= DATABASE */ - 297, /* (397) database_kw_opt ::= */ - 300, /* (398) kwcolumn_opt ::= */ - 300, /* (399) kwcolumn_opt ::= COLUMNKW */ - 302, /* (400) vtabarglist ::= vtabarg */ - 302, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ - 303, /* (402) vtabarg ::= vtabarg vtabargtoken */ - 306, /* (403) anylist ::= */ - 306, /* (404) anylist ::= anylist LP anylist RP */ - 306, /* (405) anylist ::= anylist ANY */ - 269, /* (406) with ::= */ - 310, /* (407) windowdefn_list ::= windowdefn */ - 312, /* (408) window ::= frame_opt */ -}; - -/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number -** of symbols on the right-hand side of that rule. */ -static const signed char yyRuleInfoNRhs[] = { - -1, /* (0) explain ::= EXPLAIN */ - -3, /* (1) explain ::= EXPLAIN QUERY PLAN */ - -1, /* (2) cmdx ::= cmd */ - -3, /* (3) cmd ::= BEGIN transtype trans_opt */ - 0, /* (4) transtype ::= */ - -1, /* (5) transtype ::= DEFERRED */ - -1, /* (6) transtype ::= IMMEDIATE */ - -1, /* (7) transtype ::= EXCLUSIVE */ - -2, /* (8) cmd ::= COMMIT|END trans_opt */ - -2, /* (9) cmd ::= ROLLBACK trans_opt */ - -2, /* (10) cmd ::= SAVEPOINT nm */ - -3, /* (11) cmd ::= RELEASE savepoint_opt nm */ - -5, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - -6, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - -1, /* (14) createkw ::= CREATE */ - 0, /* (15) ifnotexists ::= */ - -3, /* (16) ifnotexists ::= IF NOT EXISTS */ - -1, /* (17) temp ::= TEMP */ - 0, /* (18) temp ::= */ - -5, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - -2, /* (20) create_table_args ::= AS select */ - 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 */ - -1, /* (95) oneselect ::= mvalues */ - -5, /* (96) mvalues ::= values COMMA LP nexprlist RP */ - -5, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ - -1, /* (98) distinct ::= DISTINCT */ - -1, /* (99) distinct ::= ALL */ - 0, /* (100) distinct ::= */ - 0, /* (101) sclp ::= */ - -5, /* (102) selcollist ::= sclp scanpt expr scanpt as */ - -3, /* (103) selcollist ::= sclp scanpt STAR */ - -5, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ - -2, /* (105) as ::= AS nm */ - 0, /* (106) as ::= */ - 0, /* (107) from ::= */ - -2, /* (108) from ::= FROM seltablist */ - -2, /* (109) stl_prefix ::= seltablist joinop */ - 0, /* (110) stl_prefix ::= */ - -5, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ - -6, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - -8, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - -6, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ - -6, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 0, /* (116) dbnm ::= */ - -2, /* (117) dbnm ::= DOT nm */ - -1, /* (118) fullname ::= nm */ - -3, /* (119) fullname ::= nm DOT nm */ - -1, /* (120) xfullname ::= nm */ - -3, /* (121) xfullname ::= nm DOT nm */ - -5, /* (122) xfullname ::= nm DOT nm AS nm */ - -3, /* (123) xfullname ::= nm AS nm */ - -1, /* (124) joinop ::= COMMA|JOIN */ - -2, /* (125) joinop ::= JOIN_KW JOIN */ - -3, /* (126) joinop ::= JOIN_KW nm JOIN */ - -4, /* (127) joinop ::= JOIN_KW nm nm JOIN */ - -2, /* (128) on_using ::= ON expr */ - -4, /* (129) on_using ::= USING LP idlist RP */ - 0, /* (130) on_using ::= */ - 0, /* (131) indexed_opt ::= */ - -3, /* (132) indexed_by ::= INDEXED BY nm */ - -2, /* (133) indexed_by ::= NOT INDEXED */ - 0, /* (134) orderby_opt ::= */ - -3, /* (135) orderby_opt ::= ORDER BY sortlist */ - -5, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ - -3, /* (137) sortlist ::= expr sortorder nulls */ - -1, /* (138) sortorder ::= ASC */ - -1, /* (139) sortorder ::= DESC */ - 0, /* (140) sortorder ::= */ - -2, /* (141) nulls ::= NULLS FIRST */ - -2, /* (142) nulls ::= NULLS LAST */ - 0, /* (143) nulls ::= */ - 0, /* (144) groupby_opt ::= */ - -3, /* (145) groupby_opt ::= GROUP BY nexprlist */ - 0, /* (146) having_opt ::= */ - -2, /* (147) having_opt ::= HAVING expr */ - 0, /* (148) limit_opt ::= */ - -2, /* (149) limit_opt ::= LIMIT expr */ - -4, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ - -4, /* (151) limit_opt ::= LIMIT expr COMMA expr */ - -6, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 0, /* (153) where_opt ::= */ - -2, /* (154) where_opt ::= WHERE expr */ - 0, /* (155) where_opt_ret ::= */ - -2, /* (156) where_opt_ret ::= WHERE expr */ - -2, /* (157) where_opt_ret ::= RETURNING selcollist */ - -4, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ - -9, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - -5, /* (160) setlist ::= setlist COMMA nm EQ expr */ - -7, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ - -3, /* (162) setlist ::= nm EQ expr */ - -5, /* (163) setlist ::= LP idlist RP EQ expr */ - -7, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - -8, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 0, /* (166) upsert ::= */ - -2, /* (167) upsert ::= RETURNING selcollist */ - -12, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - -9, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - -5, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ - -8, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - -2, /* (172) returning ::= RETURNING selcollist */ - -2, /* (173) insert_cmd ::= INSERT orconf */ - -1, /* (174) insert_cmd ::= REPLACE */ - 0, /* (175) idlist_opt ::= */ - -3, /* (176) idlist_opt ::= LP idlist RP */ - -3, /* (177) idlist ::= idlist COMMA nm */ - -1, /* (178) idlist ::= nm */ - -3, /* (179) expr ::= LP expr RP */ - -1, /* (180) expr ::= ID|INDEXED|JOIN_KW */ - -3, /* (181) expr ::= nm DOT nm */ - -5, /* (182) expr ::= nm DOT nm DOT nm */ - -1, /* (183) term ::= NULL|FLOAT|BLOB */ - -1, /* (184) term ::= STRING */ - -1, /* (185) term ::= INTEGER */ - -1, /* (186) expr ::= VARIABLE */ - -3, /* (187) expr ::= expr COLLATE ID|STRING */ - -6, /* (188) expr ::= CAST LP expr AS typetoken RP */ - -5, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - -8, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ - -4, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - -6, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - -9, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ - -5, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - -1, /* (195) term ::= CTIME_KW */ - -5, /* (196) expr ::= LP nexprlist COMMA expr RP */ - -3, /* (197) expr ::= expr AND expr */ - -3, /* (198) expr ::= expr OR expr */ - -3, /* (199) expr ::= expr LT|GT|GE|LE expr */ - -3, /* (200) expr ::= expr EQ|NE expr */ - -3, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - -3, /* (202) expr ::= expr PLUS|MINUS expr */ - -3, /* (203) expr ::= expr STAR|SLASH|REM expr */ - -3, /* (204) expr ::= expr CONCAT expr */ - -2, /* (205) likeop ::= NOT LIKE_KW|MATCH */ - -3, /* (206) expr ::= expr likeop expr */ - -5, /* (207) expr ::= expr likeop expr ESCAPE expr */ - -2, /* (208) expr ::= expr ISNULL|NOTNULL */ - -3, /* (209) expr ::= expr NOT NULL */ - -3, /* (210) expr ::= expr IS expr */ - -4, /* (211) expr ::= expr IS NOT expr */ - -6, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ - -5, /* (213) expr ::= expr IS DISTINCT FROM expr */ - -2, /* (214) expr ::= NOT expr */ - -2, /* (215) expr ::= BITNOT expr */ - -2, /* (216) expr ::= PLUS|MINUS expr */ - -3, /* (217) expr ::= expr PTR expr */ - -1, /* (218) between_op ::= BETWEEN */ - -2, /* (219) between_op ::= NOT BETWEEN */ - -5, /* (220) expr ::= expr between_op expr AND expr */ - -1, /* (221) in_op ::= IN */ - -2, /* (222) in_op ::= NOT IN */ - -5, /* (223) expr ::= expr in_op LP exprlist RP */ - -3, /* (224) expr ::= LP select RP */ - -5, /* (225) expr ::= expr in_op LP select RP */ - -5, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ - -4, /* (227) expr ::= EXISTS LP select RP */ - -5, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ - -5, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - -4, /* (230) case_exprlist ::= WHEN expr THEN expr */ - -2, /* (231) case_else ::= ELSE expr */ - 0, /* (232) case_else ::= */ - 0, /* (233) case_operand ::= */ - 0, /* (234) exprlist ::= */ - -3, /* (235) nexprlist ::= nexprlist COMMA expr */ - -1, /* (236) nexprlist ::= expr */ - 0, /* (237) paren_exprlist ::= */ - -3, /* (238) paren_exprlist ::= LP exprlist RP */ - -12, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - -1, /* (240) uniqueflag ::= UNIQUE */ - 0, /* (241) uniqueflag ::= */ - 0, /* (242) eidlist_opt ::= */ - -3, /* (243) eidlist_opt ::= LP eidlist RP */ - -5, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ - -3, /* (245) eidlist ::= nm collate sortorder */ - 0, /* (246) collate ::= */ - -2, /* (247) collate ::= COLLATE ID|STRING */ - -4, /* (248) cmd ::= DROP INDEX ifexists fullname */ - -2, /* (249) cmd ::= VACUUM vinto */ - -3, /* (250) cmd ::= VACUUM nm vinto */ - -2, /* (251) vinto ::= INTO expr */ - 0, /* (252) vinto ::= */ - -3, /* (253) cmd ::= PRAGMA nm dbnm */ - -5, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ - -6, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - -5, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ - -6, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - -2, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ - -2, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ - -5, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - -11, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - -1, /* (262) trigger_time ::= BEFORE|AFTER */ - -2, /* (263) trigger_time ::= INSTEAD OF */ - 0, /* (264) trigger_time ::= */ - -1, /* (265) trigger_event ::= DELETE|INSERT */ - -1, /* (266) trigger_event ::= UPDATE */ - -3, /* (267) trigger_event ::= UPDATE OF idlist */ - 0, /* (268) when_clause ::= */ - -2, /* (269) when_clause ::= WHEN expr */ - -3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - -2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (272) trnm ::= nm DOT nm */ - -3, /* (273) tridxby ::= INDEXED BY nm */ - -2, /* (274) tridxby ::= NOT INDEXED */ - -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - -3, /* (278) trigger_cmd ::= scanpt select scanpt */ - -4, /* (279) expr ::= RAISE LP IGNORE RP */ - -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ - -1, /* (281) raisetype ::= ROLLBACK */ - -1, /* (282) raisetype ::= ABORT */ - -1, /* (283) raisetype ::= FAIL */ - -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (286) cmd ::= DETACH database_kw_opt expr */ - 0, /* (287) key_opt ::= */ - -2, /* (288) key_opt ::= KEY expr */ - -1, /* (289) cmd ::= REINDEX */ - -3, /* (290) cmd ::= REINDEX nm dbnm */ - -1, /* (291) cmd ::= ANALYZE */ - -3, /* (292) cmd ::= ANALYZE nm dbnm */ - -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - -6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -1, /* (296) add_column_fullname ::= fullname */ - -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -1, /* (298) cmd ::= create_vtab */ - -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (301) vtabarg ::= */ - -1, /* (302) vtabargtoken ::= ANY */ - -3, /* (303) vtabargtoken ::= lp anylist RP */ - -1, /* (304) lp ::= LP */ - -2, /* (305) with ::= WITH wqlist */ - -3, /* (306) with ::= WITH RECURSIVE wqlist */ - -1, /* (307) wqas ::= AS */ - -2, /* (308) wqas ::= AS MATERIALIZED */ - -3, /* (309) wqas ::= AS NOT MATERIALIZED */ - -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ - -1, /* (311) withnm ::= nm */ - -1, /* (312) wqlist ::= wqitem */ - -3, /* (313) wqlist ::= wqlist COMMA wqitem */ - -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (315) windowdefn ::= nm AS LP window RP */ - -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (318) window ::= ORDER BY sortlist frame_opt */ - -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */ - -2, /* (320) window ::= nm frame_opt */ - 0, /* (321) frame_opt ::= */ - -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (325) frame_bound_s ::= frame_bound */ - -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (327) frame_bound_e ::= frame_bound */ - -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (330) frame_bound ::= CURRENT ROW */ - 0, /* (331) frame_exclude_opt ::= */ - -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (333) frame_exclude ::= NO OTHERS */ - -2, /* (334) frame_exclude ::= CURRENT ROW */ - -1, /* (335) frame_exclude ::= GROUP|TIES */ - -2, /* (336) window_clause ::= WINDOW windowdefn_list */ - -2, /* (337) filter_over ::= filter_clause over_clause */ - -1, /* (338) filter_over ::= over_clause */ - -1, /* (339) filter_over ::= filter_clause */ - -4, /* (340) over_clause ::= OVER LP window RP */ - -2, /* (341) over_clause ::= OVER nm */ - -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (343) term ::= QNUMBER */ - -1, /* (344) input ::= cmdlist */ - -2, /* (345) cmdlist ::= cmdlist ecmd */ - -1, /* (346) cmdlist ::= ecmd */ - -1, /* (347) ecmd ::= SEMI */ - -2, /* (348) ecmd ::= cmdx SEMI */ - -3, /* (349) ecmd ::= explain cmdx SEMI */ - 0, /* (350) trans_opt ::= */ - -1, /* (351) trans_opt ::= TRANSACTION */ - -2, /* (352) trans_opt ::= TRANSACTION nm */ - -1, /* (353) savepoint_opt ::= SAVEPOINT */ - 0, /* (354) savepoint_opt ::= */ - -2, /* (355) cmd ::= create_table create_table_args */ - -1, /* (356) table_option_set ::= table_option */ - -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (358) columnlist ::= columnname carglist */ - -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (360) nm ::= STRING */ - -1, /* (361) typetoken ::= typename */ - -1, /* (362) typename ::= ID|STRING */ - -1, /* (363) signed ::= plus_num */ - -1, /* (364) signed ::= minus_num */ - -2, /* (365) carglist ::= carglist ccons */ - 0, /* (366) carglist ::= */ - -2, /* (367) ccons ::= NULL onconf */ - -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (369) ccons ::= AS generated */ - -2, /* (370) conslist_opt ::= COMMA conslist */ - -3, /* (371) conslist ::= conslist tconscomma tcons */ - -1, /* (372) conslist ::= tcons */ - 0, /* (373) tconscomma ::= */ - -1, /* (374) defer_subclause_opt ::= defer_subclause */ - -1, /* (375) resolvetype ::= raisetype */ - -1, /* (376) selectnowith ::= oneselect */ - -1, /* (377) oneselect ::= values */ - -2, /* (378) sclp ::= selcollist COMMA */ - -1, /* (379) as ::= ID|STRING */ - -1, /* (380) indexed_opt ::= indexed_by */ - 0, /* (381) returning ::= */ - -1, /* (382) expr ::= term */ - -1, /* (383) likeop ::= LIKE_KW|MATCH */ - -1, /* (384) case_operand ::= expr */ - -1, /* (385) exprlist ::= nexprlist */ - -1, /* (386) nmnum ::= plus_num */ - -1, /* (387) nmnum ::= nm */ - -1, /* (388) nmnum ::= ON */ - -1, /* (389) nmnum ::= DELETE */ - -1, /* (390) nmnum ::= DEFAULT */ - -1, /* (391) plus_num ::= INTEGER|FLOAT */ - 0, /* (392) foreach_clause ::= */ - -3, /* (393) foreach_clause ::= FOR EACH ROW */ - -1, /* (394) trnm ::= nm */ - 0, /* (395) tridxby ::= */ - -1, /* (396) database_kw_opt ::= DATABASE */ - 0, /* (397) database_kw_opt ::= */ - 0, /* (398) kwcolumn_opt ::= */ - -1, /* (399) kwcolumn_opt ::= COLUMNKW */ - -1, /* (400) vtabarglist ::= vtabarg */ - -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (402) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (403) anylist ::= */ - -4, /* (404) anylist ::= anylist LP anylist RP */ - -2, /* (405) anylist ::= anylist ANY */ - 0, /* (406) with ::= */ - -1, /* (407) windowdefn_list ::= windowdefn */ - -1, /* (408) window ::= frame_opt */ -}; - -static void yy_accept(yyParser*); /* Forward Declaration */ - -/* -** Perform a reduce action and the shift that must immediately -** follow the reduce. -** -** The yyLookahead and yyLookaheadToken parameters provide reduce actions -** access to the lookahead token (if any). The yyLookahead will be YYNOCODE -** if the lookahead token has already been consumed. As this procedure is -** only called from one place, optimizing compilers will in-line it, which -** means that the extra parameters have no performance impact. -*/ -static YYACTIONTYPE yy_reduce( - yyParser *yypParser, /* The parser */ - unsigned int yyruleno, /* Number of the rule by which to reduce */ - int yyLookahead, /* Lookahead token, or YYNOCODE if none */ - sqlite3ParserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ - sqlite3ParserCTX_PDECL /* %extra_context */ -){ - int yygoto; /* The next state */ - YYACTIONTYPE yyact; /* The next action */ - yyStackEntry *yymsp; /* The top of the parser's stack */ - int yysize; /* Amount to pop the stack */ - sqlite3ParserARG_FETCH - (void)yyLookahead; - (void)yyLookaheadToken; - yymsp = yypParser->yytos; - - switch( yyruleno ){ - /* Beginning here are the reduction cases. A typical example - ** follows: - ** case 0: - ** #line - ** { ... } // User supplied code - ** #line - ** break; - */ -/********** Begin reduce actions **********************************************/ - YYMINORTYPE yylhsminor; - case 0: /* explain ::= EXPLAIN */ -{ if( pParse->pReprepare==0 ) pParse->explain = 1; } - break; - case 1: /* explain ::= EXPLAIN QUERY PLAN */ -{ if( pParse->pReprepare==0 ) pParse->explain = 2; } - break; - case 2: /* cmdx ::= cmd */ -{ sqlite3FinishCoding(pParse); } - break; - case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);} - break; - case 4: /* transtype ::= */ -{yymsp[1].minor.yy502 = TK_DEFERRED;} - break; - case 5: /* transtype ::= DEFERRED */ - case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); - case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324); -{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/} - break; - case 8: /* cmd ::= COMMIT|END trans_opt */ - case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); -{sqlite3EndTransaction(pParse,yymsp[-1].major);} - break; - case 10: /* cmd ::= SAVEPOINT nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0); -} - break; - case 11: /* cmd ::= RELEASE savepoint_opt nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0); -} - break; - case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); -} - break; - case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ -{ - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); -} - break; - case 14: /* createkw ::= CREATE */ -{ - disableLookaside(pParse); -} - break; - case 15: /* ifnotexists ::= */ - case 18: /* temp ::= */ yytestcase(yyruleno==18); - 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 100: /* distinct ::= */ yytestcase(yyruleno==100); - case 246: /* collate ::= */ yytestcase(yyruleno==246); -{yymsp[1].minor.yy502 = 0;} - break; - case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy502 = 1;} - break; - case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy502 = pParse->db->init.busy==0;} - break; - case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ -{ - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0); -} - break; - case 20: /* create_table_args ::= AS select */ -{ - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); -} - break; - case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy9 = 0;} - break; - case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;} - yymsp[-2].minor.yy9 = yylhsminor.yy9; - break; - case 23: /* table_option ::= WITHOUT nm */ -{ - if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid; - }else{ - yymsp[-1].minor.yy9 = 0; - 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 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy9 = TF_Strict; - }else{ - yylhsminor.yy9 = 0; - sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); - } -} - yymsp[0].minor.yy9 = yylhsminor.yy9; - break; - case 25: /* columnname ::= nm typetoken */ -{sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} - break; - case 26: /* typetoken ::= */ - case 65: /* conslist_opt ::= */ yytestcase(yyruleno==65); - case 106: /* as ::= */ yytestcase(yyruleno==106); -{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} - break; - 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 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 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 30: /* scanpt ::= */ -{ - assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy342 = yyLookaheadToken.z; -} - break; - case 31: /* scantok ::= */ -{ - assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy0 = yyLookaheadToken; -} - break; - case 32: /* ccons ::= CONSTRAINT nm */ - case 67: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67); -{ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;} - break; - case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} - break; - case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} - break; - case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} - break; - case 36: /* ccons ::= DEFAULT MINUS scantok term */ -{ - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0); - sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); -} - break; - case 37: /* ccons ::= DEFAULT scantok ID|INDEXED */ -{ - Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); - if( p ){ - sqlite3ExprIdToTrueFalse(p); - testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); - } - sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); -} - break; - case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);} - break; - case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);} - break; - case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0, - SQLITE_IDXTYPE_UNIQUE);} - break; - case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} - break; - case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);} - break; - case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);} - break; - case 44: /* ccons ::= COLLATE ID|STRING */ -{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} - break; - case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);} - break; - case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);} - break; - case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy502 = 1;} - break; - case 49: /* refargs ::= */ -{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */} - break; - case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; } - break; - case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; } - break; - case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; } - break; - case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; } - break; - case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; } - break; - case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */} - break; - case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */} - break; - case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */} - break; - case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */} - break; - case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */} - break; - case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy502 = 0;} - break; - case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); - case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173); -{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;} - break; - case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); - case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); - case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); - case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); -{yymsp[-1].minor.yy502 = 1;} - break; - case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy502 = 0;} - break; - case 66: /* tconscomma ::= COMMA */ -{ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;} - break; - case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} - break; - case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0, - SQLITE_IDXTYPE_UNIQUE);} - break; - case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} - break; - case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ -{ - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502); -} - break; - case 73: /* onconf ::= */ - case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy502 = OE_Default;} - break; - case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;} - break; - case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy502 = OE_Ignore;} - break; - case 78: /* resolvetype ::= REPLACE */ - case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174); -{yymsp[0].minor.yy502 = OE_Replace;} - break; - case 79: /* cmd ::= DROP TABLE ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502); -} - break; - case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ -{ - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502); -} - break; - case 83: /* cmd ::= DROP VIEW ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502); -} - break; - case 84: /* cmd ::= select */ -{ - SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0 - || sqlite3ReadSchema(pParse)==SQLITE_OK - ){ - sqlite3Select(pParse, yymsp[0].minor.yy637, &dest); - } - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); -} - break; - case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} - break; - case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} - break; - case 87: /* select ::= selectnowith */ -{ - Select *p = yymsp[0].minor.yy637; - if( p ){ - parserDoubleLinkSelect(pParse, p); - } -} - break; - case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ -{ - Select *pRhs = yymsp[0].minor.yy637; - Select *pLhs = yymsp[-2].minor.yy637; - if( pRhs && pRhs->pPrior ){ - SrcList *pFrom; - Token x; - x.n = 0; - parserDoubleLinkSelect(pParse, pRhs); - pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0); - pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); - } - if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy502; - pRhs->pPrior = pLhs; - if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue; - pRhs->selFlags &= ~(u32)SF_MultiValue; - if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; - }else{ - sqlite3SelectDelete(pParse->db, pLhs); - } - yymsp[-2].minor.yy637 = pRhs; -} - break; - case 89: /* multiselect_op ::= UNION */ - case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/} - break; - case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy502 = TK_ALL;} - break; - case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ -{ - yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590); -} - break; - case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ -{ - yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590); - if( yymsp[-9].minor.yy637 ){ - yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483; - }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483); - } -} - break; - case 94: /* values ::= VALUES LP nexprlist RP */ -{ - yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0); -} - break; - case 95: /* oneselect ::= mvalues */ -{ - sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637); -} - break; - case 96: /* mvalues ::= values COMMA LP nexprlist RP */ - case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97); -{ - yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402); -} - break; - case 98: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy502 = SF_Distinct;} - break; - case 99: /* distinct ::= ALL */ -{yymsp[0].minor.yy502 = SF_All;} - break; - case 101: /* sclp ::= */ - case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134); - case 144: /* groupby_opt ::= */ yytestcase(yyruleno==144); - case 234: /* exprlist ::= */ yytestcase(yyruleno==234); - case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237); - case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242); -{yymsp[1].minor.yy402 = 0;} - break; - case 102: /* selcollist ::= sclp scanpt expr scanpt as */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342); -} - break; - case 103: /* selcollist ::= sclp scanpt STAR */ -{ - Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p); -} - break; - case 104: /* selcollist ::= sclp scanpt nm DOT STAR */ -{ - Expr *pRight, *pLeft, *pDot; - pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); - pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot); -} - break; - case 105: /* as ::= AS nm */ - case 117: /* dbnm ::= DOT nm */ yytestcase(yyruleno==117); - case 258: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==258); - case 259: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==259); -{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} - break; - case 107: /* from ::= */ - case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110); -{yymsp[1].minor.yy563 = 0;} - break; - case 108: /* from ::= FROM seltablist */ -{ - yymsp[-1].minor.yy563 = yymsp[0].minor.yy563; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563); -} - break; - case 109: /* stl_prefix ::= seltablist joinop */ -{ - if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502; -} - break; - case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */ -{ - yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); -} - break; - case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ -{ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0); -} - break; - case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ -{ - yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402); -} - break; - case 114: /* seltablist ::= stl_prefix LP select RP as on_using */ -{ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421); - } - break; - case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ -{ - if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){ - yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563; - }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); - if( yymsp[-5].minor.yy563 ){ - SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1]; - SrcItem *pOld = yymsp[-3].minor.yy563->a; - assert( pOld->fg.fixedSchema==0 ); - pNew->zName = pOld->zName; - assert( pOld->fg.fixedSchema==0 ); - if( pOld->fg.isSubquery ){ - pNew->fg.isSubquery = 1; - pNew->u4.pSubq = pOld->u4.pSubq; - pOld->u4.pSubq = 0; - pOld->fg.isSubquery = 0; - assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 ); - if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){ - pNew->fg.isNestedFrom = 1; - } - }else{ - pNew->u4.zDatabase = pOld->u4.zDatabase; - pOld->u4.zDatabase = 0; - } - if( pOld->fg.isTabFunc ){ - pNew->u1.pFuncArg = pOld->u1.pFuncArg; - pOld->u1.pFuncArg = 0; - pOld->fg.isTabFunc = 0; - pNew->fg.isTabFunc = 1; - } - pOld->zName = 0; - } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563); - }else{ - Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421); - } - } - break; - case 116: /* dbnm ::= */ - case 131: /* indexed_opt ::= */ yytestcase(yyruleno==131); -{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} - break; - case 118: /* fullname ::= nm */ -{ - yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); -} - yymsp[0].minor.yy563 = yylhsminor.yy563; - break; - case 119: /* fullname ::= nm DOT nm */ -{ - yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); -} - yymsp[-2].minor.yy563 = yylhsminor.yy563; - break; - case 120: /* xfullname ::= nm */ -{yymsp[0].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} - break; - case 121: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 122: /* xfullname ::= nm DOT nm AS nm */ -{ - yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); -} - break; - case 123: /* xfullname ::= nm AS nm */ -{ - yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); -} - break; - case 124: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy502 = JT_INNER; } - break; - case 125: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} - break; - case 126: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} - break; - case 127: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} - break; - case 128: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;} - break; - case 129: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;} - break; - case 130: /* on_using ::= */ -{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;} - break; - case 132: /* indexed_by ::= INDEXED BY nm */ -{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} - break; - case 133: /* indexed_by ::= NOT INDEXED */ -{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} - break; - case 135: /* orderby_opt ::= ORDER BY sortlist */ - case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145); -{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;} - break; - case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); -} - break; - case 137: /* sortlist ::= expr sortorder nulls */ -{ - yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); -} - break; - case 138: /* sortorder ::= ASC */ -{yymsp[0].minor.yy502 = SQLITE_SO_ASC;} - break; - case 139: /* sortorder ::= DESC */ -{yymsp[0].minor.yy502 = SQLITE_SO_DESC;} - break; - case 140: /* sortorder ::= */ - case 143: /* nulls ::= */ yytestcase(yyruleno==143); -{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;} - break; - case 141: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;} - break; - case 142: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;} - break; - case 146: /* having_opt ::= */ - case 148: /* limit_opt ::= */ yytestcase(yyruleno==148); - case 153: /* where_opt ::= */ yytestcase(yyruleno==153); - case 155: /* where_opt_ret ::= */ yytestcase(yyruleno==155); - case 232: /* case_else ::= */ yytestcase(yyruleno==232); - case 233: /* case_operand ::= */ yytestcase(yyruleno==233); - case 252: /* vinto ::= */ yytestcase(yyruleno==252); -{yymsp[1].minor.yy590 = 0;} - break; - case 147: /* having_opt ::= HAVING expr */ - case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154); - case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156); - case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); - case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251); -{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;} - break; - case 149: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);} - break; - case 150: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 151: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);} - break; - case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy563, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy563,yymsp[0].minor.yy590,0,0); -} - break; - case 157: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;} - break; - case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;} - break; - case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy402,"set list"); - if( yymsp[-1].minor.yy563 ){ - SrcList *pFromClause = yymsp[-1].minor.yy563; - if( pFromClause->nSrc>1 ){ - Select *pSubquery; - Token as; - pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0); - as.n = 0; - as.z = 0; - pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); - } - yymsp[-5].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy563, pFromClause); - } - sqlite3Update(pParse,yymsp[-5].minor.yy563,yymsp[-2].minor.yy402,yymsp[0].minor.yy590,yymsp[-6].minor.yy502,0,0,0); -} - break; - case 160: /* setlist ::= setlist COMMA nm EQ expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1); -} - break; - case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ -{ - yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); -} - break; - case 162: /* setlist ::= nm EQ expr */ -{ - yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590); - sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1); -} - yymsp[-2].minor.yy402 = yylhsminor.yy402; - break; - case 163: /* setlist ::= LP idlist RP EQ expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); -} - break; - case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ -{ - sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403); -} - break; - case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ -{ - sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0); -} - break; - case 166: /* upsert ::= */ -{ yymsp[1].minor.yy403 = 0; } - break; - case 167: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); } - break; - case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);} - break; - case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); } - break; - case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } - break; - case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);} - break; - case 172: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);} - break; - case 175: /* idlist_opt ::= */ -{yymsp[1].minor.yy204 = 0;} - break; - case 176: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;} - break; - case 177: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);} - break; - case 178: /* idlist ::= nm */ -{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} - break; - case 179: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;} - break; - case 180: /* expr ::= ID|INDEXED|JOIN_KW */ -{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 181: /* expr ::= nm DOT nm */ -{ - Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); - Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); - yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); -} - yymsp[-2].minor.yy590 = yylhsminor.yy590; - break; - case 182: /* expr ::= nm DOT nm DOT nm */ -{ - 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 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, 0, temp1); - } - yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 183: /* term ::= NULL|FLOAT|BLOB */ - case 184: /* term ::= STRING */ yytestcase(yyruleno==184); -{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 185: /* term ::= INTEGER */ -{ - yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); - if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; - break; - case 186: /* expr ::= VARIABLE */ -{ - if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ - u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, 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 - ** in the virtual machine. #N is the N-th register. */ - Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ - assert( t.n>=2 ); - if( pParse->nested==0 ){ - parserSyntaxError(pParse, &t); - yymsp[0].minor.yy590 = 0; - }else{ - yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable); - } - } -} - break; - case 187: /* expr ::= expr COLLATE ID|STRING */ -{ - yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1); -} - break; - case 188: /* expr ::= CAST LP expr AS typetoken RP */ -{ - yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0); -} - break; - case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402); -} - yymsp[-7].minor.yy590 = yylhsminor.yy590; - break; - case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); -} - yymsp[-3].minor.yy590 = yylhsminor.yy590; - break; - case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); -} - yymsp[-5].minor.yy590 = yylhsminor.yy590; - break; - case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402); -} - yymsp[-8].minor.yy590 = yylhsminor.yy590; - break; - case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 195: /* term ::= CTIME_KW */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; - break; - case 196: /* expr ::= LP nexprlist COMMA expr RP */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = pList; - if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate; - } - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } -} - break; - case 197: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 198: /* expr ::= expr OR expr */ - case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199); - case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200); - case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201); - case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204); -{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 205: /* 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 206: /* expr ::= expr likeop expr */ -{ - ExprList *pList; - int bNot = yymsp[-1].minor.yy0.n & 0x80000000; - yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590); - yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0); - if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc; -} - break; - case 207: /* expr ::= expr likeop expr ESCAPE expr */ -{ - ExprList *pList; - int bNot = yymsp[-3].minor.yy0.n & 0x80000000; - yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc; -} - break; - case 208: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);} - break; - case 209: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);} - break; - case 210: /* expr ::= expr IS expr */ -{ - yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL); -} - break; - case 211: /* expr ::= expr IS NOT expr */ -{ - yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL); -} - break; - case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */ -{ - yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL); -} - break; - case 213: /* expr ::= expr IS DISTINCT FROM expr */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL); -} - break; - case 214: /* expr ::= NOT expr */ - case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/} - break; - case 216: /* expr ::= PLUS|MINUS expr */ -{ - Expr *p = yymsp[0].minor.yy590; - u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS); - assert( TK_UPLUS>TK_PLUS ); - assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) ); - if( p && p->op==TK_UPLUS ){ - p->op = op; - yymsp[-1].minor.yy590 = p; - }else{ - yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0); - /*A-overwrites-B*/ - } -} - break; - case 217: /* expr ::= expr PTR expr */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590); - yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); -} - yymsp[-2].minor.yy590 = yylhsminor.yy590; - break; - case 218: /* between_op ::= BETWEEN */ - case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); -{yymsp[0].minor.yy502 = 0;} - break; - case 220: /* expr ::= expr between_op expr AND expr */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = pList; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); -} - break; - case 223: /* expr ::= expr in_op LP exprlist RP */ -{ - if( yymsp[-1].minor.yy402==0 ){ - /* Expressions of the form - ** - ** expr1 IN () - ** expr1 NOT IN () - ** - ** simplify to constants 0 (false) and 1 (true), respectively. - ** - ** Except, do not apply this optimization if expr1 contains a function - ** because that function might be an aggregate (we don't know yet whether - ** it is or not) and if it is an aggregate, that could change the meaning - ** of the whole query. - */ - Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false"); - if( pB ) sqlite3ExprIdToTrueFalse(pB); - if( !ExprHasProperty(yymsp[-4].minor.yy590, EP_HasFunc) ){ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590); - yymsp[-4].minor.yy590 = pB; - }else{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy590); - } - }else{ - Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr; - if( yymsp[-1].minor.yy402->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy590->op!=TK_VECTOR ){ - yymsp[-1].minor.yy402->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS); - }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect); - pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - }else{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - }else if( yymsp[-4].minor.yy590->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy590->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy402); - if( pSelectRHS ){ - parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS); - } - }else{ - yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); - } - } - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - } - break; - case 224: /* expr ::= LP select RP */ -{ - yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637); - } - break; - case 225: /* expr ::= expr in_op LP select RP */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637); - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - break; - case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */ -{ - SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); - Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect); - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - break; - case 227: /* expr ::= EXISTS LP select RP */ -{ - Expr *p; - p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637); - } - break; - case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); - } -} - break; - case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590); -} - break; - case 230: /* case_exprlist ::= WHEN expr THEN expr */ -{ - yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590); -} - break; - case 235: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);} - break; - case 236: /* nexprlist ::= expr */ -{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/} - break; - case 238: /* paren_exprlist ::= LP exprlist RP */ - case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243); -{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;} - break; - case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ -{ - sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF); - if( IN_RENAME_OBJECT && pParse->pNewIndex ){ - sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); - } -} - break; - case 240: /* uniqueflag ::= UNIQUE */ - case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282); -{yymsp[0].minor.yy502 = OE_Abort;} - break; - case 241: /* uniqueflag ::= */ -{yymsp[1].minor.yy502 = OE_None;} - break; - case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */ -{ - yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); -} - break; - case 245: /* eidlist ::= nm collate sortorder */ -{ - yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/ -} - break; - case 248: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);} - break; - case 249: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);} - break; - case 250: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);} - break; - case 253: /* cmd ::= PRAGMA nm dbnm */ -{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} - break; - case 254: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} - break; - case 255: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} - break; - case 256: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} - break; - case 257: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} - break; - case 260: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ -{ - Token all; - all.z = yymsp[-3].minor.yy0.z; - all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all); -} - break; - case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ -{ - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); - yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ -#ifdef SQLITE_DEBUG - assert( pParse->isCreate ); /* Set by createkw reduce action */ - pParse->isCreate = 0; /* But, should not be set for CREATE TRIGGER */ -#endif -} - break; - case 262: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } - break; - case 263: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy502 = TK_INSTEAD;} - break; - case 264: /* trigger_time ::= */ -{ yymsp[1].minor.yy502 = TK_BEFORE; } - break; - case 265: /* trigger_event ::= DELETE|INSERT */ - case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266); -{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;} - break; - case 267: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;} - break; - case 268: /* when_clause ::= */ - case 287: /* key_opt ::= */ yytestcase(yyruleno==287); -{ yymsp[1].minor.yy590 = 0; } - break; - case 269: /* when_clause ::= WHEN expr */ - case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288); -{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; } - break; - case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ -{ - assert( yymsp[-2].minor.yy319!=0 ); - yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319; - yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319; -} - break; - case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */ -{ - assert( yymsp[-1].minor.yy319!=0 ); - yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319; -} - break; - case 272: /* trnm ::= nm DOT nm */ -{ - yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; - sqlite3ErrorMsg(pParse, - "qualified table names are not allowed on INSERT, UPDATE, and DELETE " - "statements within triggers"); -} - break; - case 273: /* tridxby ::= INDEXED BY nm */ -{ - sqlite3ErrorMsg(pParse, - "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " - "within triggers"); -} - break; - case 274: /* tridxby ::= NOT INDEXED */ -{ - sqlite3ErrorMsg(pParse, - "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " - "within triggers"); -} - break; - case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);} - yymsp[-8].minor.yy319 = yylhsminor.yy319; - break; - case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ -{ - yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/ -} - yymsp[-7].minor.yy319 = yylhsminor.yy319; - break; - case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);} - yymsp[-5].minor.yy319 = yylhsminor.yy319; - break; - case 278: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/} - yymsp[-2].minor.yy319 = yylhsminor.yy319; - break; - case 279: /* expr ::= RAISE LP IGNORE RP */ -{ - yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy590 ){ - yymsp[-3].minor.yy590->affExpr = OE_Ignore; - } -} - break; - case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */ -{ - yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0); - if( yymsp[-5].minor.yy590 ) { - yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502; - } -} - break; - case 281: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy502 = OE_Rollback;} - break; - case 283: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy502 = OE_Fail;} - break; - case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ -{ - sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502); -} - break; - case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ -{ - sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590); -} - break; - case 286: /* cmd ::= DETACH database_kw_opt expr */ -{ - sqlite3Detach(pParse, yymsp[0].minor.yy590); -} - break; - case 289: /* cmd ::= REINDEX */ -{sqlite3Reindex(pParse, 0, 0);} - break; - case 290: /* cmd ::= REINDEX nm dbnm */ -{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} - break; - case 291: /* cmd ::= ANALYZE */ -{sqlite3Analyze(pParse, 0, 0);} - break; - case 292: /* cmd ::= ANALYZE nm dbnm */ -{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} - break; - case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ -{ - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0); -} - break; - case 294: /* 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; - sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); -} - break; - case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ -{ - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0); -} - break; - case 296: /* add_column_fullname ::= fullname */ -{ - disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563); -} - break; - case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ -{ - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 298: /* cmd ::= create_vtab */ -{sqlite3VtabFinishParse(pParse,0);} - break; - case 299: /* cmd ::= create_vtab LP vtabarglist RP */ -{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} - break; - case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ -{ - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502); -} - break; - case 301: /* vtabarg ::= */ -{sqlite3VtabArgInit(pParse);} - break; - case 302: /* vtabargtoken ::= ANY */ - case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303); - case 304: /* lp ::= LP */ yytestcase(yyruleno==304); -{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} - break; - case 305: /* with ::= WITH wqlist */ - case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); } - break; - case 307: /* wqas ::= AS */ -{yymsp[0].minor.yy444 = M10d_Any;} - break; - case 308: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy444 = M10d_Yes;} - break; - case 309: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy444 = M10d_No;} - break; - case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ -{ - yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/ -} - break; - case 311: /* withnm ::= nm */ -{pParse->bHasWith = 1;} - break; - case 312: /* wqlist ::= wqitem */ -{ - yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/ -} - break; - case 313: /* wqlist ::= wqlist COMMA wqitem */ -{ - yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361); -} - break; - case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ -{ - assert( yymsp[0].minor.yy483!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483); - yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483; - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[-2].minor.yy483 = yylhsminor.yy483; - break; - case 315: /* windowdefn ::= nm AS LP window RP */ -{ - if( ALWAYS(yymsp[-1].minor.yy483) ){ - yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); - } - yylhsminor.yy483 = yymsp[-1].minor.yy483; -} - yymsp[-4].minor.yy483 = yylhsminor.yy483; - break; - case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ -{ - yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0); -} - break; - case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0); -} - yymsp[-5].minor.yy483 = yylhsminor.yy483; - break; - case 318: /* window ::= ORDER BY sortlist frame_opt */ -{ - yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0); -} - break; - case 319: /* window ::= nm ORDER BY sortlist frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0); -} - yymsp[-4].minor.yy483 = yylhsminor.yy483; - break; - case 320: /* window ::= nm frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0); -} - yymsp[-1].minor.yy483 = yylhsminor.yy483; - break; - case 321: /* frame_opt ::= */ -{ - yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); -} - break; - case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444); -} - yymsp[-2].minor.yy483 = yylhsminor.yy483; - break; - case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444); -} - yymsp[-5].minor.yy483 = yylhsminor.yy483; - break; - case 325: /* frame_bound_s ::= frame_bound */ - case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327); -{yylhsminor.yy205 = yymsp[0].minor.yy205;} - yymsp[0].minor.yy205 = yylhsminor.yy205; - break; - case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328); - case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330); -{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;} - yymsp[-1].minor.yy205 = yylhsminor.yy205; - break; - case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;} - yymsp[-1].minor.yy205 = yylhsminor.yy205; - break; - case 331: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy444 = 0;} - break; - case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;} - break; - case 333: /* frame_exclude ::= NO OTHERS */ - case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334); -{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/} - break; - case 335: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/} - break; - case 336: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; } - break; - case 337: /* filter_over ::= filter_clause over_clause */ -{ - if( yymsp[0].minor.yy483 ){ - yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590; - }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); - } - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[-1].minor.yy483 = yylhsminor.yy483; - break; - case 338: /* filter_over ::= over_clause */ -{ - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[0].minor.yy483 = yylhsminor.yy483; - break; - case 339: /* filter_over ::= filter_clause */ -{ - yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy483 ){ - yylhsminor.yy483->eFrmType = TK_FILTER; - yylhsminor.yy483->pFilter = yymsp[0].minor.yy590; - }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590); - } -} - yymsp[0].minor.yy483 = yylhsminor.yy483; - break; - case 340: /* over_clause ::= OVER LP window RP */ -{ - yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483; - assert( yymsp[-3].minor.yy483!=0 ); -} - break; - case 341: /* over_clause ::= OVER nm */ -{ - yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy483 ){ - yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); - } -} - break; - case 342: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; } - break; - case 343: /* term ::= QNUMBER */ -{ - yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); - sqlite3DequoteNumber(pParse, yylhsminor.yy590); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; - break; - default: - /* (344) input ::= cmdlist */ yytestcase(yyruleno==344); - /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345); - /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346); - /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347); - /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348); - /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349); - /* (350) trans_opt ::= */ yytestcase(yyruleno==350); - /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351); - /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352); - /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353); - /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354); - /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355); - /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356); - /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357); - /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358); - /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359); - /* (360) nm ::= STRING */ yytestcase(yyruleno==360); - /* (361) typetoken ::= typename */ yytestcase(yyruleno==361); - /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362); - /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); - /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364); - /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365); - /* (366) carglist ::= */ yytestcase(yyruleno==366); - /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367); - /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368); - /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369); - /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370); - /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371); - /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372); - /* (373) tconscomma ::= */ yytestcase(yyruleno==373); - /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374); - /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375); - /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) oneselect ::= values */ yytestcase(yyruleno==377); - /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378); - /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379); - /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) returning ::= */ yytestcase(yyruleno==381); - /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382); - /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383); - /* (384) case_operand ::= expr */ yytestcase(yyruleno==384); - /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385); - /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386); - /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387); - /* (388) nmnum ::= ON */ yytestcase(yyruleno==388); - /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389); - /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390); - /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391); - /* (392) foreach_clause ::= */ yytestcase(yyruleno==392); - /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393); - /* (394) trnm ::= nm */ yytestcase(yyruleno==394); - /* (395) tridxby ::= */ yytestcase(yyruleno==395); - /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396); - /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397); - /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398); - /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399); - /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400); - /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401); - /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402); - /* (403) anylist ::= */ yytestcase(yyruleno==403); - /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404); - /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405); - /* (406) with ::= */ yytestcase(yyruleno==406); - /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407); - /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408); - break; -/********** End reduce actions ************************************************/ - }; - assert( yyrulenoYY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) ); - - /* It is not possible for a REDUCE to be followed by an error */ - assert( yyact!=YY_ERROR_ACTION ); - - yymsp += yysize+1; - yypParser->yytos = yymsp; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact, "... then shift"); - return yyact; -} - -/* -** The following code executes when the parse fails -*/ -#ifndef YYNOERRORRECOVERY -static void yy_parse_failed( - yyParser *yypParser /* The parser */ -){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); - } -#endif - while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser fails */ -/************ Begin %parse_failure code ***************************************/ -/************ End %parse_failure code *****************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE -} -#endif /* YYNOERRORRECOVERY */ - -/* -** The following code executes when a syntax error first occurs. -*/ -static void yy_syntax_error( - yyParser *yypParser, /* The parser */ - int yymajor, /* The major type of the error token */ - sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ -){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH -#define TOKEN yyminor -/************ Begin %syntax_error code ****************************************/ - - UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ - if( TOKEN.z[0] ){ - parserSyntaxError(pParse, &TOKEN); - }else{ - sqlite3ErrorMsg(pParse, "incomplete input"); - } -/************ End %syntax_error code ******************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE -} - -/* -** The following is executed when the parser accepts -*/ -static void yy_accept( - yyParser *yypParser /* The parser */ -){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); - } -#endif -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - assert( yypParser->yytos==yypParser->yystack ); - /* Here code is inserted which will be executed whenever the - ** parser accepts */ -/*********** Begin %parse_accept code *****************************************/ -/*********** End %parse_accept code *******************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE -} - -/* The main parser program. -** The first argument is a pointer to a structure obtained from -** "sqlite3ParserAlloc" which describes the current state of the parser. -** The second argument is the major token number. The third is -** the minor token. The fourth optional argument is whatever the -** user wants (and specified in the grammar) and is available for -** use by the action routines. -** -** Inputs: -**
      -**
    • A pointer to the parser (an opaque structure.) -**
    • The major token number. -**
    • The minor token number. -**
    • An option argument of a grammar-specified type. -**
    -** -** Outputs: -** None. -*/ -SQLITE_PRIVATE void sqlite3Parser( - void *yyp, /* The parser */ - int yymajor, /* The major token code number */ - sqlite3ParserTOKENTYPE yyminor /* The value for the token */ - sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ -){ - YYMINORTYPE yyminorunion; - YYACTIONTYPE yyact; /* The parser action. */ -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - int yyendofinput; /* True if we are at the end of input */ -#endif -#ifdef YYERRORSYMBOL - int yyerrorhit = 0; /* True if yymajor has invoked an error */ -#endif - yyParser *yypParser = (yyParser*)yyp; /* The parser */ - sqlite3ParserCTX_FETCH - sqlite3ParserARG_STORE - - assert( yypParser->yytos!=0 ); -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - yyendofinput = (yymajor==0); -#endif - - yyact = yypParser->yytos->stateno; -#ifndef NDEBUG - if( yyTraceFILE ){ - if( yyact < YY_MIN_REDUCE ){ - fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact); - }else{ - fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); - } - } -#endif - - 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 ){ - 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], - yyrulenoyytos[yysize].stateno); - }else{ - fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n", - yyTracePrompt, yyruleno, yyRuleName[yyruleno], - yyrulenoyytos - yypParser->yystack)>yypParser->yyhwm ){ - yypParser->yyhwm++; - assert( yypParser->yyhwm == - (int)(yypParser->yytos - yypParser->yystack)); - } -#endif - if( yypParser->yytos>=yypParser->yystackEnd ){ - if( yyGrowStack(yypParser) ){ - yyStackOverflow(yypParser); - break; - } - } - } - yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor sqlite3ParserCTX_PARAM); - }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt--; -#endif - break; - }else if( yyact==YY_ACCEPT_ACTION ){ - yypParser->yytos--; - yy_accept(yypParser); - return; - }else{ - assert( yyact == YY_ERROR_ACTION ); - yyminorunion.yy0 = yyminor; -#ifdef YYERRORSYMBOL - int yymx; -#endif -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); - } -#endif -#ifdef YYERRORSYMBOL - /* A syntax error has occurred. - ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". - ** - ** This is what we do if the grammar does define ERROR: - ** - ** * Call the %syntax_error function. - ** - ** * Begin popping the stack until we enter a state where - ** it is legal to shift the error symbol, then shift - ** the error symbol. - ** - ** * Set the error count to three. - ** - ** * Begin accepting and shifting new tokens. No new error - ** processing will occur until three tokens have been - ** shifted successfully. - ** - */ - if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminor); - } - yymx = yypParser->yytos->major; - if( yymx==YYERRORSYMBOL || yyerrorhit ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sDiscard input token %s\n", - yyTracePrompt,yyTokenName[yymajor]); - } -#endif - yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); - yymajor = YYNOCODE; - }else{ - 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 ){ - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yy_parse_failed(yypParser); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yymajor = YYNOCODE; - }else if( yymx!=YYERRORSYMBOL ){ - yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); - } - } - yypParser->yyerrcnt = 3; - yyerrorhit = 1; - if( yymajor==YYNOCODE ) break; - yyact = yypParser->yytos->stateno; -#elif defined(YYNOERRORRECOVERY) - /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to - ** do any kind of error recovery. Instead, simply invoke the syntax - ** error routine and continue going as if nothing had happened. - ** - ** Applications can set this macro (for example inside %include) if - ** they intend to abandon the parse upon the first syntax error seen. - */ - yy_syntax_error(yypParser,yymajor, yyminor); - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - break; -#else /* YYERRORSYMBOL is not defined */ - /* This is what we do if the grammar does not define ERROR: - ** - ** * Report an error message, and throw away the input token. - ** - ** * If the input token is $, then fail the parse. - ** - ** As before, subsequent error messages are suppressed until - ** three input tokens have been successfully shifted. - */ - if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor, yyminor); - } - yypParser->yyerrcnt = 3; - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - if( yyendofinput ){ - yy_parse_failed(yypParser); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - } - break; -#endif - } - } -#ifndef NDEBUG - if( yyTraceFILE ){ - yyStackEntry *i; - char cDiv = '['; - fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ - fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); - cDiv = ' '; - } - fprintf(yyTraceFILE,"]\n"); - } -#endif - return; -} - -/* -** Return the fallback token corresponding to canonical token iToken, or -** 0 if iToken has no fallback. -*/ -SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){ -#ifdef YYFALLBACK - assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); - return yyFallback[iToken]; -#else - (void)iToken; - return 0; -#endif -} - -/************** End of parse.c ***********************************************/ -/************** Begin file tokenize.c ****************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** An tokenizer for SQL -** -** This file contains C code that splits an SQL input string up into -** individual tokens and sends those tokens one-by-one over to the -** parser for analysis. -*/ -/* #include "sqliteInt.h" */ -/* #include */ - -/* Character classes for tokenizing -** -** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented -** using a lookup table, whereas a switch() directly on c uses a binary search. -** The lookup table is much faster. To maximize speed, and to ensure that -** a lookup table is used, all of the classes need to be small integers and -** all of them need to be used within the switch. -*/ -#define CC_X 0 /* The letter 'x', or start of BLOB literal */ -#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 */ -#define CC_VARNUM 6 /* '?'. Numeric SQL variables */ -#define CC_SPACE 7 /* Space characters */ -#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ -#define CC_QUOTE2 9 /* '['. [...] style quoted ids */ -#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */ -#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */ -#define CC_LT 12 /* '<'. Part of < or <= or <> */ -#define CC_GT 13 /* '>'. Part of > or >= */ -#define CC_EQ 14 /* '='. Part of = or == */ -#define CC_BANG 15 /* '!'. Part of != */ -#define CC_SLASH 16 /* '/'. / or c-style comment */ -#define CC_LP 17 /* '(' */ -#define CC_RP 18 /* ')' */ -#define CC_SEMI 19 /* ';' */ -#define CC_PLUS 20 /* '+' */ -#define CC_STAR 21 /* '*' */ -#define CC_PERCENT 22 /* '%' */ -#define CC_COMMA 23 /* ',' */ -#define CC_AND 24 /* '&' */ -#define CC_TILDA 25 /* '~' */ -#define CC_DOT 26 /* '.' */ -#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 */ 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, 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, 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 */ 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 -}; - -/* -** The charMap() macro maps alphabetic characters (only) into their -** lower-case ASCII equivalent. On ASCII machines, this is just -** an upper-to-lower case map. On EBCDIC machines we also need -** to adjust the encoding. The mapping is only valid for alphabetics -** which are the only characters for which this feature is used. -** -** Used by keywordhash.h -*/ -#ifdef SQLITE_ASCII -# define charMap(X) sqlite3UpperToLower[(unsigned char)X] -#endif -#ifdef SQLITE_EBCDIC -# define charMap(X) ebcdicToAscii[(unsigned char)X] -const unsigned char ebcdicToAscii[] = { -/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */ - 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */ - 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */ - 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */ - 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */ -}; -#endif - -/* -** The sqlite3KeywordCode function looks up an identifier to determine if -** it is a keyword. If it is a keyword, the token code of that keyword is -** returned. If the input is not a keyword, TK_ID is returned. -** -** The implementation of this routine was generated by a program, -** mkkeywordhash.c, located in the tool subdirectory of the distribution. -** The output of the mkkeywordhash.c program is written into a file -** named keywordhash.h and then included into this source file by -** the #include below. -*/ -/************** Include keywordhash.h in the middle of tokenize.c ************/ -/************** Begin file keywordhash.h *************************************/ -/***** This file contains automatically generated code ****** -** -** The code in this file has been automatically generated by -** -** sqlite/tool/mkkeywordhash.c -** -** The code in this file implements a function that determines whether -** or not a given identifier is really an SQL keyword. The same thing -** might be implemented more directly using a hand-written hash table. -** But by using this automatically generated code, the size of the code -** is substantially reduced. This is important for embedded applications -** on platforms with limited memory. -*/ -/* Hash score: 231 */ -/* zKWText[] encodes 1007 bytes of keyword text in 667 bytes */ -/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ -/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */ -/* IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS */ -/* CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES */ -/* UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT */ -/* CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE */ -/* 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', - 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', - 'E','R','R','A','B','L','E','L','S','E','X','C','L','U','D','E','L','E', - 'T','E','M','P','O','R','A','R','Y','I','S','N','U','L','L','S','A','V', - 'E','P','O','I','N','T','E','R','S','E','C','T','I','E','S','N','O','T', - 'N','U','L','L','I','K','E','X','C','E','P','T','R','A','N','S','A','C', - 'T','I','O','N','A','T','U','R','A','L','T','E','R','A','I','S','E','X', - 'C','L','U','S','I','V','E','X','I','S','T','S','C','O','N','S','T','R', - 'A','I','N','T','O','F','F','S','E','T','R','I','G','G','E','R','A','N', - 'G','E','N','E','R','A','T','E','D','E','T','A','C','H','A','V','I','N', - 'G','L','O','B','E','G','I','N','N','E','R','E','F','E','R','E','N','C', - 'E','S','U','N','I','Q','U','E','R','Y','W','I','T','H','O','U','T','E', - 'R','E','L','E','A','S','E','A','T','T','A','C','H','B','E','T','W','E', - 'E','N','O','T','H','I','N','G','R','O','U','P','S','C','A','S','C','A', - 'D','E','F','A','U','L','T','C','A','S','E','C','O','L','L','A','T','E', - 'C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E', - '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','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, 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[148] = {0, - 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, 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[148] = {0, - 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, 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[148] = {0, - 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, 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[148] = {0, - 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, - TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, - TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, - TK_EXCLUDE, TK_DELETE, TK_TEMP, TK_TEMP, TK_OR, - TK_ISNULL, TK_NULLS, TK_SAVEPOINT, TK_INTERSECT, TK_TIES, - TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, - TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, - TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_CONSTRAINT, - TK_INTO, TK_OFFSET, TK_OF, TK_SET, TK_TRIGGER, - TK_RANGE, TK_GENERATED, TK_DETACH, TK_HAVING, TK_LIKE_KW, - TK_BEGIN, TK_JOIN_KW, TK_REFERENCES, TK_UNIQUE, TK_QUERY, - TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH, - 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_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 -** 1: IS -** 2: ROLLBACK TRIGGER -** 3: IMMEDIATE -** 4: PARTITION -** 5: TEMP -** 6: -** 7: -** 8: VALUES WITHOUT -** 9: -** 10: MATCH -** 11: NOTHING -** 12: -** 13: OF -** 14: TIES IGNORE -** 15: PLAN -** 16: INSTEAD INDEXED -** 17: -** 18: TRANSACTION RIGHT -** 19: WHEN -** 20: SET HAVING -** 21: MATERIALIZED IF -** 22: ROWS -** 23: SELECT -** 24: -** 25: -** 26: VACUUM SAVEPOINT -** 27: -** 28: LIKE UNION VIRTUAL REFERENCES -** 29: RESTRICT -** 30: -** 31: THEN REGEXP -** 32: TO -** 33: -** 34: BEFORE -** 35: -** 36: -** 37: FOLLOWING COLLATE CASCADE -** 38: CREATE -** 39: -** 40: CASE REINDEX -** 41: EACH -** 42: -** 43: QUERY -** 44: AND ADD -** 45: PRIMARY ANALYZE -** 46: -** 47: ROW ASC DETACH -** 48: CURRENT_TIME CURRENT_DATE -** 49: -** 50: -** 51: EXCLUSIVE TEMPORARY -** 52: -** 53: DEFERRED -** 54: DEFERRABLE -** 55: -** 56: DATABASE -** 57: -** 58: DELETE VIEW GENERATED -** 59: ATTACH -** 60: END -** 61: EXCLUDE -** 62: ESCAPE DESC -** 63: GLOB -** 64: WINDOW ELSE -** 65: COLUMN -** 66: FIRST -** 67: -** 68: GROUPS ALL -** 69: DISTINCT DROP KEY -** 70: BETWEEN -** 71: INITIALLY -** 72: BEGIN -** 73: FILTER CHECK ACTION -** 74: GROUP INDEX -** 75: -** 76: EXISTS DEFAULT -** 77: -** 78: FOR CURRENT_TIMESTAMP -** 79: EXCEPT -** 80: -** 81: CROSS -** 82: -** 83: -** 84: -** 85: CAST -** 86: FOREIGN AUTOINCREMENT -** 87: COMMIT -** 88: CURRENT AFTER ALTER -** 89: FULL FAIL CONFLICT -** 90: EXPLAIN -** 91: CONSTRAINT -** 92: FROM ALWAYS -** 93: -** 94: ABORT -** 95: -** 96: AS DO -** 97: REPLACE WITH RELEASE -** 98: BY RENAME -** 99: RANGE RAISE -** 100: OTHERS -** 101: USING NULLS -** 102: PRAGMA -** 103: JOIN ISNULL OFFSET -** 104: NOT -** 105: OR LAST LEFT -** 106: LIMIT -** 107: -** 108: -** 109: IN -** 110: INTO -** 111: OVER RECURSIVE -** 112: ORDER OUTER -** 113: -** 114: INTERSECT UNBOUNDED -** 115: -** 116: -** 117: RETURNING ON -** 118: -** 119: WHERE -** 120: NO INNER -** 121: NULL -** 122: -** 123: TABLE -** 124: NATURAL NOTNULL -** 125: PRECEDING -** 126: UPDATE UNIQUE -*/ -/* Check to see if z[0..n-1] is a keyword. If it is, write the -** parser symbol code for that keyword into *pType. Always -** return the integer n (the length of the token). */ -static int keywordCode(const char *z, int n, int *pType){ - int i, j; - const char *zKW; - assert( n>=2 ); - i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; - for(i=(int)aKWHash[i]; i>0; i=aKWNext[i]){ - if( aKWLen[i]!=n ) continue; - zKW = &zKWText[aKWOffset[i]]; -#ifdef SQLITE_ASCII - if( (z[0]&~0x20)!=zKW[0] ) continue; - if( (z[1]&~0x20)!=zKW[1] ) continue; - j = 2; - while( j=2 ) keywordCode((char*)z, n, &id); - return id; -} -#define SQLITE_N_KEYWORD 147 -SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ - if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; - i++; - *pzName = zKWText + aKWOffset[i]; - *pnName = aKWLen[i]; - return SQLITE_OK; -} -SQLITE_API int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; } -SQLITE_API int sqlite3_keyword_check(const char *zName, int nName){ - return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName); -} - -/************** End of keywordhash.h *****************************************/ -/************** Continuing where we left off in tokenize.c *******************/ - - -/* -** If X is a character that can be used in an identifier then -** IdChar(X) will be true. Otherwise it is false. -** -** For ASCII, any character with the high-order bit set is -** allowed in an identifier. For 7-bit characters, -** sqlite3IsIdChar[X] must be 1. -** -** For EBCDIC, the rules are more complex but have the same -** end result. -** -** Ticket #1066. the SQL standard does not allow '$' in the -** middle of identifiers. But many SQL implementations do. -** SQLite will allow '$' in identifiers for compatibility. -** But the feature is undocumented. -*/ -#ifdef SQLITE_ASCII -#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) -#endif -#ifdef SQLITE_EBCDIC -SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */ - 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ -}; -#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) -#endif - -/* Make the IdChar function accessible from ctime.c and alter.c */ -SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Return the id of the next token in string (*pz). Before returning, set -** (*pz) to point to the byte following the parsed token. -*/ -static int getToken(const unsigned char **pz){ - const unsigned char *z = *pz; - int t; /* Token type to return */ - do { - z += sqlite3GetToken(z, &t); - }while( t==TK_SPACE || t==TK_COMMENT ); - if( t==TK_ID - || t==TK_STRING - || t==TK_JOIN_KW - || t==TK_WINDOW - || t==TK_OVER - || sqlite3ParserFallback(t)==TK_ID - ){ - t = TK_ID; - } - *pz = z; - return t; -} - -/* -** The following three functions are called immediately after the tokenizer -** reads the keywords WINDOW, OVER and FILTER, respectively, to determine -** whether the token should be treated as a keyword or an SQL identifier. -** This cannot be handled by the usual lemon %fallback method, due to -** the ambiguity in some constructions. e.g. -** -** SELECT sum(x) OVER ... -** -** In the above, "OVER" might be a keyword, or it might be an alias for the -** sum(x) expression. If a "%fallback ID OVER" directive were added to -** grammar, then SQLite would always treat "OVER" as an alias, making it -** impossible to call a window-function without a FILTER clause. -** -** WINDOW is treated as a keyword if: -** -** * the following token is an identifier, or a keyword that can fallback -** to being an identifier, and -** * the token after than one is TK_AS. -** -** OVER is a keyword if: -** -** * the previous token was TK_RP, and -** * the next token is either TK_LP or an identifier. -** -** FILTER is a keyword if: -** -** * the previous token was TK_RP, and -** * the next token is TK_LP. -*/ -static int analyzeWindowKeyword(const unsigned char *z){ - int t; - t = getToken(&z); - if( t!=TK_ID ) return TK_ID; - t = getToken(&z); - if( t!=TK_AS ) return TK_ID; - return TK_WINDOW; -} -static int analyzeOverKeyword(const unsigned char *z, int lastToken){ - if( lastToken==TK_RP ){ - int t = getToken(&z); - if( t==TK_LP || t==TK_ID ) return TK_OVER; - } - return TK_ID; -} -static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ - if( lastToken==TK_RP && getToken(&z)==TK_LP ){ - return TK_FILTER; - } - return TK_ID; -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** Return the length (in bytes) of the token that begins at z[0]. -** Store the token type in *tokenType before returning. -*/ -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ - int i, c; - switch( aiClass[*z] ){ /* Switch on the character-class of the first byte - ** of the token. See the comment on the CC_ defines - ** above. */ - case CC_SPACE: { - testcase( z[0]==' ' ); - testcase( z[0]=='\t' ); - testcase( z[0]=='\n' ); - testcase( z[0]=='\f' ); - testcase( z[0]=='\r' ); - for(i=1; sqlite3Isspace(z[i]); i++){} - *tokenType = TK_SPACE; - return i; - } - case CC_MINUS: { - if( z[1]=='-' ){ - for(i=2; (c=z[i])!=0 && c!='\n'; i++){} - *tokenType = TK_COMMENT; - return i; - }else if( z[1]=='>' ){ - *tokenType = TK_PTR; - return 2 + (z[2]=='>'); - } - *tokenType = TK_MINUS; - return 1; - } - case CC_LP: { - *tokenType = TK_LP; - return 1; - } - case CC_RP: { - *tokenType = TK_RP; - return 1; - } - case CC_SEMI: { - *tokenType = TK_SEMI; - return 1; - } - case CC_PLUS: { - *tokenType = TK_PLUS; - return 1; - } - case CC_STAR: { - *tokenType = TK_STAR; - return 1; - } - case CC_SLASH: { - if( z[1]!='*' || z[2]==0 ){ - *tokenType = TK_SLASH; - return 1; - } - for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} - if( c ) i++; - *tokenType = TK_COMMENT; - return i; - } - case CC_PERCENT: { - *tokenType = TK_REM; - return 1; - } - case CC_EQ: { - *tokenType = TK_EQ; - return 1 + (z[1]=='='); - } - case CC_LT: { - if( (c=z[1])=='=' ){ - *tokenType = TK_LE; - return 2; - }else if( c=='>' ){ - *tokenType = TK_NE; - return 2; - }else if( c=='<' ){ - *tokenType = TK_LSHIFT; - return 2; - }else{ - *tokenType = TK_LT; - return 1; - } - } - case CC_GT: { - if( (c=z[1])=='=' ){ - *tokenType = TK_GE; - return 2; - }else if( c=='>' ){ - *tokenType = TK_RSHIFT; - return 2; - }else{ - *tokenType = TK_GT; - return 1; - } - } - case CC_BANG: { - if( z[1]!='=' ){ - *tokenType = TK_ILLEGAL; - return 1; - }else{ - *tokenType = TK_NE; - return 2; - } - } - case CC_PIPE: { - if( z[1]!='|' ){ - *tokenType = TK_BITOR; - return 1; - }else{ - *tokenType = TK_CONCAT; - return 2; - } - } - case CC_COMMA: { - *tokenType = TK_COMMA; - return 1; - } - case CC_AND: { - *tokenType = TK_BITAND; - return 1; - } - case CC_TILDA: { - *tokenType = TK_BITNOT; - return 1; - } - case CC_QUOTE: { - int delim = z[0]; - testcase( delim=='`' ); - testcase( delim=='\'' ); - testcase( delim=='"' ); - for(i=1; (c=z[i])!=0; i++){ - if( c==delim ){ - if( z[i+1]==delim ){ - i++; - }else{ - break; - } - } - } - if( c=='\'' ){ - *tokenType = TK_STRING; - return i+1; - }else if( c!=0 ){ - *tokenType = TK_ID; - return i+1; - }else{ - *tokenType = TK_ILLEGAL; - return i; - } - } - case CC_DOT: { -#ifndef SQLITE_OMIT_FLOATING_POINT - if( !sqlite3Isdigit(z[1]) ) -#endif - { - *tokenType = TK_DOT; - return 1; - } - /* If the next character is a digit, this is a floating point - ** number that begins with ".". Fall thru into the next case */ - /* no break */ deliberate_fall_through - } - case CC_DIGIT: { - testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); - testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); - testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); - testcase( z[0]=='9' ); testcase( z[0]=='.' ); - *tokenType = TK_INTEGER; -#ifndef SQLITE_OMIT_HEX_INTEGER - if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ - for(i=3; 1; i++){ - if( sqlite3Isxdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - }else -#endif - { - for(i=0; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } -#ifndef SQLITE_OMIT_FLOATING_POINT - if( z[i]=='.' ){ - if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; - for(i++; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - } - if( (z[i]=='e' || z[i]=='E') && - ( sqlite3Isdigit(z[i+1]) - || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) - ) - ){ - if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; - for(i+=2; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - } -#endif - } - while( IdChar(z[i]) ){ - *tokenType = TK_ILLEGAL; - i++; - } - return i; - } - case CC_QUOTE2: { - for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} - *tokenType = c==']' ? TK_ID : TK_ILLEGAL; - return i; - } - case CC_VARNUM: { - *tokenType = TK_VARIABLE; - for(i=1; sqlite3Isdigit(z[i]); i++){} - return i; - } - case CC_DOLLAR: - case CC_VARALPHA: { - int n = 0; - testcase( z[0]=='$' ); testcase( z[0]=='@' ); - testcase( z[0]==':' ); testcase( z[0]=='#' ); - *tokenType = TK_VARIABLE; - for(i=1; (c=z[i])!=0; i++){ - if( IdChar(c) ){ - n++; -#ifndef SQLITE_OMIT_TCL_VARIABLE - }else if( c=='(' && n>0 ){ - do{ - i++; - }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' ); - if( c==')' ){ - i++; - }else{ - *tokenType = TK_ILLEGAL; - } - break; - }else if( c==':' && z[i+1]==':' ){ - i++; -#endif - }else{ - break; - } - } - if( n==0 ) *tokenType = TK_ILLEGAL; - return i; - } - case CC_KYWD0: { - if( aiClass[z[1]]>CC_KYWD ){ i = 1; break; } - for(i=2; aiClass[z[i]]<=CC_KYWD; i++){} - if( IdChar(z[i]) ){ - /* This token started out using characters that can appear in keywords, - ** but z[i] is a character not allowed within keywords, so this must - ** be an identifier instead */ - i++; - break; - } - *tokenType = TK_ID; - return keywordCode((char*)z, i, tokenType); - } - case CC_X: { -#ifndef SQLITE_OMIT_BLOB_LITERAL - testcase( z[0]=='x' ); testcase( z[0]=='X' ); - if( z[1]=='\'' ){ - *tokenType = TK_BLOB; - for(i=2; sqlite3Isxdigit(z[i]); i++){} - if( z[i]!='\'' || i%2 ){ - *tokenType = TK_ILLEGAL; - while( z[i] && z[i]!='\'' ){ i++; } - } - if( z[i] ) i++; - return i; - } -#endif - /* If it is not a BLOB literal, then it must be an ID, since no - ** 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; - } - default: { - *tokenType = TK_ILLEGAL; - return 1; - } - } - while( IdChar(z[i]) ){ i++; } - *tokenType = TK_ID; - return i; -} - -/* -** Run the parser on the given SQL string. -*/ -SQLITE_PRIVATE int 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 */ - int tokenType; /* type of the next token */ - int lastTokenParsed = -1; /* type of the previous token */ - sqlite3 *db = pParse->db; /* The database connection */ - int mxSqlLen; /* Max length of an SQL string */ - Parse *pParentParse = 0; /* Outer parse context, if any */ -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ -#endif - VVA_ONLY( u8 startedWithOom = db->mallocFailed ); - - assert( zSql!=0 ); - mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; - if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); - } - pParse->rc = SQLITE_OK; - pParse->zTail = zSql; -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_ParserTrace ){ - printf("parser: [[[%s]]]\n", zSql); - sqlite3ParserTrace(stdout, "parser: "); - }else{ - sqlite3ParserTrace(0, 0); - } -#endif -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - pEngine = &sEngine; - sqlite3ParserInit(pEngine, pParse); -#else - pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); - if( pEngine==0 ){ - sqlite3OomFault(db); - return SQLITE_NOMEM_BKPT; - } -#endif - assert( pParse->pNewTable==0 ); - assert( pParse->pNewTrigger==0 ); - assert( pParse->nVar==0 ); - assert( pParse->pVList==0 ); - pParentParse = db->pParse; - db->pParse = pParse; - while( 1 ){ - n = sqlite3GetToken((u8*)zSql, &tokenType); - mxSqlLen -= n; - if( mxSqlLen<0 ){ - pParse->rc = SQLITE_TOOBIG; - pParse->nErr++; - break; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( tokenType>=TK_WINDOW ){ - assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER - || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW - || tokenType==TK_QNUMBER || tokenType==TK_COMMENT - ); -#else - if( tokenType>=TK_SPACE ){ - assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL - || tokenType==TK_QNUMBER || tokenType==TK_COMMENT - ); -#endif /* SQLITE_OMIT_WINDOWFUNC */ - if( AtomicLoad(&db->u1.isInterrupted) ){ - pParse->rc = SQLITE_INTERRUPT; - pParse->nErr++; - break; - } - if( tokenType==TK_SPACE ){ - zSql += n; - continue; - } - if( zSql[0]==0 ){ - /* Upon reaching the end of input, call the parser two more times - ** with tokens TK_SEMI and 0, in that order. */ - if( lastTokenParsed==TK_SEMI ){ - tokenType = 0; - }else if( lastTokenParsed==0 ){ - break; - }else{ - tokenType = TK_SEMI; - } - n = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - }else if( tokenType==TK_WINDOW ){ - assert( n==6 ); - tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); - }else if( tokenType==TK_OVER ){ - assert( n==4 ); - tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); - }else if( tokenType==TK_FILTER ){ - assert( n==6 ); - tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); -#endif /* SQLITE_OMIT_WINDOWFUNC */ - }else if( tokenType==TK_COMMENT - && (db->init.busy || (db->flags & SQLITE_Comments)!=0) - ){ - /* Ignore SQL comments if either (1) we are reparsing the schema or - ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */ - zSql += n; - continue; - }else if( tokenType!=TK_QNUMBER ){ - Token x; - x.z = zSql; - x.n = n; - sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); - break; - } - } - pParse->sLastToken.z = zSql; - pParse->sLastToken.n = n; - sqlite3Parser(pEngine, tokenType, pParse->sLastToken); - lastTokenParsed = tokenType; - zSql += n; - assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); - if( pParse->rc!=SQLITE_OK ) break; - } - assert( nErr==0 ); -#ifdef YYTRACKMAXSTACKDEPTH - sqlite3_mutex_enter(sqlite3MallocMutex()); - sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, - sqlite3ParserStackPeak(pEngine) - ); - sqlite3_mutex_leave(sqlite3MallocMutex()); -#endif /* YYDEBUG */ -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - sqlite3ParserFinalize(pEngine); -#else - sqlite3ParserFree(pEngine, sqlite3_free); -#endif - if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM_BKPT; - } - if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){ - if( pParse->zErrMsg==0 ){ - pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); - } - if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){ - sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail); - } - nErr++; - } - pParse->zTail = zSql; -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_free(pParse->apVtabLock); -#endif - - 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. - */ - sqlite3DeleteTable(db, pParse->pNewTable); - } - if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){ - sqlite3DeleteTrigger(db, pParse->pNewTrigger); - } - if( pParse->pVList ) sqlite3DbNNFreeNN(db, pParse->pVList); - db->pParse = pParentParse; - assert( nErr==0 || pParse->rc!=SQLITE_OK ); - return nErr; -} - - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Insert a single space character into pStr if the current string -** ends with an identifier -*/ -static void addSpaceSeparator(sqlite3_str *pStr){ - if( pStr->nChar && sqlite3IsIdChar(pStr->zText[pStr->nChar-1]) ){ - sqlite3_str_append(pStr, " ", 1); - } -} - -/* -** Compute a normalization of the SQL given by zSql[0..nSql-1]. Return -** the normalization in space obtained from sqlite3DbMalloc(). Or return -** NULL if anything goes wrong or if zSql is NULL. -*/ -SQLITE_PRIVATE char *sqlite3Normalize( - Vdbe *pVdbe, /* VM being reprepared */ - const char *zSql /* The original SQL string */ -){ - sqlite3 *db; /* The database connection */ - int i; /* Next unread byte of zSql[] */ - int n; /* length of current token */ - int tokenType; /* type of current token */ - int prevType = 0; /* Previous non-whitespace token */ - int nParen; /* Number of nested levels of parentheses */ - int iStartIN; /* Start of RHS of IN operator in z[] */ - int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ - u32 j; /* Bytes of normalized SQL generated so far */ - sqlite3_str *pStr; /* The normalized SQL string under construction */ - - db = sqlite3VdbeDb(pVdbe); - tokenType = -1; - nParen = iStartIN = nParenAtIN = 0; - pStr = sqlite3_str_new(db); - assert( pStr!=0 ); /* sqlite3_str_new() never returns NULL */ - for(i=0; zSql[i] && pStr->accError==0; i+=n){ - if( tokenType!=TK_SPACE ){ - prevType = tokenType; - } - n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType); - if( NEVER(n<=0) ) break; - switch( tokenType ){ - case TK_COMMENT: - case TK_SPACE: { - break; - } - case TK_NULL: { - if( prevType==TK_IS || prevType==TK_NOT ){ - sqlite3_str_append(pStr, " NULL", 5); - break; - } - /* Fall through */ - } - case TK_STRING: - case TK_INTEGER: - case TK_FLOAT: - case TK_VARIABLE: - case TK_BLOB: { - sqlite3_str_append(pStr, "?", 1); - break; - } - case TK_LP: { - nParen++; - if( prevType==TK_IN ){ - iStartIN = pStr->nChar; - nParenAtIN = nParen; - } - sqlite3_str_append(pStr, "(", 1); - break; - } - case TK_RP: { - if( iStartIN>0 && nParen==nParenAtIN ){ - assert( pStr->nChar>=(u32)iStartIN ); - pStr->nChar = iStartIN+1; - sqlite3_str_append(pStr, "?,?,?", 5); - iStartIN = 0; - } - nParen--; - sqlite3_str_append(pStr, ")", 1); - break; - } - case TK_ID: { - iStartIN = 0; - j = pStr->nChar; - if( sqlite3Isquote(zSql[i]) ){ - char *zId = sqlite3DbStrNDup(db, zSql+i, n); - int nId; - int eType = 0; - if( zId==0 ) break; - sqlite3Dequote(zId); - if( zSql[i]=='"' && sqlite3VdbeUsesDoubleQuotedString(pVdbe, zId) ){ - sqlite3_str_append(pStr, "?", 1); - sqlite3DbFree(db, zId); - break; - } - nId = sqlite3Strlen30(zId); - if( sqlite3GetToken((u8*)zId, &eType)==nId && eType==TK_ID ){ - addSpaceSeparator(pStr); - sqlite3_str_append(pStr, zId, nId); - }else{ - sqlite3_str_appendf(pStr, "\"%w\"", zId); - } - sqlite3DbFree(db, zId); - }else{ - addSpaceSeparator(pStr); - sqlite3_str_append(pStr, zSql+i, n); - } - while( jnChar ){ - pStr->zText[j] = sqlite3Tolower(pStr->zText[j]); - j++; - } - break; - } - case TK_SELECT: { - iStartIN = 0; - /* fall through */ - } - default: { - if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr); - j = pStr->nChar; - sqlite3_str_append(pStr, zSql+i, n); - while( jnChar ){ - pStr->zText[j] = sqlite3Toupper(pStr->zText[j]); - j++; - } - break; - } - } - } - if( tokenType!=TK_SEMI ) sqlite3_str_append(pStr, ";", 1); - return sqlite3_str_finish(pStr); -} -#endif /* SQLITE_ENABLE_NORMALIZE */ - -/************** End of tokenize.c ********************************************/ -/************** Begin file complete.c ****************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** An tokenizer for SQL -** -** This file contains C code that implements the sqlite3_complete() API. -** This code used to be part of the tokenizer.c source file. But by -** separating it out, the code will be automatically omitted from -** static links that do not use it. -*/ -/* #include "sqliteInt.h" */ -#ifndef SQLITE_OMIT_COMPLETE - -/* -** This is defined in tokenize.c. We just have to import the definition. -*/ -#ifndef SQLITE_AMALGAMATION -#ifdef SQLITE_ASCII -#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) -#endif -#ifdef SQLITE_EBCDIC -SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; -#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) -#endif -#endif /* SQLITE_AMALGAMATION */ - - -/* -** Token types used by the sqlite3_complete() routine. See the header -** comments on that procedure for additional information. -*/ -#define tkSEMI 0 -#define tkWS 1 -#define tkOTHER 2 -#ifndef SQLITE_OMIT_TRIGGER -#define tkEXPLAIN 3 -#define tkCREATE 4 -#define tkTEMP 5 -#define tkTRIGGER 6 -#define tkEND 7 -#endif - -/* -** Return TRUE if the given SQL string ends in a semicolon. -** -** Special handling is require for CREATE TRIGGER statements. -** Whenever the CREATE TRIGGER keywords are seen, the statement -** must end with ";END;". -** -** This implementation uses a state machine with 8 states: -** -** (0) INVALID We have not yet seen a non-whitespace character. -** -** (1) START At the beginning or end of an SQL statement. This routine -** returns 1 if it ends in the START state and 0 if it ends -** in any other state. -** -** (2) NORMAL We are in the middle of statement which ends with a single -** semicolon. -** -** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of -** a statement. -** -** (4) CREATE The keyword CREATE has been seen at the beginning of a -** statement, possibly preceded by EXPLAIN and/or followed by -** TEMP or TEMPORARY -** -** (5) TRIGGER We are in the middle of a trigger definition that must be -** ended by a semicolon, the keyword END, and another semicolon. -** -** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at -** the end of a trigger definition. -** -** (7) END We've seen the ";END" of the ";END;" that occurs at the end -** of a trigger definition. -** -** Transitions between states above are determined by tokens extracted -** from the input. The following tokens are significant: -** -** (0) tkSEMI A semicolon. -** (1) tkWS Whitespace. -** (2) tkOTHER Any other SQL token. -** (3) tkEXPLAIN The "explain" keyword. -** (4) tkCREATE The "create" keyword. -** (5) tkTEMP The "temp" or "temporary" keyword. -** (6) tkTRIGGER The "trigger" keyword. -** (7) tkEND The "end" keyword. -** -** Whitespace never causes a state transition and is always ignored. -** This means that a SQL string of all whitespace is invalid. -** -** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed -** to recognize the end of a trigger can be omitted. All we have to do -** is look for a semicolon that is not part of an string or comment. -*/ -SQLITE_API int sqlite3_complete(const char *zSql){ - u8 state = 0; /* Current state, using numbers defined in header comment */ - u8 token; /* Value of the next token */ - -#ifndef SQLITE_OMIT_TRIGGER - /* A complex statement machine used to detect the end of a CREATE TRIGGER - ** statement. This is the normal case. - */ - static const u8 trans[8][8] = { - /* Token: */ - /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ - /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, }, - /* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, }, - /* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, }, - /* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, }, - /* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, }, - /* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, }, - /* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, }, - /* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, }, - }; -#else - /* If triggers are not supported by this compile then the statement machine - ** used to detect the end of a statement is much simpler - */ - static const u8 trans[3][3] = { - /* Token: */ - /* State: ** SEMI WS OTHER */ - /* 0 INVALID: */ { 1, 0, 2, }, - /* 1 START: */ { 1, 1, 2, }, - /* 2 NORMAL: */ { 1, 2, 2, }, - }; -#endif /* SQLITE_OMIT_TRIGGER */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zSql==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - - while( *zSql ){ - switch( *zSql ){ - case ';': { /* A semicolon */ - token = tkSEMI; - break; - } - case ' ': - case '\r': - case '\t': - case '\n': - case '\f': { /* White space is ignored */ - token = tkWS; - break; - } - case '/': { /* C-style comments */ - if( zSql[1]!='*' ){ - token = tkOTHER; - break; - } - zSql += 2; - while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } - if( zSql[0]==0 ) return 0; - zSql++; - token = tkWS; - break; - } - case '-': { /* SQL-style comments from "--" to end of line */ - if( zSql[1]!='-' ){ - token = tkOTHER; - break; - } - while( *zSql && *zSql!='\n' ){ zSql++; } - if( *zSql==0 ) return state==1; - token = tkWS; - break; - } - case '[': { /* Microsoft-style identifiers in [...] */ - zSql++; - while( *zSql && *zSql!=']' ){ zSql++; } - if( *zSql==0 ) return 0; - token = tkOTHER; - break; - } - case '`': /* Grave-accent quoted symbols used by MySQL */ - case '"': /* single- and double-quoted strings */ - case '\'': { - int c = *zSql; - zSql++; - while( *zSql && *zSql!=c ){ zSql++; } - if( *zSql==0 ) return 0; - token = tkOTHER; - break; - } - default: { -#ifdef SQLITE_EBCDIC - unsigned char c; -#endif - if( IdChar((u8)*zSql) ){ - /* Keywords and unquoted identifiers */ - int nId; - for(nId=1; IdChar(zSql[nId]); nId++){} -#ifdef SQLITE_OMIT_TRIGGER - token = tkOTHER; -#else - switch( *zSql ){ - case 'c': case 'C': { - if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ - token = tkCREATE; - }else{ - token = tkOTHER; - } - break; - } - case 't': case 'T': { - if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ - token = tkTRIGGER; - }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ - token = tkTEMP; - }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ - token = tkTEMP; - }else{ - token = tkOTHER; - } - break; - } - case 'e': case 'E': { - if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ - token = tkEND; - }else -#ifndef SQLITE_OMIT_EXPLAIN - if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ - token = tkEXPLAIN; - }else -#endif - { - token = tkOTHER; - } - break; - } - default: { - token = tkOTHER; - break; - } - } -#endif /* SQLITE_OMIT_TRIGGER */ - zSql += nId-1; - }else{ - /* Operators and special symbols */ - token = tkOTHER; - } - break; - } - } - state = trans[state][token]; - zSql++; - } - return state==1; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** This routine is the same as the sqlite3_complete() routine described -** above, except that the parameter is required to be UTF-16 encoded, not -** UTF-8. -*/ -SQLITE_API int sqlite3_complete16(const void *zSql){ - sqlite3_value *pVal; - char const *zSql8; - int rc; - -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); - if( zSql8 ){ - rc = sqlite3_complete(zSql8); - }else{ - rc = SQLITE_NOMEM_BKPT; - } - sqlite3ValueFree(pVal); - return rc & 0xff; -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_OMIT_COMPLETE */ - -/************** End of complete.c ********************************************/ -/************** Begin file main.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Main file for the SQLite library. The routines in this file -** implement the programmer interface to the library. Routines in -** other files are for internal use by SQLite and should not be -** accessed by users of the library. -*/ -/* #include "sqliteInt.h" */ - -#ifdef SQLITE_ENABLE_FTS3 -/************** Include fts3.h in the middle of main.c ***********************/ -/************** Begin file fts3.h ********************************************/ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. -*/ -/* #include "sqlite3.h" */ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of fts3.h ************************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif -#ifdef SQLITE_ENABLE_RTREE -/************** Include rtree.h in the middle of main.c **********************/ -/************** Begin file rtree.h *******************************************/ -/* -** 2008 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** RTREE library. All it does is declare the sqlite3RtreeInit() interface. -*/ -/* #include "sqlite3.h" */ - -#ifdef SQLITE_OMIT_VIRTUALTABLE -# undef SQLITE_ENABLE_RTREE -#endif - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of rtree.h ***********************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif -#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) -/************** Include sqliteicu.h in the middle of main.c ******************/ -/************** Begin file sqliteicu.h ***************************************/ -/* -** 2008 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** ICU extension. All it does is declare the sqlite3IcuInit() interface. -*/ -/* #include "sqlite3.h" */ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of sqliteicu.h *******************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif - -/* -** This is an extension initializer that is a no-op and always -** succeeds, except that it fails if the fault-simulation is set -** to 500. -*/ -static int sqlite3TestExtInit(sqlite3 *db){ - (void)db; - return sqlite3FaultSim(500); -} - - -/* -** Forward declarations of external module initializer functions -** for modules that need them. -*/ -#ifdef SQLITE_ENABLE_FTS5 -SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); -#endif -#ifdef SQLITE_ENABLE_STMTVTAB -SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); -#endif -#ifdef SQLITE_EXTRA_AUTOEXT -int SQLITE_EXTRA_AUTOEXT(sqlite3*); -#endif -/* -** An array of pointers to extension initializer functions for -** built-in extensions. -*/ -static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { -#ifdef SQLITE_ENABLE_FTS3 - sqlite3Fts3Init, -#endif -#ifdef SQLITE_ENABLE_FTS5 - sqlite3Fts5Init, -#endif -#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) - sqlite3IcuInit, -#endif -#ifdef SQLITE_ENABLE_RTREE - sqlite3RtreeInit, -#endif -#ifdef SQLITE_ENABLE_DBPAGE_VTAB - sqlite3DbpageRegister, -#endif -#ifdef SQLITE_ENABLE_DBSTAT_VTAB - sqlite3DbstatRegister, -#endif - sqlite3TestExtInit, -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) - sqlite3JsonTableFunctions, -#endif -#ifdef SQLITE_ENABLE_STMTVTAB - sqlite3StmtVtabInit, -#endif -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - sqlite3VdbeBytecodeVtabInit, -#endif -#ifdef SQLITE_EXTRA_AUTOEXT - SQLITE_EXTRA_AUTOEXT, -#endif -}; - -#ifndef SQLITE_AMALGAMATION -/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant -** contains the text of SQLITE_VERSION macro. -*/ -SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -#endif - -/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns -** a pointer to the to the sqlite3_version[] string constant. -*/ -SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } - -/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a -** pointer to a string constant whose value is the same as the -** SQLITE_SOURCE_ID C preprocessor macro. Except if SQLite is built using -** an edited copy of the amalgamation, then the last four characters of -** the hash might be different from SQLITE_SOURCE_ID. -*/ -/* SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } */ - -/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function -** returns an integer equal to SQLITE_VERSION_NUMBER. -*/ -SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } - -/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns -** zero if and only if SQLite was compiled with mutexing code omitted due to -** the SQLITE_THREADSAFE compile-time option being set to 0. -*/ -SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } - -/* -** When compiling the test fixture or with debugging enabled (on Win32), -** this variable being set to non-zero will cause OSTRACE macros to emit -** extra diagnostic information. -*/ -#ifdef SQLITE_HAVE_OS_TRACE -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -#endif - -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) -/* -** If the following function pointer is not NULL and if -** SQLITE_ENABLE_IOTRACE is enabled, then messages describing -** I/O active are written using this function. These messages -** are intended for debugging activity only. -*/ -SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0; -#endif - -/* -** If the following global variable points to a string which is the -** name of a directory, then that directory will be used to store -** temporary files. -** -** See also the "PRAGMA temp_store_directory" SQL command. -*/ -SQLITE_API char *sqlite3_temp_directory = 0; - -/* -** If the following global variable points to a string which is the -** name of a directory, then that directory will be used to store -** all database files specified with a relative pathname. -** -** See also the "PRAGMA data_store_directory" SQL command. -*/ -SQLITE_API char *sqlite3_data_directory = 0; - -/* -** Initialize SQLite. -** -** This routine must be called to initialize the memory allocation, -** VFS, and mutex subsystems prior to doing any serious work with -** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT -** this routine will be called automatically by key routines such as -** sqlite3_open(). -** -** This routine is a no-op except on its very first call for the process, -** or for the first call after a call to sqlite3_shutdown. -** -** The first thread to call this routine runs the initialization to -** completion. If subsequent threads call this routine before the first -** thread has finished the initialization process, then the subsequent -** threads must block until the first thread finishes with the initialization. -** -** The first thread might call this routine recursively. Recursive -** calls to this routine should not block, of course. Otherwise the -** initialization process would never complete. -** -** Let X be the first thread to enter this routine. Let Y be some other -** thread. Then while the initial invocation of this routine by X is -** incomplete, it is required that: -** -** * Calls to this routine from Y must block until the outer-most -** call by X completes. -** -** * Recursive calls to this routine from thread X return immediately -** without blocking. -*/ -SQLITE_API int sqlite3_initialize(void){ - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */ - int rc; /* Result code */ -#ifdef SQLITE_EXTRA_INIT - int bRunExtraInit = 0; /* Extra initialization needed */ -#endif - -#ifdef SQLITE_OMIT_WSD - rc = sqlite3_wsd_init(4096, 24); - if( rc!=SQLITE_OK ){ - return rc; - } -#endif - - /* If the following assert() fails on some obscure processor/compiler - ** combination, the work-around is to set the correct pointer - ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ - assert( SQLITE_PTRSIZE==sizeof(char*) ); - - /* If SQLite is already completely initialized, then this call - ** to sqlite3_initialize() should be a no-op. But the initialization - ** must be complete. So isInit must not be set until the very end - ** of this routine. - */ - if( sqlite3GlobalConfig.isInit ){ - sqlite3MemoryBarrier(); - return SQLITE_OK; - } - - /* Make sure the mutex subsystem is initialized. If unable to - ** initialize the mutex subsystem, return early with the error. - ** If the system is so sick that we are unable to allocate a mutex, - ** there is not much SQLite is going to be able to do. - ** - ** The mutex subsystem must take care of serializing its own - ** initialization. - */ - rc = sqlite3MutexInit(); - if( rc ) return rc; - - /* Initialize the malloc() system and the recursive pInitMutex mutex. - ** This operation is protected by the STATIC_MAIN mutex. Note that - ** MutexAlloc() is called for a static mutex prior to initializing the - ** malloc subsystem - this implies that the allocation of a static - ** mutex must not require support from the malloc subsystem. - */ - MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(pMainMtx); - sqlite3GlobalConfig.isMutexInit = 1; - if( !sqlite3GlobalConfig.isMallocInit ){ - rc = sqlite3MallocInit(); - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.isMallocInit = 1; - if( !sqlite3GlobalConfig.pInitMutex ){ - sqlite3GlobalConfig.pInitMutex = - sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); - if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ - rc = SQLITE_NOMEM_BKPT; - } - } - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.nRefInitMutex++; - } - sqlite3_mutex_leave(pMainMtx); - - /* If rc is not SQLITE_OK at this point, then either the malloc - ** subsystem could not be initialized or the system failed to allocate - ** the pInitMutex mutex. Return an error in either case. */ - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Do the rest of the initialization under the recursive mutex so - ** that we will be able to handle recursive calls into - ** sqlite3_initialize(). The recursive calls normally come through - ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other - ** recursive calls might also be possible. - ** - ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls - ** to the xInit method, so the xInit method need not be threadsafe. - ** - ** The following mutex is what serializes access to the appdef pcache xInit - ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the - ** call to sqlite3PcacheInitialize(). - */ - sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); - if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ - sqlite3GlobalConfig.inProgress = 1; -#ifdef SQLITE_ENABLE_SQLLOG - { - extern void sqlite3_init_sqllog(void); - sqlite3_init_sqllog(); - } -#endif - memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions)); - sqlite3RegisterBuiltinFunctions(); - if( sqlite3GlobalConfig.isPCacheInit==0 ){ - rc = sqlite3PcacheInitialize(); - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.isPCacheInit = 1; - rc = sqlite3OsInit(); - } -#ifndef SQLITE_OMIT_DESERIALIZE - if( rc==SQLITE_OK ){ - rc = sqlite3MemdbInit(); - } -#endif - if( rc==SQLITE_OK ){ - sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, - sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); -#ifdef SQLITE_EXTRA_INIT_MUTEXED - { - int SQLITE_EXTRA_INIT_MUTEXED(const char*); - rc = SQLITE_EXTRA_INIT_MUTEXED(0); - } -#endif - } - if( rc==SQLITE_OK ){ - sqlite3MemoryBarrier(); - sqlite3GlobalConfig.isInit = 1; -#ifdef SQLITE_EXTRA_INIT - bRunExtraInit = 1; -#endif - } - sqlite3GlobalConfig.inProgress = 0; - } - sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex); - - /* Go back under the static mutex and clean up the recursive - ** mutex to prevent a resource leak. - */ - sqlite3_mutex_enter(pMainMtx); - sqlite3GlobalConfig.nRefInitMutex--; - if( sqlite3GlobalConfig.nRefInitMutex<=0 ){ - assert( sqlite3GlobalConfig.nRefInitMutex==0 ); - sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex); - sqlite3GlobalConfig.pInitMutex = 0; - } - sqlite3_mutex_leave(pMainMtx); - - /* The following is just a sanity check to make sure SQLite has - ** been compiled correctly. It is important to run this code, but - ** we don't want to run it too often and soak up CPU cycles for no - ** reason. So we run it once during initialization. - */ -#ifndef NDEBUG -#ifndef SQLITE_OMIT_FLOATING_POINT - /* This section of code's only "output" is via assert() statements. */ - if( rc==SQLITE_OK ){ - u64 x = (((u64)1)<<63)-1; - double y; - assert(sizeof(x)==8); - assert(sizeof(x)==sizeof(y)); - memcpy(&y, &x, 8); - assert( sqlite3IsNaN(y) ); - } -#endif -#endif - - /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT - ** compile-time option. - */ -#ifdef SQLITE_EXTRA_INIT - if( bRunExtraInit ){ - int SQLITE_EXTRA_INIT(const char*); - rc = SQLITE_EXTRA_INIT(0); - } -#endif - return rc; -} - -/* -** Undo the effects of sqlite3_initialize(). Must not be called while -** there are outstanding database connections or memory allocations or -** while any part of SQLite is otherwise in use in any thread. This -** routine is not threadsafe. But it is safe to invoke this routine -** on when SQLite is already shut down. If SQLite is already shut down -** when this routine is invoked, then this routine is a harmless no-op. -*/ -SQLITE_API int sqlite3_shutdown(void){ -#ifdef SQLITE_OMIT_WSD - int rc = sqlite3_wsd_init(4096, 24); - if( rc!=SQLITE_OK ){ - return rc; - } -#endif - - if( sqlite3GlobalConfig.isInit ){ -#ifdef SQLITE_EXTRA_SHUTDOWN - void SQLITE_EXTRA_SHUTDOWN(void); - SQLITE_EXTRA_SHUTDOWN(); -#endif - sqlite3_os_end(); - sqlite3_reset_auto_extension(); - sqlite3GlobalConfig.isInit = 0; - } - if( sqlite3GlobalConfig.isPCacheInit ){ - sqlite3PcacheShutdown(); - sqlite3GlobalConfig.isPCacheInit = 0; - } - if( sqlite3GlobalConfig.isMallocInit ){ - sqlite3MallocEnd(); - sqlite3GlobalConfig.isMallocInit = 0; - -#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES - /* The heap subsystem has now been shutdown and these values are supposed - ** to be NULL or point to memory that was obtained from sqlite3_malloc(), - ** which would rely on that heap subsystem; therefore, make sure these - ** values cannot refer to heap memory that was just invalidated when the - ** heap subsystem was shutdown. This is only done if the current call to - ** this function resulted in the heap subsystem actually being shutdown. - */ - sqlite3_data_directory = 0; - sqlite3_temp_directory = 0; -#endif - } - if( sqlite3GlobalConfig.isMutexInit ){ - sqlite3MutexEnd(); - sqlite3GlobalConfig.isMutexInit = 0; - } - - return SQLITE_OK; -} - -/* -** This API allows applications to modify the global configuration of -** the SQLite library at run-time. -** -** This routine should only be called when there are no outstanding -** database connections or memory allocations. This routine is not -** threadsafe. Failure to heed these warnings can lead to unpredictable -** behavior. -*/ -SQLITE_API int sqlite3_config(int op, ...){ - va_list ap; - int rc = SQLITE_OK; - - /* sqlite3_config() normally returns SQLITE_MISUSE if it is invoked while - ** the SQLite library is in use. Except, a few selected opcodes - ** are allowed. - */ - if( sqlite3GlobalConfig.isInit ){ - static const u64 mAnytimeConfigOption = 0 - | MASKBIT64( SQLITE_CONFIG_LOG ) - | MASKBIT64( SQLITE_CONFIG_PCACHE_HDRSZ ) - ; - if( op<0 || op>63 || (MASKBIT64(op) & mAnytimeConfigOption)==0 ){ - return SQLITE_MISUSE_BKPT; - } - testcase( op==SQLITE_CONFIG_LOG ); - testcase( op==SQLITE_CONFIG_PCACHE_HDRSZ ); - } - - va_start(ap, op); - switch( op ){ - - /* Mutex configuration options are only available in a threadsafe - ** compile. - */ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ - case SQLITE_CONFIG_SINGLETHREAD: { - /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to - ** Single-thread. */ - sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ - break; - } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ - case SQLITE_CONFIG_MULTITHREAD: { - /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to - ** Multi-thread. */ - sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ - break; - } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ - case SQLITE_CONFIG_SERIALIZED: { - /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to - ** Serialized. */ - sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ - break; - } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ - case SQLITE_CONFIG_MUTEX: { - /* Specify an alternative mutex implementation */ - sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); - break; - } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */ - case SQLITE_CONFIG_GETMUTEX: { - /* Retrieve the current mutex implementation */ - *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; - break; - } -#endif - - case SQLITE_CONFIG_MALLOC: { - /* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a - ** single argument which is a pointer to an instance of the - ** sqlite3_mem_methods structure. The argument specifies alternative - ** low-level memory allocation routines to be used in place of the memory - ** allocation routines built into SQLite. */ - sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); - break; - } - case SQLITE_CONFIG_GETMALLOC: { - /* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a - ** single argument which is a pointer to an instance of the - ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is - ** filled with the currently defined memory allocation routines. */ - if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); - *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; - break; - } - case SQLITE_CONFIG_MEMSTATUS: { - assert( !sqlite3GlobalConfig.isInit ); /* Cannot change at runtime */ - /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes - ** single argument of type int, interpreted as a boolean, which enables - ** or disables the collection of memory allocation statistics. */ - sqlite3GlobalConfig.bMemstat = va_arg(ap, int); - break; - } - case SQLITE_CONFIG_SMALL_MALLOC: { - sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int); - break; - } - case SQLITE_CONFIG_PAGECACHE: { - /* EVIDENCE-OF: R-18761-36601 There are three arguments to - ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem), - ** the size of each page cache line (sz), and the number of cache lines - ** (N). */ - sqlite3GlobalConfig.pPage = va_arg(ap, void*); - sqlite3GlobalConfig.szPage = va_arg(ap, int); - sqlite3GlobalConfig.nPage = va_arg(ap, int); - break; - } - case SQLITE_CONFIG_PCACHE_HDRSZ: { - /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes - ** a single parameter which is a pointer to an integer and writes into - ** that integer the number of extra bytes per page required for each page - ** in SQLITE_CONFIG_PAGECACHE. */ - *va_arg(ap, int*) = - sqlite3HeaderSizeBtree() + - sqlite3HeaderSizePcache() + - sqlite3HeaderSizePcache1(); - break; - } - - case SQLITE_CONFIG_PCACHE: { - /* no-op */ - break; - } - case SQLITE_CONFIG_GETPCACHE: { - /* now an error */ - rc = SQLITE_ERROR; - break; - } - - case SQLITE_CONFIG_PCACHE2: { - /* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a - ** single argument which is a pointer to an sqlite3_pcache_methods2 - ** object. This object specifies the interface to a custom page cache - ** implementation. */ - sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); - break; - } - case SQLITE_CONFIG_GETPCACHE2: { - /* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a - ** single argument which is a pointer to an sqlite3_pcache_methods2 - ** object. SQLite copies of the current page cache implementation into - ** that object. */ - if( sqlite3GlobalConfig.pcache2.xInit==0 ){ - sqlite3PCacheSetDefault(); - } - *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2; - break; - } - -/* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only -** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or -** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */ -#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) - case SQLITE_CONFIG_HEAP: { - /* EVIDENCE-OF: R-19854-42126 There are three arguments to - ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the - ** number of bytes in the memory buffer, and the minimum allocation size. - */ - sqlite3GlobalConfig.pHeap = va_arg(ap, void*); - sqlite3GlobalConfig.nHeap = va_arg(ap, int); - sqlite3GlobalConfig.mnReq = va_arg(ap, int); - - if( sqlite3GlobalConfig.mnReq<1 ){ - sqlite3GlobalConfig.mnReq = 1; - }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){ - /* cap min request size at 2^12 */ - sqlite3GlobalConfig.mnReq = (1<<12); - } - - if( sqlite3GlobalConfig.pHeap==0 ){ - /* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer) - ** is NULL, then SQLite reverts to using its default memory allocator - ** (the system malloc() implementation), undoing any prior invocation of - ** SQLITE_CONFIG_MALLOC. - ** - ** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to - ** revert to its default implementation when sqlite3_initialize() is run - */ - memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); - }else{ - /* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the - ** alternative memory allocator is engaged to handle all of SQLites - ** memory allocation needs. */ -#ifdef SQLITE_ENABLE_MEMSYS3 - sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); -#endif -#ifdef SQLITE_ENABLE_MEMSYS5 - sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5(); -#endif - } - break; - } -#endif - - case SQLITE_CONFIG_LOOKASIDE: { - sqlite3GlobalConfig.szLookaside = va_arg(ap, int); - sqlite3GlobalConfig.nLookaside = va_arg(ap, int); - break; - } - - /* Record a pointer to the logger function and its first argument. - ** The default is NULL. Logging is disabled if the function pointer is - ** NULL. - */ - case SQLITE_CONFIG_LOG: { - /* MSVC is picky about pulling func ptrs from va lists. - ** http://support.microsoft.com/kb/47961 - ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); - */ - typedef void(*LOGFUNC_t)(void*,int,const char*); - LOGFUNC_t xLog = va_arg(ap, LOGFUNC_t); - void *pLogArg = va_arg(ap, void*); - AtomicStore(&sqlite3GlobalConfig.xLog, xLog); - AtomicStore(&sqlite3GlobalConfig.pLogArg, pLogArg); - break; - } - - /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames - ** can be changed at start-time using the - ** sqlite3_config(SQLITE_CONFIG_URI,1) or - ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. - */ - case SQLITE_CONFIG_URI: { - /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single - ** argument of type int. If non-zero, then URI handling is globally - ** enabled. If the parameter is zero, then URI handling is globally - ** disabled. */ - int bOpenUri = va_arg(ap, int); - AtomicStore(&sqlite3GlobalConfig.bOpenUri, bOpenUri); - break; - } - - case SQLITE_CONFIG_COVERING_INDEX_SCAN: { - /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN - ** option takes a single integer argument which is interpreted as a - ** boolean in order to enable or disable the use of covering indices for - ** full table scans in the query optimizer. */ - sqlite3GlobalConfig.bUseCis = va_arg(ap, int); - break; - } - -#ifdef SQLITE_ENABLE_SQLLOG - case SQLITE_CONFIG_SQLLOG: { - typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); - sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); - sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); - break; - } -#endif - - case SQLITE_CONFIG_MMAP_SIZE: { - /* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit - ** integer (sqlite3_int64) values that are the default mmap size limit - ** (the default setting for PRAGMA mmap_size) and the maximum allowed - ** mmap size limit. */ - sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); - sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); - /* EVIDENCE-OF: R-53367-43190 If either argument to this option is - ** negative, then that argument is changed to its compile-time default. - ** - ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be - ** silently truncated if necessary so that it does not exceed the - ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE - ** compile-time option. - */ - if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ - mxMmap = SQLITE_MAX_MMAP_SIZE; - } - if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; - if( szMmap>mxMmap) szMmap = mxMmap; - sqlite3GlobalConfig.mxMmap = mxMmap; - sqlite3GlobalConfig.szMmap = szMmap; - break; - } - -#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */ - case SQLITE_CONFIG_WIN32_HEAPSIZE: { - /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit - ** unsigned integer value that specifies the maximum size of the created - ** heap. */ - sqlite3GlobalConfig.nHeap = va_arg(ap, int); - break; - } -#endif - - case SQLITE_CONFIG_PMASZ: { - sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); - break; - } - - case SQLITE_CONFIG_STMTJRNL_SPILL: { - sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); - break; - } - -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - case SQLITE_CONFIG_SORTERREF_SIZE: { - int iVal = va_arg(ap, int); - if( iVal<0 ){ - iVal = SQLITE_DEFAULT_SORTERREF_SIZE; - } - sqlite3GlobalConfig.szSorterRef = (u32)iVal; - break; - } -#endif /* SQLITE_ENABLE_SORTER_REFERENCES */ - -#ifndef SQLITE_OMIT_DESERIALIZE - case SQLITE_CONFIG_MEMDB_MAXSIZE: { - sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64); - break; - } -#endif /* SQLITE_OMIT_DESERIALIZE */ - - case SQLITE_CONFIG_ROWID_IN_VIEW: { - int *pVal = va_arg(ap,int*); -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid; - if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0; - *pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0); -#else - *pVal = 0; -#endif - break; - } - - default: { - rc = SQLITE_ERROR; - break; - } - } - va_end(ap); - return rc; -} - -/* -** Set up the lookaside buffers for a database connection. -** Return SQLITE_OK on success. -** If lookaside is already active, return SQLITE_BUSY. -** -** The sz parameter is the number of bytes in each lookaside slot. -** The cnt parameter is the number of slots. If pBuf is NULL the -** space for the lookaside memory is obtained from sqlite3_malloc() -** or similar. If pBuf is not NULL then it is sz*cnt bytes of memory -** to use for the lookaside memory. -*/ -static int setupLookaside( - sqlite3 *db, /* Database connection being configured */ - void *pBuf, /* Memory to use for lookaside. May be NULL */ - int sz, /* Desired size of each lookaside memory slot */ - int cnt /* Number of slots to allocate */ -){ -#ifndef SQLITE_OMIT_LOOKASIDE - void *pStart; /* Start of the lookaside buffer */ - sqlite3_int64 szAlloc; /* Total space set aside for lookaside memory */ - int nBig; /* Number of full-size slots */ - int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */ - - if( sqlite3LookasideUsed(db,0)>0 ){ - return SQLITE_BUSY; - } - /* Free any existing lookaside buffer for this handle before - ** allocating a new one so we don't have to have space for - ** both at the same time. - */ - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } - /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger - ** than a pointer and small enough to fit in a u16. - */ - sz = ROUNDDOWN8(sz); - if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; - if( sz>65528 ) sz = 65528; - /* Count must be at least 1 to be useful, but not so large as to use - ** more than 0x7fff0000 total bytes for lookaside. */ - if( cnt<1 ) cnt = 0; - if( sz>0 && cnt>(0x7fff0000/sz) ) cnt = 0x7fff0000/sz; - szAlloc = (i64)sz*(i64)cnt; - if( szAlloc==0 ){ - sz = 0; - pStart = 0; - }else if( pBuf==0 ){ - sqlite3BeginBenignMalloc(); - pStart = sqlite3Malloc( szAlloc ); - sqlite3EndBenignMalloc(); - if( pStart ) szAlloc = sqlite3MallocSize(pStart); - }else{ - pStart = pBuf; - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( sz>=LOOKASIDE_SMALL*3 ){ - nBig = szAlloc/(3*LOOKASIDE_SMALL+sz); - nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL; - }else if( sz>=LOOKASIDE_SMALL*2 ){ - nBig = szAlloc/(LOOKASIDE_SMALL+sz); - nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL; - }else -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( sz>0 ){ - nBig = szAlloc/sz; - nSm = 0; - }else{ - nBig = nSm = 0; - } - db->lookaside.pStart = pStart; - db->lookaside.pInit = 0; - db->lookaside.pFree = 0; - db->lookaside.sz = (u16)sz; - db->lookaside.szTrue = (u16)sz; - if( pStart ){ - int i; - LookasideSlot *p; - assert( sz > (int)sizeof(LookasideSlot*) ); - p = (LookasideSlot*)pStart; - for(i=0; ipNext = db->lookaside.pInit; - db->lookaside.pInit = p; - p = (LookasideSlot*)&((u8*)p)[sz]; - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - db->lookaside.pSmallInit = 0; - db->lookaside.pSmallFree = 0; - db->lookaside.pMiddle = p; - for(i=0; ipNext = db->lookaside.pSmallInit; - db->lookaside.pSmallInit = p; - p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL]; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - assert( ((uptr)p)<=szAlloc + (uptr)pStart ); - db->lookaside.pEnd = p; - db->lookaside.bDisable = 0; - db->lookaside.bMalloced = pBuf==0 ?1:0; - db->lookaside.nSlot = nBig+nSm; - }else{ - db->lookaside.pStart = 0; -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - db->lookaside.pSmallInit = 0; - db->lookaside.pSmallFree = 0; - db->lookaside.pMiddle = 0; -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - db->lookaside.pEnd = 0; - db->lookaside.bDisable = 1; - db->lookaside.sz = 0; - db->lookaside.bMalloced = 0; - db->lookaside.nSlot = 0; - } - db->lookaside.pTrueEnd = db->lookaside.pEnd; - assert( sqlite3LookasideUsed(db,0)==0 ); -#endif /* SQLITE_OMIT_LOOKASIDE */ - return SQLITE_OK; -} - -/* -** Return the mutex associated with a database connection. -*/ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->mutex; -} - -/* -** Free up as much memory as we can from the given database -** connection. -*/ -SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ - int i; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - Pager *pPager = sqlite3BtreePager(pBt); - sqlite3PagerShrink(pPager); - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Flush any dirty pages in the pager-cache for any attached database -** to disk. -*/ -SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){ - int i; - int rc = SQLITE_OK; - int bSeenBusy = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ - Pager *pPager = sqlite3BtreePager(pBt); - rc = sqlite3PagerFlush(pPager); - if( rc==SQLITE_BUSY ){ - bSeenBusy = 1; - rc = SQLITE_OK; - } - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc); -} - -/* -** Configuration settings for an individual database connection -*/ -SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ - va_list ap; - int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - va_start(ap, op); - switch( op ){ - case SQLITE_DBCONFIG_MAINDBNAME: { - /* IMP: R-06824-28531 */ - /* IMP: R-36257-52125 */ - db->aDb[0].zDbSName = va_arg(ap,char*); - rc = SQLITE_OK; - break; - } - case SQLITE_DBCONFIG_LOOKASIDE: { - void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ - int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ - int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */ - rc = setupLookaside(db, pBuf, sz, cnt); - break; - } - default: { - static const struct { - int op; /* The opcode */ - u64 mask; /* Mask of the bit in sqlite3.flags to set/clear */ - } aFlagOp[] = { - { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, - { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, - { SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView }, - { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, - { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, - { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, - { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, - { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, - { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, - { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, - { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| - SQLITE_NoSchemaError }, - { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter }, - { SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL }, - { SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML }, - { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt }, - { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema }, - { SQLITE_DBCONFIG_STMT_SCANSTATUS, SQLITE_StmtScanStatus }, - { SQLITE_DBCONFIG_REVERSE_SCANORDER, SQLITE_ReverseOrder }, - { SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE, SQLITE_AttachCreate }, - { SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE, SQLITE_AttachWrite }, - { SQLITE_DBCONFIG_ENABLE_COMMENTS, SQLITE_Comments }, - }; - unsigned int i; - rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ - for(i=0; iflags; - if( onoff>0 ){ - db->flags |= aFlagOp[i].mask; - }else if( onoff==0 ){ - db->flags &= ~(u64)aFlagOp[i].mask; - } - if( oldFlags!=db->flags ){ - sqlite3ExpirePreparedStatements(db, 0); - } - if( pRes ){ - *pRes = (db->flags & aFlagOp[i].mask)!=0; - } - rc = SQLITE_OK; - break; - } - } - break; - } - } - va_end(ap); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** This is the default collating function named "BINARY" which is always -** available. -*/ -static int binCollFunc( - void *NotUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - int rc, n; - UNUSED_PARAMETER(NotUsed); - n = nKey1xCmp!=binCollFunc || strcmp(p->zName,"BINARY")==0 ); - return p==0 || p->xCmp==binCollFunc; -} - -/* -** Another built-in collating sequence: NOCASE. -** -** This collating sequence is intended to be used for "case independent -** comparison". SQLite's knowledge of upper and lower case equivalents -** extends only to the 26 characters used in the English language. -** -** At the moment there is only a UTF-8 implementation. -*/ -static int nocaseCollatingFunc( - void *NotUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - int r = sqlite3StrNICmp( - (const char *)pKey1, (const char *)pKey2, (nKey1lastRowid; -} - -/* -** Set the value returned by the sqlite3_last_insert_rowid() API function. -*/ -SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif - sqlite3_mutex_enter(db->mutex); - db->lastRowid = iRowid; - sqlite3_mutex_leave(db->mutex); -} - -/* -** Return the number of changes in the most recent call to sqlite3_exec(). -*/ -SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->nChange; -} -SQLITE_API int sqlite3_changes(sqlite3 *db){ - return (int)sqlite3_changes64(db); -} - -/* -** Return the number of changes since the database handle was opened. -*/ -SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->nTotalChange; -} -SQLITE_API int sqlite3_total_changes(sqlite3 *db){ - return (int)sqlite3_total_changes64(db); -} - -/* -** Close all open savepoints. This function only manipulates fields of the -** database handle object, it does not close any savepoints that may be open -** at the b-tree/pager level. -*/ -SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *db){ - while( db->pSavepoint ){ - Savepoint *pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; - sqlite3DbFree(db, pTmp); - } - db->nSavepoint = 0; - db->nStatement = 0; - db->isTransactionSavepoint = 0; -} - -/* -** Invoke the destructor function associated with FuncDef p, if any. Except, -** if this is not the last copy of the function, do not invoke it. Multiple -** copies of a single function are created when create_function() is called -** with SQLITE_ANY as the encoding. -*/ -static void functionDestroy(sqlite3 *db, FuncDef *p){ - FuncDestructor *pDestructor; - assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 ); - pDestructor = p->u.pDestructor; - if( pDestructor ){ - pDestructor->nRef--; - if( pDestructor->nRef==0 ){ - pDestructor->xDestroy(pDestructor->pUserData); - sqlite3DbFree(db, pDestructor); - } - } -} - -/* -** Disconnect all sqlite3_vtab objects that belong to database connection -** db. This is called when db is being closed. -*/ -static void disconnectAllVtab(sqlite3 *db){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - int i; - HashElem *p; - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Schema *pSchema = db->aDb[i].pSchema; - if( pSchema ){ - for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ - Table *pTab = (Table *)sqliteHashData(p); - if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); - } - } - } - for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){ - Module *pMod = (Module *)sqliteHashData(p); - if( pMod->pEpoTab ){ - sqlite3VtabDisconnect(db, pMod->pEpoTab); - } - } - sqlite3VtabUnlockList(db); - sqlite3BtreeLeaveAll(db); -#else - UNUSED_PARAMETER(db); -#endif -} - -/* -** Return TRUE if database connection db has unfinalized prepared -** statements or unfinished sqlite3_backup objects. -*/ -static int connectionIsBusy(sqlite3 *db){ - int j; - assert( sqlite3_mutex_held(db->mutex) ); - if( db->pVdbe ) return 1; - for(j=0; jnDb; j++){ - Btree *pBt = db->aDb[j].pBt; - if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1; - } - return 0; -} - -/* -** Close an existing SQLite database -*/ -static int sqlite3Close(sqlite3 *db, int forceZombie){ - if( !db ){ - /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or - ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */ - return SQLITE_OK; - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - if( db->mTrace & SQLITE_TRACE_CLOSE ){ - db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); - } - - /* Force xDisconnect calls on all virtual tables */ - disconnectAllVtab(db); - - /* If a transaction is open, the disconnectAllVtab() call above - ** will not have called the xDisconnect() method on any virtual - ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() - ** call will do so. We need to do this before the check for active - ** SQL statements below, as the v-table implementation may be storing - ** some prepared statements internally. - */ - sqlite3VtabRollback(db); - - /* Legacy behavior (sqlite3_close() behavior) is to return - ** SQLITE_BUSY if the connection can not be closed immediately. - */ - if( !forceZombie && connectionIsBusy(db) ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to close due to unfinalized " - "statements or unfinished backups"); - sqlite3_mutex_leave(db->mutex); - return SQLITE_BUSY; - } - -#ifdef SQLITE_ENABLE_SQLLOG - if( sqlite3GlobalConfig.xSqllog ){ - /* Closing the handle. Fourth parameter is passed the value 2. */ - sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2); - } -#endif - - while( db->pDbData ){ - DbClientData *p = db->pDbData; - db->pDbData = p->pNext; - assert( p->pData!=0 ); - if( p->xDestructor ) p->xDestructor(p->pData); - sqlite3_free(p); - } - - /* Convert the connection into a zombie and then close it. - */ - db->eOpenState = SQLITE_STATE_ZOMBIE; - sqlite3LeaveMutexAndCloseZombie(db); - return SQLITE_OK; -} - -/* -** Return the transaction state for a single databse, or the maximum -** transaction state over all attached databases if zSchema is null. -*/ -SQLITE_API int sqlite3_txn_state(sqlite3 *db, const char *zSchema){ - int iDb, nDb; - int iTxn = -1; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( zSchema ){ - nDb = iDb = sqlite3FindDbName(db, zSchema); - if( iDb<0 ) nDb--; - }else{ - iDb = 0; - nDb = db->nDb-1; - } - for(; iDb<=nDb; iDb++){ - Btree *pBt = db->aDb[iDb].pBt; - int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE; - if( x>iTxn ) iTxn = x; - } - sqlite3_mutex_leave(db->mutex); - return iTxn; -} - -/* -** Two variations on the public interface for closing a database -** connection. The sqlite3_close() version returns SQLITE_BUSY and -** leaves the connection open if there are unfinalized prepared -** statements or unfinished sqlite3_backups. The sqlite3_close_v2() -** version forces the connection to become a zombie if there are -** unclosed resources, and arranges for deallocation when the last -** prepare statement or sqlite3_backup closes. -*/ -SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } - - -/* -** Close the mutex on database connection db. -** -** Furthermore, if database connection db is a zombie (meaning that there -** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and -** every sqlite3_stmt has now been finalized and every sqlite3_backup has -** finished, then free all resources. -*/ -SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ - HashElem *i; /* Hash table iterator */ - int j; - - /* If there are outstanding sqlite3_stmt or sqlite3_backup objects - ** or if the connection has not yet been closed by sqlite3_close_v2(), - ** then just leave the mutex and return. - */ - if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){ - sqlite3_mutex_leave(db->mutex); - return; - } - - /* If we reach this point, it means that the database connection has - ** closed all sqlite3_stmt and sqlite3_backup objects and has been - ** passed to sqlite3_close (meaning that it is a zombie). Therefore, - ** go ahead and free all resources. - */ - - /* If a transaction is open, roll it back. This also ensures that if - ** any database schemas have been modified by an uncommitted transaction - ** they are reset. And that the required b-tree mutex is held to make - ** the pager rollback and schema reset an atomic operation. */ - sqlite3RollbackAll(db, SQLITE_OK); - - /* Free any outstanding Savepoint structures. */ - sqlite3CloseSavepoints(db); - - /* Close all database connections */ - for(j=0; jnDb; j++){ - struct Db *pDb = &db->aDb[j]; - if( pDb->pBt ){ - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - if( j!=1 ){ - pDb->pSchema = 0; - } - } - } - /* Clear the TEMP schema separately and last */ - if( db->aDb[1].pSchema ){ - sqlite3SchemaClear(db->aDb[1].pSchema); - } - sqlite3VtabUnlockList(db); - - /* Free up the array of auxiliary databases */ - sqlite3CollapseDatabaseArray(db); - assert( db->nDb<=2 ); - assert( db->aDb==db->aDbStatic ); - - /* Tell the code in notify.c that the connection no longer holds any - ** locks and does not require any further unlock-notify callbacks. - */ - sqlite3ConnectionClosed(db); - - for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ - FuncDef *pNext, *p; - p = sqliteHashData(i); - do{ - functionDestroy(db, p); - pNext = p->pNext; - sqlite3DbFree(db, p); - p = pNext; - }while( p ); - } - sqlite3HashClear(&db->aFunc); - for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ - CollSeq *pColl = (CollSeq *)sqliteHashData(i); - /* Invoke any destructors registered for collation sequence user data. */ - for(j=0; j<3; j++){ - if( pColl[j].xDel ){ - pColl[j].xDel(pColl[j].pUser); - } - } - sqlite3DbFree(db, pColl); - } - sqlite3HashClear(&db->aCollSeq); -#ifndef SQLITE_OMIT_VIRTUALTABLE - for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ - Module *pMod = (Module *)sqliteHashData(i); - sqlite3VtabEponymousTableClear(db, pMod); - sqlite3VtabModuleUnref(db, pMod); - } - sqlite3HashClear(&db->aModule); -#endif - - sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ - sqlite3ValueFree(db->pErr); - sqlite3CloseExtensions(db); - - db->eOpenState = SQLITE_STATE_ERROR; - - /* The temp-database schema is allocated differently from the other schema - ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). - ** So it needs to be freed here. Todo: Why not roll the temp schema into - ** the same sqliteMalloc() as the one that allocates the database - ** structure? - */ - sqlite3DbFree(db, db->aDb[1].pSchema); - if( db->xAutovacDestr ){ - db->xAutovacDestr(db->pAutovacPagesArg); - } - sqlite3_mutex_leave(db->mutex); - db->eOpenState = SQLITE_STATE_CLOSED; - sqlite3_mutex_free(db->mutex); - assert( sqlite3LookasideUsed(db,0)==0 ); - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } - sqlite3_free(db); -} - -/* -** Rollback all database files. If tripCode is not SQLITE_OK, then -** any write cursors are invalidated ("tripped" - as in "tripping a circuit -** breaker") and made to return tripCode if there are any further -** attempts to use that cursor. Read cursors remain open and valid -** but are "saved" in case the table pages are moved around. -*/ -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ - int i; - int inTrans = 0; - int schemaChange; - assert( sqlite3_mutex_held(db->mutex) ); - sqlite3BeginBenignMalloc(); - - /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). - ** This is important in case the transaction being rolled back has - ** modified the database schema. If the b-tree mutexes are not taken - ** here, then another shared-cache connection might sneak in between - ** the database rollback and schema reset, which can cause false - ** corruption reports in some cases. */ - sqlite3BtreeEnterAll(db); - schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0; - - for(i=0; inDb; i++){ - Btree *p = db->aDb[i].pBt; - if( p ){ - if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){ - inTrans = 1; - } - sqlite3BtreeRollback(p, tripCode, !schemaChange); - } - } - sqlite3VtabRollback(db); - sqlite3EndBenignMalloc(); - - if( schemaChange ){ - sqlite3ExpirePreparedStatements(db, 0); - sqlite3ResetAllSchemasOfConnection(db); - } - sqlite3BtreeLeaveAll(db); - - /* Any deferred constraint violations have now been resolved. */ - db->nDeferredCons = 0; - db->nDeferredImmCons = 0; - db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly); - - /* If one has been configured, invoke the rollback-hook callback */ - if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ - db->xRollbackCallback(db->pRollbackArg); - } -} - -/* -** Return a static string containing the name corresponding to the error code -** specified in the argument. -*/ -#if defined(SQLITE_NEED_ERR_NAME) -SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ - const char *zName = 0; - int i, origRc = rc; - for(i=0; i<2 && zName==0; i++, rc &= 0xff){ - switch( rc ){ - case SQLITE_OK: zName = "SQLITE_OK"; break; - case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; - case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; - case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; - case SQLITE_PERM: zName = "SQLITE_PERM"; break; - case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; - case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; - case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; - case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break; - case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break; - case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; - case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; - case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; - case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; - case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; - case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; - case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; - case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; - case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break; - case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; - case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; - case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; - case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; - case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; - case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break; - case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break; - case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break; - case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break; - case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break; - case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break; - case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break; - case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break; - case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break; - case SQLITE_IOERR_CHECKRESERVEDLOCK: - zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; - case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break; - case SQLITE_IOERR_CLOSE: zName = "SQLITE_IOERR_CLOSE"; break; - case SQLITE_IOERR_DIR_CLOSE: zName = "SQLITE_IOERR_DIR_CLOSE"; break; - case SQLITE_IOERR_SHMOPEN: zName = "SQLITE_IOERR_SHMOPEN"; break; - case SQLITE_IOERR_SHMSIZE: zName = "SQLITE_IOERR_SHMSIZE"; break; - case SQLITE_IOERR_SHMLOCK: zName = "SQLITE_IOERR_SHMLOCK"; break; - case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break; - case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break; - case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break; - case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break; - case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break; - case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break; - case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; - case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; - case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; - case SQLITE_FULL: zName = "SQLITE_FULL"; break; - case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; - case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; - case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; - case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break; - case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break; - case SQLITE_CANTOPEN_SYMLINK: zName = "SQLITE_CANTOPEN_SYMLINK"; break; - case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; - case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; - case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; - case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; - case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; - case SQLITE_CONSTRAINT_UNIQUE: zName = "SQLITE_CONSTRAINT_UNIQUE"; break; - case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break; - case SQLITE_CONSTRAINT_FOREIGNKEY: - zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break; - case SQLITE_CONSTRAINT_CHECK: zName = "SQLITE_CONSTRAINT_CHECK"; break; - case SQLITE_CONSTRAINT_PRIMARYKEY: - zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break; - case SQLITE_CONSTRAINT_NOTNULL: zName = "SQLITE_CONSTRAINT_NOTNULL";break; - case SQLITE_CONSTRAINT_COMMITHOOK: - zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break; - case SQLITE_CONSTRAINT_VTAB: zName = "SQLITE_CONSTRAINT_VTAB"; break; - case SQLITE_CONSTRAINT_FUNCTION: - zName = "SQLITE_CONSTRAINT_FUNCTION"; break; - case SQLITE_CONSTRAINT_ROWID: zName = "SQLITE_CONSTRAINT_ROWID"; break; - case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; - case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; - case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; - case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; - case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; - case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; - case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; - case SQLITE_ROW: zName = "SQLITE_ROW"; break; - case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break; - case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break; - case SQLITE_NOTICE_RECOVER_ROLLBACK: - zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break; - case SQLITE_NOTICE_RBU: zName = "SQLITE_NOTICE_RBU"; break; - case SQLITE_WARNING: zName = "SQLITE_WARNING"; break; - case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break; - case SQLITE_DONE: zName = "SQLITE_DONE"; break; - } - } - if( zName==0 ){ - static char zBuf[50]; - sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc); - zName = zBuf; - } - return zName; -} -#endif - -/* -** Return a static string that describes the kind of error specified in the -** argument. -*/ -SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ - static const char* const aMsg[] = { - /* SQLITE_OK */ "not an error", - /* SQLITE_ERROR */ "SQL logic error", - /* SQLITE_INTERNAL */ 0, - /* SQLITE_PERM */ "access permission denied", - /* SQLITE_ABORT */ "query aborted", - /* SQLITE_BUSY */ "database is locked", - /* SQLITE_LOCKED */ "database table is locked", - /* SQLITE_NOMEM */ "out of memory", - /* SQLITE_READONLY */ "attempt to write a readonly database", - /* SQLITE_INTERRUPT */ "interrupted", - /* SQLITE_IOERR */ "disk I/O error", - /* SQLITE_CORRUPT */ "database disk image is malformed", - /* SQLITE_NOTFOUND */ "unknown operation", - /* SQLITE_FULL */ "database or disk is full", - /* SQLITE_CANTOPEN */ "unable to open database file", - /* SQLITE_PROTOCOL */ "locking protocol", - /* SQLITE_EMPTY */ 0, - /* SQLITE_SCHEMA */ "database schema has changed", - /* SQLITE_TOOBIG */ "string or blob too big", - /* SQLITE_CONSTRAINT */ "constraint failed", - /* SQLITE_MISMATCH */ "datatype mismatch", - /* SQLITE_MISUSE */ "bad parameter or other API misuse", -#ifdef SQLITE_DISABLE_LFS - /* SQLITE_NOLFS */ "large file support is disabled", -#else - /* SQLITE_NOLFS */ 0, -#endif - /* SQLITE_AUTH */ "authorization denied", - /* SQLITE_FORMAT */ 0, - /* SQLITE_RANGE */ "column index out of range", - /* SQLITE_NOTADB */ "file is not a database", - /* SQLITE_NOTICE */ "notification message", - /* SQLITE_WARNING */ "warning message", - }; - const char *zErr = "unknown error"; - switch( rc ){ - case SQLITE_ABORT_ROLLBACK: { - zErr = "abort due to ROLLBACK"; - break; - } - case SQLITE_ROW: { - zErr = "another row available"; - break; - } - case SQLITE_DONE: { - zErr = "no more rows available"; - break; - } - default: { - rc &= 0xff; - if( ALWAYS(rc>=0) && rcbusyTimeout; - int delay, prior; - - assert( count>=0 ); - if( count < NDELAY ){ - delay = delays[count]; - prior = totals[count]; - }else{ - delay = delays[NDELAY-1]; - prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); - } - if( prior + delay > tmout ){ - delay = tmout - prior; - if( delay<=0 ) return 0; - } - sqlite3OsSleep(db->pVfs, delay*1000); - return 1; -#else - /* This case for unix systems that lack usleep() support. Sleeping - ** must be done in increments of whole seconds */ - sqlite3 *db = (sqlite3 *)ptr; - int tmout = ((sqlite3 *)ptr)->busyTimeout; - if( (count+1)*1000 > tmout ){ - return 0; - } - sqlite3OsSleep(db->pVfs, 1000000); - return 1; -#endif -} - -/* -** Invoke the given busy handler. -** -** This routine is called when an operation failed to acquire a -** lock on VFS file pFile. -** -** If this routine returns non-zero, the lock is retried. If it -** returns 0, the operation aborts with an SQLITE_BUSY error. -*/ -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ - int rc; - if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; - rc = p->xBusyHandler(p->pBusyArg, p->nBusy); - if( rc==0 ){ - p->nBusy = -1; - }else{ - p->nBusy++; - } - return rc; -} - -/* -** This routine sets the busy callback for an Sqlite database to the -** given callback function with the given argument. -*/ -SQLITE_API int sqlite3_busy_handler( - sqlite3 *db, - int (*xBusy)(void*,int), - void *pArg -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - db->busyHandler.xBusyHandler = xBusy; - db->busyHandler.pBusyArg = pArg; - db->busyHandler.nBusy = 0; - db->busyTimeout = 0; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - db->setlkTimeout = 0; -#endif - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK -/* -** This routine sets the progress callback for an Sqlite database to the -** given callback function with the given argument. The progress callback will -** be invoked every nOps opcodes. -*/ -SQLITE_API void sqlite3_progress_handler( - sqlite3 *db, - int nOps, - int (*xProgress)(void*), - void *pArg -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( nOps>0 ){ - db->xProgress = xProgress; - db->nProgressOps = (unsigned)nOps; - db->pProgressArg = pArg; - }else{ - db->xProgress = 0; - db->nProgressOps = 0; - db->pProgressArg = 0; - } - sqlite3_mutex_leave(db->mutex); -} -#endif - - -/* -** This routine installs a default busy handler that waits for the -** specified number of milliseconds before returning 0. -*/ -SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - if( ms>0 ){ - sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, - (void*)db); - db->busyTimeout = ms; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - db->setlkTimeout = ms; -#endif - }else{ - sqlite3_busy_handler(db, 0, 0); - } - return SQLITE_OK; -} - -/* -** Set the setlk timeout value. -*/ -SQLITE_API int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int iDb; - int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0); -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - if( ms<-1 ) return SQLITE_RANGE; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3_mutex_enter(db->mutex); - db->setlkTimeout = ms; - db->setlkFlags = flags; - sqlite3BtreeEnterAll(db); - for(iDb=0; iDbnDb; iDb++){ - Btree *pBt = db->aDb[iDb].pBt; - if( pBt ){ - sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt)); - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC); - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); -#endif -#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT) - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(flags); -#endif - return SQLITE_OK; -} - -/* -** Cause any pending operation to stop at its earliest opportunity. -*/ -SQLITE_API void sqlite3_interrupt(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) - && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) - ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif - AtomicStore(&db->u1.isInterrupted, 1); -} - -/* -** Return true or false depending on whether or not an interrupt is -** pending on connection db. -*/ -SQLITE_API int sqlite3_is_interrupted(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) - && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) - ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return AtomicLoad(&db->u1.isInterrupted)!=0; -} - -/* -** This function is exactly the same as sqlite3_create_function(), except -** that it is designed to be called by internal code. The difference is -** that if a malloc() fails in sqlite3_create_function(), an error code -** is returned and the mallocFailed flag cleared. -*/ -SQLITE_PRIVATE int sqlite3CreateFunc( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int enc, - void *pUserData, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value **), - FuncDestructor *pDestructor -){ - FuncDef *p; - int extraFlags; - - assert( sqlite3_mutex_held(db->mutex) ); - assert( xValue==0 || xSFunc==0 ); - if( zFunctionName==0 /* Must have a valid name */ - || (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */ - || ((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) - || (255funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){ - if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, - "unable to delete/modify user-function due to active statements"); - assert( !db->mallocFailed ); - return SQLITE_BUSY; - }else{ - 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 = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1); - assert(p || db->mallocFailed); - if( !p ){ - return SQLITE_NOMEM_BKPT; - } - - /* If an older version of the function with a configured destructor is - ** being replaced invoke the destructor function here. */ - functionDestroy(db, p); - - if( pDestructor ){ - pDestructor->nRef++; - } - p->u.pDestructor = pDestructor; - p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; - testcase( p->funcFlags & SQLITE_DETERMINISTIC ); - testcase( p->funcFlags & SQLITE_DIRECTONLY ); - p->xSFunc = xSFunc ? xSFunc : xStep; - p->xFinalize = xFinal; - p->xValue = xValue; - p->xInverse = xInverse; - p->pUserData = pUserData; - p->nArg = (u16)nArg; - return SQLITE_OK; -} - -/* -** Worker function used by utf-8 APIs that create new functions: -** -** sqlite3_create_function() -** sqlite3_create_function_v2() -** sqlite3_create_window_function() -*/ -static int createFunctionApi( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) -){ - int rc = SQLITE_ERROR; - FuncDestructor *pArg = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( xDestroy ){ - pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor)); - if( !pArg ){ - sqlite3OomFault(db); - xDestroy(p); - goto out; - } - pArg->nRef = 0; - pArg->xDestroy = xDestroy; - pArg->pUserData = p; - } - rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, - xSFunc, xStep, xFinal, xValue, xInverse, pArg - ); - if( pArg && pArg->nRef==0 ){ - assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) ); - xDestroy(p); - sqlite3_free(pArg); - } - - out: - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Create new user functions. -*/ -SQLITE_API int sqlite3_create_function( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*) -){ - return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, - xFinal, 0, 0, 0); -} -SQLITE_API int sqlite3_create_function_v2( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - void (*xDestroy)(void *) -){ - return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, - xFinal, 0, 0, xDestroy); -} -SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value **), - void (*xDestroy)(void *) -){ - return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep, - xFinal, xValue, xInverse, xDestroy); -} - -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *p, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -){ - int rc; - char *zFunc8; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); - rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0); - sqlite3DbFree(db, zFunc8); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} -#endif - - -/* -** The following is the implementation of an SQL function that always -** fails with an error message stating that the function is used in the -** wrong context. The sqlite3_overload_function() API might construct -** SQL function that use this routine so that the functions will exist -** for name resolution but are actually overloaded by the xFindFunction -** method of virtual tables. -*/ -static void sqlite3InvalidFunction( - sqlite3_context *context, /* The function calling context */ - int NotUsed, /* Number of arguments to the function */ - sqlite3_value **NotUsed2 /* Value of each argument */ -){ - const char *zName = (const char*)sqlite3_user_data(context); - char *zErr; - UNUSED_PARAMETER2(NotUsed, NotUsed2); - zErr = sqlite3_mprintf( - "unable to use function %s in the requested context", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); -} - -/* -** Declare that a function has been overloaded by a virtual table. -** -** If the function already exists as a regular global function, then -** this routine is a no-op. If the function does not exist, then create -** a new one that always throws a run-time error. -** -** When virtual tables intend to provide an overloaded function, they -** should call this routine to make sure the global function exists. -** A global function must exist in order for name resolution to work -** properly. -*/ -SQLITE_API int sqlite3_overload_function( - sqlite3 *db, - const char *zName, - int nArg -){ - int rc; - char *zCopy; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0; - sqlite3_mutex_leave(db->mutex); - if( rc ) return SQLITE_OK; - zCopy = sqlite3_mprintf("%s", zName); - if( zCopy==0 ) return SQLITE_NOMEM; - return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8, - zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free); -} - -#ifndef SQLITE_OMIT_TRACE -/* -** Register a trace function. The pArg from the previously registered trace -** is returned. -** -** A NULL trace function means that no tracing is executes. A non-NULL -** trace is a pointer to a function that is invoked at the start of each -** SQL statement. -*/ -#ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){ - void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pOld = db->pTraceArg; - db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0; - db->trace.xLegacy = xTrace; - db->pTraceArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pOld; -} -#endif /* SQLITE_OMIT_DEPRECATED */ - -/* Register a trace callback using the version-2 interface. -*/ -SQLITE_API int sqlite3_trace_v2( - sqlite3 *db, /* Trace this connection */ - unsigned mTrace, /* Mask of events to be traced */ - int(*xTrace)(unsigned,void*,void*,void*), /* Callback to invoke */ - void *pArg /* Context */ -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( mTrace==0 ) xTrace = 0; - if( xTrace==0 ) mTrace = 0; - db->mTrace = mTrace; - db->trace.xV2 = xTrace; - db->pTraceArg = pArg; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Register a profile function. The pArg from the previously registered -** profile function is returned. -** -** A NULL profile function means that no profiling is executes. A non-NULL -** profile is a pointer to a function that is invoked at the conclusion of -** each SQL statement that is run. -*/ -SQLITE_API void *sqlite3_profile( - sqlite3 *db, - void (*xProfile)(void*,const char*,sqlite_uint64), - void *pArg -){ - void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pOld = db->pProfileArg; - db->xProfile = xProfile; - db->pProfileArg = pArg; - db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK; - if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE; - sqlite3_mutex_leave(db->mutex); - return pOld; -} -#endif /* SQLITE_OMIT_DEPRECATED */ -#endif /* SQLITE_OMIT_TRACE */ - -/* -** Register a function to be invoked when a transaction commits. -** If the invoked function returns non-zero, then the commit becomes a -** rollback. -*/ -SQLITE_API void *sqlite3_commit_hook( - sqlite3 *db, /* Attach the hook to this database */ - int (*xCallback)(void*), /* Function to invoke on each commit */ - void *pArg /* Argument to the function */ -){ - void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pOld = db->pCommitArg; - db->xCommitCallback = xCallback; - db->pCommitArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pOld; -} - -/* -** Register a callback to be invoked each time a row is updated, -** inserted or deleted using this database connection. -*/ -SQLITE_API void *sqlite3_update_hook( - sqlite3 *db, /* Attach the hook to this database */ - void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), - void *pArg /* Argument to the function */ -){ - void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pRet = db->pUpdateArg; - db->xUpdateCallback = xCallback; - db->pUpdateArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} - -/* -** Register a callback to be invoked each time a transaction is rolled -** back by this database connection. -*/ -SQLITE_API void *sqlite3_rollback_hook( - sqlite3 *db, /* Attach the hook to this database */ - void (*xCallback)(void*), /* Callback function */ - void *pArg /* Argument to the function */ -){ - void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pRet = db->pRollbackArg; - db->xRollbackCallback = xCallback; - db->pRollbackArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} - -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** Register a callback to be invoked each time a row is updated, -** inserted or deleted using this database connection. -*/ -SQLITE_API void *sqlite3_preupdate_hook( - sqlite3 *db, /* Attach the hook to this database */ - void(*xCallback)( /* Callback function */ - void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), - void *pArg /* First callback argument */ -){ - void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 ){ - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pRet = db->pPreUpdateArg; - db->xPreUpdateCallback = xCallback; - db->pPreUpdateArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} -#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 sqlite3_autovacuum_pages( - 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( !sqlite3SafetyCheckOk(db) ){ - if( xDestructor ) xDestructor(pArg); - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( db->xAutovacDestr ){ - db->xAutovacDestr(db->pAutovacPagesArg); - } - db->xAutovacPages = xCallback; - db->pAutovacPagesArg = pArg; - db->xAutovacDestr = xDestructor; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - - -#ifndef SQLITE_OMIT_WAL -/* -** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). -** Invoke sqlite3_wal_checkpoint if the number of frames in the log file -** is greater than sqlite3.pWalArg cast to an integer (the value configured by -** wal_autocheckpoint()). -*/ -SQLITE_PRIVATE int sqlite3WalDefaultHook( - void *pClientData, /* Argument */ - sqlite3 *db, /* Connection */ - const char *zDb, /* Database */ - int nFrame /* Size of WAL */ -){ - if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){ - sqlite3BeginBenignMalloc(); - sqlite3_wal_checkpoint(db, zDb); - sqlite3EndBenignMalloc(); - } - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_WAL */ - -/* -** Configure an sqlite3_wal_hook() callback to automatically checkpoint -** a database after committing a transaction if there are nFrame or -** more frames in the log file. Passing zero or a negative value as the -** nFrame parameter disables automatic checkpoints entirely. -** -** The callback registered by this function replaces any existing callback -** registered using sqlite3_wal_hook(). Likewise, registering a callback -** using sqlite3_wal_hook() disables the automatic checkpoint mechanism -** configured by this function. -*/ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ -#ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(nFrame); -#else -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - if( nFrame>0 ){ - sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); - }else{ - sqlite3_wal_hook(db, 0, 0); - } -#endif - return SQLITE_OK; -} - -/* -** Register a callback to be invoked each time a transaction is written -** into the write-ahead-log by this database connection. -*/ -SQLITE_API void *sqlite3_wal_hook( - sqlite3 *db, /* Attach the hook to this db handle */ - int(*xCallback)(void *, sqlite3*, const char*, int), - void *pArg /* First argument passed to xCallback() */ -){ -#ifndef SQLITE_OMIT_WAL - void *pRet; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - sqlite3_mutex_enter(db->mutex); - pRet = db->pWalArg; - db->xWalCallback = xCallback; - db->pWalArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -#else - return 0; -#endif -} - -/* -** Checkpoint database zDb. -*/ -SQLITE_API int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ -){ -#ifdef SQLITE_OMIT_WAL - return SQLITE_OK; -#else - int rc; /* Return code */ - int iDb; /* Schema to checkpoint */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - - /* Initialize the output variables to -1 in case an error occurs. */ - if( pnLog ) *pnLog = -1; - if( pnCkpt ) *pnCkpt = -1; - - assert( SQLITE_CHECKPOINT_PASSIVE==0 ); - assert( SQLITE_CHECKPOINT_FULL==1 ); - assert( SQLITE_CHECKPOINT_RESTART==2 ); - assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); - if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ - /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint - ** mode: */ - return SQLITE_MISUSE_BKPT; - } - - sqlite3_mutex_enter(db->mutex); - if( zDb && zDb[0] ){ - iDb = sqlite3FindDbName(db, zDb); - }else{ - iDb = SQLITE_MAX_DB; /* This means process all schemas */ - } - if( iDb<0 ){ - rc = SQLITE_ERROR; - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); - }else{ - db->busyHandler.nBusy = 0; - rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); - sqlite3Error(db, rc); - } - rc = sqlite3ApiExit(db, rc); - - /* If there are no active statements, clear the interrupt flag at this - ** point. */ - if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); - } - - sqlite3_mutex_leave(db->mutex); - return rc; -#endif -} - - -/* -** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points -** to contains a zero-length string, all attached databases are -** checkpointed. -*/ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ - /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to - ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ - return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); -} - -#ifndef SQLITE_OMIT_WAL -/* -** Run a checkpoint on database iDb. This is a no-op if database iDb is -** not currently open in WAL mode. -** -** If a transaction is open on the database being checkpointed, this -** function returns SQLITE_LOCKED and a checkpoint is not attempted. If -** an error occurs while running the checkpoint, an SQLite error code is -** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK. -** -** The mutex on database handle db should be held by the caller. The mutex -** associated with the specific b-tree being checkpointed is taken by -** this function while the checkpoint is running. -** -** 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. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART -** or TRUNCATE. -*/ -SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ - int rc = SQLITE_OK; /* Return code */ - int i; /* Used to iterate through attached dbs */ - int bBusy = 0; /* True if SQLITE_BUSY has been encountered */ - - assert( 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; inDb && rc==SQLITE_OK; i++){ - if( i==iDb || iDb==SQLITE_MAX_DB ){ - rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt); - pnLog = 0; - pnCkpt = 0; - if( rc==SQLITE_BUSY ){ - bBusy = 1; - rc = SQLITE_OK; - } - } - } - - return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc; -} -#endif /* SQLITE_OMIT_WAL */ - -/* -** This function returns true if main-memory should be used instead of -** a temporary file for transient pager files and statement journals. -** The value returned depends on the value of db->temp_store (runtime -** parameter) and the compile time value of SQLITE_TEMP_STORE. The -** following table describes the relationship between these two values -** and this functions return value. -** -** SQLITE_TEMP_STORE db->temp_store Location of temporary database -** ----------------- -------------- ------------------------------ -** 0 any file (return 0) -** 1 1 file (return 0) -** 1 2 memory (return 1) -** 1 0 file (return 0) -** 2 1 file (return 0) -** 2 2 memory (return 1) -** 2 0 memory (return 1) -** 3 any memory (return 1) -*/ -SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ -#if SQLITE_TEMP_STORE==1 - return ( db->temp_store==2 ); -#endif -#if SQLITE_TEMP_STORE==2 - return ( db->temp_store!=1 ); -#endif -#if SQLITE_TEMP_STORE==3 - UNUSED_PARAMETER(db); - return 1; -#endif -#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 - UNUSED_PARAMETER(db); - return 0; -#endif -} - -/* -** Return UTF-8 encoded English language explanation of the most recent -** error. -*/ -SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ - const char *z; - if( !db ){ - return sqlite3ErrStr(SQLITE_NOMEM_BKPT); - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return sqlite3ErrStr(SQLITE_MISUSE_BKPT); - } - sqlite3_mutex_enter(db->mutex); - if( db->mallocFailed ){ - z = sqlite3ErrStr(SQLITE_NOMEM_BKPT); - }else{ - testcase( db->pErr==0 ); - z = db->errCode ? (char*)sqlite3_value_text(db->pErr) : 0; - assert( !db->mallocFailed ); - if( z==0 ){ - z = sqlite3ErrStr(db->errCode); - } - } - sqlite3_mutex_leave(db->mutex); - return z; -} - -/* -** Return the byte offset of the most recent error -*/ -SQLITE_API int sqlite3_error_offset(sqlite3 *db){ - int iOffset = -1; - if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){ - sqlite3_mutex_enter(db->mutex); - iOffset = db->errByteOffset; - sqlite3_mutex_leave(db->mutex); - } - return iOffset; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Return UTF-16 encoded English language explanation of the most recent -** error. -*/ -SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ - static const u16 outOfMem[] = { - 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 - }; - static const u16 misuse[] = { - 'b', 'a', 'd', ' ', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ' ', - 'o', 'r', ' ', 'o', 't', 'h', 'e', 'r', ' ', 'A', 'P', 'I', ' ', - 'm', 'i', 's', 'u', 's', 'e', 0 - }; - - const void *z; - if( !db ){ - return (void *)outOfMem; - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return (void *)misuse; - } - sqlite3_mutex_enter(db->mutex); - if( db->mallocFailed ){ - z = (void *)outOfMem; - }else{ - z = sqlite3_value_text16(db->pErr); - if( z==0 ){ - sqlite3ErrorWithMsg(db, db->errCode, sqlite3ErrStr(db->errCode)); - z = sqlite3_value_text16(db->pErr); - } - /* A malloc() may have failed within the call to sqlite3_value_text16() - ** above. If this is the case, then the db->mallocFailed flag needs to - ** be cleared before returning. Do this directly, instead of via - ** sqlite3ApiExit(), to avoid setting the database handle error message. - */ - sqlite3OomClear(db); - } - sqlite3_mutex_leave(db->mutex); - return z; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the most recent error code generated by an SQLite routine. If NULL is -** passed to this function, we assume a malloc() failed during sqlite3_open(). -*/ -SQLITE_API int sqlite3_errcode(sqlite3 *db){ - if( db && !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( !db || db->mallocFailed ){ - return SQLITE_NOMEM_BKPT; - } - return db->errCode & db->errMask; -} -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ - if( db && !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( !db || db->mallocFailed ){ - return SQLITE_NOMEM_BKPT; - } - return db->errCode; -} -SQLITE_API int sqlite3_system_errno(sqlite3 *db){ - return db ? db->iSysErrno : 0; -} - -/* -** Return a string that describes the kind of error specified in the -** argument. For now, this simply calls the internal sqlite3ErrStr() -** function. -*/ -SQLITE_API const char *sqlite3_errstr(int rc){ - return sqlite3ErrStr(rc); -} - -/* -** Create a new collating function for database "db". The name is zName -** and the encoding is enc. -*/ -static int createCollation( - sqlite3* db, - const char *zName, - u8 enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDel)(void*) -){ - CollSeq *pColl; - int enc2; - - assert( sqlite3_mutex_held(db->mutex) ); - - /* If SQLITE_UTF16 is specified as the encoding type, transform this - ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the - ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. - */ - enc2 = enc; - testcase( enc2==SQLITE_UTF16 ); - testcase( enc2==SQLITE_UTF16_ALIGNED ); - if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ - enc2 = SQLITE_UTF16NATIVE; - } - if( enc2SQLITE_UTF16BE ){ - return SQLITE_MISUSE_BKPT; - } - - /* Check if this call is removing or replacing an existing collation - ** sequence. If so, and there are active VMs, return busy. If there - ** are no active VMs, invalidate any pre-compiled statements. - */ - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); - if( pColl && pColl->xCmp ){ - if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, - "unable to delete/modify collation sequence due to active statements"); - return SQLITE_BUSY; - } - sqlite3ExpirePreparedStatements(db, 0); - - /* If collation sequence pColl was created directly by a call to - ** sqlite3_create_collation, and not generated by synthCollSeq(), - ** then any copies made by synthCollSeq() need to be invalidated. - ** Also, collation destructor - CollSeq.xDel() - function may need - ** to be called. - */ - if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ - CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName); - int j; - for(j=0; j<3; j++){ - CollSeq *p = &aColl[j]; - if( p->enc==pColl->enc ){ - if( p->xDel ){ - p->xDel(p->pUser); - } - p->xCmp = 0; - } - } - } - } - - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); - if( pColl==0 ) return SQLITE_NOMEM_BKPT; - pColl->xCmp = xCompare; - pColl->pUser = pCtx; - pColl->xDel = xDel; - pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); - sqlite3Error(db, SQLITE_OK); - return SQLITE_OK; -} - - -/* -** This array defines hard upper bounds on limit values. The -** initializer must be kept in sync with the SQLITE_LIMIT_* -** #defines in sqlite3.h. -*/ -static const int aHardLimit[] = { - SQLITE_MAX_LENGTH, - SQLITE_MAX_SQL_LENGTH, - SQLITE_MAX_COLUMN, - SQLITE_MAX_EXPR_DEPTH, - SQLITE_MAX_COMPOUND_SELECT, - SQLITE_MAX_VDBE_OP, - SQLITE_MAX_FUNCTION_ARG, - SQLITE_MAX_ATTACHED, - SQLITE_MAX_LIKE_PATTERN_LENGTH, - SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */ - SQLITE_MAX_TRIGGER_DEPTH, - SQLITE_MAX_WORKER_THREADS, -}; - -/* -** Make sure the hard limits are set to reasonable values -*/ -#if SQLITE_MAX_LENGTH<100 -# error SQLITE_MAX_LENGTH must be at least 100 -#endif -#if SQLITE_MAX_SQL_LENGTH<100 -# error SQLITE_MAX_SQL_LENGTH must be at least 100 -#endif -#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH -# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH -#endif -#if SQLITE_MAX_COMPOUND_SELECT<2 -# error SQLITE_MAX_COMPOUND_SELECT must be at least 2 -#endif -#if SQLITE_MAX_VDBE_OP<40 -# error SQLITE_MAX_VDBE_OP must be at least 40 -#endif -#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>32767 -# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 32767 -#endif -#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 -# error SQLITE_MAX_ATTACHED must be between 0 and 125 -#endif -#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 -# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 -#endif -#if SQLITE_MAX_COLUMN>32767 -# error SQLITE_MAX_COLUMN must not exceed 32767 -#endif -#if SQLITE_MAX_TRIGGER_DEPTH<1 -# error SQLITE_MAX_TRIGGER_DEPTH must be at least 1 -#endif -#if SQLITE_MAX_WORKER_THREADS<0 || SQLITE_MAX_WORKER_THREADS>50 -# error SQLITE_MAX_WORKER_THREADS must be between 0 and 50 -#endif - - -/* -** Change the value of a limit. Report the old value. -** If an invalid limit index is supplied, report -1. -** Make no changes but still report the old value if the -** new limit is negative. -** -** A new lower limit does not shrink existing constructs. -** It merely prevents new constructs that exceed the limit -** from forming. -*/ -SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ - int oldLimit; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif - - /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME - ** there is a hard upper bound set at compile-time by a C preprocessor - ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to - ** "_MAX_".) - */ - assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); - assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); - assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); - assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); - assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED ); - assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]== - SQLITE_MAX_LIKE_PATTERN_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); - assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS ); - assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) ); - - - if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ - return -1; - } - oldLimit = db->aLimit[limitId]; - if( newLimit>=0 ){ /* IMP: R-52476-28732 */ - if( newLimit>aHardLimit[limitId] ){ - newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ - }else if( newLimitaLimit[limitId] = newLimit; - } - return oldLimit; /* IMP: R-53341-35419 */ -} - -/* -** This function is used to parse both URIs and non-URI filenames passed by the -** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database -** URIs specified as part of ATTACH statements. -** -** The first argument to this function is the name of the VFS to use (or -** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx" -** query parameter. The second argument contains the URI (or non-URI filename) -** itself. When this function is called the *pFlags variable should contain -** the default flags to open the database handle with. The value stored in -** *pFlags may be updated before returning if the URI filename contains -** "cache=xxx" or "mode=xxx" query parameters. -** -** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to -** the VFS that should be used to open the database file. *pzFile is set to -** point to a buffer containing the name of the file to open. The value -** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter() -** and is in the same format as names created using sqlite3_create_filename(). -** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on -** the value returned in *pzFile to avoid a memory leak. -** -** If an error occurs, then an SQLite error code is returned and *pzErrMsg -** may be set to point to a buffer containing an English language error -** message. It is the responsibility of the caller to eventually release -** this buffer by calling sqlite3_free(). -*/ -SQLITE_PRIVATE int sqlite3ParseUri( - const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */ - const char *zUri, /* Nul-terminated URI to parse */ - unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */ - sqlite3_vfs **ppVfs, /* OUT: VFS to use */ - char **pzFile, /* OUT: Filename component of URI */ - char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */ -){ - int rc = SQLITE_OK; - unsigned int flags = *pFlags; - const char *zVfs = zDefaultVfs; - char *zFile; - char c; - int nUri = sqlite3Strlen30(zUri); - - assert( *pzErrMsg==0 ); - - if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ - || AtomicLoad(&sqlite3GlobalConfig.bOpenUri)) /* IMP: R-51689-46548 */ - && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ - ){ - char *zOpt; - int eState; /* Parser state when parsing URI */ - int iIn; /* Input character index */ - int iOut = 0; /* Output character index */ - u64 nByte = nUri+8; /* Bytes of space to allocate */ - - /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen - ** method that there may be extra parameters following the file-name. */ - flags |= SQLITE_OPEN_URI; - - for(iIn=0; iIn=0 && octet<256 ); - if( octet==0 ){ -#ifndef SQLITE_ENABLE_URI_00_ERROR - /* This branch is taken when "%00" appears within the URI. In this - ** case we ignore all text in the remainder of the path, name or - ** value currently being parsed. So ignore the current character - ** and skip to the next "?", "=" or "&", as appropriate. */ - while( (c = zUri[iIn])!=0 && c!='#' - && (eState!=0 || c!='?') - && (eState!=1 || (c!='=' && c!='&')) - && (eState!=2 || c!='&') - ){ - iIn++; - } - continue; -#else - /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ - *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); - rc = SQLITE_ERROR; - goto parse_uri_out; -#endif - } - c = octet; - }else if( eState==1 && (c=='&' || c=='=') ){ - if( zFile[iOut-1]==0 ){ - /* An empty option name. Ignore this option altogether. */ - while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++; - continue; - } - if( c=='&' ){ - zFile[iOut++] = '\0'; - }else{ - eState = 2; - } - c = 0; - }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){ - c = 0; - eState = 1; - } - zFile[iOut++] = c; - } - if( eState==1 ) zFile[iOut++] = '\0'; - memset(zFile+iOut, 0, 4); /* end-of-options + empty journal filenames */ - - /* Check if there were any options specified that should be interpreted - ** here. Options that are interpreted here include "vfs" and those that - ** correspond to flags that may be passed to the sqlite3_open_v2() - ** method. */ - zOpt = &zFile[sqlite3Strlen30(zFile)+1]; - while( zOpt[0] ){ - int nOpt = sqlite3Strlen30(zOpt); - char *zVal = &zOpt[nOpt+1]; - int nVal = sqlite3Strlen30(zVal); - - if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){ - zVfs = zVal; - }else{ - struct OpenMode { - const char *z; - int mode; - } *aMode = 0; - char *zModeType = 0; - int mask = 0; - int limit = 0; - - if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){ - static struct OpenMode aCacheMode[] = { - { "shared", SQLITE_OPEN_SHAREDCACHE }, - { "private", SQLITE_OPEN_PRIVATECACHE }, - { 0, 0 } - }; - - mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE; - aMode = aCacheMode; - limit = mask; - zModeType = "cache"; - } - if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){ - static struct OpenMode aOpenMode[] = { - { "ro", SQLITE_OPEN_READONLY }, - { "rw", SQLITE_OPEN_READWRITE }, - { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE }, - { "memory", SQLITE_OPEN_MEMORY }, - { 0, 0 } - }; - - mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY; - aMode = aOpenMode; - limit = mask & flags; - zModeType = "access"; - } - - if( aMode ){ - int i; - int mode = 0; - for(i=0; aMode[i].z; i++){ - const char *z = aMode[i].z; - if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){ - mode = aMode[i].mode; - break; - } - } - if( mode==0 ){ - *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal); - rc = SQLITE_ERROR; - goto parse_uri_out; - } - if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){ - *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s", - zModeType, zVal); - rc = SQLITE_PERM; - goto parse_uri_out; - } - flags = (flags & ~mask) | mode; - } - } - - zOpt = &zVal[nVal+1]; - } - - }else{ - zFile = sqlite3_malloc64(nUri+8); - if( !zFile ) return SQLITE_NOMEM_BKPT; - memset(zFile, 0, 4); - zFile += 4; - if( nUri ){ - memcpy(zFile, zUri, nUri); - } - memset(zFile+nUri, 0, 4); - flags &= ~SQLITE_OPEN_URI; - } - - *ppVfs = sqlite3_vfs_find(zVfs); - if( *ppVfs==0 ){ - *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs); - rc = SQLITE_ERROR; - } - parse_uri_out: - if( rc!=SQLITE_OK ){ - sqlite3_free_filename(zFile); - zFile = 0; - } - *pFlags = flags; - *pzFile = zFile; - return rc; -} - -/* -** This routine does the core work of extracting URI parameters from a -** database filename for the sqlite3_uri_parameter() interface. -*/ -static const char *uriParameter(const char *zFilename, const char *zParam){ - zFilename += sqlite3Strlen30(zFilename) + 1; - while( ALWAYS(zFilename!=0) && zFilename[0] ){ - int x = strcmp(zFilename, zParam); - zFilename += sqlite3Strlen30(zFilename) + 1; - if( x==0 ) return zFilename; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return 0; -} - -/* BEGIN SQLCIPHER */ -#if defined(SQLITE_HAS_CODEC) -/* -** Process URI filename query parameters relevant to the SQLite Encryption -** Extension. Return true if any of the relevant query parameters are -** seen and return false if not. -*/ -SQLITE_PRIVATE int sqlite3CodecQueryParameters( - sqlite3 *db, /* Database connection */ - const char *zDb, /* Which schema is being created/attached */ - const char *zUri /* URI filename */ -){ - const char *zKey; - if( zUri==0 ){ - return 0; - }else if( (zKey = uriParameter(zUri, "hexkey"))!=0 && zKey[0] ){ - u8 iByte; - int i; - char zDecoded[40]; - for(i=0, iByte=0; imutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); - if( db->mutex==0 ){ - sqlite3_free(db); - db = 0; - goto opendb_out; - } - if( isThreadsafe==0 ){ - sqlite3MutexWarnOnContention(db->mutex); - } - } - sqlite3_mutex_enter(db->mutex); - db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff; - db->nDb = 2; - db->eOpenState = SQLITE_STATE_BUSY; - db->aDb = db->aDbStatic; - db->lookaside.bDisable = 1; - db->lookaside.sz = 0; - - assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); - memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); - db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; - db->autoCommit = 1; - db->nextAutovac = -1; - db->szMmap = sqlite3GlobalConfig.szMmap; - db->nextPagesize = 0; - db->init.azInit = 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 - | SQLITE_CacheSpill - | SQLITE_AttachCreate - | SQLITE_AttachWrite - | SQLITE_Comments -#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0 - | SQLITE_TrustedSchema -#endif -/* The SQLITE_DQS compile-time option determines the default settings -** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML. -** -** SQLITE_DQS SQLITE_DBCONFIG_DQS_DDL SQLITE_DBCONFIG_DQS_DML -** ---------- ----------------------- ----------------------- -** undefined on on -** 3 on on -** 2 on off -** 1 off on -** 0 off off -** -** Legacy behavior is 3 (double-quoted string literals are allowed anywhere) -** and so that is the default. But developers are encouraged to use -** -DSQLITE_DQS=0 (best) or -DSQLITE_DQS=1 (second choice) if possible. -*/ -#if !defined(SQLITE_DQS) -# define SQLITE_DQS 3 -#endif -#if (SQLITE_DQS&1)==1 - | SQLITE_DqsDML -#endif -#if (SQLITE_DQS&2)==2 - | SQLITE_DqsDDL -#endif - -#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX - | SQLITE_AutoIndex -#endif -#if SQLITE_DEFAULT_CKPTFULLFSYNC - | SQLITE_CkptFullFSync -#endif -#if SQLITE_DEFAULT_FILE_FORMAT<4 - | SQLITE_LegacyFileFmt -#endif -#ifdef SQLITE_ENABLE_LOAD_EXTENSION - | SQLITE_LoadExtension -#endif -#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS - | SQLITE_RecTriggers -#endif -#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS - | SQLITE_ForeignKeys -#endif -#if defined(SQLITE_REVERSE_UNORDERED_SELECTS) - | SQLITE_ReverseOrder -#endif -#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) - | SQLITE_CellSizeCk -#endif -#if defined(SQLITE_ENABLE_FTS3_TOKENIZER) - | SQLITE_Fts3Tokenizer -#endif -#if defined(SQLITE_ENABLE_QPSG) - | SQLITE_EnableQPSG -#endif -#if defined(SQLITE_DEFAULT_DEFENSIVE) - | SQLITE_Defensive -#endif -#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE) - | SQLITE_LegacyAlter -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) - | SQLITE_StmtScanStatus -#endif - ; - sqlite3HashInit(&db->aCollSeq); -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3HashInit(&db->aModule); -#endif - - /* Add the default collation sequence BINARY. BINARY works for both UTF-8 - ** and UTF-16, so add a version for each to avoid any unnecessary - ** conversions. The only error that can occur here is a malloc() failure. - ** - ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating - ** functions: - */ - createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0); - createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0); - createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0); - createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); - createCollation(db, "RTRIM", SQLITE_UTF8, 0, rtrimCollFunc, 0); - if( db->mallocFailed ){ - goto opendb_out; - } - -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) - /* Process magic filenames ":localStorage:" and ":sessionStorage:" */ - if( zFilename && zFilename[0]==':' ){ - if( strcmp(zFilename, ":localStorage:")==0 ){ - zFilename = "file:local?vfs=kvvfs"; - flags |= SQLITE_OPEN_URI; - }else if( strcmp(zFilename, ":sessionStorage:")==0 ){ - zFilename = "file:session?vfs=kvvfs"; - flags |= SQLITE_OPEN_URI; - } - } -#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */ - - /* Parse the filename/URI argument - ** - ** Only allow sensible combinations of bits in the flags argument. - ** Throw an error if any non-sense combination is used. If we - ** do not block illegal combinations here, it could trigger - ** assert() statements in deeper layers. Sensible combinations - ** are: - ** - ** 1: SQLITE_OPEN_READONLY - ** 2: SQLITE_OPEN_READWRITE - ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE - */ - db->openFlags = flags; - assert( SQLITE_OPEN_READONLY == 0x01 ); - assert( SQLITE_OPEN_READWRITE == 0x02 ); - assert( SQLITE_OPEN_CREATE == 0x04 ); - testcase( (1<<(flags&7))==0x02 ); /* READONLY */ - testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ - testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ - if( ((1<<(flags&7)) & 0x46)==0 ){ - rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */ - }else{ - if( zFilename==0 ) zFilename = ":memory:"; - rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); - } - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); - sqlite3_free(zErrMsg); - goto opendb_out; - } - assert( db->pVfs!=0 ); -#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL) - if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){ - db->temp_store = 2; - } -#endif - - /* Open the backend database driver */ - rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, - flags | SQLITE_OPEN_MAIN_DB); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_IOERR_NOMEM ){ - rc = SQLITE_NOMEM_BKPT; - } - sqlite3Error(db, rc); - goto opendb_out; - } - sqlite3BtreeEnter(db->aDb[0].pBt); - db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); - if( !db->mallocFailed ){ - sqlite3SetTextEncoding(db, SCHEMA_ENC(db)); - } - sqlite3BtreeLeave(db->aDb[0].pBt); - db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); - - /* The default safety_level for the main database is FULL; for the temp - ** database it is OFF. This matches the pager layer defaults. - */ - db->aDb[0].zDbSName = "main"; - db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - db->aDb[1].zDbSName = "temp"; - db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; - - db->eOpenState = SQLITE_STATE_OPEN; - if( db->mallocFailed ){ - goto opendb_out; - } - - /* Register all built-in functions, but do not attempt to read the - ** database schema yet. This is delayed until the first time the database - ** is accessed. - */ - sqlite3Error(db, SQLITE_OK); - sqlite3RegisterPerConnectionBuiltinFunctions(db); - rc = sqlite3_errcode(db); - - - /* Load compiled-in extensions */ - for(i=0; rc==SQLITE_OK && imDbFlags |= DBFLAG_InternalFunc; -#endif - - /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking - ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking - ** mode. Doing nothing at all also makes NORMAL the default. - */ -#ifdef SQLITE_DEFAULT_LOCKING_MODE - db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; - sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), - SQLITE_DEFAULT_LOCKING_MODE); -#endif - - if( rc ) sqlite3Error(db, rc); - - /* Enable the lookaside-malloc subsystem */ - setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, - sqlite3GlobalConfig.nLookaside); - - sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); - -opendb_out: - if( db ){ - assert( db->mutex!=0 || isThreadsafe==0 - || sqlite3GlobalConfig.bFullMutex==0 ); - sqlite3_mutex_leave(db->mutex); - } - rc = sqlite3_errcode(db); - assert( db!=0 || (rc&0xff)==SQLITE_NOMEM ); - if( (rc&0xff)==SQLITE_NOMEM ){ - sqlite3_close(db); - db = 0; - }else if( rc!=SQLITE_OK ){ - db->eOpenState = SQLITE_STATE_SICK; - } - *ppDb = db; -#ifdef SQLITE_ENABLE_SQLLOG - if( sqlite3GlobalConfig.xSqllog ){ - /* Opening a db handle. Fourth parameter is passed 0. */ - void *pArg = sqlite3GlobalConfig.pSqllogArg; - sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); - } -#endif -/* BEGIN SQLCIPHER */ -#if defined(SQLITE_HAS_CODEC) - if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen); -#endif -/* END SQLCIPHER */ - sqlite3_free_filename(zOpen); - return rc; -} - - -/* -** Open a new database handle. -*/ -SQLITE_API int sqlite3_open( - const char *zFilename, - sqlite3 **ppDb -){ - return openDatabase(zFilename, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); -} -SQLITE_API int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -){ - return openDatabase(filename, ppDb, (unsigned int)flags, zVfs); -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Open a new database handle. -*/ -SQLITE_API int sqlite3_open16( - const void *zFilename, - sqlite3 **ppDb -){ - char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ - sqlite3_value *pVal; - int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppDb==0 ) return SQLITE_MISUSE_BKPT; -#endif - *ppDb = 0; -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - if( zFilename==0 ) zFilename = "\000\000"; - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); - if( zFilename8 ){ - rc = openDatabase(zFilename8, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); - assert( *ppDb || rc==SQLITE_NOMEM ); - if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ - SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; - } - }else{ - rc = SQLITE_NOMEM_BKPT; - } - sqlite3ValueFree(pVal); - - return rc & 0xff; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation( - sqlite3* db, - const char *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*) -){ - return sqlite3_create_collation_v2(db, zName, enc, pCtx, xCompare, 0); -} - -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation_v2( - sqlite3* db, - const char *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDel)(void*) -){ - int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation16( - sqlite3* db, - const void *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*) -){ - int rc = SQLITE_OK; - char *zName8; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); - if( zName8 ){ - rc = createCollation(db, zName8, (u8)enc, pCtx, xCompare, 0); - sqlite3DbFree(db, zName8); - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Register a collation sequence factory callback with the database handle -** db. Replace any previously installed collation sequence factory. -*/ -SQLITE_API int sqlite3_collation_needed( - sqlite3 *db, - void *pCollNeededArg, - void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - db->xCollNeeded = xCollNeeded; - db->xCollNeeded16 = 0; - db->pCollNeededArg = pCollNeededArg; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Register a collation sequence factory callback with the database handle -** db. Replace any previously installed collation sequence factory. -*/ -SQLITE_API int sqlite3_collation_needed16( - sqlite3 *db, - void *pCollNeededArg, - void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - db->xCollNeeded = 0; - db->xCollNeeded16 = xCollNeeded16; - db->pCollNeededArg = pCollNeededArg; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Find existing client data. -*/ -SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){ - DbClientData *p; - sqlite3_mutex_enter(db->mutex); - for(p=db->pDbData; p; p=p->pNext){ - if( strcmp(p->zName, zName)==0 ){ - void *pResult = p->pData; - sqlite3_mutex_leave(db->mutex); - return pResult; - } - } - sqlite3_mutex_leave(db->mutex); - return 0; -} - -/* -** Add new client data to a database connection. -*/ -SQLITE_API int sqlite3_set_clientdata( - sqlite3 *db, /* Attach client data to this connection */ - const char *zName, /* Name of the client data */ - void *pData, /* The client data itself */ - void (*xDestructor)(void*) /* Destructor */ -){ - DbClientData *p, **pp; - sqlite3_mutex_enter(db->mutex); - pp = &db->pDbData; - for(p=db->pDbData; p && strcmp(p->zName,zName); p=p->pNext){ - pp = &p->pNext; - } - if( p ){ - assert( p->pData!=0 ); - if( p->xDestructor ) p->xDestructor(p->pData); - if( pData==0 ){ - *pp = p->pNext; - sqlite3_free(p); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; - } - }else if( pData==0 ){ - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; - }else{ - size_t n = strlen(zName); - p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) ); - if( p==0 ){ - if( xDestructor ) xDestructor(pData); - sqlite3_mutex_leave(db->mutex); - return SQLITE_NOMEM; - } - memcpy(p->zName, zName, n+1); - p->pNext = db->pDbData; - db->pDbData = p; - } - p->pData = pData; - p->xDestructor = xDestructor; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** This function is now an anachronism. It used to be used to recover from a -** malloc() failure, but SQLite now does this automatically. -*/ -SQLITE_API int sqlite3_global_recover(void){ - return SQLITE_OK; -} -#endif - -/* -** Test to see whether or not the database connection is in autocommit -** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on -** by default. Autocommit is disabled by a BEGIN statement and reenabled -** by the next COMMIT or ROLLBACK. -*/ -SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->autoCommit; -} - -/* -** The following routines are substitutes for constants SQLITE_CORRUPT, -** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_NOMEM and possibly other error -** constants. They serve two purposes: -** -** 1. Serve as a convenient place to set a breakpoint in a debugger -** to detect when version error conditions occurs. -** -** 2. Invoke sqlite3_log() to provide the source code location where -** a low-level error is first detected. -*/ -SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ - sqlite3_log(iErr, "%s at line %d of [%.10s]", - zType, lineno, 20+sqlite3_sourceid()); - return iErr; -} -SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); -} -SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse"); -} -SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file"); -} -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) -SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ - char zMsg[100]; - sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); -} -#endif -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3NomemError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM"); -} -SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); -} -#endif - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** This is a convenience routine that makes sure that all thread-specific -** data for this thread has been deallocated. -** -** SQLite no longer uses thread-specific data so this routine is now a -** no-op. It is retained for historical compatibility. -*/ -SQLITE_API void sqlite3_thread_cleanup(void){ -} -#endif - -/* -** Return meta information about a specific column of a database table. -** See comment in sqlite3.h (sqlite.h.in) for details. -*/ -SQLITE_API int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -){ - int rc; - char *zErrMsg = 0; - Table *pTab = 0; - Column *pCol = 0; - int iCol = 0; - char const *zDataType = 0; - char const *zCollSeq = 0; - int notnull = 0; - int primarykey = 0; - int autoinc = 0; - - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - - /* Ensure the database schema has been loaded */ - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - rc = sqlite3Init(db, &zErrMsg); - if( SQLITE_OK!=rc ){ - goto error_out; - } - - /* Locate the table in question */ - pTab = sqlite3FindTable(db, zTableName, zDbName); - if( !pTab || IsView(pTab) ){ - pTab = 0; - goto error_out; - } - - /* Find the column for which info is requested */ - if( zColumnName==0 ){ - /* Query for existence of table only */ - }else{ - iCol = sqlite3ColumnIndex(pTab, zColumnName); - if( iCol>=0 ){ - pCol = &pTab->aCol[iCol]; - }else{ - if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ - iCol = pTab->iPKey; - pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; - }else{ - pTab = 0; - goto error_out; - } - } - } - - /* The following block stores the meta information that will be returned - ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey - ** and autoinc. At this point there are two possibilities: - ** - ** 1. The specified column name was rowid", "oid" or "_rowid_" - ** and there is no explicitly declared IPK column. - ** - ** 2. The table is not a view and the column name identified an - ** explicitly declared column. Copy meta information from *pCol. - */ - if( pCol ){ - zDataType = sqlite3ColumnType(pCol,0); - zCollSeq = sqlite3ColumnColl(pCol); - notnull = pCol->notNull!=0; - primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; - autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; - }else{ - zDataType = "INTEGER"; - primarykey = 1; - } - if( !zCollSeq ){ - zCollSeq = sqlite3StrBINARY; - } - -error_out: - sqlite3BtreeLeaveAll(db); - - /* Whether the function call succeeded or failed, set the output parameters - ** to whatever their local counterparts contain. If an error did occur, - ** this has the effect of zeroing all output parameters. - */ - if( pzDataType ) *pzDataType = zDataType; - if( pzCollSeq ) *pzCollSeq = zCollSeq; - if( pNotNull ) *pNotNull = notnull; - if( pPrimaryKey ) *pPrimaryKey = primarykey; - if( pAutoinc ) *pAutoinc = autoinc; - - if( SQLITE_OK==rc && !pTab ){ - sqlite3DbFree(db, zErrMsg); - zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName, - zColumnName); - rc = SQLITE_ERROR; - } - sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg); - sqlite3DbFree(db, zErrMsg); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -SQLITE_API int sqlite3_sleep(int ms){ - sqlite3_vfs *pVfs; - int rc; - pVfs = sqlite3_vfs_find(0); - if( pVfs==0 ) return 0; - - /* This function works in milliseconds, but the underlying OsSleep() - ** API uses microseconds. Hence the 1000's. - */ - rc = (sqlite3OsSleep(pVfs, ms<0 ? 0 : 1000*ms)/1000); - return rc; -} - -/* -** Enable or disable the extended result codes. -*/ -SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - db->errMask = onoff ? 0xffffffff : 0xff; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Invoke the xFileControl method on a particular database. -*/ -SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ - int rc = SQLITE_ERROR; - Btree *pBtree; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - pBtree = sqlite3DbNameToBtree(db, zDbName); - if( pBtree ){ - Pager *pPager; - sqlite3_file *fd; - sqlite3BtreeEnter(pBtree); - pPager = sqlite3BtreePager(pBtree); - assert( pPager!=0 ); - fd = sqlite3PagerFile(pPager); - assert( fd!=0 ); - if( op==SQLITE_FCNTL_FILE_POINTER ){ - *(sqlite3_file**)pArg = fd; - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_VFS_POINTER ){ - *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ - *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_DATA_VERSION ){ - *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){ - int iNew = *(int*)pArg; - *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree); - if( iNew>=0 && iNew<=255 ){ - sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0); - } - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_RESET_CACHE ){ - sqlite3BtreeClearCache(pBtree); - rc = SQLITE_OK; - }else{ - int nSave = db->busyHandler.nBusy; - rc = sqlite3OsFileControl(fd, op, pArg); - db->busyHandler.nBusy = nSave; - } - sqlite3BtreeLeave(pBtree); - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Interface to the testing logic. -*/ -SQLITE_API int sqlite3_test_control(int op, ...){ - int rc = 0; -#ifdef SQLITE_UNTESTABLE - UNUSED_PARAMETER(op); -#else - va_list ap; - va_start(ap, op); - switch( op ){ - - /* - ** Save the current state of the PRNG. - */ - case SQLITE_TESTCTRL_PRNG_SAVE: { - sqlite3PrngSaveState(); - break; - } - - /* - ** Restore the state of the PRNG to the last state saved using - ** PRNG_SAVE. If PRNG_SAVE has never before been called, then - ** this verb acts like PRNG_RESET. - */ - case SQLITE_TESTCTRL_PRNG_RESTORE: { - sqlite3PrngRestoreState(); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db); - ** - ** Control the seed for the pseudo-random number generator (PRNG) that - ** is built into SQLite. Cases: - ** - ** x!=0 && db!=0 Seed the PRNG to the current value of the - ** schema cookie in the main database for db, or - ** x if the schema cookie is zero. This case - ** is convenient to use with database fuzzers - ** as it allows the fuzzer some control over the - ** the PRNG seed. - ** - ** x!=0 && db==0 Seed the PRNG to the value of x. - ** - ** x==0 && db==0 Revert to default behavior of using the - ** xRandomness method on the primary VFS. - ** - ** This test-control also resets the PRNG so that the new seed will - ** be used for the next call to sqlite3_randomness(). - */ -#ifndef SQLITE_OMIT_WSD - case SQLITE_TESTCTRL_PRNG_SEED: { - int x = va_arg(ap, int); - int y; - sqlite3 *db = va_arg(ap, sqlite3*); - assert( db==0 || db->aDb[0].pSchema!=0 ); - if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; } - sqlite3Config.iPrngSeed = x; - sqlite3_randomness(0,0); - break; - } -#endif - - /* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b); - ** - ** If b is true, then activate the SQLITE_FkNoAction setting. If b is - ** false then clear that setting. If the SQLITE_FkNoAction setting is - ** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if - ** they were NO ACTION, regardless of how they are defined. - ** - ** NB: One must usually run "PRAGMA writable_schema=RESET" after - ** using this test-control, before it will take full effect. failing - ** to reset the schema can result in some unexpected behavior. - */ - case SQLITE_TESTCTRL_FK_NO_ACTION: { - sqlite3 *db = va_arg(ap, sqlite3*); - int b = va_arg(ap, int); - if( b ){ - db->flags |= SQLITE_FkNoAction; - }else{ - db->flags &= ~SQLITE_FkNoAction; - } - break; - } - - /* - ** sqlite3_test_control(BITVEC_TEST, size, program) - ** - ** Run a test against a Bitvec object of size. The program argument - ** is an array of integers that defines the test. Return -1 on a - ** memory allocation error, 0 on success, or non-zero for an error. - ** See the sqlite3BitvecBuiltinTest() for additional information. - */ - case SQLITE_TESTCTRL_BITVEC_TEST: { - int sz = va_arg(ap, int); - int *aProg = va_arg(ap, int*); - rc = sqlite3BitvecBuiltinTest(sz, aProg); - break; - } - - /* - ** sqlite3_test_control(FAULT_INSTALL, xCallback) - ** - ** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called, - ** if xCallback is not NULL. - ** - ** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0) - ** is called immediately after installing the new callback and the return - ** value from sqlite3FaultSim(0) becomes the return from - ** sqlite3_test_control(). - */ - case SQLITE_TESTCTRL_FAULT_INSTALL: { - /* 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. - ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int)); - */ - typedef int(*sqlite3FaultFuncType)(int); - sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType); - rc = sqlite3FaultSim(0); - break; - } - - /* - ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) - ** - ** Register hooks to call to indicate which malloc() failures - ** are benign. - */ - case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: { - typedef void (*void_function)(void); - void_function xBenignBegin; - void_function xBenignEnd; - xBenignBegin = va_arg(ap, void_function); - xBenignEnd = va_arg(ap, void_function); - sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd); - break; - } - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X) - ** - ** Set the PENDING byte to the value in the argument, if X>0. - ** Make no changes if X==0. Return the value of the pending byte - ** as it existing before this routine was called. - ** - ** IMPORTANT: Changing the PENDING byte from 0x40000000 results in - ** an incompatible database file format. Changing the PENDING byte - ** while any database connection is open results in undefined and - ** deleterious behavior. - */ - case SQLITE_TESTCTRL_PENDING_BYTE: { - rc = PENDING_BYTE; -#ifndef SQLITE_OMIT_WSD - { - unsigned int newVal = va_arg(ap, unsigned int); - if( newVal ) sqlite3PendingByte = newVal; - } -#endif - break; - } - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X) - ** - ** This action provides a run-time test to see whether or not - ** assert() was enabled at compile-time. If X is true and assert() - ** is enabled, then the return value is true. If X is true and - ** assert() is disabled, then the return value is zero. If X is - ** false and assert() is enabled, then the assertion fires and the - ** process aborts. If X is false and assert() is disabled, then the - ** return value is zero. - */ - case SQLITE_TESTCTRL_ASSERT: { - 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 ){ - sqlite3ShowExpr(0); - sqlite3ShowExprList(0); - sqlite3ShowIdList(0); - sqlite3ShowSrcList(0); - sqlite3ShowWith(0); - sqlite3ShowUpsert(0); -#ifndef SQLITE_OMIT_TRIGGER - sqlite3ShowTriggerStep(0); - sqlite3ShowTriggerStepList(0); - sqlite3ShowTrigger(0); - sqlite3ShowTriggerList(0); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC - sqlite3ShowWindow(0); - sqlite3ShowWinFunc(0); -#endif - sqlite3ShowSelect(0); - } -#endif - break; - } - - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X) - ** - ** This action provides a run-time test to see how the ALWAYS and - ** NEVER macros were defined at compile-time. - ** - ** The return value is ALWAYS(X) if X is true, or 0 if X is false. - ** - ** The recommended test is X==2. If the return value is 2, that means - ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the - ** default setting. If the return value is 1, then ALWAYS() is either - ** hard-coded to true or else it asserts if its argument is false. - ** The first behavior (hard-coded to true) is the case if - ** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second - ** behavior (assert if the argument to ALWAYS() is false) is the case if - ** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled. - ** - ** The run-time test procedure might look something like this: - ** - ** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){ - ** // ALWAYS() and NEVER() are no-op pass-through macros - ** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){ - ** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false. - ** }else{ - ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0. - ** } - */ - case SQLITE_TESTCTRL_ALWAYS: { - int x = va_arg(ap,int); - rc = x ? ALWAYS(x) : 0; - break; - } - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER); - ** - ** The integer returned reveals the byte-order of the computer on which - ** SQLite is running: - ** - ** 1 big-endian, determined at run-time - ** 10 little-endian, determined at run-time - ** 432101 big-endian, determined at compile-time - ** 123410 little-endian, determined at compile-time - */ - case SQLITE_TESTCTRL_BYTEORDER: { - rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N) - ** - ** Enable or disable various optimizations for testing purposes. The - ** argument N is a bitmask of optimizations to be disabled. For normal - ** operation N should be 0. The idea is that a test program (like the - ** SQL Logic Test or SLT test module) can run the same SQL multiple times - ** with various optimizations disabled to verify that the same answer - ** is obtained in every case. - */ - case SQLITE_TESTCTRL_OPTIMIZATIONS: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->dbOptFlags = va_arg(ap, u32); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, sqlite3 *db, int *N) - ** - ** Write the current optimization settings into *N. A zero bit means that - ** the optimization is on, and a 1 bit means that the optimization is off. - */ - case SQLITE_TESTCTRL_GETOPT: { - sqlite3 *db = va_arg(ap, sqlite3*); - int *pN = va_arg(ap, int*); - *pN = db->dbOptFlags; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt); - ** - ** 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: { - sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); - if( sqlite3GlobalConfig.bLocaltimeFault==2 ){ - typedef int(*sqlite3LocaltimeType)(const void*,void*); - sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType); - }else{ - sqlite3GlobalConfig.xAltLocaltime = 0; - } - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*); - ** - ** Toggle the ability to use internal functions on or off for - ** the database connection given in the argument. - */ - case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->mDbFlags ^= DBFLAG_InternalFunc; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); - ** - ** Set or clear a flag that indicates that the database file is always well- - ** formed and never corrupt. This flag is clear by default, indicating that - ** database files might have arbitrary corruption. Setting the flag during - ** testing causes certain assert() statements in the code to be activated - ** that demonstrate invariants on well-formed database files. - */ - case SQLITE_TESTCTRL_NEVER_CORRUPT: { - sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int); - ** - ** Set or clear a flag that causes SQLite to verify that type, name, - ** and tbl_name fields of the sqlite_schema table. This is normally - ** on, but it is sometimes useful to turn it off for testing. - ** - ** 2020-07-22: Disabling EXTRA_SCHEMA_CHECKS also disables the - ** verification of rootpage numbers when parsing the schema. This - ** is useful to make it easier to reach strange internal error states - ** during testing. The EXTRA_SCHEMA_CHECKS setting is always enabled - ** in production. - */ - case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: { - sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int); - break; - } - - /* Set the threshold at which OP_Once counters reset back to zero. - ** By default this is 0x7ffffffe (over 2 billion), but that value is - ** too big to test in a reasonable amount of time, so this control is - ** provided to set a small and easily reachable reset value. - */ - case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: { - sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); - ** - ** Set the VDBE coverage callback function to xCallback with context - ** pointer ptr. - */ - case SQLITE_TESTCTRL_VDBE_COVERAGE: { -#ifdef SQLITE_VDBE_COVERAGE - typedef void (*branch_callback)(void*,unsigned int, - unsigned char,unsigned char); - sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); - sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); -#endif - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, nMax); */ - case SQLITE_TESTCTRL_SORTER_MMAP: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->nMaxSorterMmap = va_arg(ap, int); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT); - ** - ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if - ** not. - */ - case SQLITE_TESTCTRL_ISINIT: { - if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); - ** - ** This test control is used to create imposter tables. "db" is a pointer - ** to the database connection. dbName is the database name (ex: "main" or - ** "temp") which will receive the imposter. "onOff" turns imposter mode on - ** or off. "tnum" is the root page of the b-tree to which the imposter - ** table should connect. - ** - ** Enable imposter mode only when the schema has already been parsed. Then - ** run a single CREATE TABLE statement to construct the imposter table in - ** the parsed schema. Then turn imposter mode back off again. - ** - ** If onOff==0 and tnum>0 then reset the schema for all databases, causing - ** the schema to be reparsed the next time it is needed. This has the - ** effect of erasing all imposter tables. - */ - case SQLITE_TESTCTRL_IMPOSTER: { - sqlite3 *db = va_arg(ap, sqlite3*); - int iDb; - sqlite3_mutex_enter(db->mutex); - iDb = 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 ){ - sqlite3ResetAllSchemasOfConnection(db); - } - } - sqlite3_mutex_leave(db->mutex); - break; - } - -#if defined(YYCOVERAGE) - /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out) - ** - ** This test control (only available when SQLite is compiled with - ** -DYYCOVERAGE) writes a report onto "out" that shows all - ** state/lookahead combinations in the parser state machine - ** which are never exercised. If any state is missed, make the - ** return code SQLITE_ERROR. - */ - case SQLITE_TESTCTRL_PARSER_COVERAGE: { - FILE *out = va_arg(ap, FILE*); - if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR; - break; - } -#endif /* defined(YYCOVERAGE) */ - - /* sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, sqlite3_context*); - ** - ** This test-control causes the most recent sqlite3_result_int64() value - ** to be interpreted as a MEM_IntReal instead of as an MEM_Int. Normally, - ** MEM_IntReal values only arise during an INSERT operation of integer - ** values into a REAL column, so they can be challenging to test. This - ** test-control enables us to write an intreal() SQL function that can - ** inject an intreal() value at arbitrary places in an SQL statement, - ** for testing purposes. - */ - case SQLITE_TESTCTRL_RESULT_INTREAL: { - sqlite3_context *pCtx = va_arg(ap, sqlite3_context*); - sqlite3ResultIntReal(pCtx); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT, - ** sqlite3 *db, // Database connection - ** u64 *pnSeek // Write seek count here - ** ); - ** - ** This test-control queries the seek-counter on the "main" database - ** file. The seek-counter is written into *pnSeek and is then reset. - ** The seek-count is only available if compiled with SQLITE_DEBUG. - */ - case SQLITE_TESTCTRL_SEEK_COUNT: { - sqlite3 *db = va_arg(ap, sqlite3*); - u64 *pn = va_arg(ap, sqlite3_uint64*); - *pn = sqlite3BtreeSeekCount(db->aDb->pBt); - (void)db; /* Silence harmless unused variable warning */ - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr) - ** - ** "ptr" is a pointer to a u32. - ** - ** op==0 Store the current sqlite3TreeTrace in *ptr - ** op==1 Set sqlite3TreeTrace to the value *ptr - ** op==2 Store the current sqlite3WhereTrace in *ptr - ** op==3 Set 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 = sqlite3TreeTrace; break; - case 1: sqlite3TreeTrace = *ptr; break; - case 2: *ptr = sqlite3WhereTrace; break; - case 3: sqlite3WhereTrace = *ptr; break; - } - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST, - ** double fIn, // Input value - ** int *pLogEst, // sqlite3LogEstFromDouble(fIn) - ** u64 *pInt, // sqlite3LogEstToInt(*pLogEst) - ** int *pLogEst2 // sqlite3LogEst(*pInt) - ** ); - ** - ** Test access for the LogEst conversion routines. - */ - case SQLITE_TESTCTRL_LOGEST: { - double rIn = va_arg(ap, double); - LogEst rLogEst = sqlite3LogEstFromDouble(rIn); - int *pI1 = va_arg(ap,int*); - u64 *pU64 = va_arg(ap,u64*); - int *pI2 = va_arg(ap,int*); - *pI1 = rLogEst; - *pU64 = sqlite3LogEstToInt(rLogEst); - *pI2 = sqlite3LogEst(*pU64); - break; - } - -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) - /* 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 - - /* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff); - ** - ** Activate or deactivate validation of JSONB that is generated from - ** text. Off by default, as the validation is slow. Validation is - ** only available if compiled using SQLITE_DEBUG. - ** - ** If onOff is initially 1, then turn it on. If onOff is initially - ** off, turn it off. If onOff is initially -1, then change onOff - ** to be the current setting. - */ - case SQLITE_TESTCTRL_JSON_SELFCHECK: { -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) - int *pOnOff = va_arg(ap, int*); - if( *pOnOff<0 ){ - *pOnOff = sqlite3Config.bJsonSelfcheck; - }else{ - sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff); - } -#endif - break; - } - } - va_end(ap); -#endif /* SQLITE_UNTESTABLE */ - return rc; -} - -/* -** The Pager stores the Database filename, Journal filename, and WAL filename -** consecutively in memory, in that order. The database filename is prefixed -** by four zero bytes. Locate the start of the database filename by searching -** backwards for the first byte following four consecutive zero bytes. -** -** This only works if the filename passed in was obtained from the Pager. -*/ -static const char *databaseName(const char *zName){ - while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ - zName--; - } - return zName; -} - -/* -** Append text z[] to the end of p[]. Return a pointer to the first -** character after then zero terminator on the new text in p[]. -*/ -static char *appendText(char *p, const char *z){ - size_t n = strlen(z); - memcpy(p, z, n+1); - return p+n+1; -} - -/* -** Allocate memory to hold names for a database, journal file, WAL file, -** and query parameters. The pointer returned is valid for use by -** sqlite3_filename_database() and sqlite3_uri_parameter() and related -** functions. -** -** Memory layout must be compatible with that generated by the pager -** and expected by sqlite3_uri_parameter() and databaseName(). -*/ -SQLITE_API const char *sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam -){ - sqlite3_int64 nByte; - int i; - char *pResult, *p; - nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10; - for(i=0; i0 ){ - zFilename += sqlite3Strlen30(zFilename) + 1; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return zFilename[0] ? zFilename : 0; -} - -/* -** Return a boolean value for a query parameter. -*/ -SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ - const char *z = sqlite3_uri_parameter(zFilename, zParam); - bDflt = bDflt!=0; - return z ? sqlite3GetBoolean(z, bDflt) : bDflt; -} - -/* -** Return a 64-bit integer value for a query parameter. -*/ -SQLITE_API sqlite3_int64 sqlite3_uri_int64( - const char *zFilename, /* Filename as passed to xOpen */ - const char *zParam, /* URI parameter sought */ - sqlite3_int64 bDflt /* return if parameter is missing */ -){ - const char *z = sqlite3_uri_parameter(zFilename, zParam); - sqlite3_int64 v; - if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ - bDflt = v; - } - return bDflt; -} - -/* -** Translate a filename that was handed to a VFS routine into the corresponding -** database, journal, or WAL file. -** -** It is an error to pass this routine a filename string that was not -** passed into the VFS from the SQLite core. Doing so is similar to -** passing free() a pointer that was not obtained from malloc() - it is -** an error that we cannot easily detect but that will likely cause memory -** corruption. -*/ -SQLITE_API const char *sqlite3_filename_database(const char *zFilename){ - if( zFilename==0 ) return 0; - return databaseName(zFilename); -} -SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){ - if( zFilename==0 ) return 0; - zFilename = databaseName(zFilename); - zFilename += sqlite3Strlen30(zFilename) + 1; - while( ALWAYS(zFilename) && zFilename[0] ){ - zFilename += sqlite3Strlen30(zFilename) + 1; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return zFilename + 1; -} -SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){ -#ifdef SQLITE_OMIT_WAL - return 0; -#else - zFilename = sqlite3_filename_journal(zFilename); - if( zFilename ) zFilename += sqlite3Strlen30(zFilename) + 1; - return zFilename; -#endif -} - -/* -** Return the Btree pointer identified by zDbName. Return NULL if not found. -*/ -SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ - int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; - return iDb<0 ? 0 : db->aDb[iDb].pBt; -} - -/* -** Return the name of the N-th database schema. Return NULL if N is out -** of range. -*/ -SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !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. -*/ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ - Btree *pBt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - pBt = sqlite3DbNameToBtree(db, zDbName); - return pBt ? sqlite3BtreeGetFilename(pBt) : 0; -} - -/* -** Return 1 if database is read-only or 0 if read/write. Return -1 if -** no such database exists. -*/ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ - Btree *pBt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif - pBt = sqlite3DbNameToBtree(db, zDbName); - return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; -} - -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** Obtain a snapshot handle for the snapshot of database zDb currently -** being read by handle db. -*/ -SQLITE_API int sqlite3_snapshot_get( - sqlite3 *db, - const char *zDb, - sqlite3_snapshot **ppSnapshot -){ - int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - - if( db->autoCommit==0 ){ - int iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){ - Pager *pPager = sqlite3BtreePager(pBt); - i64 dummy = 0; - sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy); - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); - } - } - } - } - - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Open a read-transaction on the snapshot identified by pSnapshot. -*/ -SQLITE_API int sqlite3_snapshot_open( - sqlite3 *db, - const char *zDb, - sqlite3_snapshot *pSnapshot -){ - int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( db->autoCommit==0 ){ - int iDb; - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){ - Pager *pPager = sqlite3BtreePager(pBt); - int bUnlock = 0; - if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){ - if( db->nVdbeActive==0 ){ - rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot); - if( rc==SQLITE_OK ){ - bUnlock = 1; - rc = sqlite3BtreeCommit(pBt); - } - } - }else{ - rc = SQLITE_OK; - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); - } - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0); - } - if( bUnlock ){ - sqlite3PagerSnapshotUnlock(pPager); - } - } - } - } - - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Recover as many snapshots as possible from the wal file associated with -** schema zDb of database db. -*/ -SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ - int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL - int iDb; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - - sqlite3_mutex_enter(db->mutex); - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); - sqlite3BtreeCommit(pBt); - } - } - } - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Free a snapshot handle obtained from sqlite3_snapshot_get(). -*/ -SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ - sqlite3_free(pSnapshot); -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -/* -** Given the name of a compile-time option, return true if that option -** was used and false if not. -** -** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix -** is not required for a match. -*/ -SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ - int i, n; - int nOpt; - const char **azCompileOpt; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zOptName==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - - azCompileOpt = sqlite3CompileOptions(&nOpt); - - if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; - n = sqlite3Strlen30(zOptName); - - /* Since nOpt is normally in single digits, a linear search is - ** adequate. No need for a binary search. */ - for(i=0; i=0 && NpNextBlocked){ - int seen = 0; - sqlite3 *p2; - - /* Verify property (1) */ - assert( p->pUnlockConnection || p->pBlockingConnection ); - - /* Verify property (2) */ - for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){ - if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1; - assert( p2->xUnlockNotify==p->xUnlockNotify || !seen ); - assert( db==0 || p->pUnlockConnection!=db ); - assert( db==0 || p->pBlockingConnection!=db ); - } - } -} -#else -# define checkListProperties(x) -#endif - -/* -** Remove connection db from the blocked connections list. If connection -** db is not currently a part of the list, this function is a no-op. -*/ -static void removeFromBlockedList(sqlite3 *db){ - sqlite3 **pp; - assertMutexHeld(); - for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){ - if( *pp==db ){ - *pp = (*pp)->pNextBlocked; - break; - } - } -} - -/* -** Add connection db to the blocked connections list. It is assumed -** that it is not already a part of the list. -*/ -static void addToBlockedList(sqlite3 *db){ - sqlite3 **pp; - assertMutexHeld(); - for( - pp=&sqlite3BlockedList; - *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify; - pp=&(*pp)->pNextBlocked - ); - db->pNextBlocked = *pp; - *pp = db; -} - -/* -** Obtain the STATIC_MAIN mutex. -*/ -static void enterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); - checkListProperties(0); -} - -/* -** Release the STATIC_MAIN mutex. -*/ -static void leaveMutex(void){ - assertMutexHeld(); - checkListProperties(0); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); -} - -/* -** Register an unlock-notify callback. -** -** This is called after connection "db" has attempted some operation -** but has received an SQLITE_LOCKED error because another connection -** (call it pOther) in the same process was busy using the same shared -** cache. pOther is found by looking at db->pBlockingConnection. -** -** If there is no blocking connection, the callback is invoked immediately, -** before this routine returns. -** -** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate -** a deadlock. -** -** Otherwise, make arrangements to invoke xNotify when pOther drops -** its locks. -** -** Each call to this routine overrides any prior callbacks registered -** on the same "db". If xNotify==0 then any prior callbacks are immediately -** cancelled. -*/ -SQLITE_API int sqlite3_unlock_notify( - sqlite3 *db, - void (*xNotify)(void **, int), - void *pArg -){ - int rc = SQLITE_OK; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - enterMutex(); - - if( xNotify==0 ){ - removeFromBlockedList(db); - db->pBlockingConnection = 0; - db->pUnlockConnection = 0; - db->xUnlockNotify = 0; - db->pUnlockArg = 0; - }else if( 0==db->pBlockingConnection ){ - /* The blocking transaction has been concluded. Or there never was a - ** blocking transaction. In either case, invoke the notify callback - ** immediately. - */ - xNotify(&pArg, 1); - }else{ - sqlite3 *p; - - for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){} - if( p ){ - rc = SQLITE_LOCKED; /* Deadlock detected. */ - }else{ - db->pUnlockConnection = db->pBlockingConnection; - db->xUnlockNotify = xNotify; - db->pUnlockArg = pArg; - removeFromBlockedList(db); - addToBlockedList(db); - } - } - - leaveMutex(); - assert( !db->mallocFailed ); - sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0)); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** This function is called while stepping or preparing a statement -** associated with connection db. The operation will return SQLITE_LOCKED -** to the user because it requires a lock that will not be available -** until connection pBlocker concludes its current transaction. -*/ -SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){ - enterMutex(); - if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){ - addToBlockedList(db); - } - db->pBlockingConnection = pBlocker; - leaveMutex(); -} - -/* -** This function is called when -** the transaction opened by database db has just finished. Locks held -** by database connection db have been released. -** -** This function loops through each entry in the blocked connections -** list and does the following: -** -** 1) If the sqlite3.pBlockingConnection member of a list entry is -** set to db, then set pBlockingConnection=0. -** -** 2) If the sqlite3.pUnlockConnection member of a list entry is -** set to db, then invoke the configured unlock-notify callback and -** set pUnlockConnection=0. -** -** 3) If the two steps above mean that pBlockingConnection==0 and -** pUnlockConnection==0, remove the entry from the blocked connections -** list. -*/ -SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){ - void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */ - int nArg = 0; /* Number of entries in aArg[] */ - sqlite3 **pp; /* Iterator variable */ - void **aArg; /* Arguments to the unlock callback */ - void **aDyn = 0; /* Dynamically allocated space for aArg[] */ - void *aStatic[16]; /* Starter space for aArg[]. No malloc required */ - - aArg = aStatic; - enterMutex(); /* Enter STATIC_MAIN mutex */ - - /* This loop runs once for each entry in the blocked-connections list. */ - for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){ - sqlite3 *p = *pp; - - /* Step 1. */ - if( p->pBlockingConnection==db ){ - p->pBlockingConnection = 0; - } - - /* Step 2. */ - if( p->pUnlockConnection==db ){ - assert( p->xUnlockNotify ); - if( p->xUnlockNotify!=xUnlockNotify && nArg!=0 ){ - xUnlockNotify(aArg, nArg); - nArg = 0; - } - - sqlite3BeginBenignMalloc(); - assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) ); - assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn ); - if( (!aDyn && nArg==(int)ArraySize(aStatic)) - || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*))) - ){ - /* The aArg[] array needs to grow. */ - void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2); - if( pNew ){ - memcpy(pNew, aArg, nArg*sizeof(void *)); - sqlite3_free(aDyn); - aDyn = aArg = pNew; - }else{ - /* This occurs when the array of context pointers that need to - ** be passed to the unlock-notify callback is larger than the - ** aStatic[] array allocated on the stack and the attempt to - ** allocate a larger array from the heap has failed. - ** - ** This is a difficult situation to handle. Returning an error - ** code to the caller is insufficient, as even if an error code - ** is returned the transaction on connection db will still be - ** closed and the unlock-notify callbacks on blocked connections - ** will go unissued. This might cause the application to wait - ** indefinitely for an unlock-notify callback that will never - ** arrive. - ** - ** Instead, invoke the unlock-notify callback with the context - ** array already accumulated. We can then clear the array and - ** begin accumulating any further context pointers without - ** requiring any dynamic allocation. This is sub-optimal because - ** it means that instead of one callback with a large array of - ** context pointers the application will receive two or more - ** callbacks with smaller arrays of context pointers, which will - ** reduce the applications ability to prioritize multiple - ** connections. But it is the best that can be done under the - ** circumstances. - */ - xUnlockNotify(aArg, nArg); - nArg = 0; - } - } - sqlite3EndBenignMalloc(); - - aArg[nArg++] = p->pUnlockArg; - xUnlockNotify = p->xUnlockNotify; - p->pUnlockConnection = 0; - p->xUnlockNotify = 0; - p->pUnlockArg = 0; - } - - /* Step 3. */ - if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){ - /* Remove connection p from the blocked connections list. */ - *pp = p->pNextBlocked; - p->pNextBlocked = 0; - }else{ - pp = &p->pNextBlocked; - } - } - - if( nArg!=0 ){ - xUnlockNotify(aArg, nArg); - } - sqlite3_free(aDyn); - leaveMutex(); /* Leave STATIC_MAIN mutex */ -} - -/* -** This is called when the database connection passed as an argument is -** being closed. The connection is removed from the blocked list. -*/ -SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ - sqlite3ConnectionUnlocked(db); - enterMutex(); - removeFromBlockedList(db); - checkListProperties(db); - leaveMutex(); -} -#endif - -/************** End of notify.c **********************************************/ -/************** Begin file fts3.c ********************************************/ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is an SQLite module implementing full-text search. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ - -/* The full-text index is stored in a series of b+tree (-like) -** structures called segments which map terms to doclists. The -** structures are like b+trees in layout, but are constructed from the -** bottom up in optimal fashion and are not updatable. Since trees -** are built from the bottom up, things will be described from the -** bottom up. -** -** -**** Varints **** -** The basic unit of encoding is a variable-length integer called a -** varint. We encode variable-length integers in little-endian order -** using seven bits * per byte as follows: -** -** KEY: -** A = 0xxxxxxx 7 bits of data and one flag bit -** B = 1xxxxxxx 7 bits of data and one flag bit -** -** 7 bits - A -** 14 bits - BA -** 21 bits - BBA -** and so on. -** -** This is similar in concept to how sqlite encodes "varints" but -** the encoding is not the same. SQLite varints are big-endian -** are are limited to 9 bytes in length whereas FTS3 varints are -** little-endian and can be up to 10 bytes in length (in theory). -** -** Example encodings: -** -** 1: 0x01 -** 127: 0x7f -** 128: 0x81 0x00 -** -** -**** Document lists **** -** A doclist (document list) holds a docid-sorted list of hits for a -** given term. Doclists hold docids and associated token positions. -** A docid is the unique integer identifier for a single document. -** A position is the index of a word within the document. The first -** word of the document has a position of 0. -** -** FTS3 used to optionally store character offsets using a compile-time -** option. But that functionality is no longer supported. -** -** A doclist is stored like this: -** -** array { -** varint docid; (delta from previous doclist) -** array { (position list for column 0) -** varint position; (2 more than the delta from previous position) -** } -** array { -** varint POS_COLUMN; (marks start of position list for new column) -** varint column; (index of new column) -** array { -** varint position; (2 more than the delta from previous position) -** } -** } -** varint POS_END; (marks end of positions for this document. -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. A "position" is an index of a token in the token stream -** generated by the tokenizer. Note that POS_END and POS_COLUMN occur -** in the same logical place as the position element, and act as sentinels -** ending a position list array. POS_END is 0. POS_COLUMN is 1. -** The positions numbers are not stored literally but rather as two more -** than the difference from the prior position, or the just the position plus -** 2 for the first position. Example: -** -** label: A B C D E F G H I J K -** value: 123 5 9 1 1 14 35 0 234 72 0 -** -** The 123 value is the first docid. For column zero in this document -** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 -** at D signals the start of a new column; the 1 at E indicates that the -** new column is column number 1. There are two positions at 12 and 45 -** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The -** 234 at I is the delta to next docid (357). It has one position 70 -** (72-2) and then terminates with the 0 at K. -** -** A "position-list" is the list of positions for multiple columns for -** a single docid. A "column-list" is the set of positions for a single -** column. Hence, a position-list consists of one or more column-lists, -** a document record consists of a docid followed by a position-list and -** a doclist consists of one or more document records. -** -** A bare doclist omits the position information, becoming an -** array of varint-encoded docids. -** -**** Segment leaf nodes **** -** Segment leaf nodes store terms and doclists, ordered by term. Leaf -** nodes are written using LeafWriter, and read using LeafReader (to -** iterate through a single leaf node's data) and LeavesReader (to -** iterate through a segment's entire leaf layer). Leaf nodes have -** the format: -** -** varint iHeight; (height from leaf level, always 0) -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of prefix shared with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix];(unshared suffix of next term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. -** -** Leaf nodes are broken into blocks which are stored contiguously in -** the %_segments table in sorted order. This means that when the end -** of a node is reached, the next term is in the node with the next -** greater node id. -** -** New data is spilled to a new leaf node when the current node -** exceeds LEAF_MAX bytes (default 2048). New data which itself is -** larger than STANDALONE_MIN (default 1024) is placed in a standalone -** node (a leaf node with a single term and doclist). The goal of -** these settings is to pack together groups of small doclists while -** making it efficient to directly access large doclists. The -** assumption is that large doclists represent terms which are more -** likely to be query targets. -** -** TODO(shess) It may be useful for blocking decisions to be more -** dynamic. For instance, it may make more sense to have a 2.5k leaf -** node rather than splitting into 2k and .5k nodes. My intuition is -** that this might extend through 2x or 4x the pagesize. -** -** -**** Segment interior nodes **** -** Segment interior nodes store blockids for subtree nodes and terms -** to describe what data is stored by the each subtree. Interior -** nodes are written using InteriorWriter, and read using -** InteriorReader. InteriorWriters are created as needed when -** SegmentWriter creates new leaf nodes, or when an interior node -** itself grows too big and must be split. The format of interior -** nodes: -** -** varint iHeight; (height from leaf level, always >0) -** varint iBlockid; (block id of node's leftmost subtree) -** optional { -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of shared prefix with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix]; (unshared suffix of next term) -** } -** } -** -** Here, optional { X } means an optional element, while array { X } -** means zero or more occurrences of X, adjacent in memory. -** -** An interior node encodes n terms separating n+1 subtrees. The -** subtree blocks are contiguous, so only the first subtree's blockid -** is encoded. The subtree at iBlockid will contain all terms less -** than the first term encoded (or all terms if no term is encoded). -** Otherwise, for terms greater than or equal to pTerm[i] but less -** than pTerm[i+1], the subtree for that term will be rooted at -** iBlockid+i. Interior nodes only store enough term data to -** distinguish adjacent children (if the rightmost term of the left -** child is "something", and the leftmost term of the right child is -** "wicked", only "w" is stored). -** -** New data is spilled to a new interior node at the same height when -** the current node exceeds INTERIOR_MAX bytes (default 2048). -** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing -** interior nodes and making the tree too skinny. The interior nodes -** at a given height are naturally tracked by interior nodes at -** height+1, and so on. -** -** -**** Segment directory **** -** The segment directory in table %_segdir stores meta-information for -** merging and deleting segments, and also the root node of the -** segment's tree. -** -** The root node is the top node of the segment's tree after encoding -** the entire segment, restricted to ROOT_MAX bytes (default 1024). -** This could be either a leaf node or an interior node. If the top -** node requires more than ROOT_MAX bytes, it is flushed to %_segments -** and a new root interior node is generated (which should always fit -** within ROOT_MAX because it only needs space for 2 varints, the -** height and the blockid of the previous root). -** -** The meta-information in the segment directory is: -** level - segment level (see below) -** idx - index within level -** - (level,idx uniquely identify a segment) -** start_block - first leaf node -** leaves_end_block - last leaf node -** end_block - last block (including interior nodes) -** root - contents of root node -** -** If the root node is a leaf node, then start_block, -** leaves_end_block, and end_block are all 0. -** -** -**** Segment merging **** -** To amortize update costs, segments are grouped into levels and -** merged in batches. Each increase in level represents exponentially -** more documents. -** -** New documents (actually, document updates) are tokenized and -** written individually (using LeafWriter) to a level 0 segment, with -** incrementing idx. When idx reaches MERGE_COUNT (default 16), all -** level 0 segments are merged into a single level 1 segment. Level 1 -** is populated like level 0, and eventually MERGE_COUNT level 1 -** segments are merged to a single level 2 segment (representing -** MERGE_COUNT^2 updates), and so on. -** -** A segment merge traverses all segments at a given level in -** parallel, performing a straightforward sorted merge. Since segment -** leaf nodes are written in to the %_segments table in order, this -** merge traverses the underlying sqlite disk structures efficiently. -** After the merge, all segment blocks from the merged level are -** deleted. -** -** MERGE_COUNT controls how often we merge segments. 16 seems to be -** somewhat of a sweet spot for insertion performance. 32 and 64 show -** very similar performance numbers to 16 on insertion, though they're -** a tiny bit slower (perhaps due to more overhead in merge-time -** sorting). 8 is about 20% slower than 16, 4 about 50% slower than -** 16, 2 about 66% slower than 16. -** -** At query time, high MERGE_COUNT increases the number of segments -** which need to be scanned and merged. For instance, with 100k docs -** inserted: -** -** MERGE_COUNT segments -** 16 25 -** 8 12 -** 4 10 -** 2 6 -** -** This appears to have only a moderate impact on queries for very -** frequent terms (which are somewhat dominated by segment merge -** costs), and infrequent and non-existent terms still seem to be fast -** even with many segments. -** -** TODO(shess) That said, it would be nice to have a better query-side -** argument for MERGE_COUNT of 16. Also, it is possible/likely that -** optimizations to things like doclist merging will swing the sweet -** spot around. -** -** -** -**** Handling of deletions and updates **** -** Since we're using a segmented structure, with no docid-oriented -** index into the term index, we clearly cannot simply update the term -** index when a document is deleted or updated. For deletions, we -** write an empty doclist (varint(docid) varint(POS_END)), for updates -** we simply write the new doclist. Segment merges overwrite older -** data for a particular docid with newer data, so deletes or updates -** will eventually overtake the earlier data and knock it out. The -** query logic likewise merges doclists so that newer data knocks out -** older data. -*/ - -/************** Include fts3Int.h in the middle of fts3.c ********************/ -/************** Begin file fts3Int.h *****************************************/ -/* -** 2009 Nov 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -*/ -#ifndef _FTSINT_H -#define _FTSINT_H - -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* FTS3/FTS4 require virtual tables */ -#ifdef SQLITE_OMIT_VIRTUALTABLE -# undef SQLITE_ENABLE_FTS3 -# undef SQLITE_ENABLE_FTS4 -#endif - -/* -** FTS4 is really an extension for FTS3. It is enabled using the -** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all -** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. -*/ -#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) -# define SQLITE_ENABLE_FTS3 -#endif - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* If not building as part of the core, include sqlite3ext.h. */ -#ifndef SQLITE_CORE -/* # include "sqlite3ext.h" */ -SQLITE_EXTENSION_INIT3 -#endif - -/* #include "sqlite3.h" */ -/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/* #include "sqlite3.h" */ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0 or 1. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialized by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. *piStartOffset should be set to the index of the first - ** byte of the token in the input buffer. *piEndOffset should be set - ** to the index of the first byte just past the end of the token in - ** the input buffer. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); - - /*********************************************************************** - ** Methods below this point are only available if iVersion>=1. - */ - - /* - ** Configure the language id of a tokenizer cursor. - */ - int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -int fts3_global_term_cnt(int iTerm, int iCol); -int fts3_term_cnt(int iTerm, int iCol); - - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3Int.h ********************/ -/************** Include fts3_hash.h in the middle of fts3Int.h ***************/ -/************** Begin file fts3_hash.h ***************************************/ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the header file for the generic hash-table implementation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct Fts3Hash Fts3Hash; -typedef struct Fts3HashElem Fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct Fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - Fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - Fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct Fts3HashElem { - Fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey); -SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); -SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); -SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); -SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear -#define fts3HashFindElem sqlite3Fts3HashFindElem - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** Fts3Hash h; -** Fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ - -/************** End of fts3_hash.h *******************************************/ -/************** Continuing where we left off in fts3Int.h ********************/ - -/* -** This constant determines the maximum depth of an FTS expression tree -** that the library will create and use. FTS uses recursion to perform -** various operations on the query tree, so the disadvantage of a large -** limit is that it may allow very large queries to use large amounts -** of stack space (perhaps causing a stack overflow). -*/ -#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH -# define SQLITE_FTS3_MAX_EXPR_DEPTH 12 -#endif - - -/* -** This constant controls how often segments are merged. Once there are -** FTS3_MERGE_COUNT segments of level N, they are merged into a single -** segment of level N+1. -*/ -#define FTS3_MERGE_COUNT 16 - -/* -** This is the maximum amount of data (in bytes) to store in the -** Fts3Table.pendingTerms hash table. Normally, the hash table is -** populated as documents are inserted/updated/deleted in a transaction -** and used to create a new segment when the transaction is committed. -** However if this limit is reached midway through a transaction, a new -** segment is created and the hash table cleared immediately. -*/ -#define FTS3_MAX_PENDING_DATA (1*1024*1024) - -/* -** Macro to return the number of elements in an array. SQLite has a -** similar macro called ArraySize(). Use a different name to avoid -** a collision when building an amalgamation with built-in FTS3. -*/ -#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0]))) - - -#ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif -#ifndef MAX -# define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -/* -** Maximum length of a varint encoded integer. The varint format is different -** from that used by SQLite, so the maximum length is 10, not 9. -*/ -#define FTS3_VARINT_MAX 10 - -#define FTS3_BUFFER_PADDING 8 - -/* -** FTS4 virtual tables may maintain multiple indexes - one index of all terms -** in the document set and zero or more prefix indexes. All indexes are stored -** as one or more b+-trees in the %_segments and %_segdir tables. -** -** It is possible to determine which index a b+-tree belongs to based on the -** value stored in the "%_segdir.level" column. Given this value L, the index -** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with -** level values between 0 and 1023 (inclusive) belong to index 0, all levels -** between 1024 and 2047 to index 1, and so on. -** -** It is considered impossible for an index to use more than 1024 levels. In -** theory though this may happen, but only after at least -** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables. -*/ -#define FTS3_SEGDIR_MAXLEVEL 1024 -#define FTS3_SEGDIR_MAXLEVEL_STR "1024" - -/* -** The testcase() macro is only used by the amalgamation. If undefined, -** make it a no-op. -*/ -#ifndef testcase -# define testcase(X) -#endif - -/* -** Terminator values for position-lists and column-lists. -*/ -#define POS_COLUMN (1) /* Column-list terminator */ -#define POS_END (0) /* Position-list terminator */ - -/* -** The assert_fts3_nc() macro is similar to the assert() macro, except that it -** is used for assert() conditions that are true only if it can be -** guranteed that the database is not corrupt. -*/ -#ifdef SQLITE_DEBUG -SQLITE_API extern int sqlite3_fts3_may_be_corrupt; -# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x)) -#else -# define assert_fts3_nc(x) assert(x) -#endif - -/* -** This section provides definitions to allow the -** FTS3 extension to be compiled outside of the -** amalgamation. -*/ -#ifndef SQLITE_AMALGAMATION -/* -** Macros indicating that conditional expressions are always true or -** false. -*/ -#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 - -/* -** Internal types used by SQLite. -*/ -typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ -typedef short int i16; /* 2-byte (or larger) signed integer */ -typedef unsigned int u32; /* 4-byte unsigned integer */ -typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */ -typedef sqlite3_int64 i64; /* 8-byte signed integer */ - -/* -** Macro used to suppress compiler warnings for unused parameters. -*/ -#define UNUSED_PARAMETER(x) (void)(x) - -/* -** Activate assert() only if SQLITE_TEST is enabled. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* -** The TESTONLY macro is used to enclose variable declarations or -** other bits of code that are needed to support the arguments -** within testcase() and assert() macros. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) -# define TESTONLY(X) X -#else -# define TESTONLY(X) -#endif - -#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) -#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) - -#define deliberate_fall_through - -/* -** Macros needed to provide flexible arrays in a portable way -*/ -#ifndef offsetof -# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define FLEXARRAY -#else -# define FLEXARRAY 1 -#endif - - -#endif /* SQLITE_AMALGAMATION */ - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3Fts3Corrupt(void); -# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() -#else -# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB -#endif - -typedef struct Fts3Table Fts3Table; -typedef struct Fts3Cursor Fts3Cursor; -typedef struct Fts3Expr Fts3Expr; -typedef struct Fts3Phrase Fts3Phrase; -typedef struct Fts3PhraseToken Fts3PhraseToken; - -typedef struct Fts3Doclist Fts3Doclist; -typedef struct Fts3SegFilter Fts3SegFilter; -typedef struct Fts3DeferredToken Fts3DeferredToken; -typedef struct Fts3SegReader Fts3SegReader; -typedef struct Fts3MultiSegReader Fts3MultiSegReader; - -typedef struct MatchinfoBuffer MatchinfoBuffer; - -/* -** A connection to a fulltext index is an instance of the following -** structure. The xCreate and xConnect methods create an instance -** of this structure and xDestroy and xDisconnect free that instance. -** All other methods receive a pointer to the structure as one of their -** arguments. -*/ -struct Fts3Table { - sqlite3_vtab base; /* Base class used by SQLite core */ - sqlite3 *db; /* The database connection */ - const char *zDb; /* logical database name */ - const char *zName; /* virtual table name */ - int nColumn; /* number of named columns in virtual table */ - char **azColumn; /* column names. malloced */ - u8 *abNotindexed; /* True for 'notindexed' columns */ - sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ - char *zContentTbl; /* content=xxx option, or NULL */ - char *zLanguageid; /* languageid=xxx option, or NULL */ - int nAutoincrmerge; /* Value configured by 'automerge' */ - u32 nLeafAdd; /* Number of leaf blocks added this trans */ - int bLock; /* Used to prevent recursive content= tbls */ - - /* Precompiled statements used by the implementation. Each of these - ** statements is run and reset within a single virtual table API call. - */ - sqlite3_stmt *aStmt[40]; - sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */ - - char *zReadExprlist; - char *zWriteExprlist; - - int nNodeSize; /* Soft limit for node size */ - u8 bFts4; /* True for FTS4, false for FTS3 */ - u8 bHasStat; /* True if %_stat table exists (2==unknown) */ - u8 bHasDocsize; /* True if %_docsize table exists */ - u8 bDescIdx; /* True if doclists are in reverse order */ - u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ - int nPgsz; /* Page size for host database */ - char *zSegmentsTbl; /* Name of %_segments table */ - sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ - int iSavepoint; - - /* - ** The following array of hash tables is used to buffer pending index - ** updates during transactions. All pending updates buffered at any one - ** time must share a common language-id (see the FTS4 langid= feature). - ** The current language id is stored in variable iPrevLangid. - ** - ** A single FTS4 table may have multiple full-text indexes. For each index - ** there is an entry in the aIndex[] array. Index 0 is an index of all the - ** terms that appear in the document set. Each subsequent index in aIndex[] - ** is an index of prefixes of a specific length. - ** - ** Variable nPendingData contains an estimate the memory consumed by the - ** pending data structures, including hash table overhead, but not including - ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash - ** tables are flushed to disk. Variable iPrevDocid is the docid of the most - ** recently inserted record. - */ - int nIndex; /* Size of aIndex[] */ - struct Fts3Index { - int nPrefix; /* Prefix length (0 for main terms index) */ - Fts3Hash hPending; /* Pending terms table for this index */ - } *aIndex; - int nMaxPendingData; /* Max pending data before flush to disk */ - int nPendingData; /* Current bytes of pending data */ - sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ - int iPrevLangid; /* Langid of recently inserted document */ - int bPrevDelete; /* True if last operation was a delete */ - -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - /* State variables used for validating that the transaction control - ** methods of the virtual table are called at appropriate times. These - ** values do not contribute to FTS functionality; they are used for - ** verifying the operation of the SQLite core. - */ - int inTransaction; /* True after xBegin but before xCommit/xRollback */ - int mxSavepoint; /* Largest valid xSavepoint integer */ -#endif - -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* True to disable the incremental doclist optimization. This is controlled - ** by special insert command 'test-no-incr-doclist'. */ - int bNoIncrDoclist; - - /* Number of segments in a level */ - int nMergeCount; -#endif -}; - -/* Macro to find the number of segments to merge */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) -# define MergeCount(P) ((P)->nMergeCount) -#else -# define MergeCount(P) FTS3_MERGE_COUNT -#endif - -/* -** When the core wants to read from the virtual table, it creates a -** virtual table cursor (an instance of the following structure) using -** the xOpen method. Cursors are destroyed using the xClose method. -*/ -struct Fts3Cursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - i16 eSearch; /* Search strategy (see below) */ - u8 isEof; /* True if at End Of Results */ - u8 isRequireSeek; /* True if must seek pStmt to %_content row */ - u8 bSeekStmt; /* True if pStmt is a seek */ - sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ - Fts3Expr *pExpr; /* Parsed MATCH query string */ - int iLangid; /* Language being queried for */ - int nPhrase; /* Number of matchable phrases in query */ - Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ - sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ - char *pNextId; /* Pointer into the body of aDoclist */ - char *aDoclist; /* List of docids for full-text queries */ - int nDoclist; /* Size of buffer at aDoclist */ - u8 bDesc; /* True to sort in descending order */ - int eEvalmode; /* An FTS3_EVAL_XX constant */ - int nRowAvg; /* Average size of database rows, in pages */ - sqlite3_int64 nDoc; /* Documents in table */ - i64 iMinDocid; /* Minimum docid to return */ - i64 iMaxDocid; /* Maximum docid to return */ - int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ - MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */ -}; - -#define FTS3_EVAL_FILTER 0 -#define FTS3_EVAL_NEXT 1 -#define FTS3_EVAL_MATCHINFO 2 - -/* -** The Fts3Cursor.eSearch member is always set to one of the following. -** Actually, Fts3Cursor.eSearch can be greater than or equal to -** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index -** of the column to be searched. For example, in -** -** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); -** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; -** -** Because the LHS of the MATCH operator is 2nd column "b", -** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, -** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" -** indicating that all columns should be searched, -** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. -*/ -#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ -#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ -#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ - -/* -** The lower 16-bits of the sqlite3_index_info.idxNum value set by -** the xBestIndex() method contains the Fts3Cursor.eSearch value described -** above. The upper 16-bits contain a combination of the following -** bits, used to describe extra constraints on full-text searches. -*/ -#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */ -#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */ -#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */ - -struct Fts3Doclist { - char *aAll; /* Array containing doclist (or NULL) */ - int nAll; /* Size of a[] in bytes */ - char *pNextDocid; /* Pointer to next docid */ - - sqlite3_int64 iDocid; /* Current docid (if pList!=0) */ - int bFreeList; /* True if pList should be sqlite3_free()d */ - char *pList; /* Pointer to position list following iDocid */ - int nList; /* Length of position list */ -}; - -/* -** A "phrase" is a sequence of one or more tokens that must match in -** sequence. A single token is the base case and the most common case. -** For a sequence of tokens contained in double-quotes (i.e. "one two three") -** nToken will be the number of tokens in the string. -*/ -struct Fts3PhraseToken { - char *z; /* Text of the token */ - int n; /* Number of bytes in buffer z */ - int isPrefix; /* True if token ends with a "*" character */ - int bFirst; /* True if token must appear at position 0 */ - - /* Variables above this point are populated when the expression is - ** parsed (by code in fts3_expr.c). Below this point the variables are - ** used when evaluating the expression. */ - Fts3DeferredToken *pDeferred; /* Deferred token object for this token */ - Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */ -}; - -struct Fts3Phrase { - /* Cache of doclist for this phrase. */ - Fts3Doclist doclist; - int bIncr; /* True if doclist is loaded incrementally */ - int iDoclistToken; - - /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an - ** OR condition. */ - char *pOrPoslist; - i64 iOrDocid; - - /* Variables below this point are populated by fts3_expr.c when parsing - ** a MATCH expression. Everything above is part of the evaluation phase. - */ - int nToken; /* Number of tokens in the phrase */ - int iColumn; /* Index of column this phrase must match */ - Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */ -}; - -/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */ -#define SZ_FTS3PHRASE(N) \ - (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken)) - -/* -** A tree of these objects forms the RHS of a MATCH operator. -** -** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist -** points to a malloced buffer, size nDoclist bytes, containing the results -** of this phrase query in FTS3 doclist format. As usual, the initial -** "Length" field found in doclists stored on disk is omitted from this -** buffer. -** -** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global -** matchinfo data. If it is not NULL, it points to an array of size nCol*3, -** where nCol is the number of columns in the queried FTS table. The array -** is populated as follows: -** -** aMI[iCol*3 + 0] = Undefined -** aMI[iCol*3 + 1] = Number of occurrences -** aMI[iCol*3 + 2] = Number of rows containing at least one instance -** -** The aMI array is allocated using sqlite3_malloc(). It should be freed -** when the expression node is. -*/ -struct Fts3Expr { - int eType; /* One of the FTSQUERY_XXX values defined below */ - int nNear; /* Valid if eType==FTSQUERY_NEAR */ - Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */ - Fts3Expr *pLeft; /* Left operand */ - Fts3Expr *pRight; /* Right operand */ - Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */ - - /* The following are used by the fts3_eval.c module. */ - sqlite3_int64 iDocid; /* Current docid */ - u8 bEof; /* True this expression is at EOF already */ - u8 bStart; /* True if iDocid is valid */ - u8 bDeferred; /* True if this expression is entirely deferred */ - - /* The following are used by the fts3_snippet.c module. */ - int iPhrase; /* Index of this phrase in matchinfo() results */ - u32 *aMI; /* See above */ -}; - -/* -** Candidate values for Fts3Query.eType. Note that the order of the first -** four values is in order of precedence when parsing expressions. For -** example, the following: -** -** "a OR b AND c NOT d NEAR e" -** -** is equivalent to: -** -** "a OR (b AND (c NOT (d NEAR e)))" -*/ -#define FTSQUERY_NEAR 1 -#define FTSQUERY_NOT 2 -#define FTSQUERY_AND 3 -#define FTSQUERY_OR 4 -#define FTSQUERY_PHRASE 5 - - -/* fts3_write.c */ -SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); -SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); -SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, - sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); -SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( - Fts3Table*,int,const char*,int,int,Fts3SegReader**); -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); -SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); - -SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); -SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); -SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); -SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); -SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); -#else -# define sqlite3Fts3FreeDeferredTokens(x) -# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK -# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK -# define sqlite3Fts3FreeDeferredDoclists(x) -# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK -#endif - -SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *); - -/* Special values interpreted by sqlite3SegReaderCursor() */ -#define FTS3_SEGCURSOR_PENDING -1 -#define FTS3_SEGCURSOR_ALL -2 - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); -SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); -SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); - -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, - int, int, int, const char *, int, int, int, Fts3MultiSegReader *); - -/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ -#define FTS3_SEGMENT_REQUIRE_POS 0x00000001 -#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 -#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 -#define FTS3_SEGMENT_PREFIX 0x00000008 -#define FTS3_SEGMENT_SCAN 0x00000010 -#define FTS3_SEGMENT_FIRST 0x00000020 - -/* Type passed as 4th argument to SegmentReaderIterate() */ -struct Fts3SegFilter { - const char *zTerm; - int nTerm; - int iCol; - int flags; -}; - -struct Fts3MultiSegReader { - /* Used internally by sqlite3Fts3SegReaderXXX() calls */ - Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */ - int nSegment; /* Size of apSegment array */ - int nAdvance; /* How many seg-readers to advance */ - Fts3SegFilter *pFilter; /* Pointer to filter object */ - char *aBuffer; /* Buffer to merge doclists in */ - i64 nBuffer; /* Allocated size of aBuffer[] in bytes */ - - int iColFilter; /* If >=0, filter for this column */ - int bRestart; - - /* Used by fts3.c only. */ - int nCost; /* Cost of running iterator */ - int bLookup; /* True if a lookup of a single entry. */ - - /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */ - char *zTerm; /* Pointer to term buffer */ - int nTerm; /* Size of zTerm in bytes */ - char *aDoclist; /* Pointer to doclist buffer */ - int nDoclist; /* Size of aDoclist[] in bytes */ -}; - -SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); - -#define fts3GetVarint32(p, piVal) ( \ - (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \ -) - -/* fts3.c */ -SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); -SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); -SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *); -SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*); -SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); -SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); -SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); -SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); -SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); -SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); -SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*); -SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc); -SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut); - -/* fts3_tokenizer.c */ -SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); -SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); -SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, - sqlite3_tokenizer **, char ** -); -SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char); - -/* fts3_snippet.c */ -SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); -SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, - const char *, const char *, int, int -); -SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); -SQLITE_PRIVATE void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p); - -/* fts3_expr.c */ -SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, - char **, int, int, int, const char *, int, Fts3Expr **, char ** -); -SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); -#ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); -SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); -#endif -SQLITE_PRIVATE void *sqlite3Fts3MallocZero(i64 nByte); - -SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, - sqlite3_tokenizer_cursor ** -); - -/* fts3_aux.c */ -SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); - -SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( - Fts3Table*, Fts3MultiSegReader*, int, const char*, int); -SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( - Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); -SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); -SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); -SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); -SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor*, Fts3Expr*); - -/* fts3_tokenize_vtab.c */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*)); - -/* fts3_unicode2.c (functions generated by parsing unicode text files) */ -#ifndef SQLITE_DISABLE_FTS3_UNICODE -SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); -SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); -SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); -#endif - -SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*); - -SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk); - -#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ -#endif /* _FTSINT_H */ - -/************** End of fts3Int.h *********************************************/ -/************** Continuing where we left off in fts3.c ***********************/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) -# define SQLITE_CORE 1 -#endif - - -/* #include "fts3.h" */ -#ifndef SQLITE_CORE -/* # include "sqlite3ext.h" */ - 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 **); - -/* -** 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 sqlite3_fts3_may_be_corrupt = 1; -#endif - -/* -** Write a 64-bit variable-length integer to memory starting at p[0]. -** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. -** The number of bytes written is returned. -*/ -SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ - unsigned char *q = (unsigned char *) p; - sqlite_uint64 vu = v; - do{ - *q++ = (unsigned char) ((vu & 0x7f) | 0x80); - vu >>= 7; - }while( vu!=0 ); - q[-1] &= 0x7f; /* turn off high bit in final byte */ - assert( q - (unsigned char *)p <= FTS3_VARINT_MAX ); - return (int) (q - (unsigned char *)p); -} - -#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \ - v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \ - if( (v & mask2)==0 ){ var = v; return ret; } -#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \ - v = (*ptr++); \ - if( (v & mask2)==0 ){ var = v; return ret; } - -SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){ - const unsigned char *p = (const unsigned char*)pBuf; - const unsigned char *pStart = p; - u32 a; - u64 b; - int shift; - - GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1); - GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2); - GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3); - GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4); - b = (a & 0x0FFFFFFF ); - - for(shift=28; shift<=63; shift+=7){ - u64 c = *p++; - b += (c&0x7F) << shift; - if( (c & 0x80)==0 ) break; - } - *v = b; - return (int)(p - pStart); -} - -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ - return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v); -} - -/* -** Read a 64-bit variable-length integer from memory starting at p[0] and -** not extending past pEnd[-1]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded( - const char *pBuf, - const char *pEnd, - sqlite_int64 *v -){ - const unsigned char *p = (const unsigned char*)pBuf; - const unsigned char *pStart = p; - const unsigned char *pX = (const unsigned char*)pEnd; - u64 b = 0; - int shift; - for(shift=0; shift<=63; shift+=7){ - u64 c = p=0 ); - return 5; -} - -/* -** Return the number of bytes required to encode v as a varint -*/ -SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64 v){ - int i = 0; - do{ - i++; - v >>= 7; - }while( v!=0 ); - return i; -} - -/* -** Convert an SQL-style quoted string into a normal string by removing -** the quote characters. The conversion is done in-place. If the -** input does not begin with a quote character, then this routine -** is a no-op. -** -** Examples: -** -** "abc" becomes abc -** 'xyz' becomes xyz -** [pqr] becomes pqr -** `mno` becomes mno -** -*/ -SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){ - char quote; /* Quote character (if any ) */ - - quote = z[0]; - if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ - int iIn = 1; /* Index of next byte to read from input */ - int iOut = 0; /* Index of next byte to write to output */ - - /* If the first byte was a '[', then the close-quote character is a ']' */ - if( quote=='[' ) quote = ']'; - - while( z[iIn] ){ - if( z[iIn]==quote ){ - if( z[iIn+1]!=quote ) break; - z[iOut++] = quote; - iIn += 2; - }else{ - z[iOut++] = z[iIn++]; - } - } - z[iOut] = '\0'; - } -} - -/* -** Read a single varint from the doclist at *pp and advance *pp to point -** to the first byte past the end of the varint. Add the value of the varint -** to *pVal. -*/ -static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); - *pVal += iVal; -} - -/* -** When this function is called, *pp points to the first byte following a -** varint that is part of a doclist (or position-list, or any other list -** of varints). This function moves *pp to point to the start of that varint, -** and sets *pVal by the varint value. -** -** Argument pStart points to the first byte of the doclist that the -** varint is part of. -*/ -static void fts3GetReverseVarint( - char **pp, - char *pStart, - sqlite3_int64 *pVal -){ - sqlite3_int64 iVal; - char *p; - - /* Pointer p now points at the first byte past the varint we are - ** interested in. So, unless the doclist is corrupt, the 0x80 bit is - ** clear on character p[-1]. */ - for(p = (*pp)-2; p>=pStart && *p&0x80; p--); - p++; - *pp = p; - - sqlite3Fts3GetVarint(p, &iVal); - *pVal = iVal; -} - -/* -** The xDisconnect() virtual table method. -*/ -static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int i; - - assert( p->nPendingData==0 ); - assert( p->pSegments==0 ); - - /* Free any prepared statements held */ - sqlite3_finalize(p->pSeekStmt); - for(i=0; iaStmt); i++){ - sqlite3_finalize(p->aStmt[i]); - } - sqlite3_free(p->zSegmentsTbl); - sqlite3_free(p->zReadExprlist); - sqlite3_free(p->zWriteExprlist); - sqlite3_free(p->zContentTbl); - sqlite3_free(p->zLanguageid); - - /* Invoke the tokenizer destructor to free the tokenizer. */ - p->pTokenizer->pModule->xDestroy(p->pTokenizer); - - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Write an error message into *pzErr -*/ -SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ - va_list ap; - sqlite3_free(*pzErr); - va_start(ap, zFormat); - *pzErr = sqlite3_vmprintf(zFormat, ap); - va_end(ap); -} - -/* -** Construct one or more SQL statements from the format string given -** and then evaluate those statements. The success code is written -** into *pRc. -** -** If *pRc is initially non-zero then this routine is a no-op. -*/ -static void fts3DbExec( - int *pRc, /* Success code */ - sqlite3 *db, /* Database in which to run SQL */ - const char *zFormat, /* Format string for SQL */ - ... /* Arguments to the format string */ -){ - va_list ap; - char *zSql; - if( *pRc ) return; - va_start(ap, zFormat); - zSql = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( zSql==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - *pRc = sqlite3_exec(db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } -} - -/* -** The xDestroy() virtual table method. -*/ -static int fts3DestroyMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return code */ - const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */ - sqlite3 *db = p->db; /* Database handle */ - - /* Drop the shadow tables */ - fts3DbExec(&rc, db, - "DROP TABLE IF EXISTS %Q.'%q_segments';" - "DROP TABLE IF EXISTS %Q.'%q_segdir';" - "DROP TABLE IF EXISTS %Q.'%q_docsize';" - "DROP TABLE IF EXISTS %Q.'%q_stat';" - "%s DROP TABLE IF EXISTS %Q.'%q_content';", - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - (p->zContentTbl ? "--" : ""), zDb,p->zName - ); - - /* If everything has worked, invoke fts3DisconnectMethod() to free the - ** memory associated with the Fts3Table structure and return SQLITE_OK. - ** Otherwise, return an SQLite error code. - */ - return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc); -} - - -/* -** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table -** passed as the first argument. This is done as part of the xConnect() -** and xCreate() methods. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DeclareVtab(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int i; /* Iterator variable */ - int rc; /* Return code */ - char *zSql; /* SQL statement passed to declare_vtab() */ - char *zCols; /* List of user defined columns */ - const char *zLanguageid; - - zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); - sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(p->db, SQLITE_VTAB_INNOCUOUS); - - /* Create a list of user columns for the virtual table */ - zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); - for(i=1; zCols && inColumn; i++){ - zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); - } - - /* Create the whole "CREATE TABLE" statement to pass to SQLite */ - zSql = sqlite3_mprintf( - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", - zCols, p->zName, zLanguageid - ); - if( !zCols || !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_declare_vtab(p->db, zSql); - } - - sqlite3_free(zSql); - sqlite3_free(zCols); - *pRc = rc; - } -} - -/* -** Create the %_stat table if it does not already exist. -*/ -SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){ - fts3DbExec(pRc, p->db, - "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'" - "(id INTEGER PRIMARY KEY, value BLOB);", - p->zDb, p->zName - ); - if( (*pRc)==SQLITE_OK ) p->bHasStat = 1; -} - -/* -** Create the backing store tables (%_content, %_segments and %_segdir) -** required by the FTS3 table passed as the only argument. This is done -** as part of the vtab xCreate() method. -** -** If the p->bHasDocsize boolean is true (indicating that this is an -** FTS4 table, not an FTS3 table) then also create the %_docsize and -** %_stat tables required by FTS4. -*/ -static int fts3CreateTables(Fts3Table *p){ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - sqlite3 *db = p->db; /* The database connection */ - - if( p->zContentTbl==0 ){ - const char *zLanguageid = p->zLanguageid; - char *zContentCols; /* Columns of %_content table */ - - /* Create a list of user columns for the content table */ - zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); - for(i=0; zContentCols && inColumn; i++){ - char *z = p->azColumn[i]; - zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); - } - if( zLanguageid && zContentCols ){ - zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); - } - if( zContentCols==0 ) rc = SQLITE_NOMEM; - - /* Create the content table */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_content'(%s)", - p->zDb, p->zName, zContentCols - ); - sqlite3_free(zContentCols); - } - - /* Create other tables */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", - p->zDb, p->zName - ); - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segdir'(" - "level INTEGER," - "idx INTEGER," - "start_block INTEGER," - "leaves_end_block INTEGER," - "end_block INTEGER," - "root BLOB," - "PRIMARY KEY(level, idx)" - ");", - p->zDb, p->zName - ); - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", - p->zDb, p->zName - ); - } - assert( p->bHasStat==p->bFts4 ); - if( p->bHasStat ){ - sqlite3Fts3CreateStatTable(&rc, p); - } - return rc; -} - -/* -** Store the current database page-size in bytes in p->nPgsz. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int rc; /* Return code */ - char *zSql; /* SQL text "PRAGMA %Q.page_size" */ - sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */ - - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_step(pStmt); - p->nPgsz = sqlite3_column_int(pStmt, 0); - rc = sqlite3_finalize(pStmt); - }else if( rc==SQLITE_AUTH ){ - p->nPgsz = 1024; - rc = SQLITE_OK; - } - } - assert( p->nPgsz>0 || rc!=SQLITE_OK ); - sqlite3_free(zSql); - *pRc = rc; - } -} - -/* -** "Special" FTS4 arguments are column specifications of the following form: -** -** = -** -** There may not be whitespace surrounding the "=" character. The -** term may be quoted, but the may not. -*/ -static int fts3IsSpecialColumn( - const char *z, - int *pnKey, - char **pzValue -){ - char *zValue; - const char *zCsr = z; - - while( *zCsr!='=' ){ - if( *zCsr=='\0' ) return 0; - zCsr++; - } - - *pnKey = (int)(zCsr-z); - zValue = sqlite3_mprintf("%s", &zCsr[1]); - if( zValue ){ - sqlite3Fts3Dequote(zValue); - } - *pzValue = zValue; - return 1; -} - -/* -** Append the output of a printf() style formatting to an existing string. -*/ -static void fts3Appendf( - int *pRc, /* IN/OUT: Error code */ - char **pz, /* IN/OUT: Pointer to string buffer */ - const char *zFormat, /* Printf format string to append */ - ... /* Arguments for printf format string */ -){ - if( *pRc==SQLITE_OK ){ - va_list ap; - char *z; - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( z && *pz ){ - char *z2 = sqlite3_mprintf("%s%s", *pz, z); - sqlite3_free(z); - z = z2; - } - if( z==0 ) *pRc = SQLITE_NOMEM; - sqlite3_free(*pz); - *pz = z; - } -} - -/* -** Return a copy of input string zInput enclosed in double-quotes (") and -** with all double quote characters escaped. For example: -** -** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\"" -** -** The pointer returned points to memory obtained from sqlite3_malloc(). It -** is the callers responsibility to call sqlite3_free() to release this -** memory. -*/ -static char *fts3QuoteId(char const *zInput){ - sqlite3_int64 nRet; - char *zRet; - nRet = 2 + (int)strlen(zInput)*2 + 1; - zRet = sqlite3_malloc64(nRet); - if( zRet ){ - int i; - char *z = zRet; - *(z++) = '"'; - for(i=0; zInput[i]; i++){ - if( zInput[i]=='"' ) *(z++) = '"'; - *(z++) = zInput[i]; - } - *(z++) = '"'; - *(z++) = '\0'; - } - return zRet; -} - -/* -** Return a list of comma separated SQL expressions and a FROM clause that -** could be used in a SELECT statement such as the following: -** -** SELECT FROM %_content AS x ... -** -** to return the docid, followed by each column of text data in order -** from left to write. If parameter zFunc is not NULL, then instead of -** being returned directly each column of text data is passed to an SQL -** function named zFunc first. For example, if zFunc is "unzip" and the -** table has the three user-defined columns "a", "b", and "c", the following -** string is returned: -** -** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( p->zContentTbl==0 ){ - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "docid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); - } - sqlite3_free(zFree); - }else{ - fts3Appendf(pRc, &zRet, "rowid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); - } - } - fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", - p->zDb, - (p->zContentTbl ? p->zContentTbl : p->zName), - (p->zContentTbl ? "" : "_content") - ); - return zRet; -} - -/* -** Return a list of N comma separated question marks, where N is the number -** of columns in the %_content table (one for the docid plus one for each -** user-defined text column). -** -** If argument zFunc is not NULL, then all but the first question mark -** is preceded by zFunc and an open bracket, and followed by a closed -** bracket. For example, if zFunc is "zip" and the FTS3 table has three -** user-defined text columns, the following string is returned: -** -** "?, zip(?), zip(?), zip(?)" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "?"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", ?"); - } - sqlite3_free(zFree); - return zRet; -} - -/* -** Buffer z contains a positive integer value encoded as utf-8 text. -** Decode this value and store it in *pnOut, returning the number of bytes -** consumed. If an overflow error occurs return a negative value. -*/ -SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut){ - u64 iVal = 0; - int i; - for(i=0; z[i]>='0' && z[i]<='9'; i++){ - iVal = iVal*10 + (z[i] - '0'); - if( iVal>0x7FFFFFFF ) return -1; - } - *pnOut = (int)iVal; - return i; -} - -/* -** This function interprets the string at (*pp) as a non-negative integer -** value. It reads the integer and sets *pnOut to the value read, then -** sets *pp to point to the byte immediately following the last byte of -** the integer value. -** -** Only decimal digits ('0'..'9') may be part of an integer value. -** -** If *pp does not being with a decimal digit SQLITE_ERROR is returned and -** the output value undefined. Otherwise SQLITE_OK is returned. -** -** This function is used when parsing the "prefix=" FTS4 parameter. -*/ -static int fts3GobbleInt(const char **pp, int *pnOut){ - const int MAX_NPREFIX = 10000000; - int nInt = 0; /* Output value */ - int nByte; - nByte = sqlite3Fts3ReadInt(*pp, &nInt); - if( nInt>MAX_NPREFIX ){ - nInt = 0; - } - if( nByte==0 ){ - return SQLITE_ERROR; - } - *pnOut = nInt; - *pp += nByte; - return SQLITE_OK; -} - -/* -** This function is called to allocate an array of Fts3Index structures -** representing the indexes maintained by the current FTS table. FTS tables -** always maintain the main "terms" index, but may also maintain one or -** more "prefix" indexes, depending on the value of the "prefix=" parameter -** (if any) specified as part of the CREATE VIRTUAL TABLE statement. -** -** Argument zParam is passed the value of the "prefix=" option if one was -** specified, or NULL otherwise. -** -** If no error occurs, SQLITE_OK is returned and *apIndex set to point to -** the allocated array. *pnIndex is set to the number of elements in the -** array. If an error does occur, an SQLite error code is returned. -** -** Regardless of whether or not an error is returned, it is the responsibility -** of the caller to call sqlite3_free() on the output array to free it. -*/ -static int fts3PrefixParameter( - const char *zParam, /* ABC in prefix=ABC parameter to parse */ - int *pnIndex, /* OUT: size of *apIndex[] array */ - struct Fts3Index **apIndex /* OUT: Array of indexes for this table */ -){ - struct Fts3Index *aIndex; /* Allocated array */ - int nIndex = 1; /* Number of entries in array */ - - if( zParam && zParam[0] ){ - const char *p; - nIndex++; - for(p=zParam; *p; p++){ - if( *p==',' ) nIndex++; - } - } - - aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex); - *apIndex = aIndex; - if( !aIndex ){ - return SQLITE_NOMEM; - } - - memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); - if( zParam ){ - const char *p = zParam; - int i; - for(i=1; i=0 ); - if( nPrefix==0 ){ - nIndex--; - i--; - }else{ - aIndex[i].nPrefix = nPrefix; - } - p++; - } - } - - *pnIndex = nIndex; - return SQLITE_OK; -} - -/* -** This function is called when initializing an FTS4 table that uses the -** content=xxx option. It determines the number of and names of the columns -** of the new FTS4 table. -** -** The third argument passed to this function is the value passed to the -** config=xxx option (i.e. "xxx"). This function queries the database for -** a table of that name. If found, the output variables are populated -** as follows: -** -** *pnCol: Set to the number of columns table xxx has, -** -** *pnStr: Set to the total amount of space required to store a copy -** of each columns name, including the nul-terminator. -** -** *pazCol: Set to point to an array of *pnCol strings. Each string is -** the name of the corresponding column in table xxx. The array -** and its contents are allocated using a single allocation. It -** is the responsibility of the caller to free this allocation -** by eventually passing the *pazCol value to sqlite3_free(). -** -** If the table cannot be found, an error code is returned and the output -** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is -** returned (and the output variables are undefined). -*/ -static int fts3ContentColumns( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ - const char *zTbl, /* Name of content table */ - const char ***pazCol, /* OUT: Malloc'd array of column names */ - int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr, /* OUT: Bytes of string content */ - char **pzErr /* OUT: error message */ -){ - int rc = SQLITE_OK; /* Return code */ - char *zSql; /* "SELECT *" statement on zTbl */ - sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ - - zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); - } - } - sqlite3_free(zSql); - - if( rc==SQLITE_OK ){ - const char **azCol; /* Output array */ - sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */ - int nCol; /* Number of table columns */ - int i; /* Used to iterate through columns */ - - /* Loop through the returned columns. Set nStr to the number of bytes of - ** space required to store a copy of each column name, including the - ** nul-terminator byte. */ - nCol = sqlite3_column_count(pStmt); - for(i=0; i module name ("fts3" or "fts4") -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> "column name" and other module argument fields. -*/ -static int fts3InitVtab( - int isCreate, /* True for xCreate, false for xConnect */ - sqlite3 *db, /* The SQLite database connection */ - void *pAux, /* Hash table containing tokenizers */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ - char **pzErr /* Write any error message here */ -){ - Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash; - Fts3Table *p = 0; /* Pointer to allocated vtab */ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - sqlite3_int64 nByte; /* Size of allocation used for *p */ - int iCol; /* Column index */ - int nString = 0; /* Bytes required to hold all column names */ - int nCol = 0; /* Number of columns in the FTS table */ - char *zCsr; /* Space for holding column names */ - int nDb; /* Bytes required to hold database name */ - int nName; /* Bytes required to hold table name */ - int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ - const char **aCol; /* Array of column names */ - sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - - int nIndex = 0; /* Size of aIndex[] array */ - struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ - - /* The results of parsing supported FTS4 key=value options: */ - int bNoDocsize = 0; /* True to omit %_docsize table */ - int bDescIdx = 0; /* True to store descending indexes */ - char *zPrefix = 0; /* Prefix parameter value (or NULL) */ - char *zCompress = 0; /* compress=? parameter (or NULL) */ - char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ - char *zContent = 0; /* content=? parameter (or NULL) */ - char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ - char **azNotindexed = 0; /* The set of notindexed= columns */ - int nNotindexed = 0; /* Size of azNotindexed[] array */ - - assert( strlen(argv[0])==4 ); - assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) - || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) - ); - - nDb = (int)strlen(argv[1]) + 1; - nName = (int)strlen(argv[2]) + 1; - - nByte = sizeof(const char *) * (argc-2); - aCol = (const char **)sqlite3_malloc64(nByte); - if( aCol ){ - memset((void*)aCol, 0, nByte); - azNotindexed = (char **)sqlite3_malloc64(nByte); - } - if( azNotindexed ){ - memset(azNotindexed, 0, nByte); - } - if( !aCol || !azNotindexed ){ - rc = SQLITE_NOMEM; - goto fts3_init_out; - } - - /* Loop through all of the arguments passed by the user to the FTS3/4 - ** module (i.e. all the column names and special arguments). This loop - ** does the following: - ** - ** + Figures out the number of columns the FTSX table will have, and - ** the number of bytes of space that must be allocated to store copies - ** of the column names. - ** - ** + If there is a tokenizer specification included in the arguments, - ** initializes the tokenizer pTokenizer. - */ - for(i=3; rc==SQLITE_OK && i8 - && 0==sqlite3_strnicmp(z, "tokenize", 8) - && 0==sqlite3Fts3IsIdChar(z[8]) - ){ - rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr); - } - - /* Check if it is an FTS4 special argument. */ - else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){ - struct Fts4Option { - const char *zOpt; - int nOpt; - } aFts4Opt[] = { - { "matchinfo", 9 }, /* 0 -> MATCHINFO */ - { "prefix", 6 }, /* 1 -> PREFIX */ - { "compress", 8 }, /* 2 -> COMPRESS */ - { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ - { "order", 5 }, /* 4 -> ORDER */ - { "content", 7 }, /* 5 -> CONTENT */ - { "languageid", 10 }, /* 6 -> LANGUAGEID */ - { "notindexed", 10 } /* 7 -> NOTINDEXED */ - }; - - int iOpt; - if( !zVal ){ - rc = SQLITE_NOMEM; - }else{ - for(iOpt=0; iOptnOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ - break; - } - } - switch( iOpt ){ - case 0: /* MATCHINFO */ - if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); - rc = SQLITE_ERROR; - } - bNoDocsize = 1; - break; - - case 1: /* PREFIX */ - sqlite3_free(zPrefix); - zPrefix = zVal; - zVal = 0; - break; - - case 2: /* COMPRESS */ - sqlite3_free(zCompress); - zCompress = zVal; - zVal = 0; - break; - - case 3: /* UNCOMPRESS */ - sqlite3_free(zUncompress); - zUncompress = zVal; - zVal = 0; - break; - - case 4: /* ORDER */ - if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) - && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) - ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); - rc = SQLITE_ERROR; - } - bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); - break; - - case 5: /* CONTENT */ - sqlite3_free(zContent); - zContent = zVal; - zVal = 0; - break; - - case 6: /* LANGUAGEID */ - assert( iOpt==6 ); - sqlite3_free(zLanguageid); - zLanguageid = zVal; - zVal = 0; - break; - - case 7: /* NOTINDEXED */ - azNotindexed[nNotindexed++] = zVal; - zVal = 0; - break; - - default: - assert( iOpt==SizeofArray(aFts4Opt) ); - sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); - rc = SQLITE_ERROR; - break; - } - sqlite3_free(zVal); - } - } - - /* Otherwise, the argument is a column name. */ - else { - nString += (int)(strlen(z) + 1); - aCol[nCol++] = z; - } - } - - /* If a content=xxx option was specified, the following: - ** - ** 1. Ignore any compress= and uncompress= options. - ** - ** 2. If no column names were specified as part of the CREATE VIRTUAL - ** TABLE statement, use all columns from the content table. - */ - if( rc==SQLITE_OK && zContent ){ - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - zCompress = 0; - zUncompress = 0; - if( nCol==0 ){ - sqlite3_free((void*)aCol); - aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); - - /* If a languageid= option was specified, remove the language id - ** column from the aCol[] array. */ - if( rc==SQLITE_OK && zLanguageid ){ - int j; - for(j=0; jdb = db; - p->nColumn = nCol; - p->nPendingData = 0; - p->azColumn = (char **)&p[1]; - p->pTokenizer = pTokenizer; - p->nMaxPendingData = FTS3_MAX_PENDING_DATA; - p->bHasDocsize = (isFts4 && bNoDocsize==0); - p->bHasStat = (u8)isFts4; - p->bFts4 = (u8)isFts4; - p->bDescIdx = (u8)bDescIdx; - p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ - p->zContentTbl = zContent; - p->zLanguageid = zLanguageid; - zContent = 0; - zLanguageid = 0; - TESTONLY( p->inTransaction = -1 ); - TESTONLY( p->mxSavepoint = -1 ); - - p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; - memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); - p->nIndex = nIndex; - for(i=0; iaIndex[i].hPending, FTS3_HASH_STRING, 1); - } - p->abNotindexed = (u8 *)&p->aIndex[nIndex]; - - /* Fill in the zName and zDb fields of the vtab structure. */ - zCsr = (char *)&p->abNotindexed[nCol]; - p->zName = zCsr; - memcpy(zCsr, argv[2], nName); - zCsr += nName; - p->zDb = zCsr; - memcpy(zCsr, argv[1], nDb); - zCsr += nDb; - - /* Fill in the azColumn array */ - for(iCol=0; iCol0 ){ - memcpy(zCsr, z, n); - } - zCsr[n] = '\0'; - sqlite3Fts3Dequote(zCsr); - p->azColumn[iCol] = zCsr; - zCsr += n+1; - assert( zCsr <= &((char *)p)[nByte] ); - } - - /* Fill in the abNotindexed array */ - for(iCol=0; iColazColumn[iCol]); - for(i=0; iazColumn[iCol], zNot, n) - ){ - p->abNotindexed[iCol] = 1; - sqlite3_free(zNot); - azNotindexed[i] = 0; - } - } - } - for(i=0; izReadExprlist = fts3ReadExprList(p, zUncompress, &rc); - p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); - if( rc!=SQLITE_OK ) goto fts3_init_out; - - /* If this is an xCreate call, create the underlying tables in the - ** database. TODO: For xConnect(), it could verify that said tables exist. - */ - if( isCreate ){ - rc = fts3CreateTables(p); - } - - /* Check to see if a legacy fts3 table has been "upgraded" by the - ** addition of a %_stat table so that it can use incremental merge. - */ - if( !isFts4 && !isCreate ){ - p->bHasStat = 2; - } - - /* Figure out the page-size for the database. This is required in order to - ** estimate the cost of loading large doclists from the database. */ - fts3DatabasePageSize(&rc, p); - p->nNodeSize = p->nPgsz-35; - -#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST) - p->nMergeCount = FTS3_MERGE_COUNT; -#endif - - /* Declare the table schema to SQLite. */ - fts3DeclareVtab(&rc, p); - -fts3_init_out: - sqlite3_free(zPrefix); - sqlite3_free(aIndex); - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - sqlite3_free(zContent); - sqlite3_free(zLanguageid); - for(i=0; ipModule->xDestroy(pTokenizer); - } - }else{ - assert( p->pSegments==0 ); - *ppVTab = &p->base; - } - return rc; -} - -/* -** The xConnect() and xCreate() methods for the virtual table. All the -** work is done in function fts3InitVtab(). -*/ -static int fts3ConnectMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr); -} -static int fts3CreateMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr); -} - -/* -** Set the pIdxInfo->estimatedRows variable to nRow. Unless this -** extension is currently being used by a version of SQLite too old to -** support estimatedRows. In that case this function is a no-op. -*/ -static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ -#if SQLITE_VERSION_NUMBER>=3008002 - if( sqlite3_libversion_number()>=3008002 ){ - pIdxInfo->estimatedRows = nRow; - } -#endif -} - -/* -** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this -** extension is currently being used by a version of SQLite too old to -** support index-info flags. In that case this function is a no-op. -*/ -static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ -#if SQLITE_VERSION_NUMBER>=3008012 - if( sqlite3_libversion_number()>=3008012 ){ - pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; - } -#endif -} - -/* -** Implementation of the xBestIndex method for FTS3 tables. There -** are three possible strategies, in order of preference: -** -** 1. Direct lookup by rowid or docid. -** 2. Full-text search using a MATCH operator on a non-docid column. -** 3. Linear scan of %_content table. -*/ -static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ - Fts3Table *p = (Fts3Table *)pVTab; - int i; /* Iterator variable */ - int iCons = -1; /* Index of constraint to use */ - - int iLangidCons = -1; /* Index of langid=x constraint, if present */ - int iDocidGe = -1; /* Index of docid>=x constraint, if present */ - int iDocidLe = -1; /* Index of docid<=x constraint, if present */ - int iIdx; - - if( p->bLock ){ - return SQLITE_ERROR; - } - - /* By default use a full table scan. This is an expensive option, - ** so search through the constraints to see if a more efficient - ** strategy is possible. - */ - pInfo->idxNum = FTS3_FULLSCAN_SEARCH; - pInfo->estimatedCost = 5000000; - for(i=0; inConstraint; i++){ - int bDocid; /* True if this constraint is on docid */ - struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; - if( pCons->usable==0 ){ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - /* There exists an unusable MATCH constraint. This means that if - ** the planner does elect to use the results of this call as part - ** of the overall query plan the user will see an "unable to use - ** function MATCH in the requested context" error. To discourage - ** this, return a very high cost here. */ - pInfo->idxNum = FTS3_FULLSCAN_SEARCH; - pInfo->estimatedCost = 1e50; - fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50); - return SQLITE_OK; - } - continue; - } - - bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1); - - /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ - if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){ - pInfo->idxNum = FTS3_DOCID_SEARCH; - pInfo->estimatedCost = 1.0; - iCons = i; - } - - /* A MATCH constraint. Use a full-text search. - ** - ** If there is more than one MATCH constraint available, use the first - ** one encountered. If there is both a MATCH constraint and a direct - ** rowid/docid lookup, prefer the MATCH strategy. This is done even - ** though the rowid/docid lookup is faster than a MATCH query, selecting - ** it would lead to an "unable to use function MATCH in the requested - ** context" error. - */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH - && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn - ){ - pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; - pInfo->estimatedCost = 2.0; - iCons = i; - } - - /* Equality constraint on the langid column */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ - && pCons->iColumn==p->nColumn + 2 - ){ - iLangidCons = i; - } - - if( bDocid ){ - switch( pCons->op ){ - case SQLITE_INDEX_CONSTRAINT_GE: - case SQLITE_INDEX_CONSTRAINT_GT: - iDocidGe = i; - break; - - case SQLITE_INDEX_CONSTRAINT_LE: - case SQLITE_INDEX_CONSTRAINT_LT: - iDocidLe = i; - break; - } - } - } - - /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ - if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); - - iIdx = 1; - if( iCons>=0 ){ - pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; - pInfo->aConstraintUsage[iCons].omit = 1; - } - if( iLangidCons>=0 ){ - pInfo->idxNum |= FTS3_HAVE_LANGID; - pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; - } - if( iDocidGe>=0 ){ - pInfo->idxNum |= FTS3_HAVE_DOCID_GE; - pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++; - } - if( iDocidLe>=0 ){ - pInfo->idxNum |= FTS3_HAVE_DOCID_LE; - pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++; - } - - /* Regardless of the strategy selected, FTS can deliver rows in rowid (or - ** docid) order. Both ascending and descending are possible. - */ - if( pInfo->nOrderBy==1 ){ - struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0]; - if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){ - if( pOrder->desc ){ - pInfo->idxStr = "DESC"; - }else{ - pInfo->idxStr = "ASC"; - } - pInfo->orderByConsumed = 1; - } - } - - assert( p->pSegments==0 ); - return SQLITE_OK; -} - -/* -** Implementation of xOpen method. -*/ -static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ - - UNUSED_PARAMETER(pVTab); - - /* Allocate a buffer large enough for an Fts3Cursor structure. If the - ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, - ** if the allocation fails, return SQLITE_NOMEM. - */ - *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3Cursor)); - return SQLITE_OK; -} - -/* -** Finalize the statement handle at pCsr->pStmt. -** -** Or, if that statement handle is one created by fts3CursorSeekStmt(), -** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement -** pointer there instead of finalizing it. -*/ -static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ - if( pCsr->bSeekStmt ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - if( p->pSeekStmt==0 ){ - p->pSeekStmt = pCsr->pStmt; - sqlite3_reset(pCsr->pStmt); - pCsr->pStmt = 0; - } - pCsr->bSeekStmt = 0; - } - sqlite3_finalize(pCsr->pStmt); -} - -/* -** Free all resources currently held by the cursor passed as the only -** argument. -*/ -static void fts3ClearCursor(Fts3Cursor *pCsr){ - fts3CursorFinalizeStmt(pCsr); - sqlite3Fts3FreeDeferredTokens(pCsr); - sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - sqlite3Fts3ExprFree(pCsr->pExpr); - memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); -} - -/* -** Close the cursor. For additional information see the documentation -** on the xClose method of the virtual table interface. -*/ -static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - fts3ClearCursor(pCsr); - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then -** compose and prepare an SQL statement of the form: -** -** "SELECT FROM %_content WHERE rowid = ?" -** -** (or the equivalent for a content=xxx table) and set pCsr->pStmt to -** it. If an error occurs, return an SQLite error code. -*/ -static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; - if( pCsr->pStmt==0 ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - char *zSql; - if( p->pSeekStmt ){ - pCsr->pStmt = p->pSeekStmt; - p->pSeekStmt = 0; - }else{ - zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); - if( !zSql ) return SQLITE_NOMEM; - p->bLock++; - rc = sqlite3_prepare_v3( - p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 - ); - p->bLock--; - sqlite3_free(zSql); - } - if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; - } - return rc; -} - -/* -** Position the pCsr->pStmt statement so that it is on the row -** of the %_content table that contains the last match. Return -** SQLITE_OK on success. -*/ -static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ - int rc = SQLITE_OK; - if( pCsr->isRequireSeek ){ - rc = fts3CursorSeekStmt(pCsr); - if( rc==SQLITE_OK ){ - Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; - pTab->bLock++; - sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); - pCsr->isRequireSeek = 0; - if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ - pTab->bLock--; - return SQLITE_OK; - }else{ - pTab->bLock--; - rc = sqlite3_reset(pCsr->pStmt); - if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ - /* If no row was found and no error has occurred, then the %_content - ** table is missing a row that is present in the full-text index. - ** The data structures are corrupt. */ - rc = FTS_CORRUPT_VTAB; - pCsr->isEof = 1; - } - } - } - } - - if( rc!=SQLITE_OK && pContext ){ - sqlite3_result_error_code(pContext, rc); - } - return rc; -} - -/* -** This function is used to process a single interior node when searching -** a b-tree for a term or term prefix. The node data is passed to this -** function via the zNode/nNode parameters. The term to search for is -** passed in zTerm/nTerm. -** -** If piFirst is not NULL, then this function sets *piFirst to the blockid -** of the child node that heads the sub-tree that may contain the term. -** -** If piLast is not NULL, then *piLast is set to the right-most child node -** that heads a sub-tree that may contain a term for which zTerm/nTerm is -** a prefix. -** -** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. -*/ -static int fts3ScanInteriorNode( - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piFirst, /* OUT: Selected child node */ - sqlite3_int64 *piLast /* OUT: Selected child node */ -){ - int rc = SQLITE_OK; /* Return code */ - const char *zCsr = zNode; /* Cursor to iterate through node */ - const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ - 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 */ - 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 - ** interior node. Then load the blockid of the left-child of the b-tree - ** node into variable iChild. - ** - ** Even if the data structure on disk is corrupted, this (reading two - ** varints from the buffer) does not risk an overread. If zNode is a - ** root node, then the buffer comes from a SELECT statement. SQLite does - ** not make this guarantee explicitly, but in practice there are always - ** either more than 20 bytes of allocated space following the nNode bytes of - ** contents, or two zero bytes. Or, if the node is read from the %_segments - ** table, then there are always 20 bytes of zeroed padding following the - ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details). - */ - zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild); - zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild); - if( zCsr>zEnd ){ - return FTS_CORRUPT_VTAB; - } - - while( zCsrnBuffer ){ - rc = FTS_CORRUPT_VTAB; - goto finish_scan; - } - } - isFirstTerm = 0; - zCsr += fts3GetVarint32(zCsr, &nSuffix); - - assert( nPrefix>=0 && nSuffix>=0 ); - if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){ - rc = FTS_CORRUPT_VTAB; - goto finish_scan; - } - if( (i64)nPrefix+nSuffix>nAlloc ){ - char *zNew; - nAlloc = ((i64)nPrefix+nSuffix) * 2; - zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); - if( !zNew ){ - rc = SQLITE_NOMEM; - goto finish_scan; - } - zBuffer = zNew; - } - assert( zBuffer ); - memcpy(&zBuffer[nPrefix], zCsr, nSuffix); - nBuffer = nPrefix + nSuffix; - zCsr += nSuffix; - - /* Compare the term we are searching for with the term just loaded from - ** the interior node. If the specified term is greater than or equal - ** to the term from the interior node, then all terms on the sub-tree - ** headed by node iChild are smaller than zTerm. No need to search - ** iChild. - ** - ** If the interior node term is larger than the specified term, then - ** the tree headed by iChild may contain the specified term. - */ - cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer)); - if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){ - *piFirst = (i64)iChild; - piFirst = 0; - } - - if( piLast && cmp<0 ){ - *piLast = (i64)iChild; - piLast = 0; - } - - iChild++; - }; - - if( piFirst ) *piFirst = (i64)iChild; - if( piLast ) *piLast = (i64)iChild; - - finish_scan: - sqlite3_free(zBuffer); - return rc; -} - - -/* -** The buffer pointed to by argument zNode (size nNode bytes) contains an -** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes) -** contains a term. This function searches the sub-tree headed by the zNode -** node for the range of leaf nodes that may contain the specified term -** or terms for which the specified term is a prefix. -** -** If piLeaf is not NULL, then *piLeaf is set to the blockid of the -** left-most leaf node in the tree that may contain the specified term. -** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the -** right-most leaf node that may contain a term for which the specified -** term is a prefix. -** -** It is possible that the range of returned leaf nodes does not contain -** the specified term or any terms for which it is a prefix. However, if the -** segment does contain any such terms, they are stored within the identified -** range. Because this function only inspects interior segment nodes (and -** never loads leaf nodes into memory), it is not possible to be sure. -** -** If an error occurs, an error code other than SQLITE_OK is returned. -*/ -static int fts3SelectLeaf( - Fts3Table *p, /* Virtual table handle */ - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piLeaf, /* Selected leaf node */ - sqlite3_int64 *piLeaf2 /* Selected leaf node */ -){ - int rc = SQLITE_OK; /* Return code */ - int iHeight; /* Height of this node in tree */ - - assert( piLeaf || piLeaf2 ); - - fts3GetVarint32(zNode, &iHeight); - rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); - assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); - - if( rc==SQLITE_OK && iHeight>1 ){ - char *zBlob = 0; /* Blob read from %_segments table */ - int nBlob = 0; /* Size of zBlob in bytes */ - - if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ - rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); - if( rc==SQLITE_OK ){ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); - } - sqlite3_free(zBlob); - piLeaf = 0; - zBlob = 0; - } - - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0); - } - if( rc==SQLITE_OK ){ - int iNewHeight = 0; - fts3GetVarint32(zBlob, &iNewHeight); - if( iNewHeight>=iHeight ){ - rc = FTS_CORRUPT_VTAB; - }else{ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2); - } - } - sqlite3_free(zBlob); - } - - return rc; -} - -/* -** This function is used to create delta-encoded serialized lists of FTS3 -** varints. Each call to this function appends a single varint to a list. -*/ -static void fts3PutDeltaVarint( - char **pp, /* IN/OUT: Output pointer */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); - *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); - *piPrev = iVal; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a position-list. After it returns, *ppPoslist points to the -** first byte after the position-list. -** -** A position list is list of positions (delta encoded) and columns for -** a single document record of a doclist. So, in other words, this -** routine advances *ppPoslist so that it points to the next docid in -** the doclist, or to the first byte past the end of the doclist. -** -** If pp is not NULL, then the contents of the position list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. -*/ -static void fts3PoslistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* The end of a position list is marked by a zero encoded as an FTS3 - ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by - ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail - ** of some other, multi-byte, value. - ** - ** The following while-loop moves pEnd to point to the first byte that is not - ** immediately preceded by a byte with the 0x80 bit set. Then increments - ** pEnd once more so that it points to the byte immediately following the - ** last byte in the position-list. - */ - while( *pEnd | c ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && (*pEnd)==0 ); - } - pEnd++; /* Advance past the POS_END terminator byte */ - - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a column-list. After it returns, *ppPoslist points to the -** to the terminator (POS_COLUMN or POS_END) byte of the column-list. -** -** A column-list is list of delta-encoded positions for a single column -** within a single document within a doclist. -** -** The column-list is terminated either by a POS_COLUMN varint (1) or -** a POS_END varint (0). This routine leaves *ppPoslist pointing to -** the POS_COLUMN or POS_END that terminates the column-list. -** -** If pp is not NULL, then the contents of the column-list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. The POS_COLUMN or POS_END terminator -** is not copied into *pp. -*/ -static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* A column-list is terminated by either a 0x01 or 0x00 byte that is - ** not part of a multi-byte varint. - */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && ((*pEnd)&0xfe)==0 ); - } - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** Value used to signify the end of an position-list. This must be -** as large or larger than any value that might appear on the -** position-list, even a position list that has been corrupted. -*/ -#define POSITION_LIST_END LARGEST_INT64 - -/* -** This function is used to help parse position-lists. When this function is -** called, *pp may point to the start of the next varint in the position-list -** being parsed, or it may point to 1 byte past the end of the position-list -** (in which case **pp will be a terminator bytes POS_END (0) or -** (1)). -** -** If *pp points past the end of the current position-list, set *pi to -** POSITION_LIST_END and return. Otherwise, read the next varint from *pp, -** increment the current value of *pi by the value read, and set *pp to -** point to the next value before returning. -** -** Before calling this routine *pi must be initialized to the value of -** the previous position, or zero if we are reading the first position -** in the position-list. Because positions are delta-encoded, the value -** of the previous position is needed in order to compute the value of -** the next position. -*/ -static void fts3ReadNextPos( - char **pp, /* IN/OUT: Pointer into position-list buffer */ - sqlite3_int64 *pi /* IN/OUT: Value read from position-list */ -){ - if( (**pp)&0xFE ){ - int iVal; - *pp += fts3GetVarint32((*pp), &iVal); - *pi += iVal; - *pi -= 2; - }else{ - *pi = POSITION_LIST_END; - } -} - -/* -** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by -** the value of iCol encoded as a varint to *pp. This will start a new -** column list. -** -** Set *pp to point to the byte just after the last byte written before -** returning (do not modify it if iCol==0). Return the total number of bytes -** written (0 if iCol==0). -*/ -static int fts3PutColNumber(char **pp, int iCol){ - int n = 0; /* Number of bytes written */ - if( iCol ){ - char *p = *pp; /* Output pointer */ - n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); - *p = 0x01; - *pp = &p[n]; - } - return n; -} - -/* -** Compute the union of two position lists. The output written -** into *pp contains all positions of both *pp1 and *pp2 in sorted -** order and with any duplicates removed. All pointers are -** updated appropriately. The caller is responsible for insuring -** that there is enough space in *pp to hold the complete output. -*/ -static int fts3PoslistMerge( - char **pp, /* Output buffer */ - char **pp1, /* Left input list */ - char **pp2 /* Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - - while( *p1 || *p2 ){ - int iCol1; /* The current column index in pp1 */ - int iCol2; /* The current column index in pp2 */ - - if( *p1==POS_COLUMN ){ - fts3GetVarint32(&p1[1], &iCol1); - if( iCol1==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p1==POS_END ) iCol1 = 0x7fffffff; - else iCol1 = 0; - - if( *p2==POS_COLUMN ){ - fts3GetVarint32(&p2[1], &iCol2); - if( iCol2==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p2==POS_END ) iCol2 = 0x7fffffff; - else iCol2 = 0; - - if( iCol1==iCol2 ){ - sqlite3_int64 i1 = 0; /* Last position from pp1 */ - sqlite3_int64 i2 = 0; /* Last position from pp2 */ - sqlite3_int64 iPrev = 0; - int n = fts3PutColNumber(&p, iCol1); - p1 += n; - p2 += n; - - /* At this point, both p1 and p2 point to the start of column-lists - ** for the same column (the column with index iCol1 and iCol2). - ** A column-list is a list of non-negative delta-encoded varints, each - ** incremented by 2 before being stored. Each list is terminated by a - ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists - ** and writes the results to buffer p. p is left pointing to the byte - ** after the list written. No terminator (POS_END or POS_COLUMN) is - ** written to the output. - */ - fts3GetDeltaVarint(&p1, &i1); - fts3GetDeltaVarint(&p2, &i2); - if( i1<2 || i2<2 ){ - break; - } - do { - fts3PutDeltaVarint(&p, &iPrev, (i1pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e. -** when the *pp1 token appears before the *pp2 token, but not more than nToken -** slots before it. -** -** e.g. nToken==1 searches for adjacent positions. -*/ -static int fts3PoslistPhraseMerge( - char **pp, /* IN/OUT: Preallocated output buffer */ - int nToken, /* Maximum difference in token positions */ - int isSaveLeft, /* Save the left position */ - int isExact, /* If *pp1 is exactly nTokens before *pp2 */ - char **pp1, /* IN/OUT: Left input list */ - char **pp2 /* IN/OUT: Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - int iCol1 = 0; - int iCol2 = 0; - - /* Never set both isSaveLeft and isExact for the same invocation. */ - assert( isSaveLeft==0 || isExact==0 ); - - assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 ); - if( *p1==POS_COLUMN ){ - p1++; - p1 += fts3GetVarint32(p1, &iCol1); - /* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN - ** entry, so this is actually end-of-doclist. */ - if( iCol1==0 ) return 0; - } - if( *p2==POS_COLUMN ){ - p2++; - p2 += fts3GetVarint32(p2, &iCol2); - /* As above, iCol2==0 indicates corruption. */ - if( iCol2==0 ) return 0; - } - - while( 1 ){ - if( iCol1==iCol2 ){ - char *pSave = p; - sqlite3_int64 iPrev = 0; - sqlite3_int64 iPos1 = 0; - sqlite3_int64 iPos2 = 0; - - if( iCol1 ){ - *p++ = POS_COLUMN; - p += sqlite3Fts3PutVarint(p, iCol1); - } - - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - if( iPos1<0 || iPos2<0 ) break; - - while( 1 ){ - if( iPos2==iPos1+nToken - || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) - ){ - sqlite3_int64 iSave; - iSave = isSaveLeft ? iPos1 : iPos2; - fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; - pSave = 0; - assert( p ); - } - if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ - if( (*p2&0xFE)==0 ) break; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - }else{ - if( (*p1&0xFE)==0 ) break; - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - } - } - - if( pSave ){ - assert( pp && p ); - p = pSave; - } - - fts3ColumnlistCopy(0, &p1); - fts3ColumnlistCopy(0, &p2); - assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 ); - if( 0==*p1 || 0==*p2 ) break; - - p1++; - p1 += fts3GetVarint32(p1, &iCol1); - p2++; - p2 += fts3GetVarint32(p2, &iCol2); - } - - /* Advance pointer p1 or p2 (whichever corresponds to the smaller of - ** iCol1 and iCol2) so that it points to either the 0x00 that marks the - ** end of the position list, or the 0x01 that precedes the next - ** column-number in the position list. - */ - else if( iCol1=pEnd ){ - *pp = 0; - }else{ - u64 iVal; - *pp += sqlite3Fts3GetVarintU(*pp, &iVal); - if( bDescIdx ){ - *pVal = (i64)((u64)*pVal - iVal); - }else{ - *pVal = (i64)((u64)*pVal + iVal); - } - } -} - -/* -** This function is used to write a single varint to a buffer. The varint -** is written to *pp. Before returning, *pp is set to point 1 byte past the -** end of the value written. -** -** If *pbFirst is zero when this function is called, the value written to -** the buffer is that of parameter iVal. -** -** If *pbFirst is non-zero when this function is called, then the value -** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal) -** (if bDescIdx is non-zero). -** -** Before returning, this function always sets *pbFirst to 1 and *piPrev -** to the value of parameter iVal. -*/ -static void fts3PutDeltaVarint3( - char **pp, /* IN/OUT: Output pointer */ - int bDescIdx, /* True for descending docids */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - int *pbFirst, /* IN/OUT: True after first int written */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - sqlite3_uint64 iWrite; - if( bDescIdx==0 || *pbFirst==0 ){ - assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev ); - iWrite = (u64)iVal - (u64)*piPrev; - }else{ - assert_fts3_nc( *piPrev>=iVal ); - iWrite = (u64)*piPrev - (u64)iVal; - } - assert( *pbFirst || *piPrev==0 ); - assert_fts3_nc( *pbFirst==0 || iWrite>0 ); - *pp += sqlite3Fts3PutVarint(*pp, iWrite); - *piPrev = iVal; - *pbFirst = 1; -} - - -/* -** This macro is used by various functions that merge doclists. The two -** arguments are 64-bit docid values. If the value of the stack variable -** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). -** Otherwise, (i2-i1). -** -** Using this makes it easier to write code that can merge doclists that are -** sorted in either ascending or descending order. -*/ -/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1))) - -/* -** This function does an "OR" merge of two doclists (output contains all -** positions contained in either argument doclist). If the docids in the -** input doclists are sorted in ascending order, parameter bDescDoclist -** should be false. If they are sorted in ascending order, it should be -** passed a non-zero value. -** -** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer -** containing the output doclist and SQLITE_OK is returned. In this case -** *pnOut is set to the number of bytes in the output doclist. -** -** If an error occurs, an SQLite error code is returned. The output values -** are undefined in this case. -*/ -static int fts3DoclistOrMerge( - int bDescDoclist, /* True if arguments are desc */ - char *a1, int n1, /* First doclist */ - char *a2, int n2, /* Second doclist */ - char **paOut, int *pnOut /* OUT: Malloc'd doclist */ -){ - int rc = SQLITE_OK; - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *pEnd1 = &a1[n1]; - char *pEnd2 = &a2[n2]; - char *p1 = a1; - char *p2 = a2; - char *p; - char *aOut; - int bFirstOut = 0; - - *paOut = 0; - *pnOut = 0; - - /* Allocate space for the output. Both the input and output doclists - ** are delta encoded. If they are in ascending order (bDescDoclist==0), - ** then the first docid in each list is simply encoded as a varint. For - ** each subsequent docid, the varint stored is the difference between the - ** current and previous docid (a positive number - since the list is in - ** ascending order). - ** - ** The first docid written to the output is therefore encoded using the - ** same number of bytes as it is in whichever of the input lists it is - ** read from. And each subsequent docid read from the same input list - ** consumes either the same or less bytes as it did in the input (since - ** the difference between it and the previous value in the output must - ** be a positive value less than or equal to the delta value read from - ** the input list). The same argument applies to all but the first docid - ** read from the 'other' list. And to the contents of all position lists - ** that will be copied and merged from the input to the output. - ** - ** However, if the first docid copied to the output is a negative number, - ** then the encoding of the first docid from the 'other' input list may - ** be larger in the output than it was in the input (since the delta value - ** may be a larger positive integer than the actual docid). - ** - ** The space required to store the output is therefore the sum of the - ** sizes of the two inputs, plus enough space for exactly one of the input - ** docids to grow. - ** - ** A symmetric argument may be made if the doclists are in descending - ** order. - */ - aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING); - if( !aOut ) return SQLITE_NOMEM; - - p = aOut; - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - while( p1 || p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - - if( p2 && p1 && iDiff==0 ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - rc = fts3PoslistMerge(&p, &p1, &p2); - if( rc ) break; - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( !p2 || (p1 && iDiff<0) ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - fts3PoslistCopy(&p, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2); - fts3PoslistCopy(&p, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - - assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) ); - } - - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - p = aOut = 0; - }else{ - assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 ); - memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING); - } - *paOut = aOut; - *pnOut = (int)(p-aOut); - return rc; -} - -/* -** This function does a "phrase" merge of two doclists. In a phrase merge, -** the output contains a copy of each position from the right-hand input -** doclist for which there is a position in the left-hand input doclist -** exactly nDist tokens before it. -** -** If the docids in the input doclists are sorted in ascending order, -** parameter bDescDoclist should be false. If they are sorted in ascending -** order, it should be passed a non-zero value. -** -** The right-hand input doclist is overwritten by this function. -*/ -static int fts3DoclistPhraseMerge( - int bDescDoclist, /* True if arguments are desc */ - int nDist, /* Distance from left to right (1=adjacent) */ - char *aLeft, int nLeft, /* Left doclist */ - char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ -){ - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *aRight = *paRight; - char *pEnd1 = &aLeft[nLeft]; - char *pEnd2 = &aRight[*pnRight]; - char *p1 = aLeft; - char *p2 = aRight; - char *p; - int bFirstOut = 0; - char *aOut; - - assert( nDist>0 ); - if( bDescDoclist ){ - aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX); - if( aOut==0 ) return SQLITE_NOMEM; - }else{ - aOut = aRight; - } - p = aOut; - - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - - while( p1 && p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - if( iDiff==0 ){ - char *pSave = p; - sqlite3_int64 iPrevSave = iPrev; - int bFirstOutSave = bFirstOut; - - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ - p = pSave; - iPrev = iPrevSave; - bFirstOut = bFirstOutSave; - } - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( iDiff<0 ){ - fts3PoslistCopy(0, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PoslistCopy(0, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - } - - *pnRight = (int)(p - aOut); - if( bDescDoclist ){ - sqlite3_free(aRight); - *paRight = aOut; - } - - return SQLITE_OK; -} - -/* -** Argument pList points to a position list nList bytes in size. This -** function checks to see if the position list contains any entries for -** a token in position 0 (of any column). If so, it writes argument iDelta -** to the output buffer pOut, followed by a position list consisting only -** of the entries from pList at position 0, and terminated by an 0x00 byte. -** The value returned is the number of bytes written to pOut (if any). -*/ -SQLITE_PRIVATE int sqlite3Fts3FirstFilter( - sqlite3_int64 iDelta, /* Varint that may be written to pOut */ - char *pList, /* Position list (no 0x00 term) */ - int nList, /* Size of pList in bytes */ - char *pOut /* Write output here */ -){ - int nOut = 0; - int bWritten = 0; /* True once iDelta has been written */ - char *p = pList; - char *pEnd = &pList[nList]; - - if( *p!=0x01 ){ - if( *p==0x02 ){ - nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta); - pOut[nOut++] = 0x02; - bWritten = 1; - } - fts3ColumnlistCopy(0, &p); - } - - while( paaOutput); i++){ - if( pTS->aaOutput[i] ){ - if( !aOut ){ - aOut = pTS->aaOutput[i]; - nOut = pTS->anOutput[i]; - pTS->aaOutput[i] = 0; - }else{ - int nNew; - char *aNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, - pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - return rc; - } - - sqlite3_free(pTS->aaOutput[i]); - sqlite3_free(aOut); - pTS->aaOutput[i] = 0; - aOut = aNew; - nOut = nNew; - } - } - } - - pTS->aaOutput[0] = aOut; - pTS->anOutput[0] = nOut; - return SQLITE_OK; -} - -/* -** Merge the doclist aDoclist/nDoclist into the TermSelect object passed -** as the first argument. The merge is an "OR" merge (see function -** fts3DoclistOrMerge() for details). -** -** This function is called with the doclist for each term that matches -** a queried prefix. It merges all these doclists into one, the doclist -** for the specified prefix. Since there can be a very large number of -** doclists to merge, the merging is done pair-wise using the TermSelect -** object. -** -** This function returns SQLITE_OK if the merge is successful, or an -** SQLite error code (SQLITE_NOMEM) if an error occurs. -*/ -static int fts3TermSelectMerge( - Fts3Table *p, /* FTS table handle */ - TermSelect *pTS, /* TermSelect object to merge into */ - char *aDoclist, /* Pointer to doclist */ - int nDoclist /* Size of aDoclist in bytes */ -){ - if( pTS->aaOutput[0]==0 ){ - /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). - ** - ** Add FTS3_VARINT_MAX bytes of unused space to the end of the - ** allocation. This is so as to ensure that the buffer is big enough - ** to hold the current doclist AND'd with any other doclist. If the - ** doclists are stored in order=ASC order, this padding would not be - ** required (since the size of [doclistA AND doclistB] is always less - ** than or equal to the size of [doclistA] in that case). But this is - ** not true for order=DESC. For example, a doclist containing (1, -1) - ** may be smaller than (-1), as in the first example the -1 may be stored - ** as a single-byte delta, whereas in the second it must be stored as a - ** FTS3_VARINT_MAX byte varint. - ** - ** Similar padding is added in the fts3DoclistOrMerge() function. - */ - pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1); - pTS->anOutput[0] = nDoclist; - if( pTS->aaOutput[0] ){ - memcpy(pTS->aaOutput[0], aDoclist, nDoclist); - memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX); - }else{ - return SQLITE_NOMEM; - } - }else{ - char *aMerge = aDoclist; - int nMerge = nDoclist; - int iOut; - - for(iOut=0; iOutaaOutput); iOut++){ - if( pTS->aaOutput[iOut]==0 ){ - assert( iOut>0 ); - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - break; - }else{ - char *aNew; - int nNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, - pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - return rc; - } - - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - sqlite3_free(pTS->aaOutput[iOut]); - pTS->aaOutput[iOut] = 0; - - aMerge = aNew; - nMerge = nNew; - if( (iOut+1)==SizeofArray(pTS->aaOutput) ){ - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - } - } - } - } - return SQLITE_OK; -} - -/* -** Append SegReader object pNew to the end of the pCsr->apSegment[] array. -*/ -static int fts3SegReaderCursorAppend( - Fts3MultiSegReader *pCsr, - Fts3SegReader *pNew -){ - if( (pCsr->nSegment%16)==0 ){ - Fts3SegReader **apNew; - sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); - apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte); - if( !apNew ){ - sqlite3Fts3SegReaderFree(pNew); - return SQLITE_NOMEM; - } - pCsr->apSegment = apNew; - } - pCsr->apSegment[pCsr->nSegment++] = pNew; - return SQLITE_OK; -} - -/* -** Add seg-reader objects to the Fts3MultiSegReader object passed as the -** 8th argument. -** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -static int fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc = SQLITE_OK; /* Error code */ - sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */ - int rc2; /* Result of sqlite3_reset() */ - - /* If iLevel is less than 0 and this is not a scan, include a seg-reader - ** for the pending-terms. If this is a scan, then this call must be being - ** made by an fts4aux module, not an FTS table. In this case calling - ** Fts3SegReaderPending might segfault, as the data structures used by - ** fts4aux are not completely populated. So it's easiest to filter these - ** calls out here. */ - if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){ - Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); - if( rc==SQLITE_OK && pSeg ){ - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - if( iLevel!=FTS3_SEGCURSOR_PENDING ){ - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); - } - - while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ - Fts3SegReader *pSeg = 0; - - /* Read the values returned by the SELECT into local variables. */ - sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1); - sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2); - sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3); - int nRoot = sqlite3_column_bytes(pStmt, 4); - char const *zRoot = sqlite3_column_blob(pStmt, 4); - - /* If zTerm is not NULL, and this segment is not stored entirely on its - ** root node, the range of leaves scanned can be reduced. Do this. */ - if( iStartBlock && zTerm && zRoot ){ - sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0); - rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi); - if( rc!=SQLITE_OK ) goto finished; - if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock; - } - - rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, - (isPrefix==0 && isScan==0), - iStartBlock, iLeavesEndBlock, - iEndBlock, zRoot, nRoot, &pSeg - ); - if( rc!=SQLITE_OK ) goto finished; - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - finished: - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_DONE ) rc = rc2; - - return rc; -} - -/* -** Set up a cursor object for iterating through a full-text index or a -** single level therein. -*/ -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language-id to search */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - assert( iIndex>=0 && iIndexnIndex ); - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevelbase.pVtab; - - if( isPrefix ){ - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr - ); - pSegcsr->bLookup = 1; - } - } - - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm+1 ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr - ); - if( rc==SQLITE_OK ){ - rc = fts3SegReaderCursorAddZero( - p, pCsr->iLangid, zTerm, nTerm, pSegcsr - ); - } - } - } - } - - if( bFound==0 ){ - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr - ); - pSegcsr->bLookup = !isPrefix; - } - } - - *ppSegcsr = pSegcsr; - return rc; -} - -/* -** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor(). -*/ -static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){ - sqlite3Fts3SegReaderFinish(pSegcsr); - sqlite3_free(pSegcsr); -} - -/* -** This function retrieves the doclist for the specified term (or term -** prefix) from the database. -*/ -static int fts3TermSelect( - Fts3Table *p, /* Virtual table handle */ - Fts3PhraseToken *pTok, /* Token to query for */ - int iColumn, /* Column to query (or -ve for all columns) */ - int *pnOut, /* OUT: Size of buffer at *ppOut */ - char **ppOut /* OUT: Malloced result buffer */ -){ - int rc; /* Return code */ - Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */ - TermSelect tsc; /* Object for pair-wise doclist merging */ - Fts3SegFilter filter; /* Segment term filter configuration */ - - pSegcsr = pTok->pSegcsr; - memset(&tsc, 0, sizeof(TermSelect)); - - filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS - | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0) - | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0) - | (iColumnnColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0); - filter.iCol = iColumn; - filter.zTerm = pTok->z; - filter.nTerm = pTok->n; - - rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter); - while( SQLITE_OK==rc - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) - ){ - rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist); - } - - if( rc==SQLITE_OK ){ - rc = fts3TermSelectFinishMerge(p, &tsc); - } - if( rc==SQLITE_OK ){ - *ppOut = tsc.aaOutput[0]; - *pnOut = tsc.anOutput[0]; - }else{ - int i; - for(i=0; ipSegcsr = 0; - return rc; -} - -/* -** This function counts the total number of docids in the doclist stored -** in buffer aList[], size nList bytes. -** -** If the isPoslist argument is true, then it is assumed that the doclist -** contains a position-list following each docid. Otherwise, it is assumed -** that the doclist is simply a list of docids stored as delta encoded -** varints. -*/ -static int fts3DoclistCountDocids(char *aList, int nList){ - int nDoc = 0; /* Return value */ - if( aList ){ - char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */ - char *p = aList; /* Cursor */ - while( peSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){ - Fts3Table *pTab = (Fts3Table*)pCursor->pVtab; - pTab->bLock++; - if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){ - pCsr->isEof = 1; - rc = sqlite3_reset(pCsr->pStmt); - }else{ - pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0); - rc = SQLITE_OK; - } - pTab->bLock--; - }else{ - rc = fts3EvalNext((Fts3Cursor *)pCursor); - } - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** If the numeric type of argument pVal is "integer", then return it -** converted to a 64-bit signed integer. Otherwise, return a copy of -** the second parameter, iDefault. -*/ -static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){ - if( pVal ){ - int eType = sqlite3_value_numeric_type(pVal); - if( eType==SQLITE_INTEGER ){ - return sqlite3_value_int64(pVal); - } - } - return iDefault; -} - -/* -** This is the xFilter interface for the virtual table. See -** the virtual table xFilter method documentation for additional -** information. -** -** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against -** the %_content table. -** -** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry -** in the %_content table. -** -** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The -** column on the left-hand side of the MATCH operator is column -** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand -** side of the MATCH operator. -*/ -static int fts3FilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc = SQLITE_OK; - char *zSql; /* SQL statement used to access %_content */ - int eSearch; - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - - sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ - sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ - sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ - sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ - int iIdx; - - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - if( p->bLock ){ - return SQLITE_ERROR; - } - - eSearch = (idxNum & 0x0000FFFF); - assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); - assert( p->pSegments==0 ); - - /* Collect arguments into local variables */ - iIdx = 0; - if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; - assert( iIdx==nVal ); - - /* In case the cursor has been used before, clear it now. */ - fts3ClearCursor(pCsr); - - /* Set the lower and upper bounds on docids to return */ - pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); - pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); - - if( idxStr ){ - pCsr->bDesc = (idxStr[0]=='D'); - }else{ - pCsr->bDesc = p->bDescIdx; - } - pCsr->eSearch = (i16)eSearch; - - if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){ - int iCol = eSearch-FTS3_FULLTEXT_SEARCH; - const char *zQuery = (const char *)sqlite3_value_text(pCons); - - if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - - pCsr->iLangid = 0; - if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid); - - assert( p->base.zErrMsg==0 ); - rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, - p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, - &p->base.zErrMsg - ); - if( rc!=SQLITE_OK ){ - return rc; - } - - rc = fts3EvalStart(pCsr); - sqlite3Fts3SegmentsClose(p); - if( rc!=SQLITE_OK ) return rc; - pCsr->pNextId = pCsr->aDoclist; - pCsr->iPrevId = 0; - } - - /* Compile a SELECT statement for this cursor. For a full-table-scan, the - ** statement loops through all rows of the %_content table. For a - ** full-text query or docid lookup, the statement retrieves a single - ** row by docid. - */ - if( eSearch==FTS3_FULLSCAN_SEARCH ){ - if( pDocidGe || pDocidLe ){ - zSql = sqlite3_mprintf( - "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", - p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, - (pCsr->bDesc ? "DESC" : "ASC") - ); - }else{ - zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); - } - if( zSql ){ - p->bLock++; - rc = sqlite3_prepare_v3( - p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 - ); - p->bLock--; - sqlite3_free(zSql); - }else{ - rc = SQLITE_NOMEM; - } - }else if( eSearch==FTS3_DOCID_SEARCH ){ - rc = fts3CursorSeekStmt(pCsr); - if( rc==SQLITE_OK ){ - rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); - } - } - if( rc!=SQLITE_OK ) return rc; - - return fts3NextMethod(pCursor); -} - -/* -** This is the xEof method of the virtual table. SQLite calls this -** routine to find out if it has reached the end of a result set. -*/ -static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Cursor *pCsr = (Fts3Cursor*)pCursor; - if( pCsr->isEof ){ - fts3ClearCursor(pCsr); - pCsr->isEof = 1; - } - return pCsr->isEof; -} - -/* -** This is the xRowid method. The SQLite core calls this routine to -** retrieve the rowid for the current row of the result set. fts3 -** exposes %_content.docid as the rowid for the virtual table. The -** rowid should be written to *pRowid. -*/ -static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - *pRowid = pCsr->iPrevId; - return SQLITE_OK; -} - -/* -** This is the xColumn method, called by SQLite to request a value from -** the row that the supplied cursor currently points to. -** -** If: -** -** (iCol < p->nColumn) -> The value of the iCol'th user column. -** (iCol == p->nColumn) -> Magic column with the same name as the table. -** (iCol == p->nColumn+1) -> Docid column -** (iCol == p->nColumn+2) -> Langid column -*/ -static int fts3ColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - - /* The column value supplied by SQLite must be in range. */ - assert( iCol>=0 && iCol<=p->nColumn+2 ); - - switch( iCol-p->nColumn ){ - case 0: - /* The special 'table-name' column */ - sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0); - break; - - case 1: - /* The docid column */ - sqlite3_result_int64(pCtx, pCsr->iPrevId); - break; - - case 2: - if( pCsr->pExpr ){ - sqlite3_result_int64(pCtx, pCsr->iLangid); - break; - }else if( p->zLanguageid==0 ){ - sqlite3_result_int(pCtx, 0); - break; - }else{ - iCol = p->nColumn; - /* no break */ deliberate_fall_through - } - - default: - /* A user column. Or, if this is a full-table scan, possibly the - ** language-id column. Seek the cursor. */ - rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){ - sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); - } - break; - } - - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** This function is the implementation of the xUpdate callback used by -** FTS3 virtual tables. It is invoked by SQLite each time a row is to be -** inserted, updated or deleted. -*/ -static int fts3UpdateMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid); -} - -/* -** Implementation of xSync() method. Flush the contents of the pending-terms -** hash-table to the database. -*/ -static int fts3SyncMethod(sqlite3_vtab *pVtab){ - - /* Following an incremental-merge operation, assuming that the input - ** segments are not completely consumed (the usual case), they are updated - ** in place to remove the entries that have already been merged. This - ** involves updating the leaf block that contains the smallest unmerged - ** entry and each block (if any) between the leaf and the root node. So - ** if the height of the input segment b-trees is N, and input segments - ** are merged eight at a time, updating the input segments at the end - ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually - ** small - often between 0 and 2. So the overhead of the incremental - ** merge is somewhere between 8 and 24 blocks. To avoid this overhead - ** dwarfing the actual productive work accomplished, the incremental merge - ** is only attempted if it will write at least 64 leaf blocks. Hence - ** nMinMerge. - ** - ** Of course, updating the input segments also involves deleting a bunch - ** of blocks from the segments table. But this is not considered overhead - ** as it would also be required by a crisis-merge that used the same input - ** segments. - */ - const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ - - Fts3Table *p = (Fts3Table*)pVtab; - int rc; - i64 iLastRowid = sqlite3_last_insert_rowid(p->db); - - rc = sqlite3Fts3PendingTermsFlush(p); - if( rc==SQLITE_OK - && p->nLeafAdd>(nMinMerge/16) - && p->nAutoincrmerge && p->nAutoincrmerge!=0xff - ){ - int mxLevel = 0; /* Maximum relative level value in db */ - int A; /* Incr-merge parameter A */ - - rc = sqlite3Fts3MaxLevel(p, &mxLevel); - assert( rc==SQLITE_OK || mxLevel==0 ); - A = p->nLeafAdd * mxLevel; - A += (A/2); - if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); - } - sqlite3Fts3SegmentsClose(p); - sqlite3_set_last_insert_rowid(p->db, iLastRowid); - return rc; -} - -/* -** If it is currently unknown whether or not the FTS table has an %_stat -** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat -** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code -** if an error occurs. -*/ -static int fts3SetHasStat(Fts3Table *p){ - int rc = SQLITE_OK; - if( p->bHasStat==2 ){ - char *zTbl = sqlite3_mprintf("%s_stat", p->zName); - if( zTbl ){ - int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0); - sqlite3_free(zTbl); - p->bHasStat = (res==SQLITE_OK); - }else{ - rc = SQLITE_NOMEM; - } - } - return rc; -} - -/* -** Implementation of xBegin() method. -*/ -static int fts3BeginMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - int rc; - UNUSED_PARAMETER(pVtab); - assert( p->pSegments==0 ); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=1 ); - p->nLeafAdd = 0; - rc = fts3SetHasStat(p); -#ifdef SQLITE_DEBUG - if( rc==SQLITE_OK ){ - p->inTransaction = 1; - p->mxSavepoint = -1; - } -#endif - return rc; -} - -/* -** Implementation of xCommit() method. This is a no-op. The contents of -** the pending-terms hash-table have already been flushed into the database -** by fts3SyncMethod(). -*/ -static int fts3CommitMethod(sqlite3_vtab *pVtab){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(pVtab); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=0 ); - assert( p->pSegments==0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** Implementation of xRollback(). Discard the contents of the pending-terms -** hash-table. Any changes made to the database are reverted by SQLite. -*/ -static int fts3RollbackMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - sqlite3Fts3PendingTermsClear(p); - assert( p->inTransaction!=0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** When called, *ppPoslist must point to the byte immediately following the -** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function -** moves *ppPoslist so that it instead points to the first byte of the -** same position list. -*/ -static void fts3ReversePoslist(char *pStart, char **ppPoslist){ - char *p = &(*ppPoslist)[-2]; - char c = 0; - - /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ - while( p>pStart && (c=*p--)==0 ); - - /* Search backwards for a varint with value zero (the end of the previous - ** poslist). This is an 0x00 byte preceded by some byte that does not - ** have the 0x80 bit set. */ - while( p>pStart && (*p & 0x80) | c ){ - c = *p--; - } - assert( p==pStart || c==0 ); - - /* At this point p points to that preceding byte without the 0x80 bit - ** set. So to find the start of the poslist, skip forward 2 bytes then - ** over a varint. - ** - ** Normally. The other case is that p==pStart and the poslist to return - ** is the first in the doclist. In this case do not skip forward 2 bytes. - ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) - ** is required for cases where the first byte of a doclist and the - ** doclist is empty. For example, if the first docid is 10, a doclist - ** that begins with: - ** - ** 0x0A 0x00 - */ - if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } - while( *p++&0x80 ); - *ppPoslist = p; -} - -/* -** Helper function used by the implementation of the overloaded snippet(), -** offsets() and optimize() SQL functions. -** -** If the value passed as the third argument is a blob of size -** sizeof(Fts3Cursor*), then the blob contents are copied to the -** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error -** message is written to context pContext and SQLITE_ERROR returned. The -** string passed via zFunc is used as part of the error message. -*/ -static int fts3FunctionArg( - sqlite3_context *pContext, /* SQL function call context */ - const char *zFunc, /* Function name */ - sqlite3_value *pVal, /* argv[0] passed to function */ - Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ -){ - int rc; - *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor"); - if( (*ppCsr)!=0 ){ - rc = SQLITE_OK; - }else{ - char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); - sqlite3_result_error(pContext, zErr, -1); - sqlite3_free(zErr); - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** Implementation of the snippet() function for FTS3 -*/ -static void fts3SnippetFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of apVal[] array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - const char *zStart = ""; - const char *zEnd = ""; - const char *zEllipsis = "..."; - int iCol = -1; - int nToken = 15; /* Default number of tokens in snippet */ - - /* There must be at least one argument passed to this function (otherwise - ** the non-overloaded version would have been called instead of this one). - */ - assert( nVal>=1 ); - - if( nVal>6 ){ - sqlite3_result_error(pContext, - "wrong number of arguments to function snippet()", -1); - return; - } - if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; - - switch( nVal ){ - case 6: nToken = sqlite3_value_int(apVal[5]); - /* no break */ deliberate_fall_through - case 5: iCol = sqlite3_value_int(apVal[4]); - /* no break */ deliberate_fall_through - case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); - /* no break */ deliberate_fall_through - case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); - /* no break */ deliberate_fall_through - case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); - } - if( !zEllipsis || !zEnd || !zStart ){ - sqlite3_result_error_nomem(pContext); - }else if( nToken==0 ){ - sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); - }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); - } -} - -/* -** Implementation of the offsets() function for FTS3 -*/ -static void fts3OffsetsFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; - assert( pCsr ); - if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Offsets(pContext, pCsr); - } -} - -/* -** Implementation of the special optimize() function for FTS3. This -** function merges all segments in the database to a single segment. -** Example usage is: -** -** SELECT optimize(t) FROM t LIMIT 1; -** -** where 't' is the name of an FTS3 table. -*/ -static void fts3OptimizeFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - int rc; /* Return code */ - Fts3Table *p; /* Virtual table handle */ - Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; - p = (Fts3Table *)pCursor->base.pVtab; - assert( p ); - - rc = sqlite3Fts3Optimize(p); - - switch( rc ){ - case SQLITE_OK: - sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC); - break; - case SQLITE_DONE: - sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC); - break; - default: - sqlite3_result_error_code(pContext, rc); - break; - } -} - -/* -** Implementation of the matchinfo() function for FTS3 -*/ -static void fts3MatchinfoFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - assert( nVal==1 || nVal==2 ); - if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ - const char *zArg = 0; - if( nVal>1 ){ - zArg = (const char *)sqlite3_value_text(apVal[1]); - } - sqlite3Fts3Matchinfo(pContext, pCsr, zArg); - } -} - -/* -** This routine implements the xFindFunction method for the FTS3 -** virtual table. -*/ -static int fts3FindFunctionMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Number of SQL function arguments */ - const char *zName, /* Name of SQL function */ - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ - void **ppArg /* Unused */ -){ - struct Overloaded { - const char *zName; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aOverload[] = { - { "snippet", fts3SnippetFunc }, - { "offsets", fts3OffsetsFunc }, - { "optimize", fts3OptimizeFunc }, - { "matchinfo", fts3MatchinfoFunc }, - }; - int i; /* Iterator variable */ - - UNUSED_PARAMETER(pVtab); - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(ppArg); - - for(i=0; idb; /* Database connection */ - int rc; /* Return Code */ - - /* At this point it must be known if the %_stat table exists or not. - ** So bHasStat may not be 2. */ - rc = fts3SetHasStat(p); - - /* As it happens, the pending terms table is always empty here. This is - ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction - ** always opens a savepoint transaction. And the xSavepoint() method - ** flushes the pending terms table. But leave the (no-op) call to - ** PendingTermsFlush() in in case that changes. - */ - assert( p->nPendingData==0 ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3PendingTermsFlush(p); - } - - p->bIgnoreSavepoint = 1; - - if( p->zContentTbl==0 ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", - p->zDb, p->zName, zName - ); - } - - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", - p->zDb, p->zName, zName - ); - } - if( p->bHasStat ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", - p->zDb, p->zName, zName - ); - } - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", - p->zDb, p->zName, zName - ); - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", - p->zDb, p->zName, zName - ); - - p->bIgnoreSavepoint = 0; - return rc; -} - -/* -** The xSavepoint() method. -** -** Flush the contents of the pending-terms table to disk. -*/ -static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - int rc = SQLITE_OK; - Fts3Table *pTab = (Fts3Table*)pVtab; - assert( pTab->inTransaction ); - assert( pTab->mxSavepoint<=iSavepoint ); - TESTONLY( pTab->mxSavepoint = iSavepoint ); - - if( pTab->bIgnoreSavepoint==0 ){ - if( fts3HashCount(&pTab->aIndex[0].hPending)>0 ){ - char *zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')", - pTab->zDb, pTab->zName, pTab->zName - ); - if( zSql ){ - pTab->bIgnoreSavepoint = 1; - rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0); - pTab->bIgnoreSavepoint = 0; - sqlite3_free(zSql); - }else{ - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK ){ - pTab->iSavepoint = iSavepoint+1; - } - } - return rc; -} - -/* -** The xRelease() method. -** -** This is a no-op. -*/ -static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *pTab = (Fts3Table*)pVtab; - assert( pTab->inTransaction ); - assert( pTab->mxSavepoint >= iSavepoint ); - TESTONLY( pTab->mxSavepoint = iSavepoint-1 ); - pTab->iSavepoint = iSavepoint; - return SQLITE_OK; -} - -/* -** The xRollbackTo() method. -** -** Discard the contents of the pending terms table. -*/ -static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *pTab = (Fts3Table*)pVtab; - UNUSED_PARAMETER(iSavepoint); - assert( pTab->inTransaction ); - TESTONLY( pTab->mxSavepoint = iSavepoint ); - if( (iSavepoint+1)<=pTab->iSavepoint ){ - sqlite3Fts3PendingTermsClear(pTab); - } - return SQLITE_OK; -} - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int fts3ShadowName(const char *zName){ - static const char *azName[] = { - "content", "docsize", "segdir", "segments", "stat", - }; - unsigned int i; - for(i=0; ibFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc)); - if( *pzErr ) rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bOk==0 ){ - *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", - p->bFts4 ? 4 : 3, zSchema, zTabname); - if( *pzErr==0 ) rc = SQLITE_NOMEM; - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - - - -static const sqlite3_module fts3Module = { - /* iVersion */ 4, - /* xCreate */ fts3CreateMethod, - /* xConnect */ fts3ConnectMethod, - /* xBestIndex */ fts3BestIndexMethod, - /* xDisconnect */ fts3DisconnectMethod, - /* xDestroy */ fts3DestroyMethod, - /* xOpen */ fts3OpenMethod, - /* xClose */ fts3CloseMethod, - /* xFilter */ fts3FilterMethod, - /* xNext */ fts3NextMethod, - /* xEof */ fts3EofMethod, - /* xColumn */ fts3ColumnMethod, - /* xRowid */ fts3RowidMethod, - /* xUpdate */ fts3UpdateMethod, - /* xBegin */ fts3BeginMethod, - /* xSync */ fts3SyncMethod, - /* xCommit */ fts3CommitMethod, - /* xRollback */ fts3RollbackMethod, - /* xFindFunction */ fts3FindFunctionMethod, - /* xRename */ fts3RenameMethod, - /* xSavepoint */ fts3SavepointMethod, - /* xRelease */ fts3ReleaseMethod, - /* xRollbackTo */ fts3RollbackToMethod, - /* xShadowName */ fts3ShadowName, - /* xIntegrity */ fts3IntegrityMethod, -}; - -/* -** This function is registered as the module destructor (called when an -** FTS3 enabled database connection is closed). It frees the memory -** allocated for the tokenizer hash table. -*/ -static void hashDestroy(void *p){ - Fts3HashWrapper *pHash = (Fts3HashWrapper *)p; - pHash->nRef--; - if( pHash->nRef<=0 ){ - sqlite3Fts3HashClear(&pHash->hash); - sqlite3_free(pHash); - } -} - -/* -** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are -** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c -** respectively. The following three forward declarations are for functions -** declared in these files used to retrieve the respective implementations. -** -** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed -** to by the argument to point to the "simple" tokenizer implementation. -** And so on. -*/ -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); -SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); -#ifndef SQLITE_DISABLE_FTS3_UNICODE -SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); -#endif -#ifdef SQLITE_ENABLE_ICU -SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); -#endif - -/* -** Initialize the fts3 extension. If this extension is built as part -** of the sqlite library, then this function is called directly by -** SQLite. If fts3 is built as a dynamically loadable extension, this -** function is called by the sqlite3_extension_init() entry point. -*/ -SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ - int rc = SQLITE_OK; - Fts3HashWrapper *pHash = 0; - const sqlite3_tokenizer_module *pSimple = 0; - const sqlite3_tokenizer_module *pPorter = 0; -#ifndef SQLITE_DISABLE_FTS3_UNICODE - const sqlite3_tokenizer_module *pUnicode = 0; -#endif - -#ifdef SQLITE_ENABLE_ICU - const sqlite3_tokenizer_module *pIcu = 0; - sqlite3Fts3IcuTokenizerModule(&pIcu); -#endif - -#ifndef SQLITE_DISABLE_FTS3_UNICODE - sqlite3Fts3UnicodeTokenizer(&pUnicode); -#endif - -#ifdef SQLITE_TEST - rc = sqlite3Fts3InitTerm(db); - if( rc!=SQLITE_OK ) return rc; -#endif - - rc = sqlite3Fts3InitAux(db); - if( rc!=SQLITE_OK ) return rc; - - sqlite3Fts3SimpleTokenizerModule(&pSimple); - sqlite3Fts3PorterTokenizerModule(&pPorter); - - /* Allocate and initialize the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(Fts3HashWrapper)); - if( !pHash ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1); - pHash->nRef = 0; - } - - /* Load the built-in tokenizers into the hash table */ - if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter) - -#ifndef SQLITE_DISABLE_FTS3_UNICODE - || sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode) -#endif -#ifdef SQLITE_ENABLE_ICU - || (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu)) -#endif - ){ - rc = SQLITE_NOMEM; - } - } - -#ifdef SQLITE_TEST - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash); - } -#endif - - /* Create the virtual table wrapper around the hash-table and overload - ** the four scalar functions. If this is successful, register the - ** module with sqlite. - */ - if( SQLITE_OK==rc - && SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer")) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) - ){ - pHash->nRef++; - rc = sqlite3_create_module_v2( - db, "fts3", &fts3Module, (void *)pHash, hashDestroy - ); - if( rc==SQLITE_OK ){ - pHash->nRef++; - rc = sqlite3_create_module_v2( - db, "fts4", &fts3Module, (void *)pHash, hashDestroy - ); - } - if( rc==SQLITE_OK ){ - pHash->nRef++; - rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy); - } - return rc; - } - - - /* An error has occurred. Delete the hash table and return the error code. */ - assert( rc!=SQLITE_OK ); - if( pHash ){ - sqlite3Fts3HashClear(&pHash->hash); - sqlite3_free(pHash); - } - return rc; -} - -/* -** Allocate an Fts3MultiSegReader for each token in the expression headed -** by pExpr. -** -** An Fts3SegReader object is a cursor that can seek or scan a range of -** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple -** Fts3SegReader objects internally to provide an interface to seek or scan -** within the union of all segments of a b-tree. Hence the name. -** -** If the allocated Fts3MultiSegReader just seeks to a single entry in a -** segment b-tree (if the term is not a prefix or it is a prefix for which -** there exists prefix b-tree of the right length) then it may be traversed -** and merged incrementally. Otherwise, it has to be merged into an in-memory -** doclist and then traversed. -*/ -static void fts3EvalAllocateReaders( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Allocate readers for this expression */ - int *pnToken, /* OUT: Total number of tokens in phrase. */ - int *pnOr, /* OUT: Total number of OR nodes in expr. */ - int *pRc /* IN/OUT: Error code */ -){ - if( pExpr && SQLITE_OK==*pRc ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - int i; - int nToken = pExpr->pPhrase->nToken; - *pnToken += nToken; - for(i=0; ipPhrase->aToken[i]; - int rc = fts3TermSegReaderCursor(pCsr, - pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr - ); - if( rc!=SQLITE_OK ){ - *pRc = rc; - return; - } - } - assert( pExpr->pPhrase->iDoclistToken==0 ); - pExpr->pPhrase->iDoclistToken = -1; - }else{ - *pnOr += (pExpr->eType==FTSQUERY_OR); - fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc); - fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc); - } - } -} - -/* -** Arguments pList/nList contain the doclist for token iToken of phrase p. -** It is merged into the main doclist stored in p->doclist.aAll/nAll. -** -** This function assumes that pList points to a buffer allocated using -** sqlite3_malloc(). This function takes responsibility for eventually -** freeing the buffer. -** -** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. -*/ -static int fts3EvalPhraseMergeToken( - Fts3Table *pTab, /* FTS Table pointer */ - Fts3Phrase *p, /* Phrase to merge pList/nList into */ - int iToken, /* Token pList/nList corresponds to */ - char *pList, /* Pointer to doclist */ - int nList /* Number of bytes in pList */ -){ - int rc = SQLITE_OK; - assert( iToken!=p->iDoclistToken ); - - if( pList==0 ){ - sqlite3_free(p->doclist.aAll); - p->doclist.aAll = 0; - p->doclist.nAll = 0; - } - - else if( p->iDoclistToken<0 ){ - p->doclist.aAll = pList; - p->doclist.nAll = nList; - } - - else if( p->doclist.aAll==0 ){ - sqlite3_free(pList); - } - - else { - char *pLeft; - char *pRight; - int nLeft; - int nRight; - int nDiff; - - if( p->iDoclistTokendoclist.aAll; - nLeft = p->doclist.nAll; - pRight = pList; - nRight = nList; - nDiff = iToken - p->iDoclistToken; - }else{ - pRight = p->doclist.aAll; - nRight = p->doclist.nAll; - pLeft = pList; - nLeft = nList; - nDiff = p->iDoclistToken - iToken; - } - - rc = fts3DoclistPhraseMerge( - pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight - ); - sqlite3_free(pLeft); - p->doclist.aAll = pRight; - p->doclist.nAll = nRight; - } - - if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; - return rc; -} - -/* -** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist -** does not take deferred tokens into account. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseLoad( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p /* Phrase object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int iToken; - int rc = SQLITE_OK; - - for(iToken=0; rc==SQLITE_OK && iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &p->aToken[iToken]; - assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); - - if( pToken->pSegcsr ){ - int nThis = 0; - char *pThis = 0; - rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); - if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); - } - } - assert( pToken->pSegcsr==0 ); - } - - return rc; -} - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -/* -** This function is called on each phrase after the position lists for -** any deferred tokens have been loaded into memory. It updates the phrases -** current position list to include only those positions that are really -** instances of the phrase (after considering deferred tokens). If this -** means that the phrase does not appear in the current row, doclist.pList -** and doclist.nList are both zeroed. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ - int iToken; /* Used to iterate through phrase tokens */ - 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 */ - char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0); - - for(iToken=0; iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; - Fts3DeferredToken *pDeferred = pToken->pDeferred; - - if( pDeferred ){ - char *pList; - int nList; - int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList); - if( rc!=SQLITE_OK ) return rc; - - if( pList==0 ){ - sqlite3_free(aPoslist); - sqlite3_free(aFree); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - - }else if( aPoslist==0 ){ - aPoslist = pList; - nPoslist = nList; - - }else{ - char *aOut = pList; - char *p1 = aPoslist; - char *p2 = aOut; - - assert( iPrev>=0 ); - fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2); - sqlite3_free(aPoslist); - aPoslist = pList; - nPoslist = (int)(aOut - aPoslist); - if( nPoslist==0 ){ - sqlite3_free(aPoslist); - sqlite3_free(aFree); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - } - } - iPrev = iToken; - } - } - - if( iPrev>=0 ){ - int nMaxUndeferred = pPhrase->iDoclistToken; - if( nMaxUndeferred<0 ){ - pPhrase->doclist.pList = aPoslist; - pPhrase->doclist.nList = nPoslist; - pPhrase->doclist.iDocid = pCsr->iPrevId; - pPhrase->doclist.bFreeList = 1; - }else{ - int nDistance; - char *p1; - char *p2; - char *aOut; - - if( nMaxUndeferred>iPrev ){ - p1 = aPoslist; - p2 = pPhrase->doclist.pList; - nDistance = nMaxUndeferred - iPrev; - }else{ - p1 = pPhrase->doclist.pList; - p2 = aPoslist; - nDistance = iPrev - nMaxUndeferred; - } - - aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING); - if( !aOut ){ - 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); - }else{ - sqlite3_free(aOut); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - } - sqlite3_free(aPoslist); - } - } - - if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree); - return SQLITE_OK; -} -#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ - -/* -** Maximum number of tokens a phrase may have to be considered for the -** incremental doclists strategy. -*/ -#define MAX_INCR_PHRASE_TOKENS 4 - -/* -** This function is called for each Fts3Phrase in a full-text query -** expression to initialize the mechanism for returning rows. Once this -** function has been called successfully on an Fts3Phrase, it may be -** used with fts3EvalPhraseNext() to iterate through the matching docids. -** -** If parameter bOptOk is true, then the phrase may (or may not) use the -** incremental loading strategy. Otherwise, the entire doclist is loaded into -** memory within this call. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; /* Error code */ - int i; - - /* Determine if doclists may be loaded from disk incrementally. This is - ** possible if the bOptOk argument is true, the FTS doclists will be - ** scanned in forward order, and the phrase consists of - ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" - ** tokens or prefix tokens that cannot use a prefix-index. */ - int bHaveIncr = 0; - int bIncrOk = (bOptOk - && pCsr->bDesc==pTab->bDescIdx - && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - && pTab->bNoIncrDoclist==0 -#endif - ); - for(i=0; bIncrOk==1 && inToken; i++){ - Fts3PhraseToken *pToken = &p->aToken[i]; - if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ - bIncrOk = 0; - } - if( pToken->pSegcsr ) bHaveIncr = 1; - } - - if( bIncrOk && bHaveIncr ){ - /* Use the incremental approach. */ - int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn); - for(i=0; rc==SQLITE_OK && inToken; i++){ - Fts3PhraseToken *pToken = &p->aToken[i]; - Fts3MultiSegReader *pSegcsr = pToken->pSegcsr; - if( pSegcsr ){ - rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n); - } - } - p->bIncr = 1; - }else{ - /* Load the full doclist for the phrase into memory. */ - rc = fts3EvalPhraseLoad(pCsr, p); - p->bIncr = 0; - } - - assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr ); - return rc; -} - -/* -** This function is used to iterate backwards (from the end to start) -** through doclists. It is used by this module to iterate through phrase -** doclists in reverse and by the fts3_write.c module to iterate through -** pending-terms lists when writing to databases with "order=desc". -** -** The doclist may be sorted in ascending (parameter bDescIdx==0) or -** descending (parameter bDescIdx==1) order of docid. Regardless, this -** function iterates from the end of the doclist to the beginning. -*/ -SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( - int bDescIdx, /* True if the doclist is desc */ - char *aDoclist, /* Pointer to entire doclist */ - int nDoclist, /* Length of aDoclist in bytes */ - char **ppIter, /* IN/OUT: Iterator pointer */ - sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */ - int *pnList, /* OUT: List length pointer */ - u8 *pbEof /* OUT: End-of-file flag */ -){ - char *p = *ppIter; - - assert( nDoclist>0 ); - assert( *pbEof==0 ); - assert_fts3_nc( p || *piDocid==0 ); - assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); - - if( p==0 ){ - sqlite3_int64 iDocid = 0; - char *pNext = 0; - char *pDocid = aDoclist; - char *pEnd = &aDoclist[nDoclist]; - int iMul = 1; - - while( pDocid0 ); - assert( *pbEof==0 ); - assert_fts3_nc( p || *piDocid==0 ); - assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); - - if( p==0 ){ - p = aDoclist; - p += sqlite3Fts3GetVarint(p, piDocid); - }else{ - fts3PoslistCopy(0, &p); - while( p<&aDoclist[nDoclist] && *p==0 ) p++; - if( p>=&aDoclist[nDoclist] ){ - *pbEof = 1; - }else{ - sqlite3_int64 iVar; - p += sqlite3Fts3GetVarint(p, &iVar); - *piDocid += ((bDescIdx ? -1 : 1) * iVar); - } - } - - *ppIter = p; -} - -/* -** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof -** to true if EOF is reached. -*/ -static void fts3EvalDlPhraseNext( - Fts3Table *pTab, - Fts3Doclist *pDL, - u8 *pbEof -){ - char *pIter; /* Used to iterate through aAll */ - char *pEnd; /* 1 byte past end of aAll */ - - if( pDL->pNextDocid ){ - pIter = pDL->pNextDocid; - assert( pDL->aAll!=0 || pIter==0 ); - }else{ - pIter = pDL->aAll; - } - - if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){ - /* We have already reached the end of this doclist. EOF. */ - *pbEof = 1; - }else{ - sqlite3_int64 iDelta; - pIter += sqlite3Fts3GetVarint(pIter, &iDelta); - if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){ - pDL->iDocid += iDelta; - }else{ - pDL->iDocid -= iDelta; - } - pDL->pList = pIter; - fts3PoslistCopy(0, &pIter); - pDL->nList = (int)(pIter - pDL->pList); - - /* pIter now points just past the 0x00 that terminates the position- - ** list for document pDL->iDocid. However, if this position-list was - ** edited in place by fts3EvalNearTrim(), then pIter may not actually - ** point to the start of the next docid value. The following line deals - ** with this case by advancing pIter past the zero-padding added by - ** fts3EvalNearTrim(). */ - while( pIterpNextDocid = pIter; - assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter ); - *pbEof = 0; - } -} - -/* -** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext(). -*/ -typedef struct TokenDoclist TokenDoclist; -struct TokenDoclist { - int bIgnore; - sqlite3_int64 iDocid; - char *pList; - int nList; -}; - -/* -** Token pToken is an incrementally loaded token that is part of a -** multi-token phrase. Advance it to the next matching document in the -** database and populate output variable *p with the details of the new -** entry. Or, if the iterator has reached EOF, set *pbEof to true. -** -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -*/ -static int incrPhraseTokenNext( - Fts3Table *pTab, /* Virtual table handle */ - Fts3Phrase *pPhrase, /* Phrase to advance token of */ - int iToken, /* Specific token to advance */ - TokenDoclist *p, /* OUT: Docid and doclist for new entry */ - u8 *pbEof /* OUT: True if iterator is at EOF */ -){ - int rc = SQLITE_OK; - - if( pPhrase->iDoclistToken==iToken ){ - assert( p->bIgnore==0 ); - assert( pPhrase->aToken[iToken].pSegcsr==0 ); - fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof); - p->pList = pPhrase->doclist.pList; - p->nList = pPhrase->doclist.nList; - p->iDocid = pPhrase->doclist.iDocid; - }else{ - Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; - assert( pToken->pDeferred==0 ); - assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 ); - if( pToken->pSegcsr ){ - assert( p->bIgnore==0 ); - rc = sqlite3Fts3MsrIncrNext( - pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList - ); - if( p->pList==0 ) *pbEof = 1; - }else{ - p->bIgnore = 1; - } - } - - return rc; -} - - -/* -** The phrase iterator passed as the second argument: -** -** * features at least one token that uses an incremental doclist, and -** -** * does not contain any deferred tokens. -** -** Advance it to the next matching document in the database and populate -** the Fts3Doclist.pList and nList fields. -** -** If there is no "next" entry and no error occurs, then *pbEof is set to -** 1 before returning. Otherwise, if no error occurs and the iterator is -** successfully advanced, *pbEof is set to 0. -** -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -*/ -static int fts3EvalIncrPhraseNext( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p, /* Phrase object to advance to next docid */ - u8 *pbEof /* OUT: Set to 1 if EOF */ -){ - int rc = SQLITE_OK; - Fts3Doclist *pDL = &p->doclist; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - u8 bEof = 0; - - /* This is only called if it is guaranteed that the phrase has at least - ** one incremental token. In which case the bIncr flag is set. */ - assert( p->bIncr==1 ); - - if( p->nToken==1 ){ - rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, - &pDL->iDocid, &pDL->pList, &pDL->nList - ); - if( pDL->pList==0 ) bEof = 1; - }else{ - int bDescDoclist = pCsr->bDesc; - struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS]; - - memset(a, 0, sizeof(a)); - assert( p->nToken<=MAX_INCR_PHRASE_TOKENS ); - assert( p->iDoclistTokennToken && bEof==0; i++){ - rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); - if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){ - iMax = a[i].iDocid; - bMaxSet = 1; - } - } - assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) ); - assert( rc!=SQLITE_OK || bMaxSet ); - - /* Keep advancing iterators until they all point to the same document */ - for(i=0; inToken; i++){ - while( rc==SQLITE_OK && bEof==0 - && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 - ){ - rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); - if( DOCID_CMP(a[i].iDocid, iMax)>0 ){ - iMax = a[i].iDocid; - i = 0; - } - } - } - - /* Check if the current entries really are a phrase match */ - if( bEof==0 ){ - int nList = 0; - int nByte = a[p->nToken-1].nList; - char *aDoclist = sqlite3_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); - - for(i=0; i<(p->nToken-1); i++){ - if( a[i].bIgnore==0 ){ - char *pL = a[i].pList; - char *pR = aDoclist; - char *pOut = aDoclist; - int nDist = p->nToken-1-i; - int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR); - if( res==0 ) break; - nList = (int)(pOut - aDoclist); - } - } - if( i==(p->nToken-1) ){ - pDL->iDocid = iMax; - pDL->pList = aDoclist; - pDL->nList = nList; - pDL->bFreeList = 1; - break; - } - sqlite3_free(aDoclist); - } - } - } - - *pbEof = bEof; - return rc; -} - -/* -** Attempt to move the phrase iterator to point to the next matching docid. -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -** -** If there is no "next" entry and no error occurs, then *pbEof is set to -** 1 before returning. Otherwise, if no error occurs and the iterator is -** successfully advanced, *pbEof is set to 0. -*/ -static int fts3EvalPhraseNext( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p, /* Phrase object to advance to next docid */ - u8 *pbEof /* OUT: Set to 1 if EOF */ -){ - int rc = SQLITE_OK; - Fts3Doclist *pDL = &p->doclist; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - - if( p->bIncr ){ - rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof); - }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){ - sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, - &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof - ); - pDL->pList = pDL->pNextDocid; - }else{ - fts3EvalDlPhraseNext(pTab, pDL, pbEof); - } - - return rc; -} - -/* -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, fts3EvalPhraseStart() is called on all phrases within the -** expression. Also the Fts3Expr.bDeferred variable is set to true for any -** expressions for which all descendent tokens are deferred. -** -** If parameter bOptOk is zero, then it is guaranteed that the -** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for -** each phrase in the expression (subject to deferred token processing). -** Or, if bOptOk is non-zero, then one or more tokens within the expression -** may be loaded incrementally, meaning doclist.aAll/nAll is not available. -** -** If an error occurs within this function, *pRc is set to an SQLite error -** code before returning. -*/ -static void fts3EvalStartReaders( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expression to initialize phrases in */ - int *pRc /* IN/OUT: Error code */ -){ - if( pExpr && SQLITE_OK==*pRc ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - int nToken = pExpr->pPhrase->nToken; - if( nToken ){ - int i; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; - } - pExpr->bDeferred = (i==nToken); - } - *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); - }else{ - fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); - fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); - pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); - } - } -} - -/* -** An array of the following structures is assembled as part of the process -** of selecting tokens to defer before the query starts executing (as part -** of the xFilter() method). There is one element in the array for each -** token in the FTS expression. -** -** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong -** to phrases that are connected only by AND and NEAR operators (not OR or -** NOT). When determining tokens to defer, each AND/NEAR cluster is considered -** separately. The root of a tokens AND/NEAR cluster is stored in -** Fts3TokenAndCost.pRoot. -*/ -typedef struct Fts3TokenAndCost Fts3TokenAndCost; -struct Fts3TokenAndCost { - Fts3Phrase *pPhrase; /* The phrase the token belongs to */ - int iToken; /* Position of token in phrase */ - Fts3PhraseToken *pToken; /* The token itself */ - Fts3Expr *pRoot; /* Root of NEAR/AND cluster */ - int nOvfl; /* Number of overflow pages to load doclist */ - int iCol; /* The column the token must match */ -}; - -/* -** This function is used to populate an allocated Fts3TokenAndCost array. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if an error occurs during execution, *pRc is set to an -** SQLite error code. -*/ -static void fts3EvalTokenCosts( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */ - Fts3Expr *pExpr, /* Expression to consider */ - Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */ - Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - for(i=0; *pRc==SQLITE_OK && inToken; i++){ - Fts3TokenAndCost *pTC = (*ppTC)++; - pTC->pPhrase = pPhrase; - pTC->iToken = i; - pTC->pRoot = pRoot; - pTC->pToken = &pPhrase->aToken[i]; - pTC->iCol = pPhrase->iColumn; - *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl); - } - }else if( pExpr->eType!=FTSQUERY_NOT ){ - assert( pExpr->eType==FTSQUERY_OR - || pExpr->eType==FTSQUERY_AND - || pExpr->eType==FTSQUERY_NEAR - ); - assert( pExpr->pLeft && pExpr->pRight ); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pLeft; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pRight; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc); - } - } -} - -/* -** Determine the average document (row) size in pages. If successful, -** write this value to *pnPage and return SQLITE_OK. Otherwise, return -** an SQLite error code. -** -** The average document size in pages is calculated by first calculating -** determining the average size in bytes, B. If B is less than the amount -** of data that will fit on a single leaf page of an intkey table in -** this database, then the average docsize is 1. Otherwise, it is 1 plus -** the number of overflow pages consumed by a record B bytes in size. -*/ -static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ - int rc = SQLITE_OK; - if( pCsr->nRowAvg==0 ){ - /* The average document size, which is required to calculate the cost - ** of each doclist, has not yet been determined. Read the required - ** data from the %_stat table to calculate it. - ** - ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 - ** varints, where nCol is the number of columns in the FTS3 table. - ** The first varint is the number of documents currently stored in - ** the table. The following nCol varints contain the total amount of - ** data stored in all rows of each column of the table, from left - ** to right. - */ - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - sqlite3_stmt *pStmt; - sqlite3_int64 nDoc = 0; - sqlite3_int64 nByte = 0; - const char *pEnd; - const char *a; - - rc = sqlite3Fts3SelectDoctotal(p, &pStmt); - if( rc!=SQLITE_OK ) return rc; - a = sqlite3_column_blob(pStmt, 0); - testcase( a==0 ); /* If %_stat.value set to X'' */ - if( a ){ - pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc); - while( anDoc = nDoc; - pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz); - assert( pCsr->nRowAvg>0 ); - rc = sqlite3_reset(pStmt); - } - - *pnPage = pCsr->nRowAvg; - return rc; -} - -/* -** This function is called to select the tokens (if any) that will be -** deferred. The array aTC[] has already been populated when this is -** called. -** -** This function is called once for each AND/NEAR cluster in the -** expression. Each invocation determines which tokens to defer within -** the cluster with root node pRoot. See comments above the definition -** of struct Fts3TokenAndCost for more details. -** -** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken() -** called on each token to defer. Otherwise, an SQLite error code is -** returned. -*/ -static int fts3EvalSelectDeferred( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Consider tokens with this root node */ - Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */ - int nTC /* Number of entries in aTC[] */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int nDocSize = 0; /* Number of pages per doc loaded */ - int rc = SQLITE_OK; /* Return code */ - int ii; /* Iterator variable for various purposes */ - int nOvfl = 0; /* Total overflow pages used by doclists */ - int nToken = 0; /* Total number of tokens in cluster */ - - int nMinEst = 0; /* The minimum count for any phrase so far. */ - int nLoad4 = 1; /* (Phrases that will be loaded)^4. */ - - /* Tokens are never deferred for FTS tables created using the content=xxx - ** option. The reason being that it is not guaranteed that the content - ** table actually contains the same data as the index. To prevent this from - ** causing any problems, the deferred token optimization is completely - ** disabled for content=xxx tables. */ - if( pTab->zContentTbl ){ - return SQLITE_OK; - } - - /* Count the tokens in this AND/NEAR cluster. If none of the doclists - ** associated with the tokens spill onto overflow pages, or if there is - ** only 1 token, exit early. No tokens to defer in this case. */ - for(ii=0; ii0 ); - - - /* Iterate through all tokens in this AND/NEAR cluster, in ascending order - ** of the number of overflow pages that will be loaded by the pager layer - ** to retrieve the entire doclist for the token from the full-text index. - ** Load the doclists for tokens that are either: - ** - ** a. The cheapest token in the entire query (i.e. the one visited by the - ** first iteration of this loop), or - ** - ** b. Part of a multi-token phrase. - ** - ** After each token doclist is loaded, merge it with the others from the - ** same phrase and count the number of documents that the merged doclist - ** contains. Set variable "nMinEst" to the smallest number of documents in - ** any phrase doclist for which 1 or more token doclists have been loaded. - ** Let nOther be the number of other phrases for which it is certain that - ** one or more tokens will not be deferred. - ** - ** Then, for each token, defer it if loading the doclist would result in - ** loading N or more overflow pages into memory, where N is computed as: - ** - ** (nMinEst + 4^nOther - 1) / (4^nOther) - */ - for(ii=0; iinOvfl) - ){ - pTC = &aTC[iTC]; - } - } - assert( pTC ); - - if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){ - /* The number of overflow pages to load for this (and therefore all - ** subsequent) tokens is greater than the estimated number of pages - ** that will be loaded if all subsequent tokens are deferred. - */ - Fts3PhraseToken *pToken = pTC->pToken; - rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol); - fts3SegReaderCursorFree(pToken->pSegcsr); - pToken->pSegcsr = 0; - }else{ - /* Set nLoad4 to the value of (4^nOther) for the next iteration of the - ** for-loop. Except, limit the value to 2^24 to prevent it from - ** overflowing the 32-bit integer it is stored in. */ - if( ii<12 ) nLoad4 = nLoad4*4; - - if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ - /* Either this is the cheapest token in the entire query, or it is - ** part of a multi-token phrase. Either way, the entire doclist will - ** (eventually) be loaded into memory. It may as well be now. */ - Fts3PhraseToken *pToken = pTC->pToken; - int nList = 0; - char *pList = 0; - rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); - assert( rc==SQLITE_OK || pList==0 ); - if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken( - pTab, pTC->pPhrase, pTC->iToken,pList,nList - ); - } - if( rc==SQLITE_OK ){ - int nCount; - nCount = fts3DoclistCountDocids( - pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll - ); - if( ii==0 || nCountpToken = 0; - } - - return rc; -} - -/* -** This function is called from within the xFilter method. It initializes -** the full-text query currently stored in pCsr->pExpr. To iterate through -** the results of a query, the caller does: -** -** fts3EvalStart(pCsr); -** while( 1 ){ -** fts3EvalNext(pCsr); -** if( pCsr->bEof ) break; -** ... return row pCsr->iPrevId to the caller ... -** } -*/ -static int fts3EvalStart(Fts3Cursor *pCsr){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int nToken = 0; - int nOr = 0; - - /* Allocate a MultiSegReader for each token in the expression. */ - fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc); - - /* Determine which, if any, tokens in the expression should be deferred. */ -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ - Fts3TokenAndCost *aTC; - aTC = (Fts3TokenAndCost *)sqlite3_malloc64( - sizeof(Fts3TokenAndCost) * nToken - + sizeof(Fts3Expr *) * nOr * 2 - ); - - if( !aTC ){ - rc = SQLITE_NOMEM; - }else{ - Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken]; - int ii; - Fts3TokenAndCost *pTC = aTC; - Fts3Expr **ppOr = apOr; - - fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc); - nToken = (int)(pTC-aTC); - nOr = (int)(ppOr-apOr); - - if( rc==SQLITE_OK ){ - rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken); - for(ii=0; rc==SQLITE_OK && iipExpr, &rc); - return rc; -} - -/* -** Invalidate the current position list for phrase pPhrase. -*/ -static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){ - if( pPhrase->doclist.bFreeList ){ - sqlite3_free(pPhrase->doclist.pList); - } - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - pPhrase->doclist.bFreeList = 0; -} - -/* -** This function is called to edit the position list associated with -** the phrase object passed as the fifth argument according to a NEAR -** condition. For example: -** -** abc NEAR/5 "def ghi" -** -** Parameter nNear is passed the NEAR distance of the expression (5 in -** the example above). When this function is called, *paPoslist points to -** the position list, and *pnToken is the number of phrase tokens in the -** phrase on the other side of the NEAR operator to pPhrase. For example, -** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to -** the position list associated with phrase "abc". -** -** All positions in the pPhrase position list that are not sufficiently -** close to a position in the *paPoslist position list are removed. If this -** leaves 0 positions, zero is returned. Otherwise, non-zero. -** -** Before returning, *paPoslist is set to point to the position lsit -** associated with pPhrase. And *pnToken is set to the number of tokens in -** pPhrase. -*/ -static int fts3EvalNearTrim( - int nNear, /* NEAR distance. As in "NEAR/nNear". */ - char *aTmp, /* Temporary space to use */ - char **paPoslist, /* IN/OUT: Position list */ - int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */ - Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */ -){ - int nParam1 = nNear + pPhrase->nToken; - int nParam2 = nNear + *pnToken; - int nNew; - char *p2; - char *pOut; - int res; - - assert( pPhrase->doclist.pList ); - - p2 = pOut = pPhrase->doclist.pList; - res = fts3PoslistNearMerge( - &pOut, aTmp, nParam1, nParam2, paPoslist, &p2 - ); - if( res ){ - nNew = (int)(pOut - pPhrase->doclist.pList) - 1; - assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 ); - if( nNew>=0 && nNew<=pPhrase->doclist.nList ){ - assert( pPhrase->doclist.pList[nNew]=='\0' ); - memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); - pPhrase->doclist.nList = nNew; - } - *paPoslist = pPhrase->doclist.pList; - *pnToken = pPhrase->nToken; - } - - return res; -} - -/* -** This function is a no-op if *pRc is other than SQLITE_OK when it is called. -** Otherwise, it advances the expression passed as the second argument to -** point to the next matching row in the database. Expressions iterate through -** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero, -** or descending if it is non-zero. -** -** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if -** successful, the following variables in pExpr are set: -** -** Fts3Expr.bEof (non-zero if EOF - there is no next row) -** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row) -** -** If the expression is of type FTSQUERY_PHRASE, and the expression is not -** at EOF, then the following variables are populated with the position list -** for the phrase for the visited row: -** -** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes) -** FTs3Expr.pPhrase->doclist.pList (pointer to position list) -** -** It says above that this function advances the expression to the next -** matching row. This is usually true, but there are the following exceptions: -** -** 1. Deferred tokens are not taken into account. If a phrase consists -** entirely of deferred tokens, it is assumed to match every row in -** the db. In this case the position-list is not populated at all. -** -** Or, if a phrase contains one or more deferred tokens and one or -** more non-deferred tokens, then the expression is advanced to the -** next possible match, considering only non-deferred tokens. In other -** words, if the phrase is "A B C", and "B" is deferred, the expression -** is advanced to the next row that contains an instance of "A * C", -** where "*" may match any single token. The position list in this case -** is populated as for "A * C" before returning. -** -** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is -** advanced to point to the next row that matches "x AND y". -** -** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is -** really a match, taking into account deferred tokens and NEAR operators. -*/ -static void fts3EvalNextRow( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expr. to advance to next matching row */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK && pExpr->bEof==0 ){ - int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ - pExpr->bStart = 1; - - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - assert( !pLeft->bDeferred || !pRight->bDeferred ); - - if( pLeft->bDeferred ){ - /* LHS is entirely deferred. So we assume it matches every row. - ** Advance the RHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pRight, pRc); - pExpr->iDocid = pRight->iDocid; - pExpr->bEof = pRight->bEof; - }else if( pRight->bDeferred ){ - /* RHS is entirely deferred. So we assume it matches every row. - ** Advance the LHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - }else{ - /* Neither the RHS or LHS are deferred. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){ - sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( iDiff==0 ) break; - if( iDiff<0 ){ - fts3EvalNextRow(pCsr, pLeft, pRc); - }else{ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = (pLeft->bEof || pRight->bEof); - if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ - assert( pRight->eType==FTSQUERY_PHRASE ); - if( pRight->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pRight->pPhrase->doclist; - while( *pRc==SQLITE_OK && pRight->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pLeft->pPhrase->doclist; - while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pLeft, pRc); - } - } - pRight->bEof = pLeft->bEof = 1; - } - } - break; - } - - case FTSQUERY_OR: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - sqlite3_int64 iCmp = DOCID_CMP(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); - }else if( pLeft->bEof || iCmp>0 ){ - fts3EvalNextRow(pCsr, pRight, pRc); - }else{ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - } - - pExpr->bEof = (pLeft->bEof && pRight->bEof); - iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ - pExpr->iDocid = pLeft->iDocid; - }else{ - pExpr->iDocid = pRight->iDocid; - } - - break; - } - - case FTSQUERY_NOT: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - - if( pRight->bStart==0 ){ - fts3EvalNextRow(pCsr, pRight, pRc); - assert( *pRc!=SQLITE_OK || pRight->bStart ); - } - - fts3EvalNextRow(pCsr, pLeft, pRc); - if( pLeft->bEof==0 ){ - while( !*pRc - && !pRight->bEof - && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 - ){ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - break; - } - - default: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - fts3EvalInvalidatePoslist(pPhrase); - *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof); - pExpr->iDocid = pPhrase->doclist.iDocid; - break; - } - } - } -} - -/* -** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR -** cluster, then this function returns 1 immediately. -** -** Otherwise, it checks if the current row really does match the NEAR -** expression, using the data currently stored in the position lists -** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. -** -** If the current row is a match, the position list associated with each -** phrase in the NEAR expression is edited in place to contain only those -** phrase instances sufficiently close to their peers to satisfy all NEAR -** constraints. In this case it returns 1. If the NEAR expression does not -** match the current row, 0 is returned. The position lists may or may not -** be edited if 0 is returned. -*/ -static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ - int res = 1; - - /* The following block runs if pExpr is the root of a NEAR query. - ** For example, the query: - ** - ** "w" NEAR "x" NEAR "y" NEAR "z" - ** - ** which is represented in tree form as: - ** - ** | - ** +--NEAR--+ <-- root of NEAR query - ** | | - ** +--NEAR--+ "z" - ** | | - ** +--NEAR--+ "y" - ** | | - ** "w" "x" - ** - ** The right-hand child of a NEAR node is always a phrase. The - ** left-hand child may be either a phrase or a NEAR node. There are - ** no exceptions to this - it's the way the parser in fts3_expr.c works. - */ - if( *pRc==SQLITE_OK - && pExpr->eType==FTSQUERY_NEAR - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - sqlite3_int64 nTmp = 0; /* Bytes of temp space */ - char *aTmp; /* Temp space for PoslistNearMerge() */ - - /* Allocate temporary working space. */ - for(p=pExpr; p->pLeft; p=p->pLeft){ - assert( p->pRight->pPhrase->doclist.nList>0 ); - nTmp += p->pRight->pPhrase->doclist.nList; - } - nTmp += p->pPhrase->doclist.nList; - aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX); - if( !aTmp ){ - *pRc = SQLITE_NOMEM; - res = 0; - }else{ - char *aPoslist = p->pPhrase->doclist.pList; - int nToken = p->pPhrase->nToken; - - for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ - Fts3Phrase *pPhrase = p->pRight->pPhrase; - int nNear = p->nNear; - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - - aPoslist = pExpr->pRight->pPhrase->doclist.pList; - nToken = pExpr->pRight->pPhrase->nToken; - for(p=pExpr->pLeft; p && res; p=p->pLeft){ - int nNear; - Fts3Phrase *pPhrase; - assert( p->pParent && p->pParent->pLeft==p ); - nNear = p->pParent->nNear; - pPhrase = ( - p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase - ); - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - } - - sqlite3_free(aTmp); - } - - return res; -} - -/* -** This function is a helper function for sqlite3Fts3EvalTestDeferred(). -** Assuming no error occurs or has occurred, It returns non-zero if the -** expression passed as the second argument matches the row that pCsr -** currently points to, or zero if it does not. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** If an error occurs during execution of this function, *pRc is set to -** the appropriate SQLite error code. In this case the returned value is -** undefined. -*/ -static int fts3EvalTestExpr( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Expr to test. May or may not be root. */ - int *pRc /* IN/OUT: Error code */ -){ - int bHit = 1; /* Return value */ - if( *pRc==SQLITE_OK ){ - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - && fts3EvalNearTest(pExpr, pRc) - ); - - /* If the NEAR expression does not match any rows, zero the doclist for - ** all phrases involved in the NEAR. This is because the snippet(), - ** offsets() and matchinfo() functions are not supposed to recognize - ** any instances of phrases that are part of unmatched NEAR queries. - ** For example if this expression: - ** - ** ... MATCH 'a OR (b NEAR c)' - ** - ** is matched against a row containing: - ** - ** 'a b d e' - ** - ** then any snippet() should ony highlight the "a" term, not the "b" - ** (as "b" is part of a non-matching NEAR clause). - */ - if( bHit==0 - && pExpr->eType==FTSQUERY_NEAR - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - for(p=pExpr; p->pPhrase==0; p=p->pLeft){ - if( p->pRight->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pRight->pPhrase); - } - } - if( p->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pPhrase); - } - } - - break; - - case FTSQUERY_OR: { - int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc); - int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc); - bHit = bHit1 || bHit2; - break; - } - - case FTSQUERY_NOT: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - ); - break; - - default: { -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( pCsr->pDeferred && (pExpr->bDeferred || ( - pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList - ))){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - if( pExpr->bDeferred ){ - fts3EvalInvalidatePoslist(pPhrase); - } - *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase); - bHit = (pPhrase->doclist.pList!=0); - pExpr->iDocid = pCsr->iPrevId; - }else -#endif - { - bHit = ( - pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId - && pExpr->pPhrase->doclist.nList>0 - ); - } - break; - } - } - } - return bHit; -} - -/* -** This function is called as the second part of each xNext operation when -** iterating through the results of a full-text query. At this point the -** cursor points to a row that matches the query expression, with the -** following caveats: -** -** * Up until this point, "NEAR" operators in the expression have been -** treated as "AND". -** -** * Deferred tokens have not yet been considered. -** -** If *pRc is not SQLITE_OK when this function is called, it immediately -** returns 0. Otherwise, it tests whether or not after considering NEAR -** operators and deferred tokens the current row is still a match for the -** expression. It returns 1 if both of the following are true: -** -** 1. *pRc is SQLITE_OK when this function returns, and -** -** 2. After scanning the current FTS table row for the deferred tokens, -** it is determined that the row does *not* match the query. -** -** Or, if no error occurs and it seems the current row does match the FTS -** query, return 0. -*/ -SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ - int rc = *pRc; - int bMiss = 0; - if( rc==SQLITE_OK ){ - - /* If there are one or more deferred tokens, load the current row into - ** memory and scan it to determine the position list for each deferred - ** token. Then, see if this row is really a match, considering deferred - ** tokens and NEAR operators (neither of which were taken into account - ** earlier, by fts3EvalNextRow()). - */ - if( pCsr->pDeferred ){ - rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3CacheDeferredDoclists(pCsr); - } - } - bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc)); - - /* Free the position-lists accumulated for each deferred token above. */ - sqlite3Fts3FreeDeferredDoclists(pCsr); - *pRc = rc; - } - return (rc==SQLITE_OK && bMiss); -} - -/* -** Advance to the next document that matches the FTS expression in -** Fts3Cursor.pExpr. -*/ -static int fts3EvalNext(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Expr *pExpr = pCsr->pExpr; - assert( pCsr->isEof==0 ); - if( pExpr==0 ){ - pCsr->isEof = 1; - }else{ - do { - if( pCsr->isRequireSeek==0 ){ - sqlite3_reset(pCsr->pStmt); - } - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - fts3EvalNextRow(pCsr, pExpr, &rc); - pCsr->isEof = pExpr->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pExpr->iDocid; - }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); - } - - /* Check if the cursor is past the end of the docid range specified - ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ - if( rc==SQLITE_OK && ( - (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) - || (pCsr->bDesc!=0 && pCsr->iPrevIdiMinDocid) - )){ - pCsr->isEof = 1; - } - - return rc; -} - -/* -** Restart iteration for expression pExpr so that the next call to -** fts3EvalNext() visits the first row. Do not allow incremental -** loading or merging of phrase doclists for this iteration. -** -** If *pRc is other than SQLITE_OK when this function is called, it is -** a no-op. If an error occurs within this function, *pRc is set to an -** SQLite error code before returning. -*/ -static void fts3EvalRestart( - Fts3Cursor *pCsr, - Fts3Expr *pExpr, - int *pRc -){ - if( pExpr && *pRc==SQLITE_OK ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - - if( pPhrase ){ - fts3EvalInvalidatePoslist(pPhrase); - if( pPhrase->bIncr ){ - int i; - for(i=0; inToken; i++){ - Fts3PhraseToken *pToken = &pPhrase->aToken[i]; - assert( pToken->pDeferred==0 ); - if( pToken->pSegcsr ){ - sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); - } - } - *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); - } - pPhrase->doclist.pNextDocid = 0; - pPhrase->doclist.iDocid = 0; - pPhrase->pOrPoslist = 0; - } - - pExpr->iDocid = 0; - pExpr->bEof = 0; - pExpr->bStart = 0; - - fts3EvalRestart(pCsr, pExpr->pLeft, pRc); - fts3EvalRestart(pCsr, pExpr->pRight, pRc); - } -} - -/* -** Expression node pExpr is an MSR phrase. This function restarts pExpr -** so that it is a regular phrase query, not an MSR. SQLITE_OK is returned -** if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor *pCsr, Fts3Expr *pExpr){ - int rc = SQLITE_OK; - if( pExpr->bEof==0 ){ - i64 iDocid = pExpr->iDocid; - fts3EvalRestart(pCsr, pExpr, &rc); - while( rc==SQLITE_OK && pExpr->iDocid!=iDocid ){ - fts3EvalNextRow(pCsr, pExpr, &rc); - if( pExpr->bEof ) rc = FTS_CORRUPT_VTAB; - } - } - return rc; -} - -/* -** After allocating the Fts3Expr.aMI[] array for each phrase in the -** expression rooted at pExpr, the cursor iterates through all rows matched -** by pExpr, calling this function for each row. This function increments -** the values in Fts3Expr.aMI[] according to the position-list currently -** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase -** expression nodes. -*/ -static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){ - if( pExpr ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - if( pPhrase && pPhrase->doclist.pList ){ - int iCol = 0; - char *p = pPhrase->doclist.pList; - - do{ - u8 c = 0; - int iCnt = 0; - while( 0xFE & (*p | c) ){ - if( (c&0x80)==0 ) iCnt++; - c = *p++ & 0x80; - } - - /* aMI[iCol*3 + 1] = Number of occurrences - ** aMI[iCol*3 + 2] = Number of rows containing at least one instance - */ - pExpr->aMI[iCol*3 + 1] += iCnt; - pExpr->aMI[iCol*3 + 2] += (iCnt>0); - if( *p==0x00 ) break; - p++; - p += fts3GetVarint32(p, &iCol); - }while( iColpLeft, nCol); - fts3EvalUpdateCounts(pExpr->pRight, nCol); - } -} - -/* -** This is an sqlite3Fts3ExprIterate() callback. If the Fts3Expr.aMI[] array -** has not yet been allocated, allocate and zero it. Otherwise, just zero -** it. -*/ -static int fts3AllocateMSI(Fts3Expr *pExpr, int iPhrase, void *pCtx){ - Fts3Table *pTab = (Fts3Table*)pCtx; - UNUSED_PARAMETER(iPhrase); - if( pExpr->aMI==0 ){ - pExpr->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32)); - if( pExpr->aMI==0 ) return SQLITE_NOMEM; - } - memset(pExpr->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); - return SQLITE_OK; -} - -/* -** Expression pExpr must be of type FTSQUERY_PHRASE. -** -** If it is not already allocated and populated, this function allocates and -** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part -** of a NEAR expression, then it also allocates and populates the same array -** for all other phrases that are part of the NEAR expression. -** -** SQLITE_OK is returned if the aMI[] array is successfully allocated and -** populated. Otherwise, if an error occurs, an SQLite error code is returned. -*/ -static int fts3EvalGatherStats( - Fts3Cursor *pCsr, /* Cursor object */ - Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( pExpr->eType==FTSQUERY_PHRASE ); - if( pExpr->aMI==0 ){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - Fts3Expr *pRoot; /* Root of NEAR expression */ - - sqlite3_int64 iPrevId = pCsr->iPrevId; - sqlite3_int64 iDocid; - u8 bEof; - - /* Find the root of the NEAR expression */ - pRoot = pExpr; - while( pRoot->pParent - && (pRoot->pParent->eType==FTSQUERY_NEAR || pRoot->bDeferred) - ){ - pRoot = pRoot->pParent; - } - iDocid = pRoot->iDocid; - bEof = pRoot->bEof; - assert( pRoot->bStart ); - - /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */ - rc = sqlite3Fts3ExprIterate(pRoot, fts3AllocateMSI, (void*)pTab); - if( rc!=SQLITE_OK ) return rc; - fts3EvalRestart(pCsr, pRoot, &rc); - - while( pCsr->isEof==0 && rc==SQLITE_OK ){ - - do { - /* Ensure the %_content statement is reset. */ - if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt); - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - - /* Advance to the next document */ - fts3EvalNextRow(pCsr, pRoot, &rc); - pCsr->isEof = pRoot->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pRoot->iDocid; - }while( pCsr->isEof==0 - && pRoot->eType==FTSQUERY_NEAR - && sqlite3Fts3EvalTestDeferred(pCsr, &rc) - ); - - if( rc==SQLITE_OK && pCsr->isEof==0 ){ - fts3EvalUpdateCounts(pRoot, pTab->nColumn); - } - } - - pCsr->isEof = 0; - pCsr->iPrevId = iPrevId; - - if( bEof ){ - pRoot->bEof = bEof; - }else{ - /* Caution: pRoot may iterate through docids in ascending or descending - ** order. For this reason, even though it seems more defensive, the - ** do loop can not be written: - ** - ** do {...} while( pRoot->iDocidbEof==0 ); - if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB; - }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); - } - } - return rc; -} - -/* -** This function is used by the matchinfo() module to query a phrase -** expression node for the following information: -** -** 1. The total number of occurrences of the phrase in each column of -** the FTS table (considering all rows), and -** -** 2. For each column, the number of rows in the table for which the -** column contains at least one instance of the phrase. -** -** If no error occurs, SQLITE_OK is returned and the values for each column -** written into the array aiOut as follows: -** -** aiOut[iCol*3 + 1] = Number of occurrences -** aiOut[iCol*3 + 2] = Number of rows containing at least one instance -** -** Caveats: -** -** * If a phrase consists entirely of deferred tokens, then all output -** values are set to the number of documents in the table. In other -** words we assume that very common tokens occur exactly once in each -** column of each row of the table. -** -** * If a phrase contains some deferred tokens (and some non-deferred -** tokens), count the potential occurrence identified by considering -** the non-deferred tokens instead of actual phrase occurrences. -** -** * If the phrase is part of a NEAR expression, then only phrase instances -** that meet the NEAR constraint are included in the counts. -*/ -SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Phrase expression */ - u32 *aiOut /* Array to write results into (see above) */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int iCol; - - if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){ - assert( pCsr->nDoc>0 ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = (u32)pCsr->nDoc; - aiOut[iCol*3 + 2] = (u32)pCsr->nDoc; - } - }else{ - rc = fts3EvalGatherStats(pCsr, pExpr); - if( rc==SQLITE_OK ){ - assert( pExpr->aMI ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1]; - aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2]; - } - } - } - - return rc; -} - -/* -** The expression pExpr passed as the second argument to this function -** must be of type FTSQUERY_PHRASE. -** -** The returned value is either NULL or a pointer to a buffer containing -** a position-list indicating the occurrences of the phrase in column iCol -** of the current row. -** -** More specifically, the returned buffer contains 1 varint for each -** occurrence of the phrase in the column, stored using the normal (delta+2) -** compression and is terminated by either an 0x01 or 0x00 byte. For example, -** if the requested column contains "a b X c d X X" and the position-list -** for 'X' is requested, the buffer returned may contain: -** -** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00 -** -** This function works regardless of whether or not the phrase is deferred, -** incremental, or neither. -*/ -SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - Fts3Expr *pExpr, /* Phrase to return doclist for */ - int iCol, /* Column to return position list for */ - char **ppOut /* OUT: Pointer to position list */ -){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - char *pIter; - int iThis; - sqlite3_int64 iDocid; - - /* If this phrase is applies specifically to some column other than - ** column iCol, return a NULL pointer. */ - *ppOut = 0; - assert( iCol>=0 && iColnColumn ); - if( (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) ){ - return SQLITE_OK; - } - - iDocid = pExpr->iDocid; - pIter = pPhrase->doclist.pList; - if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ - int rc = SQLITE_OK; - int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ - int bOr = 0; - u8 bTreeEof = 0; - Fts3Expr *p; /* Used to iterate from pExpr to root */ - Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ - Fts3Expr *pRun; /* Closest non-deferred ancestor of pNear */ - int bMatch; - - /* Check if this phrase descends from an OR expression node. If not, - ** return NULL. Otherwise, the entry that corresponds to docid - ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the - ** tree that the node is part of has been marked as EOF, but the node - ** itself is not EOF, then it may point to an earlier entry. */ - pNear = pExpr; - for(p=pExpr->pParent; p; p=p->pParent){ - if( p->eType==FTSQUERY_OR ) bOr = 1; - if( p->eType==FTSQUERY_NEAR ) pNear = p; - if( p->bEof ) bTreeEof = 1; - } - if( bOr==0 ) return SQLITE_OK; - pRun = pNear; - while( pRun->bDeferred ){ - assert( pRun->pParent ); - pRun = pRun->pParent; - } - - /* This is the descendent of an OR node. In this case we cannot use - ** an incremental phrase. Load the entire doclist for the phrase - ** into memory in this case. */ - if( pPhrase->bIncr ){ - int bEofSave = pRun->bEof; - fts3EvalRestart(pCsr, pRun, &rc); - while( rc==SQLITE_OK && !pRun->bEof ){ - fts3EvalNextRow(pCsr, pRun, &rc); - if( bEofSave==0 && pRun->iDocid==iDocid ) break; - } - assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); - if( rc==SQLITE_OK && pRun->bEof!=bEofSave ){ - rc = FTS_CORRUPT_VTAB; - } - } - if( bTreeEof ){ - while( rc==SQLITE_OK && !pRun->bEof ){ - fts3EvalNextRow(pCsr, pRun, &rc); - } - } - if( rc!=SQLITE_OK ) return rc; - - bMatch = 1; - for(p=pNear; p; p=p->pLeft){ - u8 bEof = 0; - Fts3Expr *pTest = p; - Fts3Phrase *pPh; - assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); - if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; - assert( pTest->eType==FTSQUERY_PHRASE ); - pPh = pTest->pPhrase; - - pIter = pPh->pOrPoslist; - iDocid = pPh->iOrDocid; - if( pCsr->bDesc==bDescDoclist ){ - bEof = !pPh->doclist.nAll || - (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &bEof - ); - } - }else{ - bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - int dummy; - sqlite3Fts3DoclistPrev( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); - } - } - pPh->pOrPoslist = pIter; - pPh->iOrDocid = iDocid; - if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; - } - - if( bMatch ){ - pIter = pPhrase->pOrPoslist; - }else{ - pIter = 0; - } - } - if( pIter==0 ) return SQLITE_OK; - - if( *pIter==0x01 ){ - pIter++; - pIter += fts3GetVarint32(pIter, &iThis); - }else{ - iThis = 0; - } - while( iThisdoclist, and -** * any Fts3MultiSegReader objects held by phrase tokens. -*/ -SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){ - if( pPhrase ){ - int i; - sqlite3_free(pPhrase->doclist.aAll); - fts3EvalInvalidatePoslist(pPhrase); - memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist)); - for(i=0; inToken; i++){ - fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr); - pPhrase->aToken[i].pSegcsr = 0; - } - } -} - - -/* -** Return SQLITE_CORRUPT_VTAB. -*/ -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3Fts3Corrupt(){ - return SQLITE_CORRUPT_VTAB; -} -#endif - -#if !defined(SQLITE_CORE) -/* -** Initialize API pointer table, if required. -*/ -#ifdef _WIN32 -__declspec(dllexport) -#endif -SQLITE_API int sqlite3_fts3_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3Fts3Init(db); -} -#endif - -#endif - -/************** End of fts3.c ************************************************/ -/************** Begin file fts3_aux.c ****************************************/ -/* -** 2011 Jan 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. -** -****************************************************************************** -** -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -typedef struct Fts3auxTable Fts3auxTable; -typedef struct Fts3auxCursor Fts3auxCursor; - -struct Fts3auxTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - Fts3Table *pFts3Tab; -}; - -struct Fts3auxCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - Fts3MultiSegReader csr; /* Must be right after "base" */ - Fts3SegFilter filter; - char *zStop; - int nStop; /* Byte-length of string zStop */ - int iLangid; /* Language id to query */ - int isEof; /* True if cursor is at EOF */ - sqlite3_int64 iRowid; /* Current rowid */ - - int iCol; /* Current value of 'col' column */ - int nStat; /* Size of aStat[] array */ - struct Fts3auxColstats { - sqlite3_int64 nDoc; /* 'documents' values for current csr row */ - sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ - } *aStat; -}; - -/* -** Schema of the terms table. -*/ -#define FTS3_AUX_SCHEMA \ - "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)" - -/* -** This function does all the work for both the xConnect and xCreate methods. -** These tables have no persistent representation of their own, so xConnect -** and xCreate are identical operations. -*/ -static int fts3auxConnectMethod( - sqlite3 *db, /* Database connection */ - void *pUnused, /* Unused */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - char const *zDb; /* Name of database (e.g. "main") */ - char const *zFts3; /* Name of fts3 table */ - int nDb; /* Result of strlen(zDb) */ - int nFts3; /* Result of strlen(zFts3) */ - sqlite3_int64 nByte; /* Bytes of space to allocate here */ - int rc; /* value returned by declare_vtab() */ - Fts3auxTable *p; /* Virtual table object to return */ - - UNUSED_PARAMETER(pUnused); - - /* The user should invoke this in one of two forms: - ** - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table); - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table); - */ - if( argc!=4 && argc!=5 ) goto bad_args; - - zDb = argv[1]; - nDb = (int)strlen(zDb); - if( argc==5 ){ - if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){ - zDb = argv[3]; - nDb = (int)strlen(zDb); - zFts3 = argv[4]; - }else{ - goto bad_args; - } - }else{ - zFts3 = argv[3]; - } - nFts3 = (int)strlen(zFts3); - - rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA); - if( rc!=SQLITE_OK ) return rc; - - nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; - p = (Fts3auxTable *)sqlite3_malloc64(nByte); - if( !p ) return SQLITE_NOMEM; - memset(p, 0, nByte); - - p->pFts3Tab = (Fts3Table *)&p[1]; - p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1]; - p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1]; - p->pFts3Tab->db = db; - p->pFts3Tab->nIndex = 1; - - memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); - memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); - sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); - - *ppVtab = (sqlite3_vtab *)p; - return SQLITE_OK; - - bad_args: - sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor"); - return SQLITE_ERROR; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3auxTable *p = (Fts3auxTable *)pVtab; - Fts3Table *pFts3 = p->pFts3Tab; - int i; - - /* Free any prepared statements held */ - for(i=0; iaStmt); i++){ - sqlite3_finalize(pFts3->aStmt[i]); - } - sqlite3_free(pFts3->zSegmentsTbl); - sqlite3_free(p); - return SQLITE_OK; -} - -#define FTS4AUX_EQ_CONSTRAINT 1 -#define FTS4AUX_GE_CONSTRAINT 2 -#define FTS4AUX_LE_CONSTRAINT 4 - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3auxBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - int iEq = -1; - int iGe = -1; - int iLe = -1; - int iLangid = -1; - int iNext = 1; /* Next free argvIndex value */ - - UNUSED_PARAMETER(pVTab); - - /* This vtab delivers always results in "ORDER BY term ASC" order. */ - if( pInfo->nOrderBy==1 - && pInfo->aOrderBy[0].iColumn==0 - && pInfo->aOrderBy[0].desc==0 - ){ - pInfo->orderByConsumed = 1; - } - - /* Search for equality and range constraints on the "term" column. - ** And equality constraints on the hidden "languageid" column. */ - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable ){ - int op = pInfo->aConstraint[i].op; - int iCol = pInfo->aConstraint[i].iColumn; - - if( iCol==0 ){ - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; - if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; - } - if( iCol==4 ){ - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i; - } - } - } - - if( iEq>=0 ){ - pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; - pInfo->aConstraintUsage[iEq].argvIndex = iNext++; - pInfo->estimatedCost = 5; - }else{ - pInfo->idxNum = 0; - pInfo->estimatedCost = 20000; - if( iGe>=0 ){ - pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; - pInfo->aConstraintUsage[iGe].argvIndex = iNext++; - pInfo->estimatedCost /= 2; - } - if( iLe>=0 ){ - pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; - pInfo->aConstraintUsage[iLe].argvIndex = iNext++; - pInfo->estimatedCost /= 2; - } - } - if( iLangid>=0 ){ - pInfo->aConstraintUsage[iLangid].argvIndex = iNext++; - pInfo->estimatedCost--; - } - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3auxCursor *pCsr; /* Pointer to cursor object to return */ - - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor)); - if( !pCsr ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(Fts3auxCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - - sqlite3Fts3SegmentsClose(pFts3); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->zStop); - sqlite3_free(pCsr->aStat); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){ - if( nSize>pCsr->nStat ){ - struct Fts3auxColstats *aNew; - aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat, - sizeof(struct Fts3auxColstats) * nSize - ); - if( aNew==0 ) return SQLITE_NOMEM; - memset(&aNew[pCsr->nStat], 0, - sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat) - ); - pCsr->aStat = aNew; - pCsr->nStat = nSize; - } - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - - /* Increment our pretend rowid value. */ - pCsr->iRowid++; - - for(pCsr->iCol++; pCsr->iColnStat; pCsr->iCol++){ - if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK; - } - - rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr); - if( rc==SQLITE_ROW ){ - int i = 0; - int nDoclist = pCsr->csr.nDoclist; - char *aDoclist = pCsr->csr.aDoclist; - int iCol; - - int eState = 0; - - if( pCsr->zStop ){ - int n = (pCsr->nStopcsr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm; - int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n); - if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){ - pCsr->isEof = 1; - return SQLITE_OK; - } - } - - if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM; - memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat); - iCol = 0; - rc = SQLITE_OK; - - while( iaStat[0].nDoc++; - eState = 1; - iCol = 0; - break; - - /* State 1. In this state we are expecting either a 1, indicating - ** that the following integer will be a column number, or the - ** start of a position list for column 0. - ** - ** The only difference between state 1 and state 2 is that if the - ** integer encountered in state 1 is not 0 or 1, then we need to - ** increment the column 0 "nDoc" count for this term. - */ - case 1: - assert( iCol==0 ); - if( v>1 ){ - pCsr->aStat[1].nDoc++; - } - eState = 2; - /* fall through */ - - case 2: - if( v==0 ){ /* 0x00. Next integer will be a docid. */ - eState = 0; - }else if( v==1 ){ /* 0x01. Next integer will be a column number. */ - eState = 3; - }else{ /* 2 or greater. A position. */ - pCsr->aStat[iCol+1].nOcc++; - pCsr->aStat[0].nOcc++; - } - break; - - /* 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; - break; - } - } - - pCsr->iCol = 0; - }else{ - pCsr->isEof = 1; - } - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3auxFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - int isScan = 0; - int iLangVal = 0; /* Language id to query */ - - int iEq = -1; /* Index of term=? value in apVal */ - int iGe = -1; /* Index of term>=? value in apVal */ - int iLe = -1; /* Index of term<=? value in apVal */ - int iLangid = -1; /* Index of languageid=? value in apVal */ - int iNext = 0; - - UNUSED_PARAMETER(nVal); - UNUSED_PARAMETER(idxStr); - - assert( idxStr==0 ); - assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 - || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT - || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) - ); - - if( idxNum==FTS4AUX_EQ_CONSTRAINT ){ - iEq = iNext++; - }else{ - isScan = 1; - if( idxNum & FTS4AUX_GE_CONSTRAINT ){ - iGe = iNext++; - } - if( idxNum & FTS4AUX_LE_CONSTRAINT ){ - iLe = iNext++; - } - } - if( iNextfilter.zTerm); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->aStat); - 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; - if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; - - if( iEq>=0 || iGe>=0 ){ - const unsigned char *zStr = sqlite3_value_text(apVal[0]); - assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) ); - if( zStr ){ - pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); - if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; - pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm); - } - } - - if( iLe>=0 ){ - pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe])); - if( pCsr->zStop==0 ) return SQLITE_NOMEM; - pCsr->nStop = (int)strlen(pCsr->zStop); - } - - if( iLangid>=0 ){ - iLangVal = sqlite3_value_int(apVal[iLangid]); - - /* If the user specified a negative value for the languageid, use zero - ** instead. This works, as the "languageid=?" constraint will also - ** be tested by the VDBE layer. The test will always be false (since - ** this module will not return a row with a negative languageid), and - ** so the overall query will return zero rows. */ - if( iLangVal<0 ) iLangVal = 0; - } - pCsr->iLangid = iLangVal; - - rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL, - pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); - } - - if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor); - return rc; -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - return pCsr->isEof; -} - -/* -** xColumn - Return a column value. -*/ -static int fts3auxColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3auxCursor *p = (Fts3auxCursor *)pCursor; - - assert( p->isEof==0 ); - switch( iCol ){ - case 0: /* term */ - sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); - break; - - case 1: /* col */ - if( p->iCol ){ - sqlite3_result_int(pCtx, p->iCol-1); - }else{ - sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC); - } - break; - - case 2: /* documents */ - sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc); - break; - - case 3: /* occurrences */ - sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc); - break; - - default: /* languageid */ - assert( iCol==4 ); - sqlite3_result_int(pCtx, p->iLangid); - break; - } - - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3auxRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - *pRowid = pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3aux module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ - static const sqlite3_module fts3aux_module = { - 0, /* iVersion */ - fts3auxConnectMethod, /* xCreate */ - fts3auxConnectMethod, /* xConnect */ - fts3auxBestIndexMethod, /* xBestIndex */ - fts3auxDisconnectMethod, /* xDisconnect */ - fts3auxDisconnectMethod, /* xDestroy */ - fts3auxOpenMethod, /* xOpen */ - fts3auxCloseMethod, /* xClose */ - fts3auxFilterMethod, /* xFilter */ - fts3auxNextMethod, /* xNext */ - fts3auxEofMethod, /* xEof */ - fts3auxColumnMethod, /* xColumn */ - fts3auxRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_aux.c ********************************************/ -/************** Begin file fts3_expr.c ***************************************/ -/* -** 2008 Nov 28 -** -** 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 module contains code that implements a parser for fts3 query strings -** (the right-hand argument to the MATCH operator). Because the supported -** syntax is relatively simple, the whole tokenizer/parser system is -** hand-coded. -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* -** By default, this module parses the legacy syntax that has been -** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined, then it uses the new syntax. The differences between -** the new and the old syntaxes are: -** -** a) The new syntax supports parenthesis. The old does not. -** -** b) The new syntax supports the AND and NOT operators. The old does not. -** -** c) The old syntax supports the "-" token qualifier. This is not -** supported by the new syntax (it is replaced by the NOT operator). -** -** d) When using the old syntax, the OR operator has a greater precedence -** than an implicit AND. When using the new, both implicity and explicit -** AND operators have a higher precedence than OR. -** -** If compiled with SQLITE_TEST defined, then this module exports the -** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable -** to zero causes the module to use the old syntax. If it is set to -** non-zero the new syntax is activated. This is so both syntaxes can -** be tested using a single build of testfixture. -** -** The following describes the syntax supported by the fts3 MATCH -** operator in a similar format to that used by the lemon parser -** generator. This module does not use actually lemon, it uses a -** custom parser. -** -** query ::= andexpr (OR andexpr)*. -** -** andexpr ::= notexpr (AND? notexpr)*. -** -** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*. -** notexpr ::= LP query RP. -** -** nearexpr ::= phrase (NEAR distance_opt nearexpr)*. -** -** distance_opt ::= . -** distance_opt ::= / INTEGER. -** -** phrase ::= TOKEN. -** phrase ::= COLUMN:TOKEN. -** phrase ::= "TOKEN TOKEN TOKEN...". -*/ - -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_fts3_enable_parentheses = 0; -#else -# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS -# define sqlite3_fts3_enable_parentheses 1 -# else -# define sqlite3_fts3_enable_parentheses 0 -# endif -#endif - -/* -** Default span for NEAR operators. -*/ -#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10 - -/* #include */ -/* #include */ - -/* -** isNot: -** This variable is used by function getNextNode(). When getNextNode() is -** called, it sets ParseContext.isNot to true if the 'next node' is a -** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the -** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to -** zero. -*/ -typedef struct ParseContext ParseContext; -struct ParseContext { - sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ - int iLangid; /* Language id used with tokenizer */ - const char **azCol; /* Array of column names for fts3 table */ - int bFts4; /* True to allow FTS4-only syntax */ - int nCol; /* Number of entries in azCol[] */ - int iDefaultCol; /* Default column to query */ - int isNot; /* True if getNextNode() sees a unary - */ - sqlite3_context *pCtx; /* Write error message here */ - int nNest; /* Number of nested brackets */ -}; - -/* -** This function is equivalent to the standard isspace() function. -** -** The standard isspace() can be awkward to use safely, because although it -** is defined to accept an argument of type int, its behavior when passed -** an integer that falls outside of the range of the unsigned char type -** is undefined (and sometimes, "undefined" means segfault). This wrapper -** is defined to accept an argument of type char, and always returns 0 for -** any values that fall outside of the range of the unsigned char type (i.e. -** negative values). -*/ -static int fts3isspace(char c){ - return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; -} - -/* -** Allocate nByte bytes of memory using sqlite3_malloc(). If successful, -** zero the memory before returning a pointer to it. If unsuccessful, -** return NULL. -*/ -SQLITE_PRIVATE void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){ - void *pRet = sqlite3_malloc64(nByte); - if( pRet ) memset(pRet, 0, nByte); - return pRet; -} - -SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( - sqlite3_tokenizer *pTokenizer, - int iLangid, - const char *z, - int n, - sqlite3_tokenizer_cursor **ppCsr -){ - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr = 0; - int rc; - - rc = pModule->xOpen(pTokenizer, z, n, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( rc==SQLITE_OK ){ - pCsr->pTokenizer = pTokenizer; - if( pModule->iVersion>=1 ){ - rc = pModule->xLanguageid(pCsr, iLangid); - if( rc!=SQLITE_OK ){ - pModule->xClose(pCsr); - pCsr = 0; - } - } - } - *ppCsr = pCsr; - return rc; -} - -/* -** Function getNextNode(), which is called by fts3ExprParse(), may itself -** call fts3ExprParse(). So this forward declaration is required. -*/ -static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *); - -/* -** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis -** is defined, search for '(' and ')' as well. Return the index of the first -** such character in the buffer. If there is no such character, return -1. -*/ -static int findBarredChar(const char *z, int n){ - int ii; - for(ii=0; iipTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - sqlite3_tokenizer_cursor *pCursor; - Fts3Expr *pRet = 0; - - *pnConsumed = n; - rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); - if( rc==SQLITE_OK ){ - const char *zToken; - int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; - sqlite3_int64 nByte; /* total space to allocate */ - - rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); - if( rc==SQLITE_OK ){ - /* Check that this tokenization did not gobble up any " characters. Or, - ** if enable_parenthesis is true, that it did not gobble up any - ** open or close parenthesis characters either. If it did, call - ** getNextToken() again, but pass only that part of the input buffer - ** up to the first such character. */ - int iBarred = findBarredChar(z, iEnd); - if( iBarred>=0 ){ - pModule->xClose(pCursor); - return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed); - } - - nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken; - pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte); - if( !pRet ){ - rc = SQLITE_NOMEM; - }else{ - pRet->eType = FTSQUERY_PHRASE; - pRet->pPhrase = (Fts3Phrase *)&pRet[1]; - pRet->pPhrase->nToken = 1; - pRet->pPhrase->iColumn = iCol; - pRet->pPhrase->aToken[0].n = nToken; - pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1]; - memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken); - - if( iEndpPhrase->aToken[0].isPrefix = 1; - iEnd++; - } - - while( 1 ){ - if( !sqlite3_fts3_enable_parentheses - && iStart>0 && z[iStart-1]=='-' - ){ - pParse->isNot = 1; - iStart--; - }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){ - pRet->pPhrase->aToken[0].bFirst = 1; - iStart--; - }else{ - break; - } - } - - } - *pnConsumed = iEnd; - }else if( n && rc==SQLITE_DONE ){ - int iBarred = findBarredChar(z, n); - if( iBarred>=0 ){ - *pnConsumed = iBarred; - } - rc = SQLITE_OK; - } - - pModule->xClose(pCursor); - } - - *ppExpr = pRet; - return rc; -} - - -/* -** Enlarge a memory allocation. If an out-of-memory allocation occurs, -** then free the old allocation. -*/ -static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){ - void *pRet = sqlite3_realloc64(pOrig, nNew); - if( !pRet ){ - sqlite3_free(pOrig); - } - return pRet; -} - -/* -** Buffer zInput, length nInput, contains the contents of a quoted string -** that appeared as part of an fts3 query expression. Neither quote character -** is included in the buffer. This function attempts to tokenize the entire -** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE -** containing the results. -** -** If successful, SQLITE_OK is returned and *ppExpr set to point at the -** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory -** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set -** to 0. -*/ -static int getNextString( - ParseContext *pParse, /* fts3 query parse context */ - const char *zInput, int nInput, /* Input string */ - Fts3Expr **ppExpr /* OUT: expression */ -){ - sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - Fts3Expr *p = 0; - sqlite3_tokenizer_cursor *pCursor = 0; - char *zTemp = 0; - i64 nTemp = 0; - - const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1); - int nToken = 0; - - /* The final Fts3Expr data structure, including the Fts3Phrase, - ** Fts3PhraseToken structures token buffers are all stored as a single - ** allocation so that the expression can be freed with a single call to - ** sqlite3_free(). Setting this up requires a two pass approach. - ** - ** The first pass, in the block below, uses a tokenizer cursor to iterate - ** through the tokens in the expression. This pass uses fts3ReallocOrFree() - ** to assemble data in two dynamic buffers: - ** - ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase - ** structure, followed by the array of Fts3PhraseToken - ** structures. This pass only populates the Fts3PhraseToken array. - ** - ** Buffer zTemp: Contains copies of all tokens. - ** - ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, - ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase - ** structures. - */ - rc = sqlite3Fts3OpenTokenizer( - pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); - if( rc==SQLITE_OK ){ - int ii; - for(ii=0; rc==SQLITE_OK; ii++){ - const char *zByte; - int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0; - rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); - if( rc==SQLITE_OK ){ - Fts3PhraseToken *pToken; - - p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); - zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte); - if( !zTemp || !p ){ - rc = SQLITE_NOMEM; - goto getnextstring_out; - } - - assert( nToken==ii ); - pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii]; - memset(pToken, 0, sizeof(Fts3PhraseToken)); - - memcpy(&zTemp[nTemp], zByte, nByte); - nTemp += nByte; - - pToken->n = nByte; - pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^'); - nToken = ii+1; - } - } - } - - if( rc==SQLITE_DONE ){ - int jj; - char *zBuf = 0; - - p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp); - if( !p ){ - rc = SQLITE_NOMEM; - goto getnextstring_out; - } - memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p); - p->eType = FTSQUERY_PHRASE; - p->pPhrase = (Fts3Phrase *)&p[1]; - p->pPhrase->iColumn = pParse->iDefaultCol; - p->pPhrase->nToken = nToken; - - zBuf = (char *)&p->pPhrase->aToken[nToken]; - assert( nTemp==0 || zTemp ); - if( zTemp ){ - memcpy(zBuf, zTemp, nTemp); - } - - for(jj=0; jjpPhrase->nToken; jj++){ - p->pPhrase->aToken[jj].z = zBuf; - zBuf += p->pPhrase->aToken[jj].n; - } - rc = SQLITE_OK; - } - - getnextstring_out: - if( pCursor ){ - pModule->xClose(pCursor); - } - sqlite3_free(zTemp); - if( rc!=SQLITE_OK ){ - sqlite3_free(p); - p = 0; - } - *ppExpr = p; - return rc; -} - -/* -** The output variable *ppExpr is populated with an allocated Fts3Expr -** structure, or set to 0 if the end of the input buffer is reached. -** -** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM -** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered. -** If SQLITE_ERROR is returned, pContext is populated with an error message. -*/ -static int getNextNode( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Input string */ - Fts3Expr **ppExpr, /* OUT: expression */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - static const struct Fts3Keyword { - char *z; /* Keyword text */ - unsigned char n; /* Length of the keyword */ - unsigned char parenOnly; /* Only valid in paren mode */ - unsigned char eType; /* Keyword code */ - } aKeyword[] = { - { "OR" , 2, 0, FTSQUERY_OR }, - { "AND", 3, 1, FTSQUERY_AND }, - { "NOT", 3, 1, FTSQUERY_NOT }, - { "NEAR", 4, 0, FTSQUERY_NEAR } - }; - int ii; - int iCol; - int iColLen; - int rc; - Fts3Expr *pRet = 0; - - const char *zInput = z; - int nInput = n; - - pParse->isNot = 0; - - /* Skip over any whitespace before checking for a keyword, an open or - ** close bracket, or a quoted string. - */ - while( nInput>0 && fts3isspace(*zInput) ){ - nInput--; - zInput++; - } - if( nInput==0 ){ - return SQLITE_DONE; - } - - /* See if we are dealing with a keyword. */ - for(ii=0; ii<(int)(sizeof(aKeyword)/sizeof(struct Fts3Keyword)); ii++){ - const struct Fts3Keyword *pKey = &aKeyword[ii]; - - if( (pKey->parenOnly & ~sqlite3_fts3_enable_parentheses)!=0 ){ - continue; - } - - if( nInput>=pKey->n && 0==memcmp(zInput, pKey->z, pKey->n) ){ - int nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM; - int nKey = pKey->n; - char cNext; - - /* If this is a "NEAR" keyword, check for an explicit nearness. */ - if( pKey->eType==FTSQUERY_NEAR ){ - assert( nKey==4 ); - if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){ - nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear); - } - } - - /* At this point this is probably a keyword. But for that to be true, - ** the next byte must contain either whitespace, an open or close - ** parenthesis, a quote character, or EOF. - */ - cNext = zInput[nKey]; - if( fts3isspace(cNext) - || cNext=='"' || cNext=='(' || cNext==')' || cNext==0 - ){ - pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr)); - if( !pRet ){ - return SQLITE_NOMEM; - } - pRet->eType = pKey->eType; - pRet->nNear = nNear; - *ppExpr = pRet; - *pnConsumed = (int)((zInput - z) + nKey); - return SQLITE_OK; - } - - /* Turns out that wasn't a keyword after all. This happens if the - ** user has supplied a token such as "ORacle". Continue. - */ - } - } - - /* See if we are dealing with a quoted phrase. If this is the case, then - ** search for the closing quote and pass the whole string to getNextString() - ** for processing. This is easy to do, as fts3 has no syntax for escaping - ** a quote character embedded in a string. - */ - if( *zInput=='"' ){ - for(ii=1; iinNest++; -#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; - }else if( *zInput==')' ){ - pParse->nNest--; - *pnConsumed = (int)((zInput - z) + 1); - *ppExpr = 0; - return SQLITE_DONE; - } - } - - /* If control flows to this point, this must be a regular token, or - ** the end of the input. Read a regular token using the sqlite3_tokenizer - ** interface. Before doing so, figure out if there is an explicit - ** column specifier for the token. - ** - ** TODO: Strangely, it is not possible to associate a column specifier - ** with a quoted phrase, only with a single token. Not sure if this was - ** an implementation artifact or an intentional decision when fts3 was - ** first implemented. Whichever it was, this module duplicates the - ** limitation. - */ - iCol = pParse->iDefaultCol; - iColLen = 0; - for(ii=0; iinCol; ii++){ - const char *zStr = pParse->azCol[ii]; - int nStr = (int)strlen(zStr); - if( nInput>nStr && zInput[nStr]==':' - && sqlite3_strnicmp(zStr, zInput, nStr)==0 - ){ - iCol = ii; - iColLen = (int)((zInput - z) + nStr + 1); - break; - } - } - rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); - *pnConsumed += iColLen; - return rc; -} - -/* -** The argument is an Fts3Expr structure for a binary operator (any type -** except an FTSQUERY_PHRASE). Return an integer value representing the -** precedence of the operator. Lower values have a higher precedence (i.e. -** group more tightly). For example, in the C language, the == operator -** groups more tightly than ||, and would therefore have a higher precedence. -** -** When using the new fts3 query syntax (when SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined), the order of the operators in precedence from highest to -** lowest is: -** -** NEAR -** NOT -** AND (including implicit ANDs) -** OR -** -** Note that when using the old query syntax, the OR operator has a higher -** precedence than the AND operator. -*/ -static int opPrecedence(Fts3Expr *p){ - assert( p->eType!=FTSQUERY_PHRASE ); - if( sqlite3_fts3_enable_parentheses ){ - return p->eType; - }else if( p->eType==FTSQUERY_NEAR ){ - return 1; - }else if( p->eType==FTSQUERY_OR ){ - return 2; - } - assert( p->eType==FTSQUERY_AND ); - return 3; -} - -/* -** Argument ppHead contains a pointer to the current head of a query -** expression tree being parsed. pPrev is the expression node most recently -** inserted into the tree. This function adds pNew, which is always a binary -** operator node, into the expression tree based on the relative precedence -** of pNew and the existing nodes of the tree. This may result in the head -** of the tree changing, in which case *ppHead is set to the new root node. -*/ -static void insertBinaryOperator( - Fts3Expr **ppHead, /* Pointer to the root node of a tree */ - Fts3Expr *pPrev, /* Node most recently inserted into the tree */ - Fts3Expr *pNew /* New binary node to insert into expression tree */ -){ - Fts3Expr *pSplit = pPrev; - while( pSplit->pParent && opPrecedence(pSplit->pParent)<=opPrecedence(pNew) ){ - pSplit = pSplit->pParent; - } - - if( pSplit->pParent ){ - assert( pSplit->pParent->pRight==pSplit ); - pSplit->pParent->pRight = pNew; - pNew->pParent = pSplit->pParent; - }else{ - *ppHead = pNew; - } - pNew->pLeft = pSplit; - pSplit->pParent = pNew; -} - -/* -** Parse the fts3 query expression found in buffer z, length n. This function -** returns either when the end of the buffer is reached or an unmatched -** closing bracket - ')' - is encountered. -** -** If successful, SQLITE_OK is returned, *ppExpr is set to point to the -** parsed form of the expression and *pnConsumed is set to the number of -** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM -** (out of memory error) or SQLITE_ERROR (parse error) is returned. -*/ -static int fts3ExprParse( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - Fts3Expr *pRet = 0; - Fts3Expr *pPrev = 0; - Fts3Expr *pNotBranch = 0; /* Only used in legacy parse mode */ - int nIn = n; - const char *zIn = z; - int rc = SQLITE_OK; - int isRequirePhrase = 1; - - while( rc==SQLITE_OK ){ - Fts3Expr *p = 0; - int nByte = 0; - - rc = getNextNode(pParse, zIn, nIn, &p, &nByte); - assert( nByte>0 || (rc!=SQLITE_OK && p==0) ); - if( rc==SQLITE_OK ){ - if( p ){ - int isPhrase; - - if( !sqlite3_fts3_enable_parentheses - && p->eType==FTSQUERY_PHRASE && pParse->isNot - ){ - /* Create an implicit NOT operator. */ - Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr)); - if( !pNot ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pNot->eType = FTSQUERY_NOT; - pNot->pRight = p; - p->pParent = pNot; - if( pNotBranch ){ - pNot->pLeft = pNotBranch; - pNotBranch->pParent = pNot; - } - pNotBranch = pNot; - p = pPrev; - }else{ - int eType = p->eType; - isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); - - /* The isRequirePhrase variable is set to true if a phrase or - ** an expression contained in parenthesis is required. If a - ** binary operator (AND, OR, NOT or NEAR) is encountered when - ** isRequirePhrase is set, this is a syntax error. - */ - if( !isPhrase && isRequirePhrase ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase && !isRequirePhrase ){ - /* Insert an implicit AND operator. */ - Fts3Expr *pAnd; - assert( pRet && pPrev ); - pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr)); - if( !pAnd ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pAnd->eType = FTSQUERY_AND; - insertBinaryOperator(&pRet, pPrev, pAnd); - pPrev = pAnd; - } - - /* This test catches attempts to make either operand of a NEAR - ** operator something other than a phrase. For example, either of - ** the following: - ** - ** (bracketed expression) NEAR phrase - ** phrase NEAR (bracketed expression) - ** - ** Return an error in either case. - */ - if( pPrev && ( - (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE) - || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR) - )){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase ){ - if( pRet ){ - assert( pPrev && pPrev->pLeft && pPrev->pRight==0 ); - pPrev->pRight = p; - p->pParent = pPrev; - }else{ - pRet = p; - } - }else{ - insertBinaryOperator(&pRet, pPrev, p); - } - isRequirePhrase = !isPhrase; - } - pPrev = p; - } - assert( nByte>0 ); - } - assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) ); - nIn -= nByte; - zIn += nByte; - } - - if( rc==SQLITE_DONE && pRet && isRequirePhrase ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - if( !sqlite3_fts3_enable_parentheses && pNotBranch ){ - if( !pRet ){ - rc = SQLITE_ERROR; - }else{ - Fts3Expr *pIter = pNotBranch; - while( pIter->pLeft ){ - pIter = pIter->pLeft; - } - pIter->pLeft = pRet; - pRet->pParent = pIter; - pRet = pNotBranch; - } - } - } - *pnConsumed = n - nIn; - -exprparse_out: - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRet); - sqlite3Fts3ExprFree(pNotBranch); - pRet = 0; - } - *ppExpr = pRet; - return rc; -} - -/* -** Return SQLITE_ERROR if the maximum depth of the expression tree passed -** as the only argument is more than nMaxDepth. -*/ -static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){ - int rc = SQLITE_OK; - if( p ){ - if( nMaxDepth<0 ){ - rc = SQLITE_TOOBIG; - }else{ - rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1); - } - } - } - return rc; -} - -/* -** This function attempts to transform the expression tree at (*pp) to -** an equivalent but more balanced form. The tree is modified in place. -** If successful, SQLITE_OK is returned and (*pp) set to point to the -** new root expression node. -** -** nMaxDepth is the maximum allowable depth of the balanced sub-tree. -** -** Otherwise, if an error occurs, an SQLite error code is returned and -** expression (*pp) freed. -*/ -static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ - int rc = SQLITE_OK; /* Return code */ - Fts3Expr *pRoot = *pp; /* Initial root node */ - Fts3Expr *pFree = 0; /* List of free nodes. Linked by pParent. */ - int eType = pRoot->eType; /* Type of node in this tree */ - - if( nMaxDepth==0 ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_OK ){ - if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ - Fts3Expr **apLeaf; - apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth); - if( 0==apLeaf ){ - rc = SQLITE_NOMEM; - }else{ - memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); - } - - if( rc==SQLITE_OK ){ - int i; - Fts3Expr *p; - - /* Set $p to point to the left-most leaf in the tree of eType nodes. */ - for(p=pRoot; p->eType==eType; p=p->pLeft){ - assert( p->pParent==0 || p->pParent->pLeft==p ); - assert( p->pLeft && p->pRight ); - } - - /* This loop runs once for each leaf in the tree of eType nodes. */ - while( 1 ){ - int iLvl; - Fts3Expr *pParent = p->pParent; /* Current parent of p */ - - assert( pParent==0 || pParent->pLeft==p ); - p->pParent = 0; - if( pParent ){ - pParent->pLeft = 0; - }else{ - pRoot = 0; - } - rc = fts3ExprBalance(&p, nMaxDepth-1); - if( rc!=SQLITE_OK ) break; - - for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; - pFree->pRight = p; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - apLeaf[iLvl] = 0; - } - } - if( p ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_TOOBIG; - break; - } - - /* If that was the last leaf node, break out of the loop */ - if( pParent==0 ) break; - - /* Set $p to point to the next leaf in the tree of eType nodes */ - for(p=pParent->pRight; p->eType==eType; p=p->pLeft); - - /* Remove pParent from the original tree. */ - assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); - pParent->pRight->pParent = pParent->pParent; - if( pParent->pParent ){ - pParent->pParent->pLeft = pParent->pRight; - }else{ - assert( pParent==pRoot ); - pRoot = pParent->pRight; - } - - /* Link pParent into the free node list. It will be used as an - ** internal node of the new tree. */ - pParent->pParent = pFree; - pFree = pParent; - } - - if( rc==SQLITE_OK ){ - p = 0; - for(i=0; ipParent = 0; - }else{ - assert( pFree!=0 ); - pFree->pRight = p; - pFree->pLeft = apLeaf[i]; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - } - } - } - pRoot = p; - }else{ - /* An error occurred. Delete the contents of the apLeaf[] array - ** and pFree list. Everything else is cleaned up by the call to - ** sqlite3Fts3ExprFree(pRoot) below. */ - Fts3Expr *pDel; - for(i=0; ipParent; - sqlite3_free(pDel); - } - } - - assert( pFree==0 ); - sqlite3_free( apLeaf ); - } - }else if( eType==FTSQUERY_NOT ){ - Fts3Expr *pLeft = pRoot->pLeft; - Fts3Expr *pRight = pRoot->pRight; - - pRoot->pLeft = 0; - pRoot->pRight = 0; - pLeft->pParent = 0; - pRight->pParent = 0; - - rc = fts3ExprBalance(&pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprBalance(&pRight, nMaxDepth-1); - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRight); - sqlite3Fts3ExprFree(pLeft); - }else{ - assert( pLeft && pRight ); - pRoot->pLeft = pLeft; - pLeft->pParent = pRoot; - pRoot->pRight = pRight; - pRight->pParent = pRoot; - } - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRoot); - pRoot = 0; - } - *pp = pRoot; - return rc; -} - -/* -** This function is similar to sqlite3Fts3ExprParse(), with the following -** differences: -** -** 1. It does not do expression rebalancing. -** 2. It does not check that the expression does not exceed the -** maximum allowable depth. -** 3. Even if it fails, *ppExpr may still be set to point to an -** expression tree. It should be deleted using sqlite3Fts3ExprFree() -** in this case. -*/ -static int fts3ExprParseUnbalanced( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr /* OUT: Parsed query structure */ -){ - int nParsed; - int rc; - ParseContext sParse; - - memset(&sParse, 0, sizeof(ParseContext)); - sParse.pTokenizer = pTokenizer; - sParse.iLangid = iLangid; - sParse.azCol = (const char **)azCol; - sParse.nCol = nCol; - sParse.iDefaultCol = iDefaultCol; - sParse.bFts4 = bFts4; - if( z==0 ){ - *ppExpr = 0; - return SQLITE_OK; - } - if( n<0 ){ - n = (int)strlen(z); - } - rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); - assert( rc==SQLITE_OK || *ppExpr==0 ); - - /* Check for mismatched parenthesis */ - if( rc==SQLITE_OK && sParse.nNest ){ - rc = SQLITE_ERROR; - } - - return rc; -} - -/* -** Parameters z and n contain a pointer to and length of a buffer containing -** an fts3 query expression, respectively. This function attempts to parse the -** query expression and create a tree of Fts3Expr structures representing the -** parsed expression. If successful, *ppExpr is set to point to the head -** of the parsed expression tree and SQLITE_OK is returned. If an error -** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse -** error) is returned and *ppExpr is set to 0. -** -** If parameter n is a negative number, then z is assumed to point to a -** nul-terminated string and the length is determined using strlen(). -** -** The first parameter, pTokenizer, is passed the fts3 tokenizer module to -** use to normalize query tokens while parsing the expression. The azCol[] -** array, which is assumed to contain nCol entries, should contain the names -** of each column in the target fts3 table, in order from left to right. -** Column names must be nul-terminated strings. -** -** The iDefaultCol parameter should be passed the index of the table column -** that appears on the left-hand-side of the MATCH operator (the default -** column to match against for tokens for which a column name is not explicitly -** specified as part of the query string), or -1 if tokens may by default -** match any table column. -*/ -SQLITE_PRIVATE int sqlite3Fts3ExprParse( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - char **pzErr /* OUT: Error message (sqlite3_malloc) */ -){ - int rc = fts3ExprParseUnbalanced( - pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr - ); - - /* Rebalance the expression. And check that its depth does not exceed - ** SQLITE_FTS3_MAX_EXPR_DEPTH. */ - if( rc==SQLITE_OK && *ppExpr ){ - rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(*ppExpr); - *ppExpr = 0; - if( rc==SQLITE_TOOBIG ){ - sqlite3Fts3ErrMsg(pzErr, - "FTS expression tree is too large (maximum depth %d)", - SQLITE_FTS3_MAX_EXPR_DEPTH - ); - rc = SQLITE_ERROR; - }else if( rc==SQLITE_ERROR ){ - sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z); - } - } - - return rc; -} - -/* -** Free a single node of an expression tree. -*/ -static void fts3FreeExprNode(Fts3Expr *p){ - assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); - sqlite3Fts3EvalPhraseCleanup(p->pPhrase); - sqlite3_free(p->aMI); - sqlite3_free(p); -} - -/* -** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse(). -** -** This function would be simpler if it recursively called itself. But -** that would mean passing a sufficiently large expression to ExprParse() -** could cause a stack overflow. -*/ -SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *pDel){ - Fts3Expr *p; - assert( pDel==0 || pDel->pParent==0 ); - for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){ - assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft ); - } - while( p ){ - Fts3Expr *pParent = p->pParent; - fts3FreeExprNode(p); - if( pParent && p==pParent->pLeft && pParent->pRight ){ - p = pParent->pRight; - while( p && (p->pLeft || p->pRight) ){ - assert( p==p->pParent->pRight || p==p->pParent->pLeft ); - p = (p->pLeft ? p->pLeft : p->pRight); - } - }else{ - p = pParent; - } - } -} - -/**************************************************************************** -***************************************************************************** -** Everything after this point is just test code. -*/ - -#ifdef SQLITE_TEST - -/* #include */ - -/* -** Return a pointer to a buffer containing a text representation of the -** expression passed as the first argument. The buffer is obtained from -** sqlite3_malloc(). It is the responsibility of the caller to use -** sqlite3_free() to release the memory. If an OOM condition is encountered, -** NULL is returned. -** -** If the second argument is not NULL, then its contents are prepended to -** the returned expression text and then freed using sqlite3_free(). -*/ -static char *exprToString(Fts3Expr *pExpr, char *zBuf){ - if( pExpr==0 ){ - return sqlite3_mprintf(""); - } - switch( pExpr->eType ){ - case FTSQUERY_PHRASE: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - zBuf = sqlite3_mprintf( - "%zPHRASE %d 0", zBuf, pPhrase->iColumn); - for(i=0; zBuf && inToken; i++){ - zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, - pPhrase->aToken[i].n, pPhrase->aToken[i].z, - (pPhrase->aToken[i].isPrefix?"+":"") - ); - } - return zBuf; - } - - case FTSQUERY_NEAR: - zBuf = sqlite3_mprintf("%zNEAR/%d ", zBuf, pExpr->nNear); - break; - case FTSQUERY_NOT: - zBuf = sqlite3_mprintf("%zNOT ", zBuf); - break; - case FTSQUERY_AND: - zBuf = sqlite3_mprintf("%zAND ", zBuf); - break; - case FTSQUERY_OR: - zBuf = sqlite3_mprintf("%zOR ", zBuf); - break; - } - - if( zBuf ) zBuf = sqlite3_mprintf("%z{", zBuf); - if( zBuf ) zBuf = exprToString(pExpr->pLeft, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z} {", zBuf); - - if( zBuf ) zBuf = exprToString(pExpr->pRight, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z}", zBuf); - - return zBuf; -} - -/* -** This is the implementation of a scalar SQL function used to test the -** expression parser. It should be called as follows: -** -** fts3_exprtest(, , , ...); -** -** The first argument, , is the name of the fts3 tokenizer used -** to parse the query expression (see README.tokenizers). The second argument -** is the query expression to parse. Each subsequent argument is the name -** of a column of the fts3 table that the query expression may refer to. -** For example: -** -** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); -*/ -static void fts3ExprTestCommon( - int bRebalance, - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3_tokenizer *pTokenizer = 0; - int rc; - char **azCol = 0; - const char *zExpr; - int nExpr; - int nCol; - int ii; - Fts3Expr *pExpr; - char *zBuf = 0; - Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); - const char *zTokenizer = 0; - char *zErr = 0; - - if( argc<3 ){ - sqlite3_result_error(context, - "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1 - ); - return; - } - - zTokenizer = (const char*)sqlite3_value_text(argv[0]); - rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_error(context, zErr, -1); - } - sqlite3_free(zErr); - return; - } - - zExpr = (const char *)sqlite3_value_text(argv[1]); - nExpr = sqlite3_value_bytes(argv[1]); - nCol = argc-2; - azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *)); - if( !azCol ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - for(ii=0; iipModule->xDestroy(pTokenizer); - } - sqlite3_free(azCol); -} - -static void fts3ExprTest( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(0, context, argc, argv); -} -static void fts3ExprTestRebalance( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(1, context, argc, argv); -} - -/* -** Register the query expression parser test function fts3_exprtest() -** with database connection db. -*/ -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ - int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 - ); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 - ); - } - return rc; -} - -#endif -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_expr.c *******************************************/ -/************** Begin file fts3_hash.c ***************************************/ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of generic hash-tables used in SQLite. -** We've modified it slightly to serve as a standalone hash table -** implementation for the full-text indexing module. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ - -/* #include "fts3_hash.h" */ - -/* -** Malloc and Free functions -*/ -static void *fts3HashMalloc(sqlite3_int64 n){ - void *p = sqlite3_malloc64(n); - if( p ){ - memset(p, 0, n); - } - return p; -} -static void fts3HashFree(void *p){ - sqlite3_free(p); -} - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "pNew" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants -** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass -** determines what kind of key the hash table will use. "copyKey" is -** true if the hash table should make its own private copy of keys and -** false if it should just use the supplied pointer. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ - assert( pNew!=0 ); - assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); - pNew->keyClass = keyClass; - pNew->copyKey = copyKey; - pNew->first = 0; - pNew->count = 0; - pNew->htsize = 0; - pNew->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash *pH){ - Fts3HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - fts3HashFree(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - Fts3HashElem *next_elem = elem->next; - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_STRING -*/ -static int fts3StrHash(const void *pKey, int nKey){ - const char *z = (const char *)pKey; - unsigned h = 0; - if( nKey<=0 ) nKey = (int) strlen(z); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ *z++; - nKey--; - } - return (int)(h & 0x7fffffff); -} -static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return strncmp((const char*)pKey1,(const char*)pKey2,n1); -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_BINARY -*/ -static int fts3BinHash(const void *pKey, int nKey){ - int h = 0; - const char *z = (const char *)pKey; - while( nKey-- > 0 ){ - h = (h<<3) ^ h ^ *(z++); - } - return h & 0x7fffffff; -} -static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return memcmp(pKey1,pKey2,n1); -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** The C syntax in this function definition may be unfamilar to some -** programmers, so we provide the following additional explanation: -** -** The name of the function is "ftsHashFunction". The function takes a -** single parameter "keyClass". The return value of ftsHashFunction() -** is a pointer to another function. Specifically, the return value -** of ftsHashFunction() is a pointer to a function that takes two parameters -** with types "const void*" and "int" and returns an "int". -*/ -static int (*ftsHashFunction(int keyClass))(const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrHash; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinHash; - } -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** For help in interpreted the obscure C code in the function definition, -** see the header comment on the previous function. -*/ -static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrCompare; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinCompare; - } -} - -/* Link an element into the hash table -*/ -static void fts3HashInsertElement( - Fts3Hash *pH, /* The complete hash table */ - struct _fts3ht *pEntry, /* The entry into which pNew is inserted */ - Fts3HashElem *pNew /* The element to be inserted */ -){ - Fts3HashElem *pHead; /* First element already in pEntry */ - pHead = pEntry->chain; - if( pHead ){ - pNew->next = pHead; - pNew->prev = pHead->prev; - if( pHead->prev ){ pHead->prev->next = pNew; } - else { pH->first = pNew; } - pHead->prev = pNew; - }else{ - pNew->next = pH->first; - if( pH->first ){ pH->first->prev = pNew; } - pNew->prev = 0; - pH->first = pNew; - } - pEntry->count++; - pEntry->chain = pNew; -} - - -/* Resize the hash table so that it contains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqliteMalloc() fails. -** -** Return non-zero if a memory allocation error occurs. -*/ -static int fts3Rehash(Fts3Hash *pH, int new_size){ - struct _fts3ht *new_ht; /* The new hash table */ - Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); - if( new_ht==0 ) return 1; - fts3HashFree(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size; - xHash = ftsHashFunction(pH->keyClass); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); - next_elem = elem->next; - fts3HashInsertElement(pH, &new_ht[h], elem); - } - return 0; -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. -*/ -static Fts3HashElem *fts3FindElementByHash( - const Fts3Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ -){ - Fts3HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ - int (*xCompare)(const void*,int,const void*,int); /* comparison function */ - - if( pH->ht ){ - struct _fts3ht *pEntry = &pH->ht[h]; - elem = pEntry->chain; - count = pEntry->count; - xCompare = ftsCompareFunction(pH->keyClass); - while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } - } - return 0; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void fts3RemoveElementByHash( - Fts3Hash *pH, /* The pH containing "elem" */ - Fts3HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ -){ - struct _fts3ht *pEntry; - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - pEntry = &pH->ht[h]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - pEntry->count--; - if( pEntry->count<=0 ){ - pEntry->chain = 0; - } - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree( elem ); - pH->count--; - if( pH->count<=0 ){ - assert( pH->first==0 ); - assert( pH->count==0 ); - fts3HashClear(pH); - } -} - -SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem( - const Fts3Hash *pH, - const void *pKey, - int nKey -){ - int h; /* A hash on key */ - int (*xHash)(const void*,int); /* The hash function */ - - if( pH==0 || pH->ht==0 ) return 0; - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); -} - -/* -** Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){ - Fts3HashElem *pElem; /* The element that matches key (if any) */ - - pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey); - return pElem ? pElem->data : 0; -} - -/* Insert an element into the hash table pH. The key is pKey,nKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -SQLITE_PRIVATE void *sqlite3Fts3HashInsert( - Fts3Hash *pH, /* The hash table to insert into */ - const void *pKey, /* The key */ - int nKey, /* Number of bytes in the key */ - void *data /* The data */ -){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ - Fts3HashElem *elem; /* Used to loop thru the element list */ - Fts3HashElem *new_elem; /* New element added to the pH */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( pH!=0 ); - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = fts3FindElementByHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - fts3RemoveElementByHash(pH,elem,h); - }else{ - elem->data = data; - } - return old_data; - } - if( data==0 ) return 0; - if( (pH->htsize==0 && fts3Rehash(pH,8)) - || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2)) - ){ - pH->count = 0; - return data; - } - assert( pH->htsize>0 ); - new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); - if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = fts3HashMalloc( nKey ); - if( new_elem->pKey==0 ){ - fts3HashFree(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } - new_elem->nKey = nKey; - pH->count++; - assert( pH->htsize>0 ); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - fts3HashInsertElement(pH, &pH->ht[h], new_elem); - new_elem->data = data; - return 0; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_hash.c *******************************************/ -/************** Begin file fts3_porter.c *************************************/ -/* -** 2006 September 30 -** -** 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. -** -************************************************************************* -** Implementation of the full-text-search tokenizer that implements -** a Porter stemmer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -/* #include "fts3_tokenizer.h" */ - -/* -** Class derived from sqlite3_tokenizer -*/ -typedef struct porter_tokenizer { - sqlite3_tokenizer base; /* Base class */ -} porter_tokenizer; - -/* -** Class derived from sqlite3_tokenizer_cursor -*/ -typedef struct porter_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *zInput; /* input we are tokenizing */ - int nInput; /* size of the input */ - int iOffset; /* current position in zInput */ - int iToken; /* index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAllocated; /* space allocated to zToken buffer */ -} porter_tokenizer_cursor; - - -/* -** Create a new tokenizer instance. -*/ -static int porterCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - porter_tokenizer *t; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int porterDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is zInput[0..nInput-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int porterOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, int nInput, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - porter_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->zInput = zInput; - if( zInput==0 ){ - c->nInput = 0; - }else if( nInput<0 ){ - c->nInput = (int)strlen(zInput); - }else{ - c->nInput = nInput; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->zToken = NULL; /* no space allocated, yet. */ - c->nAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** porterOpen() above. -*/ -static int porterClose(sqlite3_tokenizer_cursor *pCursor){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - sqlite3_free(c->zToken); - sqlite3_free(c); - return SQLITE_OK; -} -/* -** Vowel or consonant -*/ -static const char cType[] = { - 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 2, 1 -}; - -/* -** isConsonant() and isVowel() determine if their first character in -** the string they point to is a consonant or a vowel, according -** to Porter ruls. -** -** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. -** 'Y' is a consonant unless it follows another consonant, -** in which case it is a vowel. -** -** In these routine, the letters are in reverse order. So the 'y' rule -** is that 'y' is a consonant unless it is followed by another -** consonent. -*/ -static int isVowel(const char*); -static int isConsonant(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return j; - return z[1]==0 || isVowel(z + 1); -} -static int isVowel(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return 1-j; - return isConsonant(z + 1); -} - -/* -** Let any sequence of one or more vowels be represented by V and let -** C be sequence of one or more consonants. Then every word can be -** represented as: -** -** [C] (VC){m} [V] -** -** In prose: A word is an optional consonant followed by zero or -** vowel-consonant pairs followed by an optional vowel. "m" is the -** number of vowel consonant pairs. This routine computes the value -** of m for the first i bytes of a word. -** -** Return true if the m-value for z is 1 or more. In other words, -** return true if z contains at least one vowel that is followed -** by a consonant. -** -** In this routine z[] is in reverse order. So we are really looking -** for an instance of a consonant followed by a vowel. -*/ -static int m_gt_0(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* Like mgt0 above except we are looking for a value of m which is -** exactly 1 -*/ -static int m_eq_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 1; - while( isConsonant(z) ){ z++; } - return *z==0; -} - -/* Like mgt0 above except we are looking for a value of m>1 instead -** or m>0 -*/ -static int m_gt_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if there is a vowel anywhere within z[0..n-1] -*/ -static int hasVowel(const char *z){ - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if the word ends in a double consonant. -** -** The text is reversed here. So we are really looking at -** the first two characters of z[]. -*/ -static int doubleConsonant(const char *z){ - return isConsonant(z) && z[0]==z[1]; -} - -/* -** Return TRUE if the word ends with three letters which -** are consonant-vowel-consonent and where the final consonant -** is not 'w', 'x', or 'y'. -** -** The word is reversed here. So we are really checking the -** first three letters and the first one cannot be in [wxy]. -*/ -static int star_oh(const char *z){ - return - isConsonant(z) && - z[0]!='w' && z[0]!='x' && z[0]!='y' && - isVowel(z+1) && - isConsonant(z+2); -} - -/* -** If the word ends with zFrom and xCond() is true for the stem -** of the word that precedes the zFrom ending, then change the -** ending to zTo. -** -** The input word *pz and zFrom are both in reverse order. zTo -** is in normal order. -** -** Return TRUE if zFrom matches. Return FALSE if zFrom does not -** match. Not that TRUE is returned even if xCond() fails and -** no substitution occurs. -*/ -static int stem( - char **pz, /* The word being stemmed (Reversed) */ - const char *zFrom, /* If the ending matches this... (Reversed) */ - const char *zTo, /* ... change the ending to this (not reversed) */ - int (*xCond)(const char*) /* Condition that must be true */ -){ - char *z = *pz; - while( *zFrom && *zFrom==*z ){ z++; zFrom++; } - if( *zFrom!=0 ) return 0; - if( xCond && !xCond(z) ) return 1; - while( *zTo ){ - *(--z) = *(zTo++); - } - *pz = z; - return 1; -} - -/* -** This is the fallback stemmer used when the porter stemmer is -** inappropriate. The input word is copied into the output with -** US-ASCII case folding. If the input word is too long (more -** than 20 bytes if it contains no digits or more than 6 bytes if -** it contains digits) then word is truncated to 20 or 6 bytes -** by taking 10 or 3 bytes from the beginning and end. -*/ -static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ - int i, mx, j; - int hasDigit = 0; - for(i=0; i='A' && c<='Z' ){ - zOut[i] = c - 'A' + 'a'; - }else{ - if( c>='0' && c<='9' ) hasDigit = 1; - zOut[i] = c; - } - } - mx = hasDigit ? 3 : 10; - if( nIn>mx*2 ){ - for(j=mx, i=nIn-mx; i=(int)sizeof(zReverse)-7 ){ - /* The word is too big or too small for the porter stemmer. - ** Fallback to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ - zReverse[j] = c + 'a' - 'A'; - }else if( c>='a' && c<='z' ){ - zReverse[j] = c; - }else{ - /* The use of a character not in [a-zA-Z] means that we fallback - ** to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - } - memset(&zReverse[sizeof(zReverse)-5], 0, 5); - z = &zReverse[j+1]; - - - /* Step 1a */ - if( z[0]=='s' ){ - if( - !stem(&z, "sess", "ss", 0) && - !stem(&z, "sei", "i", 0) && - !stem(&z, "ss", "ss", 0) - ){ - z++; - } - } - - /* Step 1b */ - z2 = z; - if( stem(&z, "dee", "ee", m_gt_0) ){ - /* Do nothing. The work was all in the test */ - }else if( - (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) - && z!=z2 - ){ - if( stem(&z, "ta", "ate", 0) || - stem(&z, "lb", "ble", 0) || - stem(&z, "zi", "ize", 0) ){ - /* Do nothing. The work was all in the test */ - }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ - z++; - }else if( m_eq_1(z) && star_oh(z) ){ - *(--z) = 'e'; - } - } - - /* Step 1c */ - if( z[0]=='y' && hasVowel(z+1) ){ - z[0] = 'i'; - } - - /* Step 2 */ - switch( z[1] ){ - case 'a': - if( !stem(&z, "lanoita", "ate", m_gt_0) ){ - stem(&z, "lanoit", "tion", m_gt_0); - } - break; - case 'c': - if( !stem(&z, "icne", "ence", m_gt_0) ){ - stem(&z, "icna", "ance", m_gt_0); - } - break; - case 'e': - stem(&z, "rezi", "ize", m_gt_0); - break; - case 'g': - stem(&z, "igol", "log", m_gt_0); - break; - case 'l': - if( !stem(&z, "ilb", "ble", m_gt_0) - && !stem(&z, "illa", "al", m_gt_0) - && !stem(&z, "iltne", "ent", m_gt_0) - && !stem(&z, "ile", "e", m_gt_0) - ){ - stem(&z, "ilsuo", "ous", m_gt_0); - } - break; - case 'o': - if( !stem(&z, "noitazi", "ize", m_gt_0) - && !stem(&z, "noita", "ate", m_gt_0) - ){ - stem(&z, "rota", "ate", m_gt_0); - } - break; - case 's': - if( !stem(&z, "msila", "al", m_gt_0) - && !stem(&z, "ssenevi", "ive", m_gt_0) - && !stem(&z, "ssenluf", "ful", m_gt_0) - ){ - stem(&z, "ssensuo", "ous", m_gt_0); - } - break; - case 't': - if( !stem(&z, "itila", "al", m_gt_0) - && !stem(&z, "itivi", "ive", m_gt_0) - ){ - stem(&z, "itilib", "ble", m_gt_0); - } - break; - } - - /* Step 3 */ - switch( z[0] ){ - case 'e': - if( !stem(&z, "etaci", "ic", m_gt_0) - && !stem(&z, "evita", "", m_gt_0) - ){ - stem(&z, "ezila", "al", m_gt_0); - } - break; - case 'i': - stem(&z, "itici", "ic", m_gt_0); - break; - case 'l': - if( !stem(&z, "laci", "ic", m_gt_0) ){ - stem(&z, "luf", "", m_gt_0); - } - break; - case 's': - stem(&z, "ssen", "", m_gt_0); - break; - } - - /* Step 4 */ - switch( z[1] ){ - case 'a': - if( z[0]=='l' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'c': - if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'e': - if( z[0]=='r' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'i': - if( z[0]=='c' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'l': - if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'n': - if( z[0]=='t' ){ - if( z[2]=='a' ){ - if( m_gt_1(z+3) ){ - z += 3; - } - }else if( z[2]=='e' ){ - if( !stem(&z, "tneme", "", m_gt_1) - && !stem(&z, "tnem", "", m_gt_1) - ){ - stem(&z, "tne", "", m_gt_1); - } - } - } - break; - case 'o': - if( z[0]=='u' ){ - if( m_gt_1(z+2) ){ - z += 2; - } - }else if( z[3]=='s' || z[3]=='t' ){ - stem(&z, "noi", "", m_gt_1); - } - break; - case 's': - if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 't': - if( !stem(&z, "eta", "", m_gt_1) ){ - stem(&z, "iti", "", m_gt_1); - } - break; - case 'u': - if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 'v': - case 'z': - if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - } - - /* Step 5a */ - if( z[0]=='e' ){ - if( m_gt_1(z+1) ){ - z++; - }else if( m_eq_1(z+1) && !star_oh(z+1) ){ - z++; - } - } - - /* Step 5b */ - if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ - z++; - } - - /* z[] is now the stemmed word in reverse order. Flip it back - ** around into forward order and return. - */ - *pnOut = i = (int)strlen(z); - zOut[i] = 0; - while( *z ){ - zOut[--i] = *(z++); - } -} - -/* -** Characters that can be part of a token. We assume any character -** whose value is greater than 0x80 (any UTF character) can be -** part of a token. In other words, delimiters all must have -** values of 0x7f or lower. -*/ -static const char porterIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ -}; -#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to porterOpen(). -*/ -static int porterNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ - const char **pzToken, /* OUT: *pzToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - const char *z = c->zInput; - - while( c->iOffsetnInput ){ - int iStartOffset, ch; - - /* Scan past delimiter characters */ - while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int n = c->iOffset-iStartOffset; - if( n>c->nAllocated ){ - char *pNew; - c->nAllocated = n+20; - pNew = sqlite3_realloc64(c->zToken, c->nAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->zToken = pNew; - } - porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); - *pzToken = c->zToken; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the porter-stemmer tokenizer -*/ -static const sqlite3_tokenizer_module porterTokenizerModule = { - 0, - porterCreate, - porterDestroy, - porterOpen, - porterClose, - porterNext, - 0 -}; - -/* -** Allocate a new porter tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &porterTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_porter.c *****************************************/ -/************** Begin file fts3_tokenizer.c **********************************/ -/* -** 2007 June 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is part of an SQLite module implementing full-text search. -** This particular file implements the generic tokenizer interface. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -/* -** Return true if the two-argument version of fts3_tokenizer() -** has been activated via a prior call to sqlite3_db_config(db, -** SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, 0); -*/ -static int fts3TokenizerEnabled(sqlite3_context *context){ - sqlite3 *db = sqlite3_context_db_handle(context); - int isEnabled = 0; - sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,-1,&isEnabled); - return isEnabled; -} - -/* -** Implementation of the SQL scalar function for accessing the underlying -** hash table. This function may be called as follows: -** -** SELECT (); -** SELECT (, ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer'). -** -** If the argument is specified, it must be a blob value -** containing a pointer to be stored as the hash data corresponding -** to the string . If is not specified, then -** the string must already exist in the has table. Otherwise, -** an error is returned. -** -** Whether or not the argument is specified, the value returned -** is a blob containing the pointer stored as the hash data corresponding -** to string (after the hash-table is updated, if applicable). -*/ -static void fts3TokenizerFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - void *pPtr = 0; - const unsigned char *zName; - int nName; - - assert( argc==1 || argc==2 ); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - - zName = sqlite3_value_text(argv[0]); - nName = sqlite3_value_bytes(argv[0])+1; - - if( argc==2 ){ - if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){ - void *pOld; - int n = sqlite3_value_bytes(argv[1]); - if( zName==0 || n!=sizeof(pPtr) ){ - sqlite3_result_error(context, "argument type mismatch", -1); - return; - } - pPtr = *(void **)sqlite3_value_blob(argv[1]); - pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); - if( pOld==pPtr ){ - sqlite3_result_error(context, "out of memory", -1); - } - }else{ - sqlite3_result_error(context, "fts3tokenize disabled", -1); - return; - } - }else{ - if( zName ){ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); - } - if( !pPtr ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - } - if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){ - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); - } -} - -SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){ - static const char isFtsIdChar[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ - }; - return (c&0x80 || isFtsIdChar[(int)(c)]); -} - -SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *zStr, int *pn){ - const char *z1; - const char *z2 = 0; - - /* Find the start of the next token. */ - z1 = zStr; - while( z2==0 ){ - char c = *z1; - switch( c ){ - case '\0': return 0; /* No more tokens here */ - case '\'': - case '"': - case '`': { - z2 = z1; - while( *++z2 && (*z2!=c || *++z2==c) ); - break; - } - case '[': - z2 = &z1[1]; - while( *z2 && z2[0]!=']' ) z2++; - if( *z2 ) z2++; - break; - - default: - if( sqlite3Fts3IsIdChar(*z1) ){ - z2 = &z1[1]; - while( sqlite3Fts3IsIdChar(*z2) ) z2++; - }else{ - z1++; - } - } - } - - *pn = (int)(z2-z1); - return z1; -} - -SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( - Fts3Hash *pHash, /* Tokenizer hash table */ - const char *zArg, /* Tokenizer name */ - sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */ - char **pzErr /* OUT: Set to malloced error message */ -){ - int rc; - char *z = (char *)zArg; - int n = 0; - char *zCopy; - char *zEnd; /* Pointer to nul-term of zCopy */ - sqlite3_tokenizer_module *m; - - zCopy = sqlite3_mprintf("%s", zArg); - if( !zCopy ) return SQLITE_NOMEM; - zEnd = &zCopy[strlen(zCopy)]; - - z = (char *)sqlite3Fts3NextToken(zCopy, &n); - if( z==0 ){ - assert( n==0 ); - z = zCopy; - } - z[n] = '\0'; - sqlite3Fts3Dequote(z); - - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); - if( !m ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z); - rc = SQLITE_ERROR; - }else{ - char const **aArg = 0; - int iArg = 0; - z = &z[n+1]; - while( zxCreate(iArg, aArg, ppTok); - assert( rc!=SQLITE_OK || *ppTok ); - if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); - }else{ - (*ppTok)->pModule = m; - } - sqlite3_free((void *)aArg); - } - - sqlite3_free(zCopy); - return rc; -} - - -#ifdef SQLITE_TEST - -#include "tclsqlite.h" -/* #include */ - -/* -** Implementation of a special SQL scalar function for testing tokenizers -** designed to be used in concert with the Tcl testing framework. This -** function must be called with two or more arguments: -** -** SELECT (, ..., ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') -** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). -** -** The return value is a string that may be interpreted as a Tcl -** list. For each token in the , three elements are -** added to the returned list. The first is the token position, the -** second is the token text (folded, stemmed, etc.) and the third is the -** substring of associated with the token. For example, -** using the built-in "simple" tokenizer: -** -** SELECT fts_tokenizer_test('simple', 'I don't see how'); -** -** will return the string: -** -** "{0 i I 1 dont don't 2 see see 3 how how}" -** -*/ -static void testFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - sqlite3_tokenizer_module *p; - sqlite3_tokenizer *pTokenizer = 0; - sqlite3_tokenizer_cursor *pCsr = 0; - - const char *zErr = 0; - - const char *zName; - int nName; - const char *zInput; - int nInput; - - const char *azArg[64]; - - const char *zToken; - int nToken = 0; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int i; - - Tcl_Obj *pRet; - - if( argc<2 ){ - sqlite3_result_error(context, "insufficient arguments", -1); - return; - } - - nName = sqlite3_value_bytes(argv[0]); - zName = (const char *)sqlite3_value_text(argv[0]); - nInput = sqlite3_value_bytes(argv[argc-1]); - zInput = (const char *)sqlite3_value_text(argv[argc-1]); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - - if( !p ){ - char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr2, -1); - sqlite3_free(zErr2); - return; - } - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - - for(i=1; ixCreate(argc-2, azArg, &pTokenizer) ){ - zErr = "error in xCreate()"; - goto finish; - } - pTokenizer->pModule = p; - if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ - zErr = "error in xOpen()"; - goto finish; - } - - while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ - Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - zToken = &zInput[iStart]; - nToken = iEnd-iStart; - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - } - - if( SQLITE_OK!=p->xClose(pCsr) ){ - zErr = "error in xClose()"; - goto finish; - } - if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ - zErr = "error in xDestroy()"; - goto finish; - } - -finish: - if( zErr ){ - sqlite3_result_error(context, zErr, -1); - }else{ - sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); - } - Tcl_DecrRefCount(pRet); -} - -static -int registerTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module *p -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; - - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); - sqlite3_step(pStmt); - - return sqlite3_finalize(pStmt); -} - - -static -int queryTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB - && sqlite3_column_bytes(pStmt, 0)==sizeof(*pp) - ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); - -/* -** Implementation of the scalar function fts3_tokenizer_internal_test(). -** This function is used for testing only, it is not included in the -** build unless SQLITE_TEST is defined. -** -** The purpose of this is to test that the fts3_tokenizer() function -** can be used as designed by the C-code in the queryTokenizer and -** registerTokenizer() functions above. These two functions are repeated -** in the README.tokenizer file as an example, so it is important to -** test them. -** -** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar -** function with no arguments. An assert() will fail if a problem is -** detected. i.e.: -** -** SELECT fts3_tokenizer_internal_test(); -** -*/ -static void intTestFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int rc; - const sqlite3_tokenizer_module *p1; - const sqlite3_tokenizer_module *p2; - sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - /* Test the query function */ - sqlite3Fts3SimpleTokenizerModule(&p1); - rc = queryTokenizer(db, "simple", &p2); - assert( rc==SQLITE_OK ); - assert( p1==p2 ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_ERROR ); - assert( p2==0 ); - assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); - - /* Test the storage function */ - if( fts3TokenizerEnabled(context) ){ - rc = registerTokenizer(db, "nosuchtokenizer", p1); - assert( rc==SQLITE_OK ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_OK ); - assert( p2==p1 ); - } - - sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); -} - -#endif - -/* -** Set up SQL objects in database db used to access the contents of -** the hash table pointed to by argument pHash. The hash table must -** been initialized to use string keys, and to take a private copy -** of the key when a value is inserted. i.e. by a call similar to: -** -** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); -** -** This function adds a scalar function (see header comment above -** fts3TokenizerFunc() in this file for details) and, if ENABLE_TABLE is -** defined at compilation time, a temporary virtual table (see header -** comment above struct HashTableVtab) to the database schema. Both -** provide read/write access to the contents of *pHash. -** -** The third argument to this function, zName, is used as the name -** of both the scalar and, if created, the virtual table. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitHashTable( - sqlite3 *db, - Fts3Hash *pHash, - const char *zName -){ - int rc = SQLITE_OK; - void *p = (void *)pHash; - const int any = SQLITE_UTF8|SQLITE_DIRECTONLY; - -#ifdef SQLITE_TEST - char *zTest = 0; - char *zTest2 = 0; - void *pdb = (void *)db; - zTest = sqlite3_mprintf("%s_test", zName); - zTest2 = sqlite3_mprintf("%s_internal_test", zName); - if( !zTest || !zTest2 ){ - rc = SQLITE_NOMEM; - } -#endif - - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 1, any, p, fts3TokenizerFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 2, any, p, fts3TokenizerFunc, 0, 0); - } -#ifdef SQLITE_TEST - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); - } -#endif - -#ifdef SQLITE_TEST - sqlite3_free(zTest); - sqlite3_free(zTest2); -#endif - - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer.c **************************************/ -/************** Begin file fts3_tokenizer1.c *********************************/ -/* -** 2006 Oct 10 -** -** 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. -** -****************************************************************************** -** -** Implementation of the "simple" full-text-search tokenizer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -/* #include "fts3_tokenizer.h" */ - -typedef struct simple_tokenizer { - sqlite3_tokenizer base; - char delim[128]; /* flag ASCII delimiters */ -} simple_tokenizer; - -typedef struct simple_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *pInput; /* input we are tokenizing */ - int nBytes; /* size of the input */ - int iOffset; /* current position in pInput */ - int iToken; /* index of next token to be returned */ - char *pToken; /* storage for current token */ - int nTokenAllocated; /* space allocated to zToken buffer */ -} simple_tokenizer_cursor; - - -static int simpleDelim(simple_tokenizer *t, unsigned char c){ - return c<0x80 && t->delim[c]; -} -static int fts3_isalnum(int x){ - return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z'); -} - -/* -** Create a new tokenizer instance. -*/ -static int simpleCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - simple_tokenizer *t; - - t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - - /* TODO(shess) Delimiters need to remain the same from run to run, - ** else we need to reindex. One solution would be a meta-table to - ** track such information in the database, then we'd only want this - ** information on the initial create. - */ - if( argc>1 ){ - int i, n = (int)strlen(argv[1]); - for(i=0; i=0x80 ){ - sqlite3_free(t); - return SQLITE_ERROR; - } - t->delim[ch] = 1; - } - } else { - /* Mark non-alphanumeric ASCII characters as delimiters */ - int i; - for(i=1; i<0x80; i++){ - t->delim[i] = !fts3_isalnum(i) ? -1 : 0; - } - } - - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int simpleOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *pInput, int nBytes, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - simple_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->pInput = pInput; - if( pInput==0 ){ - c->nBytes = 0; - }else if( nBytes<0 ){ - c->nBytes = (int)strlen(pInput); - }else{ - c->nBytes = nBytes; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->pToken = NULL; /* no space allocated, yet. */ - c->nTokenAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - sqlite3_free(c->pToken); - sqlite3_free(c); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int simpleNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; - unsigned char *p = (unsigned char *)c->pInput; - - while( c->iOffsetnBytes ){ - int iStartOffset; - - /* Scan past delimiter characters */ - while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int i, n = c->iOffset-iStartOffset; - if( n>c->nTokenAllocated ){ - char *pNew; - c->nTokenAllocated = n+20; - pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->pToken = pNew; - } - for(i=0; ipToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch); - } - *ppToken = c->pToken; - *pnBytes = n; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module simpleTokenizerModule = { - 0, - simpleCreate, - simpleDestroy, - simpleOpen, - simpleClose, - simpleNext, - 0, -}; - -/* -** Allocate a new simple tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &simpleTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer1.c *************************************/ -/************** Begin file fts3_tokenize_vtab.c ******************************/ -/* -** 2013 Apr 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 code for the "fts3tokenize" virtual table module. -** An fts3tokenize virtual table is created as follows: -** -** CREATE VIRTUAL TABLE USING fts3tokenize( -** , , ... -** ); -** -** The table created has the following schema: -** -** CREATE TABLE (input, token, start, end, position) -** -** When queried, the query must include a WHERE clause of type: -** -** input = -** -** The virtual table module tokenizes this , using the FTS3 -** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE -** statement and returns one row for each token in the result. With -** fields set as follows: -** -** input: Always set to a copy of -** token: A token from the input. -** start: Byte offset of the token within the input . -** end: Byte offset of the byte immediately following the end of the -** token within the input string. -** pos: Token offset of token within input. -** -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -typedef struct Fts3tokTable Fts3tokTable; -typedef struct Fts3tokCursor Fts3tokCursor; - -/* -** Virtual table structure. -*/ -struct Fts3tokTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - const sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer *pTok; -}; - -/* -** Virtual table cursor structure. -*/ -struct Fts3tokCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - char *zInput; /* Input string */ - sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */ - int iRowid; /* Current 'rowid' value */ - const char *zToken; /* Current 'token' value */ - int nToken; /* Size of zToken in bytes */ - int iStart; /* Current 'start' value */ - int iEnd; /* Current 'end' value */ - int iPos; /* Current 'pos' value */ -}; - -/* -** Query FTS for the tokenizer implementation named zName. -*/ -static int fts3tokQueryTokenizer( - Fts3Hash *pHash, - const char *zName, - const sqlite3_tokenizer_module **pp, - char **pzErr -){ - sqlite3_tokenizer_module *p; - int nName = (int)strlen(zName); - - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - if( !p ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName); - return SQLITE_ERROR; - } - - *pp = p; - return SQLITE_OK; -} - -/* -** The second argument, argv[], is an array of pointers to nul-terminated -** strings. This function makes a copy of the array and strings into a -** single block of memory. It then dequotes any of the strings that appear -** to be quoted. -** -** If successful, output parameter *pazDequote is set to point at the -** array of dequoted strings and SQLITE_OK is returned. The caller is -** responsible for eventually calling sqlite3_free() to free the array -** in this case. Or, if an error occurs, an SQLite error code is returned. -** The final value of *pazDequote is undefined in this case. -*/ -static int fts3tokDequoteArray( - int argc, /* Number of elements in argv[] */ - const char * const *argv, /* Input array */ - char ***pazDequote /* Output array */ -){ - int rc = SQLITE_OK; /* Return code */ - if( argc==0 ){ - *pazDequote = 0; - }else{ - int i; - int nByte = 0; - char **azDequote; - - for(i=0; i1 ) azArg = (const char * const *)&azDequote[1]; - rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok); - } - - if( rc==SQLITE_OK ){ - pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - memset(pTab, 0, sizeof(Fts3tokTable)); - pTab->pMod = pMod; - pTab->pTok = pTok; - *ppVtab = &pTab->base; - }else{ - if( pTok ){ - pMod->xDestroy(pTok); - } - } - - sqlite3_free(azDequote); - return rc; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3tokTable *pTab = (Fts3tokTable *)pVtab; - - pTab->pMod->xDestroy(pTab->pTok); - sqlite3_free(pTab); - return SQLITE_OK; -} - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3tokBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - UNUSED_PARAMETER(pVTab); - - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable - && pInfo->aConstraint[i].iColumn==0 - && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ - ){ - pInfo->idxNum = 1; - pInfo->aConstraintUsage[i].argvIndex = 1; - pInfo->aConstraintUsage[i].omit = 1; - pInfo->estimatedCost = 1; - return SQLITE_OK; - } - } - - pInfo->idxNum = 0; - assert( pInfo->estimatedCost>1000000.0 ); - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3tokCursor *pCsr; - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3tokCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Reset the tokenizer cursor passed as the only argument. As if it had -** just been returned by fts3tokOpenMethod(). -*/ -static void fts3tokResetCursor(Fts3tokCursor *pCsr){ - if( pCsr->pCsr ){ - Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab); - pTab->pMod->xClose(pCsr->pCsr); - pCsr->pCsr = 0; - } - sqlite3_free(pCsr->zInput); - pCsr->zInput = 0; - pCsr->zToken = 0; - pCsr->nToken = 0; - pCsr->iStart = 0; - pCsr->iEnd = 0; - pCsr->iPos = 0; - pCsr->iRowid = 0; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - fts3tokResetCursor(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - int rc; /* Return code */ - - pCsr->iRowid++; - rc = pTab->pMod->xNext(pCsr->pCsr, - &pCsr->zToken, &pCsr->nToken, - &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos - ); - - if( rc!=SQLITE_OK ){ - fts3tokResetCursor(pCsr); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3tokFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc = SQLITE_ERROR; - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - fts3tokResetCursor(pCsr); - if( idxNum==1 ){ - const char *zByte = (const char *)sqlite3_value_text(apVal[0]); - sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]); - pCsr->zInput = sqlite3_malloc64(nByte+1); - if( pCsr->zInput==0 ){ - rc = SQLITE_NOMEM; - }else{ - if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte); - pCsr->zInput[nByte] = 0; - rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr); - if( rc==SQLITE_OK ){ - pCsr->pCsr->pTokenizer = pTab->pTok; - } - } - } - - if( rc!=SQLITE_OK ) return rc; - return fts3tokNextMethod(pCursor); -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - return (pCsr->zToken==0); -} - -/* -** xColumn - Return a column value. -*/ -static int fts3tokColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - /* CREATE TABLE x(input, token, start, end, position) */ - switch( iCol ){ - case 0: - sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT); - break; - case 1: - sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT); - break; - case 2: - sqlite3_result_int(pCtx, pCsr->iStart); - break; - case 3: - sqlite3_result_int(pCtx, pCsr->iEnd); - break; - default: - assert( iCol==4 ); - sqlite3_result_int(pCtx, pCsr->iPos); - break; - } - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3tokRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - *pRowid = (sqlite3_int64)pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3tok module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){ - static const sqlite3_module fts3tok_module = { - 0, /* iVersion */ - fts3tokConnectMethod, /* xCreate */ - fts3tokConnectMethod, /* xConnect */ - fts3tokBestIndexMethod, /* xBestIndex */ - fts3tokDisconnectMethod, /* xDisconnect */ - fts3tokDisconnectMethod, /* xDestroy */ - fts3tokOpenMethod, /* xOpen */ - fts3tokCloseMethod, /* xClose */ - fts3tokFilterMethod, /* xFilter */ - fts3tokNextMethod, /* xNext */ - fts3tokEofMethod, /* xEof */ - fts3tokColumnMethod, /* xColumn */ - fts3tokRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module_v2( - db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy - ); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenize_vtab.c **********************************/ -/************** Begin file fts3_write.c **************************************/ -/* -** 2009 Oct 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 is part of the SQLite FTS3 extension module. Specifically, -** this file contains code to insert, update and delete rows from FTS3 -** tables. It also contains code to merge FTS3 b-tree segments. Some -** of the sub-routines used to merge segments are also used by the query -** code in fts3.c. -*/ - -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -#define FTS_MAX_APPENDABLE_HEIGHT 16 - -/* -** When full-text index nodes are loaded from disk, the buffer that they -** are loaded into has the following number of bytes of padding at the end -** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer -** of 920 bytes is allocated for it. -** -** This means that if we have a pointer into a buffer containing node data, -** it is always safe to read up to two varints from it without risking an -** overread, even if the node data is corrupted. -*/ -#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2) - -/* -** Under certain circumstances, b-tree nodes (doclists) can be loaded into -** memory incrementally instead of all at once. This can be a big performance -** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext() -** method before retrieving all query results (as may happen, for example, -** if a query has a LIMIT clause). -** -** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD -** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes. -** The code is written so that the hard lower-limit for each of these values -** is 1. Clearly such small values would be inefficient, but can be useful -** for testing purposes. -** -** If this module is built with SQLITE_TEST defined, these constants may -** be overridden at runtime for testing purposes. File fts3_test.c contains -** a Tcl interface to read and write the values. -*/ -#ifdef SQLITE_TEST -int test_fts3_node_chunksize = (4*1024); -int test_fts3_node_chunk_threshold = (4*1024)*4; -# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize -# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold -#else -# define FTS3_NODE_CHUNKSIZE (4*1024) -# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4) -#endif - -/* -** The values that may be meaningfully bound to the :1 parameter in -** statements SQL_REPLACE_STAT and SQL_SELECT_STAT. -*/ -#define FTS_STAT_DOCTOTAL 0 -#define FTS_STAT_INCRMERGEHINT 1 -#define FTS_STAT_AUTOINCRMERGE 2 - -/* -** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic -** and incremental merge operation that takes place. This is used for -** debugging FTS only, it should not usually be turned on in production -** systems. -*/ -#ifdef FTS3_LOG_MERGES -static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){ - sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel); -} -#else -#define fts3LogMerge(x, y) -#endif - - -typedef struct PendingList PendingList; -typedef struct SegmentNode SegmentNode; -typedef struct SegmentWriter SegmentWriter; - -/* -** An instance of the following data structure is used to build doclists -** incrementally. See function fts3PendingListAppend() for details. -*/ -struct PendingList { - int nData; - char *aData; - int nSpace; - sqlite3_int64 iLastDocid; - sqlite3_int64 iLastCol; - sqlite3_int64 iLastPos; -}; - - -/* -** Each cursor has a (possibly empty) linked list of the following objects. -*/ -struct Fts3DeferredToken { - Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */ - int iCol; /* Column token must occur in */ - Fts3DeferredToken *pNext; /* Next in list of deferred tokens */ - PendingList *pList; /* Doclist is assembled here */ -}; - -/* -** An instance of this structure is used to iterate through the terms on -** a contiguous set of segment b-tree leaf nodes. Although the details of -** this structure are only manipulated by code in this file, opaque handles -** of type Fts3SegReader* are also used by code in fts3.c to iterate through -** terms when querying the full-text index. See functions: -** -** sqlite3Fts3SegReaderNew() -** sqlite3Fts3SegReaderFree() -** sqlite3Fts3SegReaderIterate() -** -** Methods used to manipulate Fts3SegReader structures: -** -** fts3SegReaderNext() -** fts3SegReaderFirstDocid() -** fts3SegReaderNextDocid() -*/ -struct Fts3SegReader { - int iIdx; /* Index within level, or 0x7FFFFFFF for PT */ - u8 bLookup; /* True for a lookup only */ - u8 rootOnly; /* True for a root-only reader */ - - sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */ - sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */ - sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */ - sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */ - - char *aNode; /* Pointer to node data (or NULL) */ - int nNode; /* Size of buffer at aNode (or 0) */ - int nPopulate; /* If >0, bytes of buffer aNode[] loaded */ - sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */ - - Fts3HashElem **ppNextElem; - - /* Variables set by fts3SegReaderNext(). These may be read directly - ** by the caller. They are valid from the time SegmentReaderNew() returns - ** until SegmentReaderNext() returns something other than SQLITE_OK - ** (i.e. SQLITE_DONE). - */ - int nTerm; /* Number of bytes in current term */ - char *zTerm; /* Pointer to current term */ - int nTermAlloc; /* Allocated size of zTerm buffer */ - char *aDoclist; /* Pointer to doclist of current entry */ - int nDoclist; /* Size of doclist in current entry */ - - /* The following variables are used by fts3SegReaderNextDocid() to iterate - ** through the current doclist (aDoclist/nDoclist). - */ - char *pOffsetList; - int nOffsetList; /* For descending pending seg-readers only */ - sqlite3_int64 iDocid; -}; - -#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0) -#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0) - -/* -** An instance of this structure is used to create a segment b-tree in the -** database. The internal details of this type are only accessed by the -** following functions: -** -** fts3SegWriterAdd() -** fts3SegWriterFlush() -** fts3SegWriterFree() -*/ -struct SegmentWriter { - SegmentNode *pTree; /* Pointer to interior tree structure */ - sqlite3_int64 iFirst; /* First slot in %_segments written */ - sqlite3_int64 iFree; /* Next free slot in %_segments */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nSize; /* Size of allocation at aData */ - int nData; /* Bytes of data in aData */ - char *aData; /* Pointer to block from malloc() */ - i64 nLeafData; /* Number of bytes of leaf data written */ -}; - -/* -** Type SegmentNode is used by the following three functions to create -** the interior part of the segment b+-tree structures (everything except -** the leaf nodes). These functions and type are only ever used by code -** within the fts3SegWriterXXX() family of functions described above. -** -** fts3NodeAddTerm() -** fts3NodeWrite() -** fts3NodeFree() -** -** When a b+tree is written to the database (either as a result of a merge -** or the pending-terms table being flushed), leaves are written into the -** database file as soon as they are completely populated. The interior of -** the tree is assembled in memory and written out only once all leaves have -** been populated and stored. This is Ok, as the b+-tree fanout is usually -** very large, meaning that the interior of the tree consumes relatively -** little memory. -*/ -struct SegmentNode { - SegmentNode *pParent; /* Parent node (or NULL for root node) */ - SegmentNode *pRight; /* Pointer to right-sibling */ - SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */ - int nEntry; /* Number of terms written to node so far */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nData; /* Bytes of valid data so far */ - char *aData; /* Node data */ -}; - -/* -** Valid values for the second argument to fts3SqlStmt(). -*/ -#define SQL_DELETE_CONTENT 0 -#define SQL_IS_EMPTY 1 -#define SQL_DELETE_ALL_CONTENT 2 -#define SQL_DELETE_ALL_SEGMENTS 3 -#define SQL_DELETE_ALL_SEGDIR 4 -#define SQL_DELETE_ALL_DOCSIZE 5 -#define SQL_DELETE_ALL_STAT 6 -#define SQL_SELECT_CONTENT_BY_ROWID 7 -#define SQL_NEXT_SEGMENT_INDEX 8 -#define SQL_INSERT_SEGMENTS 9 -#define SQL_NEXT_SEGMENTS_ID 10 -#define SQL_INSERT_SEGDIR 11 -#define SQL_SELECT_LEVEL 12 -#define SQL_SELECT_LEVEL_RANGE 13 -#define SQL_SELECT_LEVEL_COUNT 14 -#define SQL_SELECT_SEGDIR_MAX_LEVEL 15 -#define SQL_DELETE_SEGDIR_LEVEL 16 -#define SQL_DELETE_SEGMENTS_RANGE 17 -#define SQL_CONTENT_INSERT 18 -#define SQL_DELETE_DOCSIZE 19 -#define SQL_REPLACE_DOCSIZE 20 -#define SQL_SELECT_DOCSIZE 21 -#define SQL_SELECT_STAT 22 -#define SQL_REPLACE_STAT 23 - -#define SQL_SELECT_ALL_PREFIX_LEVEL 24 -#define SQL_DELETE_ALL_TERMS_SEGDIR 25 -#define SQL_DELETE_SEGDIR_RANGE 26 -#define SQL_SELECT_ALL_LANGID 27 -#define SQL_FIND_MERGE_LEVEL 28 -#define SQL_MAX_LEAF_NODE_ESTIMATE 29 -#define SQL_DELETE_SEGDIR_ENTRY 30 -#define SQL_SHIFT_SEGDIR_ENTRY 31 -#define SQL_SELECT_SEGDIR 32 -#define SQL_CHOMP_SEGDIR 33 -#define SQL_SEGMENT_IS_APPENDABLE 34 -#define SQL_SELECT_INDEXES 35 -#define SQL_SELECT_MXLEVEL 36 - -#define SQL_SELECT_LEVEL_RANGE2 37 -#define SQL_UPDATE_LEVEL_IDX 38 -#define SQL_UPDATE_LEVEL 39 - -/* -** This function is used to obtain an SQLite prepared statement handle -** for the statement identified by the second argument. If successful, -** *pp is set to the requested statement handle and SQLITE_OK returned. -** Otherwise, an SQLite error code is returned and *pp is set to 0. -** -** If argument apVal is not NULL, then it must point to an array with -** at least as many entries as the requested statement has bound -** parameters. The values are bound to the statements parameters before -** returning. -*/ -static int fts3SqlStmt( - Fts3Table *p, /* Virtual table handle */ - int eStmt, /* One of the SQL_XXX constants above */ - sqlite3_stmt **pp, /* OUT: Statement handle */ - sqlite3_value **apVal /* Values to bind to statement */ -){ - const char *azSql[] = { -/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", -/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", -/* 2 */ "DELETE FROM %Q.'%q_content'", -/* 3 */ "DELETE FROM %Q.'%q_segments'", -/* 4 */ "DELETE FROM %Q.'%q_segdir'", -/* 5 */ "DELETE FROM %Q.'%q_docsize'", -/* 6 */ "DELETE FROM %Q.'%q_stat'", -/* 7 */ "SELECT %s WHERE rowid=?", -/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", -/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", -/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", -/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", - - /* Return segments in order from oldest to newest.*/ -/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", -/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?" - "ORDER BY level DESC, idx ASC", - -/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", -/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", - -/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", -/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", -/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", -/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", -/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", -/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", -/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", -/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", -/* 24 */ "", -/* 25 */ "", - -/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", - -/* This statement is used to determine which level to read the input from -** when performing an incremental merge. It returns the absolute level number -** of the oldest level in the db that contains at least ? segments. Or, -** if no level in the FTS index contains more than ? segments, the statement -** returns zero rows. */ -/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' " - " GROUP BY level HAVING cnt>=?" - " ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1", - -/* Estimate the upper limit on the number of leaf nodes in a new segment -** created by merging the oldest :2 segments from absolute level :1. See -** function sqlite3Fts3Incrmerge() for details. */ -/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) " - " FROM (SELECT * FROM %Q.'%q_segdir' " - " WHERE level = ? ORDER BY idx ASC LIMIT ?" - " )", - -/* SQL_DELETE_SEGDIR_ENTRY -** Delete the %_segdir entry on absolute level :1 with index :2. */ -/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_SHIFT_SEGDIR_ENTRY -** Modify the idx value for the segment with idx=:3 on absolute level :2 -** to :1. */ -/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", - -/* SQL_SELECT_SEGDIR -** Read a single entry from the %_segdir table. The entry from absolute -** level :1 with index value :2. */ -/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_CHOMP_SEGDIR -** Update the start_block (:1) and root (:2) fields of the %_segdir -** entry located on absolute level :3 with index :4. */ -/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?" - "WHERE level = ? AND idx = ?", - -/* SQL_SEGMENT_IS_APPENDABLE -** Return a single row if the segment with end_block=? is appendable. Or -** no rows otherwise. */ -/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL", - -/* SQL_SELECT_INDEXES -** Return the list of valid segment indexes for absolute level ? */ -/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC", - -/* SQL_SELECT_MXLEVEL -** Return the largest relative level in the FTS index or indexes. */ -/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'", - - /* Return segments in order from oldest to newest.*/ -/* 37 */ "SELECT level, idx, end_block " - "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? " - "ORDER BY level DESC, idx ASC", - - /* Update statements used while promoting segments */ -/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? " - "WHERE level=? AND idx=?", -/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1" - - }; - int rc = SQLITE_OK; - sqlite3_stmt *pStmt; - - assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); - assert( eStmt=0 ); - - pStmt = p->aStmt[eStmt]; - if( !pStmt ){ - int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB; - char *zSql; - if( eStmt==SQL_CONTENT_INSERT ){ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); - }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - f &= ~SQLITE_PREPARE_NO_VTAB; - zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); - }else{ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); - } - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL); - sqlite3_free(zSql); - assert( rc==SQLITE_OK || pStmt==0 ); - p->aStmt[eStmt] = pStmt; - } - } - if( apVal ){ - int i; - int nParam = sqlite3_bind_parameter_count(pStmt); - for(i=0; rc==SQLITE_OK && inPendingData==0 ){ - sqlite3_stmt *pStmt; - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_null(pStmt, 1); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - } - } - - return rc; -} - -/* -** FTS maintains a separate indexes for each language-id (a 32-bit integer). -** Within each language id, a separate index is maintained to store the -** document terms, and each configured prefix size (configured the FTS -** "prefix=" option). And each index consists of multiple levels ("relative -** levels"). -** -** All three of these values (the language id, the specific index and the -** level within the index) are encoded in 64-bit integer values stored -** in the %_segdir table on disk. This function is used to convert three -** separate component values into the single 64-bit integer value that -** can be used to query the %_segdir table. -** -** Specifically, each language-id/index combination is allocated 1024 -** 64-bit integer level values ("absolute levels"). The main terms index -** for language-id 0 is allocate values 0-1023. The first prefix index -** (if any) for language-id 0 is allocated values 1024-2047. And so on. -** Language 1 indexes are allocated immediately following language 0. -** -** So, for a system with nPrefix prefix indexes configured, the block of -** absolute levels that corresponds to language-id iLangid and index -** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024). -*/ -static sqlite3_int64 getAbsoluteLevel( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index in p->aIndex[] */ - int iLevel /* Level of segments */ -){ - sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */ - assert_fts3_nc( iLangid>=0 ); - assert( p->nIndex>0 ); - assert( iIndex>=0 && iIndexnIndex ); - - iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL; - return iBase + iLevel; -} - -/* -** Set *ppStmt to a statement handle that may be used to iterate through -** all rows in the %_segdir table, from oldest to newest. If successful, -** return SQLITE_OK. If an error occurs while preparing the statement, -** return an SQLite error code. -** -** There is only ever one instance of this SQL statement compiled for -** each FTS3 table. -** -** The statement returns the following columns from the %_segdir table: -** -** 0: idx -** 1: start_block -** 2: leaves_end_block -** 3: end_block -** 4: root -*/ -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( - Fts3Table *p, /* FTS3 table */ - int iLangid, /* Language being queried */ - int iIndex, /* Index for p->aIndex[] */ - int iLevel, /* Level to select (relative level) */ - sqlite3_stmt **ppStmt /* OUT: Compiled statement */ -){ - int rc; - sqlite3_stmt *pStmt = 0; - - assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 ); - assert( iLevel=0 && iIndexnIndex ); - - if( iLevel<0 ){ - /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); - } - } - *ppStmt = pStmt; - return rc; -} - - -/* -** Append a single varint to a PendingList buffer. SQLITE_OK is returned -** if successful, or an SQLite error code otherwise. -** -** This function also serves to allocate the PendingList structure itself. -** For example, to create a new PendingList structure containing two -** varints: -** -** PendingList *p = 0; -** fts3PendingListAppendVarint(&p, 1); -** fts3PendingListAppendVarint(&p, 2); -*/ -static int fts3PendingListAppendVarint( - PendingList **pp, /* IN/OUT: Pointer to PendingList struct */ - sqlite3_int64 i /* Value to append to data */ -){ - PendingList *p = *pp; - - /* Allocate or grow the PendingList as required. */ - if( !p ){ - p = sqlite3_malloc64(sizeof(*p) + 100); - if( !p ){ - return SQLITE_NOMEM; - } - p->nSpace = 100; - p->aData = (char *)&p[1]; - p->nData = 0; - } - else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - i64 nNew = p->nSpace * 2; - p = sqlite3_realloc64(p, sizeof(*p) + nNew); - if( !p ){ - sqlite3_free(*pp); - *pp = 0; - return SQLITE_NOMEM; - } - p->nSpace = (int)nNew; - p->aData = (char *)&p[1]; - } - - /* Append the new serialized varint to the end of the list. */ - p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i); - p->aData[p->nData] = '\0'; - *pp = p; - return SQLITE_OK; -} - -/* -** Add a docid/column/position entry to a PendingList structure. Non-zero -** is returned if the structure is sqlite3_realloced as part of adding -** the entry. Otherwise, zero. -** -** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning. -** Zero is always returned in this case. Otherwise, if no OOM error occurs, -** it is set to SQLITE_OK. -*/ -static int fts3PendingListAppend( - PendingList **pp, /* IN/OUT: PendingList structure */ - sqlite3_int64 iDocid, /* Docid for entry to add */ - sqlite3_int64 iCol, /* Column for entry to add */ - sqlite3_int64 iPos, /* Position of term for entry to add */ - int *pRc /* OUT: Return code */ -){ - PendingList *p = *pp; - int rc = SQLITE_OK; - - assert( !p || p->iLastDocid<=iDocid ); - - if( !p || p->iLastDocid!=iDocid ){ - u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0); - if( p ){ - assert( p->nDatanSpace ); - assert( p->aData[p->nData]==0 ); - p->nData++; - } - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){ - goto pendinglistappend_out; - } - p->iLastCol = -1; - p->iLastPos = 0; - p->iLastDocid = iDocid; - } - if( iCol>0 && p->iLastCol!=iCol ){ - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1)) - || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol)) - ){ - goto pendinglistappend_out; - } - p->iLastCol = iCol; - p->iLastPos = 0; - } - if( iCol>=0 ){ - assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); - rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); - if( rc==SQLITE_OK ){ - p->iLastPos = iPos; - } - } - - pendinglistappend_out: - *pRc = rc; - if( p!=*pp ){ - *pp = p; - return 1; - } - return 0; -} - -/* -** Free a PendingList object allocated by fts3PendingListAppend(). -*/ -static void fts3PendingListDelete(PendingList *pList){ - sqlite3_free(pList); -} - -/* -** Add an entry to one of the pending-terms hash tables. -*/ -static int fts3PendingTermsAddOne( - Fts3Table *p, - int iCol, - int iPos, - Fts3Hash *pHash, /* Pending terms hash table to add entry to */ - const char *zToken, - int nToken -){ - PendingList *pList; - int rc = SQLITE_OK; - - pList = (PendingList *)fts3HashFind(pHash, zToken, nToken); - if( pList ){ - p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); - } - if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ - if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ - /* Malloc failed while inserting the new entry. This can only - ** happen if there was no previous entry for this token. - */ - assert( 0==fts3HashFind(pHash, zToken, nToken) ); - sqlite3_free(pList); - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK ){ - p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); - } - return rc; -} - -/* -** Tokenize the nul-terminated string zText and add all tokens to the -** pending-terms hash-table. The docid used is that currently stored in -** p->iPrevDocid, and the column is specified by argument iCol. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3PendingTermsAdd( - Fts3Table *p, /* Table into which text will be inserted */ - int iLangid, /* Language id to use */ - const char *zText, /* Text of document to be inserted */ - int iCol, /* Column into which text is being inserted */ - u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */ -){ - int rc; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int nWord = 0; - - char const *zToken; - int nToken = 0; - - sqlite3_tokenizer *pTokenizer = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr; - int (*xNext)(sqlite3_tokenizer_cursor *pCursor, - const char**,int*,int*,int*,int*); - - assert( pTokenizer && pModule ); - - /* If the user has inserted a NULL value, this function may be called with - ** zText==0. In this case, add zero token entries to the hash table and - ** return early. */ - if( zText==0 ){ - *pnWord = 0; - return SQLITE_OK; - } - - rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); - if( rc!=SQLITE_OK ){ - return rc; - } - - xNext = pModule->xNext; - while( SQLITE_OK==rc - && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) - ){ - int i; - if( iPos>=nWord ) nWord = iPos+1; - - /* Positions cannot be negative; we use -1 as a terminator internally. - ** Tokens must have a non-zero length. - */ - if( iPos<0 || !zToken || nToken<=0 ){ - rc = SQLITE_ERROR; - break; - } - - /* Add the term to the terms index */ - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken - ); - - /* Add the term to each of the prefix indexes that it is not too - ** short for. */ - for(i=1; rc==SQLITE_OK && inIndex; i++){ - struct Fts3Index *pIndex = &p->aIndex[i]; - if( nTokennPrefix ) continue; - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix - ); - } - } - - pModule->xClose(pCsr); - *pnWord += nWord; - return (rc==SQLITE_DONE ? SQLITE_OK : rc); -} - -/* -** Calling this function indicates that subsequent calls to -** fts3PendingTermsAdd() are to add term/position-list pairs for the -** contents of the document with docid iDocid. -*/ -static int fts3PendingTermsDocid( - Fts3Table *p, /* Full-text table handle */ - int bDelete, /* True if this op is a delete */ - int iLangid, /* Language id of row being written */ - sqlite_int64 iDocid /* Docid of row being written */ -){ - assert( iLangid>=0 ); - assert( bDelete==1 || bDelete==0 ); - - /* TODO(shess) Explore whether partially flushing the buffer on - ** forced-flush would provide better performance. I suspect that if - ** we ordered the doclists by size and flushed the largest until the - ** buffer was half empty, that would let the less frequent terms - ** generate longer doclists. - */ - if( iDocidiPrevDocid - || (iDocid==p->iPrevDocid && p->bPrevDelete==0) - || p->iPrevLangid!=iLangid - || p->nPendingData>p->nMaxPendingData - ){ - int rc = sqlite3Fts3PendingTermsFlush(p); - if( rc!=SQLITE_OK ) return rc; - } - p->iPrevDocid = iDocid; - p->iPrevLangid = iLangid; - p->bPrevDelete = bDelete; - return SQLITE_OK; -} - -/* -** Discard the contents of the pending-terms hash tables. -*/ -SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){ - int i; - for(i=0; inIndex; i++){ - Fts3HashElem *pElem; - Fts3Hash *pHash = &p->aIndex[i].hPending; - for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){ - PendingList *pList = (PendingList *)fts3HashData(pElem); - fts3PendingListDelete(pList); - } - fts3HashClear(pHash); - } - p->nPendingData = 0; -} - -/* -** This function is called by the xUpdate() method as part of an INSERT -** operation. It adds entries for each term in the new record to the -** pendingTerms hash table. -** -** Argument apVal is the same as the similarly named argument passed to -** fts3InsertData(). Parameter iDocid is the docid of the new row. -*/ -static int fts3InsertTerms( - Fts3Table *p, - int iLangid, - sqlite3_value **apVal, - u32 *aSz -){ - int i; /* Iterator variable */ - for(i=2; inColumn+2; i++){ - int iCol = i-2; - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_value_text(apVal[i]); - int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]); - if( rc!=SQLITE_OK ){ - return rc; - } - aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); - } - } - return SQLITE_OK; -} - -/* -** This function is called by the xUpdate() method for an INSERT operation. -** The apVal parameter is passed a copy of the apVal argument passed by -** SQLite to the xUpdate() method. i.e: -** -** apVal[0] Not used for INSERT. -** apVal[1] rowid -** apVal[2] Left-most user-defined column -** ... -** apVal[p->nColumn+1] Right-most user-defined column -** apVal[p->nColumn+2] Hidden column with same name as table -** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) -** apVal[p->nColumn+4] Hidden languageid column -*/ -static int fts3InsertData( - Fts3Table *p, /* Full-text table */ - sqlite3_value **apVal, /* Array of values to insert */ - sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ -){ - int rc; /* Return code */ - sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ - - if( p->zContentTbl ){ - sqlite3_value *pRowid = apVal[p->nColumn+3]; - if( sqlite3_value_type(pRowid)==SQLITE_NULL ){ - pRowid = apVal[1]; - } - if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){ - return SQLITE_CONSTRAINT; - } - *piDocid = sqlite3_value_int64(pRowid); - return SQLITE_OK; - } - - /* Locate the statement handle used to insert data into the %_content - ** table. The SQL for this statement is: - ** - ** INSERT INTO %_content VALUES(?, ?, ?, ...) - ** - ** The statement features N '?' variables, where N is the number of user - ** defined columns in the FTS3 table, plus one for the docid field. - */ - rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); - if( rc==SQLITE_OK && p->zLanguageid ){ - rc = sqlite3_bind_int( - pContentInsert, p->nColumn+2, - sqlite3_value_int(apVal[p->nColumn+4]) - ); - } - if( rc!=SQLITE_OK ) return rc; - - /* There is a quirk here. The users INSERT statement may have specified - ** a value for the "rowid" field, for the "docid" field, or for both. - ** Which is a problem, since "rowid" and "docid" are aliases for the - ** same value. For example: - ** - ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); - ** - ** In FTS3, this is an error. It is an error to specify non-NULL values - ** for both docid and some other rowid alias. - */ - if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ - if( SQLITE_NULL==sqlite3_value_type(apVal[0]) - && SQLITE_NULL!=sqlite3_value_type(apVal[1]) - ){ - /* A rowid/docid conflict. */ - return SQLITE_ERROR; - } - rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); - if( rc!=SQLITE_OK ) return rc; - } - - /* Execute the statement to insert the record. Set *piDocid to the - ** new docid value. - */ - sqlite3_step(pContentInsert); - rc = sqlite3_reset(pContentInsert); - - *piDocid = sqlite3_last_insert_rowid(p->db); - return rc; -} - - - -/* -** Remove all data from the FTS3 table. Clear the hash table containing -** pending terms. -*/ -static int fts3DeleteAll(Fts3Table *p, int bContent){ - int rc = SQLITE_OK; /* Return code */ - - /* Discard the contents of the pending-terms hash table. */ - sqlite3Fts3PendingTermsClear(p); - - /* Delete everything from the shadow tables. Except, leave %_content as - ** is if bContent is false. */ - assert( p->zContentTbl==0 || bContent==0 ); - if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); - } - if( p->bHasStat ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); - } - return rc; -} - -/* -** -*/ -static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ - int iLangid = 0; - if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); - return iLangid; -} - -/* -** The first element in the apVal[] array is assumed to contain the docid -** (an integer) of a row about to be deleted. Remove all terms from the -** full-text index. -*/ -static void fts3DeleteTerms( - int *pRC, /* Result code */ - Fts3Table *p, /* The FTS table to delete from */ - sqlite3_value *pRowid, /* The docid to be deleted */ - u32 *aSz, /* Sizes of deleted document written here */ - int *pbFound /* OUT: Set to true if row really does exist */ -){ - int rc; - sqlite3_stmt *pSelect; - - assert( *pbFound==0 ); - if( *pRC ) return; - rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - int i; - int iLangid = langidFromSelect(p, pSelect); - i64 iDocid = sqlite3_column_int64(pSelect, 0); - rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); - for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ - int iCol = i-1; - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pSelect, i); - rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); - aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); - } - } - if( rc!=SQLITE_OK ){ - sqlite3_reset(pSelect); - *pRC = rc; - return; - } - *pbFound = 1; - } - rc = sqlite3_reset(pSelect); - }else{ - sqlite3_reset(pSelect); - } - *pRC = rc; -} - -/* -** Forward declaration to account for the circular dependency between -** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). -*/ -static int fts3SegmentMerge(Fts3Table *, int, int, int); - -/* -** This function allocates a new level iLevel index in the segdir table. -** Usually, indexes are allocated within a level sequentially starting -** with 0, so the allocated index is one greater than the value returned -** by: -** -** SELECT max(idx) FROM %_segdir WHERE level = :iLevel -** -** However, if there are already FTS3_MERGE_COUNT indexes at the requested -** level, they are merged into a single level (iLevel+1) segment and the -** allocated index is 0. -** -** If successful, *piIdx is set to the allocated index slot and SQLITE_OK -** returned. Otherwise, an SQLite error code is returned. -*/ -static int fts3AllocateSegdirIdx( - Fts3Table *p, - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, - int *piIdx -){ - int rc; /* Return Code */ - sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ - int iNext = 0; /* Result of query pNextIdx */ - - assert( iLangid>=0 ); - assert( p->nIndex>=1 ); - - /* Set variable iNext to the next available segdir index at level iLevel. */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ - iNext = sqlite3_column_int(pNextIdx, 0); - } - rc = sqlite3_reset(pNextIdx); - } - - if( rc==SQLITE_OK ){ - /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already - ** full, merge all segments in level iLevel into a single iLevel+1 - ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, - ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. - */ - if( iNext>=MergeCount(p) ){ - fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); - rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); - *piIdx = 0; - }else{ - *piIdx = iNext; - } - } - - return rc; -} - -/* -** The %_segments table is declared as follows: -** -** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB) -** -** This function reads data from a single row of the %_segments table. The -** specific row is identified by the iBlockid parameter. If paBlob is not -** NULL, then a buffer is allocated using sqlite3_malloc() and populated -** with the contents of the blob stored in the "block" column of the -** identified table row is. Whether or not paBlob is NULL, *pnBlob is set -** to the size of the blob in bytes before returning. -** -** If an error occurs, or the table does not contain the specified row, -** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If -** paBlob is non-NULL, then it is the responsibility of the caller to -** eventually free the returned buffer. -** -** This function may leave an open sqlite3_blob* handle in the -** Fts3Table.pSegments variable. This handle is reused by subsequent calls -** to this function. The handle may be closed by calling the -** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy -** performance improvement, but the blob handle should always be closed -** before control is returned to the user (to prevent a lock being held -** on the database file for longer than necessary). Thus, any virtual table -** method (xFilter etc.) that may directly or indirectly call this function -** must call sqlite3Fts3SegmentsClose() before returning. -*/ -SQLITE_PRIVATE int sqlite3Fts3ReadBlock( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */ - char **paBlob, /* OUT: Blob data in malloc'd buffer */ - int *pnBlob, /* OUT: Size of blob data */ - int *pnLoad /* OUT: Bytes actually loaded */ -){ - int rc; /* Return code */ - - /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */ - assert( pnBlob ); - - if( p->pSegments ){ - rc = sqlite3_blob_reopen(p->pSegments, iBlockid); - }else{ - if( 0==p->zSegmentsTbl ){ - p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName); - if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM; - } - rc = sqlite3_blob_open( - p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments - ); - } - - if( rc==SQLITE_OK ){ - int nByte = sqlite3_blob_bytes(p->pSegments); - *pnBlob = nByte; - if( paBlob ){ - char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING); - if( !aByte ){ - rc = SQLITE_NOMEM; - }else{ - if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){ - nByte = FTS3_NODE_CHUNKSIZE; - *pnLoad = nByte; - } - rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0); - memset(&aByte[nByte], 0, FTS3_NODE_PADDING); - if( rc!=SQLITE_OK ){ - sqlite3_free(aByte); - aByte = 0; - } - } - *paBlob = aByte; - } - }else if( rc==SQLITE_ERROR ){ - rc = FTS_CORRUPT_VTAB; - } - - return rc; -} - -/* -** Close the blob handle at p->pSegments, if it is open. See comments above -** the sqlite3Fts3ReadBlock() function for details. -*/ -SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){ - sqlite3_blob_close(p->pSegments); - p->pSegments = 0; -} - -static int fts3SegReaderIncrRead(Fts3SegReader *pReader){ - int nRead; /* Number of bytes to read */ - int rc; /* Return code */ - - nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE); - rc = sqlite3_blob_read( - pReader->pBlob, - &pReader->aNode[pReader->nPopulate], - nRead, - pReader->nPopulate - ); - - if( rc==SQLITE_OK ){ - pReader->nPopulate += nRead; - memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING); - if( pReader->nPopulate==pReader->nNode ){ - sqlite3_blob_close(pReader->pBlob); - pReader->pBlob = 0; - pReader->nPopulate = 0; - } - } - return rc; -} - -static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){ - int rc = SQLITE_OK; - assert( !pReader->pBlob - || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode]) - ); - while( pReader->pBlob && rc==SQLITE_OK - && (pFrom - pReader->aNode + nByte)>pReader->nPopulate - ){ - rc = fts3SegReaderIncrRead(pReader); - } - return rc; -} - -/* -** Set an Fts3SegReader cursor to point at EOF. -*/ -static void fts3SegReaderSetEof(Fts3SegReader *pSeg){ - if( !fts3SegReaderIsRootOnly(pSeg) ){ - sqlite3_free(pSeg->aNode); - sqlite3_blob_close(pSeg->pBlob); - pSeg->pBlob = 0; - } - pSeg->aNode = 0; -} - -/* -** Move the iterator passed as the first argument to the next term in the -** segment. If successful, SQLITE_OK is returned. If there is no next term, -** SQLITE_DONE. Otherwise, an SQLite error code. -*/ -static int fts3SegReaderNext( - Fts3Table *p, - Fts3SegReader *pReader, - int bIncr -){ - int rc; /* Return code of various sub-routines */ - char *pNext; /* Cursor variable */ - int nPrefix; /* Number of bytes in term prefix */ - int nSuffix; /* Number of bytes in term suffix */ - - if( !pReader->aDoclist ){ - pNext = pReader->aNode; - }else{ - pNext = &pReader->aDoclist[pReader->nDoclist]; - } - - if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ - - if( fts3SegReaderIsPending(pReader) ){ - Fts3HashElem *pElem = *(pReader->ppNextElem); - sqlite3_free(pReader->aNode); - pReader->aNode = 0; - if( pElem ){ - char *aCopy; - PendingList *pList = (PendingList *)fts3HashData(pElem); - int nCopy = pList->nData+1; - - int nTerm = fts3HashKeysize(pElem); - if( (nTerm+1)>pReader->nTermAlloc ){ - sqlite3_free(pReader->zTerm); - pReader->zTerm = (char*)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*)sqlite3_malloc64(nCopy); - if( !aCopy ) return SQLITE_NOMEM; - memcpy(aCopy, pList->aData, nCopy); - pReader->nNode = pReader->nDoclist = nCopy; - pReader->aNode = pReader->aDoclist = aCopy; - pReader->ppNextElem++; - assert( pReader->aNode ); - } - return SQLITE_OK; - } - - fts3SegReaderSetEof(pReader); - - /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf - ** blocks have already been traversed. */ -#ifdef CORRUPT_DB - assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB ); -#endif - if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){ - return SQLITE_OK; - } - - rc = sqlite3Fts3ReadBlock( - p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, - (bIncr ? &pReader->nPopulate : 0) - ); - if( rc!=SQLITE_OK ) return rc; - assert( pReader->pBlob==0 ); - if( bIncr && pReader->nPopulatenNode ){ - pReader->pBlob = p->pSegments; - p->pSegments = 0; - } - pNext = pReader->aNode; - } - - assert( !fts3SegReaderIsPending(pReader) ); - - rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2); - if( rc!=SQLITE_OK ) return rc; - - /* Because of the FTS3_NODE_PADDING bytes of padding, the following is - ** safe (no risk of overread) even if the node data is corrupted. */ - pNext += fts3GetVarint32(pNext, &nPrefix); - pNext += fts3GetVarint32(pNext, &nSuffix); - if( nSuffix<=0 - || (&pReader->aNode[pReader->nNode] - pNext)pReader->nTerm - ){ - return FTS_CORRUPT_VTAB; - } - - /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are - ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer - ** overflow - hence the (i64) casts. */ - if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){ - i64 nNew = ((i64)nPrefix+nSuffix)*2; - char *zNew = sqlite3_realloc64(pReader->zTerm, nNew); - if( !zNew ){ - return SQLITE_NOMEM; - } - pReader->zTerm = zNew; - pReader->nTermAlloc = nNew; - } - - rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX); - if( rc!=SQLITE_OK ) return rc; - - memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix); - pReader->nTerm = nPrefix+nSuffix; - pNext += nSuffix; - pNext += fts3GetVarint32(pNext, &pReader->nDoclist); - pReader->aDoclist = pNext; - pReader->pOffsetList = 0; - - /* Check that the doclist does not appear to extend past the end of the - ** b-tree node. And that the final byte of the doclist is 0x00. If either - ** of these statements is untrue, then the data structure is corrupt. - */ - if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode) - || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) - || pReader->nDoclist==0 - ){ - return FTS_CORRUPT_VTAB; - } - return SQLITE_OK; -} - -/* -** Set the SegReader to point to the first docid in the doclist associated -** with the current term. -*/ -static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){ - int rc = SQLITE_OK; - assert( pReader->aDoclist ); - assert( !pReader->pOffsetList ); - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - u8 bEof = 0; - pReader->iDocid = 0; - pReader->nOffsetList = 0; - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, - &pReader->iDocid, &pReader->nOffsetList, &bEof - ); - }else{ - rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid); - pReader->pOffsetList = &pReader->aDoclist[n]; - } - } - return rc; -} - -/* -** Advance the SegReader to point to the next docid in the doclist -** associated with the current term. -** -** If arguments ppOffsetList and pnOffsetList are not NULL, then -** *ppOffsetList is set to point to the first column-offset list -** in the doclist entry (i.e. immediately past the docid varint). -** *pnOffsetList is set to the length of the set of column-offset -** lists, not including the nul-terminator byte. For example: -*/ -static int fts3SegReaderNextDocid( - Fts3Table *pTab, - Fts3SegReader *pReader, /* Reader to advance to next docid */ - char **ppOffsetList, /* OUT: Pointer to current position-list */ - int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */ -){ - int rc = SQLITE_OK; - char *p = pReader->pOffsetList; - char c = 0; - - assert( p ); - - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - /* A pending-terms seg-reader for an FTS4 table that uses order=desc. - ** Pending-terms doclists are always built up in ascending order, so - ** we have to iterate through them backwards here. */ - u8 bEof = 0; - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = pReader->nOffsetList - 1; - } - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid, - &pReader->nOffsetList, &bEof - ); - if( bEof ){ - pReader->pOffsetList = 0; - }else{ - pReader->pOffsetList = p; - } - }else{ - char *pEnd = &pReader->aDoclist[pReader->nDoclist]; - - /* Pointer p currently points at the first byte of an offset list. The - ** following block advances it to point one byte past the end of - ** the same offset list. */ - while( 1 ){ - - /* The following line of code (and the "p++" below the while() loop) is - ** normally all that is required to move pointer p to the desired - ** position. The exception is if this node is being loaded from disk - ** incrementally and pointer "p" now points to the first byte past - ** the populated part of pReader->aNode[]. - */ - while( *p | c ) c = *p++ & 0x80; - assert( *p==0 ); - - if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break; - rc = fts3SegReaderIncrRead(pReader); - if( rc!=SQLITE_OK ) return rc; - } - p++; - - /* If required, populate the output variables with a pointer to and the - ** size of the previous offset-list. - */ - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = (int)(p - pReader->pOffsetList - 1); - } - - /* List may have been edited in place by fts3EvalNearTrim() */ - while( p=pEnd ){ - pReader->pOffsetList = 0; - }else{ - rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - u64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta); - if( pTab->bDescIdx ){ - pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta); - }else{ - pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta); - } - } - } - } - - return rc; -} - - -SQLITE_PRIVATE int sqlite3Fts3MsrOvfl( - Fts3Cursor *pCsr, - Fts3MultiSegReader *pMsr, - int *pnOvfl -){ - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - int nOvfl = 0; - int ii; - int rc = SQLITE_OK; - int pgsz = p->nPgsz; - - assert( p->bFts4 ); - assert( pgsz>0 ); - - for(ii=0; rc==SQLITE_OK && iinSegment; ii++){ - Fts3SegReader *pReader = pMsr->apSegment[ii]; - if( !fts3SegReaderIsPending(pReader) - && !fts3SegReaderIsRootOnly(pReader) - ){ - sqlite3_int64 jj; - for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){ - int nBlob; - rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0); - if( rc!=SQLITE_OK ) break; - if( (nBlob+35)>pgsz ){ - nOvfl += (nBlob + 34)/pgsz; - } - } - } - } - *pnOvfl = nOvfl; - return rc; -} - -/* -** Free all allocations associated with the iterator passed as the -** second argument. -*/ -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ - if( pReader ){ - sqlite3_free(pReader->zTerm); - if( !fts3SegReaderIsRootOnly(pReader) ){ - sqlite3_free(pReader->aNode); - } - sqlite3_blob_close(pReader->pBlob); - } - sqlite3_free(pReader); -} - -/* -** Allocate a new SegReader object. -*/ -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( - int iAge, /* Segment "age". */ - int bLookup, /* True for a lookup only */ - sqlite3_int64 iStartLeaf, /* First leaf to traverse */ - sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ - sqlite3_int64 iEndBlock, /* Final block of segment */ - const char *zRoot, /* Buffer containing root node */ - int nRoot, /* Size of buffer containing root node */ - Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ -){ - Fts3SegReader *pReader; /* Newly allocated SegReader object */ - int nExtra = 0; /* Bytes to allocate segment root node */ - - assert( zRoot!=0 || nRoot==0 ); -#ifdef CORRUPT_DB - assert( zRoot!=0 || CORRUPT_DB ); -#endif - - if( iStartLeaf==0 ){ - if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB; - nExtra = nRoot + FTS3_NODE_PADDING; - } - - pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra); - if( !pReader ){ - return SQLITE_NOMEM; - } - memset(pReader, 0, sizeof(Fts3SegReader)); - pReader->iIdx = iAge; - pReader->bLookup = bLookup!=0; - pReader->iStartBlock = iStartLeaf; - pReader->iLeafEndBlock = iEndLeaf; - pReader->iEndBlock = iEndBlock; - - if( nExtra ){ - /* The entire segment is stored in the root node. */ - pReader->aNode = (char *)&pReader[1]; - pReader->rootOnly = 1; - pReader->nNode = nRoot; - if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot); - memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING); - }else{ - pReader->iCurrentBlock = iStartLeaf-1; - } - *ppReader = pReader; - return SQLITE_OK; -} - -/* -** This is a comparison function used as a qsort() callback when sorting -** an array of pending terms by term. This occurs as part of flushing -** the contents of the pending-terms hash table to the database. -*/ -static int SQLITE_CDECL fts3CompareElemByTerm( - const void *lhs, - const void *rhs -){ - char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); - char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); - int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); - int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs); - - int n = (n1aIndex */ - const char *zTerm, /* Term to search for */ - int nTerm, /* Size of buffer zTerm */ - int bPrefix, /* True for a prefix iterator */ - Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */ -){ - Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */ - Fts3HashElem *pE; /* Iterator variable */ - Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */ - int nElem = 0; /* Size of array at aElem */ - int rc = SQLITE_OK; /* Return Code */ - Fts3Hash *pHash; - - pHash = &p->aIndex[iIndex].hPending; - if( bPrefix ){ - int nAlloc = 0; /* Size of allocated array at aElem */ - - for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){ - char *zKey = (char *)fts3HashKey(pE); - int nKey = fts3HashKeysize(pE); - if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){ - if( nElem==nAlloc ){ - Fts3HashElem **aElem2; - nAlloc += 16; - aElem2 = (Fts3HashElem **)sqlite3_realloc64( - aElem, nAlloc*sizeof(Fts3HashElem *) - ); - if( !aElem2 ){ - rc = SQLITE_NOMEM; - nElem = 0; - break; - } - aElem = aElem2; - } - - aElem[nElem++] = pE; - } - } - - /* If more than one term matches the prefix, sort the Fts3HashElem - ** objects in term order using qsort(). This uses the same comparison - ** callback as is used when flushing terms to disk. - */ - if( nElem>1 ){ - qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm); - } - - }else{ - /* The query is a simple term lookup that matches at most one term in - ** the index. All that is required is a straight hash-lookup. - ** - ** Because the stack address of pE may be accessed via the aElem pointer - ** below, the "Fts3HashElem *pE" must be declared so that it is valid - ** within this entire function, not just this "else{...}" block. - */ - pE = fts3HashFindElem(pHash, zTerm, nTerm); - if( pE ){ - aElem = &pE; - nElem = 1; - } - } - - if( nElem>0 ){ - sqlite3_int64 nByte; - nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); - pReader = (Fts3SegReader *)sqlite3_malloc64(nByte); - if( !pReader ){ - rc = SQLITE_NOMEM; - }else{ - memset(pReader, 0, nByte); - pReader->iIdx = 0x7FFFFFFF; - pReader->ppNextElem = (Fts3HashElem **)&pReader[1]; - memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *)); - } - } - - if( bPrefix ){ - sqlite3_free(aElem); - } - *ppReader = pReader; - return rc; -} - -/* -** Compare the entries pointed to by two Fts3SegReader structures. -** Comparison is as follows: -** -** 1) EOF is greater than not EOF. -** -** 2) The current terms (if any) are compared using memcmp(). If one -** term is a prefix of another, the longer term is considered the -** larger. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc; - if( pLhs->aNode && pRhs->aNode ){ - int rc2 = pLhs->nTerm - pRhs->nTerm; - if( rc2<0 ){ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm); - }else{ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm); - } - if( rc==0 ){ - rc = rc2; - } - }else{ - rc = (pLhs->aNode==0) - (pRhs->aNode==0); - } - if( rc==0 ){ - rc = pRhs->iIdx - pLhs->iIdx; - } - assert_fts3_nc( rc!=0 ); - return rc; -} - -/* -** A different comparison function for SegReader structures. In this -** version, it is assumed that each SegReader points to an entry in -** a doclist for identical terms. Comparison is made as follows: -** -** 1) EOF (end of doclist in this case) is greater than not EOF. -** -** 2) By current docid. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} -static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} - -/* -** Compare the term that the Fts3SegReader object passed as the first argument -** points to with the term specified by arguments zTerm and nTerm. -** -** If the pSeg iterator is already at EOF, return 0. Otherwise, return -** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are -** equal, or +ve if the pSeg term is greater than zTerm/nTerm. -*/ -static int fts3SegReaderTermCmp( - Fts3SegReader *pSeg, /* Segment reader object */ - const char *zTerm, /* Term to compare to */ - int nTerm /* Size of term zTerm in bytes */ -){ - int res = 0; - if( pSeg->aNode ){ - if( pSeg->nTerm>nTerm ){ - res = memcmp(pSeg->zTerm, zTerm, nTerm); - }else{ - res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm); - } - if( res==0 ){ - res = pSeg->nTerm-nTerm; - } - } - return res; -} - -/* -** Argument apSegment is an array of nSegment elements. It is known that -** the final (nSegment-nSuspect) members are already in sorted order -** (according to the comparison function provided). This function shuffles -** the array around until all entries are in sorted order. -*/ -static void fts3SegReaderSort( - Fts3SegReader **apSegment, /* Array to sort entries of */ - int nSegment, /* Size of apSegment array */ - int nSuspect, /* Unsorted entry count */ - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */ -){ - int i; /* Iterator variable */ - - assert( nSuspect<=nSegment ); - - if( nSuspect==nSegment ) nSuspect--; - for(i=nSuspect-1; i>=0; i--){ - int j; - for(j=i; j<(nSegment-1); j++){ - Fts3SegReader *pTmp; - if( xCmp(apSegment[j], apSegment[j+1])<0 ) break; - pTmp = apSegment[j+1]; - apSegment[j+1] = apSegment[j]; - apSegment[j] = pTmp; - } - } - -#ifndef NDEBUG - /* Check that the list really is sorted now. */ - for(i=0; i<(nSuspect-1); i++){ - assert( xCmp(apSegment[i], apSegment[i+1])<0 ); - } -#endif -} - -/* -** Insert a record into the %_segments table. -*/ -static int fts3WriteSegment( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iBlock, /* Block id for new block */ - char *z, /* Pointer to buffer containing block data */ - int n /* Size of buffer z in bytes */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iBlock); - sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); - } - return rc; -} - -/* -** Find the largest relative level number in the table. If successful, set -** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs, -** set *pnMax to zero and return an SQLite error code. -*/ -SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){ - int rc; - int mxLevel = 0; - sqlite3_stmt *pStmt = 0; - - rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - mxLevel = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - *pnMax = mxLevel; - return rc; -} - -/* -** Insert a record into the %_segdir table. -*/ -static int fts3WriteSegdir( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ - int iIdx, /* Value for "idx" field */ - sqlite3_int64 iStartBlock, /* Value for "start_block" field */ - sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ - sqlite3_int64 iEndBlock, /* Value for "end_block" field */ - sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */ - char *zRoot, /* Blob value for "root" field */ - int nRoot /* Number of bytes in buffer zRoot */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iLevel); - sqlite3_bind_int(pStmt, 2, iIdx); - sqlite3_bind_int64(pStmt, 3, iStartBlock); - sqlite3_bind_int64(pStmt, 4, iLeafEndBlock); - if( nLeafData==0 ){ - sqlite3_bind_int64(pStmt, 5, iEndBlock); - }else{ - char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData); - if( !zEnd ) return SQLITE_NOMEM; - sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free); - } - sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 6); - } - return rc; -} - -/* -** Return the size of the common prefix (if any) shared by zPrev and -** zNext, in bytes. For example, -** -** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3 -** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2 -** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0 -*/ -static int fts3PrefixCompress( - const char *zPrev, /* Buffer containing previous term */ - int nPrev, /* Size of buffer zPrev in bytes */ - const char *zNext, /* Buffer containing next term */ - int nNext /* Size of buffer zNext in bytes */ -){ - int n; - for(n=0; nnData; /* Current size of node in bytes */ - int nReq = nData; /* Required space after adding zTerm */ - int nPrefix; /* Number of bytes of prefix compression */ - int nSuffix; /* Suffix length */ - - nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of - ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when - ** compared with BINARY collation. This indicates corruption. */ - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - - nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; - if( nReq<=p->nNodeSize || !pTree->zTerm ){ - - if( nReq>p->nNodeSize ){ - /* An unusual case: this is the first term to be added to the node - ** and the static node buffer (p->nNodeSize bytes) is not large - ** enough. Use a separately malloced buffer instead This wastes - ** p->nNodeSize bytes, but since this scenario only comes about when - ** the database contain two terms that share a prefix of almost 2KB, - ** this is not expected to be a serious problem. - */ - assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)sqlite3_malloc64(nReq); - if( !pTree->aData ){ - return SQLITE_NOMEM; - } - } - - if( pTree->zTerm ){ - /* There is no prefix-length field for first term in a node */ - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix); - } - - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix); - memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix); - pTree->nData = nData + nSuffix; - pTree->nEntry++; - - if( isCopyTerm ){ - if( pTree->nMalloczMalloc, (i64)nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pTree->nMalloc = nTerm*2; - pTree->zMalloc = zNew; - } - pTree->zTerm = pTree->zMalloc; - memcpy(pTree->zTerm, zTerm, nTerm); - pTree->nTerm = nTerm; - }else{ - pTree->zTerm = (char *)zTerm; - pTree->nTerm = nTerm; - } - return SQLITE_OK; - } - } - - /* If control flows to here, it was not possible to append zTerm to the - ** current node. Create a new node (a right-sibling of the current node). - ** If this is the first node in the tree, the term is added to it. - ** - ** Otherwise, the term is not added to the new node, it is left empty for - ** now. Instead, the term is inserted into the parent of pTree. If pTree - ** has no parent, one is created here. - */ - pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize); - if( !pNew ){ - return SQLITE_NOMEM; - } - memset(pNew, 0, sizeof(SegmentNode)); - pNew->nData = 1 + FTS3_VARINT_MAX; - pNew->aData = (char *)&pNew[1]; - - if( pTree ){ - SegmentNode *pParent = pTree->pParent; - rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm); - if( pTree->pParent==0 ){ - pTree->pParent = pParent; - } - pTree->pRight = pNew; - pNew->pLeftmost = pTree->pLeftmost; - pNew->pParent = pParent; - pNew->zMalloc = pTree->zMalloc; - pNew->nMalloc = pTree->nMalloc; - pTree->zMalloc = 0; - }else{ - pNew->pLeftmost = pNew; - rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm); - } - - *ppTree = pNew; - return rc; -} - -/* -** Helper function for fts3NodeWrite(). -*/ -static int fts3TreeFinishNode( - SegmentNode *pTree, - int iHeight, - sqlite3_int64 iLeftChild -){ - int nStart; - assert( iHeight>=1 && iHeight<128 ); - nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); - pTree->aData[nStart] = (char)iHeight; - sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild); - return nStart; -} - -/* -** Write the buffer for the segment node pTree and all of its peers to the -** database. Then call this function recursively to write the parent of -** pTree and its peers to the database. -** -** Except, if pTree is a root node, do not write it to the database. Instead, -** set output variables *paRoot and *pnRoot to contain the root node. -** -** If successful, SQLITE_OK is returned and output variable *piLast is -** set to the largest blockid written to the database (or zero if no -** blocks were written to the db). Otherwise, an SQLite error code is -** returned. -*/ -static int fts3NodeWrite( - Fts3Table *p, /* Virtual table handle */ - SegmentNode *pTree, /* SegmentNode handle */ - int iHeight, /* Height of this node in tree */ - sqlite3_int64 iLeaf, /* Block id of first leaf node */ - sqlite3_int64 iFree, /* Block id of next free slot in %_segments */ - sqlite3_int64 *piLast, /* OUT: Block id of last entry written */ - char **paRoot, /* OUT: Data for root node */ - int *pnRoot /* OUT: Size of root node in bytes */ -){ - int rc = SQLITE_OK; - - if( !pTree->pParent ){ - /* Root node of the tree. */ - int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf); - *piLast = iFree-1; - *pnRoot = pTree->nData - nStart; - *paRoot = &pTree->aData[nStart]; - }else{ - SegmentNode *pIter; - sqlite3_int64 iNextFree = iFree; - sqlite3_int64 iNextLeaf = iLeaf; - for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){ - int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf); - int nWrite = pIter->nData - nStart; - - rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite); - iNextFree++; - iNextLeaf += (pIter->nEntry+1); - } - if( rc==SQLITE_OK ){ - assert( iNextLeaf==iFree ); - rc = fts3NodeWrite( - p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot - ); - } - } - - return rc; -} - -/* -** Free all memory allocations associated with the tree pTree. -*/ -static void fts3NodeFree(SegmentNode *pTree){ - if( pTree ){ - SegmentNode *p = pTree->pLeftmost; - fts3NodeFree(p->pParent); - while( p ){ - SegmentNode *pRight = p->pRight; - if( p->aData!=(char *)&p[1] ){ - sqlite3_free(p->aData); - } - assert( pRight==0 || p->zMalloc==0 ); - sqlite3_free(p->zMalloc); - sqlite3_free(p); - p = pRight; - } - } -} - -/* -** Add a term to the segment being constructed by the SegmentWriter object -** *ppWriter. When adding the first term to a segment, *ppWriter should -** be passed NULL. This function will allocate a new SegmentWriter object -** and return it via the input/output variable *ppWriter in this case. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterAdd( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ - int isCopyTerm, /* True if buffer zTerm must be copied */ - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of term in bytes */ - const char *aDoclist, /* Pointer to buffer containing doclist */ - int nDoclist /* Size of doclist in bytes */ -){ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - i64 nReq; /* Number of bytes required on leaf page */ - int nData; - SegmentWriter *pWriter = *ppWriter; - - if( !pWriter ){ - int rc; - sqlite3_stmt *pStmt; - - /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)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 *)sqlite3_malloc64(p->nNodeSize); - if( !pWriter->aData ) return SQLITE_NOMEM; - pWriter->nSize = p->nNodeSize; - - /* Find the next free blockid in the %_segments table */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - pWriter->iFree = sqlite3_column_int64(pStmt, 0); - pWriter->iFirst = pWriter->iFree; - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ) return rc; - } - nData = pWriter->nData; - - nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of - ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when - ** compared with BINARY collation. This indicates corruption. */ - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - - /* Figure out how many bytes are required by this new entry */ - nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ - nSuffix + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - - if( nData>0 && nData+nReq>p->nNodeSize ){ - int rc; - - /* The current leaf node is full. Write it out to the database. */ - if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB; - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); - if( rc!=SQLITE_OK ) return rc; - p->nLeafAdd++; - - /* Add the current term to the interior node tree. The term added to - ** the interior tree must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pWriter->zTerm), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - assert( nPrefixpTree, isCopyTerm, zTerm, nPrefix+1); - if( rc!=SQLITE_OK ) return rc; - - nData = 0; - pWriter->nTerm = 0; - - nPrefix = 0; - nSuffix = nTerm; - nReq = 1 + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */ - nTerm + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - } - - /* Increase the total number of bytes written to account for the new entry. */ - pWriter->nLeafData += nReq; - - /* If the buffer currently allocated is too small for this entry, realloc - ** the buffer to make it large enough. - */ - if( nReq>pWriter->nSize ){ - char *aNew = sqlite3_realloc64(pWriter->aData, nReq); - if( !aNew ) return SQLITE_NOMEM; - pWriter->aData = aNew; - pWriter->nSize = nReq; - } - assert( nData+nReq<=pWriter->nSize ); - - /* Append the prefix-compressed term and doclist to the buffer. */ - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix); - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix); - assert( nSuffix>0 ); - memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix); - nData += nSuffix; - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist); - assert( nDoclist>0 ); - memcpy(&pWriter->aData[nData], aDoclist, nDoclist); - pWriter->nData = nData + nDoclist; - - /* Save the current term so that it can be used to prefix-compress the next. - ** If the isCopyTerm parameter is true, then the buffer pointed to by - ** zTerm is transient, so take a copy of the term data. Otherwise, just - ** store a copy of the pointer. - */ - if( isCopyTerm ){ - if( nTerm>pWriter->nMalloc ){ - char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pWriter->nMalloc = nTerm*2; - pWriter->zMalloc = zNew; - pWriter->zTerm = zNew; - } - assert( pWriter->zTerm==pWriter->zMalloc ); - assert( nTerm>0 ); - memcpy(pWriter->zTerm, zTerm, nTerm); - }else{ - pWriter->zTerm = (char *)zTerm; - } - pWriter->nTerm = nTerm; - - return SQLITE_OK; -} - -/* -** Flush all data associated with the SegmentWriter object pWriter to the -** database. This function must be called after all terms have been added -** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is -** returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterFlush( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter *pWriter, /* SegmentWriter to flush to the db */ - sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */ - int iIdx /* Value for 'idx' column of %_segdir */ -){ - int rc; /* Return code */ - if( pWriter->pTree ){ - sqlite3_int64 iLast = 0; /* Largest block id written to database */ - sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ - char *zRoot = NULL; /* Pointer to buffer containing root node */ - int nRoot = 0; /* Size of buffer zRoot */ - - iLastLeaf = pWriter->iFree; - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); - if( rc==SQLITE_OK ){ - rc = fts3NodeWrite(p, pWriter->pTree, 1, - pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, iLevel, iIdx, - pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot); - } - }else{ - /* The entire tree fits on the root node. Write it to the segdir table. */ - rc = fts3WriteSegdir(p, iLevel, iIdx, - 0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData); - } - p->nLeafAdd++; - return rc; -} - -/* -** Release all memory held by the SegmentWriter object passed as the -** first argument. -*/ -static void fts3SegWriterFree(SegmentWriter *pWriter){ - if( pWriter ){ - sqlite3_free(pWriter->aData); - sqlite3_free(pWriter->zMalloc); - fts3NodeFree(pWriter->pTree); - sqlite3_free(pWriter); - } -} - -/* -** The first value in the apVal[] array is assumed to contain an integer. -** This function tests if there exist any documents with docid values that -** are different from that integer. i.e. if deleting the document with docid -** pRowid would mean the FTS3 table were empty. -** -** If successful, *pisEmpty is set to true if the table is empty except for -** document pRowid, or false otherwise, and SQLITE_OK is returned. If an -** error occurs, an SQLite error code is returned. -*/ -static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){ - sqlite3_stmt *pStmt; - int rc; - if( p->zContentTbl ){ - /* If using the content=xxx option, assume the table is never empty */ - *pisEmpty = 0; - rc = SQLITE_OK; - }else{ - rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pisEmpty = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - } - return rc; -} - -/* -** Set *pnMax to the largest segment level in the database for the index -** iIndex. -** -** Segment levels are stored in the 'level' column of the %_segdir table. -** -** Return SQLITE_OK if successful, or an SQLite error code if not. -*/ -static int fts3SegmentMaxLevel( - Fts3Table *p, - int iLangid, - int iIndex, - sqlite3_int64 *pnMax -){ - sqlite3_stmt *pStmt; - int rc; - assert( iIndex>=0 && iIndexnIndex ); - - /* Set pStmt to the compiled version of: - ** - ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? - ** - ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). - */ - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pnMax = sqlite3_column_int64(pStmt, 0); - } - return sqlite3_reset(pStmt); -} - -/* -** iAbsLevel is an absolute level that may be assumed to exist within -** the database. This function checks if it is the largest level number -** within its index. Assuming no error occurs, *pbMax is set to 1 if -** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK -** is returned. If an error occurs, an error code is returned and the -** final value of *pbMax is undefined. -*/ -static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){ - - /* Set pStmt to the compiled version of: - ** - ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? - ** - ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). - */ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pStmt, 1, iAbsLevel+1); - sqlite3_bind_int64(pStmt, 2, - (((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL - ); - - *pbMax = 0; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL; - } - return sqlite3_reset(pStmt); -} - -/* -** Delete all entries in the %_segments table associated with the segment -** opened with seg-reader pSeg. This function does not affect the contents -** of the %_segdir table. -*/ -static int fts3DeleteSegment( - Fts3Table *p, /* FTS table handle */ - Fts3SegReader *pSeg /* Segment to delete */ -){ - int rc = SQLITE_OK; /* Return code */ - if( pSeg->iStartBlock ){ - sqlite3_stmt *pDelete; /* SQL statement to delete rows */ - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock); - sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - } - return rc; -} - -/* -** This function is used after merging multiple segments into a single large -** segment to delete the old, now redundant, segment b-trees. Specifically, -** it: -** -** 1) Deletes all %_segments entries for the segments associated with -** each of the SegReader objects in the array passed as the third -** argument, and -** -** 2) deletes all %_segdir entries with level iLevel, or all %_segdir -** entries regardless of level if (iLevel<0). -** -** SQLITE_OK is returned if successful, otherwise an SQLite error code. -*/ -static int fts3DeleteSegdir( - Fts3Table *p, /* Virtual table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, /* Level of %_segdir entries to delete */ - Fts3SegReader **apSegment, /* Array of SegReader objects */ - int nReader /* Size of array apSegment */ -){ - int rc = SQLITE_OK; /* Return Code */ - int i; /* Iterator variable */ - sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */ - - for(i=0; rc==SQLITE_OK && i=0 || iLevel==FTS3_SEGCURSOR_ALL ); - if( iLevel==FTS3_SEGCURSOR_ALL ){ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pDelete, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** When this function is called, buffer *ppList (size *pnList bytes) contains -** a position list that may (or may not) feature multiple columns. This -** function adjusts the pointer *ppList and the length *pnList so that they -** identify the subset of the position list that corresponds to column iCol. -** -** If there are no entries in the input position list for column iCol, then -** *pnList is set to zero before returning. -** -** If parameter bZero is non-zero, then any part of the input list following -** the end of the output list is zeroed before returning. -*/ -static void fts3ColumnFilter( - int iCol, /* Column to filter on */ - int bZero, /* Zero out anything following *ppList */ - char **ppList, /* IN/OUT: Pointer to position list */ - int *pnList /* IN/OUT: Size of buffer *ppList in bytes */ -){ - char *pList = *ppList; - int nList = *pnList; - char *pEnd = &pList[nList]; - int iCurrent = 0; - char *p = pList; - - assert( iCol>=0 ); - while( 1 ){ - char c = 0; - while( p0){ - memset(&pList[nList], 0, pEnd - &pList[nList]); - } - *ppList = pList; - *pnList = nList; -} - -/* -** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any -** existing data). Grow the buffer if required. -** -** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered -** trying to resize the buffer, return SQLITE_NOMEM. -*/ -static int fts3MsrBufferData( - Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ - char *pList, - i64 nList -){ - if( (nList+FTS3_NODE_PADDING)>pMsr->nBuffer ){ - char *pNew; - int nNew = nList*2 + FTS3_NODE_PADDING; - pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, nNew); - if( !pNew ) return SQLITE_NOMEM; - pMsr->aBuffer = pNew; - pMsr->nBuffer = nNew; - } - - assert( nList>0 ); - memcpy(pMsr->aBuffer, pList, nList); - memset(&pMsr->aBuffer[nList], 0, FTS3_NODE_PADDING); - return SQLITE_OK; -} - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ - sqlite3_int64 *piDocid, /* OUT: Docid value */ - char **paPoslist, /* OUT: Pointer to position list */ - int *pnPoslist /* OUT: Size of position list in bytes */ -){ - int nMerge = pMsr->nAdvance; - Fts3SegReader **apSegment = pMsr->apSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( nMerge==0 ){ - *paPoslist = 0; - return SQLITE_OK; - } - - while( 1 ){ - Fts3SegReader *pSeg; - pSeg = pMsr->apSegment[0]; - - if( pSeg->pOffsetList==0 ){ - *paPoslist = 0; - break; - }else{ - int rc; - char *pList; - int nList; - int j; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - - rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( rc==SQLITE_OK - && jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - if( rc!=SQLITE_OK ) return rc; - fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); - - if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1); - if( rc!=SQLITE_OK ) return rc; - assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); - pList = pMsr->aBuffer; - } - - if( pMsr->iColFilter>=0 ){ - fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList); - } - - if( nList>0 ){ - *paPoslist = pList; - *piDocid = iDocid; - *pnPoslist = nList; - break; - } - } - } - - return SQLITE_OK; -} - -static int fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - const char *zTerm, /* Term searched for (or NULL) */ - int nTerm /* Length of zTerm in bytes */ -){ - int i; - int nSeg = pCsr->nSegment; - - /* If the Fts3SegFilter defines a specific term (or term prefix) to search - ** for, then advance each segment iterator until it points to a term of - ** equal or greater value than the specified term. This prevents many - ** unnecessary merge/sort operations for the case where single segment - ** b-tree leaf nodes contain more than one term. - */ - for(i=0; pCsr->bRestart==0 && inSegment; i++){ - int res = 0; - Fts3SegReader *pSeg = pCsr->apSegment[i]; - do { - int rc = fts3SegReaderNext(p, pSeg, 0); - if( rc!=SQLITE_OK ) return rc; - }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 ); - - if( pSeg->bLookup && res!=0 ){ - fts3SegReaderSetEof(pSeg); - } - } - fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp); - - return SQLITE_OK; -} - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - Fts3SegFilter *pFilter /* Restrictions on range of iteration */ -){ - pCsr->pFilter = pFilter; - return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm); -} - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - int iCol, /* Column to match on. */ - const char *zTerm, /* Term to iterate through a doclist for */ - int nTerm /* Number of bytes in zTerm */ -){ - int i; - int rc; - int nSegment = pCsr->nSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - assert( pCsr->pFilter==0 ); - assert( zTerm && nTerm>0 ); - - /* Advance each segment iterator until it points to the term zTerm/nTerm. */ - rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm); - if( rc!=SQLITE_OK ) return rc; - - /* Determine how many of the segments actually point to zTerm/nTerm. */ - for(i=0; iapSegment[i]; - if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){ - break; - } - } - pCsr->nAdvance = i; - - /* Advance each of the segments to point to the first docid. */ - for(i=0; inAdvance; i++){ - rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]); - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(pCsr->apSegment, i, i, xCmp); - - assert( iCol<0 || iColnColumn ); - pCsr->iColFilter = iCol; - - return SQLITE_OK; -} - -/* -** This function is called on a MultiSegReader that has been started using -** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also -** have been made. Calling this function puts the MultiSegReader in such -** a state that if the next two calls are: -** -** sqlite3Fts3SegReaderStart() -** sqlite3Fts3SegReaderStep() -** -** then the entire doclist for the term is available in -** MultiSegReader.aDoclist/nDoclist. -*/ -SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ - int i; /* Used to iterate through segment-readers */ - - assert( pCsr->zTerm==0 ); - assert( pCsr->nTerm==0 ); - assert( pCsr->aDoclist==0 ); - assert( pCsr->nDoclist==0 ); - - pCsr->nAdvance = 0; - pCsr->bRestart = 1; - for(i=0; inSegment; i++){ - pCsr->apSegment[i]->pOffsetList = 0; - pCsr->apSegment[i]->nOffsetList = 0; - pCsr->apSegment[i]->iDocid = 0; - } - - return SQLITE_OK; -} - -static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){ - if( nReq>pCsr->nBuffer ){ - char *aNew; - pCsr->nBuffer = nReq*2; - aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer); - if( !aNew ){ - return SQLITE_NOMEM; - } - pCsr->aBuffer = aNew; - } - return SQLITE_OK; -} - - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - int rc = SQLITE_OK; - - int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); - int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); - int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); - int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX); - int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN); - int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST); - - Fts3SegReader **apSegment = pCsr->apSegment; - int nSegment = pCsr->nSegment; - Fts3SegFilter *pFilter = pCsr->pFilter; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( pCsr->nSegment==0 ) return SQLITE_OK; - - do { - int nMerge; - int i; - - /* Advance the first pCsr->nAdvance entries in the apSegment[] array - ** forward. Then sort the list in order of current term again. - */ - for(i=0; inAdvance; i++){ - Fts3SegReader *pSeg = apSegment[i]; - if( pSeg->bLookup ){ - fts3SegReaderSetEof(pSeg); - }else{ - rc = fts3SegReaderNext(p, pSeg, 0); - } - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp); - pCsr->nAdvance = 0; - - /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */ - assert( rc==SQLITE_OK ); - if( apSegment[0]->aNode==0 ) break; - - pCsr->nTerm = apSegment[0]->nTerm; - pCsr->zTerm = apSegment[0]->zTerm; - - /* If this is a prefix-search, and if the term that apSegment[0] points - ** to does not share a suffix with pFilter->zTerm/nTerm, then all - ** required callbacks have been made. In this case exit early. - ** - ** Similarly, if this is a search for an exact match, and the first term - ** of segment apSegment[0] is not a match, exit early. - */ - if( pFilter->zTerm && !isScan ){ - if( pCsr->nTermnTerm - || (!isPrefix && pCsr->nTerm>pFilter->nTerm) - || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) - ){ - break; - } - } - - nMerge = 1; - while( nMergeaNode - && apSegment[nMerge]->nTerm==pCsr->nTerm - && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm) - ){ - nMerge++; - } - - assert( isIgnoreEmpty || (isRequirePos && !isColFilter) ); - if( nMerge==1 - && !isIgnoreEmpty - && !isFirst - && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0) - ){ - pCsr->nDoclist = apSegment[0]->nDoclist; - if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, - (i64)pCsr->nDoclist); - pCsr->aDoclist = pCsr->aBuffer; - }else{ - pCsr->aDoclist = apSegment[0]->aDoclist; - } - if( rc==SQLITE_OK ) rc = SQLITE_ROW; - }else{ - int nDoclist = 0; /* Size of doclist */ - sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */ - - /* The current term of the first nMerge entries in the array - ** of Fts3SegReader objects is the same. The doclists must be merged - ** and a single term returned with the merged doclist. - */ - for(i=0; ipOffsetList ){ - int j; /* Number of segments that share a docid */ - char *pList = 0; - int nList = 0; - int nByte; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - - if( isColFilter ){ - fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList); - } - - if( !isIgnoreEmpty || nList>0 ){ - - /* Calculate the 'docid' delta value to write into the merged - ** doclist. */ - sqlite3_int64 iDelta; - if( p->bDescIdx && nDoclist>0 ){ - if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB; - iDelta = (i64)((u64)iPrev - (u64)iDocid); - }else{ - if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB; - iDelta = (i64)((u64)iDocid - (u64)iPrev); - } - - nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - - rc = fts3GrowSegReaderBuffer(pCsr, - (i64)nByte+nDoclist+FTS3_NODE_PADDING); - if( rc ) return rc; - - if( isFirst ){ - char *a = &pCsr->aBuffer[nDoclist]; - int nWrite; - - nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a); - if( nWrite ){ - iPrev = iDocid; - nDoclist += nWrite; - } - }else{ - nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta); - iPrev = iDocid; - if( isRequirePos ){ - memcpy(&pCsr->aBuffer[nDoclist], pList, nList); - nDoclist += nList; - pCsr->aBuffer[nDoclist++] = '\0'; - } - } - } - - fts3SegReaderSort(apSegment, nMerge, j, xCmp); - } - if( nDoclist>0 ){ - rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING); - if( rc ) return rc; - memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING); - pCsr->aDoclist = pCsr->aBuffer; - pCsr->nDoclist = nDoclist; - rc = SQLITE_ROW; - } - } - pCsr->nAdvance = nMerge; - }while( rc==SQLITE_OK ); - - return rc; -} - - -SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish( - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - if( pCsr ){ - int i; - for(i=0; inSegment; i++){ - sqlite3Fts3SegReaderFree(pCsr->apSegment[i]); - } - sqlite3_free(pCsr->apSegment); - sqlite3_free(pCsr->aBuffer); - - pCsr->nSegment = 0; - pCsr->apSegment = 0; - pCsr->aBuffer = 0; - } -} - -/* -** Decode the "end_block" field, selected by column iCol of the SELECT -** statement passed as the first argument. -** -** The "end_block" field may contain either an integer, or a text field -** containing the text representation of two non-negative integers separated -** by one or more space (0x20) characters. In the first case, set *piEndBlock -** to the integer value and *pnByte to zero before returning. In the second, -** set *piEndBlock to the first value and *pnByte to the second. -*/ -static void fts3ReadEndBlockField( - sqlite3_stmt *pStmt, - int iCol, - i64 *piEndBlock, - i64 *pnByte -){ - const unsigned char *zText = sqlite3_column_text(pStmt, iCol); - if( zText ){ - int i; - int iMul = 1; - u64 iVal = 0; - for(i=0; zText[i]>='0' && zText[i]<='9'; i++){ - iVal = iVal*10 + (zText[i] - '0'); - } - *piEndBlock = (i64)iVal; - while( zText[i]==' ' ) i++; - iVal = 0; - if( zText[i]=='-' ){ - i++; - iMul = -1; - } - for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){ - iVal = iVal*10 + (zText[i] - '0'); - } - *pnByte = ((i64)iVal * (i64)iMul); - } -} - - -/* -** A segment of size nByte bytes has just been written to absolute level -** iAbsLevel. Promote any segments that should be promoted as a result. -*/ -static int fts3PromoteSegments( - Fts3Table *p, /* FTS table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level just updated */ - sqlite3_int64 nByte /* Size of new segment at iAbsLevel */ -){ - int rc = SQLITE_OK; - sqlite3_stmt *pRange; - - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0); - - if( rc==SQLITE_OK ){ - int bOk = 0; - i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1; - i64 nLimit = (nByte*3)/2; - - /* Loop through all entries in the %_segdir table corresponding to - ** segments in this index on levels greater than iAbsLevel. If there is - ** at least one such segment, and it is possible to determine that all - ** such segments are smaller than nLimit bytes in size, they will be - ** promoted to level iAbsLevel. */ - sqlite3_bind_int64(pRange, 1, iAbsLevel+1); - sqlite3_bind_int64(pRange, 2, iLast); - while( SQLITE_ROW==sqlite3_step(pRange) ){ - i64 nSize = 0, dummy; - fts3ReadEndBlockField(pRange, 2, &dummy, &nSize); - if( nSize<=0 || nSize>nLimit ){ - /* If nSize==0, then the %_segdir.end_block field does not not - ** contain a size value. This happens if it was written by an - ** old version of FTS. In this case it is not possible to determine - ** the size of the segment, and so segment promotion does not - ** take place. */ - bOk = 0; - break; - } - bOk = 1; - } - rc = sqlite3_reset(pRange); - - if( bOk ){ - int iIdx = 0; - sqlite3_stmt *pUpdate1 = 0; - sqlite3_stmt *pUpdate2 = 0; - - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); - } - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0); - } - - if( rc==SQLITE_OK ){ - - /* Loop through all %_segdir entries for segments in this index with - ** levels equal to or greater than iAbsLevel. As each entry is visited, - ** updated it to set (level = -1) and (idx = N), where N is 0 for the - ** oldest segment in the range, 1 for the next oldest, and so on. - ** - ** In other words, move all segments being promoted to level -1, - ** setting the "idx" fields as appropriate to keep them in the same - ** order. The contents of level -1 (which is never used, except - ** transiently here), will be moved back to level iAbsLevel below. */ - sqlite3_bind_int64(pRange, 1, iAbsLevel); - while( SQLITE_ROW==sqlite3_step(pRange) ){ - sqlite3_bind_int(pUpdate1, 1, iIdx++); - sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0)); - sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1)); - sqlite3_step(pUpdate1); - rc = sqlite3_reset(pUpdate1); - if( rc!=SQLITE_OK ){ - sqlite3_reset(pRange); - break; - } - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3_reset(pRange); - } - - /* Move level -1 to level iAbsLevel */ - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate2, 1, iAbsLevel); - sqlite3_step(pUpdate2); - rc = sqlite3_reset(pUpdate2); - } - } - } - - - return rc; -} - -/* -** Merge all level iLevel segments in the database into a single -** iLevel+1 segment. Or, if iLevel<0, merge all segments into a -** single segment with a level equal to the numerically largest level -** currently present in the database. -** -** If this function is called with iLevel<0, but there is only one -** segment in the database, SQLITE_DONE is returned immediately. -** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, -** an SQLite error code is returned. -*/ -static int fts3SegmentMerge( - Fts3Table *p, - int iLangid, /* Language id to merge */ - int iIndex, /* Index in p->aIndex[] to merge */ - int iLevel /* Level to merge */ -){ - int rc; /* Return code */ - int iIdx = 0; /* Index of new segment */ - sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */ - SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ - Fts3SegFilter filter; /* Segment term filter condition */ - Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ - int bIgnoreEmpty = 0; /* True to ignore empty segments */ - i64 iMaxLevel = 0; /* Max level number for this index/langid */ - - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevel=0 && iIndexnIndex ); - - rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); - if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; - - if( iLevel!=FTS3_SEGCURSOR_PENDING ){ - rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel); - if( rc!=SQLITE_OK ) goto finished; - } - - if( iLevel==FTS3_SEGCURSOR_ALL ){ - /* This call is to merge all segments in the database to a single - ** segment. The level of the new segment is equal to the numerically - ** greatest segment level currently present in the database for this - ** index. The idx of the new segment is always 0. */ - if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){ - rc = SQLITE_DONE; - goto finished; - } - iNewLevel = iMaxLevel; - bIgnoreEmpty = 1; - - }else{ - /* This call is to merge all segments at level iLevel. find the next - ** available segment index at level iLevel+1. The call to - ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to - ** a single iLevel+2 segment if necessary. */ - assert( FTS3_SEGCURSOR_PENDING==-1 ); - iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); - bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel); - } - if( rc!=SQLITE_OK ) goto finished; - - assert( csr.nSegment>0 ); - assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); - assert_fts3_nc( - iNewLevelnLeafData); - } - } - } - - finished: - fts3SegWriterFree(pWriter); - sqlite3Fts3SegReaderFinish(&csr); - return rc; -} - - -/* -** Flush the contents of pendingTerms to level 0 segments. -*/ -SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ - int rc = SQLITE_OK; - int i; - - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - - /* Determine the auto-incr-merge setting if unknown. If enabled, - ** estimate the number of leaf blocks of content to be written - */ - if( rc==SQLITE_OK && p->bHasStat - && p->nAutoincrmerge==0xff && p->nLeafAdd>0 - ){ - sqlite3_stmt *pStmt = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - p->nAutoincrmerge = sqlite3_column_int(pStmt, 0); - if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8; - }else if( rc==SQLITE_DONE ){ - p->nAutoincrmerge = 0; - } - rc = sqlite3_reset(pStmt); - } - } - - if( rc==SQLITE_OK ){ - sqlite3Fts3PendingTermsClear(p); - } - return rc; -} - -/* -** Encode N integers as varints into a blob. -*/ -static void fts3EncodeIntArray( - int N, /* The number of integers to encode */ - u32 *a, /* The integer values */ - char *zBuf, /* Write the BLOB here */ - int *pNBuf /* Write number of bytes if zBuf[] used here */ -){ - int i, j; - for(i=j=0; iiPrevDocid. The sizes are encoded as -** a blob of varints. -*/ -static void fts3InsertDocsize( - int *pRC, /* Result code */ - Fts3Table *p, /* Table into which to insert */ - u32 *aSz /* Sizes of each column, in tokens */ -){ - char *pBlob; /* The BLOB encoding of the document size */ - int nBlob; /* Number of bytes in the BLOB */ - sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ - int rc; /* Result code from subfunctions */ - - if( *pRC ) return; - pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn ); - if( pBlob==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); - if( rc ){ - sqlite3_free(pBlob); - *pRC = rc; - return; - } - sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); -} - -/* -** Record 0 of the %_stat table contains a blob consisting of N varints, -** where N is the number of user defined columns in the fts3 table plus -** two. If nCol is the number of user defined columns, then values of the -** varints are set as follows: -** -** Varint 0: Total number of rows in the table. -** -** Varint 1..nCol: For each column, the total number of tokens stored in -** the column for all rows of the table. -** -** Varint 1+nCol: The total size, in bytes, of all text values in all -** columns of all rows of the table. -** -*/ -static void fts3UpdateDocTotals( - int *pRC, /* The result code */ - Fts3Table *p, /* Table being updated */ - u32 *aSzIns, /* Size increases */ - u32 *aSzDel, /* Size decreases */ - int nChng /* Change in the number of documents */ -){ - char *pBlob; /* Storage for BLOB written into %_stat */ - int nBlob; /* Size of BLOB written into %_stat */ - u32 *a; /* Array of integers that becomes the BLOB */ - sqlite3_stmt *pStmt; /* Statement for reading and writing */ - int i; /* Loop counter */ - int rc; /* Result code from subfunctions */ - - const int nStat = p->nColumn+2; - - if( *pRC ) return; - a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat ); - if( a==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - pBlob = (char*)&a[nStat]; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - fts3DecodeIntArray(nStat, a, - sqlite3_column_blob(pStmt, 0), - sqlite3_column_bytes(pStmt, 0)); - }else{ - memset(a, 0, sizeof(u32)*(nStat) ); - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - sqlite3_free(a); - *pRC = rc; - return; - } - if( nChng<0 && a[0]<(u32)(-nChng) ){ - a[0] = 0; - }else{ - a[0] += nChng; - } - for(i=0; inColumn+1; i++){ - u32 x = a[i+1]; - if( x+aSzIns[i] < aSzDel[i] ){ - x = 0; - }else{ - x = x + aSzIns[i] - aSzDel[i]; - } - a[i+1] = x; - } - fts3EncodeIntArray(nStat, a, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); - sqlite3_free(a); -} - -/* -** Merge the entire database so that there is one segment for each -** iIndex/iLangid combination. -*/ -static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ - int bSeenDone = 0; - int rc; - sqlite3_stmt *pAllLangid = 0; - - rc = sqlite3Fts3PendingTermsFlush(p); - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - } - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); - while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int i; - int iLangid = sqlite3_column_int(pAllLangid, 0); - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); - if( rc==SQLITE_DONE ){ - bSeenDone = 1; - rc = SQLITE_OK; - } - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - sqlite3Fts3SegmentsClose(p); - - return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; -} - -/* -** This function is called when the user executes the following statement: -** -** INSERT INTO () VALUES('rebuild'); -** -** The entire FTS index is discarded and rebuilt. If the table is one -** created using the content=xxx option, then the new index is based on -** the current contents of the xxx table. Otherwise, it is rebuilt based -** on the contents of the %_content table. -*/ -static int fts3DoRebuild(Fts3Table *p){ - int rc; /* Return Code */ - - rc = fts3DeleteAll(p, 0); - if( rc==SQLITE_OK ){ - u32 *aSz = 0; - u32 *aSzIns = 0; - u32 *aSzDel = 0; - sqlite3_stmt *pStmt = 0; - int nEntry = 0; - - /* Compose and prepare an SQL statement to loop through the content table */ - char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - if( rc==SQLITE_OK ){ - sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3; - aSz = (u32 *)sqlite3_malloc64(nByte); - if( aSz==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(aSz, 0, nByte); - aSzIns = &aSz[p->nColumn+1]; - aSzDel = &aSzIns[p->nColumn+1]; - } - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - int iCol; - int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); - memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - if( p->abNotindexed[iCol]==0 ){ - const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); - rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); - aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); - } - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSz); - } - if( rc!=SQLITE_OK ){ - sqlite3_finalize(pStmt); - pStmt = 0; - }else{ - nEntry++; - for(iCol=0; iCol<=p->nColumn; iCol++){ - aSzIns[iCol] += aSz[iCol]; - } - } - } - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry); - } - sqlite3_free(aSz); - - if( pStmt ){ - int rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - return rc; -} - - -/* -** This function opens a cursor used to read the input data for an -** incremental merge operation. Specifically, it opens a cursor to scan -** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute -** level iAbsLevel. -*/ -static int fts3IncrmergeCsr( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to open */ - int nSeg, /* Number of segments to merge */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc; /* Return Code */ - sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ - sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */ - - /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ - memset(pCsr, 0, sizeof(*pCsr)); - nByte = sizeof(Fts3SegReader *) * nSeg; - pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte); - - if( pCsr->apSegment==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->apSegment, 0, nByte); - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - } - if( rc==SQLITE_OK ){ - int i; - int rc2; - sqlite3_bind_int64(pStmt, 1, iAbsLevel); - assert( pCsr->nSegment==0 ); - for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && iapSegment[i] - ); - pCsr->nSegment++; - } - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -typedef struct IncrmergeWriter IncrmergeWriter; -typedef struct NodeWriter NodeWriter; -typedef struct Blob Blob; -typedef struct NodeReader NodeReader; - -/* -** An instance of the following structure is used as a dynamic buffer -** to build up nodes or other blobs of data in. -** -** The function blobGrowBuffer() is used to extend the allocation. -*/ -struct Blob { - char *a; /* Pointer to allocation */ - int n; /* Number of valid bytes of data in a[] */ - int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ -}; - -/* -** This structure is used to build up buffers containing segment b-tree -** nodes (blocks). -*/ -struct NodeWriter { - sqlite3_int64 iBlock; /* Current block id */ - Blob key; /* Last key written to the current block */ - Blob block; /* Current block image */ -}; - -/* -** An object of this type contains the state required to create or append -** to an appendable b-tree segment. -*/ -struct IncrmergeWriter { - int nLeafEst; /* Space allocated for leaf blocks */ - int nWork; /* Number of leaf pages flushed */ - sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ - int iIdx; /* Index of *output* segment in iAbsLevel+1 */ - sqlite3_int64 iStart; /* Block number of first allocated block */ - sqlite3_int64 iEnd; /* Block number of last allocated block */ - sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */ - u8 bNoLeafData; /* If true, store 0 for segment size */ - NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT]; -}; - -/* -** An object of the following type is used to read data from a single -** FTS segment node. See the following functions: -** -** nodeReaderInit() -** nodeReaderNext() -** nodeReaderRelease() -*/ -struct NodeReader { - const char *aNode; - int nNode; - int iOff; /* Current offset within aNode[] */ - - /* Output variables. Containing the current node entry. */ - sqlite3_int64 iChild; /* Pointer to child node */ - Blob term; /* Current term */ - const char *aDoclist; /* Pointer to doclist */ - int nDoclist; /* Size of doclist in bytes */ -}; - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if the allocation at pBlob->a is not already at least nMin -** bytes in size, extend (realloc) it to be so. -** -** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a -** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc -** to reflect the new size of the pBlob->a[] buffer. -*/ -static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ - if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ - int nAlloc = nMin; - char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc); - if( a ){ - pBlob->nAlloc = nAlloc; - pBlob->a = a; - }else{ - *pRc = SQLITE_NOMEM; - } - } -} - -/* -** Attempt to advance the node-reader object passed as the first argument to -** the next entry on the node. -** -** Return an error code if an error occurs (SQLITE_NOMEM is possible). -** Otherwise return SQLITE_OK. If there is no next entry on the node -** (e.g. because the current entry is the last) set NodeReader->aNode to -** NULL to indicate EOF. Otherwise, populate the NodeReader structure output -** variables for the new entry. -*/ -static int nodeReaderNext(NodeReader *p){ - int bFirst = (p->term.n==0); /* True for first term on the node */ - int nPrefix = 0; /* Bytes to copy from previous term */ - int nSuffix = 0; /* Bytes to append to the prefix */ - int rc = SQLITE_OK; /* Return code */ - - assert( p->aNode ); - if( p->iChild && bFirst==0 ) p->iChild++; - if( p->iOff>=p->nNode ){ - /* EOF */ - p->aNode = 0; - }else{ - if( bFirst==0 ){ - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix); - } - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); - - if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){ - return FTS_CORRUPT_VTAB; - } - blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); - 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; - if( p->iChild==0 ){ - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); - if( (p->nNode-p->iOff)nDoclist ){ - return FTS_CORRUPT_VTAB; - } - p->aDoclist = &p->aNode[p->iOff]; - p->iOff += p->nDoclist; - } - } - } - - assert_fts3_nc( p->iOff<=p->nNode ); - return rc; -} - -/* -** Release all dynamic resources held by node-reader object *p. -*/ -static void nodeReaderRelease(NodeReader *p){ - sqlite3_free(p->term.a); -} - -/* -** Initialize a node-reader object to read the node in buffer aNode/nNode. -** -** If successful, SQLITE_OK is returned and the NodeReader object set to -** point to the first entry on the node (if any). Otherwise, an SQLite -** error code is returned. -*/ -static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ - memset(p, 0, sizeof(NodeReader)); - p->aNode = aNode; - p->nNode = nNode; - - /* Figure out if this is a leaf or an internal node. */ - if( aNode && aNode[0] ){ - /* An internal node. */ - p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); - }else{ - p->iOff = 1; - } - - return aNode ? nodeReaderNext(p) : SQLITE_OK; -} - -/* -** This function is called while writing an FTS segment each time a leaf o -** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed -** to be greater than the largest key on the node just written, but smaller -** than or equal to the first key that will be written to the next leaf -** node. -** -** The block id of the leaf node just written to disk may be found in -** (pWriter->aNodeWriter[0].iBlock) when this function is called. -*/ -static int fts3IncrmergePush( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - const char *zTerm, /* Term to write to internal node */ - int nTerm /* Bytes at zTerm */ -){ - sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock; - int iLayer; - - assert( nTerm>0 ); - for(iLayer=1; ALWAYS(iLayeraNodeWriter[iLayer]; - int rc = SQLITE_OK; - int nPrefix; - int nSuffix; - int nSpace; - - /* Figure out how much space the key will consume if it is written to - ** the current node of layer iLayer. Due to the prefix compression, - ** the space required changes depending on which node the key is to - ** be added to. */ - nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - if(nSuffix<=0 ) return FTS_CORRUPT_VTAB; - nSpace = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - - if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ - /* If the current node of layer iLayer contains zero keys, or if adding - ** the key to it will not cause it to grow to larger than nNodeSize - ** bytes in size, write the key here. */ - - Blob *pBlk = &pNode->block; - if( pBlk->n==0 ){ - blobGrowBuffer(pBlk, p->nNodeSize, &rc); - if( rc==SQLITE_OK ){ - pBlk->a[0] = (char)iLayer; - pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr); - } - } - blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc); - blobGrowBuffer(&pNode->key, nTerm, &rc); - - if( rc==SQLITE_OK ){ - if( pNode->key.n ){ - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); - } - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); - assert( nPrefix+nSuffix<=nTerm ); - assert( nPrefix>=0 ); - memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); - pBlk->n += nSuffix; - - memcpy(pNode->key.a, zTerm, nTerm); - pNode->key.n = nTerm; - } - }else{ - /* Otherwise, flush the current node of layer iLayer to disk. - ** Then allocate a new, empty sibling node. The key will be written - ** into the parent of this node. */ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - - assert( pNode->block.nAlloc>=p->nNodeSize ); - pNode->block.a[0] = (char)iLayer; - pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1); - - iNextPtr = pNode->iBlock; - pNode->iBlock++; - pNode->key.n = 0; - } - - if( rc!=SQLITE_OK || iNextPtr==0 ) return rc; - iPtr = iNextPtr; - } - - assert( 0 ); - return 0; -} - -/* -** Append a term and (optionally) doclist to the FTS segment node currently -** stored in blob *pNode. The node need not contain any terms, but the -** header must be written before this function is called. -** -** A node header is a single 0x00 byte for a leaf node, or a height varint -** followed by the left-hand-child varint for an internal node. -** -** The term to be appended is passed via arguments zTerm/nTerm. For a -** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal -** node, both aDoclist and nDoclist must be passed 0. -** -** If the size of the value in blob pPrev is zero, then this is the first -** term written to the node. Otherwise, pPrev contains a copy of the -** previous term. Before this function returns, it is updated to contain a -** copy of zTerm/nTerm. -** -** It is assumed that the buffer associated with pNode is already large -** enough to accommodate the new entry. The buffer associated with pPrev -** is extended by this function if required. -** -** If an error (i.e. OOM condition) occurs, an SQLite error code is -** returned. Otherwise, SQLITE_OK. -*/ -static int fts3AppendToNode( - Blob *pNode, /* Current node image to append to */ - Blob *pPrev, /* Buffer containing previous term written */ - const char *zTerm, /* New term to write */ - int nTerm, /* Size of zTerm in bytes */ - const char *aDoclist, /* Doclist (or NULL) to write */ - int nDoclist /* Size of aDoclist in bytes */ -){ - int rc = SQLITE_OK; /* Return code */ - int bFirst = (pPrev->n==0); /* True if this is the first term written */ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - - /* Node must have already been started. There must be a doclist for a - ** leaf node, and there must not be a doclist for an internal node. */ - assert( pNode->n>0 ); - assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) ); - - blobGrowBuffer(pPrev, nTerm, &rc); - if( rc!=SQLITE_OK ) return rc; - assert( pPrev!=0 ); - assert( pPrev->a!=0 ); - - nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - memcpy(pPrev->a, zTerm, nTerm); - pPrev->n = nTerm; - - if( bFirst==0 ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix); - } - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix); - memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix); - pNode->n += nSuffix; - - if( aDoclist ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist); - memcpy(&pNode->a[pNode->n], aDoclist, nDoclist); - pNode->n += nDoclist; - } - - assert( pNode->n<=pNode->nAlloc ); - - return SQLITE_OK; -} - -/* -** Append the current term and doclist pointed to by cursor pCsr to the -** appendable b-tree segment opened for writing by pWriter. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int fts3IncrmergeAppend( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */ -){ - const char *zTerm = pCsr->zTerm; - int nTerm = pCsr->nTerm; - const char *aDoclist = pCsr->aDoclist; - int nDoclist = pCsr->nDoclist; - int rc = SQLITE_OK; /* Return code */ - int nSpace; /* Total space in bytes required on leaf */ - int nPrefix; /* Size of prefix shared with previous term */ - int nSuffix; /* Size of suffix (nTerm - nPrefix) */ - NodeWriter *pLeaf; /* Object used to write leaf nodes */ - - 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 = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - - /* If the current block is not empty, and if adding this term/doclist - ** to the current block would make it larger than Fts3Table.nNodeSize bytes, - ** and if there is still room for another leaf page, write this block out to - ** the database. */ - if( pLeaf->block.n>0 - && (pLeaf->block.n + nSpace)>p->nNodeSize - && pLeaf->iBlock < (pWriter->iStart + pWriter->nLeafEst) - ){ - rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); - pWriter->nWork++; - - /* Add the current term to the parent node. The term added to the - ** parent must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pLeaf->key), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - if( rc==SQLITE_OK ){ - rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1); - } - - /* Advance to the next output block */ - pLeaf->iBlock++; - pLeaf->key.n = 0; - pLeaf->block.n = 0; - - nSuffix = nTerm; - nSpace = 1; - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - } - - pWriter->nLeafData += nSpace; - blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); - if( rc==SQLITE_OK ){ - if( pLeaf->block.n==0 ){ - pLeaf->block.n = 1; - pLeaf->block.a[0] = '\0'; - } - rc = fts3AppendToNode( - &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist - ); - } - - return rc; -} - -/* -** This function is called to release all dynamic resources held by the -** merge-writer object pWriter, and if no error has occurred, to flush -** all outstanding node buffers held by pWriter to disk. -** -** If *pRc is not SQLITE_OK when this function is called, then no attempt -** is made to write any data to disk. Instead, this function serves only -** to release outstanding resources. -** -** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while -** flushing buffers to disk, *pRc is set to an SQLite error code before -** returning. -*/ -static void fts3IncrmergeRelease( - Fts3Table *p, /* FTS3 table handle */ - IncrmergeWriter *pWriter, /* Merge-writer object */ - int *pRc /* IN/OUT: Error code */ -){ - int i; /* Used to iterate through non-root layers */ - int iRoot; /* Index of root in pWriter->aNodeWriter */ - NodeWriter *pRoot; /* NodeWriter for root node */ - int rc = *pRc; /* Error code */ - - /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment - ** root node. If the segment fits entirely on a single leaf node, iRoot - ** will be set to 0. If the root node is the parent of the leaves, iRoot - ** will be 1. And so on. */ - for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ - NodeWriter *pNode = &pWriter->aNodeWriter[iRoot]; - if( pNode->block.n>0 ) break; - assert( *pRc || pNode->block.nAlloc==0 ); - assert( *pRc || pNode->key.nAlloc==0 ); - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Empty output segment. This is a no-op. */ - if( iRoot<0 ) return; - - /* The entire output segment fits on a single node. Normally, this means - ** the node would be stored as a blob in the "root" column of the %_segdir - ** table. However, this is not permitted in this case. The problem is that - ** space has already been reserved in the %_segments table, and so the - ** start_block and end_block fields of the %_segdir table must be populated. - ** And, by design or by accident, released versions of FTS cannot handle - ** segments that fit entirely on the root node with start_block!=0. - ** - ** Instead, create a synthetic root node that contains nothing but a - ** pointer to the single content node. So that the segment consists of a - ** single leaf and a single interior (root) node. - ** - ** Todo: Better might be to defer allocating space in the %_segments - ** table until we are sure it is needed. - */ - if( iRoot==0 ){ - Blob *pBlock = &pWriter->aNodeWriter[1].block; - blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc); - if( rc==SQLITE_OK ){ - pBlock->a[0] = 0x01; - pBlock->n = 1 + sqlite3Fts3PutVarint( - &pBlock->a[1], pWriter->aNodeWriter[0].iBlock - ); - } - iRoot = 1; - } - pRoot = &pWriter->aNodeWriter[iRoot]; - - /* Flush all currently outstanding nodes to disk. */ - for(i=0; iaNodeWriter[i]; - if( pNode->block.n>0 && rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - } - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Write the %_segdir record. */ - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, - pWriter->iAbsLevel+1, /* level */ - pWriter->iIdx, /* idx */ - pWriter->iStart, /* start_block */ - pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ - pWriter->iEnd, /* end_block */ - (pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */ - pRoot->block.a, pRoot->block.n /* root */ - ); - } - sqlite3_free(pRoot->block.a); - sqlite3_free(pRoot->key.a); - - *pRc = rc; -} - -/* -** Compare the term in buffer zLhs (size in bytes nLhs) with that in -** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of -** the other, it is considered to be smaller than the other. -** -** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve -** if it is greater. -*/ -static int fts3TermCmp( - const char *zLhs, int nLhs, /* LHS of comparison */ - const char *zRhs, int nRhs /* RHS of comparison */ -){ - int nCmp = MIN(nLhs, nRhs); - int res; - - if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){ - res = memcmp(zLhs, zRhs, nCmp); - }else{ - res = 0; - } - if( res==0 ) res = nLhs - nRhs; - - return res; -} - - -/* -** Query to see if the entry in the %_segments table with blockid iEnd is -** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before -** returning. Otherwise, set *pbRes to 0. -** -** Or, if an error occurs while querying the database, return an SQLite -** error code. The final value of *pbRes is undefined in this case. -** -** This is used to test if a segment is an "appendable" segment. If it -** is, then a NULL entry has been inserted into the %_segments table -** with blockid %_segdir.end_block. -*/ -static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){ - int bRes = 0; /* Result to set *pbRes to */ - sqlite3_stmt *pCheck = 0; /* Statement to query database with */ - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck, 1, iEnd); - if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; - rc = sqlite3_reset(pCheck); - } - - *pbRes = bRes; - return rc; -} - -/* -** This function is called when initializing an incremental-merge operation. -** It checks if the existing segment with index value iIdx at absolute level -** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the -** merge-writer object *pWriter is initialized to write to it. -** -** An existing segment can be appended to by an incremental merge if: -** -** * It was initially created as an appendable segment (with all required -** space pre-allocated), and -** -** * The first key read from the input (arguments zKey and nKey) is -** greater than the largest key currently stored in the potential -** output segment. -*/ -static int fts3IncrmergeLoad( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of candidate output segment */ - const char *zKey, /* First key to write */ - int nKey, /* Number of bytes in nKey */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return code */ - sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0); - if( rc==SQLITE_OK ){ - sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */ - sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */ - sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */ - const char *aRoot = 0; /* Pointer to %_segdir.root buffer */ - int nRoot = 0; /* Size of aRoot[] in bytes */ - int rc2; /* Return code from sqlite3_reset() */ - int bAppendable = 0; /* Set to true if segment is appendable */ - - /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */ - sqlite3_bind_int64(pSelect, 1, iAbsLevel+1); - sqlite3_bind_int(pSelect, 2, iIdx); - if( sqlite3_step(pSelect)==SQLITE_ROW ){ - iStart = sqlite3_column_int64(pSelect, 1); - iLeafEnd = sqlite3_column_int64(pSelect, 2); - fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData); - if( pWriter->nLeafData<0 ){ - pWriter->nLeafData = pWriter->nLeafData * -1; - } - pWriter->bNoLeafData = (pWriter->nLeafData==0); - nRoot = sqlite3_column_bytes(pSelect, 4); - aRoot = sqlite3_column_blob(pSelect, 4); - if( aRoot==0 ){ - sqlite3_reset(pSelect); - return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB; - } - }else{ - return sqlite3_reset(pSelect); - } - - /* Check for the zero-length marker in the %_segments table */ - rc = fts3IsAppendable(p, iEnd, &bAppendable); - - /* Check that zKey/nKey is larger than the largest key the candidate */ - if( rc==SQLITE_OK && bAppendable ){ - char *aLeaf = 0; - int nLeaf = 0; - - rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); - if( rc==SQLITE_OK ){ - NodeReader reader; - for(rc = nodeReaderInit(&reader, aLeaf, nLeaf); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - assert( reader.aNode ); - } - if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){ - bAppendable = 0; - } - nodeReaderRelease(&reader); - } - sqlite3_free(aLeaf); - } - - if( rc==SQLITE_OK && bAppendable ){ - /* It is possible to append to this segment. Set up the IncrmergeWriter - ** object to do so. */ - int i; - int nHeight = (int)aRoot[0]; - NodeWriter *pNode; - if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){ - sqlite3_reset(pSelect); - return FTS_CORRUPT_VTAB; - } - - pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; - pWriter->iStart = iStart; - pWriter->iEnd = iEnd; - pWriter->iAbsLevel = iAbsLevel; - pWriter->iIdx = iIdx; - - for(i=nHeight+1; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - - pNode = &pWriter->aNodeWriter[nHeight]; - pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; - blobGrowBuffer(&pNode->block, - MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc - ); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aRoot, nRoot); - pNode->block.n = nRoot; - memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING); - } - - for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ - NodeReader reader; - memset(&reader, 0, sizeof(reader)); - pNode = &pWriter->aNodeWriter[i]; - - if( pNode->block.a){ - rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); - blobGrowBuffer(&pNode->key, reader.term.n, &rc); - if( rc==SQLITE_OK ){ - 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 = 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; - memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING); - } - sqlite3_free(aBlock); - } - } - } - nodeReaderRelease(&reader); - } - } - - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** Determine the largest segment index value that exists within absolute -** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus -** one before returning SQLITE_OK. Or, if there are no segments at all -** within level iAbsLevel, set *piIdx to zero. -** -** If an error occurs, return an SQLite error code. The final value of -** *piIdx is undefined in this case. -*/ -static int fts3IncrmergeOutputIdx( - Fts3Table *p, /* FTS Table handle */ - sqlite3_int64 iAbsLevel, /* Absolute index of input segments */ - int *piIdx /* OUT: Next free index at iAbsLevel+1 */ -){ - int rc; - sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */ - - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1); - sqlite3_step(pOutputIdx); - *piIdx = sqlite3_column_int(pOutputIdx, 0); - rc = sqlite3_reset(pOutputIdx); - } - - return rc; -} - -/* -** Allocate an appendable output segment on absolute level iAbsLevel+1 -** with idx value iIdx. -** -** In the %_segdir table, a segment is defined by the values in three -** columns: -** -** start_block -** leaves_end_block -** end_block -** -** When an appendable segment is allocated, it is estimated that the -** maximum number of leaf blocks that may be required is the sum of the -** number of leaf blocks consumed by the input segments, plus the number -** of input segments, multiplied by two. This value is stored in stack -** variable nLeafEst. -** -** A total of 16*nLeafEst blocks are allocated when an appendable segment -** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous -** array of leaf nodes starts at the first block allocated. The array -** of interior nodes that are parents of the leaf nodes start at block -** (start_block + (1 + end_block - start_block) / 16). And so on. -** -** In the actual code below, the value "16" is replaced with the -** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT. -*/ -static int fts3IncrmergeWriter( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of new output segment */ - Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return Code */ - int i; /* Iterator variable */ - int nLeafEst = 0; /* Blocks allocated for leaf nodes */ - sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ - sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ - - /* Calculate nLeafEst. */ - rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); - sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); - if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ - nLeafEst = sqlite3_column_int(pLeafEst, 0); - } - rc = sqlite3_reset(pLeafEst); - } - if( rc!=SQLITE_OK ) return rc; - - /* Calculate the first block to use in the output segment */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){ - pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0); - pWriter->iEnd = pWriter->iStart - 1; - pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT; - } - rc = sqlite3_reset(pFirstBlock); - } - if( rc!=SQLITE_OK ) return rc; - - /* Insert the marker in the %_segments table to make sure nobody tries - ** to steal the space just allocated. This is also used to identify - ** appendable segments. */ - rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); - if( rc!=SQLITE_OK ) return rc; - - pWriter->iAbsLevel = iAbsLevel; - pWriter->nLeafEst = nLeafEst; - pWriter->iIdx = iIdx; - - /* Set up the array of NodeWriter objects */ - for(i=0; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - return SQLITE_OK; -} - -/* -** Remove an entry from the %_segdir table. This involves running the -** following two statements: -** -** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx -** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx -** -** The DELETE statement removes the specific %_segdir level. The UPDATE -** statement ensures that the remaining segments have contiguously allocated -** idx values. -*/ -static int fts3RemoveSegdirEntry( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to delete from */ - int iIdx /* Index of %_segdir entry to delete */ -){ - int rc; /* Return code */ - sqlite3_stmt *pDelete = 0; /* DELETE statement */ - - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, iAbsLevel); - sqlite3_bind_int(pDelete, 2, iIdx); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** One or more segments have just been removed from absolute level iAbsLevel. -** Update the 'idx' values of the remaining segments in the level so that -** the idx values are a contiguous sequence starting from 0. -*/ -static int fts3RepackSegdirLevel( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel /* Absolute level to repack */ -){ - int rc; /* Return code */ - int *aIdx = 0; /* Array of remaining idx values */ - int nIdx = 0; /* Valid entries in aIdx[] */ - int nAlloc = 0; /* Allocated size of aIdx[] */ - int i; /* Iterator variable */ - sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */ - sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */ - - rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int64(pSelect, 1, iAbsLevel); - while( SQLITE_ROW==sqlite3_step(pSelect) ){ - if( nIdx>=nAlloc ){ - int *aNew; - nAlloc += 16; - aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int)); - if( !aNew ){ - rc = SQLITE_NOMEM; - break; - } - aIdx = aNew; - } - aIdx[nIdx++] = sqlite3_column_int(pSelect, 0); - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0); - } - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate, 2, iAbsLevel); - } - - assert( p->bIgnoreSavepoint==0 ); - p->bIgnoreSavepoint = 1; - for(i=0; rc==SQLITE_OK && ibIgnoreSavepoint = 0; - - sqlite3_free(aIdx); - return rc; -} - -static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){ - pNode->a[0] = (char)iHeight; - if( iChild ){ - assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) ); - pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild); - }else{ - assert( pNode->nAlloc>=1 ); - pNode->n = 1; - } -} - -/* -** The first two arguments are a pointer to and the size of a segment b-tree -** node. The node may be a leaf or an internal node. -** -** This function creates a new node image in blob object *pNew by copying -** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes) -** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode. -*/ -static int fts3TruncateNode( - const char *aNode, /* Current node image */ - int nNode, /* Size of aNode in bytes */ - Blob *pNew, /* OUT: Write new node image here */ - const char *zTerm, /* Omit all terms smaller than this */ - int nTerm, /* Size of zTerm in bytes */ - sqlite3_int64 *piBlock /* OUT: Block number in next layer down */ -){ - NodeReader reader; /* Reader object */ - Blob prev = {0, 0, 0}; /* Previous term written to new node */ - int rc = SQLITE_OK; /* Return code */ - int bLeaf; /* True for a leaf node */ - - if( nNode<1 ) return FTS_CORRUPT_VTAB; - bLeaf = aNode[0]=='\0'; - - /* Allocate required output space */ - blobGrowBuffer(pNew, nNode, &rc); - if( rc!=SQLITE_OK ) return rc; - pNew->n = 0; - - /* Populate new node buffer */ - for(rc = nodeReaderInit(&reader, aNode, nNode); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - if( pNew->n==0 ){ - int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm); - if( res<0 || (bLeaf==0 && res==0) ) continue; - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - rc = fts3AppendToNode( - pNew, &prev, reader.term.a, reader.term.n, - reader.aDoclist, reader.nDoclist - ); - if( rc!=SQLITE_OK ) break; - } - if( pNew->n==0 ){ - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - assert( pNew->n<=pNew->nAlloc ); - - nodeReaderRelease(&reader); - sqlite3_free(prev.a); - return rc; -} - -/* -** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute -** level iAbsLevel. This may involve deleting entries from the %_segments -** table, and modifying existing entries in both the %_segments and %_segdir -** tables. -** -** SQLITE_OK is returned if the segment is updated successfully. Or an -** SQLite error code otherwise. -*/ -static int fts3TruncateSegment( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */ - int iIdx, /* Index within level of segment to modify */ - const char *zTerm, /* Remove terms smaller than this */ - int nTerm /* Number of bytes in buffer zTerm */ -){ - int rc = SQLITE_OK; /* Return code */ - Blob root = {0,0,0}; /* New root page image */ - Blob block = {0,0,0}; /* Buffer used for any other block */ - sqlite3_int64 iBlock = 0; /* Block id */ - sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */ - sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */ - sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0); - if( rc==SQLITE_OK ){ - int rc2; /* sqlite3_reset() return code */ - sqlite3_bind_int64(pFetch, 1, iAbsLevel); - sqlite3_bind_int(pFetch, 2, iIdx); - if( SQLITE_ROW==sqlite3_step(pFetch) ){ - const char *aRoot = sqlite3_column_blob(pFetch, 4); - int nRoot = sqlite3_column_bytes(pFetch, 4); - iOldStart = sqlite3_column_int64(pFetch, 1); - rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); - } - rc2 = sqlite3_reset(pFetch); - if( rc==SQLITE_OK ) rc = rc2; - } - - while( rc==SQLITE_OK && iBlock ){ - char *aBlock = 0; - int nBlock = 0; - iNewStart = iBlock; - - rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); - if( rc==SQLITE_OK ){ - rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, iNewStart, block.a, block.n); - } - sqlite3_free(aBlock); - } - - /* Variable iNewStart now contains the first valid leaf node. */ - if( rc==SQLITE_OK && iNewStart ){ - sqlite3_stmt *pDel = 0; - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDel, 1, iOldStart); - sqlite3_bind_int64(pDel, 2, iNewStart-1); - sqlite3_step(pDel); - rc = sqlite3_reset(pDel); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_stmt *pChomp = 0; - rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pChomp, 1, iNewStart); - sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); - sqlite3_bind_int64(pChomp, 3, iAbsLevel); - sqlite3_bind_int(pChomp, 4, iIdx); - sqlite3_step(pChomp); - rc = sqlite3_reset(pChomp); - sqlite3_bind_null(pChomp, 2); - } - } - - sqlite3_free(root.a); - sqlite3_free(block.a); - return rc; -} - -/* -** This function is called after an incrmental-merge operation has run to -** merge (or partially merge) two or more segments from absolute level -** iAbsLevel. -** -** Each input segment is either removed from the db completely (if all of -** its data was copied to the output segment by the incrmerge operation) -** or modified in place so that it no longer contains those entries that -** have been duplicated in the output segment. -*/ -static int fts3IncrmergeChomp( - Fts3Table *p, /* FTS table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level containing segments */ - Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */ - int *pnRem /* Number of segments not deleted */ -){ - int i; - int nRem = 0; - int rc = SQLITE_OK; - - for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){ - Fts3SegReader *pSeg = 0; - int j; - - /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding - ** somewhere in the pCsr->apSegment[] array. */ - for(j=0; ALWAYS(jnSegment); j++){ - pSeg = pCsr->apSegment[j]; - if( pSeg->iIdx==i ) break; - } - assert( jnSegment && pSeg->iIdx==i ); - - if( pSeg->aNode==0 ){ - /* Seg-reader is at EOF. Remove the entire input segment. */ - rc = fts3DeleteSegment(p, pSeg); - if( rc==SQLITE_OK ){ - rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx); - } - *pnRem = 0; - }else{ - /* The incremental merge did not copy all the data from this - ** segment to the upper level. The segment is modified in place - ** so that it contains no keys smaller than zTerm/nTerm. */ - const char *zTerm = pSeg->zTerm; - int nTerm = pSeg->nTerm; - rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm); - nRem++; - } - } - - if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){ - rc = fts3RepackSegdirLevel(p, iAbsLevel); - } - - *pnRem = nRem; - return rc; -} - -/* -** Store an incr-merge hint in the database. -*/ -static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pReplace = 0; - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT); - sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); - sqlite3_step(pReplace); - rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); - } - - return rc; -} - -/* -** Load an incr-merge hint from the database. The incr-merge hint, if one -** exists, is stored in the rowid==1 row of the %_stat table. -** -** If successful, populate blob *pHint with the value read from the %_stat -** table and return SQLITE_OK. Otherwise, if an error occurs, return an -** SQLite error code. -*/ -static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pSelect = 0; - int rc; - - pHint->n = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT); - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - const char *aHint = sqlite3_column_blob(pSelect, 0); - int nHint = sqlite3_column_bytes(pSelect, 0); - if( aHint ){ - blobGrowBuffer(pHint, nHint, &rc); - if( rc==SQLITE_OK ){ - if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint); - pHint->n = nHint; - } - } - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, append an entry to the hint stored in blob *pHint. Each entry -** consists of two varints, the absolute level number of the input segments -** and the number of input segments. -** -** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs, -** set *pRc to an SQLite error code before returning. -*/ -static void fts3IncrmergeHintPush( - Blob *pHint, /* Hint blob to append to */ - i64 iAbsLevel, /* First varint to store in hint */ - int nInput, /* Second varint to store in hint */ - int *pRc /* IN/OUT: Error code */ -){ - blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc); - if( *pRc==SQLITE_OK ){ - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel); - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput); - } -} - -/* -** Read the last entry (most recently pushed) from the hint blob *pHint -** and then remove the entry. Write the two values read to *piAbsLevel and -** *pnInput before returning. -** -** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does -** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB. -*/ -static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ - const int nHint = pHint->n; - int i; - - i = pHint->n-1; - if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - if( i==0 ) return FTS_CORRUPT_VTAB; - i--; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - - pHint->n = i; - i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); - i += fts3GetVarint32(&pHint->a[i], pnInput); - assert( i<=nHint ); - if( i!=nHint ) return FTS_CORRUPT_VTAB; - - return SQLITE_OK; -} - - -/* -** Attempt an incremental merge that writes nMerge leaf blocks. -** -** Incremental merges happen nMin segments at a time. The segments -** to be merged are the nMin oldest segments (the ones with the smallest -** values for the _segdir.idx field) in the highest level that contains -** at least nMin segments. Multiple merges might occur in an attempt to -** write the quota of nMerge leaf blocks. -*/ -SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ - int rc; /* Return code */ - int nRem = nMerge; /* Number of leaf pages yet to be written */ - Fts3MultiSegReader *pCsr; /* Cursor used to read input data */ - Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */ - IncrmergeWriter *pWriter; /* Writer object */ - int nSeg = 0; /* Number of input segments */ - sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */ - Blob hint = {0, 0, 0}; /* Hint read from %_stat table */ - int bDirtyHint = 0; /* True if blob 'hint' has been modified */ - - /* Allocate space for the cursor, filter and writer objects */ - const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc); - if( !pWriter ) return SQLITE_NOMEM; - pFilter = (Fts3SegFilter *)&pWriter[1]; - pCsr = (Fts3MultiSegReader *)&pFilter[1]; - - rc = fts3IncrmergeHintLoad(p, &hint); - while( rc==SQLITE_OK && nRem>0 ){ - const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex; - sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */ - int bUseHint = 0; /* True if attempting to append */ - int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ - - /* Search the %_segdir table for the absolute level with the smallest - ** relative level number that contains at least nMin segments, if any. - ** If one is found, set iAbsLevel to the absolute level number and - ** nSeg to nMin. If no level with at least nMin segments can be found, - ** set nSeg to -1. - */ - rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); - sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin)); - if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ - iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - nSeg = sqlite3_column_int(pFindLevel, 1); - assert( nSeg>=2 ); - }else{ - nSeg = -1; - } - rc = sqlite3_reset(pFindLevel); - - /* If the hint read from the %_stat table is not empty, check if the - ** last entry in it specifies a relative level smaller than or equal - ** to the level identified by the block above (if any). If so, this - ** iteration of the loop will work on merging at the hinted level. - */ - if( rc==SQLITE_OK && hint.n ){ - int nHint = hint.n; - sqlite3_int64 iHintAbsLevel = 0; /* Hint level */ - int nHintSeg = 0; /* Hint number of segments */ - - rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg); - if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){ - /* Based on the scan in the block above, it is known that there - ** are no levels with a relative level smaller than that of - ** iAbsLevel with more than nSeg segments, or if nSeg is -1, - ** no levels with more than nMin segments. Use this to limit the - ** value of nHintSeg to avoid a large memory allocation in case the - ** merge-hint is corrupt*/ - iAbsLevel = iHintAbsLevel; - nSeg = MIN(MAX(nMin,nSeg), nHintSeg); - bUseHint = 1; - bDirtyHint = 1; - }else{ - /* This undoes the effect of the HintPop() above - so that no entry - ** is removed from the hint blob. */ - hint.n = nHint; - } - } - - /* If nSeg is less that zero, then there is no level with at least - ** nMin segments and no hint in the %_stat table. No work to do. - ** Exit early in this case. */ - if( nSeg<=0 ) break; - - assert( nMod<=0x7FFFFFFF ); - if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){ - rc = FTS_CORRUPT_VTAB; - break; - } - - /* Open a cursor to iterate through the contents of the oldest nSeg - ** indexes of absolute level iAbsLevel. If this cursor is opened using - ** the 'hint' parameters, it is possible that there are less than nSeg - ** segments available in level iAbsLevel. In this case, no work is - ** done on iAbsLevel - fall through to the next iteration of the loop - ** to start work on some other level. */ - memset(pWriter, 0, nAlloc); - pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; - - if( rc==SQLITE_OK ){ - rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); - assert( bUseHint==1 || bUseHint==0 ); - if( iIdx==0 || (bUseHint && iIdx==1) ){ - int bIgnore = 0; - rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore); - if( bIgnore ){ - pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY; - } - } - } - - if( rc==SQLITE_OK ){ - rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); - } - if( SQLITE_OK==rc && pCsr->nSegment==nSeg - && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) - ){ - int bEmpty = 0; - rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( rc==SQLITE_OK ){ - bEmpty = 1; - }else if( rc!=SQLITE_ROW ){ - sqlite3Fts3SegReaderFinish(pCsr); - break; - } - if( bUseHint && iIdx>0 ){ - const char *zKey = pCsr->zTerm; - int nKey = pCsr->nTerm; - rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); - }else{ - rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); - } - - if( rc==SQLITE_OK && pWriter->nLeafEst ){ - fts3LogMerge(nSeg, iAbsLevel); - if( bEmpty==0 ){ - do { - rc = fts3IncrmergeAppend(p, pWriter, pCsr); - if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; - }while( rc==SQLITE_ROW ); - } - - /* Update or delete the input segments */ - if( rc==SQLITE_OK ){ - nRem -= (1 + pWriter->nWork); - rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg); - if( nSeg!=0 ){ - bDirtyHint = 1; - fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc); - } - } - } - - if( nSeg!=0 ){ - pWriter->nLeafData = pWriter->nLeafData * -1; - } - fts3IncrmergeRelease(p, pWriter, &rc); - if( nSeg==0 && pWriter->bNoLeafData==0 ){ - fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData); - } - } - - sqlite3Fts3SegReaderFinish(pCsr); - } - - /* Write the hint values into the %_stat table for the next incr-merger */ - if( bDirtyHint && rc==SQLITE_OK ){ - rc = fts3IncrmergeHintStore(p, &hint); - } - - sqlite3_free(pWriter); - sqlite3_free(hint.a); - return rc; -} - -/* -** Convert the text beginning at *pz into an integer and return -** its value. Advance *pz to point to the first character past -** the integer. -** -** This function used for parameters to merge= and incrmerge= -** commands. -*/ -static int fts3Getint(const char **pz){ - const char *z = *pz; - int i = 0; - while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0'; - *pz = z; - return i; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('merge=A,B'); -** -** A and B are integers that decode to be the number of leaf pages -** written for the merge, and the minimum number of segments on a level -** before it will be selected for a merge, respectively. -*/ -static int fts3DoIncrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing "A,B" */ -){ - int rc; - int nMin = (MergeCount(p) / 2); - int nMerge = 0; - const char *z = zParam; - - /* Read the first integer value */ - nMerge = fts3Getint(&z); - - /* If the first integer value is followed by a ',', read the second - ** integer value. */ - if( z[0]==',' && z[1]!='\0' ){ - z++; - nMin = fts3Getint(&z); - } - - if( z[0]!='\0' || nMin<2 ){ - rc = SQLITE_ERROR; - }else{ - rc = SQLITE_OK; - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3Incrmerge(p, nMerge, nMin); - } - sqlite3Fts3SegmentsClose(p); - } - return rc; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('automerge=X'); -** -** where X is an integer. X==0 means to turn automerge off. X!=0 means -** turn it on. The setting is persistent. -*/ -static int fts3DoAutoincrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing boolean */ -){ - int rc = SQLITE_OK; - sqlite3_stmt *pStmt = 0; - p->nAutoincrmerge = fts3Getint(&zParam); - if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){ - p->nAutoincrmerge = 8; - } - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - if( rc ) return rc; - } - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ) return rc; - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - return rc; -} - -/* -** Return a 64-bit checksum for the FTS index entry specified by the -** arguments to this function. -*/ -static u64 fts3ChecksumEntry( - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of zTerm in bytes */ - int iLangid, /* Language id for current row */ - int iIndex, /* Index (0..Fts3Table.nIndex-1) */ - i64 iDocid, /* Docid for current row. */ - int iCol, /* Column number */ - int iPos /* Position */ -){ - int i; - u64 ret = (u64)iDocid; - - ret += (ret<<3) + iLangid; - ret += (ret<<3) + iIndex; - ret += (ret<<3) + iCol; - ret += (ret<<3) + iPos; - for(i=0; inIndex-1) */ - int *pRc /* OUT: Return code */ -){ - Fts3SegFilter filter; - Fts3MultiSegReader csr; - int rc; - u64 cksum = 0; - - if( *pRc ) return 0; - - memset(&filter, 0, sizeof(filter)); - memset(&csr, 0, sizeof(csr)); - filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; - filter.flags |= FTS3_SEGMENT_SCAN; - - rc = sqlite3Fts3SegReaderCursor( - p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(p, &csr, &filter); - } - - if( rc==SQLITE_OK ){ - while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){ - char *pCsr = csr.aDoclist; - char *pEnd = &pCsr[csr.nDoclist]; - - i64 iDocid = 0; - i64 iCol = 0; - u64 iPos = 0; - - pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); - while( pCsrbDescIdx ){ - iDocid = (i64)((u64)iDocid - iVal); - }else{ - iDocid = (i64)((u64)iDocid + iVal); - } - } - }else{ - iPos += (iVal - 2); - cksum = cksum ^ fts3ChecksumEntry( - csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid, - (int)iCol, (int)iPos - ); - } - } - } - } - } - sqlite3Fts3SegReaderFinish(&csr); - - *pRc = rc; - return cksum; -} - -/* -** Check if the contents of the FTS index match the current contents of the -** content table. If no error occurs and the contents do match, set *pbOk -** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk -** to false before returning. -** -** If an error occurs (e.g. an OOM or IO error), return an SQLite error -** code. The final value of *pbOk is undefined in this case. -*/ -SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ - int rc = SQLITE_OK; /* Return code */ - u64 cksum1 = 0; /* Checksum based on FTS index contents */ - u64 cksum2 = 0; /* Checksum based on %_content contents */ - sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */ - - /* This block calculates the checksum according to the FTS index. */ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); - while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int iLangid = sqlite3_column_int(pAllLangid, 0); - int i; - for(i=0; inIndex; i++){ - cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - /* This block calculates the checksum according to the %_content table */ - if( rc==SQLITE_OK ){ - sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; - sqlite3_stmt *pStmt = 0; - char *zSql; - - zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - i64 iDocid = sqlite3_column_int64(pStmt, 0); - int iLang = langidFromSelect(p, pStmt); - int iCol; - - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); - sqlite3_tokenizer_cursor *pT = 0; - - rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); - if( rc==SQLITE_OK ){ - int i; - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, nToken, iLang, 0, iDocid, iCol, iPos - ); - for(i=1; inIndex; i++){ - if( p->aIndex[i].nPrefix<=nToken ){ - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos - ); - } - } - } - } - if( pT ) pModule->xClose(pT); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - } - } - - sqlite3_finalize(pStmt); - } - - if( rc==SQLITE_CORRUPT_VTAB ){ - rc = SQLITE_OK; - *pbOk = 0; - }else{ - *pbOk = (rc==SQLITE_OK && cksum1==cksum2); - } - return rc; -} - -/* -** Run the integrity-check. If no error occurs and the current contents of -** the FTS index are correct, return SQLITE_OK. Or, if the contents of the -** FTS index are incorrect, return SQLITE_CORRUPT_VTAB. -** -** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite -** error code. -** -** The integrity-check works as follows. For each token and indexed token -** prefix in the document set, a 64-bit checksum is calculated (by code -** in fts3ChecksumEntry()) based on the following: -** -** + The index number (0 for the main index, 1 for the first prefix -** index etc.), -** + The token (or token prefix) text itself, -** + The language-id of the row it appears in, -** + The docid of the row it appears in, -** + The column it appears in, and -** + The tokens position within that column. -** -** The checksums for all entries in the index are XORed together to create -** a single checksum for the entire index. -** -** The integrity-check code calculates the same checksum in two ways: -** -** 1. By scanning the contents of the FTS index, and -** 2. By scanning and tokenizing the content table. -** -** If the two checksums are identical, the integrity-check is deemed to have -** passed. -*/ -static int fts3DoIntegrityCheck( - Fts3Table *p /* FTS3 table handle */ -){ - int rc; - int bOk = 0; - rc = sqlite3Fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; - return rc; -} - -/* -** Handle a 'special' INSERT of the form: -** -** "INSERT INTO tbl(tbl) VALUES()" -** -** Argument pVal contains the result of . Currently the only -** meaningful value to insert is the text 'optimize'. -*/ -static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ - int rc = SQLITE_ERROR; /* Return Code */ - const char *zVal = (const char *)sqlite3_value_text(pVal); - int nVal = sqlite3_value_bytes(pVal); - - if( !zVal ){ - return SQLITE_NOMEM; - }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){ - rc = fts3DoOptimize(p, 0); - }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){ - rc = fts3DoRebuild(p); - }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){ - rc = fts3DoIntegrityCheck(p); - }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){ - rc = fts3DoIncrmerge(p, &zVal[6]); - }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ - rc = fts3DoAutoincrmerge(p, &zVal[10]); - }else if( nVal==5 && 0==sqlite3_strnicmp(zVal, "flush", 5) ){ - rc = sqlite3Fts3PendingTermsFlush(p); - } -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - else{ - int v; - if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ - v = atoi(&zVal[9]); - if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v; - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ - v = atoi(&zVal[11]); - if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v; - rc = SQLITE_OK; - }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){ - p->bNoIncrDoclist = atoi(&zVal[21]); - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){ - v = atoi(&zVal[11]); - if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v; - rc = SQLITE_OK; - } - } -#endif - return rc; -} - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -/* -** Delete all cached deferred doclists. Deferred doclists are cached -** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){ - fts3PendingListDelete(pDef->pList); - pDef->pList = 0; - } -} - -/* -** Free all entries in the pCsr->pDeffered list. Entries are added to -** this list using sqlite3Fts3DeferToken(). -*/ -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - Fts3DeferredToken *pNext; - for(pDef=pCsr->pDeferred; pDef; pDef=pNext){ - pNext = pDef->pNext; - fts3PendingListDelete(pDef->pList); - sqlite3_free(pDef); - } - pCsr->pDeferred = 0; -} - -/* -** Generate deferred-doclists for all tokens in the pCsr->pDeferred list -** based on the row that pCsr currently points to. -** -** A deferred-doclist is like any other doclist with position information -** included, except that it only contains entries for a single row of the -** table, not for all rows. -*/ -SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return code */ - if( pCsr->pDeferred ){ - int i; /* Used to iterate through table columns */ - sqlite3_int64 iDocid; /* Docid of the row pCsr points to */ - Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */ - - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer *pT = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pT->pModule; - - assert( pCsr->isRequireSeek==0 ); - iDocid = sqlite3_column_int64(pCsr->pStmt, 0); - - for(i=0; inColumn && rc==SQLITE_OK; i++){ - if( p->abNotindexed[i]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); - sqlite3_tokenizer_cursor *pTC = 0; - - rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - Fts3PhraseToken *pPT = pDef->pToken; - if( (pDef->iCol>=p->nColumn || pDef->iCol==i) - && (pPT->bFirst==0 || iPos==0) - && (pPT->n==nToken || (pPT->isPrefix && pPT->nz, pPT->n)) - ){ - fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc); - } - } - } - if( pTC ) pModule->xClose(pTC); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - } - - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - if( pDef->pList ){ - rc = fts3PendingListAppendVarint(&pDef->pList, 0); - } - } - } - - return rc; -} - -SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList( - Fts3DeferredToken *p, - char **ppData, - int *pnData -){ - char *pRet; - int nSkip; - sqlite3_int64 dummy; - - *ppData = 0; - *pnData = 0; - - if( p->pList==0 ){ - return SQLITE_OK; - } - - pRet = (char *)sqlite3_malloc64(p->pList->nData); - if( !pRet ) return SQLITE_NOMEM; - - nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy); - *pnData = p->pList->nData - nSkip; - *ppData = pRet; - - memcpy(pRet, &p->pList->aData[nSkip], *pnData); - return SQLITE_OK; -} - -/* -** Add an entry for token pToken to the pCsr->pDeferred list. -*/ -SQLITE_PRIVATE int sqlite3Fts3DeferToken( - Fts3Cursor *pCsr, /* Fts3 table cursor */ - Fts3PhraseToken *pToken, /* Token to defer */ - int iCol /* Column that token must appear in (or -1) */ -){ - Fts3DeferredToken *pDeferred; - pDeferred = sqlite3_malloc64(sizeof(*pDeferred)); - if( !pDeferred ){ - return SQLITE_NOMEM; - } - memset(pDeferred, 0, sizeof(*pDeferred)); - pDeferred->pToken = pToken; - pDeferred->pNext = pCsr->pDeferred; - pDeferred->iCol = iCol; - pCsr->pDeferred = pDeferred; - - assert( pToken->pDeferred==0 ); - pToken->pDeferred = pDeferred; - - return SQLITE_OK; -} -#endif - -/* -** SQLite value pRowid contains the rowid of a row that may or may not be -** present in the FTS3 table. If it is, delete it and adjust the contents -** of subsidiary data structures accordingly. -*/ -static int fts3DeleteByRowid( - Fts3Table *p, - sqlite3_value *pRowid, - int *pnChng, /* IN/OUT: Decrement if row is deleted */ - u32 *aSzDel -){ - int rc = SQLITE_OK; /* Return code */ - int bFound = 0; /* True if *pRowid really is in the table */ - - fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound); - if( bFound && rc==SQLITE_OK ){ - int isEmpty = 0; /* Deleting *pRowid leaves the table empty */ - rc = fts3IsEmpty(p, pRowid, &isEmpty); - if( rc==SQLITE_OK ){ - if( isEmpty ){ - /* Deleting this row means the whole table is empty. In this case - ** delete the contents of all three tables and throw away any - ** data in the pendingTerms hash table. */ - rc = fts3DeleteAll(p, 1); - *pnChng = 0; - memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2); - }else{ - *pnChng = *pnChng - 1; - if( p->zContentTbl==0 ){ - fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); - } - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid); - } - } - } - } - - return rc; -} - -/* -** This function does the work for the xUpdate method of FTS3 virtual -** tables. The schema of the virtual table being: -** -** CREATE TABLE
    ( -** , -**
    HIDDEN, -** docid HIDDEN, -** HIDDEN -** ); -** -** -*/ -SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( - sqlite3_vtab *pVtab, /* FTS3 vtab object */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return Code */ - u32 *aSzIns = 0; /* Sizes of inserted documents */ - u32 *aSzDel = 0; /* Sizes of deleted documents */ - int nChng = 0; /* Net change in number of documents */ - int bInsertDone = 0; - - /* At this point it must be known if the %_stat table exists or not. - ** So bHasStat may not be 2. */ - assert( p->bHasStat==0 || p->bHasStat==1 ); - - assert( p->pSegments==0 ); - assert( - nArg==1 /* DELETE operations */ - || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ - ); - - /* Check for a "special" INSERT operation. One of the form: - ** - ** INSERT INTO xyz(xyz) VALUES('command'); - */ - if( nArg>1 - && sqlite3_value_type(apVal[0])==SQLITE_NULL - && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL - ){ - rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); - goto update_out; - } - - if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ - rc = SQLITE_CONSTRAINT; - goto update_out; - } - - /* Allocate space to hold the change in document sizes */ - aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2); - if( aSzDel==0 ){ - rc = SQLITE_NOMEM; - goto update_out; - } - aSzIns = &aSzDel[p->nColumn+1]; - memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2); - - rc = fts3Writelock(p); - if( rc!=SQLITE_OK ) goto update_out; - - /* If this is an INSERT operation, or an UPDATE that modifies the rowid - ** value, then this operation requires constraint handling. - ** - ** If the on-conflict mode is REPLACE, this means that the existing row - ** should be deleted from the database before inserting the new row. Or, - ** if the on-conflict mode is other than REPLACE, then this method must - ** detect the conflict and return SQLITE_CONSTRAINT before beginning to - ** modify the database file. - */ - if( nArg>1 && p->zContentTbl==0 ){ - /* Find the value object that holds the new rowid value. */ - sqlite3_value *pNewRowid = apVal[3+p->nColumn]; - if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){ - pNewRowid = apVal[1]; - } - - if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( - sqlite3_value_type(apVal[0])==SQLITE_NULL - || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid) - )){ - /* The new rowid is not NULL (in this case the rowid will be - ** automatically assigned and there is no chance of a conflict), and - ** the statement is either an INSERT or an UPDATE that modifies the - ** rowid column. So if the conflict mode is REPLACE, then delete any - ** existing row with rowid=pNewRowid. - ** - ** Or, if the conflict mode is not REPLACE, insert the new record into - ** the %_content table. If we hit the duplicate rowid constraint (or any - ** other error) while doing so, return immediately. - ** - ** This branch may also run if pNewRowid contains a value that cannot - ** be losslessly converted to an integer. In this case, the eventual - ** call to fts3InsertData() (either just below or further on in this - ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is - ** invoked, it will delete zero rows (since no row will have - ** docid=$pNewRowid if $pNewRowid is not an integer value). - */ - if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){ - rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel); - }else{ - rc = fts3InsertData(p, apVal, pRowid); - bInsertDone = 1; - } - } - } - if( rc!=SQLITE_OK ){ - goto update_out; - } - - /* If this is a DELETE or UPDATE operation, remove the old record. */ - if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ - assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); - rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); - } - - /* If this is an INSERT or UPDATE operation, insert the new record. */ - if( nArg>1 && rc==SQLITE_OK ){ - int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); - if( bInsertDone==0 ){ - rc = fts3InsertData(p, apVal, pRowid); - if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - if( rc==SQLITE_OK ){ - rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); - } - if( rc==SQLITE_OK ){ - assert( p->iPrevDocid==*pRowid ); - rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSzIns); - } - nChng++; - } - - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); - } - - update_out: - sqlite3_free(aSzDel); - sqlite3Fts3SegmentsClose(p); - return rc; -} - -/* -** Flush any data in the pending-terms hash table to disk. If successful, -** merge all segments in the database (including the new segment, if -** there was any data to flush) into a single segment. -*/ -SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ - int rc; - rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3DoOptimize(p, 1); - if( rc==SQLITE_OK || rc==SQLITE_DONE ){ - int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - if( rc2!=SQLITE_OK ) rc = rc2; - }else{ - sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0); - sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - } - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - -#endif - -/************** End of fts3_write.c ******************************************/ -/************** Begin file fts3_snippet.c ************************************/ -/* -** 2009 Oct 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. -** -****************************************************************************** -*/ - -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -#ifndef SQLITE_AMALGAMATION -typedef sqlite3_int64 i64; -#endif - -/* -** Characters that may appear in the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ -#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ -#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ -#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ -#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ -#define FTS3_MATCHINFO_LCS 's' /* nCol values */ -#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */ - -/* -** The default value for the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_DEFAULT "pcx" - - -/* -** Used as an sqlite3Fts3ExprIterate() context when loading phrase doclists to -** Fts3Expr.aDoclist[]/nDoclist. -*/ -typedef struct LoadDoclistCtx LoadDoclistCtx; -struct LoadDoclistCtx { - Fts3Cursor *pCsr; /* FTS3 Cursor */ - int nPhrase; /* Number of phrases seen so far */ - int nToken; /* Number of tokens seen so far */ -}; - -/* -** The following types are used as part of the implementation of the -** fts3BestSnippet() routine. -*/ -typedef struct SnippetIter SnippetIter; -typedef struct SnippetPhrase SnippetPhrase; -typedef struct SnippetFragment SnippetFragment; - -struct SnippetIter { - Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ - int iCol; /* Extract snippet from this column */ - int nSnippet; /* Requested snippet length (in tokens) */ - int nPhrase; /* Number of phrases in query */ - SnippetPhrase *aPhrase; /* Array of size nPhrase */ - int iCurrent; /* First token of current snippet */ -}; - -struct SnippetPhrase { - int nToken; /* Number of tokens in phrase */ - char *pList; /* Pointer to start of phrase position list */ - i64 iHead; /* Next value in position list */ - char *pHead; /* Position list data following iHead */ - i64 iTail; /* Next value in trailing position list */ - char *pTail; /* Position list data following iTail */ -}; - -struct SnippetFragment { - int iCol; /* Column snippet is extracted from */ - int iPos; /* Index of first token in snippet */ - u64 covered; /* Mask of query phrases covered */ - u64 hlmask; /* Mask of snippet terms to highlight */ -}; - -/* -** This type is used as an sqlite3Fts3ExprIterate() context object while -** accumulating the data returned by the matchinfo() function. -*/ -typedef struct MatchInfo MatchInfo; -struct MatchInfo { - Fts3Cursor *pCursor; /* FTS3 Cursor */ - int nCol; /* Number of columns in table */ - int nPhrase; /* Number of matchable phrases in query */ - sqlite3_int64 nDoc; /* Number of docs in database */ - char flag; - u32 *aMatchinfo; /* Pre-allocated buffer */ -}; - -/* -** An instance of this structure is used to manage a pair of buffers, each -** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below -** for details. -*/ -struct MatchinfoBuffer { - u8 aRef[3]; - int nElem; - int bGlobal; /* Set if global data is loaded */ - char *zMatchinfo; - u32 aMI[FLEXARRAY]; -}; - -/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */ -#define SZ_MATCHINFOBUFFER(N) \ - (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64)) - - -/* -** The snippet() and offsets() functions both return text values. An instance -** of the following structure is used to accumulate those values while the -** functions are running. See fts3StringAppend() for details. -*/ -typedef struct StrBuffer StrBuffer; -struct StrBuffer { - char *z; /* Pointer to buffer containing string */ - int n; /* Length of z in bytes (excl. nul-term) */ - int nAlloc; /* Allocated size of buffer z in bytes */ -}; - - -/************************************************************************* -** Start of MatchinfoBuffer code. -*/ - -/* -** Allocate a two-slot MatchinfoBuffer object. -*/ -static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){ - MatchinfoBuffer *pRet; - sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) - + SZ_MATCHINFOBUFFER(1); - sqlite3_int64 nStr = strlen(zMatchinfo); - - pRet = sqlite3Fts3MallocZero(nByte + nStr+1); - if( pRet ){ - pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet; - pRet->aMI[1+nElem] = pRet->aMI[0] - + sizeof(u32)*((int)nElem+1); - pRet->nElem = (int)nElem; - pRet->zMatchinfo = ((char*)pRet) + nByte; - memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); - pRet->aRef[0] = 1; - } - - return pRet; -} - -static void fts3MIBufferFree(void *p){ - MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); - - assert( (u32*)p==&pBuf->aMI[1] - || (u32*)p==&pBuf->aMI[pBuf->nElem+2] - ); - if( (u32*)p==&pBuf->aMI[1] ){ - pBuf->aRef[1] = 0; - }else{ - pBuf->aRef[2] = 0; - } - - if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){ - sqlite3_free(pBuf); - } -} - -static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){ - void (*xRet)(void*) = 0; - u32 *aOut = 0; - - if( p->aRef[1]==0 ){ - p->aRef[1] = 1; - aOut = &p->aMI[1]; - xRet = fts3MIBufferFree; - } - else if( p->aRef[2]==0 ){ - p->aRef[2] = 1; - aOut = &p->aMI[p->nElem+2]; - xRet = fts3MIBufferFree; - }else{ - aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32)); - if( aOut ){ - xRet = sqlite3_free; - if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32)); - } - } - - *paOut = aOut; - return xRet; -} - -static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){ - p->bGlobal = 1; - memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32)); -} - -/* -** Free a MatchinfoBuffer object allocated using fts3MIBufferNew() -*/ -SQLITE_PRIVATE void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){ - if( p ){ - assert( p->aRef[0]==1 ); - p->aRef[0] = 0; - if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){ - sqlite3_free(p); - } - } -} - -/* -** End of MatchinfoBuffer code. -*************************************************************************/ - - -/* -** This function is used to help iterate through a position-list. A position -** list is a list of unique integers, sorted from smallest to largest. Each -** element of the list is represented by an FTS3 varint that takes the value -** of the difference between the current element and the previous one plus -** two. For example, to store the position-list: -** -** 4 9 113 -** -** the three varints: -** -** 6 7 106 -** -** are encoded. -** -** When this function is called, *pp points to the start of an element of -** the list. *piPos contains the value of the previous entry in the list. -** 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, i64 *piPos){ - int iVal; - *pp += fts3GetVarint32(*pp, &iVal); - *piPos += (iVal-2); -} - -/* -** Helper function for sqlite3Fts3ExprIterate() (see below). -*/ -static int fts3ExprIterate2( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int *piPhrase, /* Pointer to phrase counter */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int rc; /* Return code */ - int eType = pExpr->eType; /* Type of expression node pExpr */ - - if( eType!=FTSQUERY_PHRASE ){ - assert( pExpr->pLeft && pExpr->pRight ); - rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); - if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ - rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); - } - }else{ - rc = x(pExpr, *piPhrase, pCtx); - (*piPhrase)++; - } - return rc; -} - -/* -** Iterate through all phrase nodes in an FTS3 query, except those that -** are part of a sub-tree that is the right-hand-side of a NOT operator. -** For each phrase node found, the supplied callback function is invoked. -** -** If the callback function returns anything other than SQLITE_OK, -** the iteration is abandoned and the error code returned immediately. -** Otherwise, SQLITE_OK is returned after a callback has been made for -** all eligible phrase nodes. -*/ -SQLITE_PRIVATE int sqlite3Fts3ExprIterate( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int iPhrase = 0; /* Variable used as the phrase counter */ - return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); -} - -/* -** This is an sqlite3Fts3ExprIterate() callback used while loading the -** doclists for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also -** fts3ExprLoadDoclists(). -*/ -static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - int rc = SQLITE_OK; - Fts3Phrase *pPhrase = pExpr->pPhrase; - LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; - - UNUSED_PARAMETER(iPhrase); - - p->nPhrase++; - p->nToken += pPhrase->nToken; - - return rc; -} - -/* -** Load the doclists for each phrase in the query associated with FTS3 cursor -** pCsr. -** -** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable -** phrases in the expression (all phrases except those directly or -** indirectly descended from the right-hand-side of a NOT operator). If -** pnToken is not NULL, then it is set to the number of tokens in all -** matchable phrases of the expression. -*/ -static int fts3ExprLoadDoclists( - Fts3Cursor *pCsr, /* Fts3 cursor for current query */ - int *pnPhrase, /* OUT: Number of phrases in query */ - int *pnToken /* OUT: Number of tokens in query */ -){ - int rc; /* Return Code */ - LoadDoclistCtx sCtx = {0,0,0}; /* Context for sqlite3Fts3ExprIterate() */ - sCtx.pCsr = pCsr; - rc = sqlite3Fts3ExprIterate(pCsr->pExpr,fts3ExprLoadDoclistsCb,(void*)&sCtx); - if( pnPhrase ) *pnPhrase = sCtx.nPhrase; - if( pnToken ) *pnToken = sCtx.nToken; - return rc; -} - -static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - (*(int *)ctx)++; - pExpr->iPhrase = iPhrase; - return SQLITE_OK; -} -static int fts3ExprPhraseCount(Fts3Expr *pExpr){ - int nPhrase = 0; - (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); - return nPhrase; -} - -/* -** Advance the position list iterator specified by the first two -** arguments so that it points to the first element with a value greater -** than or equal to parameter iNext. -*/ -static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){ - char *pIter = *ppIter; - if( pIter ){ - i64 iIter = *piIter; - - while( iIteriCurrent<0 ){ - /* The SnippetIter object has just been initialized. The first snippet - ** candidate always starts at offset 0 (even if this candidate has a - ** score of 0.0). - */ - pIter->iCurrent = 0; - - /* Advance the 'head' iterator of each phrase to the first offset that - ** is greater than or equal to (iNext+nSnippet). - */ - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); - } - }else{ - int iStart; - int iEnd = 0x7FFFFFFF; - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pHead && pPhrase->iHeadiHead; - } - } - if( iEnd==0x7FFFFFFF ){ - return 1; - } - - assert( pIter->nSnippet>=0 ); - pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); - fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); - } - } - - return 0; -} - -/* -** Retrieve information about the current candidate snippet of snippet -** iterator pIter. -*/ -static void fts3SnippetDetails( - SnippetIter *pIter, /* Snippet iterator */ - u64 mCovered, /* Bitmask of phrases already covered */ - int *piToken, /* OUT: First token of proposed snippet */ - int *piScore, /* OUT: "Score" for this snippet */ - u64 *pmCover, /* OUT: Bitmask of phrases covered */ - u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ -){ - int iStart = pIter->iCurrent; /* First token of snippet */ - int iScore = 0; /* Score of this snippet */ - int i; /* Loop counter */ - u64 mCover = 0; /* Mask of phrases covered by this snippet */ - u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pTail ){ - char *pCsr = pPhrase->pTail; - i64 iCsr = pPhrase->iTail; - - while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){ - int j; - u64 mPhrase = (u64)1 << (i%64); - u64 mPos = (u64)1 << (iCsr - iStart); - assert( iCsr>=iStart && (iCsr - iStart)<=64 ); - assert( i>=0 ); - if( (mCover|mCovered)&mPhrase ){ - iScore++; - }else{ - iScore += 1000; - } - mCover |= mPhrase; - - for(j=0; jnToken && jnSnippet; j++){ - mHighlight |= (mPos>>j); - } - - if( 0==(*pCsr & 0x0FE) ) break; - fts3GetDeltaPosition(&pCsr, &iCsr); - } - } - } - - /* Set the output variables before returning. */ - *piToken = iStart; - *piScore = iScore; - *pmCover = mCover; - *pmHighlight = mHighlight; -} - -/* -** This function is an sqlite3Fts3ExprIterate() callback used by -** fts3BestSnippet(). Each invocation populates an element of the -** SnippetIter.aPhrase[] array. -*/ -static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ - SnippetIter *p = (SnippetIter *)ctx; - SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; - char *pCsr; - int rc; - - pPhrase->nToken = pExpr->pPhrase->nToken; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( pCsr ){ - i64 iFirst = 0; - pPhrase->pList = pCsr; - fts3GetDeltaPosition(&pCsr, &iFirst); - if( iFirst<0 ){ - rc = FTS_CORRUPT_VTAB; - }else{ - pPhrase->pHead = pCsr; - pPhrase->pTail = pCsr; - pPhrase->iHead = iFirst; - pPhrase->iTail = iFirst; - } - }else{ - assert( rc!=SQLITE_OK || ( - pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 - )); - } - - return rc; -} - -/* -** Select the fragment of text consisting of nFragment contiguous tokens -** from column iCol that represent the "best" snippet. The best snippet -** is the snippet with the highest score, where scores are calculated -** by adding: -** -** (a) +1 point for each occurrence of a matchable phrase in the snippet. -** -** (b) +1000 points for the first occurrence of each matchable phrase in -** the snippet for which the corresponding mCovered bit is not set. -** -** The selected snippet parameters are stored in structure *pFragment before -** returning. The score of the selected snippet is stored in *piScore -** before returning. -*/ -static int fts3BestSnippet( - int nSnippet, /* Desired snippet length */ - Fts3Cursor *pCsr, /* Cursor to create snippet for */ - int iCol, /* Index of column to create snippet from */ - u64 mCovered, /* Mask of phrases already covered */ - u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ - SnippetFragment *pFragment, /* OUT: Best snippet found */ - int *piScore /* OUT: Score of snippet pFragment */ -){ - int rc; /* Return Code */ - int nList; /* Number of phrases in expression */ - SnippetIter sIter; /* Iterates through snippet candidates */ - sqlite3_int64 nByte; /* Number of bytes of space to allocate */ - int iBestScore = -1; /* Best snippet score found so far */ - int i; /* Loop counter */ - - memset(&sIter, 0, sizeof(sIter)); - - /* Iterate through the phrases in the expression to count them. The same - ** callback makes sure the doclists are loaded for each phrase. - */ - rc = fts3ExprLoadDoclists(pCsr, &nList, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Now that it is known how many phrases there are, allocate and zero - ** the required space using malloc(). - */ - nByte = sizeof(SnippetPhrase) * nList; - sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte); - if( !sIter.aPhrase ){ - return SQLITE_NOMEM; - } - - /* Initialize the contents of the SnippetIter object. Then iterate through - ** the set of phrases in the expression to populate the aPhrase[] array. - */ - sIter.pCsr = pCsr; - sIter.iCol = iCol; - sIter.nSnippet = nSnippet; - sIter.nPhrase = nList; - sIter.iCurrent = -1; - rc = sqlite3Fts3ExprIterate( - pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter - ); - if( rc==SQLITE_OK ){ - - /* Set the *pmSeen output variable. */ - for(i=0; iiCol = iCol; - while( !fts3SnippetNextCandidate(&sIter) ){ - int iPos; - int iScore; - u64 mCover; - u64 mHighlite; - fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite); - assert( iScore>=0 ); - if( iScore>iBestScore ){ - pFragment->iPos = iPos; - pFragment->hlmask = mHighlite; - pFragment->covered = mCover; - iBestScore = iScore; - } - } - - *piScore = iBestScore; - } - sqlite3_free(sIter.aPhrase); - return rc; -} - - -/* -** Append a string to the string-buffer passed as the first argument. -** -** If nAppend is negative, then the length of the string zAppend is -** determined using strlen(). -*/ -static int fts3StringAppend( - StrBuffer *pStr, /* Buffer to append to */ - const char *zAppend, /* Pointer to data to append to buffer */ - int nAppend /* Size of zAppend in bytes (or -1) */ -){ - if( nAppend<0 ){ - nAppend = (int)strlen(zAppend); - } - - /* If there is insufficient space allocated at StrBuffer.z, use realloc() - ** to grow the buffer until so that it is big enough to accommodate the - ** appended data. - */ - if( pStr->n+nAppend+1>=pStr->nAlloc ){ - sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100; - char *zNew = sqlite3_realloc64(pStr->z, nAlloc); - if( !zNew ){ - return SQLITE_NOMEM; - } - pStr->z = zNew; - pStr->nAlloc = nAlloc; - } - assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) ); - - /* Append the data to the string buffer. */ - memcpy(&pStr->z[pStr->n], zAppend, nAppend); - pStr->n += nAppend; - pStr->z[pStr->n] = '\0'; - - return SQLITE_OK; -} - -/* -** The fts3BestSnippet() function often selects snippets that end with a -** query term. That is, the final term of the snippet is always a term -** that requires highlighting. For example, if 'X' is a highlighted term -** and '.' is a non-highlighted term, BestSnippet() may select: -** -** ........X.....X -** -** This function "shifts" the beginning of the snippet forward in the -** document so that there are approximately the same number of -** non-highlighted terms to the right of the final highlighted term as there -** are to the left of the first highlighted term. For example, to this: -** -** ....X.....X.... -** -** This is done as part of extracting the snippet text, not when selecting -** the snippet. Snippet selection is done based on doclists only, so there -** is no way for fts3BestSnippet() to know whether or not the document -** actually contains terms that follow the final highlighted term. -*/ -static int fts3SnippetShift( - Fts3Table *pTab, /* FTS3 table snippet comes from */ - int iLangid, /* Language id to use in tokenizing */ - int nSnippet, /* Number of tokens desired for snippet */ - const char *zDoc, /* Document text to extract snippet from */ - int nDoc, /* Size of buffer zDoc in bytes */ - int *piPos, /* IN/OUT: First token of snippet */ - u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ -){ - u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ - - if( hlmask ){ - int nLeft; /* Tokens to the left of first highlight */ - int nRight; /* Tokens to the right of last highlight */ - int nDesired; /* Ideal number of tokens to shift forward */ - - for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); - for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); - assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 ); - nDesired = (nLeft-nRight)/2; - - /* Ideally, the start of the snippet should be pushed forward in the - ** document nDesired tokens. This block checks if there are actually - ** nDesired tokens to the right of the snippet. If so, *piPos and - ** *pHlMask are updated to shift the snippet nDesired tokens to the - ** right. Otherwise, the snippet is shifted by the number of tokens - ** available. - */ - if( nDesired>0 ){ - int nShift; /* Number of tokens to shift snippet by */ - int iCurrent = 0; /* Token counter */ - int rc; /* Return Code */ - sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer_cursor *pC; - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - - /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) - ** or more tokens in zDoc/nDoc. - */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); - if( rc!=SQLITE_OK ){ - return rc; - } - while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ - const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0; - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); - } - pMod->xClose(pC); - if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } - - nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; - assert( nShift<=nDesired ); - if( nShift>0 ){ - *piPos += nShift; - *pHlmask = hlmask >> nShift; - } - } - } - return SQLITE_OK; -} - -/* -** Extract the snippet text for fragment pFragment from cursor pCsr and -** append it to string buffer pOut. -*/ -static int fts3SnippetText( - Fts3Cursor *pCsr, /* FTS3 Cursor */ - SnippetFragment *pFragment, /* Snippet to extract */ - int iFragment, /* Fragment number */ - int isLast, /* True for final fragment in snippet */ - int nSnippet, /* Number of tokens in extracted snippet */ - const char *zOpen, /* String inserted before highlighted term */ - const char *zClose, /* String inserted after highlighted term */ - const char *zEllipsis, /* String inserted between snippets */ - StrBuffer *pOut /* Write output here */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc; /* Return code */ - const char *zDoc; /* Document text to extract snippet from */ - int nDoc; /* Size of zDoc in bytes */ - int iCurrent = 0; /* Current token number of document */ - int iEnd = 0; /* Byte offset of end of current token */ - int isShiftDone = 0; /* True after snippet is shifted */ - int iPos = pFragment->iPos; /* First token of snippet */ - u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ - int iCol = pFragment->iCol+1; /* Query column to extract text from */ - sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ - - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - return SQLITE_OK; - } - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); - - /* Open a token cursor on the document. */ - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); - if( rc!=SQLITE_OK ){ - return rc; - } - - while( rc==SQLITE_OK ){ - const char *ZDUMMY; /* Dummy argument used with tokenizer */ - int DUMMY1 = -1; /* Dummy argument used with tokenizer */ - int iBegin = 0; /* Offset in zDoc of start of token */ - int iFin = 0; /* Offset in zDoc of end of token */ - int isHighlight = 0; /* True for highlighted terms */ - - /* Variable DUMMY1 is initialized to a negative value above. Elsewhere - ** in the FTS code the variable that the third argument to xNext points to - ** is initialized to zero before the first (*but not necessarily - ** subsequent*) call to xNext(). This is done for a particular application - ** that needs to know whether or not the tokenizer is being used for - ** snippet generation or for some other purpose. - ** - ** Extreme care is required when writing code to depend on this - ** initialization. It is not a documented part of the tokenizer interface. - ** If a tokenizer is used directly by any code outside of FTS, this - ** convention might not be respected. */ - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - /* Special case - the last token of the snippet is also the last token - ** of the column. Append any punctuation that occurred between the end - ** of the previous token and the end of the document to the output. - ** Then break out of the loop. */ - rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); - } - break; - } - if( iCurrentiLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask - ); - isShiftDone = 1; - - /* Now that the shift has been done, check if the initial "..." are - ** required. They are required if (a) this is not the first fragment, - ** or (b) this fragment does not begin at position 0 of its column. - */ - if( rc==SQLITE_OK ){ - if( iPos>0 || iFragment>0 ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - }else if( iBegin ){ - rc = fts3StringAppend(pOut, zDoc, iBegin); - } - } - if( rc!=SQLITE_OK || iCurrent=(iPos+nSnippet) ){ - if( isLast ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - } - break; - } - - /* Set isHighlight to true if this term should be highlighted. */ - isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; - - if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); - if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); - - iEnd = iFin; - } - - pMod->xClose(pC); - return rc; -} - - -/* -** This function is used to count the entries in a column-list (a -** delta-encoded list of term offsets within a single column of a single -** row). When this function is called, *ppCollist should point to the -** beginning of the first varint in the column-list (the varint that -** contains the position of the first matching term in the column data). -** Before returning, *ppCollist is set to point to the first byte after -** the last varint in the column-list (either the 0x00 signifying the end -** of the position-list, or the 0x01 that precedes the column number of -** the next column in the position-list). -** -** The number of elements in the column-list is returned. -*/ -static int fts3ColumnlistCount(char **ppCollist){ - char *pEnd = *ppCollist; - char c = 0; - int nEntry = 0; - - /* A column-list is terminated by either a 0x01 or 0x00. */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - if( !c ) nEntry++; - } - - *ppCollist = pEnd; - return nEntry; -} - -/* -** This function gathers 'y' or 'b' data for a single phrase. -*/ -static int fts3ExprLHits( - Fts3Expr *pExpr, /* Phrase expression node */ - MatchInfo *p /* Matchinfo context */ -){ - Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab; - int iStart; - Fts3Phrase *pPhrase = pExpr->pPhrase; - char *pIter = pPhrase->doclist.pList; - int iCol = 0; - - assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS ); - if( p->flag==FTS3_MATCHINFO_LHITS ){ - iStart = pExpr->iPhrase * p->nCol; - }else{ - iStart = pExpr->iPhrase * ((p->nCol + 31) / 32); - } - - if( pIter ) while( 1 ){ - int nHit = fts3ColumnlistCount(&pIter); - if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ - if( p->flag==FTS3_MATCHINFO_LHITS ){ - p->aMatchinfo[iStart + iCol] = (u32)nHit; - }else if( nHit ){ - p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F)); - } - } - assert( *pIter==0x00 || *pIter==0x01 ); - if( *pIter!=0x01 ) break; - pIter++; - pIter += fts3GetVarint32(pIter, &iCol); - if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB; - } - return SQLITE_OK; -} - -/* -** Gather the results for matchinfo directives 'y' and 'b'. -*/ -static int fts3ExprLHitGather( - Fts3Expr *pExpr, - MatchInfo *p -){ - int rc = SQLITE_OK; - assert( (pExpr->pLeft==0)==(pExpr->pRight==0) ); - if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ - if( pExpr->pLeft ){ - rc = fts3ExprLHitGather(pExpr->pLeft, p); - if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p); - }else{ - rc = fts3ExprLHits(pExpr, p); - } - } - return rc; -} - -/* -** sqlite3Fts3ExprIterate() callback used to collect the "global" matchinfo -** stats for a single query. -** -** sqlite3Fts3ExprIterate() callback to load the 'global' elements of a -** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements -** of the matchinfo array that are constant for all rows returned by the -** current query. -** -** Argument pCtx is actually a pointer to a struct of type MatchInfo. This -** function populates Matchinfo.aMatchinfo[] as follows: -** -** for(iCol=0; iColpCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol] - ); -} - -/* -** sqlite3Fts3ExprIterate() callback used to collect the "local" part of the -** FTS3_MATCHINFO_HITS array. The local stats are those elements of the -** array that are different for each row returned by the query. -*/ -static int fts3ExprLocalHitsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - int rc = SQLITE_OK; - MatchInfo *p = (MatchInfo *)pCtx; - int iStart = iPhrase * p->nCol * 3; - int i; - - for(i=0; inCol && rc==SQLITE_OK; i++){ - char *pCsr; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr); - if( pCsr ){ - p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr); - }else{ - p->aMatchinfo[iStart+i*3] = 0; - } - } - - return rc; -} - -static int fts3MatchinfoCheck( - Fts3Table *pTab, - char cArg, - char **pzErr -){ - if( (cArg==FTS3_MATCHINFO_NPHRASE) - || (cArg==FTS3_MATCHINFO_NCOL) - || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) - || (cArg==FTS3_MATCHINFO_LCS) - || (cArg==FTS3_MATCHINFO_HITS) - || (cArg==FTS3_MATCHINFO_LHITS) - || (cArg==FTS3_MATCHINFO_LHITS_BM) - ){ - return SQLITE_OK; - } - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); - return SQLITE_ERROR; -} - -static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ - size_t nVal; /* Number of integers output by cArg */ - - switch( cArg ){ - case FTS3_MATCHINFO_NDOC: - case FTS3_MATCHINFO_NPHRASE: - case FTS3_MATCHINFO_NCOL: - nVal = 1; - break; - - case FTS3_MATCHINFO_AVGLENGTH: - case FTS3_MATCHINFO_LENGTH: - case FTS3_MATCHINFO_LCS: - nVal = pInfo->nCol; - break; - - case FTS3_MATCHINFO_LHITS: - nVal = (size_t)pInfo->nCol * pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_LHITS_BM: - nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32); - break; - - default: - assert( cArg==FTS3_MATCHINFO_HITS ); - nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3; - break; - } - - return nVal; -} - -static int fts3MatchinfoSelectDoctotal( - Fts3Table *pTab, - sqlite3_stmt **ppStmt, - sqlite3_int64 *pnDoc, - const char **paLen, - const char **ppEnd -){ - sqlite3_stmt *pStmt; - const char *a; - const char *pEnd; - sqlite3_int64 nDoc; - int n; - - - if( !*ppStmt ){ - int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); - if( rc!=SQLITE_OK ) return rc; - } - pStmt = *ppStmt; - assert( sqlite3_data_count(pStmt)==1 ); - - n = sqlite3_column_bytes(pStmt, 0); - a = sqlite3_column_blob(pStmt, 0); - if( a==0 ){ - return FTS_CORRUPT_VTAB; - } - pEnd = a + n; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc); - if( nDoc<=0 || a>pEnd ){ - return FTS_CORRUPT_VTAB; - } - *pnDoc = nDoc; - - if( paLen ) *paLen = a; - if( ppEnd ) *ppEnd = pEnd; - return SQLITE_OK; -} - -/* -** An instance of the following structure is used to store state while -** iterating through a multi-column position-list corresponding to the -** hits for a single phrase on a single row in order to calculate the -** values for a matchinfo() FTS3_MATCHINFO_LCS request. -*/ -typedef struct LcsIterator LcsIterator; -struct LcsIterator { - Fts3Expr *pExpr; /* Pointer to phrase expression */ - int iPosOffset; /* Tokens count up to end of this phrase */ - char *pRead; /* Cursor used to iterate through aDoclist */ - int iPos; /* Current position */ -}; - -/* -** If LcsIterator.iCol is set to the following value, the iterator has -** finished iterating through all offsets for all columns. -*/ -#define LCS_ITERATOR_FINISHED 0x7FFFFFFF; - -static int fts3MatchinfoLcsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number (numbered from zero) */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - LcsIterator *aIter = (LcsIterator *)pCtx; - aIter[iPhrase].pExpr = pExpr; - return SQLITE_OK; -} - -/* -** Advance the iterator passed as an argument to the next position. Return -** 1 if the iterator is at EOF or if it now points to the start of the -** position list for the next column. -*/ -static int fts3LcsIteratorAdvance(LcsIterator *pIter){ - char *pRead; - sqlite3_int64 iRead; - int rc = 0; - - if( NEVER(pIter==0) ) return 1; - pRead = pIter->pRead; - pRead += sqlite3Fts3GetVarint(pRead, &iRead); - if( iRead==0 || iRead==1 ){ - pRead = 0; - rc = 1; - }else{ - pIter->iPos += (int)(iRead-2); - } - - pIter->pRead = pRead; - return rc; -} - -/* -** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. -** -** If the call is successful, the longest-common-substring lengths for each -** column are written into the first nCol elements of the pInfo->aMatchinfo[] -** array before returning. SQLITE_OK is returned in this case. -** -** Otherwise, if an error occurs, an SQLite error code is returned and the -** data written to the first nCol elements of pInfo->aMatchinfo[] is -** undefined. -*/ -static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ - LcsIterator *aIter; - int i; - int iCol; - int nToken = 0; - int rc = SQLITE_OK; - - /* Allocate and populate the array of LcsIterator objects. The array - ** contains one element for each matchable phrase in the query. - **/ - aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase); - if( !aIter ) return SQLITE_NOMEM; - (void)sqlite3Fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - nToken -= pIter->pExpr->pPhrase->nToken; - pIter->iPosOffset = nToken; - } - - for(iCol=0; iColnCol; iCol++){ - int nLcs = 0; /* LCS value for this column */ - int nLive = 0; /* Number of iterators in aIter not at EOF */ - - for(i=0; inPhrase; i++){ - LcsIterator *pIt = &aIter[i]; - rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead); - if( rc!=SQLITE_OK ) goto matchinfo_lcs_out; - if( pIt->pRead ){ - pIt->iPos = pIt->iPosOffset; - fts3LcsIteratorAdvance(pIt); - if( pIt->pRead==0 ){ - rc = FTS_CORRUPT_VTAB; - goto matchinfo_lcs_out; - } - nLive++; - } - } - - while( nLive>0 ){ - LcsIterator *pAdv = 0; /* The iterator to advance by one position */ - int nThisLcs = 0; /* LCS for the current iterator positions */ - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - if( pIter->pRead==0 ){ - /* This iterator is already at EOF for this column. */ - nThisLcs = 0; - }else{ - if( pAdv==0 || pIter->iPosiPos ){ - pAdv = pIter; - } - if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){ - nThisLcs++; - }else{ - nThisLcs = 1; - } - if( nThisLcs>nLcs ) nLcs = nThisLcs; - } - } - if( fts3LcsIteratorAdvance(pAdv) ) nLive--; - } - - pInfo->aMatchinfo[iCol] = nLcs; - } - - matchinfo_lcs_out: - sqlite3_free(aIter); - return rc; -} - -/* -** Populate the buffer pInfo->aMatchinfo[] with an array of integers to -** be returned by the matchinfo() function. Argument zArg contains the -** format string passed as the second argument to matchinfo (or the -** default value "pcx" if no second argument was specified). The format -** string has already been validated and the pInfo->aMatchinfo[] array -** is guaranteed to be large enough for the output. -** -** If bGlobal is true, then populate all fields of the matchinfo() output. -** If it is false, then assume that those fields that do not change between -** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) -** have already been populated. -** -** Return SQLITE_OK if successful, or an SQLite error code if an error -** occurs. If a value other than SQLITE_OK is returned, the state the -** pInfo->aMatchinfo[] buffer is left in is undefined. -*/ -static int fts3MatchinfoValues( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - int bGlobal, /* True to grab the global stats */ - MatchInfo *pInfo, /* Matchinfo context object */ - const char *zArg /* Matchinfo format string */ -){ - int rc = SQLITE_OK; - int i; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_stmt *pSelect = 0; - - for(i=0; rc==SQLITE_OK && zArg[i]; i++){ - pInfo->flag = zArg[i]; - switch( zArg[i] ){ - case FTS3_MATCHINFO_NPHRASE: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_NCOL: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; - break; - - case FTS3_MATCHINFO_NDOC: - if( bGlobal ){ - sqlite3_int64 nDoc = 0; - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0); - pInfo->aMatchinfo[0] = (u32)nDoc; - } - break; - - case FTS3_MATCHINFO_AVGLENGTH: - if( bGlobal ){ - sqlite3_int64 nDoc; /* Number of rows in table */ - const char *a; /* Aggregate column length array */ - const char *pEnd; /* First byte past end of length array */ - - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd); - if( rc==SQLITE_OK ){ - int iCol; - for(iCol=0; iColnCol; iCol++){ - u32 iVal; - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarint(a, &nToken); - if( a>pEnd ){ - rc = SQLITE_CORRUPT_VTAB; - break; - } - iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); - pInfo->aMatchinfo[iCol] = iVal; - } - } - } - break; - - case FTS3_MATCHINFO_LENGTH: { - sqlite3_stmt *pSelectDocsize = 0; - rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); - if( rc==SQLITE_OK ){ - int iCol; - const char *a = sqlite3_column_blob(pSelectDocsize, 0); - const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0); - for(iCol=0; iColnCol; iCol++){ - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken); - if( a>pEnd ){ - rc = SQLITE_CORRUPT_VTAB; - break; - } - pInfo->aMatchinfo[iCol] = (u32)nToken; - } - } - sqlite3_reset(pSelectDocsize); - break; - } - - case FTS3_MATCHINFO_LCS: - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3MatchinfoLcs(pCsr, pInfo); - } - break; - - case FTS3_MATCHINFO_LHITS_BM: - case FTS3_MATCHINFO_LHITS: { - size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); - memset(pInfo->aMatchinfo, 0, nZero); - rc = fts3ExprLHitGather(pCsr->pExpr, pInfo); - break; - } - - default: { - Fts3Expr *pExpr; - assert( zArg[i]==FTS3_MATCHINFO_HITS ); - pExpr = pCsr->pExpr; - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc!=SQLITE_OK ) break; - if( bGlobal ){ - if( pCsr->pDeferred ){ - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0); - if( rc!=SQLITE_OK ) break; - } - rc = sqlite3Fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); - sqlite3Fts3EvalTestDeferred(pCsr, &rc); - if( rc!=SQLITE_OK ) break; - } - (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); - break; - } - } - - pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); - } - - sqlite3_reset(pSelect); - return rc; -} - - -/* -** Populate pCsr->aMatchinfo[] with data for the current row. The -** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). -*/ -static void fts3GetMatchinfo( - sqlite3_context *pCtx, /* Return results here */ - Fts3Cursor *pCsr, /* FTS3 Cursor object */ - const char *zArg /* Second argument to matchinfo() function */ -){ - MatchInfo sInfo; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int bGlobal = 0; /* Collect 'global' stats as well as local */ - - u32 *aOut = 0; - void (*xDestroyOut)(void*) = 0; - - memset(&sInfo, 0, sizeof(MatchInfo)); - sInfo.pCursor = pCsr; - sInfo.nCol = pTab->nColumn; - - /* If there is cached matchinfo() data, but the format string for the - ** cache does not match the format string for this request, discard - ** the cached data. */ - if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){ - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - pCsr->pMIBuffer = 0; - } - - /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the - ** matchinfo function has been called for this query. In this case - ** allocate the array used to accumulate the matchinfo data and - ** initialize those elements that are constant for every row. - */ - if( pCsr->pMIBuffer==0 ){ - size_t nMatchinfo = 0; /* Number of u32 elements in match-info */ - int i; /* Used to iterate through zArg */ - - /* Determine the number of phrases in the query */ - pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); - sInfo.nPhrase = pCsr->nPhrase; - - /* Determine the number of integers in the buffer returned by this call. */ - for(i=0; zArg[i]; i++){ - char *zErr = 0; - if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ - sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); - return; - } - nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); - } - - /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ - pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg); - if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM; - - pCsr->isMatchinfoNeeded = 1; - bGlobal = 1; - } - - if( rc==SQLITE_OK ){ - xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut); - if( xDestroyOut==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - sInfo.aMatchinfo = aOut; - sInfo.nPhrase = pCsr->nPhrase; - rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); - if( bGlobal ){ - fts3MIBufferSetGlobal(pCsr->pMIBuffer); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - if( xDestroyOut ) xDestroyOut(aOut); - }else{ - int n = pCsr->pMIBuffer->nElem * sizeof(u32); - sqlite3_result_blob(pCtx, aOut, n, xDestroyOut); - } -} - -/* -** Implementation of snippet() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Snippet( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr, /* Cursor object */ - const char *zStart, /* Snippet start text - "" */ - const char *zEnd, /* Snippet end text - "" */ - const char *zEllipsis, /* Snippet ellipsis text - "..." */ - int iCol, /* Extract snippet from this column */ - int nToken /* Approximate number of tokens in snippet */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int i; - StrBuffer res = {0, 0, 0}; - - /* The returned text includes up to four fragments of text extracted from - ** the data in the current row. The first iteration of the for(...) loop - ** below attempts to locate a single fragment of text nToken tokens in - ** size that contains at least one instance of all phrases in the query - ** expression that appear in the current row. If such a fragment of text - ** cannot be found, the second iteration of the loop attempts to locate - ** a pair of fragments, and so on. - */ - int nSnippet = 0; /* Number of fragments in this snippet */ - SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ - int nFToken = -1; /* Number of tokens in each fragment */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - /* Limit the snippet length to 64 tokens. */ - if( nToken<-64 ) nToken = -64; - if( nToken>+64 ) nToken = +64; - - for(nSnippet=1; 1; nSnippet++){ - - int iSnip; /* Loop counter 0..nSnippet-1 */ - u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ - u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ - - if( nToken>=0 ){ - nFToken = (nToken+nSnippet-1) / nSnippet; - }else{ - nFToken = -1 * nToken; - } - - for(iSnip=0; iSnipnColumn; iRead++){ - SnippetFragment sF = {0, 0, 0, 0}; - int iS = 0; - if( iCol>=0 && iRead!=iCol ) continue; - - /* Find the best snippet of nFToken tokens in column iRead. */ - rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); - if( rc!=SQLITE_OK ){ - goto snippet_out; - } - if( iS>iBestScore ){ - *pFragment = sF; - iBestScore = iS; - } - } - - mCovered |= pFragment->covered; - } - - /* If all query phrases seen by fts3BestSnippet() are present in at least - ** one of the nSnippet snippet fragments, break out of the loop. - */ - assert( (mCovered&mSeen)==mCovered ); - if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; - } - - assert( nFToken>0 ); - - for(i=0; ipCsr, pExpr, p->iCol, &pList); - nTerm = pExpr->pPhrase->nToken; - if( pList ){ - fts3GetDeltaPosition(&pList, &iPos); - assert_fts3_nc( iPos>=0 ); - } - - for(iTerm=0; iTermaTerm[p->iTerm++]; - pT->iOff = nTerm-iTerm-1; - pT->pList = pList; - pT->iPos = iPos; - } - - return rc; -} - -/* -** If expression pExpr is a phrase expression that uses an MSR query, -** restart it as a regular, non-incremental query. Return SQLITE_OK -** if successful, or an SQLite error code otherwise. -*/ -static int fts3ExprRestartIfCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - TermOffsetCtx *p = (TermOffsetCtx*)ctx; - int rc = SQLITE_OK; - UNUSED_PARAMETER(iPhrase); - if( pExpr->pPhrase && pExpr->pPhrase->bIncr ){ - rc = sqlite3Fts3MsrCancel(p->pCsr, pExpr); - pExpr->pPhrase->bIncr = 0; - } - return rc; -} - -/* -** Implementation of offsets() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Offsets( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr /* Cursor object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; - int rc; /* Return Code */ - int nToken; /* Number of tokens in query */ - int iCol; /* Column currently being processed */ - StrBuffer res = {0, 0, 0}; /* Result string */ - TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - memset(&sCtx, 0, sizeof(sCtx)); - assert( pCsr->isRequireSeek==0 ); - - /* Count the number of terms in the query */ - rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); - if( rc!=SQLITE_OK ) goto offsets_out; - - /* Allocate the array of TermOffset iterators. */ - sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken); - if( 0==sCtx.aTerm ){ - rc = SQLITE_NOMEM; - goto offsets_out; - } - sCtx.iDocid = pCsr->iPrevId; - sCtx.pCsr = pCsr; - - /* If a query restart will be required, do it here, rather than later of - ** after pointers to poslist buffers that may be invalidated by a restart - ** have been saved. */ - rc = sqlite3Fts3ExprIterate(pCsr->pExpr, fts3ExprRestartIfCb, (void*)&sCtx); - if( rc!=SQLITE_OK ) goto offsets_out; - - /* Loop through the table columns, appending offset information to - ** string-buffer res for each column. - */ - for(iCol=0; iColnColumn; iCol++){ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ - const char *ZDUMMY; /* Dummy argument used with xNext() */ - int NDUMMY = 0; /* Dummy argument used with xNext() */ - int iStart = 0; - int iEnd = 0; - int iCurrent = 0; - const char *zDoc; - int nDoc; - - /* 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; - rc = sqlite3Fts3ExprIterate( - 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. - ** If an OOM occurs while retrieving the data (this can happen if SQLite - ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM - ** to the caller. - */ - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ - continue; - } - rc = SQLITE_NOMEM; - goto offsets_out; - } - - /* Initialize a tokenizer iterator to iterate through column iCol. */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, - zDoc, nDoc, &pC - ); - if( rc!=SQLITE_OK ) goto offsets_out; - - rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - while( rc==SQLITE_OK ){ - int i; /* Used to loop through terms */ - int iMinPos = 0x7FFFFFFF; /* Position of next token */ - TermOffset *pTerm = 0; /* TermOffset associated with next token */ - - for(i=0; ipList && (pT->iPos-pT->iOff)iPos-pT->iOff; - pTerm = pT; - } - } - - if( !pTerm ){ - /* All offsets for this column have been gathered. */ - rc = SQLITE_DONE; - }else{ - assert_fts3_nc( iCurrent<=iMinPos ); - if( 0==(0xFE&*pTerm->pList) ){ - pTerm->pList = 0; - }else{ - fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); - } - while( rc==SQLITE_OK && iCurrentxNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - } - if( rc==SQLITE_OK ){ - char aBuffer[64]; - sqlite3_snprintf(sizeof(aBuffer), aBuffer, - "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart - ); - rc = fts3StringAppend(&res, aBuffer, -1); - }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - } - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - - pMod->xClose(pC); - if( rc!=SQLITE_OK ) goto offsets_out; - } - - offsets_out: - sqlite3_free(sCtx.aTerm); - assert( rc!=SQLITE_DONE ); - sqlite3Fts3SegmentsClose(pTab); - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - sqlite3_free(res.z); - }else{ - sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); - } - return; -} - -/* -** Implementation of matchinfo() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Matchinfo( - sqlite3_context *pContext, /* Function call context */ - Fts3Cursor *pCsr, /* FTS3 table cursor */ - const char *zArg /* Second arg to matchinfo() function */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - const char *zFormat; - - if( zArg ){ - zFormat = zArg; - }else{ - zFormat = FTS3_MATCHINFO_DEFAULT; - } - - if( !pCsr->pExpr ){ - sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); - return; - }else{ - /* Retrieve matchinfo() data. */ - fts3GetMatchinfo(pContext, pCsr, zFormat); - sqlite3Fts3SegmentsClose(pTab); - } -} - -#endif - -/************** End of fts3_snippet.c ****************************************/ -/************** Begin file fts3_unicode.c ************************************/ -/* -** 2012 May 24 -** -** 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. -** -****************************************************************************** -** -** Implementation of the "unicode" full-text-search tokenizer. -*/ - -#ifndef SQLITE_DISABLE_FTS3_UNICODE - -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -/* #include "fts3_tokenizer.h" */ - -/* -** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied -** from the sqlite3 source file utf.c. If this file is compiled as part -** of the amalgamation, they are not required. -*/ -#ifndef SQLITE_AMALGAMATION - -static const unsigned char sqlite3Utf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - -#define READ_UTF8(zIn, zTerm, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ - c = (c<<6) + (0x3f & *(zIn++)); \ - } \ - if( c<0x80 \ - || (c&0xFFFFF800)==0xD800 \ - || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ - } - -#define WRITE_UTF8(zOut, c) { \ - if( c<0x00080 ){ \ - *zOut++ = (u8)(c&0xFF); \ - } \ - else if( c<0x00800 ){ \ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ - else if( c<0x10000 ){ \ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - }else{ \ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ -} - -#endif /* ifndef SQLITE_AMALGAMATION */ - -typedef struct unicode_tokenizer unicode_tokenizer; -typedef struct unicode_cursor unicode_cursor; - -struct unicode_tokenizer { - sqlite3_tokenizer base; - int eRemoveDiacritic; - int nException; - int *aiException; -}; - -struct unicode_cursor { - sqlite3_tokenizer_cursor base; - const unsigned char *aInput; /* Input text being tokenized */ - int nInput; /* Size of aInput[] in bytes */ - int iOff; /* Current offset within aInput[] */ - int iToken; /* Index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAlloc; /* space allocated at zToken */ -}; - - -/* -** Destroy a tokenizer allocated by unicodeCreate(). -*/ -static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){ - if( pTokenizer ){ - unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer; - sqlite3_free(p->aiException); - sqlite3_free(p); - } - return SQLITE_OK; -} - -/* -** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE -** statement has specified that the tokenizer for this table shall consider -** all characters in string zIn/nIn to be separators (if bAlnum==0) or -** token characters (if bAlnum==1). -** -** For each codepoint in the zIn/nIn string, this function checks if the -** sqlite3FtsUnicodeIsalnum() function already returns the desired result. -** If so, no action is taken. Otherwise, the codepoint is added to the -** unicode_tokenizer.aiException[] array. For the purposes of tokenization, -** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all -** codepoints in the aiException[] array. -** -** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() -** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. -** It is not possible to change the behavior of the tokenizer with respect -** to these codepoints. -*/ -static int unicodeAddExceptions( - unicode_tokenizer *p, /* Tokenizer to add exceptions to */ - int bAlnum, /* Replace Isalnum() return value with this */ - const char *zIn, /* Array of characters to make exceptions */ - int nIn /* Length of z in bytes */ -){ - const unsigned char *z = (const unsigned char *)zIn; - const unsigned char *zTerm = &z[nIn]; - unsigned int iCode; - int nEntry = 0; - - assert( bAlnum==0 || bAlnum==1 ); - - while( zaiException,(p->nException+nEntry)*sizeof(int)); - if( aNew==0 ) return SQLITE_NOMEM; - nNew = p->nException; - - z = (const unsigned char *)zIn; - while( zi; j--) aNew[j] = aNew[j-1]; - aNew[i] = (int)iCode; - nNew++; - } - } - p->aiException = aNew; - p->nException = nNew; - } - - return SQLITE_OK; -} - -/* -** Return true if the p->aiException[] array contains the value iCode. -*/ -static int unicodeIsException(unicode_tokenizer *p, int iCode){ - if( p->nException>0 ){ - int *a = p->aiException; - int iLo = 0; - int iHi = p->nException-1; - - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( iCode==a[iTest] ){ - return 1; - }else if( iCode>a[iTest] ){ - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - } - - return 0; -} - -/* -** Return true if, for the purposes of tokenization, codepoint iCode is -** considered a token character (not a separator). -*/ -static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){ - assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); - return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode); -} - -/* -** Create a new tokenizer instance. -*/ -static int unicodeCreate( - int nArg, /* Size of array argv[] */ - const char * const *azArg, /* Tokenizer creation arguments */ - sqlite3_tokenizer **pp /* OUT: New tokenizer handle */ -){ - unicode_tokenizer *pNew; /* New tokenizer object */ - int i; - int rc = SQLITE_OK; - - pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer)); - if( pNew==NULL ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(unicode_tokenizer)); - pNew->eRemoveDiacritic = 1; - - for(i=0; rc==SQLITE_OK && ieRemoveDiacritic = 1; - } - else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){ - pNew->eRemoveDiacritic = 0; - } - else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){ - pNew->eRemoveDiacritic = 2; - } - else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 1, &z[11], n-11); - } - else if( n>=11 && memcmp("separators=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 0, &z[11], n-11); - } - else{ - /* Unrecognized argument */ - rc = SQLITE_ERROR; - } - } - - if( rc!=SQLITE_OK ){ - unicodeDestroy((sqlite3_tokenizer *)pNew); - pNew = 0; - } - *pp = (sqlite3_tokenizer *)pNew; - return rc; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int unicodeOpen( - sqlite3_tokenizer *p, /* The tokenizer */ - const char *aInput, /* Input string */ - int nInput, /* Size of string aInput in bytes */ - sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */ -){ - unicode_cursor *pCsr; - - pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(unicode_cursor)); - - 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{ - pCsr->nInput = nInput; - } - - *pp = &pCsr->base; - UNUSED_PARAMETER(p); - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){ - unicode_cursor *pCsr = (unicode_cursor *) pCursor; - sqlite3_free(pCsr->zToken); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int unicodeNext( - sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */ - const char **paToken, /* OUT: Token text */ - int *pnToken, /* OUT: Number of bytes at *paToken */ - int *piStart, /* OUT: Starting offset of token */ - int *piEnd, /* OUT: Ending offset of token */ - int *piPos /* OUT: Position integer of token */ -){ - unicode_cursor *pCsr = (unicode_cursor *)pC; - unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); - unsigned int iCode = 0; - char *zOut; - const unsigned char *z = &pCsr->aInput[pCsr->iOff]; - const unsigned char *zStart = z; - const unsigned char *zEnd; - const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; - - /* Scan past any delimiter characters before the start of the next token. - ** Return SQLITE_DONE early if this takes us all the way to the end of - ** the input. */ - while( z=zTerm ) return SQLITE_DONE; - - zOut = pCsr->zToken; - do { - int iOut; - - /* Grow the output buffer if required. */ - if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){ - char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64); - if( !zNew ) return SQLITE_NOMEM; - zOut = &zNew[zOut - pCsr->zToken]; - pCsr->zToken = zNew; - pCsr->nAlloc += 64; - } - - /* Write the folded case of the last character read to the output */ - zEnd = z; - iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic); - if( iOut ){ - WRITE_UTF8(zOut, iOut); - } - - /* If the cursor is not at EOF, read the next character */ - if( z>=zTerm ) break; - READ_UTF8(z, zTerm, iCode); - }while( unicodeIsAlnum(p, (int)iCode) - || sqlite3FtsUnicodeIsdiacritic((int)iCode) - ); - - /* Set the output variables and return. */ - pCsr->iOff = (int)(z - pCsr->aInput); - *paToken = pCsr->zToken; - *pnToken = (int)(zOut - pCsr->zToken); - *piStart = (int)(zStart - pCsr->aInput); - *piEnd = (int)(zEnd - pCsr->aInput); - *piPos = pCsr->iToken++; - return SQLITE_OK; -} - -/* -** Set *ppModule to a pointer to the sqlite3_tokenizer_module -** structure for the unicode tokenizer. -*/ -SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){ - static const sqlite3_tokenizer_module module = { - 0, - unicodeCreate, - unicodeDestroy, - unicodeOpen, - unicodeClose, - unicodeNext, - 0, - }; - *ppModule = &module; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ -#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */ - -/************** End of fts3_unicode.c ****************************************/ -/************** Begin file fts3_unicode2.c ***********************************/ -/* -** 2012-05-25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -*/ - -/* -** DO NOT EDIT THIS MACHINE GENERATED FILE. -*/ - -#ifndef SQLITE_DISABLE_FTS3_UNICODE -#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) - -/* #include */ - -/* -** Return true if the argument corresponds to a unicode codepoint -** classified as either a letter or a number. Otherwise false. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ - /* Each unsigned integer in the following array corresponds to a contiguous - ** range of unicode codepoints that are not either letters or numbers (i.e. - ** codepoints for which this function should return 0). - ** - ** The most significant 22 bits in each 32-bit value contain the first - ** codepoint in the range. The least significant 10 bits are used to store - ** the size of the range (always at least 1). In other words, the value - ** ((C<<22) + N) represents a range of N codepoints starting with codepoint - ** C. It is not possible to represent a range larger than 1023 codepoints - ** using this format. - */ - static const unsigned int aEntry[] = { - 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, - 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, - 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, - 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, - 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, - 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, - 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, - 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, - 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, - 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, - 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, - 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, - 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, - 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, - 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, - 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, - 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, - 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, - 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, - 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, - 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, - 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, - 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, - 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, - 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, - 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, - 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, - 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, - 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, - 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, - 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, - 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, - 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, - 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, - 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, - 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, - 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, - 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, - 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, - 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, - 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, - 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, - 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, - 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, - 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, - 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, - 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, - 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, - 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, - 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, - 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, - 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, - 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, - 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, - 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, - 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, - 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, - 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, - 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, - 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, - 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, - 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, - 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, - 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, - 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, - 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, - 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, - 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, - 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, - 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, - 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, - 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, - 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, - 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, - 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, - 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, - 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, - 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, - 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, - 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, - 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, - 0x380400F0, - }; - static const unsigned int aAscii[4] = { - 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, - }; - - if( (unsigned int)c<128 ){ - return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 ); - }else if( (unsigned int)c<(1<<22) ){ - unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; - int iRes = 0; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aEntry[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( aEntry[0]=aEntry[iRes] ); - return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); - } - return 1; -} - - -/* -** If the argument is a codepoint corresponding to a lowercase letter -** in the ASCII range with a diacritic added, return the codepoint -** of the ASCII letter only. For example, if passed 235 - "LATIN -** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER -** E"). The resuls of passing a codepoint that corresponds to an -** uppercase letter are undefined. -*/ -static int remove_diacritic(int c, int bComplex){ - unsigned short aDia[] = { - 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, - 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, - 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, - 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, - 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896, - 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106, - 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344, - 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198, - 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468, - 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704, - 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, - 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, - 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, - 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, - 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, - 63182, 63242, 63274, 63310, 63368, 63390, - }; -#define HIBIT ((unsigned char)0x80) - unsigned char aChar[] = { - '\0', 'a', 'c', 'e', 'i', 'n', - 'o', 'u', 'y', 'y', 'a', 'c', - 'd', 'e', 'e', 'g', 'h', 'i', - 'j', 'k', 'l', 'n', 'o', 'r', - 's', 't', 'u', 'u', 'w', 'y', - 'z', 'o', 'u', 'a', 'i', 'o', - 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o', - 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a', - 'e', 'i', 'o', 'r', 'u', 's', - 't', 'h', 'a', 'e', 'o'|HIBIT, 'o', - 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', 'a', 'b', - 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT, - 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT, - 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n', - 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's', - 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w', - 'w', 'x', 'y', 'z', 'h', 't', - 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, - 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT, - 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y', - }; - - unsigned int key = (((unsigned int)c)<<3) | 0x00000007; - int iRes = 0; - int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aDia[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( key>=aDia[iRes] ); - if( bComplex==0 && (aChar[iRes] & 0x80) ) return c; - return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F); -} - - -/* -** Return true if the argument interpreted as a unicode codepoint -** is a diacritical modifier character. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){ - unsigned int mask0 = 0x08029FDF; - unsigned int mask1 = 0x000361F8; - if( c<768 || c>817 ) return 0; - return (c < 768+32) ? - (mask0 & ((unsigned int)1 << (c-768))) : - (mask1 & ((unsigned int)1 << (c-768-32))); -} - - -/* -** Interpret the argument as a unicode codepoint. If the codepoint -** is an upper case character that has a lower case equivalent, -** return the codepoint corresponding to the lower case version. -** Otherwise, return a copy of the argument. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ - /* Each entry in the following array defines a rule for folding a range - ** of codepoints to lower case. The rule applies to a range of nRange - ** codepoints starting at codepoint iCode. - ** - ** If the least significant bit in flags is clear, then the rule applies - ** to all nRange codepoints (i.e. all nRange codepoints are upper case and - ** need to be folded). Or, if it is set, then the rule only applies to - ** every second codepoint in the range, starting with codepoint C. - ** - ** The 7 most significant bits in flags are an index into the aiOff[] - ** array. If a specific codepoint C does require folding, then its lower - ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF). - ** - ** The contents of this array are generated by parsing the CaseFolding.txt - ** file distributed as part of the "Unicode Character Database". See - ** http://www.unicode.org for details. - */ - static const struct TableEntry { - unsigned short iCode; - unsigned char flags; - unsigned char nRange; - } aEntry[] = { - {65, 14, 26}, {181, 64, 1}, {192, 14, 23}, - {216, 14, 7}, {256, 1, 48}, {306, 1, 6}, - {313, 1, 16}, {330, 1, 46}, {376, 116, 1}, - {377, 1, 6}, {383, 104, 1}, {385, 50, 1}, - {386, 1, 4}, {390, 44, 1}, {391, 0, 1}, - {393, 42, 2}, {395, 0, 1}, {398, 32, 1}, - {399, 38, 1}, {400, 40, 1}, {401, 0, 1}, - {403, 42, 1}, {404, 46, 1}, {406, 52, 1}, - {407, 48, 1}, {408, 0, 1}, {412, 52, 1}, - {413, 54, 1}, {415, 56, 1}, {416, 1, 6}, - {422, 60, 1}, {423, 0, 1}, {425, 60, 1}, - {428, 0, 1}, {430, 60, 1}, {431, 0, 1}, - {433, 58, 2}, {435, 1, 4}, {439, 62, 1}, - {440, 0, 1}, {444, 0, 1}, {452, 2, 1}, - {453, 0, 1}, {455, 2, 1}, {456, 0, 1}, - {458, 2, 1}, {459, 1, 18}, {478, 1, 18}, - {497, 2, 1}, {498, 1, 4}, {502, 122, 1}, - {503, 134, 1}, {504, 1, 40}, {544, 110, 1}, - {546, 1, 18}, {570, 70, 1}, {571, 0, 1}, - {573, 108, 1}, {574, 68, 1}, {577, 0, 1}, - {579, 106, 1}, {580, 28, 1}, {581, 30, 1}, - {582, 1, 10}, {837, 36, 1}, {880, 1, 4}, - {886, 0, 1}, {902, 18, 1}, {904, 16, 3}, - {908, 26, 1}, {910, 24, 2}, {913, 14, 17}, - {931, 14, 9}, {962, 0, 1}, {975, 4, 1}, - {976, 140, 1}, {977, 142, 1}, {981, 146, 1}, - {982, 144, 1}, {984, 1, 24}, {1008, 136, 1}, - {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1}, - {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1}, - {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32}, - {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1}, - {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38}, - {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1}, - {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1}, - {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6}, - {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6}, - {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8}, - {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2}, - {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1}, - {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2}, - {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2}, - {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2}, - {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1}, - {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16}, - {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47}, - {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1}, - {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1}, - {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1}, - {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2}, - {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, - {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, - {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, - {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, - {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, - {65313, 14, 26}, - }; - static const unsigned short aiOff[] = { - 1, 2, 8, 15, 16, 26, 28, 32, - 37, 38, 40, 48, 63, 64, 69, 71, - 79, 80, 116, 202, 203, 205, 206, 207, - 209, 210, 211, 213, 214, 217, 218, 219, - 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, - 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, - 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, - 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, - 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, - 65514, 65521, 65527, 65528, 65529, - }; - - int ret = c; - - assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); - - if( c<128 ){ - if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); - }else if( c<65536 ){ - const struct TableEntry *p; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - int iRes = -1; - - assert( c>aEntry[0].iCode ); - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - int cmp = (c - aEntry[iTest].iCode); - if( cmp>=0 ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - - assert( iRes>=0 && c>=aEntry[iRes].iCode ); - p = &aEntry[iRes]; - if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ - ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; - assert( ret>0 ); - } - - if( eRemoveDiacritic ){ - ret = remove_diacritic(ret, eRemoveDiacritic==2); - } - } - - else if( c>=66560 && c<66600 ){ - ret = c + 40; - } - - return ret; -} -#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ -#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ - -/************** End of fts3_unicode2.c ***************************************/ -/************** Begin file json.c ********************************************/ -/* -** 2015-08-12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** SQLite JSON functions. -** -** 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. -** -** The original design stored all JSON as pure text, canonical RFC-8259. -** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16). -** All generated JSON text still conforms strictly to RFC-8259, but text -** with JSON-5 extensions is accepted as input. -** -** Beginning with version 3.45.0 (circa 2024-01-01), these routines also -** accept BLOB values that have JSON encoded using a binary representation -** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk -** format for SQLite-JSONB is completely different and incompatible with -** PostgreSQL-JSONB. -** -** Decoding and interpreting JSONB is still O(N) where N is the size of -** the input, the same as text JSON. However, the constant of proportionality -** for JSONB is much smaller due to faster parsing. The size of each -** element in JSONB is encoded in its header, so there is no need to search -** for delimiters using persnickety syntax rules. JSONB seems to be about -** 3x faster than text JSON as a result. JSONB is also tends to be slightly -** smaller than text JSON, by 5% or 10%, but there are corner cases where -** JSONB can be slightly larger. So you are not far mistaken to say that -** a JSONB blob is the same size as the equivalent RFC-8259 text. -** -** -** THE JSONB ENCODING: -** -** Every JSON element is encoded in JSONB as a header and a payload. -** The header is between 1 and 9 bytes in size. The payload is zero -** or more bytes. -** -** The lower 4 bits of the first byte of the header determines the -** element type: -** -** 0: NULL -** 1: TRUE -** 2: FALSE -** 3: INT -- RFC-8259 integer literal -** 4: INT5 -- JSON5 integer literal -** 5: FLOAT -- RFC-8259 floating point literal -** 6: FLOAT5 -- JSON5 floating point literal -** 7: TEXT -- Text literal acceptable to both SQL and JSON -** 8: TEXTJ -- Text containing RFC-8259 escapes -** 9: TEXT5 -- Text containing JSON5 and/or RFC-8259 escapes -** 10: TEXTRAW -- Text containing unescaped syntax characters -** 11: ARRAY -** 12: OBJECT -** -** The other three possible values (13-15) are reserved for future -** enhancements. -** -** The upper 4 bits of the first byte determine the size of the header -** and sometimes also the size of the payload. If X is the first byte -** of the element and if X>>4 is between 0 and 11, then the payload -** will be that many bytes in size and the header is exactly one byte -** in size. Other four values for X>>4 (12-15) indicate that the header -** is more than one byte in size and that the payload size is determined -** by the remainder of the header, interpreted as a unsigned big-endian -** integer. -** -** Value of X>>4 Size integer Total header size -** ------------- -------------------- ----------------- -** 12 1 byte (0-255) 2 -** 13 2 byte (0-65535) 3 -** 14 4 byte (0-4294967295) 5 -** 15 8 byte (0-1.8e19) 9 -** -** The payload size need not be expressed in its minimal form. For example, -** if the payload size is 10, the size can be expressed in any of 5 different -** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by one 0x0a byte, -** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by -** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and -** a single byte of 0x0a. The shorter forms are preferred, of course, but -** sometimes when generating JSONB, the payload size is not known in advance -** and it is convenient to reserve sufficient header space to cover the -** largest possible payload size and then come back later and patch up -** the size when it becomes known, resulting in a non-minimal encoding. -** -** The value (X>>4)==15 is not actually used in the current implementation -** (as SQLite is currently unable to handle BLOBs larger than about 2GB) -** but is included in the design to allow for future enhancements. -** -** The payload follows the header. NULL, TRUE, and FALSE have no payload and -** their payload size must always be zero. The payload for INT, INT5, -** FLOAT, FLOAT5, TEXT, TEXTJ, TEXT5, and TEXTROW is text. Note that the -** "..." or '...' delimiters are omitted from the various text encodings. -** The payload for ARRAY and OBJECT is a list of additional elements that -** are the content for the array or object. The payload for an OBJECT -** must be an even number of elements. The first element of each pair is -** the label and must be of type TEXT, TEXTJ, TEXT5, or TEXTRAW. -** -** A valid JSONB blob consists of a single element, as described above. -** Usually this will be an ARRAY or OBJECT element which has many more -** elements as its content. But the overall blob is just a single element. -** -** Input validation for JSONB blobs simply checks that the element type -** code is between 0 and 12 and that the total size of the element -** (header plus payload) is the same as the size of the BLOB. If those -** checks are true, the BLOB is assumed to be JSONB and processing continues. -** Errors are only raised if some other miscoding is discovered during -** processing. -** -** Additional information can be found in the doc/jsonb.md file of the -** canonical SQLite source tree. -*/ -#ifndef SQLITE_OMIT_JSON -/* #include "sqliteInt.h" */ - -/* JSONB element types -*/ -#define JSONB_NULL 0 /* "null" */ -#define JSONB_TRUE 1 /* "true" */ -#define JSONB_FALSE 2 /* "false" */ -#define JSONB_INT 3 /* integer acceptable to JSON and SQL */ -#define JSONB_INT5 4 /* integer in 0x000 notation */ -#define JSONB_FLOAT 5 /* float acceptable to JSON and SQL */ -#define JSONB_FLOAT5 6 /* float with JSON5 extensions */ -#define JSONB_TEXT 7 /* Text compatible with both JSON and SQL */ -#define JSONB_TEXTJ 8 /* Text with JSON escapes */ -#define JSONB_TEXT5 9 /* Text with JSON-5 escape */ -#define JSONB_TEXTRAW 10 /* SQL text that needs escaping for JSON */ -#define JSONB_ARRAY 11 /* An array */ -#define JSONB_OBJECT 12 /* An object */ - -/* Human-readable names for the JSONB values. The index for each -** string must correspond to the JSONB_* integer above. -*/ -static const char * const jsonbType[] = { - "null", "true", "false", "integer", "integer", - "real", "real", "text", "text", "text", - "text", "array", "object", "", "", "", "" -}; - -/* -** Growing our own isspace() routine this way is twice as fast as -** the library isspace() function, resulting in a 7% overall performance -** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). -*/ -static const char jsonIsSpace[] = { -#ifdef SQLITE_ASCII -/*0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */ -#endif -#ifdef SQLITE_EBCDIC -/*0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */ -#endif - -}; -#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x]) - -/* -** The set of all space characters recognized by jsonIsspace(). -** Useful as the second argument to strspn(). -*/ -#ifdef SQLITE_ASCII -static const char jsonSpaces[] = "\011\012\015\040"; -#endif -#ifdef SQLITE_EBCDIC -static const char jsonSpaces[] = "\005\045\015\100"; -#endif - - -/* -** Characters that are special to JSON. Control characters, -** '"' and '\\' and '\''. Actually, '\'' is not special to -** canonical JSON, but it is special in JSON-5, so we include -** it in the set of special characters. -*/ -static const char jsonIsOk[256] = { -#ifdef SQLITE_ASCII -/*0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ - 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 5 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */ -#endif -#ifdef SQLITE_EBCDIC -/*0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 3 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 7 */ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */ -#endif -}; - -/* Objects */ -typedef struct JsonCache JsonCache; -typedef struct JsonString JsonString; -typedef struct JsonParse JsonParse; - -/* -** Magic number used for the JSON parse cache in sqlite3_get_auxdata() -*/ -#define JSON_CACHE_ID (-429938) /* Cache entry */ -#define JSON_CACHE_SIZE 4 /* Max number of cache entries */ - -/* -** jsonUnescapeOneChar() returns this invalid code point if it encounters -** a syntax error. -*/ -#define JSON_INVALID_CHAR 0x99999 - -/* A cache mapping JSON text into JSONB blobs. -** -** Each cache entry is a JsonParse object with the following restrictions: -** -** * The bReadOnly flag must be set -** -** * The aBlob[] array must be owned by the JsonParse object. In other -** words, nBlobAlloc must be non-zero. -** -** * eEdit and delta must be zero. -** -** * zJson must be an RCStr. In other words bJsonIsRCStr must be true. -*/ -struct JsonCache { - sqlite3 *db; /* Database connection */ - int nUsed; /* Number of active entries in the cache */ - JsonParse *a[JSON_CACHE_SIZE]; /* One line for each cache entry */ -}; - -/* An instance of this object represents a JSON string -** under construction. Really, this is a generic string accumulator -** that can be and is used to create strings other than JSON. -** -** If the generated string is longer than will fit into the zSpace[] buffer, -** then it will be an RCStr string. This aids with caching of large -** JSON strings. -*/ -struct JsonString { - sqlite3_context *pCtx; /* Function context - put error messages here */ - char *zBuf; /* Append JSON content here */ - u64 nAlloc; /* Bytes of storage available in zBuf[] */ - u64 nUsed; /* Bytes of zBuf[] currently used */ - u8 bStatic; /* True if zBuf is static space */ - u8 eErr; /* True if an error has been encountered */ - char zSpace[100]; /* Initial static space */ -}; - -/* Allowed values for JsonString.eErr */ -#define JSTRING_OOM 0x01 /* Out of memory */ -#define JSTRING_MALFORMED 0x02 /* Malformed JSONB */ -#define JSTRING_ERR 0x04 /* Error already sent to sqlite3_result */ - -/* The "subtype" set for text JSON values passed through using -** sqlite3_result_subtype() and sqlite3_value_subtype(). -*/ -#define JSON_SUBTYPE 74 /* Ascii for "J" */ - -/* -** Bit values for the flags passed into various SQL function implementations -** via the sqlite3_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() */ -#define JSON_BLOB 0x08 /* Use the BLOB output format */ - - -/* A parsed JSON value. Lifecycle: -** -** 1. JSON comes in and is parsed into a JSONB value in aBlob. The -** original text is stored in zJson. This step is skipped if the -** input is JSONB instead of text JSON. -** -** 2. The aBlob[] array is searched using the JSON path notation, if needed. -** -** 3. Zero or more changes are made to aBlob[] (via json_remove() or -** json_replace() or json_patch() or similar). -** -** 4. New JSON text is generated from the aBlob[] for output. This step -** is skipped if the function is one of the jsonb_* functions that -** returns JSONB instead of text JSON. -*/ -struct JsonParse { - u8 *aBlob; /* JSONB representation of JSON value */ - u32 nBlob; /* Bytes of aBlob[] actually used */ - u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */ - char *zJson; /* Json text used for parsing */ - sqlite3 *db; /* The database connection to which this object belongs */ - int nJson; /* Length of the zJson string in bytes */ - u32 nJPRef; /* Number of references to this object */ - u32 iErr; /* Error location in zJson[] */ - u16 iDepth; /* Nesting depth */ - u8 nErr; /* Number of errors seen */ - u8 oom; /* Set to true if out of memory */ - u8 bJsonIsRCStr; /* True if zJson is an RCStr */ - u8 hasNonstd; /* True if input uses non-standard features like JSON5 */ - u8 bReadOnly; /* Do not modify. */ - /* Search and edit information. See jsonLookupStep() */ - u8 eEdit; /* Edit operation to apply */ - int delta; /* Size change due to the edit */ - u32 nIns; /* Number of bytes to insert */ - u32 iLabel; /* Location of label if search landed on an object value */ - u8 *aIns; /* Content to be inserted */ -}; - -/* Allowed values for JsonParse.eEdit */ -#define JEDIT_DEL 1 /* Delete if exists */ -#define JEDIT_REPL 2 /* Overwrite if exists */ -#define JEDIT_INS 3 /* Insert if not exists */ -#define JEDIT_SET 4 /* Insert or overwrite */ - -/* -** Maximum nesting depth of JSON for this implementation. -** -** This limit is needed to avoid a stack overflow in the recursive -** descent parser. A depth of 1000 is far deeper than any sane JSON -** should go. Historical note: This limit was 2000 prior to version 3.42.0 -*/ -#ifndef SQLITE_JSON_MAX_DEPTH -# define JSON_MAX_DEPTH 1000 -#else -# define JSON_MAX_DEPTH SQLITE_JSON_MAX_DEPTH -#endif - -/* -** Allowed values for the flgs argument to jsonParseFuncArg(); -*/ -#define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */ -#define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */ - -/************************************************************************** -** Forward references -**************************************************************************/ -static void jsonReturnStringAsBlob(JsonString*); -static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p); -static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*); -static void jsonReturnParse(sqlite3_context*,JsonParse*); -static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); -static void jsonParseFree(JsonParse*); -static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); -static u32 jsonUnescapeOneChar(const char*, u32, u32*); - -/************************************************************************** -** Utility routines for dealing with JsonCache objects -**************************************************************************/ - -/* -** Free a JsonCache object. -*/ -static void jsonCacheDelete(JsonCache *p){ - int i; - for(i=0; inUsed; i++){ - jsonParseFree(p->a[i]); - } - sqlite3DbFree(p->db, p); -} -static void jsonCacheDeleteGeneric(void *p){ - jsonCacheDelete((JsonCache*)p); -} - -/* -** Insert a new entry into the cache. If the cache is full, expel -** the least recently used entry. Return SQLITE_OK on success or a -** result code otherwise. -** -** Cache entries are stored in age order, oldest first. -*/ -static int jsonCacheInsert( - sqlite3_context *ctx, /* The SQL statement context holding the cache */ - JsonParse *pParse /* The parse object to be added to the cache */ -){ - JsonCache *p; - - assert( pParse->zJson!=0 ); - assert( pParse->bJsonIsRCStr ); - assert( pParse->delta==0 ); - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ){ - sqlite3 *db = sqlite3_context_db_handle(ctx); - p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; - p->db = db; - sqlite3_set_auxdata(ctx, JSON_CACHE_ID, p, jsonCacheDeleteGeneric); - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ) return SQLITE_NOMEM; - } - if( p->nUsed >= JSON_CACHE_SIZE ){ - jsonParseFree(p->a[0]); - memmove(p->a, &p->a[1], (JSON_CACHE_SIZE-1)*sizeof(p->a[0])); - p->nUsed = JSON_CACHE_SIZE-1; - } - assert( pParse->nBlobAlloc>0 ); - pParse->eEdit = 0; - pParse->nJPRef++; - pParse->bReadOnly = 1; - p->a[p->nUsed] = pParse; - p->nUsed++; - return SQLITE_OK; -} - -/* -** Search for a cached translation the json text supplied by pArg. Return -** the JsonParse object if found. Return NULL if not found. -** -** When a match if found, the matching entry is moved to become the -** most-recently used entry if it isn't so already. -** -** The JsonParse object returned still belongs to the Cache and might -** be deleted at any moment. If the caller wants the JsonParse to -** linger, it needs to increment the nPJRef reference counter. -*/ -static JsonParse *jsonCacheSearch( - sqlite3_context *ctx, /* The SQL statement context holding the cache */ - sqlite3_value *pArg /* Function argument containing SQL text */ -){ - JsonCache *p; - int i; - const char *zJson; - int nJson; - - if( sqlite3_value_type(pArg)!=SQLITE_TEXT ){ - return 0; - } - zJson = (const char*)sqlite3_value_text(pArg); - if( zJson==0 ) return 0; - nJson = sqlite3_value_bytes(pArg); - - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ){ - return 0; - } - for(i=0; inUsed; i++){ - if( p->a[i]->zJson==zJson ) break; - } - if( i>=p->nUsed ){ - for(i=0; inUsed; i++){ - if( p->a[i]->nJson!=nJson ) continue; - if( memcmp(p->a[i]->zJson, zJson, nJson)==0 ) break; - } - } - if( inUsed ){ - if( inUsed-1 ){ - /* Make the matching entry the most recently used entry */ - JsonParse *tmp = p->a[i]; - memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp)); - p->a[p->nUsed-1] = tmp; - i = p->nUsed - 1; - } - assert( p->a[i]->delta==0 ); - return p->a[i]; - }else{ - return 0; - } -} - -/************************************************************************** -** Utility routines for dealing with JsonString objects -**************************************************************************/ - -/* Turn uninitialized bulk memory into a valid JsonString object -** holding a zero-length string. -*/ -static void jsonStringZero(JsonString *p){ - p->zBuf = p->zSpace; - p->nAlloc = sizeof(p->zSpace); - p->nUsed = 0; - p->bStatic = 1; -} - -/* Initialize the JsonString object -*/ -static void jsonStringInit(JsonString *p, sqlite3_context *pCtx){ - p->pCtx = pCtx; - p->eErr = 0; - jsonStringZero(p); -} - -/* Free all allocated memory and reset the JsonString object back to its -** initial state. -*/ -static void jsonStringReset(JsonString *p){ - if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf); - jsonStringZero(p); -} - -/* Report an out-of-memory (OOM) condition -*/ -static void jsonStringOom(JsonString *p){ - p->eErr |= JSTRING_OOM; - if( p->pCtx ) sqlite3_result_error_nomem(p->pCtx); - jsonStringReset(p); -} - -/* Enlarge pJson->zBuf so that it can hold at least N more bytes. -** Return zero on success. Return non-zero on an OOM error -*/ -static int jsonStringGrow(JsonString *p, u32 N){ - u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; - char *zNew; - if( p->bStatic ){ - if( p->eErr ) return 1; - zNew = sqlite3RCStrNew(nTotal); - if( zNew==0 ){ - jsonStringOom(p); - return SQLITE_NOMEM; - } - memcpy(zNew, p->zBuf, (size_t)p->nUsed); - p->zBuf = zNew; - p->bStatic = 0; - }else{ - p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal); - if( p->zBuf==0 ){ - p->eErr |= JSTRING_OOM; - jsonStringZero(p); - return SQLITE_NOMEM; - } - } - p->nAlloc = nTotal; - return SQLITE_OK; -} - -/* Append N bytes from zIn onto the end of the JsonString string. -*/ -static SQLITE_NOINLINE void jsonStringExpandAndAppend( - JsonString *p, - const char *zIn, - u32 N -){ - assert( N>0 ); - if( jsonStringGrow(p,N) ) return; - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; -} -static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ - if( N==0 ) return; - if( N+p->nUsed >= p->nAlloc ){ - jsonStringExpandAndAppend(p,zIn,N); - }else{ - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; - } -} -static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){ - assert( N>0 ); - if( N+p->nUsed >= p->nAlloc ){ - jsonStringExpandAndAppend(p,zIn,N); - }else{ - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; - } -} - -/* Append formatted text (not to exceed N bytes) to the JsonString. -*/ -static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ - va_list ap; - if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return; - va_start(ap, zFormat); - sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); - va_end(ap); - p->nUsed += (int)strlen(p->zBuf+p->nUsed); -} - -/* Append a single character -*/ -static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){ - if( jsonStringGrow(p,1) ) return; - p->zBuf[p->nUsed++] = c; -} -static void jsonAppendChar(JsonString *p, char c){ - if( p->nUsed>=p->nAlloc ){ - jsonAppendCharExpand(p,c); - }else{ - p->zBuf[p->nUsed++] = c; - } -} - -/* Remove a single character from the end of the string -*/ -static void jsonStringTrimOneChar(JsonString *p){ - if( p->eErr==0 ){ - assert( p->nUsed>0 ); - p->nUsed--; - } -} - - -/* Make sure there is a zero terminator on p->zBuf[] -** -** Return true on success. Return false if an OOM prevents this -** from happening. -*/ -static int jsonStringTerminate(JsonString *p){ - jsonAppendChar(p, 0); - jsonStringTrimOneChar(p); - return p->eErr==0; -} - -/* Append a comma separator to the output buffer, if the previous -** character is not '[' or '{'. -*/ -static void jsonAppendSeparator(JsonString *p){ - char c; - if( p->nUsed==0 ) return; - c = p->zBuf[p->nUsed-1]; - if( c=='[' || c=='{' ) return; - jsonAppendChar(p, ','); -} - -/* c is a control character. Append the canonical JSON representation -** of that control character to p. -** -** This routine assumes that the output buffer has already been enlarged -** sufficiently to hold the worst-case encoding plus a nul terminator. -*/ -static void jsonAppendControlChar(JsonString *p, u8 c){ - static const char aSpecial[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - assert( sizeof(aSpecial)==32 ); - assert( aSpecial['\b']=='b' ); - assert( aSpecial['\f']=='f' ); - assert( aSpecial['\n']=='n' ); - assert( aSpecial['\r']=='r' ); - assert( aSpecial['\t']=='t' ); - assert( c>=0 && cnUsed+7 <= p->nAlloc ); - if( aSpecial[c] ){ - p->zBuf[p->nUsed] = '\\'; - p->zBuf[p->nUsed+1] = aSpecial[c]; - p->nUsed += 2; - }else{ - p->zBuf[p->nUsed] = '\\'; - p->zBuf[p->nUsed+1] = 'u'; - p->zBuf[p->nUsed+2] = '0'; - p->zBuf[p->nUsed+3] = '0'; - p->zBuf[p->nUsed+4] = "0123456789abcdef"[c>>4]; - p->zBuf[p->nUsed+5] = "0123456789abcdef"[c&0xf]; - p->nUsed += 6; - } -} - -/* Append the N-byte string in zIn to the end of the JsonString string -** under construction. Enclose the string in double-quotes ("...") and -** escape any double-quotes or backslash characters contained within the -** string. -** -** This routine is a high-runner. There is a measurable performance -** increase associated with unwinding the jsonIsOk[] loop. -*/ -static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ - u32 k; - u8 c; - const u8 *z = (const u8*)zIn; - if( z==0 ) return; - if( (N+p->nUsed+2 >= p->nAlloc) && jsonStringGrow(p,N+2)!=0 ) return; - p->zBuf[p->nUsed++] = '"'; - while( 1 /*exit-by-break*/ ){ - k = 0; - /* The following while() is the 4-way unwound equivalent of - ** - ** while( k=N ){ - while( k=N ){ - if( k>0 ){ - memcpy(&p->zBuf[p->nUsed], z, k); - p->nUsed += k; - } - break; - } - if( k>0 ){ - memcpy(&p->zBuf[p->nUsed], z, k); - p->nUsed += k; - z += k; - N -= k; - } - c = z[0]; - if( c=='"' || c=='\\' ){ - if( (p->nUsed+N+3 > p->nAlloc) && jsonStringGrow(p,N+3)!=0 ) return; - p->zBuf[p->nUsed++] = '\\'; - p->zBuf[p->nUsed++] = c; - }else if( c=='\'' ){ - p->zBuf[p->nUsed++] = c; - }else{ - if( (p->nUsed+N+7 > p->nAlloc) && jsonStringGrow(p,N+7)!=0 ) return; - jsonAppendControlChar(p, c); - } - z++; - N--; - } - p->zBuf[p->nUsed++] = '"'; - assert( p->nUsednAlloc ); -} - -/* -** Append an sqlite3_value (such as a function parameter) to the JSON -** string under construction in p. -*/ -static void jsonAppendSqlValue( - JsonString *p, /* Append to this JSON string */ - sqlite3_value *pValue /* Value to append */ -){ - switch( sqlite3_value_type(pValue) ){ - case SQLITE_NULL: { - jsonAppendRawNZ(p, "null", 4); - break; - } - case SQLITE_FLOAT: { - jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue)); - break; - } - case SQLITE_INTEGER: { - const char *z = (const char*)sqlite3_value_text(pValue); - u32 n = (u32)sqlite3_value_bytes(pValue); - jsonAppendRaw(p, z, n); - break; - } - case SQLITE_TEXT: { - const char *z = (const char*)sqlite3_value_text(pValue); - u32 n = (u32)sqlite3_value_bytes(pValue); - if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ - jsonAppendRaw(p, z, n); - }else{ - jsonAppendString(p, z, n); - } - break; - } - default: { - JsonParse px; - memset(&px, 0, sizeof(px)); - if( jsonArgIsJsonb(pValue, &px) ){ - jsonTranslateBlobToText(&px, 0, p); - }else if( p->eErr==0 ){ - sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); - p->eErr = JSTRING_ERR; - jsonStringReset(p); - } - break; - } - } -} - -/* Make the text in p (which is probably a generated JSON text string) -** the result of the SQL function. -** -** The JsonString is reset. -** -** If pParse and ctx are both non-NULL, then the SQL string in p is -** loaded into the zJson field of the pParse object as a RCStr and the -** pParse is added to the cache. -*/ -static void jsonReturnString( - JsonString *p, /* String to return */ - JsonParse *pParse, /* JSONB source or NULL */ - sqlite3_context *ctx /* Where to cache */ -){ - assert( (pParse!=0)==(ctx!=0) ); - assert( ctx==0 || ctx==p->pCtx ); - if( p->eErr==0 ){ - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(p->pCtx)); - if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(p); - }else if( p->bStatic ){ - sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, - SQLITE_TRANSIENT, SQLITE_UTF8); - }else if( jsonStringTerminate(p) ){ - if( pParse && pParse->bJsonIsRCStr==0 && pParse->nBlobAlloc>0 ){ - int rc; - pParse->zJson = sqlite3RCStrRef(p->zBuf); - pParse->nJson = p->nUsed; - pParse->bJsonIsRCStr = 1; - rc = jsonCacheInsert(ctx, pParse); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(ctx); - jsonStringReset(p); - return; - } - } - sqlite3_result_text64(p->pCtx, sqlite3RCStrRef(p->zBuf), p->nUsed, - sqlite3RCStrUnref, - SQLITE_UTF8); - }else{ - sqlite3_result_error_nomem(p->pCtx); - } - }else if( p->eErr & JSTRING_OOM ){ - sqlite3_result_error_nomem(p->pCtx); - }else if( p->eErr & JSTRING_MALFORMED ){ - sqlite3_result_error(p->pCtx, "malformed JSON", -1); - } - jsonStringReset(p); -} - -/************************************************************************** -** Utility routines for dealing with JsonParse objects -**************************************************************************/ - -/* -** Reclaim all memory allocated by a JsonParse object. But do not -** delete the JsonParse object itself. -*/ -static void jsonParseReset(JsonParse *pParse){ - assert( pParse->nJPRef<=1 ); - if( pParse->bJsonIsRCStr ){ - sqlite3RCStrUnref(pParse->zJson); - pParse->zJson = 0; - pParse->nJson = 0; - pParse->bJsonIsRCStr = 0; - } - if( pParse->nBlobAlloc ){ - sqlite3DbFree(pParse->db, pParse->aBlob); - pParse->aBlob = 0; - pParse->nBlob = 0; - pParse->nBlobAlloc = 0; - } -} - -/* -** Decrement the reference count on the JsonParse object. When the -** count reaches zero, free the object. -*/ -static void jsonParseFree(JsonParse *pParse){ - if( pParse ){ - if( pParse->nJPRef>1 ){ - pParse->nJPRef--; - }else{ - jsonParseReset(pParse); - sqlite3DbFree(pParse->db, pParse); - } - } -} - -/************************************************************************** -** Utility routines for the JSON text parser -**************************************************************************/ - -/* -** Translate a single byte of Hex into an integer. -** This routine only gives a correct answer if h really is a valid hexadecimal -** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not -** assert() if the digit is not hex. -*/ -static u8 jsonHexToInt(int h){ -#ifdef SQLITE_ASCII - h += 9*(1&(h>>6)); -#endif -#ifdef SQLITE_EBCDIC - h += 9*(1&~(h>>4)); -#endif - return (u8)(h & 0xf); -} - -/* -** Convert a 4-byte hex string into an integer -*/ -static u32 jsonHexToInt4(const char *z){ - u32 v; - v = (jsonHexToInt(z[0])<<12) - + (jsonHexToInt(z[1])<<8) - + (jsonHexToInt(z[2])<<4) - + jsonHexToInt(z[3]); - return v; -} - -/* -** Return true if z[] begins with 2 (or more) hexadecimal digits -*/ -static int jsonIs2Hex(const char *z){ - return sqlite3Isxdigit(z[0]) && sqlite3Isxdigit(z[1]); -} - -/* -** Return true if z[] begins with 4 (or more) hexadecimal digits -*/ -static int jsonIs4Hex(const char *z){ - return jsonIs2Hex(z) && jsonIs2Hex(&z[2]); -} - -/* -** Return the number of bytes of JSON5 whitespace at the beginning of -** the input string z[]. -** -** JSON5 whitespace consists of any of the following characters: -** -** Unicode UTF-8 Name -** U+0009 09 horizontal tab -** U+000a 0a line feed -** U+000b 0b vertical tab -** U+000c 0c form feed -** U+000d 0d carriage return -** U+0020 20 space -** U+00a0 c2 a0 non-breaking space -** U+1680 e1 9a 80 ogham space mark -** U+2000 e2 80 80 en quad -** U+2001 e2 80 81 em quad -** U+2002 e2 80 82 en space -** U+2003 e2 80 83 em space -** U+2004 e2 80 84 three-per-em space -** U+2005 e2 80 85 four-per-em space -** U+2006 e2 80 86 six-per-em space -** U+2007 e2 80 87 figure space -** U+2008 e2 80 88 punctuation space -** U+2009 e2 80 89 thin space -** U+200a e2 80 8a hair space -** U+2028 e2 80 a8 line separator -** U+2029 e2 80 a9 paragraph separator -** U+202f e2 80 af narrow no-break space (NNBSP) -** U+205f e2 81 9f medium mathematical space (MMSP) -** U+3000 e3 80 80 ideographical space -** U+FEFF ef bb bf byte order mark -** -** In addition, comments between '/', '*' and '*', '/' and -** from '/', '/' to end-of-line are also considered to be whitespace. -*/ -static int json5Whitespace(const char *zIn){ - int n = 0; - const u8 *z = (u8*)zIn; - while( 1 /*exit by "goto whitespace_done"*/ ){ - switch( z[n] ){ - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x20: { - n++; - break; - } - case '/': { - if( z[n+1]=='*' && z[n+2]!=0 ){ - int j; - for(j=n+3; z[j]!='/' || z[j-1]!='*'; j++){ - if( z[j]==0 ) goto whitespace_done; - } - n = j+1; - break; - }else if( z[n+1]=='/' ){ - int j; - char c; - for(j=n+2; (c = z[j])!=0; j++){ - if( c=='\n' || c=='\r' ) break; - if( 0xe2==(u8)c && 0x80==(u8)z[j+1] - && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]) - ){ - j += 2; - break; - } - } - n = j; - if( z[n] ) n++; - break; - } - goto whitespace_done; - } - case 0xc2: { - if( z[n+1]==0xa0 ){ - n += 2; - break; - } - goto whitespace_done; - } - case 0xe1: { - if( z[n+1]==0x9a && z[n+2]==0x80 ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xe2: { - if( z[n+1]==0x80 ){ - u8 c = z[n+2]; - if( c<0x80 ) goto whitespace_done; - if( c<=0x8a || c==0xa8 || c==0xa9 || c==0xaf ){ - n += 3; - break; - } - }else if( z[n+1]==0x81 && z[n+2]==0x9f ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xe3: { - if( z[n+1]==0x80 && z[n+2]==0x80 ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xef: { - if( z[n+1]==0xbb && z[n+2]==0xbf ){ - n += 3; - break; - } - goto whitespace_done; - } - default: { - goto whitespace_done; - } - } - } - whitespace_done: - return n; -} - -/* -** Extra floating-point literals to allow in JSON. -*/ -static const struct NanInfName { - char c1; - char c2; - char n; - char eType; - char nRepl; - char *zMatch; - char *zRepl; -} aNanInfName[] = { - { 'i', 'I', 3, JSONB_FLOAT, 7, "inf", "9.0e999" }, - { 'i', 'I', 8, JSONB_FLOAT, 7, "infinity", "9.0e999" }, - { 'n', 'N', 3, JSONB_NULL, 4, "NaN", "null" }, - { 'q', 'Q', 4, JSONB_NULL, 4, "QNaN", "null" }, - { 's', 'S', 4, JSONB_NULL, 4, "SNaN", "null" }, -}; - - -/* -** Report the wrong number of arguments for json_insert(), json_replace() -** or json_set(). -*/ -static void jsonWrongNumArgs( - sqlite3_context *pCtx, - const char *zFuncName -){ - char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", - zFuncName); - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); -} - -/**************************************************************************** -** Utility routines for dealing with the binary BLOB representation of JSON -****************************************************************************/ - -/* -** Expand pParse->aBlob so that it holds at least N bytes. -** -** Return the number of errors. -*/ -static int jsonBlobExpand(JsonParse *pParse, u32 N){ - u8 *aNew; - u64 t; - assert( N>pParse->nBlobAlloc ); - if( pParse->nBlobAlloc==0 ){ - t = 100; - }else{ - t = pParse->nBlobAlloc*2; - } - if( tdb, pParse->aBlob, t); - if( aNew==0 ){ pParse->oom = 1; return 1; } - assert( t<0x7fffffff ); - pParse->aBlob = aNew; - pParse->nBlobAlloc = (u32)t; - return 0; -} - -/* -** If pParse->aBlob is not previously editable (because it is taken -** from sqlite3_value_blob(), as indicated by the fact that -** pParse->nBlobAlloc==0 and pParse->nBlob>0) then make it editable -** by making a copy into space obtained from malloc. -** -** Return true on success. Return false on OOM. -*/ -static int jsonBlobMakeEditable(JsonParse *pParse, u32 nExtra){ - u8 *aOld; - u32 nSize; - assert( !pParse->bReadOnly ); - if( pParse->oom ) return 0; - if( pParse->nBlobAlloc>0 ) return 1; - aOld = pParse->aBlob; - nSize = pParse->nBlob + nExtra; - pParse->aBlob = 0; - if( jsonBlobExpand(pParse, nSize) ){ - return 0; - } - assert( pParse->nBlobAlloc >= pParse->nBlob + nExtra ); - memcpy(pParse->aBlob, aOld, pParse->nBlob); - return 1; -} - -/* Expand pParse->aBlob and append one bytes. -*/ -static SQLITE_NOINLINE void jsonBlobExpandAndAppendOneByte( - JsonParse *pParse, - u8 c -){ - jsonBlobExpand(pParse, pParse->nBlob+1); - if( pParse->oom==0 ){ - assert( pParse->nBlob+1<=pParse->nBlobAlloc ); - pParse->aBlob[pParse->nBlob++] = c; - } -} - -/* Append a single character. -*/ -static void jsonBlobAppendOneByte(JsonParse *pParse, u8 c){ - if( pParse->nBlob >= pParse->nBlobAlloc ){ - jsonBlobExpandAndAppendOneByte(pParse, c); - }else{ - pParse->aBlob[pParse->nBlob++] = c; - } -} - -/* Slow version of jsonBlobAppendNode() that first resizes the -** pParse->aBlob structure. -*/ -static void jsonBlobAppendNode(JsonParse*,u8,u32,const void*); -static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode( - JsonParse *pParse, - u8 eType, - u32 szPayload, - const void *aPayload -){ - if( jsonBlobExpand(pParse, pParse->nBlob+szPayload+9) ) return; - jsonBlobAppendNode(pParse, eType, szPayload, aPayload); -} - - -/* Append a node type byte together with the payload size and -** possibly also the payload. -** -** If aPayload is not NULL, then it is a pointer to the payload which -** is also appended. If aPayload is NULL, the pParse->aBlob[] array -** is resized (if necessary) so that it is big enough to hold the -** payload, but the payload is not appended and pParse->nBlob is left -** pointing to where the first byte of payload will eventually be. -*/ -static void jsonBlobAppendNode( - JsonParse *pParse, /* The JsonParse object under construction */ - u8 eType, /* Node type. One of JSONB_* */ - u32 szPayload, /* Number of bytes of payload */ - const void *aPayload /* The payload. Might be NULL */ -){ - u8 *a; - if( pParse->nBlob+szPayload+9 > pParse->nBlobAlloc ){ - jsonBlobExpandAndAppendNode(pParse,eType,szPayload,aPayload); - return; - } - assert( pParse->aBlob!=0 ); - a = &pParse->aBlob[pParse->nBlob]; - if( szPayload<=11 ){ - a[0] = eType | (szPayload<<4); - pParse->nBlob += 1; - }else if( szPayload<=0xff ){ - a[0] = eType | 0xc0; - a[1] = szPayload & 0xff; - pParse->nBlob += 2; - }else if( szPayload<=0xffff ){ - a[0] = eType | 0xd0; - a[1] = (szPayload >> 8) & 0xff; - a[2] = szPayload & 0xff; - pParse->nBlob += 3; - }else{ - a[0] = eType | 0xe0; - a[1] = (szPayload >> 24) & 0xff; - a[2] = (szPayload >> 16) & 0xff; - a[3] = (szPayload >> 8) & 0xff; - a[4] = szPayload & 0xff; - pParse->nBlob += 5; - } - if( aPayload ){ - pParse->nBlob += szPayload; - memcpy(&pParse->aBlob[pParse->nBlob-szPayload], aPayload, szPayload); - } -} - -/* Change the payload size for the node at index i to be szPayload. -*/ -static int jsonBlobChangePayloadSize( - JsonParse *pParse, - u32 i, - u32 szPayload -){ - u8 *a; - u8 szType; - u8 nExtra; - u8 nNeeded; - int delta; - if( pParse->oom ) return 0; - a = &pParse->aBlob[i]; - szType = a[0]>>4; - if( szType<=11 ){ - nExtra = 0; - }else if( szType==12 ){ - nExtra = 1; - }else if( szType==13 ){ - nExtra = 2; - }else if( szType==14 ){ - nExtra = 4; - }else{ - nExtra = 8; - } - if( szPayload<=11 ){ - nNeeded = 0; - }else if( szPayload<=0xff ){ - nNeeded = 1; - }else if( szPayload<=0xffff ){ - nNeeded = 2; - }else{ - nNeeded = 4; - } - delta = nNeeded - nExtra; - if( delta ){ - u32 newSize = pParse->nBlob + delta; - if( delta>0 ){ - if( newSize>pParse->nBlobAlloc && jsonBlobExpand(pParse, newSize) ){ - return 0; /* OOM error. Error state recorded in pParse->oom. */ - } - a = &pParse->aBlob[i]; - memmove(&a[1+delta], &a[1], pParse->nBlob - (i+1)); - }else{ - memmove(&a[1], &a[1-delta], pParse->nBlob - (i+1-delta)); - } - pParse->nBlob = newSize; - } - if( nNeeded==0 ){ - a[0] = (a[0] & 0x0f) | (szPayload<<4); - }else if( nNeeded==1 ){ - a[0] = (a[0] & 0x0f) | 0xc0; - a[1] = szPayload & 0xff; - }else if( nNeeded==2 ){ - a[0] = (a[0] & 0x0f) | 0xd0; - a[1] = (szPayload >> 8) & 0xff; - a[2] = szPayload & 0xff; - }else{ - a[0] = (a[0] & 0x0f) | 0xe0; - a[1] = (szPayload >> 24) & 0xff; - a[2] = (szPayload >> 16) & 0xff; - a[3] = (szPayload >> 8) & 0xff; - a[4] = szPayload & 0xff; - } - return delta; -} - -/* -** If z[0] is 'u' and is followed by exactly 4 hexadecimal character, -** then set *pOp to JSONB_TEXTJ and return true. If not, do not make -** any changes to *pOp and return false. -*/ -static int jsonIs4HexB(const char *z, int *pOp){ - if( z[0]!='u' ) return 0; - if( !jsonIs4Hex(&z[1]) ) return 0; - *pOp = JSONB_TEXTJ; - return 1; -} - -/* -** Check a single element of the JSONB in pParse for validity. -** -** The element to be checked starts at offset i and must end at on the -** last byte before iEnd. -** -** Return 0 if everything is correct. Return the 1-based byte offset of the -** error if a problem is detected. (In other words, if the error is at offset -** 0, return 1). -*/ -static u32 jsonbValidityCheck( - const JsonParse *pParse, /* Input JSONB. Only aBlob and nBlob are used */ - u32 i, /* Start of element as pParse->aBlob[i] */ - u32 iEnd, /* One more than the last byte of the element */ - u32 iDepth /* Current nesting depth */ -){ - u32 n, sz, j, k; - const u8 *z; - u8 x; - if( iDepth>JSON_MAX_DEPTH ) return i+1; - sz = 0; - n = jsonbPayloadSize(pParse, i, &sz); - if( NEVER(n==0) ) return i+1; /* Checked by caller */ - if( NEVER(i+n+sz!=iEnd) ) return i+1; /* Checked by caller */ - z = pParse->aBlob; - x = z[i] & 0x0f; - switch( x ){ - case JSONB_NULL: - case JSONB_TRUE: - case JSONB_FALSE: { - return n+sz==1 ? 0 : i+1; - } - case JSONB_INT: { - if( sz<1 ) return i+1; - j = i+n; - if( z[j]=='-' ){ - j++; - if( sz<2 ) return i+1; - } - k = i+n+sz; - while( jk ) return j+1; - if( z[j+1]!='.' && z[j+1]!='e' && z[j+1]!='E' ) return j+1; - j++; - } - for(; j0 ) return j+1; - if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ - return j+1; - } - seen = 1; - continue; - } - if( z[j]=='e' || z[j]=='E' ){ - if( seen==2 ) return j+1; - if( j==k-1 ) return j+1; - if( z[j+1]=='+' || z[j+1]=='-' ){ - j++; - if( j==k-1 ) return j+1; - } - seen = 2; - continue; - } - return j+1; - } - if( seen==0 ) return i+1; - return 0; - } - case JSONB_TEXT: { - j = i+n; - k = j+sz; - while( j=k ){ - return j+1; - }else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){ - j++; - }else if( z[j+1]=='u' ){ - if( j+5>=k ) return j+1; - if( !jsonIs4Hex((const char*)&z[j+2]) ) return j+1; - j++; - }else if( x!=JSONB_TEXT5 ){ - return j+1; - }else{ - u32 c = 0; - u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c); - if( c==JSON_INVALID_CHAR ) return j+1; - j += szC - 1; - } - } - j++; - } - return 0; - } - case JSONB_TEXTRAW: { - return 0; - } - case JSONB_ARRAY: { - u32 sub; - j = i+n; - k = j+sz; - while( jk ) return j+1; - sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); - if( sub ) return sub; - j += n + sz; - } - assert( j==k ); - return 0; - } - case JSONB_OBJECT: { - u32 cnt = 0; - u32 sub; - j = i+n; - k = j+sz; - while( jk ) return j+1; - if( (cnt & 1)==0 ){ - x = z[j] & 0x0f; - if( xJSONB_TEXTRAW ) return j+1; - } - sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); - if( sub ) return sub; - cnt++; - j += n + sz; - } - assert( j==k ); - if( (cnt & 1)!=0 ) return j+1; - return 0; - } - default: { - return i+1; - } - } -} - -/* -** Translate a single element of JSON text at pParse->zJson[i] into -** its equivalent binary JSONB representation. Append the translation into -** pParse->aBlob[] beginning at pParse->nBlob. The size of -** pParse->aBlob[] is increased as necessary. -** -** Return the index of the first character past the end of the element parsed, -** or one of the following special result codes: -** -** 0 End of input -** -1 Syntax error or OOM -** -2 '}' seen \ -** -3 ']' seen \___ For these returns, pParse->iErr is set to -** -4 ',' seen / the index in zJson[] of the seen character -** -5 ':' seen / -*/ -static int jsonTranslateTextToBlob(JsonParse *pParse, u32 i){ - char c; - u32 j; - u32 iThis, iStart; - int x; - u8 t; - const char *z = pParse->zJson; -json_parse_restart: - switch( (u8)z[i] ){ - case '{': { - /* Parse object */ - iThis = pParse->nBlob; - jsonBlobAppendNode(pParse, JSONB_OBJECT, pParse->nJson-i, 0); - if( ++pParse->iDepth > JSON_MAX_DEPTH ){ - pParse->iErr = i; - return -1; - } - iStart = pParse->nBlob; - for(j=i+1;;j++){ - u32 iBlob = pParse->nBlob; - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - int op; - if( x==(-2) ){ - j = pParse->iErr; - if( pParse->nBlob!=(u32)iStart ) pParse->hasNonstd = 1; - break; - } - j += json5Whitespace(&z[j]); - op = JSONB_TEXT; - if( sqlite3JsonId1(z[j]) - || (z[j]=='\\' && jsonIs4HexB(&z[j+1], &op)) - ){ - int k = j+1; - while( (sqlite3JsonId2(z[k]) && json5Whitespace(&z[k])==0) - || (z[k]=='\\' && jsonIs4HexB(&z[k+1], &op)) - ){ - k++; - } - assert( iBlob==pParse->nBlob ); - jsonBlobAppendNode(pParse, op, k-j, &z[j]); - pParse->hasNonstd = 1; - x = k; - }else{ - if( x!=-1 ) pParse->iErr = j; - return -1; - } - } - if( pParse->oom ) return -1; - t = pParse->aBlob[iBlob] & 0x0f; - if( tJSONB_TEXTRAW ){ - pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==':' ){ - j++; - }else{ - if( jsonIsspace(z[j]) ){ - /* strspn() is not helpful here */ - do{ j++; }while( jsonIsspace(z[j]) ); - if( z[j]==':' ){ - j++; - goto parse_object_value; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x!=(-5) ){ - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = pParse->iErr+1; - } - parse_object_value: - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==',' ){ - continue; - }else if( z[j]=='}' ){ - break; - }else{ - if( jsonIsspace(z[j]) ){ - j += 1 + (u32)strspn(&z[j+1], jsonSpaces); - if( z[j]==',' ){ - continue; - }else if( z[j]=='}' ){ - break; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x==(-4) ){ - j = pParse->iErr; - continue; - } - if( x==(-2) ){ - j = pParse->iErr; - break; - } - } - pParse->iErr = j; - return -1; - } - jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); - pParse->iDepth--; - return j+1; - } - case '[': { - /* Parse array */ - iThis = pParse->nBlob; - assert( i<=(u32)pParse->nJson ); - jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0); - iStart = pParse->nBlob; - if( pParse->oom ) return -1; - if( ++pParse->iDepth > JSON_MAX_DEPTH ){ - pParse->iErr = i; - return -1; - } - for(j=i+1;;j++){ - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - if( x==(-3) ){ - j = pParse->iErr; - if( pParse->nBlob!=iStart ) pParse->hasNonstd = 1; - break; - } - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==',' ){ - continue; - }else if( z[j]==']' ){ - break; - }else{ - if( jsonIsspace(z[j]) ){ - j += 1 + (u32)strspn(&z[j+1], jsonSpaces); - if( z[j]==',' ){ - continue; - }else if( z[j]==']' ){ - break; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x==(-4) ){ - j = pParse->iErr; - continue; - } - if( x==(-3) ){ - j = pParse->iErr; - break; - } - } - pParse->iErr = j; - return -1; - } - jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); - pParse->iDepth--; - return j+1; - } - case '\'': { - u8 opcode; - char cDelim; - pParse->hasNonstd = 1; - opcode = JSONB_TEXT; - goto parse_string; - case '"': - /* Parse string */ - opcode = JSONB_TEXT; - parse_string: - cDelim = z[i]; - j = i+1; - while( 1 /*exit-by-break*/ ){ - if( jsonIsOk[(u8)z[j]] ){ - if( !jsonIsOk[(u8)z[j+1]] ){ - j += 1; - }else if( !jsonIsOk[(u8)z[j+2]] ){ - j += 2; - }else{ - j += 3; - continue; - } - } - c = z[j]; - if( c==cDelim ){ - break; - }else if( c=='\\' ){ - c = z[++j]; - if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' - || c=='n' || c=='r' || c=='t' - || (c=='u' && jsonIs4Hex(&z[j+1])) ){ - if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ; - }else if( c=='\'' || c=='v' || c=='\n' -#ifdef SQLITE_BUG_COMPATIBLE_20250510 - || (c=='0') /* Legacy bug compatible */ -#else - || (c=='0' && !sqlite3Isdigit(z[j+1])) /* Correct implementation */ -#endif - || (0xe2==(u8)c && 0x80==(u8)z[j+1] - && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2])) - || (c=='x' && jsonIs2Hex(&z[j+1])) ){ - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else if( c=='\r' ){ - if( z[j+1]=='\n' ) j++; - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else{ - pParse->iErr = j; - return -1; - } - }else if( c<=0x1f ){ - if( c==0 ){ - pParse->iErr = j; - return -1; - } - /* Control characters are not allowed in canonical JSON string - ** literals, but are allowed in JSON5 string literals. */ - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else if( c=='"' ){ - opcode = JSONB_TEXT5; - } - j++; - } - jsonBlobAppendNode(pParse, opcode, j-1-i, &z[i+1]); - return j+1; - } - case 't': { - if( strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonBlobAppendOneByte(pParse, JSONB_TRUE); - return i+4; - } - pParse->iErr = i; - return -1; - } - case 'f': { - if( strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){ - jsonBlobAppendOneByte(pParse, JSONB_FALSE); - return i+5; - } - pParse->iErr = i; - return -1; - } - case '+': { - u8 seenE; - pParse->hasNonstd = 1; - t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - goto parse_number; - case '.': - if( sqlite3Isdigit(z[i+1]) ){ - pParse->hasNonstd = 1; - t = 0x03; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - seenE = 0; - goto parse_number_2; - } - pParse->iErr = i; - return -1; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* Parse number */ - t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - parse_number: - seenE = 0; - assert( '-' < '0' ); - assert( '+' < '0' ); - assert( '.' < '0' ); - c = z[i]; - - if( c<='0' ){ - if( c=='0' ){ - if( (z[i+1]=='x' || z[i+1]=='X') && sqlite3Isxdigit(z[i+2]) ){ - assert( t==0x00 ); - pParse->hasNonstd = 1; - t = 0x01; - for(j=i+3; sqlite3Isxdigit(z[j]); j++){} - goto parse_number_finish; - }else if( sqlite3Isdigit(z[i+1]) ){ - pParse->iErr = i+1; - return -1; - } - }else{ - if( !sqlite3Isdigit(z[i+1]) ){ - /* JSON5 allows for "+Infinity" and "-Infinity" using exactly - ** that case. SQLite also allows these in any case and it allows - ** "+inf" and "-inf". */ - if( (z[i+1]=='I' || z[i+1]=='i') - && sqlite3StrNICmp(&z[i+1], "inf",3)==0 - ){ - pParse->hasNonstd = 1; - if( z[i]=='-' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); - }else{ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); - } - return i + (sqlite3StrNICmp(&z[i+4],"inity",5)==0 ? 9 : 4); - } - if( z[i+1]=='.' ){ - pParse->hasNonstd = 1; - t |= 0x01; - goto parse_number_2; - } - pParse->iErr = i; - return -1; - } - if( z[i+1]=='0' ){ - if( sqlite3Isdigit(z[i+2]) ){ - pParse->iErr = i+1; - return -1; - }else if( (z[i+2]=='x' || z[i+2]=='X') && sqlite3Isxdigit(z[i+3]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - for(j=i+4; sqlite3Isxdigit(z[j]); j++){} - goto parse_number_finish; - } - } - } - } - - parse_number_2: - for(j=i+1;; j++){ - c = z[j]; - if( sqlite3Isdigit(c) ) continue; - if( c=='.' ){ - if( (t & 0x02)!=0 ){ - pParse->iErr = j; - return -1; - } - t |= 0x02; - continue; - } - if( c=='e' || c=='E' ){ - if( z[j-1]<'0' ){ - if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - }else{ - pParse->iErr = j; - return -1; - } - } - if( seenE ){ - pParse->iErr = j; - return -1; - } - t |= 0x02; - seenE = 1; - c = z[j+1]; - if( c=='+' || c=='-' ){ - j++; - c = z[j+1]; - } - if( c<'0' || c>'9' ){ - pParse->iErr = j; - return -1; - } - continue; - } - break; - } - if( z[j-1]<'0' ){ - if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - }else{ - pParse->iErr = j; - return -1; - } - } - parse_number_finish: - assert( JSONB_INT+0x01==JSONB_INT5 ); - assert( JSONB_FLOAT+0x01==JSONB_FLOAT5 ); - assert( JSONB_INT+0x02==JSONB_FLOAT ); - if( z[i]=='+' ) i++; - jsonBlobAppendNode(pParse, JSONB_INT+t, j-i, &z[i]); - return j; - } - case '}': { - pParse->iErr = i; - return -2; /* End of {...} */ - } - case ']': { - pParse->iErr = i; - return -3; /* End of [...] */ - } - case ',': { - pParse->iErr = i; - return -4; /* List separator */ - } - case ':': { - pParse->iErr = i; - return -5; /* Object label/value separator */ - } - case 0: { - return 0; /* End of file */ - } - case 0x09: - case 0x0a: - case 0x0d: - case 0x20: { - i += 1 + (u32)strspn(&z[i+1], jsonSpaces); - goto json_parse_restart; - } - case 0x0b: - case 0x0c: - case '/': - case 0xc2: - case 0xe1: - case 0xe2: - case 0xe3: - case 0xef: { - j = json5Whitespace(&z[i]); - if( j>0 ){ - i += j; - pParse->hasNonstd = 1; - goto json_parse_restart; - } - pParse->iErr = i; - return -1; - } - case 'n': { - if( strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonBlobAppendOneByte(pParse, JSONB_NULL); - return i+4; - } - /* fall-through into the default case that checks for NaN */ - /* no break */ deliberate_fall_through - } - default: { - u32 k; - int nn; - c = z[i]; - for(k=0; khasNonstd = 1; - return i + nn; - } - pParse->iErr = i; - return -1; /* Syntax error */ - } - } /* End switch(z[i]) */ -} - - -/* -** Parse a complete JSON string. Return 0 on success or non-zero if there -** are any errors. If an error occurs, free all memory held by pParse, -** but not pParse itself. -** -** pParse must be initialized to an empty parse object prior to calling -** this routine. -*/ -static int jsonConvertTextToBlob( - JsonParse *pParse, /* Initialize and fill this JsonParse object */ - sqlite3_context *pCtx /* Report errors here */ -){ - int i; - const char *zJson = pParse->zJson; - i = jsonTranslateTextToBlob(pParse, 0); - if( pParse->oom ) i = -1; - if( i>0 ){ -#ifdef SQLITE_DEBUG - assert( pParse->iDepth==0 ); - if( sqlite3Config.bJsonSelfcheck ){ - assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 ); - } -#endif - while( jsonIsspace(zJson[i]) ) i++; - if( zJson[i] ){ - i += json5Whitespace(&zJson[i]); - if( zJson[i] ){ - if( pCtx ) sqlite3_result_error(pCtx, "malformed JSON", -1); - jsonParseReset(pParse); - return 1; - } - pParse->hasNonstd = 1; - } - } - if( i<=0 ){ - if( pCtx!=0 ){ - if( pParse->oom ){ - sqlite3_result_error_nomem(pCtx); - }else{ - sqlite3_result_error(pCtx, "malformed JSON", -1); - } - } - jsonParseReset(pParse); - return 1; - } - return 0; -} - -/* -** The input string pStr is a well-formed JSON text string. Convert -** this into the JSONB format and make it the return value of the -** SQL function. -*/ -static void jsonReturnStringAsBlob(JsonString *pStr){ - JsonParse px; - memset(&px, 0, sizeof(px)); - jsonStringTerminate(pStr); - if( pStr->eErr ){ - sqlite3_result_error_nomem(pStr->pCtx); - return; - } - px.zJson = pStr->zBuf; - px.nJson = pStr->nUsed; - px.db = sqlite3_context_db_handle(pStr->pCtx); - (void)jsonTranslateTextToBlob(&px, 0); - if( px.oom ){ - sqlite3DbFree(px.db, px.aBlob); - sqlite3_result_error_nomem(pStr->pCtx); - }else{ - assert( px.nBlobAlloc>0 ); - assert( !px.bReadOnly ); - sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, SQLITE_DYNAMIC); - } -} - -/* The byte at index i is a node type-code. This routine -** determines the payload size for that node and writes that -** payload size in to *pSz. It returns the offset from i to the -** beginning of the payload. Return 0 on error. -*/ -static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){ - u8 x; - u32 sz; - u32 n; - assert( i<=pParse->nBlob ); - x = pParse->aBlob[i]>>4; - if( x<=11 ){ - sz = x; - n = 1; - }else if( x==12 ){ - if( i+1>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = pParse->aBlob[i+1]; - n = 2; - }else if( x==13 ){ - if( i+2>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = (pParse->aBlob[i+1]<<8) + pParse->aBlob[i+2]; - n = 3; - }else if( x==14 ){ - if( i+4>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = ((u32)pParse->aBlob[i+1]<<24) + (pParse->aBlob[i+2]<<16) + - (pParse->aBlob[i+3]<<8) + pParse->aBlob[i+4]; - n = 5; - }else{ - if( i+8>=pParse->nBlob - || pParse->aBlob[i+1]!=0 - || pParse->aBlob[i+2]!=0 - || pParse->aBlob[i+3]!=0 - || pParse->aBlob[i+4]!=0 - ){ - *pSz = 0; - return 0; - } - sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) + - (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8]; - n = 9; - } - if( (i64)i+sz+n > pParse->nBlob - && (i64)i+sz+n > pParse->nBlob-pParse->delta - ){ - *pSz = 0; - return 0; - } - *pSz = sz; - return n; -} - - -/* -** Translate the binary JSONB representation of JSON beginning at -** pParse->aBlob[i] into a JSON text string. Append the JSON -** text onto the end of pOut. Return the index in pParse->aBlob[] -** of the first byte past the end of the element that is translated. -** -** If an error is detected in the BLOB input, the pOut->eErr flag -** might get set to JSTRING_MALFORMED. But not all BLOB input errors -** are detected. So a malformed JSONB input might either result -** in an error, or in incorrect JSON. -** -** The pOut->eErr JSTRING_OOM flag is set on a OOM. -*/ -static u32 jsonTranslateBlobToText( - const JsonParse *pParse, /* the complete parse of the JSON */ - u32 i, /* Start rendering at this index */ - JsonString *pOut /* Write JSON here */ -){ - u32 sz, n, j, iEnd; - - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - pOut->eErr |= JSTRING_MALFORMED; - return pParse->nBlob+1; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_NULL: { - jsonAppendRawNZ(pOut, "null", 4); - return i+1; - } - case JSONB_TRUE: { - jsonAppendRawNZ(pOut, "true", 4); - return i+1; - } - case JSONB_FALSE: { - jsonAppendRawNZ(pOut, "false", 5); - return i+1; - } - case JSONB_INT: - case JSONB_FLOAT: { - if( sz==0 ) goto malformed_jsonb; - jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); - break; - } - case JSONB_INT5: { /* Integer literal in hexadecimal notation */ - u32 k = 2; - sqlite3_uint64 u = 0; - const char *zIn = (const char*)&pParse->aBlob[i+n]; - int bOverflow = 0; - if( sz==0 ) goto malformed_jsonb; - if( zIn[0]=='-' ){ - jsonAppendChar(pOut, '-'); - k++; - }else if( zIn[0]=='+' ){ - k++; - } - for(; keErr |= JSTRING_MALFORMED; - break; - }else if( (u>>60)!=0 ){ - bOverflow = 1; - }else{ - u = u*16 + sqlite3HexToInt(zIn[k]); - } - } - jsonPrintf(100,pOut,bOverflow?"9.0e999":"%llu", u); - break; - } - case JSONB_FLOAT5: { /* Float literal missing digits beside "." */ - u32 k = 0; - const char *zIn = (const char*)&pParse->aBlob[i+n]; - if( sz==0 ) goto malformed_jsonb; - if( zIn[0]=='-' ){ - jsonAppendChar(pOut, '-'); - k++; - } - if( zIn[k]=='.' ){ - jsonAppendChar(pOut, '0'); - } - for(; knUsed+sz+2<=pOut->nAlloc || jsonStringGrow(pOut, sz+2)==0 ){ - pOut->zBuf[pOut->nUsed] = '"'; - memcpy(pOut->zBuf+pOut->nUsed+1,(const char*)&pParse->aBlob[i+n],sz); - pOut->zBuf[pOut->nUsed+sz+1] = '"'; - pOut->nUsed += sz+2; - } - break; - } - case JSONB_TEXT5: { - const char *zIn; - u32 k; - u32 sz2 = sz; - zIn = (const char*)&pParse->aBlob[i+n]; - jsonAppendChar(pOut, '"'); - while( sz2>0 ){ - for(k=0; k0 ){ - jsonAppendRawNZ(pOut, zIn, k); - if( k>=sz2 ){ - break; - } - zIn += k; - sz2 -= k; - } - if( zIn[0]=='"' ){ - jsonAppendRawNZ(pOut, "\\\"", 2); - zIn++; - sz2--; - continue; - } - if( zIn[0]<=0x1f ){ - if( pOut->nUsed+7>pOut->nAlloc && jsonStringGrow(pOut,7) ) break; - jsonAppendControlChar(pOut, zIn[0]); - zIn++; - sz2--; - continue; - } - assert( zIn[0]=='\\' ); - assert( sz2>=1 ); - if( sz2<2 ){ - pOut->eErr |= JSTRING_MALFORMED; - break; - } - switch( (u8)zIn[1] ){ - case '\'': - jsonAppendChar(pOut, '\''); - break; - case 'v': - jsonAppendRawNZ(pOut, "\\u0009", 6); - break; - case 'x': - if( sz2<4 ){ - pOut->eErr |= JSTRING_MALFORMED; - sz2 = 2; - break; - } - jsonAppendRawNZ(pOut, "\\u00", 4); - jsonAppendRawNZ(pOut, &zIn[2], 2); - zIn += 2; - sz2 -= 2; - break; - case '0': - jsonAppendRawNZ(pOut, "\\u0000", 6); - break; - case '\r': - if( sz2>2 && zIn[2]=='\n' ){ - zIn++; - sz2--; - } - break; - case '\n': - break; - case 0xe2: - /* '\' followed by either U+2028 or U+2029 is ignored as - ** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29. - ** U+2029 is the same except for the last byte */ - if( sz2<4 - || 0x80!=(u8)zIn[2] - || (0xa8!=(u8)zIn[3] && 0xa9!=(u8)zIn[3]) - ){ - pOut->eErr |= JSTRING_MALFORMED; - sz2 = 2; - break; - } - zIn += 2; - sz2 -= 2; - break; - default: - jsonAppendRawNZ(pOut, zIn, 2); - break; - } - assert( sz2>=2 ); - zIn += 2; - sz2 -= 2; - } - jsonAppendChar(pOut, '"'); - break; - } - case JSONB_TEXTRAW: { - jsonAppendString(pOut, (const char*)&pParse->aBlob[i+n], sz); - break; - } - case JSONB_ARRAY: { - jsonAppendChar(pOut, '['); - j = i+n; - iEnd = j+sz; - while( jeErr==0 ){ - j = jsonTranslateBlobToText(pParse, j, pOut); - jsonAppendChar(pOut, ','); - } - if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; - if( sz>0 ) jsonStringTrimOneChar(pOut); - jsonAppendChar(pOut, ']'); - break; - } - case JSONB_OBJECT: { - int x = 0; - jsonAppendChar(pOut, '{'); - j = i+n; - iEnd = j+sz; - while( jeErr==0 ){ - j = jsonTranslateBlobToText(pParse, j, pOut); - jsonAppendChar(pOut, (x++ & 1) ? ',' : ':'); - } - if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; - if( sz>0 ) jsonStringTrimOneChar(pOut); - jsonAppendChar(pOut, '}'); - break; - } - - default: { - malformed_jsonb: - pOut->eErr |= JSTRING_MALFORMED; - break; - } - } - return i+n+sz; -} - -/* Context for recursion of json_pretty() -*/ -typedef struct JsonPretty JsonPretty; -struct JsonPretty { - JsonParse *pParse; /* The BLOB being rendered */ - JsonString *pOut; /* Generate pretty output into this string */ - const char *zIndent; /* Use this text for indentation */ - u32 szIndent; /* Bytes in zIndent[] */ - u32 nIndent; /* Current level of indentation */ -}; - -/* Append indentation to the pretty JSON under construction */ -static void jsonPrettyIndent(JsonPretty *pPretty){ - u32 jj; - for(jj=0; jjnIndent; jj++){ - jsonAppendRaw(pPretty->pOut, pPretty->zIndent, pPretty->szIndent); - } -} - -/* -** Translate the binary JSONB representation of JSON beginning at -** pParse->aBlob[i] into a JSON text string. Append the JSON -** text onto the end of pOut. Return the index in pParse->aBlob[] -** of the first byte past the end of the element that is translated. -** -** This is a variant of jsonTranslateBlobToText() that "pretty-prints" -** the output. Extra whitespace is inserted to make the JSON easier -** for humans to read. -** -** If an error is detected in the BLOB input, the pOut->eErr flag -** might get set to JSTRING_MALFORMED. But not all BLOB input errors -** are detected. So a malformed JSONB input might either result -** in an error, or in incorrect JSON. -** -** The pOut->eErr JSTRING_OOM flag is set on a OOM. -*/ -static u32 jsonTranslateBlobToPrettyText( - JsonPretty *pPretty, /* Pretty-printing context */ - u32 i /* Start rendering at this index */ -){ - u32 sz, n, j, iEnd; - const JsonParse *pParse = pPretty->pParse; - JsonString *pOut = pPretty->pOut; - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - pOut->eErr |= JSTRING_MALFORMED; - return pParse->nBlob+1; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_ARRAY: { - j = i+n; - iEnd = j+sz; - jsonAppendChar(pOut, '['); - if( jnIndent++; - while( pOut->eErr==0 ){ - jsonPrettyIndent(pPretty); - j = jsonTranslateBlobToPrettyText(pPretty, j); - if( j>=iEnd ) break; - jsonAppendRawNZ(pOut, ",\n", 2); - } - jsonAppendChar(pOut, '\n'); - pPretty->nIndent--; - jsonPrettyIndent(pPretty); - } - jsonAppendChar(pOut, ']'); - i = iEnd; - break; - } - case JSONB_OBJECT: { - j = i+n; - iEnd = j+sz; - jsonAppendChar(pOut, '{'); - if( jnIndent++; - while( pOut->eErr==0 ){ - jsonPrettyIndent(pPretty); - j = jsonTranslateBlobToText(pParse, j, pOut); - if( j>iEnd ){ - pOut->eErr |= JSTRING_MALFORMED; - break; - } - jsonAppendRawNZ(pOut, ": ", 2); - j = jsonTranslateBlobToPrettyText(pPretty, j); - if( j>=iEnd ) break; - jsonAppendRawNZ(pOut, ",\n", 2); - } - jsonAppendChar(pOut, '\n'); - pPretty->nIndent--; - jsonPrettyIndent(pPretty); - } - jsonAppendChar(pOut, '}'); - i = iEnd; - break; - } - default: { - i = jsonTranslateBlobToText(pParse, i, pOut); - break; - } - } - return i; -} - -/* -** Given that a JSONB_ARRAY object starts at offset i, return -** the number of entries in that array. -*/ -static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){ - u32 n, sz, i, iEnd; - u32 k = 0; - n = jsonbPayloadSize(pParse, iRoot, &sz); - iEnd = iRoot+n+sz; - for(i=iRoot+n; n>0 && idelta. -*/ -static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){ - u32 sz = 0; - u32 nBlob; - assert( pParse->delta!=0 ); - assert( pParse->nBlobAlloc >= pParse->nBlob ); - nBlob = pParse->nBlob; - pParse->nBlob = pParse->nBlobAlloc; - (void)jsonbPayloadSize(pParse, iRoot, &sz); - pParse->nBlob = nBlob; - sz += pParse->delta; - pParse->delta += jsonBlobChangePayloadSize(pParse, iRoot, sz); -} - -/* -** If the JSONB at aIns[0..nIns-1] can be expanded (by denormalizing the -** size field) by d bytes, then write the expansion into aOut[] and -** return true. In this way, an overwrite happens without changing the -** size of the JSONB, which reduces memcpy() operations and also make it -** faster and easier to update the B-Tree entry that contains the JSONB -** in the database. -** -** If the expansion of aIns[] by d bytes cannot be (easily) accomplished -** then return false. -** -** The d parameter is guaranteed to be between 1 and 8. -** -** This routine is an optimization. A correct answer is obtained if it -** always leaves the output unchanged and returns false. -*/ -static int jsonBlobOverwrite( - u8 *aOut, /* Overwrite here */ - const u8 *aIns, /* New content */ - u32 nIns, /* Bytes of new content */ - u32 d /* Need to expand new content by this much */ -){ - u32 szPayload; /* Bytes of payload */ - u32 i; /* New header size, after expansion & a loop counter */ - u8 szHdr; /* Size of header before expansion */ - - /* Lookup table for finding the upper 4 bits of the first byte of the - ** expanded aIns[], based on the size of the expanded aIns[] header: - ** - ** 2 3 4 5 6 7 8 9 */ - static const u8 aType[] = { 0xc0, 0xd0, 0, 0xe0, 0, 0, 0, 0xf0 }; - - if( (aIns[0]&0x0f)<=2 ) return 0; /* Cannot enlarge NULL, true, false */ - switch( aIns[0]>>4 ){ - default: { /* aIns[] header size 1 */ - if( ((1<=2 && i<=9 && aType[i-2]!=0 ); - aOut[0] = (aIns[0] & 0x0f) | aType[i-2]; - memcpy(&aOut[i], &aIns[szHdr], nIns-szHdr); - szPayload = nIns - szHdr; - while( 1/*edit-by-break*/ ){ - i--; - aOut[i] = szPayload & 0xff; - if( i==1 ) break; - szPayload >>= 8; - } - assert( (szPayload>>8)==0 ); - return 1; -} - -/* -** Modify the JSONB blob at pParse->aBlob by removing nDel bytes of -** content beginning at iDel, and replacing them with nIns bytes of -** content given by aIns. -** -** nDel may be zero, in which case no bytes are removed. But iDel is -** still important as new bytes will be insert beginning at iDel. -** -** aIns may be zero, in which case space is created to hold nIns bytes -** beginning at iDel, but that space is uninitialized. -** -** Set pParse->oom if an OOM occurs. -*/ -static void jsonBlobEdit( - JsonParse *pParse, /* The JSONB to be modified is in pParse->aBlob */ - u32 iDel, /* First byte to be removed */ - u32 nDel, /* Number of bytes to remove */ - const u8 *aIns, /* Content to insert */ - u32 nIns /* Bytes of content to insert */ -){ - i64 d = (i64)nIns - (i64)nDel; - if( d<0 && d>=(-8) && aIns!=0 - && jsonBlobOverwrite(&pParse->aBlob[iDel], aIns, nIns, (int)-d) - ){ - return; - } - if( d!=0 ){ - if( pParse->nBlob + d > pParse->nBlobAlloc ){ - jsonBlobExpand(pParse, pParse->nBlob+d); - if( pParse->oom ) return; - } - memmove(&pParse->aBlob[iDel+nIns], - &pParse->aBlob[iDel+nDel], - pParse->nBlob - (iDel+nDel)); - pParse->nBlob += d; - pParse->delta += d; - } - if( nIns && aIns ){ - memcpy(&pParse->aBlob[iDel], aIns, nIns); - } -} - -/* -** Return the number of escaped newlines to be ignored. -** An escaped newline is a one of the following byte sequences: -** -** 0x5c 0x0a -** 0x5c 0x0d -** 0x5c 0x0d 0x0a -** 0x5c 0xe2 0x80 0xa8 -** 0x5c 0xe2 0x80 0xa9 -*/ -static u32 jsonBytesToBypass(const char *z, u32 n){ - u32 i = 0; - while( i+10 ); - assert( z[0]=='\\' ); - if( n<2 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - switch( (u8)z[1] ){ - case 'u': { - u32 v, vlo; - if( n<6 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - v = jsonHexToInt4(&z[2]); - if( (v & 0xfc00)==0xd800 - && n>=12 - && z[6]=='\\' - && z[7]=='u' - && ((vlo = jsonHexToInt4(&z[8]))&0xfc00)==0xdc00 - ){ - *piOut = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000; - return 12; - }else{ - *piOut = v; - return 6; - } - } - case 'b': { *piOut = '\b'; return 2; } - case 'f': { *piOut = '\f'; return 2; } - case 'n': { *piOut = '\n'; return 2; } - case 'r': { *piOut = '\r'; return 2; } - case 't': { *piOut = '\t'; return 2; } - case 'v': { *piOut = '\v'; return 2; } - case '0': { - /* JSON5 requires that the \0 escape not be followed by a digit. - ** But SQLite did not enforce this restriction in versions 3.42.0 - ** through 3.49.2. That was a bug. But some applications might have - ** come to depend on that bug. Use the SQLITE_BUG_COMPATIBLE_20250510 - ** option to restore the old buggy behavior. */ -#ifdef SQLITE_BUG_COMPATIBLE_20250510 - /* Legacy bug-compatible behavior */ - *piOut = 0; -#else - /* Correct behavior */ - *piOut = (n>2 && sqlite3Isdigit(z[2])) ? JSON_INVALID_CHAR : 0; -#endif - return 2; - } - case '\'': - case '"': - case '/': - case '\\':{ *piOut = z[1]; return 2; } - case 'x': { - if( n<4 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - *piOut = (jsonHexToInt(z[2])<<4) | jsonHexToInt(z[3]); - return 4; - } - case 0xe2: - case '\r': - case '\n': { - u32 nSkip = jsonBytesToBypass(z, n); - if( nSkip==0 ){ - *piOut = JSON_INVALID_CHAR; - return n; - }else if( nSkip==n ){ - *piOut = 0; - return n; - }else if( z[nSkip]=='\\' ){ - return nSkip + jsonUnescapeOneChar(&z[nSkip], n-nSkip, piOut); - }else{ - int sz = sqlite3Utf8ReadLimited((u8*)&z[nSkip], n-nSkip, piOut); - return nSkip + sz; - } - } - default: { - *piOut = JSON_INVALID_CHAR; - return 2; - } - } -} - - -/* -** Compare two object labels. Return 1 if they are equal and -** 0 if they differ. -** -** In this version, we know that one or the other or both of the -** two comparands contains an escape sequence. -*/ -static SQLITE_NOINLINE int jsonLabelCompareEscaped( - const char *zLeft, /* The left label */ - u32 nLeft, /* Size of the left label in bytes */ - int rawLeft, /* True if zLeft contains no escapes */ - const char *zRight, /* The right label */ - u32 nRight, /* Size of the right label in bytes */ - int rawRight /* True if zRight is escape-free */ -){ - u32 cLeft, cRight; - assert( rawLeft==0 || rawRight==0 ); - while( 1 /*exit-by-return*/ ){ - if( nLeft==0 ){ - cLeft = 0; - }else if( rawLeft || zLeft[0]!='\\' ){ - cLeft = ((u8*)zLeft)[0]; - if( cLeft>=0xc0 ){ - int sz = sqlite3Utf8ReadLimited((u8*)zLeft, nLeft, &cLeft); - zLeft += sz; - nLeft -= sz; - }else{ - zLeft++; - nLeft--; - } - }else{ - u32 n = jsonUnescapeOneChar(zLeft, nLeft, &cLeft); - zLeft += n; - assert( n<=nLeft ); - nLeft -= n; - } - if( nRight==0 ){ - cRight = 0; - }else if( rawRight || zRight[0]!='\\' ){ - cRight = ((u8*)zRight)[0]; - if( cRight>=0xc0 ){ - int sz = sqlite3Utf8ReadLimited((u8*)zRight, nRight, &cRight); - zRight += sz; - nRight -= sz; - }else{ - zRight++; - nRight--; - } - }else{ - u32 n = jsonUnescapeOneChar(zRight, nRight, &cRight); - zRight += n; - assert( n<=nRight ); - nRight -= n; - } - if( cLeft!=cRight ) return 0; - if( cLeft==0 ) return 1; - } -} - -/* -** Compare two object labels. Return 1 if they are equal and -** 0 if they differ. Return -1 if an OOM occurs. -*/ -static int jsonLabelCompare( - const char *zLeft, /* The left label */ - u32 nLeft, /* Size of the left label in bytes */ - int rawLeft, /* True if zLeft contains no escapes */ - const char *zRight, /* The right label */ - u32 nRight, /* Size of the right label in bytes */ - int rawRight /* True if zRight is escape-free */ -){ - if( rawLeft && rawRight ){ - /* Simpliest case: Neither label contains escapes. A simple - ** memcmp() is sufficient. */ - if( nLeft!=nRight ) return 0; - return memcmp(zLeft, zRight, nLeft)==0; - }else{ - return jsonLabelCompareEscaped(zLeft, nLeft, rawLeft, - zRight, nRight, rawRight); - } -} - -/* -** Error returns from jsonLookupStep() -*/ -#define JSON_LOOKUP_ERROR 0xffffffff -#define JSON_LOOKUP_NOTFOUND 0xfffffffe -#define JSON_LOOKUP_PATHERROR 0xfffffffd -#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) - -/* Forward declaration */ -static u32 jsonLookupStep(JsonParse*,u32,const char*,u32); - - -/* This helper routine for jsonLookupStep() populates pIns with -** binary data that is to be inserted into pParse. -** -** In the common case, pIns just points to pParse->aIns and pParse->nIns. -** But if the zPath of the original edit operation includes path elements -** that go deeper, additional substructure must be created. -** -** For example: -** -** json_insert('{}', '$.a.b.c', 123); -** -** The search stops at '$.a' But additional substructure must be -** created for the ".b.c" part of the patch so that the final result -** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with -** the binary equivalent of {"b":{"c":123}} so that it can be inserted. -** -** The caller is responsible for resetting pIns when it has finished -** using the substructure. -*/ -static u32 jsonCreateEditSubstructure( - JsonParse *pParse, /* The original JSONB that is being edited */ - JsonParse *pIns, /* Populate this with the blob data to insert */ - const char *zTail /* Tail of the path that determins substructure */ -){ - static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT }; - int rc; - memset(pIns, 0, sizeof(*pIns)); - pIns->db = pParse->db; - if( zTail[0]==0 ){ - /* No substructure. Just insert what is given in pParse. */ - pIns->aBlob = pParse->aIns; - pIns->nBlob = pParse->nIns; - rc = 0; - }else{ - /* Construct the binary substructure */ - pIns->nBlob = 1; - pIns->aBlob = (u8*)&emptyObject[zTail[0]=='.']; - pIns->eEdit = pParse->eEdit; - pIns->nIns = pParse->nIns; - pIns->aIns = pParse->aIns; - rc = jsonLookupStep(pIns, 0, zTail, 0); - pParse->oom |= pIns->oom; - } - return rc; /* Error code only */ -} - -/* -** Search along zPath to find the Json element specified. Return an -** index into pParse->aBlob[] for the start of that element's value. -** -** If the value found by this routine is the value half of label/value pair -** within an object, then set pPath->iLabel to the start of the corresponding -** label, before returning. -** -** Return one of the JSON_LOOKUP error codes if problems are seen. -** -** This routine will also modify the blob. If pParse->eEdit is one of -** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be -** made to the selected value. If an edit is performed, then the return -** value does not necessarily point to the select element. If an edit -** is performed, the return value is only useful for detecting error -** conditions. -*/ -static u32 jsonLookupStep( - JsonParse *pParse, /* The JSON to search */ - u32 iRoot, /* Begin the search at this element of aBlob[] */ - const char *zPath, /* The path to search */ - u32 iLabel /* Label if iRoot is a value of in an object */ -){ - u32 i, j, k, nKey, sz, n, iEnd, rc; - const char *zKey; - u8 x; - - if( zPath[0]==0 ){ - if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){ - n = jsonbPayloadSize(pParse, iRoot, &sz); - sz += n; - if( pParse->eEdit==JEDIT_DEL ){ - if( iLabel>0 ){ - sz += iRoot - iLabel; - iRoot = iLabel; - } - jsonBlobEdit(pParse, iRoot, sz, 0, 0); - }else if( pParse->eEdit==JEDIT_INS ){ - /* Already exists, so json_insert() is a no-op */ - }else{ - /* json_set() or json_replace() */ - jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns); - } - } - pParse->iLabel = iLabel; - return iRoot; - } - if( zPath[0]=='.' ){ - int rawKey = 1; - x = pParse->aBlob[iRoot]; - zPath++; - if( zPath[0]=='"' ){ - zKey = zPath + 1; - for(i=1; zPath[i] && zPath[i]!='"'; i++){ - if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++; - } - nKey = i-1; - if( zPath[i] ){ - i++; - }else{ - return JSON_LOOKUP_PATHERROR; - } - testcase( nKey==0 ); - rawKey = memchr(zKey, '\\', nKey)==0; - }else{ - zKey = zPath; - for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} - nKey = i; - if( nKey==0 ){ - return JSON_LOOKUP_PATHERROR; - } - } - if( (x & 0x0f)!=JSONB_OBJECT ) return JSON_LOOKUP_NOTFOUND; - n = jsonbPayloadSize(pParse, iRoot, &sz); - j = iRoot + n; /* j is the index of a label */ - iEnd = j+sz; - while( jaBlob[j] & 0x0f; - if( xJSONB_TEXTRAW ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - k = j+n; /* k is the index of the label text */ - if( k+sz>=iEnd ) return JSON_LOOKUP_ERROR; - zLabel = (const char*)&pParse->aBlob[k]; - rawLabel = x==JSONB_TEXT || x==JSONB_TEXTRAW; - if( jsonLabelCompare(zKey, nKey, rawKey, zLabel, sz, rawLabel) ){ - u32 v = k+sz; /* v is the index of the value */ - if( ((pParse->aBlob[v])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, v, &sz); - if( n==0 || v+n+sz>iEnd ) return JSON_LOOKUP_ERROR; - assert( j>0 ); - rc = jsonLookupStep(pParse, v, &zPath[i], j); - if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - j = k+sz; - if( ((pParse->aBlob[j])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - j += n+sz; - } - if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( pParse->eEdit>=JEDIT_INS ){ - u32 nIns; /* Total bytes to insert (label+value) */ - JsonParse v; /* BLOB encoding of the value to be inserted */ - JsonParse ix; /* Header of the label to be inserted */ - testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_SET ); - memset(&ix, 0, sizeof(ix)); - ix.db = pParse->db; - jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0); - pParse->oom |= ix.oom; - rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]); - if( !JSON_LOOKUP_ISERROR(rc) - && jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob) - ){ - assert( !pParse->oom ); - nIns = ix.nBlob + nKey + v.nBlob; - jsonBlobEdit(pParse, j, 0, 0, nIns); - if( !pParse->oom ){ - assert( pParse->aBlob!=0 ); /* Because pParse->oom!=0 */ - assert( ix.aBlob!=0 ); /* Because pPasre->oom!=0 */ - memcpy(&pParse->aBlob[j], ix.aBlob, ix.nBlob); - k = j + ix.nBlob; - memcpy(&pParse->aBlob[k], zKey, nKey); - k += nKey; - memcpy(&pParse->aBlob[k], v.aBlob, v.nBlob); - if( ALWAYS(pParse->delta) ) jsonAfterEditSizeAdjust(pParse, iRoot); - } - } - jsonParseReset(&v); - jsonParseReset(&ix); - return rc; - } - }else if( zPath[0]=='[' ){ - x = pParse->aBlob[iRoot] & 0x0f; - if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND; - n = jsonbPayloadSize(pParse, iRoot, &sz); - k = 0; - i = 1; - while( sqlite3Isdigit(zPath[i]) ){ - k = k*10 + zPath[i] - '0'; - i++; - } - if( i<2 || zPath[i]!=']' ){ - if( zPath[1]=='#' ){ - k = jsonbArrayCount(pParse, iRoot); - i = 2; - if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ - unsigned int nn = 0; - i = 3; - do{ - nn = nn*10 + zPath[i] - '0'; - i++; - }while( sqlite3Isdigit(zPath[i]) ); - if( nn>k ) return JSON_LOOKUP_NOTFOUND; - k -= nn; - } - if( zPath[i]!=']' ){ - return JSON_LOOKUP_PATHERROR; - } - }else{ - return JSON_LOOKUP_PATHERROR; - } - } - j = iRoot+n; - iEnd = j+sz; - while( jdelta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - k--; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - j += n+sz; - } - if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( k>0 ) return JSON_LOOKUP_NOTFOUND; - if( pParse->eEdit>=JEDIT_INS ){ - JsonParse v; - testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_SET ); - rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]); - if( !JSON_LOOKUP_ISERROR(rc) - && jsonBlobMakeEditable(pParse, v.nBlob) - ){ - assert( !pParse->oom ); - jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob); - } - jsonParseReset(&v); - if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - }else{ - return JSON_LOOKUP_PATHERROR; - } - return JSON_LOOKUP_NOTFOUND; -} - -/* -** Convert a JSON BLOB into text and make that text the return value -** of an SQL function. -*/ -static void jsonReturnTextJsonFromBlob( - sqlite3_context *ctx, - const u8 *aBlob, - u32 nBlob -){ - JsonParse x; - JsonString s; - - if( NEVER(aBlob==0) ) return; - memset(&x, 0, sizeof(x)); - x.aBlob = (u8*)aBlob; - x.nBlob = nBlob; - jsonStringInit(&s, ctx); - jsonTranslateBlobToText(&x, 0, &s); - jsonReturnString(&s, 0, 0); -} - - -/* -** Return the value of the BLOB node at index i. -** -** If the value is a primitive, return it as an SQL value. -** If the value is an array or object, return it as either -** JSON text or the BLOB encoding, depending on the JSON_B flag -** on the userdata. -*/ -static void jsonReturnFromBlob( - JsonParse *pParse, /* Complete JSON parse tree */ - u32 i, /* Index of the node */ - sqlite3_context *pCtx, /* Return value for this function */ - int textOnly /* return text JSON. Disregard user-data */ -){ - u32 n, sz; - int rc; - sqlite3 *db = sqlite3_context_db_handle(pCtx); - - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - sqlite3_result_error(pCtx, "malformed JSON", -1); - return; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_NULL: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_null(pCtx); - break; - } - case JSONB_TRUE: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_int(pCtx, 1); - break; - } - case JSONB_FALSE: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_int(pCtx, 0); - break; - } - case JSONB_INT5: - case JSONB_INT: { - sqlite3_int64 iRes = 0; - char *z; - int bNeg = 0; - char x; - if( sz==0 ) goto returnfromblob_malformed; - x = (char)pParse->aBlob[i+n]; - if( x=='-' ){ - if( sz<2 ) goto returnfromblob_malformed; - n++; - sz--; - bNeg = 1; - } - z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); - if( z==0 ) goto returnfromblob_oom; - rc = sqlite3DecOrHexToI64(z, &iRes); - sqlite3DbFree(db, z); - if( rc==0 ){ - sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes); - }else if( rc==3 && bNeg ){ - sqlite3_result_int64(pCtx, SMALLEST_INT64); - }else if( rc==1 ){ - goto returnfromblob_malformed; - }else{ - if( bNeg ){ n--; sz++; } - goto to_double; - } - break; - } - case JSONB_FLOAT5: - case JSONB_FLOAT: { - double r; - char *z; - if( sz==0 ) goto returnfromblob_malformed; - to_double: - z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); - if( z==0 ) goto returnfromblob_oom; - rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); - sqlite3DbFree(db, z); - if( rc<=0 ) goto returnfromblob_malformed; - sqlite3_result_double(pCtx, r); - break; - } - case JSONB_TEXTRAW: - case JSONB_TEXT: { - sqlite3_result_text(pCtx, (char*)&pParse->aBlob[i+n], sz, - SQLITE_TRANSIENT); - break; - } - case JSONB_TEXT5: - case JSONB_TEXTJ: { - /* Translate JSON formatted string into raw text */ - u32 iIn, iOut; - const char *z; - char *zOut; - u32 nOut = sz; - z = (const char*)&pParse->aBlob[i+n]; - zOut = sqlite3DbMallocRaw(db, ((u64)nOut)+1); - if( zOut==0 ) goto returnfromblob_oom; - for(iIn=iOut=0; iIn=2 ); - zOut[iOut++] = (char)(0xc0 | (v>>6)); - zOut[iOut++] = 0x80 | (v&0x3f); - }else if( v<0x10000 ){ - assert( szEscape>=3 ); - zOut[iOut++] = 0xe0 | (v>>12); - zOut[iOut++] = 0x80 | ((v>>6)&0x3f); - zOut[iOut++] = 0x80 | (v&0x3f); - }else if( v==JSON_INVALID_CHAR ){ - /* Silently ignore illegal unicode */ - }else{ - assert( szEscape>=4 ); - zOut[iOut++] = 0xf0 | (v>>18); - zOut[iOut++] = 0x80 | ((v>>12)&0x3f); - zOut[iOut++] = 0x80 | ((v>>6)&0x3f); - zOut[iOut++] = 0x80 | (v&0x3f); - } - iIn += szEscape - 1; - }else{ - zOut[iOut++] = c; - } - } /* end for() */ - assert( iOut<=nOut ); - zOut[iOut] = 0; - sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC); - break; - } - case JSONB_ARRAY: - case JSONB_OBJECT: { - int flags = textOnly ? 0 : SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)); - if( flags & JSON_BLOB ){ - sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT); - }else{ - jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n); - } - break; - } - default: { - goto returnfromblob_malformed; - } - } - return; - -returnfromblob_oom: - sqlite3_result_error_nomem(pCtx); - return; - -returnfromblob_malformed: - sqlite3_result_error(pCtx, "malformed JSON", -1); - return; -} - -/* -** pArg is a function argument that might be an SQL value or a JSON -** value. Figure out what it is and encode it as a JSONB blob. -** Return the results in pParse. -** -** pParse is uninitialized upon entry. This routine will handle the -** initialization of pParse. The result will be contained in -** pParse->aBlob and pParse->nBlob. pParse->aBlob might be dynamically -** allocated (if pParse->nBlobAlloc is greater than zero) in which case -** the caller is responsible for freeing the space allocated to pParse->aBlob -** when it has finished with it. Or pParse->aBlob might be a static string -** or a value obtained from sqlite3_value_blob(pArg). -** -** If the argument is a BLOB that is clearly not a JSONB, then this -** function might set an error message in ctx and return non-zero. -** It might also set an error message and return non-zero on an OOM error. -*/ -static int jsonFunctionArgToBlob( - sqlite3_context *ctx, - sqlite3_value *pArg, - JsonParse *pParse -){ - int eType = sqlite3_value_type(pArg); - static u8 aNull[] = { 0x00 }; - memset(pParse, 0, sizeof(pParse[0])); - pParse->db = sqlite3_context_db_handle(ctx); - switch( eType ){ - default: { - pParse->aBlob = aNull; - pParse->nBlob = 1; - return 0; - } - case SQLITE_BLOB: { - if( !jsonArgIsJsonb(pArg, pParse) ){ - sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1); - return 1; - } - break; - } - case SQLITE_TEXT: { - const char *zJson = (const char*)sqlite3_value_text(pArg); - int nJson = sqlite3_value_bytes(pArg); - if( zJson==0 ) return 1; - if( sqlite3_value_subtype(pArg)==JSON_SUBTYPE ){ - pParse->zJson = (char*)zJson; - pParse->nJson = nJson; - if( jsonConvertTextToBlob(pParse, ctx) ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - sqlite3DbFree(pParse->db, pParse->aBlob); - memset(pParse, 0, sizeof(pParse[0])); - return 1; - } - }else{ - jsonBlobAppendNode(pParse, JSONB_TEXTRAW, nJson, zJson); - } - break; - } - case SQLITE_FLOAT: { - double r = sqlite3_value_double(pArg); - if( NEVER(sqlite3IsNaN(r)) ){ - jsonBlobAppendNode(pParse, JSONB_NULL, 0, 0); - }else{ - int n = sqlite3_value_bytes(pArg); - const char *z = (const char*)sqlite3_value_text(pArg); - if( z==0 ) return 1; - if( z[0]=='I' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); - }else if( z[0]=='-' && z[1]=='I' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); - }else{ - jsonBlobAppendNode(pParse, JSONB_FLOAT, n, z); - } - } - break; - } - case SQLITE_INTEGER: { - int n = sqlite3_value_bytes(pArg); - const char *z = (const char*)sqlite3_value_text(pArg); - if( z==0 ) return 1; - jsonBlobAppendNode(pParse, JSONB_INT, n, z); - break; - } - } - if( pParse->oom ){ - sqlite3_result_error_nomem(ctx); - return 1; - }else{ - return 0; - } -} - -/* -** Generate a bad path error. -** -** If ctx is not NULL then push the error message into ctx and return NULL. -** If ctx is NULL, then return the text of the error message. -*/ -static char *jsonBadPathError( - sqlite3_context *ctx, /* The function call containing the error */ - const char *zPath /* The path with the problem */ -){ - char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); - if( ctx==0 ) return zMsg; - if( zMsg ){ - sqlite3_result_error(ctx, zMsg, -1); - sqlite3_free(zMsg); - }else{ - sqlite3_result_error_nomem(ctx); - } - return 0; -} - -/* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent -** arguments come in pairs where each pair contains a JSON path and -** content to insert or set at that patch. Do the updates -** and return the result. -** -** The specific operation is determined by eEdit, which can be one -** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET. -*/ -static void jsonInsertIntoBlob( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv, - int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */ -){ - int i; - u32 rc = 0; - const char *zPath = 0; - int flgs; - JsonParse *p; - JsonParse ax; - - assert( (argc&1)==1 ); - flgs = argc==1 ? 0 : JSON_EDITABLE; - p = jsonParseFuncArg(ctx, argv[0], flgs); - if( p==0 ) return; - for(i=1; inBlob, ax.aBlob, ax.nBlob); - } - rc = 0; - }else{ - p->eEdit = eEdit; - p->nIns = ax.nBlob; - p->aIns = ax.aBlob; - p->delta = 0; - rc = jsonLookupStep(p, 0, zPath+1, 0); - } - jsonParseReset(&ax); - if( rc==JSON_LOOKUP_NOTFOUND ) continue; - if( JSON_LOOKUP_ISERROR(rc) ) goto jsonInsertIntoBlob_patherror; - } - jsonReturnParse(ctx, p); - jsonParseFree(p); - return; - -jsonInsertIntoBlob_patherror: - jsonParseFree(p); - if( rc==JSON_LOOKUP_ERROR ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - }else{ - jsonBadPathError(ctx, zPath); - } - return; -} - -/* -** If pArg is a blob that seems like a JSONB blob, then initialize -** p to point to that JSONB and return TRUE. If pArg does not seem like -** a JSONB blob, then return FALSE. -** -** For small BLOBs (having no more than 7 bytes of payload) a full -** validity check is done. So for small BLOBs this routine only returns -** true if the value is guaranteed to be a valid JSONB. For larger BLOBs -** (8 byte or more of payload) only the size of the outermost element is -** checked to verify that the BLOB is superficially valid JSONB. -** -** A full JSONB validation is done on smaller BLOBs because those BLOBs might -** also be text JSON that has been incorrectly cast into a BLOB. -** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5) -** If the BLOB is 9 bytes are larger, then it is not possible for the -** superficial size check done here to pass if the input is really text -** JSON so we do not need to look deeper in that case. -** -** Why we only need to do full JSONB validation for smaller BLOBs: -** -** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n', -** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset -** can also be the first byte of JSONB: '{', '[', and digits '3' -** through '9'. In every one of those cases, the payload size is 7 bytes -** or less. So if we do full JSONB validation for every BLOB where the -** payload is less than 7 bytes, we will never get a false positive for -** JSONB on an input that is really text JSON. -*/ -static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){ - u32 n, sz = 0; - u8 c; - if( sqlite3_value_type(pArg)!=SQLITE_BLOB ) return 0; - p->aBlob = (u8*)sqlite3_value_blob(pArg); - p->nBlob = (u32)sqlite3_value_bytes(pArg); - if( p->nBlob>0 - && ALWAYS(p->aBlob!=0) - && ((c = p->aBlob[0]) & 0x0f)<=JSONB_OBJECT - && (n = jsonbPayloadSize(p, 0, &sz))>0 - && sz+n==p->nBlob - && ((c & 0x0f)>JSONB_FALSE || sz==0) - && (sz>7 - || (c!=0x7b && c!=0x5b && !sqlite3Isdigit(c)) - || jsonbValidityCheck(p, 0, p->nBlob, 1)==0) - ){ - return 1; - } - p->aBlob = 0; - p->nBlob = 0; - return 0; -} - -/* -** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob, -** from the SQL function argument pArg. Return a pointer to the new -** JsonParse object. -** -** Ownership of the new JsonParse object is passed to the caller. The -** caller should invoke jsonParseFree() on the return value when it -** has finished using it. -** -** If any errors are detected, an appropriate error messages is set -** using sqlite3_result_error() or the equivalent and this routine -** returns NULL. This routine also returns NULL if the pArg argument -** is an SQL NULL value, but no error message is set in that case. This -** is so that SQL functions that are given NULL arguments will return -** a NULL value. -*/ -static JsonParse *jsonParseFuncArg( - sqlite3_context *ctx, - sqlite3_value *pArg, - u32 flgs -){ - int eType; /* Datatype of pArg */ - JsonParse *p = 0; /* Value to be returned */ - JsonParse *pFromCache = 0; /* Value taken from cache */ - sqlite3 *db; /* The database connection */ - - assert( ctx!=0 ); - eType = sqlite3_value_type(pArg); - if( eType==SQLITE_NULL ){ - return 0; - } - pFromCache = jsonCacheSearch(ctx, pArg); - if( pFromCache ){ - pFromCache->nJPRef++; - if( (flgs & JSON_EDITABLE)==0 ){ - return pFromCache; - } - } - db = sqlite3_context_db_handle(ctx); -rebuild_from_cache: - p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p==0 ) goto json_pfa_oom; - memset(p, 0, sizeof(*p)); - p->db = db; - p->nJPRef = 1; - if( pFromCache!=0 ){ - u32 nBlob = pFromCache->nBlob; - p->aBlob = sqlite3DbMallocRaw(db, nBlob); - if( p->aBlob==0 ) goto json_pfa_oom; - memcpy(p->aBlob, pFromCache->aBlob, nBlob); - p->nBlobAlloc = p->nBlob = nBlob; - p->hasNonstd = pFromCache->hasNonstd; - jsonParseFree(pFromCache); - return p; - } - if( eType==SQLITE_BLOB ){ - if( jsonArgIsJsonb(pArg,p) ){ - if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){ - goto json_pfa_oom; - } - return p; - } - /* If the blob is not valid JSONB, fall through into trying to cast - ** the blob into text which is then interpreted as JSON. (tag-20240123-a) - ** - ** This goes against all historical documentation about how the SQLite - ** JSON functions were suppose to work. From the beginning, blob was - ** reserved for expansion and a blob value should have raised an error. - ** But it did not, due to a bug. And many applications came to depend - ** upon this buggy behavior, especially when using the CLI and reading - ** JSON text using readfile(), which returns a blob. For this reason - ** we will continue to support the bug moving forward. - ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d - */ - } - p->zJson = (char*)sqlite3_value_text(pArg); - p->nJson = sqlite3_value_bytes(pArg); - if( db->mallocFailed ) goto json_pfa_oom; - if( p->nJson==0 ) goto json_pfa_malformed; - assert( p->zJson!=0 ); - if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){ - if( flgs & JSON_KEEPERROR ){ - p->nErr = 1; - return p; - }else{ - jsonParseFree(p); - return 0; - } - }else{ - int isRCStr = sqlite3ValueIsOfClass(pArg, sqlite3RCStrUnref); - int rc; - if( !isRCStr ){ - char *zNew = sqlite3RCStrNew( p->nJson ); - if( zNew==0 ) goto json_pfa_oom; - memcpy(zNew, p->zJson, p->nJson); - p->zJson = zNew; - p->zJson[p->nJson] = 0; - }else{ - sqlite3RCStrRef(p->zJson); - } - p->bJsonIsRCStr = 1; - rc = jsonCacheInsert(ctx, p); - if( rc==SQLITE_NOMEM ) goto json_pfa_oom; - if( flgs & JSON_EDITABLE ){ - pFromCache = p; - p = 0; - goto rebuild_from_cache; - } - } - return p; - -json_pfa_malformed: - if( flgs & JSON_KEEPERROR ){ - p->nErr = 1; - return p; - }else{ - jsonParseFree(p); - sqlite3_result_error(ctx, "malformed JSON", -1); - return 0; - } - -json_pfa_oom: - jsonParseFree(pFromCache); - jsonParseFree(p); - sqlite3_result_error_nomem(ctx); - return 0; -} - -/* -** Make the return value of a JSON function either the raw JSONB blob -** or make it JSON text, depending on whether the JSON_BLOB flag is -** set on the function. -*/ -static void jsonReturnParse( - sqlite3_context *ctx, - JsonParse *p -){ - int flgs; - if( p->oom ){ - sqlite3_result_error_nomem(ctx); - return; - } - flgs = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( flgs & JSON_BLOB ){ - if( p->nBlobAlloc>0 && !p->bReadOnly ){ - sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_DYNAMIC); - p->nBlobAlloc = 0; - }else{ - sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_TRANSIENT); - } - }else{ - JsonString s; - jsonStringInit(&s, ctx); - p->delta = 0; - jsonTranslateBlobToText(p, 0, &s); - jsonReturnString(&s, p, ctx); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } -} - -/**************************************************************************** -** SQL functions used for testing and debugging -****************************************************************************/ - -#if SQLITE_DEBUG -/* -** Decode JSONB bytes in aBlob[] starting at iStart through but not -** including iEnd. Indent the -** content by nIndent spaces. -*/ -static void jsonDebugPrintBlob( - JsonParse *pParse, /* JSON content */ - u32 iStart, /* Start rendering here */ - u32 iEnd, /* Do not render this byte or any byte after this one */ - int nIndent, /* Indent by this many spaces */ - sqlite3_str *pOut /* Generate output into this sqlite3_str object */ -){ - while( iStartaBlob[iStart] & 0x0f; - u32 savedNBlob = pParse->nBlob; - sqlite3_str_appendf(pOut, "%5d:%*s", iStart, nIndent, ""); - if( pParse->nBlobAlloc>pParse->nBlob ){ - pParse->nBlob = pParse->nBlobAlloc; - } - nn = n = jsonbPayloadSize(pParse, iStart, &sz); - if( nn==0 ) nn = 1; - if( sz>0 && xaBlob[iStart+i]); - } - if( n==0 ){ - sqlite3_str_appendf(pOut, " ERROR invalid node size\n"); - iStart = n==0 ? iStart+1 : iEnd; - continue; - } - pParse->nBlob = savedNBlob; - if( iStart+n+sz>iEnd ){ - iEnd = iStart+n+sz; - if( iEnd>pParse->nBlob ){ - if( pParse->nBlobAlloc>0 && iEnd>pParse->nBlobAlloc ){ - iEnd = pParse->nBlobAlloc; - }else{ - iEnd = pParse->nBlob; - } - } - } - sqlite3_str_appendall(pOut," <-- "); - switch( x ){ - case JSONB_NULL: sqlite3_str_appendall(pOut,"null"); break; - case JSONB_TRUE: sqlite3_str_appendall(pOut,"true"); break; - case JSONB_FALSE: sqlite3_str_appendall(pOut,"false"); break; - case JSONB_INT: sqlite3_str_appendall(pOut,"int"); break; - case JSONB_INT5: sqlite3_str_appendall(pOut,"int5"); break; - case JSONB_FLOAT: sqlite3_str_appendall(pOut,"float"); break; - case JSONB_FLOAT5: sqlite3_str_appendall(pOut,"float5"); break; - case JSONB_TEXT: sqlite3_str_appendall(pOut,"text"); break; - case JSONB_TEXTJ: sqlite3_str_appendall(pOut,"textj"); break; - case JSONB_TEXT5: sqlite3_str_appendall(pOut,"text5"); break; - case JSONB_TEXTRAW: sqlite3_str_appendall(pOut,"textraw"); break; - case JSONB_ARRAY: { - sqlite3_str_appendf(pOut,"array, %u bytes\n", sz); - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); - showContent = 0; - break; - } - case JSONB_OBJECT: { - sqlite3_str_appendf(pOut, "object, %u bytes\n", sz); - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); - showContent = 0; - break; - } - default: { - sqlite3_str_appendall(pOut, "ERROR: unknown node type\n"); - showContent = 0; - break; - } - } - if( showContent ){ - if( sz==0 && x<=JSONB_FALSE ){ - sqlite3_str_append(pOut, "\n", 1); - }else{ - u32 j; - sqlite3_str_appendall(pOut, ": \""); - for(j=iStart+n; jaBlob[j]; - if( c<0x20 || c>=0x7f ) c = '.'; - sqlite3_str_append(pOut, (char*)&c, 1); - } - sqlite3_str_append(pOut, "\"\n", 2); - } - } - iStart += n + sz; - } -} -static void jsonShowParse(JsonParse *pParse){ - sqlite3_str out; - char zBuf[1000]; - if( pParse==0 ){ - printf("NULL pointer\n"); - return; - }else{ - printf("nBlobAlloc = %u\n", pParse->nBlobAlloc); - printf("nBlob = %u\n", pParse->nBlob); - printf("delta = %d\n", pParse->delta); - if( pParse->nBlob==0 ) return; - printf("content (bytes 0..%u):\n", pParse->nBlob-1); - } - sqlite3StrAccumInit(&out, 0, zBuf, sizeof(zBuf), 1000000); - jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0, &out); - printf("%s", sqlite3_str_value(&out)); - sqlite3_str_reset(&out); -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -** SQL function: json_parse(JSON) -** -** Parse JSON using jsonParseFuncArg(). Return text that is a -** human-readable dump of the binary JSONB for the input parameter. -*/ -static void jsonParseFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - sqlite3_str out; - - assert( argc>=1 ); - sqlite3StrAccumInit(&out, 0, 0, 0, 1000000); - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - if( argc==1 ){ - jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out); - sqlite3_result_text64(ctx,out.zText,out.nChar,SQLITE_TRANSIENT,SQLITE_UTF8); - }else{ - jsonShowParse(p); - } - jsonParseFree(p); - sqlite3_str_reset(&out); -} -#endif /* SQLITE_DEBUG */ - -/**************************************************************************** -** Scalar SQL function implementations -****************************************************************************/ - -/* -** Implementation of the json_quote(VALUE) function. Return a JSON value -** corresponding to the SQL value input. Mostly this means putting -** double-quotes around strings and returning the unquoted string "null" -** when given a NULL input. -*/ -static void jsonQuoteFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString jx; - UNUSED_PARAMETER(argc); - - jsonStringInit(&jx, ctx); - jsonAppendSqlValue(&jx, argv[0]); - jsonReturnString(&jx, 0, 0); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} - -/* -** Implementation of the json_array(VALUE,...) function. Return a JSON -** array that contains all values given in arguments. Or if any argument -** is a BLOB, throw an error. -*/ -static void jsonArrayFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - int i; - JsonString jx; - - jsonStringInit(&jx, ctx); - jsonAppendChar(&jx, '['); - for(i=0; iaBlob[i] & 0x0f)==JSONB_ARRAY ){ - cnt = jsonbArrayCount(p, i); - } - if( !eErr ) sqlite3_result_int64(ctx, cnt); - jsonParseFree(p); -} - -/* True if the string is all alphanumerics and underscores */ -static int jsonAllAlphanum(const char *z, int n){ - int i; - for(i=0; i"(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. -** -** Abbreviated JSON path expressions are allows if JSON_ABPATH, for -** compatibility with PG. -*/ -static void jsonExtractFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p = 0; /* The parse */ - int flags; /* Flags associated with the function */ - int i; /* Loop counter */ - JsonString jx; /* String for array result */ - - if( argc<2 ) return; - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - jsonStringInit(&jx, ctx); - if( argc>2 ){ - jsonAppendChar(&jx, '['); - } - for(i=1; i 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 - ** - ** Updated 2024-05-27: If the NUMBER is negative, then PG counts from - ** the right of the array. Hence for negative NUMBER: - ** - ** NUMBER ==> $[#NUMBER] // PG compatible - */ - jsonStringInit(&jx, ctx); - if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){ - jsonAppendRawNZ(&jx, "[", 1); - if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1); - jsonAppendRaw(&jx, zPath, nPath); - jsonAppendRawNZ(&jx, "]", 2); - }else if( jsonAllAlphanum(zPath, nPath) ){ - jsonAppendRawNZ(&jx, ".", 1); - jsonAppendRaw(&jx, zPath, nPath); - }else if( zPath[0]=='[' && nPath>=3 && zPath[nPath-1]==']' ){ - jsonAppendRaw(&jx, zPath, nPath); - }else{ - jsonAppendRawNZ(&jx, ".\"", 2); - jsonAppendRaw(&jx, zPath, nPath); - jsonAppendRawNZ(&jx, "\"", 1); - } - jsonStringTerminate(&jx); - j = jsonLookupStep(p, 0, jx.zBuf, 0); - jsonStringReset(&jx); - }else{ - jsonBadPathError(ctx, zPath); - goto json_extract_error; - } - if( jnBlob ){ - if( argc==2 ){ - if( flags & JSON_JSON ){ - jsonStringInit(&jx, ctx); - jsonTranslateBlobToText(p, j, &jx); - jsonReturnString(&jx, 0, 0); - jsonStringReset(&jx); - assert( (flags & JSON_BLOB)==0 ); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - }else{ - jsonReturnFromBlob(p, j, ctx, 0); - if( (flags & (JSON_SQL|JSON_BLOB))==0 - && (p->aBlob[j]&0x0f)>=JSONB_ARRAY - ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - } - }else{ - jsonAppendSeparator(&jx); - jsonTranslateBlobToText(p, j, &jx); - } - }else if( j==JSON_LOOKUP_NOTFOUND ){ - if( argc==2 ){ - goto json_extract_error; /* Return NULL if not found */ - }else{ - jsonAppendSeparator(&jx); - jsonAppendRawNZ(&jx, "null", 4); - } - }else if( j==JSON_LOOKUP_ERROR ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - goto json_extract_error; - }else{ - jsonBadPathError(ctx, zPath); - goto json_extract_error; - } - } - if( argc>2 ){ - jsonAppendChar(&jx, ']'); - jsonReturnString(&jx, 0, 0); - if( (flags & JSON_BLOB)==0 ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - } -json_extract_error: - jsonStringReset(&jx); - jsonParseFree(p); - return; -} - -/* -** Return codes for jsonMergePatch() -*/ -#define JSON_MERGE_OK 0 /* Success */ -#define JSON_MERGE_BADTARGET 1 /* Malformed TARGET blob */ -#define JSON_MERGE_BADPATCH 2 /* Malformed PATCH blob */ -#define JSON_MERGE_OOM 3 /* Out-of-memory condition */ - -/* -** RFC-7396 MergePatch for two JSONB blobs. -** -** pTarget is the target. pPatch is the patch. The target is updated -** in place. The patch is read-only. -** -** The original RFC-7396 algorithm is this: -** -** define MergePatch(Target, Patch): -** if Patch is an Object: -** if Target is not an Object: -** Target = {} # Ignore the contents and set it to an empty Object -** for each Name/Value pair in Patch: -** if Value is null: -** if Name exists in Target: -** remove the Name/Value pair from Target -** else: -** Target[Name] = MergePatch(Target[Name], Value) -** return Target -** else: -** return Patch -** -** Here is an equivalent algorithm restructured to show the actual -** implementation: -** -** 01 define MergePatch(Target, Patch): -** 02 if Patch is not an Object: -** 03 return Patch -** 04 else: // if Patch is an Object -** 05 if Target is not an Object: -** 06 Target = {} -** 07 for each Name/Value pair in Patch: -** 08 if Name exists in Target: -** 09 if Value is null: -** 10 remove the Name/Value pair from Target -** 11 else -** 12 Target[name] = MergePatch(Target[Name], Value) -** 13 else if Value is not NULL: -** 14 if Value is not an Object: -** 15 Target[name] = Value -** 16 else: -** 17 Target[name] = MergePatch('{}',value) -** 18 return Target -** | -** ^---- Line numbers referenced in comments in the implementation -*/ -static int jsonMergePatch( - JsonParse *pTarget, /* The JSON parser that contains the TARGET */ - u32 iTarget, /* Index of TARGET in pTarget->aBlob[] */ - const JsonParse *pPatch, /* The PATCH */ - u32 iPatch /* Index of PATCH in pPatch->aBlob[] */ -){ - u8 x; /* Type of a single node */ - u32 n, sz=0; /* Return values from jsonbPayloadSize() */ - u32 iTCursor; /* Cursor position while scanning the target object */ - u32 iTStart; /* First label in the target object */ - u32 iTEndBE; /* Original first byte past end of target, before edit */ - u32 iTEnd; /* Current first byte past end of target */ - u8 eTLabel; /* Node type of the target label */ - u32 iTLabel = 0; /* Index of the label */ - u32 nTLabel = 0; /* Header size in bytes for the target label */ - u32 szTLabel = 0; /* Size of the target label payload */ - u32 iTValue = 0; /* Index of the target value */ - u32 nTValue = 0; /* Header size of the target value */ - u32 szTValue = 0; /* Payload size for the target value */ - - u32 iPCursor; /* Cursor position while scanning the patch */ - u32 iPEnd; /* First byte past the end of the patch */ - u8 ePLabel; /* Node type of the patch label */ - u32 iPLabel; /* Start of patch label */ - u32 nPLabel; /* Size of header on the patch label */ - u32 szPLabel; /* Payload size of the patch label */ - u32 iPValue; /* Start of patch value */ - u32 nPValue; /* Header size for the patch value */ - u32 szPValue; /* Payload size of the patch value */ - - assert( iTarget>=0 && iTargetnBlob ); - assert( iPatch>=0 && iPatchnBlob ); - x = pPatch->aBlob[iPatch] & 0x0f; - if( x!=JSONB_OBJECT ){ /* Algorithm line 02 */ - u32 szPatch; /* Total size of the patch, header+payload */ - u32 szTarget; /* Total size of the target, header+payload */ - n = jsonbPayloadSize(pPatch, iPatch, &sz); - szPatch = n+sz; - sz = 0; - n = jsonbPayloadSize(pTarget, iTarget, &sz); - szTarget = n+sz; - jsonBlobEdit(pTarget, iTarget, szTarget, pPatch->aBlob+iPatch, szPatch); - return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; /* Line 03 */ - } - x = pTarget->aBlob[iTarget] & 0x0f; - if( x!=JSONB_OBJECT ){ /* Algorithm line 05 */ - n = jsonbPayloadSize(pTarget, iTarget, &sz); - jsonBlobEdit(pTarget, iTarget+n, sz, 0, 0); - x = pTarget->aBlob[iTarget]; - pTarget->aBlob[iTarget] = (x & 0xf0) | JSONB_OBJECT; - } - n = jsonbPayloadSize(pPatch, iPatch, &sz); - if( NEVER(n==0) ) return JSON_MERGE_BADPATCH; - iPCursor = iPatch+n; - iPEnd = iPCursor+sz; - n = jsonbPayloadSize(pTarget, iTarget, &sz); - if( NEVER(n==0) ) return JSON_MERGE_BADTARGET; - iTStart = iTarget+n; - iTEndBE = iTStart+sz; - - while( iPCursoraBlob[iPCursor] & 0x0f; - if( ePLabelJSONB_TEXTRAW ){ - return JSON_MERGE_BADPATCH; - } - nPLabel = jsonbPayloadSize(pPatch, iPCursor, &szPLabel); - if( nPLabel==0 ) return JSON_MERGE_BADPATCH; - iPValue = iPCursor + nPLabel + szPLabel; - if( iPValue>=iPEnd ) return JSON_MERGE_BADPATCH; - nPValue = jsonbPayloadSize(pPatch, iPValue, &szPValue); - if( nPValue==0 ) return JSON_MERGE_BADPATCH; - iPCursor = iPValue + nPValue + szPValue; - if( iPCursor>iPEnd ) return JSON_MERGE_BADPATCH; - - iTCursor = iTStart; - iTEnd = iTEndBE + pTarget->delta; - while( iTCursoraBlob[iTCursor] & 0x0f; - if( eTLabelJSONB_TEXTRAW ){ - return JSON_MERGE_BADTARGET; - } - nTLabel = jsonbPayloadSize(pTarget, iTCursor, &szTLabel); - if( nTLabel==0 ) return JSON_MERGE_BADTARGET; - iTValue = iTLabel + nTLabel + szTLabel; - if( iTValue>=iTEnd ) return JSON_MERGE_BADTARGET; - nTValue = jsonbPayloadSize(pTarget, iTValue, &szTValue); - if( nTValue==0 ) return JSON_MERGE_BADTARGET; - if( iTValue + nTValue + szTValue > iTEnd ) return JSON_MERGE_BADTARGET; - isEqual = jsonLabelCompare( - (const char*)&pPatch->aBlob[iPLabel+nPLabel], - szPLabel, - (ePLabel==JSONB_TEXT || ePLabel==JSONB_TEXTRAW), - (const char*)&pTarget->aBlob[iTLabel+nTLabel], - szTLabel, - (eTLabel==JSONB_TEXT || eTLabel==JSONB_TEXTRAW)); - if( isEqual ) break; - iTCursor = iTValue + nTValue + szTValue; - } - x = pPatch->aBlob[iPValue] & 0x0f; - if( iTCursoroom) ) return JSON_MERGE_OOM; - }else{ - /* Algorithm line 12 */ - int rc, savedDelta = pTarget->delta; - pTarget->delta = 0; - rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue); - if( rc ) return rc; - pTarget->delta += savedDelta; - } - }else if( x>0 ){ /* Algorithm line 13 */ - /* No match and patch value is not NULL */ - u32 szNew = szPLabel+nPLabel; - if( (pPatch->aBlob[iPValue] & 0x0f)!=JSONB_OBJECT ){ /* Line 14 */ - jsonBlobEdit(pTarget, iTEnd, 0, 0, szPValue+nPValue+szNew); - if( pTarget->oom ) return JSON_MERGE_OOM; - memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); - memcpy(&pTarget->aBlob[iTEnd+szNew], - &pPatch->aBlob[iPValue], szPValue+nPValue); - }else{ - int rc, savedDelta; - jsonBlobEdit(pTarget, iTEnd, 0, 0, szNew+1); - if( pTarget->oom ) return JSON_MERGE_OOM; - memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); - pTarget->aBlob[iTEnd+szNew] = 0x00; - savedDelta = pTarget->delta; - pTarget->delta = 0; - rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue); - if( rc ) return rc; - pTarget->delta += savedDelta; - } - } - } - if( pTarget->delta ) jsonAfterEditSizeAdjust(pTarget, iTarget); - return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; -} - - -/* -** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON -** object that is the result of running the RFC 7396 MergePatch() algorithm -** on the two arguments. -*/ -static void jsonPatchFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *pTarget; /* The TARGET */ - JsonParse *pPatch; /* The PATCH */ - int rc; /* Result code */ - - UNUSED_PARAMETER(argc); - assert( argc==2 ); - pTarget = jsonParseFuncArg(ctx, argv[0], JSON_EDITABLE); - if( pTarget==0 ) return; - pPatch = jsonParseFuncArg(ctx, argv[1], 0); - if( pPatch ){ - rc = jsonMergePatch(pTarget, 0, pPatch, 0); - if( rc==JSON_MERGE_OK ){ - jsonReturnParse(ctx, pTarget); - }else if( rc==JSON_MERGE_OOM ){ - sqlite3_result_error_nomem(ctx); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - jsonParseFree(pPatch); - } - jsonParseFree(pTarget); -} - - -/* -** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON -** object that contains all name/value given in arguments. Or if any name -** is not a string or if any value is a BLOB, throw an error. -*/ -static void jsonObjectFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - int i; - JsonString jx; - const char *z; - u32 n; - - if( argc&1 ){ - sqlite3_result_error(ctx, "json_object() requires an even number " - "of arguments", -1); - return; - } - jsonStringInit(&jx, ctx); - jsonAppendChar(&jx, '{'); - for(i=0; i1 ? JSON_EDITABLE : 0); - if( p==0 ) return; - for(i=1; ieEdit = JEDIT_DEL; - p->delta = 0; - rc = jsonLookupStep(p, 0, zPath+1, 0); - if( JSON_LOOKUP_ISERROR(rc) ){ - if( rc==JSON_LOOKUP_NOTFOUND ){ - continue; /* No-op */ - }else if( rc==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - goto json_remove_done; - } - } - jsonReturnParse(ctx, p); - jsonParseFree(p); - return; - -json_remove_patherror: - jsonBadPathError(ctx, zPath); - -json_remove_done: - jsonParseFree(p); - return; -} - -/* -** json_replace(JSON, PATH, VALUE, ...) -** -** Replace the value at PATH with VALUE. If PATH does not already exist, -** this routine is a no-op. If JSON or PATH is malformed, throw an error. -*/ -static void jsonReplaceFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - if( argc<1 ) return; - if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, "replace"); - return; - } - jsonInsertIntoBlob(ctx, argc, argv, JEDIT_REPL); -} - - -/* -** json_set(JSON, PATH, VALUE, ...) -** -** Set the value at PATH to VALUE. Create the PATH if it does not already -** exist. Overwrite existing values that do exist. -** If JSON or PATH is malformed, throw an error. -** -** json_insert(JSON, PATH, VALUE, ...) -** -** Create PATH and initialize it to VALUE. If PATH already exists, this -** routine is a no-op. If JSON or PATH is malformed, throw an error. -*/ -static void jsonSetFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - int bIsSet = (flags&JSON_ISSET)!=0; - - if( argc<1 ) return; - if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); - return; - } - jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS); -} - -/* -** json_type(JSON) -** json_type(JSON, PATH) -** -** 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( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - const char *zPath = 0; - u32 i; - - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - if( argc==2 ){ - zPath = (const char*)sqlite3_value_text(argv[1]); - if( zPath==0 ) goto json_type_done; - if( zPath[0]!='$' ){ - jsonBadPathError(ctx, zPath); - goto json_type_done; - } - i = jsonLookupStep(p, 0, zPath+1, 0); - if( JSON_LOOKUP_ISERROR(i) ){ - if( i==JSON_LOOKUP_NOTFOUND ){ - /* no-op */ - }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - goto json_type_done; - } - }else{ - i = 0; - } - sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC); -json_type_done: - jsonParseFree(p); -} - -/* -** json_pretty(JSON) -** json_pretty(JSON, INDENT) -** -** Return text that is a pretty-printed rendering of the input JSON. -** If the argument is not valid JSON, return NULL. -** -** The INDENT argument is text that is used for indentation. If omitted, -** it defaults to four spaces (the same as PostgreSQL). -*/ -static void jsonPrettyFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString s; /* The output string */ - JsonPretty x; /* Pretty printing context */ - - memset(&x, 0, sizeof(x)); - x.pParse = jsonParseFuncArg(ctx, argv[0], 0); - if( x.pParse==0 ) return; - x.pOut = &s; - jsonStringInit(&s, ctx); - if( argc==1 || (x.zIndent = (const char*)sqlite3_value_text(argv[1]))==0 ){ - x.zIndent = " "; - x.szIndent = 4; - }else{ - x.szIndent = (u32)strlen(x.zIndent); - } - jsonTranslateBlobToPrettyText(&x, 0); - jsonReturnString(&s, 0, 0); - jsonParseFree(x.pParse); -} - -/* -** json_valid(JSON) -** json_valid(JSON, FLAGS) -** -** Check the JSON argument to see if it is well-formed. The FLAGS argument -** encodes the various constraints on what is meant by "well-formed": -** -** 0x01 Canonical RFC-8259 JSON text -** 0x02 JSON text with optional JSON-5 extensions -** 0x04 Superficially appears to be JSONB -** 0x08 Strictly well-formed JSONB -** -** If the FLAGS argument is omitted, it defaults to 1. Useful values for -** FLAGS include: -** -** 1 Strict canonical JSON text -** 2 JSON text perhaps with JSON-5 extensions -** 4 Superficially appears to be JSONB -** 5 Canonical JSON text or superficial JSONB -** 6 JSON-5 text or superficial JSONB -** 8 Strict JSONB -** 9 Canonical JSON text or strict JSONB -** 10 JSON-5 text or strict JSONB -** -** Other flag combinations are redundant. For example, every canonical -** JSON text is also well-formed JSON-5 text, so FLAG values 2 and 3 -** are the same. Similarly, any input that passes a strict JSONB validation -** will also pass the superficial validation so 12 through 15 are the same -** as 8 through 11 respectively. -** -** This routine runs in linear time to validate text and when doing strict -** JSONB validation. Superficial JSONB validation is constant time, -** assuming the BLOB is already in memory. The performance advantage -** of superficial JSONB validation is why that option is provided. -** Application developers can choose to do fast superficial validation or -** slower strict validation, according to their specific needs. -** -** Only the lower four bits of the FLAGS argument are currently used. -** Higher bits are reserved for future expansion. To facilitate -** compatibility, the current implementation raises an error if any bit -** in FLAGS is set other than the lower four bits. -** -** The original circa 2015 implementation of the JSON routines in -** SQLite only supported canonical RFC-8259 JSON text and the json_valid() -** function only accepted one argument. That is why the default value -** for the FLAGS argument is 1, since FLAGS=1 causes this routine to only -** recognize canonical RFC-8259 JSON text as valid. The extra FLAGS -** argument was added when the JSON routines were extended to support -** JSON5-like extensions and binary JSONB stored in BLOBs. -** -** Return Values: -** -** * Raise an error if FLAGS is outside the range of 1 to 15. -** * Return NULL if the input is NULL -** * Return 1 if the input is well-formed. -** * Return 0 if the input is not well-formed. -*/ -static void jsonValidFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - u8 flags = 1; - u8 res = 0; - if( argc==2 ){ - i64 f = sqlite3_value_int64(argv[1]); - if( f<1 || f>15 ){ - sqlite3_result_error(ctx, "FLAGS parameter to json_valid() must be" - " between 1 and 15", -1); - return; - } - flags = f & 0x0f; - } - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_NULL: { -#ifdef SQLITE_LEGACY_JSON_VALID - /* Incorrect legacy behavior was to return FALSE for a NULL input */ - sqlite3_result_int(ctx, 0); -#endif - return; - } - case SQLITE_BLOB: { - JsonParse py; - memset(&py, 0, sizeof(py)); - if( jsonArgIsJsonb(argv[0], &py) ){ - if( flags & 0x04 ){ - /* Superficial checking only - accomplished by the - ** jsonArgIsJsonb() call above. */ - res = 1; - }else if( flags & 0x08 ){ - /* Strict checking. Check by translating BLOB->TEXT->BLOB. If - ** no errors occur, call that a "strict check". */ - res = 0==jsonbValidityCheck(&py, 0, py.nBlob, 1); - } - break; - } - /* Fall through into interpreting the input as text. See note - ** above at tag-20240123-a. */ - /* no break */ deliberate_fall_through - } - default: { - JsonParse px; - if( (flags & 0x3)==0 ) break; - memset(&px, 0, sizeof(px)); - - p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR); - if( p ){ - if( p->oom ){ - sqlite3_result_error_nomem(ctx); - }else if( p->nErr ){ - /* no-op */ - }else if( (flags & 0x02)!=0 || p->hasNonstd==0 ){ - res = 1; - } - jsonParseFree(p); - }else{ - sqlite3_result_error_nomem(ctx); - } - break; - } - } - sqlite3_result_int(ctx, res); -} - -/* -** json_error_position(JSON) -** -** If the argument is NULL, return NULL -** -** If the argument is BLOB, do a full validity check and return non-zero -** if the check fails. The return value is the approximate 1-based offset -** to the byte of the element that contains the first error. -** -** Otherwise interpret the argument is TEXT (even if it is numeric) and -** return the 1-based character position for where the parser first recognized -** that the input was not valid JSON, or return 0 if the input text looks -** ok. JSON-5 extensions are accepted. -*/ -static void jsonErrorFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - i64 iErrPos = 0; /* Error position to be returned */ - JsonParse s; - - assert( argc==1 ); - UNUSED_PARAMETER(argc); - memset(&s, 0, sizeof(s)); - s.db = sqlite3_context_db_handle(ctx); - if( jsonArgIsJsonb(argv[0], &s) ){ - iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1); - }else{ - s.zJson = (char*)sqlite3_value_text(argv[0]); - if( s.zJson==0 ) return; /* NULL input or OOM */ - s.nJson = sqlite3_value_bytes(argv[0]); - if( jsonConvertTextToBlob(&s,0) ){ - if( s.oom ){ - iErrPos = -1; - }else{ - /* Convert byte-offset s.iErr into a character offset */ - u32 k; - assert( s.zJson!=0 ); /* Because s.oom is false */ - for(k=0; kzBuf==0 ){ - jsonStringInit(pStr, ctx); - jsonAppendChar(pStr, '['); - }else if( pStr->nUsed>1 ){ - jsonAppendChar(pStr, ','); - } - pStr->pCtx = ctx; - jsonAppendSqlValue(pStr, argv[0]); - } -} -static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ - JsonString *pStr; - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); - if( pStr ){ - int flags; - pStr->pCtx = ctx; - jsonAppendChar(pStr, ']'); - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( pStr->eErr ){ - jsonReturnString(pStr, 0, 0); - return; - }else if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(pStr); - if( isFinal ){ - if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); - }else{ - jsonStringTrimOneChar(pStr); - } - return; - }else if( isFinal ){ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : - sqlite3RCStrUnref); - pStr->bStatic = 1; - }else{ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - jsonStringTrimOneChar(pStr); - } - }else{ - sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); - } - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} -static void jsonArrayValue(sqlite3_context *ctx){ - jsonArrayCompute(ctx, 0); -} -static void jsonArrayFinal(sqlite3_context *ctx){ - jsonArrayCompute(ctx, 1); -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** This method works for both json_group_array() and json_group_object(). -** It works by removing the first element of the group by searching forward -** to the first comma (",") that is not within a string and deleting all -** text through that comma. -*/ -static void jsonGroupInverse( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - unsigned int i; - int inStr = 0; - int nNest = 0; - char *z; - char c; - JsonString *pStr; - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); -#ifdef NEVER - /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will - ** always have been called to initialize it */ - if( NEVER(!pStr) ) return; -#endif - z = pStr->zBuf; - for(i=1; inUsed && ((c = z[i])!=',' || inStr || nNest); i++){ - if( c=='"' ){ - inStr = !inStr; - }else if( c=='\\' ){ - i++; - }else if( !inStr ){ - if( c=='{' || c=='[' ) nNest++; - if( c=='}' || c==']' ) nNest--; - } - } - if( inUsed ){ - 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 -#endif - - -/* -** json_group_obj(NAME,VALUE) -** -** Return a JSON object composed of all names and values in the aggregate. -*/ -static void jsonObjectStep( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString *pStr; - const char *z; - u32 n; - UNUSED_PARAMETER(argc); - pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); - if( pStr ){ - z = (const char*)sqlite3_value_text(argv[0]); - n = sqlite3Strlen30(z); - if( pStr->zBuf==0 ){ - jsonStringInit(pStr, ctx); - jsonAppendChar(pStr, '{'); - }else if( pStr->nUsed>1 && z!=0 ){ - jsonAppendChar(pStr, ','); - } - pStr->pCtx = ctx; - if( z!=0 ){ - jsonAppendString(pStr, z, n); - jsonAppendChar(pStr, ':'); - jsonAppendSqlValue(pStr, argv[1]); - } - } -} -static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ - JsonString *pStr; - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); - if( pStr ){ - int flags; - jsonAppendChar(pStr, '}'); - pStr->pCtx = ctx; - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( pStr->eErr ){ - jsonReturnString(pStr, 0, 0); - return; - }else if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(pStr); - if( isFinal ){ - if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); - }else{ - jsonStringTrimOneChar(pStr); - } - return; - }else if( isFinal ){ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : - sqlite3RCStrUnref); - pStr->bStatic = 1; - }else{ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - jsonStringTrimOneChar(pStr); - } - }else{ - sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); - } - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} -static void jsonObjectValue(sqlite3_context *ctx){ - jsonObjectCompute(ctx, 0); -} -static void jsonObjectFinal(sqlite3_context *ctx){ - jsonObjectCompute(ctx, 1); -} - - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/**************************************************************************** -** The json_each virtual table -****************************************************************************/ -typedef struct JsonParent JsonParent; -struct JsonParent { - u32 iHead; /* Start of object or array */ - u32 iValue; /* Start of the value */ - u32 iEnd; /* First byte past the end */ - u32 nPath; /* Length of path */ - i64 iKey; /* Key for JSONB_ARRAY */ -}; - -typedef struct JsonEachCursor JsonEachCursor; -struct JsonEachCursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - u32 iRowid; /* The rowid */ - u32 i; /* Index in sParse.aBlob[] of current row */ - u32 iEnd; /* EOF when i equals or exceeds this value */ - u32 nRoot; /* Size of the root path in bytes */ - u8 eType; /* Type of the container for element i */ - u8 bRecursive; /* True for json_tree(). False for json_each() */ - u32 nParent; /* Current nesting depth */ - u32 nParentAlloc; /* Space allocated for aParent[] */ - JsonParent *aParent; /* Parent elements of i */ - sqlite3 *db; /* Database connection */ - JsonString path; /* Current path */ - JsonParse sParse; /* Parse of the input JSON */ -}; -typedef struct JsonEachConnection JsonEachConnection; -struct JsonEachConnection { - sqlite3_vtab base; /* Base class - must be first */ - sqlite3 *db; /* Database connection */ -}; - - -/* Constructor for the json_each virtual table */ -static int jsonEachConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - JsonEachConnection *pNew; - int rc; - -/* Column numbers */ -#define JEACH_KEY 0 -#define JEACH_VALUE 1 -#define JEACH_TYPE 2 -#define JEACH_ATOM 3 -#define JEACH_ID 4 -#define JEACH_PARENT 5 -#define JEACH_FULLKEY 6 -#define JEACH_PATH 7 -/* The xBestIndex method assumes that the JSON and ROOT columns are -** the last two columns in the table. Should this ever changes, be -** sure to update the xBestIndex method. */ -#define JEACH_JSON 8 -#define JEACH_ROOT 9 - - UNUSED_PARAMETER(pzErr); - UNUSED_PARAMETER(argv); - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(pAux); - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," - "json HIDDEN,root HIDDEN)"); - if( rc==SQLITE_OK ){ - pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew)); - *ppVtab = (sqlite3_vtab*)pNew; - if( pNew==0 ) return SQLITE_NOMEM; - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - pNew->db = db; - } - return rc; -} - -/* destructor for json_each virtual table */ -static int jsonEachDisconnect(sqlite3_vtab *pVtab){ - JsonEachConnection *p = (JsonEachConnection*)pVtab; - sqlite3DbFree(p->db, pVtab); - return SQLITE_OK; -} - -/* constructor for a JsonEachCursor object for json_each(). */ -static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - JsonEachConnection *pVtab = (JsonEachConnection*)p; - JsonEachCursor *pCur; - - UNUSED_PARAMETER(p); - pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur)); - if( pCur==0 ) return SQLITE_NOMEM; - pCur->db = pVtab->db; - jsonStringZero(&pCur->path); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* constructor for a JsonEachCursor object for json_tree(). */ -static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - int rc = jsonEachOpenEach(p, ppCursor); - if( rc==SQLITE_OK ){ - JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; - pCur->bRecursive = 1; - } - return rc; -} - -/* Reset a JsonEachCursor back to its original state. Free any memory -** held. */ -static void jsonEachCursorReset(JsonEachCursor *p){ - jsonParseReset(&p->sParse); - jsonStringReset(&p->path); - sqlite3DbFree(p->db, p->aParent); - p->iRowid = 0; - p->i = 0; - p->aParent = 0; - p->nParent = 0; - p->nParentAlloc = 0; - p->iEnd = 0; - p->eType = 0; -} - -/* Destructor for a jsonEachCursor object */ -static int jsonEachClose(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - jsonEachCursorReset(p); - - sqlite3DbFree(p->db, cur); - return SQLITE_OK; -} - -/* Return TRUE if the jsonEachCursor object has been advanced off the end -** of the JSON object */ -static int jsonEachEof(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - return p->i >= p->iEnd; -} - -/* -** If the cursor is currently pointing at the label of a object entry, -** then return the index of the value. For all other cases, return the -** current pointer position, which is the value. -*/ -static int jsonSkipLabel(JsonEachCursor *p){ - if( p->eType==JSONB_OBJECT ){ - u32 sz = 0; - u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz); - return p->i + n + sz; - }else{ - return p->i; - } -} - -/* -** Append the path name for the current element. -*/ -static void jsonAppendPathName(JsonEachCursor *p){ - assert( p->nParent>0 ); - assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT ); - if( p->eType==JSONB_ARRAY ){ - jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey); - }else{ - u32 n, sz = 0, k, i; - const char *z; - int needQuote = 0; - n = jsonbPayloadSize(&p->sParse, p->i, &sz); - k = p->i + n; - z = (const char*)&p->sParse.aBlob[k]; - if( sz==0 || !sqlite3Isalpha(z[0]) ){ - needQuote = 1; - }else{ - for(i=0; ipath,".\"%.*s\"", sz, z); - }else{ - jsonPrintf(sz+2,&p->path,".%.*s", sz, z); - } - } -} - -/* Advance the cursor to the next element for json_tree() */ -static int jsonEachNext(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - int rc = SQLITE_OK; - if( p->bRecursive ){ - u8 x; - u8 levelChange = 0; - u32 n, sz = 0; - u32 i = jsonSkipLabel(p); - x = p->sParse.aBlob[i] & 0x0f; - n = jsonbPayloadSize(&p->sParse, i, &sz); - if( x==JSONB_OBJECT || x==JSONB_ARRAY ){ - JsonParent *pParent; - if( p->nParent>=p->nParentAlloc ){ - JsonParent *pNew; - u64 nNew; - nNew = p->nParentAlloc*2 + 3; - pNew = sqlite3DbRealloc(p->db, p->aParent, sizeof(JsonParent)*nNew); - if( pNew==0 ) return SQLITE_NOMEM; - p->nParentAlloc = (u32)nNew; - p->aParent = pNew; - } - levelChange = 1; - pParent = &p->aParent[p->nParent]; - pParent->iHead = p->i; - pParent->iValue = i; - pParent->iEnd = i + n + sz; - pParent->iKey = -1; - pParent->nPath = (u32)p->path.nUsed; - if( p->eType && p->nParent ){ - jsonAppendPathName(p); - if( p->path.eErr ) rc = SQLITE_NOMEM; - } - p->nParent++; - p->i = i + n; - }else{ - p->i = i + n + sz; - } - while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){ - p->nParent--; - p->path.nUsed = p->aParent[p->nParent].nPath; - levelChange = 1; - } - if( levelChange ){ - if( p->nParent>0 ){ - JsonParent *pParent = &p->aParent[p->nParent-1]; - u32 iVal = pParent->iValue; - p->eType = p->sParse.aBlob[iVal] & 0x0f; - }else{ - p->eType = 0; - } - } - }else{ - u32 n, sz = 0; - u32 i = jsonSkipLabel(p); - n = jsonbPayloadSize(&p->sParse, i, &sz); - p->i = i + n + sz; - } - if( p->eType==JSONB_ARRAY && p->nParent ){ - p->aParent[p->nParent-1].iKey++; - } - p->iRowid++; - return rc; -} - -/* Length of the path for rowid==0 in bRecursive mode. -*/ -static int jsonEachPathLength(JsonEachCursor *p){ - u32 n = p->path.nUsed; - char *z = p->path.zBuf; - if( p->iRowid==0 && p->bRecursive && n>=2 ){ - while( n>1 ){ - n--; - if( z[n]=='[' || z[n]=='.' ){ - u32 x, sz = 0; - char cSaved = z[n]; - z[n] = 0; - assert( p->sParse.eEdit==0 ); - x = jsonLookupStep(&p->sParse, 0, z+1, 0); - z[n] = cSaved; - if( JSON_LOOKUP_ISERROR(x) ) continue; - if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break; - } - } - } - return n; -} - -/* Return the value of a column */ -static int jsonEachColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int iColumn /* Which column to return */ -){ - JsonEachCursor *p = (JsonEachCursor*)cur; - switch( iColumn ){ - case JEACH_KEY: { - if( p->nParent==0 ){ - u32 n, j; - if( p->nRoot==1 ) break; - j = jsonEachPathLength(p); - n = p->nRoot - j; - if( n==0 ){ - break; - }else if( p->path.zBuf[j]=='[' ){ - i64 x; - sqlite3Atoi64(&p->path.zBuf[j+1], &x, n-1, SQLITE_UTF8); - sqlite3_result_int64(ctx, x); - }else if( p->path.zBuf[j+1]=='"' ){ - sqlite3_result_text(ctx, &p->path.zBuf[j+2], n-3, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(ctx, &p->path.zBuf[j+1], n-1, SQLITE_TRANSIENT); - } - break; - } - if( p->eType==JSONB_OBJECT ){ - jsonReturnFromBlob(&p->sParse, p->i, ctx, 1); - }else{ - assert( p->eType==JSONB_ARRAY ); - sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey); - } - break; - } - case JEACH_VALUE: { - u32 i = jsonSkipLabel(p); - jsonReturnFromBlob(&p->sParse, i, ctx, 1); - if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - break; - } - case JEACH_TYPE: { - u32 i = jsonSkipLabel(p); - u8 eType = p->sParse.aBlob[i] & 0x0f; - sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC); - break; - } - case JEACH_ATOM: { - u32 i = jsonSkipLabel(p); - if( (p->sParse.aBlob[i] & 0x0f)sParse, i, ctx, 1); - } - break; - } - case JEACH_ID: { - sqlite3_result_int64(ctx, (sqlite3_int64)p->i); - break; - } - case JEACH_PARENT: { - if( p->nParent>0 && p->bRecursive ){ - sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead); - } - break; - } - case JEACH_FULLKEY: { - u64 nBase = p->path.nUsed; - if( p->nParent ) jsonAppendPathName(p); - sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed, - SQLITE_TRANSIENT, SQLITE_UTF8); - p->path.nUsed = nBase; - break; - } - case JEACH_PATH: { - u32 n = jsonEachPathLength(p); - sqlite3_result_text64(ctx, p->path.zBuf, n, - SQLITE_TRANSIENT, SQLITE_UTF8); - break; - } - default: { - sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC); - break; - } - case JEACH_JSON: { - if( p->sParse.zJson==0 ){ - sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob, - SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT); - } - break; - } - } - return SQLITE_OK; -} - -/* Return the current rowid value */ -static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - JsonEachCursor *p = (JsonEachCursor*)cur; - *pRowid = p->iRowid; - return SQLITE_OK; -} - -/* The query strategy is to look for an equality constraint on the json -** column. Without such a constraint, the table cannot operate. idxNum is -** 1 if the constraint is found, 3 if the constraint and zRoot are found, -** and 0 otherwise. -*/ -static int jsonEachBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; /* Loop counter or computed array index */ - int aIdx[2]; /* Index of constraints for JSON and ROOT */ - int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ - int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ - const struct sqlite3_index_constraint *pConstraint; - - /* This implementation assumes that JSON and ROOT are the last two - ** columns in the table */ - assert( JEACH_ROOT == JEACH_JSON+1 ); - UNUSED_PARAMETER(tab); - aIdx[0] = aIdx[1] = -1; - pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pConstraint++){ - int iCol; - int iMask; - 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; - }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - aIdx[iCol] = i; - idxMask |= iMask; - } - } - if( pIdxInfo->nOrderBy>0 - && pIdxInfo->aOrderBy[0].iColumn<0 - && pIdxInfo->aOrderBy[0].desc==0 - ){ - pIdxInfo->orderByConsumed = 1; - } - - if( (unusableMask & ~idxMask)!=0 ){ - /* If there are any unusable constraints on JSON or ROOT, then reject - ** this entire plan */ - return SQLITE_CONSTRAINT; - } - if( aIdx[0]<0 ){ - /* No JSON input. Leave estimatedCost at the huge value that it was - ** initialized to to discourage the query planner from selecting this - ** plan. */ - pIdxInfo->idxNum = 0; - }else{ - pIdxInfo->estimatedCost = 1.0; - i = aIdx[0]; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - pIdxInfo->aConstraintUsage[i].omit = 1; - if( aIdx[1]<0 ){ - pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ - }else{ - i = aIdx[1]; - pIdxInfo->aConstraintUsage[i].argvIndex = 2; - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ - } - } - return SQLITE_OK; -} - -/* Start a search on a new JSON string */ -static int jsonEachFilter( - sqlite3_vtab_cursor *cur, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - JsonEachCursor *p = (JsonEachCursor*)cur; - const char *zRoot = 0; - u32 i, n, sz; - - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(argc); - jsonEachCursorReset(p); - if( idxNum==0 ) return SQLITE_OK; - memset(&p->sParse, 0, sizeof(p->sParse)); - p->sParse.nJPRef = 1; - p->sParse.db = p->db; - if( jsonArgIsJsonb(argv[0], &p->sParse) ){ - /* We have JSONB */ - }else{ - p->sParse.zJson = (char*)sqlite3_value_text(argv[0]); - p->sParse.nJson = sqlite3_value_bytes(argv[0]); - if( p->sParse.zJson==0 ){ - p->i = p->iEnd = 0; - return SQLITE_OK; - } - if( jsonConvertTextToBlob(&p->sParse, 0) ){ - if( p->sParse.oom ){ - return SQLITE_NOMEM; - } - goto json_each_malformed_input; - } - } - if( idxNum==3 ){ - zRoot = (const char*)sqlite3_value_text(argv[1]); - if( zRoot==0 ) return SQLITE_OK; - if( zRoot[0]!='$' ){ - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; - } - p->nRoot = sqlite3Strlen30(zRoot); - if( zRoot[1]==0 ){ - i = p->i = 0; - p->eType = 0; - }else{ - i = jsonLookupStep(&p->sParse, 0, zRoot+1, 0); - if( JSON_LOOKUP_ISERROR(i) ){ - if( i==JSON_LOOKUP_NOTFOUND ){ - p->i = 0; - p->eType = 0; - p->iEnd = 0; - return SQLITE_OK; - } - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; - } - if( p->sParse.iLabel ){ - p->i = p->sParse.iLabel; - p->eType = JSONB_OBJECT; - }else{ - p->i = i; - p->eType = JSONB_ARRAY; - } - } - jsonAppendRaw(&p->path, zRoot, p->nRoot); - }else{ - i = p->i = 0; - p->eType = 0; - p->nRoot = 1; - jsonAppendRaw(&p->path, "$", 1); - } - p->nParent = 0; - n = jsonbPayloadSize(&p->sParse, i, &sz); - p->iEnd = i+n+sz; - if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){ - p->i = i + n; - p->eType = p->sParse.aBlob[i] & 0x0f; - p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent)); - if( p->aParent==0 ) return SQLITE_NOMEM; - p->nParent = 1; - p->nParentAlloc = 1; - p->aParent[0].iKey = 0; - p->aParent[0].iEnd = p->iEnd; - p->aParent[0].iHead = p->i; - p->aParent[0].iValue = i; - } - return SQLITE_OK; - -json_each_malformed_input: - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; -} - -/* The methods of the json_each virtual table */ -static sqlite3_module jsonEachModule = { - 0, /* iVersion */ - 0, /* xCreate */ - jsonEachConnect, /* xConnect */ - jsonEachBestIndex, /* xBestIndex */ - jsonEachDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - jsonEachOpenEach, /* xOpen - open a cursor */ - jsonEachClose, /* xClose - close a cursor */ - jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNext, /* xNext - advance a cursor */ - jsonEachEof, /* xEof - check for end of scan */ - jsonEachColumn, /* xColumn - read data */ - jsonEachRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ -}; - -/* The methods of the json_tree virtual table. */ -static sqlite3_module jsonTreeModule = { - 0, /* iVersion */ - 0, /* xCreate */ - jsonEachConnect, /* xConnect */ - jsonEachBestIndex, /* xBestIndex */ - jsonEachDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - jsonEachOpenTree, /* xOpen - open a cursor */ - jsonEachClose, /* xClose - close a cursor */ - jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNext, /* xNext - advance a cursor */ - jsonEachEof, /* xEof - check for end of scan */ - jsonEachColumn, /* xColumn - read data */ - jsonEachRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ -}; -#endif /* SQLITE_OMIT_VIRTUALTABLE */ -#endif /* !defined(SQLITE_OMIT_JSON) */ - -/* -** Register JSON functions. -*/ -SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ -#ifndef SQLITE_OMIT_JSON - static FuncDef aJsonFunc[] = { - /* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */ - /* | | */ - /* Uses cache ------, | | ,---- Returns JSONB */ - /* | | | | */ - /* Number of arguments ---, | | | | ,--- Flags */ - /* | | | | | | */ - JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc), - JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), - JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), - JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), - JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc), - JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc), - JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc), - JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc), - JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc), - JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc), - JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc), - JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc), - JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc), - JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc), - JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc), - JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc), - JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc), - JFUNCTION(json_pretty, 1,1,0, 0,0,0, jsonPrettyFunc), - JFUNCTION(json_pretty, 2,1,0, 0,0,0, jsonPrettyFunc), - JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc), - JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc), - JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc), - JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc), - JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc), - JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc), - JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc), - JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc), - JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc), - JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc), - JFUNCTION(json_valid, 2,1,0, 0,0,0, jsonValidFunc), -#if SQLITE_DEBUG - JFUNCTION(json_parse, 1,1,0, 0,0,0, jsonParseFunc), -#endif - WAGGREGATE(json_group_array, 1, 0, 0, - jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC), - WAGGREGATE(jsonb_group_array, 1, JSON_BLOB, 0, - jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), - WAGGREGATE(json_group_object, 2, 0, 0, - jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), - WAGGREGATE(jsonb_group_object,2, JSON_BLOB, 0, - jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC) - }; - sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); -#endif -} - -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) -/* -** Register the JSON table-valued functions -*/ -SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3 *db){ - int rc = SQLITE_OK; - static const struct { - const char *zName; - sqlite3_module *pModule; - } aMod[] = { - { "json_each", &jsonEachModule }, - { "json_tree", &jsonTreeModule }, - }; - unsigned int i; - for(i=0; i */ - -/* -** If building separately, we will need some setup that is normally -** found in sqliteInt.h -*/ -#if !defined(SQLITE_AMALGAMATION) -#include "sqlite3rtree.h" -typedef sqlite3_int64 i64; -typedef sqlite3_uint64 u64; -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif -#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 -#ifndef offsetof -#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define FLEXARRAY -#else -# define FLEXARRAY 1 -#endif -#endif /* !defined(SQLITE_AMALGAMATION) */ - -/* Macro to check for 4-byte alignment. Only used inside of assert() */ -#ifdef SQLITE_DEBUG -# define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0) -#endif - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -/* The following macro is used to suppress compiler warnings. -*/ -#ifndef UNUSED_PARAMETER -# define UNUSED_PARAMETER(x) (void)(x) -#endif - -typedef struct Rtree Rtree; -typedef struct RtreeCursor RtreeCursor; -typedef struct RtreeNode RtreeNode; -typedef struct RtreeCell RtreeCell; -typedef struct RtreeConstraint RtreeConstraint; -typedef struct RtreeMatchArg RtreeMatchArg; -typedef struct RtreeGeomCallback RtreeGeomCallback; -typedef union RtreeCoord RtreeCoord; -typedef struct RtreeSearchPoint RtreeSearchPoint; - -/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ -#define RTREE_MAX_DIMENSIONS 5 - -/* Maximum number of auxiliary columns */ -#define RTREE_MAX_AUX_COLUMN 100 - -/* Size of hash table Rtree.aHash. This hash table is not expected to -** ever contain very many entries, so a fixed number of buckets is -** used. -*/ -#define HASHSIZE 97 - -/* The xBestIndex method of this virtual table requires an estimate of -** the number of rows in the virtual table to calculate the costs of -** various strategies. If possible, this estimate is loaded from the -** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum). -** Otherwise, if no sqlite_stat1 entry is available, use -** RTREE_DEFAULT_ROWEST. -*/ -#define RTREE_DEFAULT_ROWEST 1048576 -#define RTREE_MIN_ROWEST 100 - -/* -** An rtree virtual-table object. -*/ -struct Rtree { - sqlite3_vtab base; /* Base class. Must be first */ - sqlite3 *db; /* Host database connection */ - int iNodeSize; /* Size in bytes of each node in the node table */ - u8 nDim; /* Number of dimensions */ - u8 nDim2; /* Twice the number of dimensions */ - u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ - 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 - int iDepth; /* Current depth of the r-tree structure */ - char *zDb; /* Name of database containing r-tree table */ - char *zName; /* Name of r-tree table */ - char *zNodeName; /* Name of the %_node table */ - u32 nBusy; /* Current number of users of this structure */ - i64 nRowEst; /* Estimated number of rows in this table */ - u32 nCursor; /* Number of open cursors */ - u32 nNodeRef; /* Number RtreeNodes with positive nRef */ - char *zReadAuxSql; /* SQL for statement to read aux data */ - - /* List of nodes removed during a CondenseTree operation. List is - ** linked together via the pointer normally used for hash chains - - ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree - ** headed by the node (leaf nodes have RtreeNode.iNode==0). - */ - RtreeNode *pDeleted; - - /* Blob I/O on xxx_node */ - sqlite3_blob *pNodeBlob; - - /* Statements to read/write/delete a record from xxx_node */ - sqlite3_stmt *pWriteNode; - sqlite3_stmt *pDeleteNode; - - /* Statements to read/write/delete a record from xxx_rowid */ - sqlite3_stmt *pReadRowid; - sqlite3_stmt *pWriteRowid; - sqlite3_stmt *pDeleteRowid; - - /* Statements to read/write/delete a record from xxx_parent */ - sqlite3_stmt *pReadParent; - sqlite3_stmt *pWriteParent; - sqlite3_stmt *pDeleteParent; - - /* Statement for writing to the "aux:" fields, if there are any */ - sqlite3_stmt *pWriteAux; - - RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ -}; - -/* Possible values for Rtree.eCoordType: */ -#define RTREE_COORD_REAL32 0 -#define RTREE_COORD_INT32 1 - -/* -** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will -** only deal with integer coordinates. No floating point operations -** will be done. -*/ -#ifdef SQLITE_RTREE_INT_ONLY - typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ - typedef int RtreeValue; /* Low accuracy coordinate */ -# define RTREE_ZERO 0 -#else - typedef double RtreeDValue; /* High accuracy coordinate */ - typedef float RtreeValue; /* Low accuracy coordinate */ -# define RTREE_ZERO 0.0 -#endif - -/* -** Set the Rtree.bCorrupt flag -*/ -#ifdef SQLITE_DEBUG -# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1) -#else -# define RTREE_IS_CORRUPT(X) -#endif - -/* -** When doing a search of an r-tree, instances of the following structure -** record intermediate results from the tree walk. -** -** The id is always a node-id. For iLevel>=1 the id is the node-id of -** the node that the RtreeSearchPoint represents. When iLevel==0, however, -** the id is of the parent node and the cell that RtreeSearchPoint -** represents is the iCell-th entry in the parent node. -*/ -struct RtreeSearchPoint { - RtreeDValue rScore; /* The score for this node. Smallest goes first. */ - sqlite3_int64 id; /* Node ID */ - u8 iLevel; /* 0=entries. 1=leaf node. 2+ for higher */ - u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */ - u8 iCell; /* Cell index within the node */ -}; - -/* -** The minimum number of cells allowed for a node is a third of the -** maximum. In Gutman's notation: -** -** m = M/3 -** -** If an R*-tree "Reinsert" operation is required, the same number of -** cells are removed from the overfull node and reinserted into the tree. -*/ -#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3) -#define RTREE_REINSERT(p) RTREE_MINCELLS(p) -#define RTREE_MAXCELLS 51 - -/* -** The smallest possible node-size is (512-64)==448 bytes. And the largest -** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). -** Therefore all non-root nodes must contain at least 3 entries. Since -** 3^40 is greater than 2^64, an r-tree structure always has a depth of -** 40 or less. -*/ -#define RTREE_MAX_DEPTH 40 - - -/* -** Number of entries in the cursor RtreeNode cache. The first entry is -** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining -** entries cache the RtreeNode for the first elements of the priority queue. -*/ -#define RTREE_CACHE_SZ 5 - -/* -** An rtree cursor object. -*/ -struct RtreeCursor { - sqlite3_vtab_cursor base; /* Base class. Must be first */ - u8 atEOF; /* True if at end of search */ - u8 bPoint; /* True if sPoint is valid */ - u8 bAuxValid; /* True if pReadAux is valid */ - int iStrategy; /* Copy of idxNum search parameter */ - int nConstraint; /* Number of entries in aConstraint */ - RtreeConstraint *aConstraint; /* Search constraints. */ - int nPointAlloc; /* Number of slots allocated for aPoint[] */ - int nPoint; /* Number of slots used in aPoint[] */ - int mxLevel; /* iLevel value for root of the tree */ - RtreeSearchPoint *aPoint; /* Priority queue for search points */ - sqlite3_stmt *pReadAux; /* Statement to read aux-data */ - RtreeSearchPoint sPoint; /* Cached next search point */ - RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ - u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ -}; - -/* Return the Rtree of a RtreeCursor */ -#define RTREE_OF_CURSOR(X) ((Rtree*)((X)->base.pVtab)) - -/* -** A coordinate can be either a floating point number or a integer. All -** coordinates within a single R-Tree are always of the same time. -*/ -union RtreeCoord { - RtreeValue f; /* Floating point value */ - int i; /* Integer value */ - u32 u; /* Unsigned for byte-order conversions */ -}; - -/* -** The argument is an RtreeCoord. Return the value stored within the RtreeCoord -** formatted as a RtreeDValue (double or int64). This macro assumes that local -** variable pRtree points to the Rtree structure associated with the -** RtreeCoord. -*/ -#ifdef SQLITE_RTREE_INT_ONLY -# define DCOORD(coord) ((RtreeDValue)coord.i) -#else -# define DCOORD(coord) ( \ - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ - ((double)coord.f) : \ - ((double)coord.i) \ - ) -#endif - -/* -** A search constraint. -*/ -struct RtreeConstraint { - int iCoord; /* Index of constrained coordinate */ - int op; /* Constraining operation */ - union { - RtreeDValue rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*); - int (*xQueryFunc)(sqlite3_rtree_query_info*); - } u; - sqlite3_rtree_query_info *pInfo; /* xGeom and xQueryFunc argument */ -}; - -/* Possible values for RtreeConstraint.op */ -#define RTREE_EQ 0x41 /* A */ -#define RTREE_LE 0x42 /* B */ -#define RTREE_LT 0x43 /* C */ -#define RTREE_GE 0x44 /* D */ -#define RTREE_GT 0x45 /* E */ -#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */ -#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */ - -/* Special operators available only on cursors. Needs to be consecutive -** with the normal values above, but must be less than RTREE_MATCH. These -** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or -** x<'xyz' (RTREE_TRUE) */ -#define RTREE_TRUE 0x3f /* ? */ -#define RTREE_FALSE 0x40 /* @ */ - -/* -** An rtree structure node. -*/ -struct RtreeNode { - RtreeNode *pParent; /* Parent node */ - i64 iNode; /* The node number */ - int nRef; /* Number of references to this node */ - int isDirty; /* True if the node needs to be written to disk */ - u8 *zData; /* Content of the node, as should be on disk */ - RtreeNode *pNext; /* Next node in this hash collision chain */ -}; - -/* Return the number of cells in a node */ -#define NCELL(pNode) readInt16(&(pNode)->zData[2]) - -/* -** A single cell from a node, deserialized -*/ -struct RtreeCell { - i64 iRowid; /* Node or entry ID */ - RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */ -}; - - -/* -** This object becomes the sqlite3_user_data() for the SQL functions -** that are created by sqlite3_rtree_geometry_callback() and -** sqlite3_rtree_query_callback() and which appear on the right of MATCH -** operators in order to constrain a search. -** -** xGeom and xQueryFunc are the callback functions. Exactly one of -** xGeom and xQueryFunc fields is non-NULL, depending on whether the -** SQL function was created using sqlite3_rtree_geometry_callback() or -** sqlite3_rtree_query_callback(). -** -** This object is deleted automatically by the destructor mechanism in -** sqlite3_create_function_v2(). -*/ -struct RtreeGeomCallback { - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); - int (*xQueryFunc)(sqlite3_rtree_query_info*); - void (*xDestructor)(void*); - void *pContext; -}; - -/* -** An instance of this structure (in the form of a BLOB) is returned by -** the SQL functions that sqlite3_rtree_geometry_callback() and -** sqlite3_rtree_query_callback() create, and is read as the right-hand -** operand to the MATCH operator of an R-Tree. -*/ -struct RtreeMatchArg { - u32 iSize; /* Size of this object */ - RtreeGeomCallback cb; /* Info about the callback functions */ - int nParam; /* Number of parameters to the SQL function */ - sqlite3_value **apSqlParam; /* Original SQL parameter values */ - RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */ -}; - -/* Size of an RtreeMatchArg object with N parameters */ -#define SZ_RTREEMATCHARG(N) \ - (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue)) - -#ifndef MAX -# define MAX(x,y) ((x) < (y) ? (y) : (x)) -#endif -#ifndef MIN -# define MIN(x,y) ((x) > (y) ? (y) : (x)) -#endif - -/* What version of GCC is being used. 0 means GCC is not being used . -** Note that the GCC_VERSION macro will also be set correctly when using -** clang, since clang works hard to be gcc compatible. So the gcc -** optimizations will also work when compiling with clang. -*/ -#ifndef GCC_VERSION -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif -#endif - -/* The testcase() macro should already be defined in the amalgamation. If -** it is not, make it a no-op. -*/ -#ifndef SQLITE_AMALGAMATION -# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) - unsigned int sqlite3RtreeTestcase = 0; -# define testcase(X) if( X ){ sqlite3RtreeTestcase += __LINE__; } -# else -# define testcase(X) -# endif -#endif - -/* -** Make sure that the compiler intrinsics we desire are enabled when -** compiling with an appropriate version of MSVC unless prevented by -** the SQLITE_DISABLE_INTRINSIC define. -*/ -#if !defined(SQLITE_DISABLE_INTRINSIC) -# if defined(_MSC_VER) && _MSC_VER>=1400 -# if !defined(_WIN32_WCE) -/* # include */ -# pragma intrinsic(_byteswap_ulong) -# pragma intrinsic(_byteswap_uint64) -# else -/* # include */ -# endif -# endif -#endif - -/* -** Macros to determine whether the machine is big or little endian, -** and whether or not that determination is run-time or compile-time. -** -** For best performance, an attempt is made to guess at the byte-order -** using C-preprocessor macros. If that is unsuccessful, or if -** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined -** at run-time. -*/ -#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ -# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ -# define SQLITE_BYTEORDER 4321 -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -# define SQLITE_BYTEORDER 1234 -# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 -# define SQLITE_BYTEORDER 4321 -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 -# else -# define SQLITE_BYTEORDER 0 -# endif -#endif - - -/* What version of MSVC is being used. 0 means MSVC is not being used */ -#ifndef MSVC_VERSION -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# define MSVC_VERSION 0 -#endif -#endif - -/* -** Functions to deserialize a 16 bit integer, 32 bit real number and -** 64 bit integer. The deserialized value is returned. -*/ -static int readInt16(u8 *p){ - return (p[0]<<8) + p[1]; -} -static void readCoord(u8 *p, RtreeCoord *pCoord){ - assert( FOUR_BYTE_ALIGNED(p) ); -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - pCoord->u = _byteswap_ulong(*(u32*)p); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - pCoord->u = __builtin_bswap32(*(u32*)p); -#elif SQLITE_BYTEORDER==4321 - pCoord->u = *(u32*)p; -#else - pCoord->u = ( - (((u32)p[0]) << 24) + - (((u32)p[1]) << 16) + - (((u32)p[2]) << 8) + - (((u32)p[3]) << 0) - ); -#endif -} -static i64 readInt64(u8 *p){ -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - u64 x; - memcpy(&x, p, 8); - return (i64)_byteswap_uint64(x); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - u64 x; - memcpy(&x, p, 8); - return (i64)__builtin_bswap64(x); -#elif SQLITE_BYTEORDER==4321 - i64 x; - memcpy(&x, p, 8); - return x; -#else - return (i64)( - (((u64)p[0]) << 56) + - (((u64)p[1]) << 48) + - (((u64)p[2]) << 40) + - (((u64)p[3]) << 32) + - (((u64)p[4]) << 24) + - (((u64)p[5]) << 16) + - (((u64)p[6]) << 8) + - (((u64)p[7]) << 0) - ); -#endif -} - -/* -** Functions to serialize a 16 bit integer, 32 bit real number and -** 64 bit integer. The value returned is the number of bytes written -** to the argument buffer (always 2, 4 and 8 respectively). -*/ -static void writeInt16(u8 *p, int i){ - p[0] = (i>> 8)&0xFF; - p[1] = (i>> 0)&0xFF; -} -static int writeCoord(u8 *p, RtreeCoord *pCoord){ - u32 i; - assert( FOUR_BYTE_ALIGNED(p) ); - assert( sizeof(RtreeCoord)==4 ); - assert( sizeof(u32)==4 ); -#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - i = __builtin_bswap32(pCoord->u); - memcpy(p, &i, 4); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - i = _byteswap_ulong(pCoord->u); - memcpy(p, &i, 4); -#elif SQLITE_BYTEORDER==4321 - i = pCoord->u; - memcpy(p, &i, 4); -#else - i = pCoord->u; - p[0] = (i>>24)&0xFF; - p[1] = (i>>16)&0xFF; - p[2] = (i>> 8)&0xFF; - p[3] = (i>> 0)&0xFF; -#endif - return 4; -} -static int writeInt64(u8 *p, i64 i){ -#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - i = (i64)__builtin_bswap64((u64)i); - memcpy(p, &i, 8); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - i = (i64)_byteswap_uint64((u64)i); - memcpy(p, &i, 8); -#elif SQLITE_BYTEORDER==4321 - memcpy(p, &i, 8); -#else - p[0] = (i>>56)&0xFF; - p[1] = (i>>48)&0xFF; - p[2] = (i>>40)&0xFF; - p[3] = (i>>32)&0xFF; - p[4] = (i>>24)&0xFF; - p[5] = (i>>16)&0xFF; - p[6] = (i>> 8)&0xFF; - p[7] = (i>> 0)&0xFF; -#endif - return 8; -} - -/* -** Increment the reference count of node p. -*/ -static void nodeReference(RtreeNode *p){ - if( p ){ - assert( p->nRef>0 ); - p->nRef++; - } -} - -/* -** Clear the content of node p (set all bytes to 0x00). -*/ -static void nodeZero(Rtree *pRtree, RtreeNode *p){ - memset(&p->zData[2], 0, pRtree->iNodeSize-2); - p->isDirty = 1; -} - -/* -** Given a node number iNode, return the corresponding key to use -** in the Rtree.aHash table. -*/ -static unsigned int nodeHash(i64 iNode){ - return ((unsigned)iNode) % HASHSIZE; -} - -/* -** Search the node hash table for node iNode. If found, return a pointer -** to it. Otherwise, return 0. -*/ -static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ - RtreeNode *p; - for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext); - return p; -} - -/* -** Add node pNode to the node hash table. -*/ -static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ - int iHash; - assert( pNode->pNext==0 ); - iHash = nodeHash(pNode->iNode); - pNode->pNext = pRtree->aHash[iHash]; - pRtree->aHash[iHash] = pNode; -} - -/* -** Remove node pNode from the node hash table. -*/ -static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ - RtreeNode **pp; - if( pNode->iNode!=0 ){ - pp = &pRtree->aHash[nodeHash(pNode->iNode)]; - for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); } - *pp = pNode->pNext; - pNode->pNext = 0; - } -} - -/* -** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0), -** indicating that node has not yet been assigned a node number. It is -** assigned a node number when nodeWrite() is called to write the -** node contents out to the database. -*/ -static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ - RtreeNode *pNode; - pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize); - if( pNode ){ - memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); - pNode->zData = (u8 *)&pNode[1]; - pNode->nRef = 1; - pRtree->nNodeRef++; - pNode->pParent = pParent; - pNode->isDirty = 1; - nodeReference(pParent); - } - return pNode; -} - -/* -** Clear the Rtree.pNodeBlob object -*/ -static void nodeBlobReset(Rtree *pRtree){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - sqlite3_blob_close(pBlob); -} - -/* -** Obtain a reference to an r-tree node. -*/ -static int nodeAcquire( - Rtree *pRtree, /* R-tree structure */ - i64 iNode, /* Node number to load */ - RtreeNode *pParent, /* Either the parent node or NULL */ - RtreeNode **ppNode /* OUT: Acquired node */ -){ - int rc = SQLITE_OK; - RtreeNode *pNode = 0; - - /* Check if the requested node is already in the hash table. If so, - ** increase its reference count and return it. - */ - if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ - if( pParent && ALWAYS(pParent!=pNode->pParent) ){ - RTREE_IS_CORRUPT(pRtree); - return SQLITE_CORRUPT_VTAB; - } - pNode->nRef++; - *ppNode = pNode; - return SQLITE_OK; - } - - if( pRtree->pNodeBlob ){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - rc = sqlite3_blob_reopen(pBlob, iNode); - pRtree->pNodeBlob = pBlob; - if( rc ){ - nodeBlobReset(pRtree); - if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM; - } - } - if( pRtree->pNodeBlob==0 ){ - rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, pRtree->zNodeName, - "data", iNode, 0, - &pRtree->pNodeBlob); - } - if( rc ){ - *ppNode = 0; - /* If unable to open an sqlite3_blob on the desired row, that can only - ** be because the shadow tables hold erroneous data. */ - if( rc==SQLITE_ERROR ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - } - }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){ - pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize); - if( !pNode ){ - rc = SQLITE_NOMEM; - }else{ - pNode->pParent = pParent; - pNode->zData = (u8 *)&pNode[1]; - pNode->nRef = 1; - pRtree->nNodeRef++; - pNode->iNode = iNode; - pNode->isDirty = 0; - pNode->pNext = 0; - rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData, - pRtree->iNodeSize, 0); - } - } - - /* If the root node was just loaded, set pRtree->iDepth to the height - ** of the r-tree structure. A height of zero means all data is stored on - ** the root node. A height of one means the children of the root node - ** 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( rc==SQLITE_OK && pNode && iNode==1 ){ - pRtree->iDepth = readInt16(pNode->zData); - if( pRtree->iDepth>RTREE_MAX_DEPTH ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - } - } - - /* If no error has occurred so far, check if the "number of entries" - ** field on the node is too large. If so, set the return code to - ** SQLITE_CORRUPT_VTAB. - */ - if( pNode && rc==SQLITE_OK ){ - if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - } - } - - if( rc==SQLITE_OK ){ - if( pNode!=0 ){ - nodeReference(pParent); - nodeHashInsert(pRtree, pNode); - }else{ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - } - *ppNode = pNode; - }else{ - nodeBlobReset(pRtree); - if( pNode ){ - pRtree->nNodeRef--; - sqlite3_free(pNode); - } - *ppNode = 0; - } - - return rc; -} - -/* -** Overwrite cell iCell of node pNode with the contents of pCell. -*/ -static void nodeOverwriteCell( - Rtree *pRtree, /* The overall R-Tree */ - RtreeNode *pNode, /* The node into which the cell is to be written */ - RtreeCell *pCell, /* The cell to write */ - int iCell /* Index into pNode into which pCell is written */ -){ - int ii; - u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; - p += writeInt64(p, pCell->iRowid); - for(ii=0; iinDim2; ii++){ - p += writeCoord(p, &pCell->aCoord[ii]); - } - pNode->isDirty = 1; -} - -/* -** Remove the cell with index iCell from node pNode. -*/ -static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){ - u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; - u8 *pSrc = &pDst[pRtree->nBytesPerCell]; - int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell; - memmove(pDst, pSrc, nByte); - writeInt16(&pNode->zData[2], NCELL(pNode)-1); - pNode->isDirty = 1; -} - -/* -** Insert the contents of cell pCell into node pNode. If the insert -** is successful, return SQLITE_OK. -** -** If there is not enough free space in pNode, return SQLITE_FULL. -*/ -static int nodeInsertCell( - Rtree *pRtree, /* The overall R-Tree */ - RtreeNode *pNode, /* Write new cell into this node */ - RtreeCell *pCell /* The cell to be inserted */ -){ - int nCell; /* Current number of cells in pNode */ - int nMaxCell; /* Maximum number of cells for pNode */ - - nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; - nCell = NCELL(pNode); - - assert( nCell<=nMaxCell ); - if( nCellzData[2], nCell+1); - pNode->isDirty = 1; - } - - return (nCell==nMaxCell); -} - -/* -** If the node is dirty, write it out to the database. -*/ -static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){ - int rc = SQLITE_OK; - if( pNode->isDirty ){ - sqlite3_stmt *p = pRtree->pWriteNode; - if( pNode->iNode ){ - sqlite3_bind_int64(p, 1, pNode->iNode); - }else{ - sqlite3_bind_null(p, 1); - } - sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC); - sqlite3_step(p); - pNode->isDirty = 0; - rc = sqlite3_reset(p); - sqlite3_bind_null(p, 2); - if( pNode->iNode==0 && rc==SQLITE_OK ){ - pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); - nodeHashInsert(pRtree, pNode); - } - } - return rc; -} - -/* -** Release a reference to a node. If the node is dirty and the reference -** count drops to zero, the node data is written to the database. -*/ -static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ - int rc = SQLITE_OK; - if( pNode ){ - assert( pNode->nRef>0 ); - assert( pRtree->nNodeRef>0 ); - pNode->nRef--; - if( pNode->nRef==0 ){ - pRtree->nNodeRef--; - if( pNode->iNode==1 ){ - pRtree->iDepth = -1; - } - if( pNode->pParent ){ - rc = nodeRelease(pRtree, pNode->pParent); - } - if( rc==SQLITE_OK ){ - rc = nodeWrite(pRtree, pNode); - } - nodeHashDelete(pRtree, pNode); - sqlite3_free(pNode); - } - } - return rc; -} - -/* -** Return the 64-bit integer value associated with cell iCell of -** node pNode. If pNode is a leaf node, this is a rowid. If it is -** an internal node, then the 64-bit integer is a child page number. -*/ -static i64 nodeGetRowid( - Rtree *pRtree, /* The overall R-Tree */ - RtreeNode *pNode, /* The node from which to extract the ID */ - int iCell /* The cell index from which to extract the ID */ -){ - assert( iCellzData[4 + pRtree->nBytesPerCell*iCell]); -} - -/* -** Return coordinate iCoord from cell iCell in node pNode. -*/ -static void nodeGetCoord( - Rtree *pRtree, /* The overall R-Tree */ - RtreeNode *pNode, /* The node from which to extract a coordinate */ - int iCell, /* The index of the cell within the node */ - int iCoord, /* Which coordinate to extract */ - RtreeCoord *pCoord /* OUT: Space to write result to */ -){ - assert( iCellzData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); -} - -/* -** Deserialize cell iCell of node pNode. Populate the structure pointed -** to by pCell with the results. -*/ -static void nodeGetCell( - Rtree *pRtree, /* The overall R-Tree */ - RtreeNode *pNode, /* The node containing the cell to be read */ - int iCell, /* Index of the cell within the node */ - RtreeCell *pCell /* OUT: Write the cell contents here */ -){ - u8 *pData; - RtreeCoord *pCoord; - int ii = 0; - pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); - pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); - pCoord = pCell->aCoord; - do{ - readCoord(pData, &pCoord[ii]); - readCoord(pData+4, &pCoord[ii+1]); - pData += 8; - ii += 2; - }while( iinDim2 ); -} - - -/* Forward declaration for the function that does the work of -** the virtual table module xCreate() and xConnect() methods. -*/ -static int rtreeInit( - sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int -); - -/* -** Rtree virtual table module xCreate method. -*/ -static int rtreeCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1); -} - -/* -** Rtree virtual table module xConnect method. -*/ -static int rtreeConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0); -} - -/* -** Increment the r-tree reference count. -*/ -static void rtreeReference(Rtree *pRtree){ - pRtree->nBusy++; -} - -/* -** Decrement the r-tree reference count. When the reference count reaches -** zero the structure is deleted. -*/ -static void rtreeRelease(Rtree *pRtree){ - pRtree->nBusy--; - if( pRtree->nBusy==0 ){ - pRtree->inWrTrans = 0; - assert( pRtree->nCursor==0 ); - nodeBlobReset(pRtree); - assert( pRtree->nNodeRef==0 || pRtree->bCorrupt ); - sqlite3_finalize(pRtree->pWriteNode); - sqlite3_finalize(pRtree->pDeleteNode); - sqlite3_finalize(pRtree->pReadRowid); - sqlite3_finalize(pRtree->pWriteRowid); - sqlite3_finalize(pRtree->pDeleteRowid); - sqlite3_finalize(pRtree->pReadParent); - sqlite3_finalize(pRtree->pWriteParent); - sqlite3_finalize(pRtree->pDeleteParent); - sqlite3_finalize(pRtree->pWriteAux); - sqlite3_free(pRtree->zReadAuxSql); - sqlite3_free(pRtree); - } -} - -/* -** Rtree virtual table module xDisconnect method. -*/ -static int rtreeDisconnect(sqlite3_vtab *pVtab){ - rtreeRelease((Rtree *)pVtab); - return SQLITE_OK; -} - -/* -** Rtree virtual table module xDestroy method. -*/ -static int rtreeDestroy(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - int rc; - char *zCreate = sqlite3_mprintf( - "DROP TABLE '%q'.'%q_node';" - "DROP TABLE '%q'.'%q_rowid';" - "DROP TABLE '%q'.'%q_parent';", - pRtree->zDb, pRtree->zName, - pRtree->zDb, pRtree->zName, - pRtree->zDb, pRtree->zName - ); - if( !zCreate ){ - rc = SQLITE_NOMEM; - }else{ - nodeBlobReset(pRtree); - rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); - } - if( rc==SQLITE_OK ){ - rtreeRelease(pRtree); - } - - return rc; -} - -/* -** Rtree virtual table module xOpen method. -*/ -static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - int rc = SQLITE_NOMEM; - Rtree *pRtree = (Rtree *)pVTab; - RtreeCursor *pCsr; - - pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor)); - if( pCsr ){ - memset(pCsr, 0, sizeof(RtreeCursor)); - pCsr->base.pVtab = pVTab; - rc = SQLITE_OK; - pRtree->nCursor++; - } - *ppCursor = (sqlite3_vtab_cursor *)pCsr; - - return rc; -} - - -/* -** Reset a cursor back to its initial state. -*/ -static void resetCursor(RtreeCursor *pCsr){ - Rtree *pRtree = (Rtree *)(pCsr->base.pVtab); - int ii; - sqlite3_stmt *pStmt; - if( pCsr->aConstraint ){ - int i; /* Used to iterate through constraint array */ - for(i=0; inConstraint; i++){ - sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo; - if( pInfo ){ - if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser); - sqlite3_free(pInfo); - } - } - sqlite3_free(pCsr->aConstraint); - pCsr->aConstraint = 0; - } - for(ii=0; iiaNode[ii]); - sqlite3_free(pCsr->aPoint); - pStmt = pCsr->pReadAux; - memset(pCsr, 0, sizeof(RtreeCursor)); - pCsr->base.pVtab = (sqlite3_vtab*)pRtree; - pCsr->pReadAux = pStmt; - -} - -/* -** Rtree virtual table module xClose method. -*/ -static int rtreeClose(sqlite3_vtab_cursor *cur){ - Rtree *pRtree = (Rtree *)(cur->pVtab); - RtreeCursor *pCsr = (RtreeCursor *)cur; - assert( pRtree->nCursor>0 ); - resetCursor(pCsr); - sqlite3_finalize(pCsr->pReadAux); - sqlite3_free(pCsr); - pRtree->nCursor--; - if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){ - nodeBlobReset(pRtree); - } - return SQLITE_OK; -} - -/* -** Rtree virtual table module xEof method. -** -** Return non-zero if the cursor does not currently point to a valid -** record (i.e if the scan has finished), or zero otherwise. -*/ -static int rtreeEof(sqlite3_vtab_cursor *cur){ - RtreeCursor *pCsr = (RtreeCursor *)cur; - return pCsr->atEOF; -} - -/* -** Convert raw bits from the on-disk RTree record into a coordinate value. -** The on-disk format is big-endian and needs to be converted for little- -** endian platforms. The on-disk record stores integer coordinates if -** eInt is true and it stores 32-bit floating point records if eInt is -** false. a[] is the four bytes of the on-disk record to be decoded. -** Store the results in "r". -** -** There are five versions of this macro. The last one is generic. The -** other four are various architectures-specific optimizations. -*/ -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - c.u = _byteswap_ulong(*(u32*)a); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - c.u = __builtin_bswap32(*(u32*)a); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#elif SQLITE_BYTEORDER==1234 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - memcpy(&c.u,a,4); \ - c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \ - ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#elif SQLITE_BYTEORDER==4321 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - memcpy(&c.u,a,4); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#else -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16) \ - +((u32)a[2]<<8) + a[3]; \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#endif - -/* -** Check the RTree node or entry given by pCellData and p against the MATCH -** constraint pConstraint. -*/ -static int rtreeCallbackConstraint( - RtreeConstraint *pConstraint, /* The constraint to test */ - int eInt, /* True if RTree holding integer coordinates */ - u8 *pCellData, /* Raw cell content */ - RtreeSearchPoint *pSearch, /* Container of this cell */ - sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */ - int *peWithin /* OUT: visibility of the cell */ -){ - sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */ - int nCoord = pInfo->nCoord; /* No. of coordinates */ - int rc; /* Callback return code */ - RtreeCoord c; /* Translator union */ - sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */ - - assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); - assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); - - if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){ - pInfo->iRowid = readInt64(pCellData); - } - pCellData += 8; -#ifndef SQLITE_RTREE_INT_ONLY - if( eInt==0 ){ - switch( nCoord ){ - case 10: readCoord(pCellData+36, &c); aCoord[9] = c.f; - readCoord(pCellData+32, &c); aCoord[8] = c.f; - case 8: readCoord(pCellData+28, &c); aCoord[7] = c.f; - readCoord(pCellData+24, &c); aCoord[6] = c.f; - case 6: readCoord(pCellData+20, &c); aCoord[5] = c.f; - readCoord(pCellData+16, &c); aCoord[4] = c.f; - case 4: readCoord(pCellData+12, &c); aCoord[3] = c.f; - readCoord(pCellData+8, &c); aCoord[2] = c.f; - default: readCoord(pCellData+4, &c); aCoord[1] = c.f; - readCoord(pCellData, &c); aCoord[0] = c.f; - } - }else -#endif - { - switch( nCoord ){ - case 10: readCoord(pCellData+36, &c); aCoord[9] = c.i; - readCoord(pCellData+32, &c); aCoord[8] = c.i; - case 8: readCoord(pCellData+28, &c); aCoord[7] = c.i; - readCoord(pCellData+24, &c); aCoord[6] = c.i; - case 6: readCoord(pCellData+20, &c); aCoord[5] = c.i; - readCoord(pCellData+16, &c); aCoord[4] = c.i; - case 4: readCoord(pCellData+12, &c); aCoord[3] = c.i; - readCoord(pCellData+8, &c); aCoord[2] = c.i; - default: readCoord(pCellData+4, &c); aCoord[1] = c.i; - readCoord(pCellData, &c); aCoord[0] = c.i; - } - } - if( pConstraint->op==RTREE_MATCH ){ - int eWithin = 0; - rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo, - nCoord, aCoord, &eWithin); - if( eWithin==0 ) *peWithin = NOT_WITHIN; - *prScore = RTREE_ZERO; - }else{ - pInfo->aCoord = aCoord; - pInfo->iLevel = pSearch->iLevel - 1; - pInfo->rScore = pInfo->rParentScore = pSearch->rScore; - pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin; - rc = pConstraint->u.xQueryFunc(pInfo); - if( pInfo->eWithin<*peWithin ) *peWithin = pInfo->eWithin; - if( pInfo->rScore<*prScore || *prScorerScore; - } - } - return rc; -} - -/* -** Check the internal RTree node given by pCellData against constraint p. -** If this constraint cannot be satisfied by any child within the node, -** set *peWithin to NOT_WITHIN. -*/ -static void rtreeNonleafConstraint( - RtreeConstraint *p, /* The constraint to test */ - int eInt, /* True if RTree holds integer coordinates */ - u8 *pCellData, /* Raw cell content as appears on disk */ - int *peWithin /* Adjust downward, as appropriate */ -){ - sqlite3_rtree_dbl val; /* Coordinate value convert to a double */ - - /* p->iCoord might point to either a lower or upper bound coordinate - ** in a coordinate pair. But make pCellData point to the lower bound. - */ - pCellData += 8 + 4*(p->iCoord&0xfe); - - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE - || p->op==RTREE_FALSE ); - assert( FOUR_BYTE_ALIGNED(pCellData) ); - 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: - RTREE_DECODE_COORD(eInt, pCellData, val); - /* val now holds the lower bound of the coordinate pair */ - if( p->u.rValue>=val ) return; - break; - - 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; -} - -/* -** Check the leaf RTree cell given by pCellData against constraint p. -** If this constraint is not satisfied, set *peWithin to NOT_WITHIN. -** If the constraint is satisfied, leave *peWithin unchanged. -** -** The constraint is of the form: xN op $val -** -** The op is given by p->op. The xN is p->iCoord-th coordinate in -** pCellData. $val is given by p->u.rValue. -*/ -static void rtreeLeafConstraint( - RtreeConstraint *p, /* The constraint to test */ - int eInt, /* True if RTree holds integer coordinates */ - u8 *pCellData, /* Raw cell content as appears on disk */ - int *peWithin /* Adjust downward, as appropriate */ -){ - RtreeDValue xN; /* Coordinate value converted to a double */ - - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE - || p->op==RTREE_FALSE ); - pCellData += 8 + p->iCoord*4; - assert( FOUR_BYTE_ALIGNED(pCellData) ); - RTREE_DECODE_COORD(eInt, pCellData, xN); - switch( p->op ){ - case RTREE_TRUE: return; /* Always satisfied */ - case RTREE_FALSE: break; /* Never satisfied */ - case RTREE_LE: if( xN <= p->u.rValue ) return; break; - case RTREE_LT: if( xN < p->u.rValue ) return; break; - case RTREE_GE: if( xN >= p->u.rValue ) return; break; - case RTREE_GT: if( xN > p->u.rValue ) return; break; - default: if( xN == p->u.rValue ) return; break; - } - *peWithin = NOT_WITHIN; -} - -/* -** One of the cells in node pNode is guaranteed to have a 64-bit -** integer value equal to iRowid. Return the index of this cell. -*/ -static int nodeRowidIndex( - Rtree *pRtree, - RtreeNode *pNode, - i64 iRowid, - int *piIndex -){ - int ii; - int nCell = NCELL(pNode); - assert( nCell<200 ); - for(ii=0; iipParent; - if( ALWAYS(pParent) ){ - return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); - }else{ - *piIndex = -1; - return SQLITE_OK; - } -} - -/* -** Compare two search points. Return negative, zero, or positive if the first -** is less than, equal to, or greater than the second. -** -** The rScore is the primary key. Smaller rScore values come first. -** If the rScore is a tie, then use iLevel as the tie breaker with smaller -** iLevel values coming first. In this way, if rScore is the same for all -** SearchPoints, then iLevel becomes the deciding factor and the result -** is a depth-first search, which is the desired default behavior. -*/ -static int rtreeSearchPointCompare( - const RtreeSearchPoint *pA, - const RtreeSearchPoint *pB -){ - if( pA->rScorerScore ) return -1; - if( pA->rScore>pB->rScore ) return +1; - if( pA->iLeveliLevel ) return -1; - if( pA->iLevel>pB->iLevel ) return +1; - return 0; -} - -/* -** Interchange two search points in a cursor. -*/ -static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){ - RtreeSearchPoint t = p->aPoint[i]; - assert( iaPoint[i] = p->aPoint[j]; - p->aPoint[j] = t; - i++; j++; - if( i=RTREE_CACHE_SZ ){ - nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); - p->aNode[i] = 0; - }else{ - RtreeNode *pTemp = p->aNode[i]; - p->aNode[i] = p->aNode[j]; - p->aNode[j] = pTemp; - } - } -} - -/* -** Return the search point with the lowest current score. -*/ -static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){ - return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0; -} - -/* -** Get the RtreeNode for the search point with the lowest score. -*/ -static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){ - sqlite3_int64 id; - int ii = 1 - pCur->bPoint; - assert( ii==0 || ii==1 ); - assert( pCur->bPoint || pCur->nPoint ); - if( pCur->aNode[ii]==0 ){ - assert( pRC!=0 ); - id = ii ? pCur->aPoint[0].id : pCur->sPoint.id; - *pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]); - } - return pCur->aNode[ii]; -} - -/* -** Push a new element onto the priority queue -*/ -static RtreeSearchPoint *rtreeEnqueue( - RtreeCursor *pCur, /* The cursor */ - RtreeDValue rScore, /* Score for the new search point */ - u8 iLevel /* Level for the new search point */ -){ - int i, j; - RtreeSearchPoint *pNew; - if( pCur->nPoint>=pCur->nPointAlloc ){ - int nNew = pCur->nPointAlloc*2 + 8; - pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); - if( pNew==0 ) return 0; - pCur->aPoint = pNew; - pCur->nPointAlloc = nNew; - } - i = pCur->nPoint++; - pNew = pCur->aPoint + i; - pNew->rScore = rScore; - pNew->iLevel = iLevel; - assert( iLevel<=RTREE_MAX_DEPTH ); - while( i>0 ){ - RtreeSearchPoint *pParent; - j = (i-1)/2; - pParent = pCur->aPoint + j; - if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; - rtreeSearchPointSwap(pCur, j, i); - i = j; - pNew = pParent; - } - return pNew; -} - -/* -** Allocate a new RtreeSearchPoint and return a pointer to it. Return -** NULL if malloc fails. -*/ -static RtreeSearchPoint *rtreeSearchPointNew( - RtreeCursor *pCur, /* The cursor */ - RtreeDValue rScore, /* Score for the new search point */ - u8 iLevel /* Level for the new search point */ -){ - RtreeSearchPoint *pNew, *pFirst; - pFirst = rtreeSearchPointFirst(pCur); - pCur->anQueue[iLevel]++; - if( pFirst==0 - || pFirst->rScore>rScore - || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) - ){ - if( pCur->bPoint ){ - int ii; - pNew = rtreeEnqueue(pCur, rScore, iLevel); - if( pNew==0 ) return 0; - ii = (int)(pNew - pCur->aPoint) + 1; - assert( ii==1 ); - if( ALWAYS(iiaNode[ii]==0 ); - pCur->aNode[ii] = pCur->aNode[0]; - }else{ - nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); - } - pCur->aNode[0] = 0; - *pNew = pCur->sPoint; - } - pCur->sPoint.rScore = rScore; - pCur->sPoint.iLevel = iLevel; - pCur->bPoint = 1; - return &pCur->sPoint; - }else{ - return rtreeEnqueue(pCur, rScore, iLevel); - } -} - -#if 0 -/* Tracing routines for the RtreeSearchPoint queue */ -static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){ - if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); } - printf(" %d.%05lld.%02d %g %d", - p->iLevel, p->id, p->iCell, p->rScore, p->eWithin - ); - idx++; - if( idxaNode[idx]); - }else{ - printf("\n"); - } -} -static void traceQueue(RtreeCursor *pCur, const char *zPrefix){ - int ii; - printf("=== %9s ", zPrefix); - if( pCur->bPoint ){ - tracePoint(&pCur->sPoint, -1, pCur); - } - for(ii=0; iinPoint; ii++){ - if( ii>0 || pCur->bPoint ) printf(" "); - tracePoint(&pCur->aPoint[ii], ii, pCur); - } -} -# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B) -#else -# define RTREE_QUEUE_TRACE(A,B) /* no-op */ -#endif - -/* Remove the search point with the lowest current score. -*/ -static void rtreeSearchPointPop(RtreeCursor *p){ - int i, j, k, n; - i = 1 - p->bPoint; - assert( i==0 || i==1 ); - if( p->aNode[i] ){ - nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); - p->aNode[i] = 0; - } - if( p->bPoint ){ - p->anQueue[p->sPoint.iLevel]--; - p->bPoint = 0; - }else if( ALWAYS(p->nPoint) ){ - p->anQueue[p->aPoint[0].iLevel]--; - n = --p->nPoint; - p->aPoint[0] = p->aPoint[n]; - if( naNode[1] = p->aNode[n+1]; - p->aNode[n+1] = 0; - } - i = 0; - while( (j = i*2+1)aPoint[k], &p->aPoint[j])<0 ){ - if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){ - rtreeSearchPointSwap(p, i, k); - i = k; - }else{ - break; - } - }else{ - if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){ - rtreeSearchPointSwap(p, i, j); - i = j; - }else{ - break; - } - } - } - } -} - - -/* -** Continue the search on cursor pCur until the front of the queue -** contains an entry suitable for returning as a result-set row, -** or until the RtreeSearchPoint queue is empty, indicating that the -** query has completed. -*/ -static int rtreeStepToLeaf(RtreeCursor *pCur){ - RtreeSearchPoint *p; - Rtree *pRtree = RTREE_OF_CURSOR(pCur); - RtreeNode *pNode; - int eWithin; - int rc = SQLITE_OK; - int nCell; - int nConstraint = pCur->nConstraint; - int ii; - int eInt; - RtreeSearchPoint x; - - eInt = pRtree->eCoordType==RTREE_COORD_INT32; - while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ - u8 *pCellData; - pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); - if( rc ) return rc; - nCell = NCELL(pNode); - assert( nCell<200 ); - pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell); - while( p->iCellaConstraint + ii; - if( pConstraint->op>=RTREE_MATCH ){ - rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p, - &rScore, &eWithin); - if( rc ) return rc; - }else if( p->iLevel==1 ){ - rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin); - }else{ - rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin); - } - if( eWithin==NOT_WITHIN ){ - p->iCell++; - pCellData += pRtree->nBytesPerCell; - break; - } - } - if( eWithin==NOT_WITHIN ) continue; - p->iCell++; - x.iLevel = p->iLevel - 1; - if( x.iLevel ){ - x.id = readInt64(pCellData); - for(ii=0; iinPoint; ii++){ - if( pCur->aPoint[ii].id==x.id ){ - RTREE_IS_CORRUPT(pRtree); - return SQLITE_CORRUPT_VTAB; - } - } - x.iCell = 0; - }else{ - x.id = p->id; - x.iCell = p->iCell - 1; - } - if( p->iCell>=nCell ){ - RTREE_QUEUE_TRACE(pCur, "POP-S:"); - rtreeSearchPointPop(pCur); - } - if( rScoreeWithin = (u8)eWithin; - p->id = x.id; - p->iCell = x.iCell; - RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); - break; - } - if( p->iCell>=nCell ){ - RTREE_QUEUE_TRACE(pCur, "POP-Se:"); - rtreeSearchPointPop(pCur); - } - } - pCur->atEOF = p==0; - return SQLITE_OK; -} - -/* -** Rtree virtual table module xNext method. -*/ -static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - int rc = SQLITE_OK; - - /* Move to the next entry that matches the configured constraints. */ - RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); - if( pCsr->bAuxValid ){ - pCsr->bAuxValid = 0; - sqlite3_reset(pCsr->pReadAux); - } - rtreeSearchPointPop(pCsr); - rc = rtreeStepToLeaf(pCsr); - return rc; -} - -/* -** Rtree virtual table module xRowid method. -*/ -static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); - int rc = SQLITE_OK; - RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - if( rc==SQLITE_OK && ALWAYS(p) ){ - if( p->iCell>=NCELL(pNode) ){ - rc = SQLITE_ABORT; - }else{ - *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); - } - } - return rc; -} - -/* -** Rtree virtual table module xColumn method. -*/ -static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - Rtree *pRtree = (Rtree *)cur->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)cur; - RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); - RtreeCoord c; - int rc = SQLITE_OK; - RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - - if( rc ) return rc; - if( NEVER(p==0) ) return SQLITE_OK; - if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT; - if( i==0 ){ - sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); - }else if( i<=pRtree->nDim2 ){ - nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - sqlite3_result_double(ctx, c.f); - }else -#endif - { - assert( pRtree->eCoordType==RTREE_COORD_INT32 ); - sqlite3_result_int(ctx, c.i); - } - }else{ - if( !pCsr->bAuxValid ){ - if( pCsr->pReadAux==0 ){ - rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, - &pCsr->pReadAux, 0); - if( rc ) return rc; - } - sqlite3_bind_int64(pCsr->pReadAux, 1, - nodeGetRowid(pRtree, pNode, p->iCell)); - rc = sqlite3_step(pCsr->pReadAux); - if( rc==SQLITE_ROW ){ - pCsr->bAuxValid = 1; - }else{ - sqlite3_reset(pCsr->pReadAux); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - return rc; - } - } - sqlite3_result_value(ctx, - sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); - } - return SQLITE_OK; -} - -/* -** Use nodeAcquire() to obtain the leaf node containing the record with -** rowid iRowid. If successful, set *ppLeaf to point to the node and -** return SQLITE_OK. If there is no such record in the table, set -** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf -** to zero and return an SQLite error code. -*/ -static int findLeafNode( - Rtree *pRtree, /* RTree to search */ - i64 iRowid, /* The rowid searching for */ - RtreeNode **ppLeaf, /* Write the node here */ - sqlite3_int64 *piNode /* Write the node-id here */ -){ - int rc; - *ppLeaf = 0; - sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid); - if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ - i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); - if( piNode ) *piNode = iNode; - rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); - sqlite3_reset(pRtree->pReadRowid); - }else{ - rc = sqlite3_reset(pRtree->pReadRowid); - } - return rc; -} - -/* -** This function is called to configure the RtreeConstraint object passed -** as the second argument for a MATCH constraint. The value passed as the -** first argument to this function is the right-hand operand to the MATCH -** operator. -*/ -static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ - RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */ - sqlite3_rtree_query_info *pInfo; /* Callback information */ - - pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg"); - if( pSrc==0 ) return SQLITE_ERROR; - pInfo = (sqlite3_rtree_query_info*) - sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize ); - if( !pInfo ) return SQLITE_NOMEM; - memset(pInfo, 0, sizeof(*pInfo)); - pBlob = (RtreeMatchArg*)&pInfo[1]; - memcpy(pBlob, pSrc, pSrc->iSize); - pInfo->pContext = pBlob->cb.pContext; - pInfo->nParam = pBlob->nParam; - pInfo->aParam = pBlob->aParam; - pInfo->apSqlParam = pBlob->apSqlParam; - - if( pBlob->cb.xGeom ){ - pCons->u.xGeom = pBlob->cb.xGeom; - }else{ - pCons->op = RTREE_QUERY; - pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; - } - pCons->pInfo = pInfo; - return SQLITE_OK; -} - -SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); - -/* -** Rtree virtual table module xFilter method. -*/ -static int rtreeFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - RtreeNode *pRoot = 0; - int ii; - int rc = SQLITE_OK; - int iCell = 0; - - rtreeReference(pRtree); - - /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ - resetCursor(pCsr); - - pCsr->iStrategy = idxNum; - if( idxNum==1 ){ - /* Special case - lookup by rowid. */ - RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - RtreeSearchPoint *p; /* Search point for the leaf */ - i64 iRowid = sqlite3_value_int64(argv[0]); - i64 iNode = 0; - int eType = sqlite3_value_numeric_type(argv[0]); - if( eType==SQLITE_INTEGER - || (eType==SQLITE_FLOAT - && 0==sqlite3IntFloatCompare(iRowid,sqlite3_value_double(argv[0]))) - ){ - rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); - }else{ - rc = SQLITE_OK; - pLeaf = 0; - } - if( rc==SQLITE_OK && pLeaf!=0 ){ - p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); - assert( p!=0 ); /* Always returns pCsr->sPoint */ - pCsr->aNode[0] = pLeaf; - p->id = iNode; - p->eWithin = PARTLY_WITHIN; - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); - p->iCell = (u8)iCell; - RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); - }else{ - pCsr->atEOF = 1; - } - }else{ - /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array - ** with the configured constraints. - */ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - if( rc==SQLITE_OK && argc>0 ){ - pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc); - pCsr->nConstraint = argc; - if( !pCsr->aConstraint ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); - memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); - assert( (idxStr==0 && argc==0) - || (idxStr && (int)strlen(idxStr)==argc*2) ); - for(ii=0; iiaConstraint[ii]; - int eType = sqlite3_value_numeric_type(argv[ii]); - p->op = idxStr[ii*2]; - p->iCoord = idxStr[ii*2+1]-'0'; - if( p->op>=RTREE_MATCH ){ - /* A MATCH operator. The right-hand-side must be a blob that - ** can be cast into an RtreeMatchArg object. One created using - ** an sqlite3_rtree_geometry_callback() SQL user function. - */ - rc = deserializeGeometry(argv[ii], p); - if( rc!=SQLITE_OK ){ - break; - } - p->pInfo->nCoord = pRtree->nDim2; - p->pInfo->anQueue = pCsr->anQueue; - p->pInfo->mxLevel = pRtree->iDepth + 1; - }else if( eType==SQLITE_INTEGER ){ - sqlite3_int64 iVal = sqlite3_value_int64(argv[ii]); -#ifdef SQLITE_RTREE_INT_ONLY - p->u.rValue = iVal; -#else - p->u.rValue = (double)iVal; - if( iVal>=((sqlite3_int64)1)<<48 - || iVal<=-(((sqlite3_int64)1)<<48) - ){ - if( p->op==RTREE_LT ) p->op = RTREE_LE; - if( p->op==RTREE_GT ) p->op = RTREE_GE; - } -#endif - }else if( eType==SQLITE_FLOAT ){ -#ifdef SQLITE_RTREE_INT_ONLY - p->u.rValue = sqlite3_value_int64(argv[ii]); -#else - p->u.rValue = sqlite3_value_double(argv[ii]); -#endif - }else{ - p->u.rValue = RTREE_ZERO; - if( eType==SQLITE_NULL ){ - p->op = RTREE_FALSE; - }else if( p->op==RTREE_LT || p->op==RTREE_LE ){ - p->op = RTREE_TRUE; - }else{ - p->op = RTREE_FALSE; - } - } - } - } - } - 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( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */ - return SQLITE_NOMEM; - } - pNew->id = 1; - pNew->iCell = 0; - pNew->eWithin = PARTLY_WITHIN; - assert( pCsr->bPoint==1 ); - pCsr->aNode[0] = pRoot; - pRoot = 0; - RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); - rc = rtreeStepToLeaf(pCsr); - } - } - - nodeRelease(pRtree, pRoot); - rtreeRelease(pRtree); - return rc; -} - -/* -** Rtree virtual table module xBestIndex method. There are three -** table scan strategies to choose from (in order from most to -** least desirable): -** -** idxNum idxStr Strategy -** ------------------------------------------------ -** 1 Unused Direct lookup by rowid. -** 2 See below R-tree query or full-table scan. -** ------------------------------------------------ -** -** If strategy 1 is used, then idxStr is not meaningful. If strategy -** 2 is used, idxStr is formatted to contain 2 bytes for each -** constraint used. The first two bytes of idxStr correspond to -** the constraint in sqlite3_index_info.aConstraintUsage[] with -** (argvIndex==1) etc. -** -** The first of each pair of bytes in idxStr identifies the constraint -** operator as follows: -** -** Operator Byte Value -** ---------------------- -** = 0x41 ('A') -** <= 0x42 ('B') -** < 0x43 ('C') -** >= 0x44 ('D') -** > 0x45 ('E') -** MATCH 0x46 ('F') -** ---------------------- -** -** The second of each pair of bytes identifies the coordinate column -** to which the constraint applies. The leftmost coordinate column -** is 'a', the second from the left 'b' etc. -*/ -static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - Rtree *pRtree = (Rtree*)tab; - int rc = SQLITE_OK; - int ii; - int bMatch = 0; /* True if there exists a MATCH constraint */ - i64 nRow; /* Estimated rows returned by this scan */ - - int iIdx = 0; - char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; - memset(zIdxStr, 0, sizeof(zIdxStr)); - - /* Check if there exists a MATCH constraint - even an unusable one. If there - ** is, do not consider the lookup-by-rowid plan as using such a plan would - ** require the VDBE to evaluate the MATCH constraint, which is not currently - ** possible. */ - for(ii=0; iinConstraint; ii++){ - if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - bMatch = 1; - } - } - - assert( pIdxInfo->idxStr==0 ); - for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - - if( bMatch==0 && p->usable - && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ - ){ - /* We have an equality constraint on the rowid. Use strategy 1. */ - int jj; - for(jj=0; jjaConstraintUsage[jj].argvIndex = 0; - pIdxInfo->aConstraintUsage[jj].omit = 0; - } - pIdxInfo->idxNum = 1; - pIdxInfo->aConstraintUsage[ii].argvIndex = 1; - pIdxInfo->aConstraintUsage[jj].omit = 1; - - /* This strategy involves a two rowid lookups on an B-Tree structures - ** and then a linear search of an R-Tree node. This should be - ** considered almost as quick as a direct rowid lookup (for which - ** sqlite uses an internal cost of 0.0). It is expected to return - ** a single row. - */ - pIdxInfo->estimatedCost = 30.0; - pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; - return SQLITE_OK; - } - - if( p->usable - && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2) - || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) - ){ - u8 op; - u8 doOmit = 1; - switch( p->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; - case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; - case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break; - default: op = 0; break; - } - if( op ){ - zIdxStr[iIdx++] = op; - zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); - pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); - pIdxInfo->aConstraintUsage[ii].omit = doOmit; - } - } - } - - pIdxInfo->idxNum = 2; - pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 ){ - pIdxInfo->idxStr = sqlite3_malloc( iIdx+1 ); - if( pIdxInfo->idxStr==0 ){ - return SQLITE_NOMEM; - } - memcpy(pIdxInfo->idxStr, zIdxStr, iIdx+1); - } - - nRow = pRtree->nRowEst >> (iIdx/2); - pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; - pIdxInfo->estimatedRows = nRow; - - return rc; -} - -/* -** Return the N-dimensional volume of the cell stored in *p. -*/ -static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ - RtreeDValue area = (RtreeDValue)1; - assert( pRtree->nDim>=1 && pRtree->nDim<=5 ); -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - switch( pRtree->nDim ){ - case 5: area = p->aCoord[9].f - p->aCoord[8].f; - case 4: area *= p->aCoord[7].f - p->aCoord[6].f; - case 3: area *= p->aCoord[5].f - p->aCoord[4].f; - case 2: area *= p->aCoord[3].f - p->aCoord[2].f; - default: area *= p->aCoord[1].f - p->aCoord[0].f; - } - }else -#endif - { - switch( pRtree->nDim ){ - case 5: area = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i; - case 4: area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i; - case 3: area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i; - case 2: area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i; - default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i; - } - } - return area; -} - -/* -** Return the margin length of cell p. The margin length is the sum -** of the objects size in each dimension. -*/ -static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ - RtreeDValue margin = 0; - int ii = pRtree->nDim2 - 2; - do{ - margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); - ii -= 2; - }while( ii>=0 ); - return margin; -} - -/* -** Store the union of cells p1 and p2 in p1. -*/ -static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ - int ii = 0; - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - do{ - p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f); - p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f); - ii += 2; - }while( iinDim2 ); - }else{ - do{ - p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i); - p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i); - ii += 2; - }while( iinDim2 ); - } -} - -/* -** Return true if the area covered by p2 is a subset of the area covered -** by p1. False otherwise. -*/ -static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ - int ii; - if( pRtree->eCoordType==RTREE_COORD_INT32 ){ - for(ii=0; iinDim2; ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( a2[0].ia1[1].i ) return 0; - } - }else{ - for(ii=0; iinDim2; ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( a2[0].fa1[1].f ) return 0; - } - } - return 1; -} - -static RtreeDValue cellOverlap( - Rtree *pRtree, - RtreeCell *p, - RtreeCell *aCell, - int nCell -){ - int ii; - RtreeDValue overlap = RTREE_ZERO; - for(ii=0; iinDim2; jj+=2){ - RtreeDValue x1, x2; - x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); - x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); - if( x2iDepth-iHeight); ii++){ - int iCell; - sqlite3_int64 iBest = 0; - int bFound = 0; - RtreeDValue fMinGrowth = RTREE_ZERO; - RtreeDValue fMinArea = RTREE_ZERO; - int nCell = NCELL(pNode); - RtreeNode *pChild = 0; - - /* First check to see if there is are any cells in pNode that completely - ** contains pCell. If two or more cells in pNode completely contain pCell - ** then pick the smallest. - */ - for(iCell=0; iCellpParent ){ - RtreeNode *pParent = p->pParent; - RtreeCell cell; - int 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; - } - - nodeGetCell(pRtree, pParent, iCell, &cell); - if( !cellContains(pRtree, &cell, pCell) ){ - cellUnion(pRtree, &cell, pCell); - nodeOverwriteCell(pRtree, pParent, &cell, iCell); - } - - p = pParent; - } - return SQLITE_OK; -} - -/* -** Write mapping (iRowid->iNode) to the _rowid table. -*/ -static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){ - sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid); - sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode); - sqlite3_step(pRtree->pWriteRowid); - return sqlite3_reset(pRtree->pWriteRowid); -} - -/* -** Write mapping (iNode->iPar) to the _parent table. -*/ -static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){ - sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode); - sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar); - sqlite3_step(pRtree->pWriteParent); - return sqlite3_reset(pRtree->pWriteParent); -} - -static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int); - - - -/* -** Arguments aIdx, aCell and aSpare all point to arrays of size -** nIdx. The aIdx array contains the set of integers from 0 to -** (nIdx-1) in no particular order. This function sorts the values -** in aIdx according to dimension iDim of the cells in aCell. The -** minimum value of dimension iDim is considered first, the -** maximum used to break ties. -** -** The aSpare array is used as temporary working space by the -** sorting algorithm. -*/ -static void SortByDimension( - Rtree *pRtree, - int *aIdx, - int nIdx, - int iDim, - RtreeCell *aCell, - int *aSpare -){ - if( nIdx>1 ){ - - int iLeft = 0; - int iRight = 0; - - int nLeft = nIdx/2; - int nRight = nIdx-nLeft; - int *aLeft = aIdx; - int *aRight = &aIdx[nLeft]; - - SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare); - SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare); - - memcpy(aSpare, aLeft, sizeof(int)*nLeft); - aLeft = aSpare; - while( iLeftnDim+1)*(sizeof(int*)+nCell*sizeof(int)); - - aaSorted = (int **)sqlite3_malloc64(nByte); - if( !aaSorted ){ - return SQLITE_NOMEM; - } - - aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell]; - memset(aaSorted, 0, nByte); - for(ii=0; iinDim; ii++){ - int jj; - aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell]; - for(jj=0; jjnDim; ii++){ - RtreeDValue margin = RTREE_ZERO; - RtreeDValue fBestOverlap = RTREE_ZERO; - RtreeDValue fBestArea = RTREE_ZERO; - int iBestLeft = 0; - int nLeft; - - for( - nLeft=RTREE_MINCELLS(pRtree); - nLeft<=(nCell-RTREE_MINCELLS(pRtree)); - nLeft++ - ){ - RtreeCell left; - RtreeCell right; - int kk; - RtreeDValue overlap; - RtreeDValue area; - - memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); - memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); - for(kk=1; kk<(nCell-1); kk++){ - if( kk0 ){ - 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); -} - -static int SplitNode( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell, - int iHeight -){ - int i; - int newCellIsRight = 0; - - int rc = SQLITE_OK; - int nCell = NCELL(pNode); - RtreeCell *aCell; - int *aiUsed; - - RtreeNode *pLeft = 0; - RtreeNode *pRight = 0; - - RtreeCell leftbbox; - RtreeCell rightbbox; - - /* Allocate an array and populate it with a copy of pCell and - ** all cells from node pLeft. Then zero the original node. - */ - aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1)); - if( !aCell ){ - rc = SQLITE_NOMEM; - goto splitnode_out; - } - aiUsed = (int *)&aCell[nCell+1]; - memset(aiUsed, 0, sizeof(int)*(nCell+1)); - for(i=0; iiNode==1 ){ - pRight = nodeNew(pRtree, pNode); - pLeft = nodeNew(pRtree, pNode); - pRtree->iDepth++; - pNode->isDirty = 1; - writeInt16(pNode->zData, pRtree->iDepth); - }else{ - pLeft = pNode; - pRight = nodeNew(pRtree, pLeft->pParent); - pLeft->nRef++; - } - - if( !pLeft || !pRight ){ - rc = SQLITE_NOMEM; - goto splitnode_out; - } - - memset(pLeft->zData, 0, pRtree->iNodeSize); - memset(pRight->zData, 0, pRtree->iNodeSize); - - rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight, - &leftbbox, &rightbbox); - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - - /* Ensure both child nodes have node numbers assigned to them by calling - ** nodeWrite(). Node pRight always needs a node number, as it was created - ** by nodeNew() above. But node pLeft sometimes already has a node number. - ** In this case avoid the all to nodeWrite(). - */ - if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight)) - || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft))) - ){ - goto splitnode_out; - } - - rightbbox.iRowid = pRight->iNode; - leftbbox.iRowid = pLeft->iNode; - - if( pNode->iNode==1 ){ - rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1); - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - }else{ - RtreeNode *pParent = pLeft->pParent; - int iCell; - rc = nodeParentIndex(pRtree, pLeft, &iCell); - if( ALWAYS(rc==SQLITE_OK) ){ - nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); - rc = AdjustTree(pRtree, pParent, &leftbbox); - assert( rc==SQLITE_OK ); - } - if( NEVER(rc!=SQLITE_OK) ){ - goto splitnode_out; - } - } - if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ - goto splitnode_out; - } - - for(i=0; iiRowid ){ - newCellIsRight = 1; - } - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - } - if( pNode->iNode==1 ){ - for(i=0; iiRowid, pLeft, iHeight); - } - - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pRight); - pRight = 0; - } - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pLeft); - pLeft = 0; - } - -splitnode_out: - nodeRelease(pRtree, pRight); - nodeRelease(pRtree, pLeft); - sqlite3_free(aCell); - return rc; -} - -/* -** If node pLeaf is not the root of the r-tree and its pParent pointer is -** still NULL, load all ancestor nodes of pLeaf into memory and populate -** the pLeaf->pParent chain all the way up to the root node. -** -** This operation is required when a row is deleted (or updated - an update -** is implemented as a delete followed by an insert). SQLite provides the -** rowid of the row to delete, which can be used to find the leaf on which -** the entry resides (argument pLeaf). Once the leaf is located, this -** function is called to determine its ancestry. -*/ -static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ - int rc = SQLITE_OK; - RtreeNode *pChild = pLeaf; - while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){ - int rc2 = SQLITE_OK; /* sqlite3_reset() return code */ - sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode); - rc = sqlite3_step(pRtree->pReadParent); - if( rc==SQLITE_ROW ){ - RtreeNode *pTest; /* Used to test for reference loops */ - i64 iNode; /* Node number of parent node */ - - /* Before setting pChild->pParent, test that we are not creating a - ** loop of references (as we would if, say, pChild==pParent). We don't - ** want to do this as it leads to a memory leak when trying to delete - ** the referenced counted node structures. - */ - iNode = sqlite3_column_int64(pRtree->pReadParent, 0); - for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent); - if( pTest==0 ){ - rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent); - } - } - rc = sqlite3_reset(pRtree->pReadParent); - if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK && !pChild->pParent ){ - RTREE_IS_CORRUPT(pRtree); - rc = SQLITE_CORRUPT_VTAB; - } - pChild = pChild->pParent; - } - return rc; -} - -static int deleteCell(Rtree *, RtreeNode *, int, int); - -static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ - int rc; - int rc2; - RtreeNode *pParent = 0; - int iCell; - - assert( pNode->nRef==1 ); - - /* Remove the entry in the parent cell. */ - rc = nodeParentIndex(pRtree, pNode, &iCell); - if( rc==SQLITE_OK ){ - 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 ){ - rc = rc2; - } - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Remove the xxx_node entry. */ - sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode); - sqlite3_step(pRtree->pDeleteNode); - if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){ - return rc; - } - - /* Remove the xxx_parent entry. */ - sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode); - sqlite3_step(pRtree->pDeleteParent); - if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){ - return rc; - } - - /* Remove the node from the in-memory hash table and link it into - ** the Rtree.pDeleted list. Its contents will be re-inserted later on. - */ - nodeHashDelete(pRtree, pNode); - pNode->iNode = iHeight; - pNode->pNext = pRtree->pDeleted; - pNode->nRef++; - pRtree->pDeleted = pNode; - - return SQLITE_OK; -} - -static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ - RtreeNode *pParent = pNode->pParent; - int rc = SQLITE_OK; - if( pParent ){ - int ii; - int nCell = NCELL(pNode); - RtreeCell box; /* Bounding box for pNode */ - nodeGetCell(pRtree, pNode, 0, &box); - for(ii=1; iiiNode; - rc = nodeParentIndex(pRtree, pNode, &ii); - if( rc==SQLITE_OK ){ - nodeOverwriteCell(pRtree, pParent, &box, ii); - rc = fixBoundingBox(pRtree, pParent); - } - } - return rc; -} - -/* -** Delete the cell at index iCell of node pNode. After removing the -** cell, adjust the r-tree data structure if required. -*/ -static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){ - RtreeNode *pParent; - int rc; - - if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){ - return rc; - } - - /* Remove the cell from the node. This call just moves bytes around - ** the in-memory node image, so it cannot fail. - */ - nodeDeleteCell(pRtree, pNode, iCell); - - /* If the node is not the tree root and now has less than the minimum - ** number of cells, remove it from the tree. Otherwise, update the - ** cell in the parent node so that it tightly contains the updated - ** node. - */ - pParent = pNode->pParent; - assert( pParent || pNode->iNode==1 ); - if( pParent ){ - if( NCELL(pNode)0 ){ - RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid); - if( pChild ){ - nodeRelease(pRtree, pChild->pParent); - nodeReference(pNode); - pChild->pParent = pNode; - } - } - if( nodeInsertCell(pRtree, pNode, pCell) ){ - rc = SplitNode(pRtree, pNode, pCell, iHeight); - }else{ - rc = AdjustTree(pRtree, pNode, pCell); - if( ALWAYS(rc==SQLITE_OK) ){ - if( iHeight==0 ){ - rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); - }else{ - rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); - } - } - } - return rc; -} - -static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ - int ii; - int rc = SQLITE_OK; - int nCell = NCELL(pNode); - - for(ii=0; rc==SQLITE_OK && iiiNode currently contains - ** the height of the sub-tree headed by the cell. - */ - rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert); - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode); - rc2 = nodeRelease(pRtree, pInsert); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - return rc; -} - -/* -** Select a currently unused rowid for a new r-tree record. -*/ -static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ - int rc; - sqlite3_bind_null(pRtree->pWriteRowid, 1); - sqlite3_bind_null(pRtree->pWriteRowid, 2); - sqlite3_step(pRtree->pWriteRowid); - rc = sqlite3_reset(pRtree->pWriteRowid); - *piRowid = sqlite3_last_insert_rowid(pRtree->db); - return rc; -} - -/* -** Remove the entry with rowid=iDelete from the r-tree structure. -*/ -static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ - int rc; /* Return code */ - RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ - int iCell; /* Index of iDelete cell in pLeaf */ - RtreeNode *pRoot = 0; /* Root node of rtree structure */ - - - /* Obtain a reference to the root node to initialize Rtree.iDepth */ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - - /* Obtain a reference to the leaf node that contains the entry - ** about to be deleted. - */ - if( rc==SQLITE_OK ){ - rc = findLeafNode(pRtree, iDelete, &pLeaf, 0); - } - -#ifdef CORRUPT_DB - assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB ); -#endif - - /* Delete the cell in question from the leaf node. */ - if( rc==SQLITE_OK && pLeaf ){ - int rc2; - rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell); - if( rc==SQLITE_OK ){ - rc = deleteCell(pRtree, pLeaf, iCell, 0); - } - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - - /* Delete the corresponding entry in the _rowid table. */ - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete); - sqlite3_step(pRtree->pDeleteRowid); - rc = sqlite3_reset(pRtree->pDeleteRowid); - } - - /* Check if the root node now has exactly one child. If so, remove - ** it, schedule the contents of the child for reinsertion and - ** reduce the tree height by one. - ** - ** This is equivalent to copying the contents of the child into - ** the root node (the operation that Gutman's paper says to perform - ** in this scenario). - */ - if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ - int rc2; - RtreeNode *pChild = 0; - i64 iChild = nodeGetRowid(pRtree, pRoot, 0); - rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */ - if( rc==SQLITE_OK ){ - rc = removeNode(pRtree, pChild, pRtree->iDepth-1); - } - rc2 = nodeRelease(pRtree, pChild); - if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK ){ - pRtree->iDepth--; - writeInt16(pRoot->zData, pRtree->iDepth); - pRoot->isDirty = 1; - } - } - - /* Re-insert the contents of any underfull nodes removed from the tree. */ - for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ - if( rc==SQLITE_OK ){ - rc = reinsertNodeContent(pRtree, pLeaf); - } - pRtree->pDeleted = pLeaf->pNext; - pRtree->nNodeRef--; - sqlite3_free(pLeaf); - } - - /* Release the reference to the root node. */ - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pRoot); - }else{ - nodeRelease(pRtree, pRoot); - } - - return rc; -} - -/* -** Rounding constants for float->double conversion. -*/ -#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */ -#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */ - -#if !defined(SQLITE_RTREE_INT_ONLY) -/* -** Convert an sqlite3_value into an RtreeValue (presumably a float) -** while taking care to round toward negative or positive, respectively. -*/ -static RtreeValue rtreeValueDown(sqlite3_value *v){ - double d = sqlite3_value_double(v); - float f = (float)d; - if( f>d ){ - f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS)); - } - return f; -} -static RtreeValue rtreeValueUp(sqlite3_value *v){ - double d = sqlite3_value_double(v); - float f = (float)d; - if( fbase.zErrMsg) to an appropriate value and returns -** SQLITE_CONSTRAINT. -** -** Parameter iCol is the index of the leftmost column involved in the -** constraint failure. If it is 0, then the constraint that failed is -** the unique constraint on the id column. Otherwise, it is the rtree -** (c1<=c2) constraint on columns iCol and iCol+1 that has failed. -** -** If an OOM occurs, SQLITE_NOMEM is returned instead of SQLITE_CONSTRAINT. -*/ -static int rtreeConstraintError(Rtree *pRtree, int iCol){ - sqlite3_stmt *pStmt = 0; - char *zSql; - int rc; - - assert( iCol==0 || iCol%2 ); - zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", pRtree->zDb, pRtree->zName); - if( zSql ){ - rc = sqlite3_prepare_v2(pRtree->db, zSql, -1, &pStmt, 0); - }else{ - rc = SQLITE_NOMEM; - } - sqlite3_free(zSql); - - if( rc==SQLITE_OK ){ - if( iCol==0 ){ - const char *zCol = sqlite3_column_name(pStmt, 0); - pRtree->base.zErrMsg = sqlite3_mprintf( - "UNIQUE constraint failed: %s.%s", pRtree->zName, zCol - ); - }else{ - const char *zCol1 = sqlite3_column_name(pStmt, iCol); - const char *zCol2 = sqlite3_column_name(pStmt, iCol+1); - pRtree->base.zErrMsg = sqlite3_mprintf( - "rtree constraint failed: %s.(%s<=%s)", pRtree->zName, zCol1, zCol2 - ); - } - } - - sqlite3_finalize(pStmt); - return (rc==SQLITE_OK ? SQLITE_CONSTRAINT : rc); -} - - - -/* -** The xUpdate method for rtree module virtual tables. -*/ -static int rtreeUpdate( - sqlite3_vtab *pVtab, - int nData, - sqlite3_value **aData, - sqlite_int64 *pRowid -){ - Rtree *pRtree = (Rtree *)pVtab; - int rc = SQLITE_OK; - RtreeCell cell; /* New cell to insert if nData>1 */ - int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ - - if( pRtree->nNodeRef ){ - /* Unable to write to the btree while another cursor is reading from it, - ** since the write might do a rebalance which would disrupt the read - ** cursor. */ - return SQLITE_LOCKED_VTAB; - } - rtreeReference(pRtree); - assert(nData>=1); - - memset(&cell, 0, sizeof(cell)); - - /* Constraint handling. A write operation on an r-tree table may return - ** SQLITE_CONSTRAINT for two reasons: - ** - ** 1. A duplicate rowid value, or - ** 2. The supplied data violates the "x2>=x1" constraint. - ** - ** In the first case, if the conflict-handling mode is REPLACE, then - ** the conflicting row can be removed before proceeding. In the second - ** case, SQLITE_CONSTRAINT must be returned regardless of the - ** conflict-handling mode specified by the user. - */ - if( nData>1 ){ - int ii; - int nn = nData - 4; - - if( nn > pRtree->nDim2 ) nn = pRtree->nDim2; - /* Populate the cell.aCoord[] array. The first coordinate is aData[3]. - ** - ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared - ** with "column" that are interpreted as table constraints. - ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); - ** This problem was discovered after years of use, so we silently ignore - ** these kinds of misdeclared tables to avoid breaking any legacy. - */ - -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; iicell.aCoord[ii+1].f ){ - rc = rtreeConstraintError(pRtree, ii+1); - goto constraint; - } - } - }else -#endif - { - for(ii=0; iicell.aCoord[ii+1].i ){ - rc = rtreeConstraintError(pRtree, ii+1); - goto constraint; - } - } - } - - /* If a rowid value was supplied, check if it is already present in - ** the table. If so, the constraint has failed. */ - if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ - cell.iRowid = sqlite3_value_int64(aData[2]); - if( sqlite3_value_type(aData[0])==SQLITE_NULL - || sqlite3_value_int64(aData[0])!=cell.iRowid - ){ - int steprc; - sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); - steprc = sqlite3_step(pRtree->pReadRowid); - rc = sqlite3_reset(pRtree->pReadRowid); - if( SQLITE_ROW==steprc ){ - if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ - rc = rtreeDeleteRowid(pRtree, cell.iRowid); - }else{ - rc = rtreeConstraintError(pRtree, 0); - goto constraint; - } - } - } - bHaveRowid = 1; - } - } - - /* If aData[0] is not an SQL NULL value, it is the rowid of a - ** record to delete from the r-tree table. The following block does - ** just that. - */ - if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ - rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); - } - - /* If the aData[] array contains more than one element, elements - ** (aData[2]..aData[argc-1]) contain a new record to insert into - ** the r-tree structure. - */ - if( rc==SQLITE_OK && nData>1 ){ - /* Insert the new record into the r-tree */ - RtreeNode *pLeaf = 0; - - /* Figure out the rowid of the new row. */ - if( bHaveRowid==0 ){ - rc = rtreeNewRowid(pRtree, &cell.iRowid); - } - *pRowid = cell.iRowid; - - if( rc==SQLITE_OK ){ - rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); - } - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - if( rc==SQLITE_OK && pRtree->nAux ){ - sqlite3_stmt *pUp = pRtree->pWriteAux; - int jj; - sqlite3_bind_int64(pUp, 1, *pRowid); - for(jj=0; jjnAux; jj++){ - sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); - } - sqlite3_step(pUp); - rc = sqlite3_reset(pUp); - } - } - -constraint: - rtreeRelease(pRtree); - return rc; -} - -/* -** Called when a transaction starts. -*/ -static int rtreeBeginTransaction(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - assert( pRtree->inWrTrans==0 ); - pRtree->inWrTrans = 1; - return SQLITE_OK; -} - -/* -** Called when a transaction completes (either by COMMIT or ROLLBACK). -** The sqlite3_blob object should be released at this point. -*/ -static int rtreeEndTransaction(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - pRtree->inWrTrans = 0; - nodeBlobReset(pRtree); - return SQLITE_OK; -} -static int rtreeRollback(sqlite3_vtab *pVtab){ - return rtreeEndTransaction(pVtab); -} - -/* -** The xRename method for rtree module virtual tables. -*/ -static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){ - Rtree *pRtree = (Rtree *)pVtab; - int rc = SQLITE_NOMEM; - char *zSql = sqlite3_mprintf( - "ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";" - "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";" - "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";" - , pRtree->zDb, pRtree->zName, zNewName - , pRtree->zDb, pRtree->zName, zNewName - , pRtree->zDb, pRtree->zName, zNewName - ); - if( zSql ){ - nodeBlobReset(pRtree); - rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } - return rc; -} - -/* -** The xSavepoint method. -** -** This module does not need to do anything to support savepoints. However, -** it uses this hook to close any open blob handle. This is done because a -** DROP TABLE command - which fortunately always opens a savepoint - cannot -** succeed if there are any open blob handles. i.e. if the blob handle were -** not closed here, the following would fail: -** -** BEGIN; -** INSERT INTO rtree... -** DROP TABLE ; -- Would fail with SQLITE_LOCKED -** COMMIT; -*/ -static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ - Rtree *pRtree = (Rtree *)pVtab; - u8 iwt = pRtree->inWrTrans; - UNUSED_PARAMETER(iSavepoint); - pRtree->inWrTrans = 0; - nodeBlobReset(pRtree); - pRtree->inWrTrans = iwt; - return SQLITE_OK; -} - -/* -** This function populates the pRtree->nRowEst variable with an estimate -** of the number of rows in the virtual table. If possible, this is based -** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST. -*/ -static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){ - const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'"; - char *zSql; - sqlite3_stmt *p; - int rc; - i64 nRow = RTREE_MIN_ROWEST; - - rc = sqlite3_table_column_metadata( - db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 - ); - if( rc!=SQLITE_OK ){ - pRtree->nRowEst = RTREE_DEFAULT_ROWEST; - return rc==SQLITE_ERROR ? SQLITE_OK : rc; - } - zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0); - if( rc==SQLITE_OK ){ - if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0); - rc = sqlite3_finalize(p); - } - sqlite3_free(zSql); - } - pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST); - return rc; -} - - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int rtreeShadowName(const char *zName){ - static const char *azName[] = { - "node", "parent", "rowid" - }; - unsigned int i; - for(i=0; idb = db; - - if( isCreate ){ - char *zCreate; - sqlite3_str *p = sqlite3_str_new(db); - int ii; - sqlite3_str_appendf(p, - "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno", - zDb, zPrefix); - for(ii=0; iinAux; ii++){ - sqlite3_str_appendf(p,",a%d",ii); - } - sqlite3_str_appendf(p, - ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);", - zDb, zPrefix); - sqlite3_str_appendf(p, - "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);", - zDb, zPrefix); - sqlite3_str_appendf(p, - "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))", - zDb, zPrefix, pRtree->iNodeSize); - zCreate = sqlite3_str_finish(p); - if( !zCreate ){ - return SQLITE_NOMEM; - } - rc = sqlite3_exec(db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); - if( rc!=SQLITE_OK ){ - return rc; - } - } - - appStmt[0] = &pRtree->pWriteNode; - appStmt[1] = &pRtree->pDeleteNode; - appStmt[2] = &pRtree->pReadRowid; - appStmt[3] = &pRtree->pWriteRowid; - appStmt[4] = &pRtree->pDeleteRowid; - appStmt[5] = &pRtree->pReadParent; - appStmt[6] = &pRtree->pWriteParent; - appStmt[7] = &pRtree->pDeleteParent; - - rc = rtreeQueryStat1(db, pRtree); - for(i=0; inAux==0 ){ - zFormat = azSql[i]; - }else { - /* An UPSERT is very slightly slower than REPLACE, but it is needed - ** if there are auxiliary columns */ - zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)" - "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno"; - } - zSql = sqlite3_mprintf(zFormat, zDb, zPrefix); - if( zSql ){ - rc = sqlite3_prepare_v3(db, zSql, -1, f, appStmt[i], 0); - }else{ - rc = SQLITE_NOMEM; - } - sqlite3_free(zSql); - } - if( pRtree->nAux && rc!=SQLITE_NOMEM ){ - pRtree->zReadAuxSql = sqlite3_mprintf( - "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", - zDb, zPrefix); - if( pRtree->zReadAuxSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3_str *p = sqlite3_str_new(db); - int ii; - char *zSql; - sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); - for(ii=0; iinAux; ii++){ - if( ii ) sqlite3_str_append(p, ",", 1); -#ifdef SQLITE_ENABLE_GEOPOLY - if( iinAuxNotNull ){ - sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii); - }else -#endif - { - sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); - } - } - sqlite3_str_appendf(p, " WHERE rowid=?1"); - zSql = sqlite3_str_finish(p); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v3(db, zSql, -1, f, &pRtree->pWriteAux, 0); - sqlite3_free(zSql); - } - } - } - - return rc; -} - -/* -** The second argument to this function contains the text of an SQL statement -** that returns a single integer value. The statement is compiled and executed -** using database connection db. If successful, the integer value returned -** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error -** code is returned and the value of *piVal after returning is not defined. -*/ -static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ - int rc = SQLITE_NOMEM; - if( zSql ){ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *piVal = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_finalize(pStmt); - } - } - return rc; -} - -/* -** This function is called from within the xConnect() or xCreate() method to -** determine the node-size used by the rtree table being created or connected -** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. -** Otherwise, an SQLite error code is returned. -** -** If this function is being called as part of an xConnect(), then the rtree -** table already exists. In this case the node-size is determined by inspecting -** the root node of the tree. -** -** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. -** This ensures that each node is stored on a single database page. If the -** database page-size is so large that more than RTREE_MAXCELLS entries -** would fit in a single node, use a smaller node-size. -*/ -static int getNodeSize( - sqlite3 *db, /* Database handle */ - Rtree *pRtree, /* Rtree handle */ - int isCreate, /* True for xCreate, false for xConnect */ - char **pzErr /* OUT: Error message, if any */ -){ - int rc; - char *zSql; - if( isCreate ){ - int iPageSize = 0; - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); - rc = getIntFromStmt(db, zSql, &iPageSize); - if( rc==SQLITE_OK ){ - pRtree->iNodeSize = iPageSize-64; - if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)iNodeSize ){ - pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; - } - }else{ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - }else{ - zSql = sqlite3_mprintf( - "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", - pRtree->zDb, pRtree->zName - ); - rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - }else if( pRtree->iNodeSize<(512-64) ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"", - pRtree->zName); - } - } - - sqlite3_free(zSql); - return rc; -} - -/* -** Return the length of a token -*/ -static int rtreeTokenLength(const char *z){ - int dummy = 0; - return sqlite3GetToken((const unsigned char*)z,&dummy); -} - -/* -** This function is the implementation of both the xConnect and xCreate -** methods of the r-tree virtual table. -** -** argv[0] -> module name -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> column names... -*/ -static int rtreeInit( - sqlite3 *db, /* Database connection */ - void *pAux, /* One of the RTREE_COORD_* constants */ - int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ - sqlite3_vtab **ppVtab, /* OUT: New virtual table */ - char **pzErr, /* OUT: Error message, if any */ - int isCreate /* True for xCreate, false for xConnect */ -){ - int rc = SQLITE_OK; - Rtree *pRtree; - int nDb; /* Length of string argv[1] */ - int nName; /* Length of string argv[2] */ - int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); - sqlite3_str *pSql; - char *zSql; - int ii = 4; - int iErr; - - const char *aErrMsg[] = { - 0, /* 0 */ - "Wrong number of columns for an rtree table", /* 1 */ - "Too few columns for an rtree table", /* 2 */ - "Too many columns for an rtree table", /* 3 */ - "Auxiliary rtree columns must be last" /* 4 */ - }; - - assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */ - if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]); - return SQLITE_ERROR; - } - - sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - - - /* Allocate the sqlite3_vtab structure */ - nDb = (int)strlen(argv[1]); - nName = (int)strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); - if( !pRtree ){ - return SQLITE_NOMEM; - } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); - pRtree->nBusy = 1; - pRtree->base.pModule = &rtreeModule; - pRtree->zDb = (char *)&pRtree[1]; - pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->zNodeName = &pRtree->zName[nName+1]; - pRtree->eCoordType = (u8)eCoordType; - memcpy(pRtree->zDb, argv[1], nDb); - memcpy(pRtree->zName, argv[2], nName); - memcpy(pRtree->zNodeName, argv[2], nName); - memcpy(&pRtree->zNodeName[nName], "_node", 6); - - - /* Create/Connect to the underlying relational database schema. If - ** that is successful, call sqlite3_declare_vtab() to configure - ** the r-tree table schema. - */ - pSql = sqlite3_str_new(db); - sqlite3_str_appendf(pSql, "CREATE TABLE x(%.*s INT", - rtreeTokenLength(argv[3]), argv[3]); - for(ii=4; iinAux++; - sqlite3_str_appendf(pSql, ",%.*s", rtreeTokenLength(zArg+1), zArg+1); - }else if( pRtree->nAux>0 ){ - break; - }else{ - static const char *azFormat[] = {",%.*s REAL", ",%.*s INT"}; - pRtree->nDim2++; - sqlite3_str_appendf(pSql, azFormat[eCoordType], - rtreeTokenLength(zArg), zArg); - } - } - sqlite3_str_appendf(pSql, ");"); - zSql = sqlite3_str_finish(pSql); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else if( iinDim = pRtree->nDim2/2; - if( pRtree->nDim<1 ){ - iErr = 2; - }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){ - iErr = 3; - }else if( pRtree->nDim2 % 2 ){ - iErr = 1; - }else{ - iErr = 0; - } - if( iErr ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); - goto rtreeInit_fail; - } - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; - - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); - if( rc ) goto rtreeInit_fail; - rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); - if( rc ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - goto rtreeInit_fail; - } - - *ppVtab = (sqlite3_vtab *)pRtree; - return SQLITE_OK; - -rtreeInit_fail: - if( rc==SQLITE_OK ) rc = SQLITE_ERROR; - assert( *ppVtab==0 ); - assert( pRtree->nBusy==1 ); - rtreeRelease(pRtree); - return rc; -} - - -/* -** Implementation of a scalar function that decodes r-tree nodes to -** human readable strings. This can be used for debugging and analysis. -** -** The scalar function takes two arguments: (1) the number of dimensions -** to the rtree (between 1 and 5, inclusive) and (2) a blob of data containing -** an r-tree node. For a two-dimensional r-tree structure called "rt", to -** deserialize all nodes, a statement like: -** -** SELECT rtreenode(2, data) FROM rt_node; -** -** The human readable string takes the form of a Tcl list with one -** entry for each cell in the r-tree node. Each entry is itself a -** list, containing the 8-byte rowid/pageno followed by the -** *2 coordinates. -*/ -static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ - RtreeNode node; - Rtree tree; - int ii; - int nData; - int errCode; - sqlite3_str *pOut; - - UNUSED_PARAMETER(nArg); - memset(&node, 0, sizeof(RtreeNode)); - memset(&tree, 0, sizeof(Rtree)); - tree.nDim = (u8)sqlite3_value_int(apArg[0]); - if( tree.nDim<1 || tree.nDim>5 ) return; - tree.nDim2 = tree.nDim*2; - tree.nBytesPerCell = 8 + 8 * tree.nDim; - node.zData = (u8 *)sqlite3_value_blob(apArg[1]); - if( node.zData==0 ) return; - nData = sqlite3_value_bytes(apArg[1]); - if( nData<4 ) return; - if( nData0 ) sqlite3_str_append(pOut, " ", 1); - sqlite3_str_appendf(pOut, "{%lld", cell.iRowid); - for(jj=0; jjrc==SQLITE_OK ) pCheck->rc = rc; -} - -/* -** The second and subsequent arguments to this function are a format string -** and printf style arguments. This function formats the string and attempts -** to compile it as an SQL statement. -** -** If successful, a pointer to the new SQL statement is returned. Otherwise, -** NULL is returned and an error code left in RtreeCheck.rc. -*/ -static sqlite3_stmt *rtreeCheckPrepare( - RtreeCheck *pCheck, /* RtreeCheck object */ - const char *zFmt, ... /* Format string and trailing args */ -){ - va_list ap; - char *z; - sqlite3_stmt *pRet = 0; - - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - - if( pCheck->rc==SQLITE_OK ){ - if( z==0 ){ - pCheck->rc = SQLITE_NOMEM; - }else{ - pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); - } - } - - sqlite3_free(z); - va_end(ap); - return pRet; -} - -/* -** The second and subsequent arguments to this function are a printf() -** style format string and arguments. This function formats the string and -** appends it to the report being accumulated in pCheck. -*/ -static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){ - va_list ap; - va_start(ap, zFmt); - if( pCheck->rc==SQLITE_OK && pCheck->nErrrc = SQLITE_NOMEM; - }else{ - pCheck->zReport = sqlite3_mprintf("%z%s%z", - pCheck->zReport, (pCheck->zReport ? "\n" : ""), z - ); - if( pCheck->zReport==0 ){ - pCheck->rc = SQLITE_NOMEM; - } - } - pCheck->nErr++; - } - va_end(ap); -} - -/* -** This function is a no-op if there is already an error code stored -** in the RtreeCheck object indicated by the first argument. NULL is -** returned in this case. -** -** Otherwise, the contents of rtree table node iNode are loaded from -** the database and copied into a buffer obtained from sqlite3_malloc(). -** If no error occurs, a pointer to the buffer is returned and (*pnNode) -** is set to the size of the buffer in bytes. -** -** Or, if an error does occur, NULL is returned and an error code left -** in the RtreeCheck object. The final value of *pnNode is undefined in -** this case. -*/ -static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){ - u8 *pRet = 0; /* Return value */ - - if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){ - pCheck->pGetNode = rtreeCheckPrepare(pCheck, - "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", - pCheck->zDb, pCheck->zTab - ); - } - - if( pCheck->rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck->pGetNode, 1, iNode); - if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){ - int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0); - const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0); - pRet = sqlite3_malloc64(nNode); - if( pRet==0 ){ - pCheck->rc = SQLITE_NOMEM; - }else{ - memcpy(pRet, pNode, nNode); - *pnNode = nNode; - } - } - rtreeCheckReset(pCheck, pCheck->pGetNode); - if( pCheck->rc==SQLITE_OK && pRet==0 ){ - rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode); - } - } - - return pRet; -} - -/* -** This function is used to check that the %_parent (if bLeaf==0) or %_rowid -** (if bLeaf==1) table contains a specified entry. The schemas of the -** two tables are: -** -** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) -** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) -** -** In both cases, this function checks that there exists an entry with -** IPK value iKey and the second column set to iVal. -** -*/ -static void rtreeCheckMapping( - RtreeCheck *pCheck, /* RtreeCheck object */ - int bLeaf, /* True for a leaf cell, false for interior */ - i64 iKey, /* Key for mapping */ - i64 iVal /* Expected value for mapping */ -){ - int rc; - sqlite3_stmt *pStmt; - const char *azSql[2] = { - "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1", - "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1" - }; - - assert( bLeaf==0 || bLeaf==1 ); - if( pCheck->aCheckMapping[bLeaf]==0 ){ - pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck, - azSql[bLeaf], pCheck->zDb, pCheck->zTab - ); - } - if( pCheck->rc!=SQLITE_OK ) return; - - pStmt = pCheck->aCheckMapping[bLeaf]; - sqlite3_bind_int64(pStmt, 1, iKey); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_DONE ){ - rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table", - iKey, iVal, (bLeaf ? "%_rowid" : "%_parent") - ); - }else if( rc==SQLITE_ROW ){ - i64 ii = sqlite3_column_int64(pStmt, 0); - if( ii!=iVal ){ - rtreeCheckAppendMsg(pCheck, - "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)", - iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal - ); - } - } - rtreeCheckReset(pCheck, pStmt); -} - -/* -** Argument pCell points to an array of coordinates stored on an rtree page. -** This function checks that the coordinates are internally consistent (no -** x1>x2 conditions) and adds an error message to the RtreeCheck object -** if they are not. -** -** Additionally, if pParent is not NULL, then it is assumed to point to -** the array of coordinates on the parent page that bound the page -** containing pCell. In this case it is also verified that the two -** sets of coordinates are mutually consistent and an error message added -** to the RtreeCheck object if they are not. -*/ -static void rtreeCheckCellCoord( - RtreeCheck *pCheck, - i64 iNode, /* Node id to use in error messages */ - int iCell, /* Cell number to use in error messages */ - u8 *pCell, /* Pointer to cell coordinates */ - u8 *pParent /* Pointer to parent coordinates */ -){ - RtreeCoord c1, c2; - RtreeCoord p1, p2; - int i; - - for(i=0; inDim; i++){ - readCoord(&pCell[4*2*i], &c1); - readCoord(&pCell[4*(2*i + 1)], &c2); - - /* printf("%e, %e\n", c1.u.f, c2.u.f); */ - if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){ - rtreeCheckAppendMsg(pCheck, - "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode - ); - } - - if( pParent ){ - readCoord(&pParent[4*2*i], &p1); - readCoord(&pParent[4*(2*i + 1)], &p2); - - if( (pCheck->bInt ? c1.ibInt ? c2.i>p2.i : c2.f>p2.f) - ){ - rtreeCheckAppendMsg(pCheck, - "Dimension %d of cell %d on node %lld is corrupt relative to parent" - , i, iCell, iNode - ); - } - } - } -} - -/* -** Run rtreecheck() checks on node iNode, which is at depth iDepth within -** the r-tree structure. Argument aParent points to the array of coordinates -** that bound node iNode on the parent node. -** -** If any problems are discovered, an error message is appended to the -** report accumulated in the RtreeCheck object. -*/ -static void rtreeCheckNode( - RtreeCheck *pCheck, - int iDepth, /* Depth of iNode (0==leaf) */ - u8 *aParent, /* Buffer containing parent coords */ - i64 iNode /* Node to check */ -){ - u8 *aNode = 0; - int nNode = 0; - - assert( iNode==1 || aParent!=0 ); - assert( pCheck->nDim>0 ); - - aNode = rtreeCheckGetNode(pCheck, iNode, &nNode); - if( aNode ){ - if( nNode<4 ){ - rtreeCheckAppendMsg(pCheck, - "Node %lld is too small (%d bytes)", iNode, nNode - ); - }else{ - int nCell; /* Number of cells on page */ - int i; /* Used to iterate through cells */ - if( aParent==0 ){ - iDepth = readInt16(aNode); - if( iDepth>RTREE_MAX_DEPTH ){ - rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth); - sqlite3_free(aNode); - return; - } - } - nCell = readInt16(&aNode[2]); - if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){ - rtreeCheckAppendMsg(pCheck, - "Node %lld is too small for cell count of %d (%d bytes)", - iNode, nCell, nNode - ); - }else{ - for(i=0; inDim*2*4)]; - i64 iVal = readInt64(pCell); - rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); - - if( iDepth>0 ){ - rtreeCheckMapping(pCheck, 0, iVal, iNode); - rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); - pCheck->nNonLeaf++; - }else{ - rtreeCheckMapping(pCheck, 1, iVal, iNode); - pCheck->nLeaf++; - } - } - } - } - sqlite3_free(aNode); - } -} - -/* -** The second argument to this function must be either "_rowid" or -** "_parent". This function checks that the number of entries in the -** %_rowid or %_parent table is exactly nExpect. If not, it adds -** an error message to the report in the RtreeCheck object indicated -** by the first argument. -*/ -static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){ - if( pCheck->rc==SQLITE_OK ){ - sqlite3_stmt *pCount; - pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'", - pCheck->zDb, pCheck->zTab, zTbl - ); - if( pCount ){ - if( sqlite3_step(pCount)==SQLITE_ROW ){ - i64 nActual = sqlite3_column_int64(pCount, 0); - if( nActual!=nExpect ){ - rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table" - " - expected %lld, actual %lld" , zTbl, nExpect, nActual - ); - } - } - pCheck->rc = sqlite3_finalize(pCount); - } - } -} - -/* -** This function does the bulk of the work for the rtree integrity-check. -** It is called by rtreecheck(), which is the SQL function implementation. -*/ -static int rtreeCheckTable( - sqlite3 *db, /* Database handle to access db through */ - const char *zDb, /* Name of db ("main", "temp" etc.) */ - const char *zTab, /* Name of rtree table to check */ - char **pzReport /* OUT: sqlite3_malloc'd report text */ -){ - RtreeCheck check; /* Common context for various routines */ - sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ - int nAux = 0; /* Number of extra columns. */ - - /* Initialize the context object */ - memset(&check, 0, sizeof(check)); - check.db = db; - check.zDb = zDb; - check.zTab = zTab; - - /* Find the number of auxiliary columns */ - pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); - if( pStmt ){ - nAux = sqlite3_column_count(pStmt) - 2; - sqlite3_finalize(pStmt); - }else - if( check.rc!=SQLITE_NOMEM ){ - check.rc = SQLITE_OK; - } - - /* Find number of dimensions in the rtree table. */ - pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab); - if( pStmt ){ - int rc; - check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2; - if( check.nDim<1 ){ - rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree"); - }else if( SQLITE_ROW==sqlite3_step(pStmt) ){ - check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER); - } - rc = sqlite3_finalize(pStmt); - if( rc!=SQLITE_CORRUPT ) check.rc = rc; - } - - /* Do the actual integrity-check */ - if( check.nDim>=1 ){ - if( check.rc==SQLITE_OK ){ - rtreeCheckNode(&check, 0, 0, 1); - } - rtreeCheckCount(&check, "_rowid", check.nLeaf); - rtreeCheckCount(&check, "_parent", check.nNonLeaf); - } - - /* Finalize SQL statements used by the integrity-check */ - sqlite3_finalize(check.pGetNode); - sqlite3_finalize(check.aCheckMapping[0]); - sqlite3_finalize(check.aCheckMapping[1]); - - *pzReport = check.zReport; - return check.rc; -} - -/* -** Implementation of the xIntegrity method for Rtree. -*/ -static int rtreeIntegrity( - sqlite3_vtab *pVtab, /* The virtual table to check */ - const char *zSchema, /* Schema in which the virtual table lives */ - const char *zName, /* Name of the virtual table */ - int isQuick, /* True for a quick_check */ - char **pzErr /* Write results here */ -){ - Rtree *pRtree = (Rtree*)pVtab; - int rc; - assert( pzErr!=0 && *pzErr==0 ); - UNUSED_PARAMETER(zSchema); - UNUSED_PARAMETER(zName); - UNUSED_PARAMETER(isQuick); - rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, pzErr); - if( rc==SQLITE_OK && *pzErr ){ - *pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z", - pRtree->zDb, pRtree->zName, *pzErr); - if( (*pzErr)==0 ) rc = SQLITE_NOMEM; - } - return rc; -} - -/* -** Usage: -** -** rtreecheck(); -** rtreecheck(, ); -** -** Invoking this SQL function runs an integrity-check on the named rtree -** table. The integrity-check verifies the following: -** -** 1. For each cell in the r-tree structure (%_node table), that: -** -** a) for each dimension, (coord1 <= coord2). -** -** b) unless the cell is on the root node, that the cell is bounded -** by the parent cell on the parent node. -** -** c) for leaf nodes, that there is an entry in the %_rowid -** table corresponding to the cell's rowid value that -** points to the correct node. -** -** d) for cells on non-leaf nodes, that there is an entry in the -** %_parent table mapping from the cell's child node to the -** node that it resides on. -** -** 2. That there are the same number of entries in the %_rowid table -** as there are leaf cells in the r-tree structure, and that there -** is a leaf cell that corresponds to each entry in the %_rowid table. -** -** 3. That there are the same number of entries in the %_parent table -** as there are non-leaf cells in the r-tree structure, and that -** there is a non-leaf cell that corresponds to each entry in the -** %_parent table. -*/ -static void rtreecheck( - sqlite3_context *ctx, - int nArg, - sqlite3_value **apArg -){ - if( nArg!=1 && nArg!=2 ){ - sqlite3_result_error(ctx, - "wrong number of arguments to function rtreecheck()", -1 - ); - }else{ - int rc; - char *zReport = 0; - const char *zDb = (const char*)sqlite3_value_text(apArg[0]); - const char *zTab; - if( nArg==1 ){ - zTab = zDb; - zDb = "main"; - }else{ - zTab = (const char*)sqlite3_value_text(apArg[1]); - } - rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); - if( rc==SQLITE_OK ){ - sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT); - }else{ - sqlite3_result_error_code(ctx, rc); - } - sqlite3_free(zReport); - } -} - -/* Conditionally include the geopoly code */ -#ifdef SQLITE_ENABLE_GEOPOLY -/************** Include geopoly.c in the middle of rtree.c *******************/ -/************** Begin file geopoly.c *****************************************/ -/* -** 2018-05-25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file implements an alternative R-Tree virtual table that -** uses polygons to express the boundaries of 2-dimensional objects. -** -** This file is #include-ed onto the end of "rtree.c" so that it has -** access to all of the R-Tree internals. -*/ -/* #include */ - -/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ -#ifdef GEOPOLY_ENABLE_DEBUG - static int geo_debug = 0; -# define GEODEBUG(X) if(geo_debug)printf X -#else -# define GEODEBUG(X) -#endif - -/* Character class routines */ -#ifdef sqlite3Isdigit - /* Use the SQLite core versions if this routine is part of the - ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) -# define safe_isxdigit(x) sqlite3Isxdigit(x) -#else - /* Use the standard library for separate compilation */ -#include /* 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 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. -*/ -static const char geopolyIsSpace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x]) -#endif /* JSON NULL - back to original code */ - -/* Compiler and version */ -#ifndef GCC_VERSION -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif -#endif -#ifndef MSVC_VERSION -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# define MSVC_VERSION 0 -#endif -#endif - -/* Datatype for coordinates -*/ -typedef float GeoCoord; - -/* -** Internal representation of a polygon. -** -** The polygon consists of a sequence of vertexes. There is a line -** segment between each pair of vertexes, and one final segment from -** the last vertex back to the first. (This differs from the GeoJSON -** standard in which the final vertex is a repeat of the first.) -** -** The polygon follows the right-hand rule. The area to the right of -** each segment is "outside" and the area to the left is "inside". -** -** The on-disk representation consists of a 4-byte header followed by -** the values. The 4-byte header is: -** -** encoding (1 byte) 0=big-endian, 1=little-endian -** nvertex (3 bytes) Number of vertexes as a big-endian integer -** -** Enough space is allocated for 4 coordinates, to work around over-zealous -** warnings coming from some compiler (notably, clang). In reality, the size -** of each GeoPoly memory allocate is adjusted as necessary so that the -** GeoPoly.a[] array at the end is the appropriate size. -*/ -typedef struct GeoPoly GeoPoly; -struct GeoPoly { - int nVertex; /* Number of vertexes */ - unsigned char hdr[4]; /* Header for on-disk representation */ - GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ -}; - -/* The size of a memory allocation needed for a GeoPoly object sufficient -** to hold N coordinate pairs. -*/ -#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) - -/* Macros to access coordinates of a GeoPoly. -** We have to use these macros, rather than just say p->a[i] in order -** to silence (incorrect) UBSAN warnings if the array index is too large. -*/ -#define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2]) -#define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1]) - - -/* -** State of a parse of a GeoJSON input. -*/ -typedef struct GeoParse GeoParse; -struct GeoParse { - const unsigned char *z; /* Unparsed input */ - int nVertex; /* Number of vertexes in a[] */ - int nAlloc; /* Space allocated to a[] */ - int nErr; /* Number of errors encountered */ - GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ -}; - -/* Do a 4-byte byte swap */ -static void geopolySwab32(unsigned char *a){ - unsigned char t = a[0]; - a[0] = a[3]; - a[3] = t; - t = a[1]; - a[1] = a[2]; - a[2] = t; -} - -/* Skip whitespace. Return the next non-whitespace character. */ -static char geopolySkipSpace(GeoParse *p){ - while( fast_isspace(p->z[0]) ) p->z++; - return p->z[0]; -} - -/* Parse out a number. Write the value into *pVal if pVal!=0. -** return non-zero on success and zero if the next token is not a number. -*/ -static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ - char c = geopolySkipSpace(p); - const unsigned char *z = p->z; - int j = 0; - int seenDP = 0; - int seenE = 0; - if( c=='-' ){ - j = 1; - c = z[j]; - } - if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; - for(;; j++){ - c = z[j]; - if( safe_isdigit(c) ) continue; - if( c=='.' ){ - if( z[j-1]=='-' ) return 0; - if( seenDP ) return 0; - seenDP = 1; - continue; - } - if( c=='e' || c=='E' ){ - if( z[j-1]<'0' ) return 0; - if( seenE ) return -1; - seenDP = seenE = 1; - c = z[j+1]; - if( c=='+' || c=='-' ){ - j++; - c = z[j+1]; - } - if( c<'0' || c>'9' ) return 0; - continue; - } - break; - } - if( z[j-1]<'0' ) return 0; - if( pVal ){ -#ifdef SQLITE_AMALGAMATION - /* The sqlite3AtoF() routine is much much faster than atof(), if it - ** is available */ - double r; - (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); - *pVal = r; -#else - *pVal = (GeoCoord)atof((const char*)p->z); -#endif - } - p->z += j; - return 1; -} - -/* -** If the input is a well-formed JSON array of coordinates with at least -** four coordinates and where each coordinate is itself a two-value array, -** then convert the JSON into a GeoPoly object and return a pointer to -** that object. -** -** If any error occurs, return NULL. -*/ -static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ - GeoParse s; - int rc = SQLITE_OK; - memset(&s, 0, sizeof(s)); - s.z = z; - if( geopolySkipSpace(&s)=='[' ){ - s.z++; - while( geopolySkipSpace(&s)=='[' ){ - int ii = 0; - char c; - s.z++; - if( s.nVertex>=s.nAlloc ){ - GeoCoord *aNew; - s.nAlloc = s.nAlloc*2 + 16; - aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); - if( aNew==0 ){ - rc = SQLITE_NOMEM; - s.nErr++; - break; - } - s.a = aNew; - } - while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ - ii++; - if( ii==2 ) s.nVertex++; - c = geopolySkipSpace(&s); - s.z++; - if( c==',' ) continue; - if( c==']' && ii>=2 ) break; - s.nErr++; - rc = SQLITE_ERROR; - goto parse_json_err; - } - if( geopolySkipSpace(&s)==',' ){ - s.z++; - continue; - } - break; - } - if( geopolySkipSpace(&s)==']' - && s.nVertex>=4 - && s.a[0]==s.a[s.nVertex*2-2] - && s.a[1]==s.a[s.nVertex*2-1] - && (s.z++, geopolySkipSpace(&s)==0) - ){ - GeoPoly *pOut; - int x = 1; - s.nVertex--; /* Remove the redundant vertex at the end */ - pOut = sqlite3_malloc64( GEOPOLY_SZ((sqlite3_int64)s.nVertex) ); - x = 1; - if( pOut==0 ) goto parse_json_err; - pOut->nVertex = s.nVertex; - memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); - pOut->hdr[0] = *(unsigned char*)&x; - pOut->hdr[1] = (s.nVertex>>16)&0xff; - pOut->hdr[2] = (s.nVertex>>8)&0xff; - pOut->hdr[3] = s.nVertex&0xff; - sqlite3_free(s.a); - if( pRc ) *pRc = SQLITE_OK; - return pOut; - }else{ - s.nErr++; - rc = SQLITE_ERROR; - } - } -parse_json_err: - if( pRc ) *pRc = rc; - sqlite3_free(s.a); - return 0; -} - -/* -** Given a function parameter, try to interpret it as a polygon, either -** in the binary format or JSON text. Compute a GeoPoly object and -** return a pointer to that object. Or if the input is not a well-formed -** polygon, put an error message in sqlite3_context and return NULL. -*/ -static GeoPoly *geopolyFuncParam( - sqlite3_context *pCtx, /* Context for error messages */ - sqlite3_value *pVal, /* The value to decode */ - int *pRc /* Write error here */ -){ - GeoPoly *p = 0; - int nByte; - testcase( pCtx==0 ); - if( sqlite3_value_type(pVal)==SQLITE_BLOB - && (nByte = sqlite3_value_bytes(pVal))>=(int)(4+6*sizeof(GeoCoord)) - ){ - const unsigned char *a = sqlite3_value_blob(pVal); - int nVertex; - if( a==0 ){ - if( pCtx ) 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 - ){ - p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); - if( p==0 ){ - if( pRc ) *pRc = SQLITE_NOMEM; - if( pCtx ) sqlite3_result_error_nomem(pCtx); - }else{ - int x = 1; - p->nVertex = nVertex; - memcpy(p->hdr, a, nByte); - if( a[0] != *(unsigned char*)&x ){ - int ii; - for(ii=0; iihdr[0] ^= 1; - } - } - } - if( pRc ) *pRc = SQLITE_OK; - return p; - }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ - const unsigned char *zJson = sqlite3_value_text(pVal); - if( zJson==0 ){ - if( pRc ) *pRc = SQLITE_NOMEM; - return 0; - } - return geopolyParseJson(zJson, pRc); - }else{ - if( pRc ) *pRc = SQLITE_ERROR; - return 0; - } -} - -/* -** Implementation of the geopoly_blob(X) function. -** -** If the input is a well-formed Geopoly BLOB or JSON string -** then return the BLOB representation of the polygon. Otherwise -** return NULL. -*/ -static void geopolyBlobFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** SQL function: geopoly_json(X) -** -** Interpret X as a polygon and render it as a JSON array -** of coordinates. Or, if X is not a valid polygon, return NULL. -*/ -static void geopolyJsonFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3 *db = sqlite3_context_db_handle(context); - sqlite3_str *x = sqlite3_str_new(db); - int i; - sqlite3_str_append(x, "[", 1); - for(i=0; inVertex; i++){ - sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i)); - } - sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0)); - sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); - sqlite3_free(p); - } -} - -/* -** SQL function: geopoly_svg(X, ....) -** -** Interpret X as a polygon and render it as a SVG . -** Additional arguments are added as attributes to the . -*/ -static void geopolySvgFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p; - if( argc<1 ) return; - p = geopolyFuncParam(context, argv[0], 0); - if( p ){ - sqlite3 *db = sqlite3_context_db_handle(context); - sqlite3_str *x = sqlite3_str_new(db); - int i; - char cSep = '\''; - sqlite3_str_appendf(x, ""); - sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); - sqlite3_free(p); - } -} - -/* -** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) -** -** Transform and/or translate a polygon as follows: -** -** x1 = A*x0 + B*y0 + E -** y1 = C*x0 + D*y0 + F -** -** For a translation: -** -** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) -** -** Rotate by R around the point (0,0): -** -** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) -*/ -static void geopolyXformFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - double A = sqlite3_value_double(argv[1]); - double B = sqlite3_value_double(argv[2]); - double C = sqlite3_value_double(argv[3]); - double D = sqlite3_value_double(argv[4]); - double E = sqlite3_value_double(argv[5]); - double F = sqlite3_value_double(argv[6]); - GeoCoord x1, y1, x0, y0; - int ii; - (void)argc; - if( p ){ - for(ii=0; iinVertex; ii++){ - x0 = GeoX(p,ii); - y0 = GeoY(p,ii); - x1 = (GeoCoord)(A*x0 + B*y0 + E); - y1 = (GeoCoord)(C*x0 + D*y0 + F); - GeoX(p,ii) = x1; - GeoY(p,ii) = y1; - } - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** Compute the area enclosed by the polygon. -** -** This routine can also be used to detect polygons that rotate in -** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). -** This routine returns a negative value for clockwise (CW) polygons. -*/ -static double geopolyArea(GeoPoly *p){ - double rArea = 0.0; - int ii; - for(ii=0; iinVertex-1; ii++){ - rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */ - * (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */ - * 0.5; - } - rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */ - * (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */ - * 0.5; - return rArea; -} - -/* -** Implementation of the geopoly_area(X) function. -** -** If the input is a well-formed Geopoly BLOB then return the area -** enclosed by the polygon. If the polygon circulates clockwise instead -** of counterclockwise (as it should) then return the negative of the -** enclosed area. Otherwise return NULL. -*/ -static void geopolyAreaFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3_result_double(context, geopolyArea(p)); - sqlite3_free(p); - } -} - -/* -** Implementation of the geopoly_ccw(X) function. -** -** If the rotation of polygon X is clockwise (incorrect) instead of -** counter-clockwise (the correct winding order according to RFC7946) -** then reverse the order of the vertexes in polygon X. -** -** In other words, this routine returns a CCW polygon regardless of the -** winding order of its input. -** -** Use this routine to sanitize historical inputs that that sometimes -** contain polygons that wind in the wrong direction. -*/ -static void geopolyCcwFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - if( geopolyArea(p)<0.0 ){ - int ii, jj; - for(ii=1, jj=p->nVertex-1; iihdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -#define GEOPOLY_PI 3.1415926535897932385 - -/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi -*/ -static double geopolySine(double r){ - assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); - if( r>=1.5*GEOPOLY_PI ){ - r -= 2.0*GEOPOLY_PI; - } - if( r>=0.5*GEOPOLY_PI ){ - return -geopolySine(r-GEOPOLY_PI); - }else{ - double r2 = r*r; - double r3 = r2*r; - double r5 = r3*r2; - return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; - } -} - -/* -** Function: geopoly_regular(X,Y,R,N) -** -** Construct a simple, convex, regular polygon centered at X, Y -** with circumradius R and with N sides. -*/ -static void geopolyRegularFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double x = sqlite3_value_double(argv[0]); - double y = sqlite3_value_double(argv[1]); - double r = sqlite3_value_double(argv[2]); - int n = sqlite3_value_int(argv[3]); - int i; - GeoPoly *p; - (void)argc; - - if( n<3 || r<=0.0 ) return; - if( n>1000 ) n = 1000; - p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); - if( p==0 ){ - sqlite3_result_error_nomem(context); - return; - } - i = 1; - p->hdr[0] = *(unsigned char*)&i; - p->hdr[1] = 0; - p->hdr[2] = (n>>8)&0xff; - p->hdr[3] = n&0xff; - for(i=0; ihdr, 4+8*n, SQLITE_TRANSIENT); - sqlite3_free(p); -} - -/* -** If pPoly is a polygon, compute its bounding box. Then: -** -** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL -** (2) otherwise, compute a GeoPoly for the bounding box and return the -** new GeoPoly -** -** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from -** the bounding box in aCoord and return a pointer to that GeoPoly. -*/ -static GeoPoly *geopolyBBox( - sqlite3_context *context, /* For recording the error */ - sqlite3_value *pPoly, /* The polygon */ - RtreeCoord *aCoord, /* Results here */ - int *pRc /* Error code here */ -){ - GeoPoly *pOut = 0; - GeoPoly *p; - float mnX, mxX, mnY, mxY; - if( pPoly==0 && aCoord!=0 ){ - p = 0; - mnX = aCoord[0].f; - mxX = aCoord[1].f; - mnY = aCoord[2].f; - mxY = aCoord[3].f; - goto geopolyBboxFill; - }else{ - p = geopolyFuncParam(context, pPoly, pRc); - } - if( p ){ - int ii; - mnX = mxX = GeoX(p,0); - mnY = mxY = GeoY(p,0); - for(ii=1; iinVertex; ii++){ - double r = GeoX(p,ii); - if( rmxX ) mxX = (float)r; - r = GeoY(p,ii); - if( rmxY ) mxY = (float)r; - } - if( pRc ) *pRc = SQLITE_OK; - if( aCoord==0 ){ - geopolyBboxFill: - pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4)); - if( pOut==0 ){ - sqlite3_free(p); - if( context ) sqlite3_result_error_nomem(context); - if( pRc ) *pRc = SQLITE_NOMEM; - return 0; - } - pOut->nVertex = 4; - ii = 1; - pOut->hdr[0] = *(unsigned char*)ⅈ - pOut->hdr[1] = 0; - pOut->hdr[2] = 0; - pOut->hdr[3] = 4; - GeoX(pOut,0) = mnX; - GeoY(pOut,0) = mnY; - GeoX(pOut,1) = mxX; - GeoY(pOut,1) = mnY; - GeoX(pOut,2) = mxX; - GeoY(pOut,2) = mxY; - GeoX(pOut,3) = mnX; - GeoY(pOut,3) = mxY; - }else{ - sqlite3_free(p); - aCoord[0].f = mnX; - aCoord[1].f = mxX; - aCoord[2].f = mnY; - aCoord[3].f = mxY; - } - }else if( aCoord ){ - memset(aCoord, 0, sizeof(RtreeCoord)*4); - } - return pOut; -} - -/* -** Implementation of the geopoly_bbox(X) SQL function. -*/ -static void geopolyBBoxFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); - (void)argc; - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** State vector for the geopoly_group_bbox() aggregate function. -*/ -typedef struct GeoBBox GeoBBox; -struct GeoBBox { - int isInit; - RtreeCoord a[4]; -}; - - -/* -** Implementation of the geopoly_group_bbox(X) aggregate SQL function. -*/ -static void geopolyBBoxStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - RtreeCoord a[4]; - int rc = SQLITE_OK; - (void)argc; - (void)geopolyBBox(context, argv[0], a, &rc); - if( rc==SQLITE_OK ){ - GeoBBox *pBBox; - pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); - if( pBBox==0 ) return; - if( pBBox->isInit==0 ){ - pBBox->isInit = 1; - memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); - }else{ - if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; - if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; - if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; - if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; - } - } -} -static void geopolyBBoxFinal( - sqlite3_context *context -){ - GeoPoly *p; - GeoBBox *pBBox; - pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); - if( pBBox==0 ) return; - p = geopolyBBox(context, 0, pBBox->a, 0); - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - - -/* -** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). -** Returns: -** -** +2 x0,y0 is on the line segment -** -** +1 x0,y0 is beneath line segment -** -** 0 x0,y0 is not on or beneath the line segment or the line segment -** is vertical and x0,y0 is not on the line segment -** -** The left-most coordinate min(x1,x2) is not considered to be part of -** the line segment for the purposes of this analysis. -*/ -static int pointBeneathLine( - double x0, double y0, - double x1, double y1, - double x2, double y2 -){ - double y; - if( x0==x1 && y0==y1 ) return 2; - if( x1x2 ) return 0; - }else if( x1>x2 ){ - if( x0<=x2 || x0>x1 ) return 0; - }else{ - /* Vertical line segment */ - if( x0!=x1 ) return 0; - if( y0y1 && y0>y2 ) return 0; - return 2; - } - y = y1 + (y2-y1)*(x0-x1)/(x2-x1); - if( y0==y ) return 2; - if( y0nVertex-1; ii++){ - v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), - GeoX(p1,ii+1),GeoY(p1,ii+1)); - if( v==2 ) break; - cnt += v; - } - if( v!=2 ){ - v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), - GeoX(p1,0), GeoY(p1,0)); - } - if( v==2 ){ - sqlite3_result_int(context, 1); - }else if( ((v+cnt)&1)==0 ){ - sqlite3_result_int(context, 0); - }else{ - sqlite3_result_int(context, 2); - } - sqlite3_free(p1); -} - -/* Forward declaration */ -static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); - -/* -** SQL function: geopoly_within(P1,P2) -** -** Return +2 if P1 and P2 are the same polygon -** Return +1 if P2 is contained within P1 -** Return 0 if any part of P2 is on the outside of P1 -** -*/ -static void geopolyWithinFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); - GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); - (void)argc; - if( p1 && p2 ){ - int x = geopolyOverlap(p1, p2); - if( x<0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); - } - } - sqlite3_free(p1); - sqlite3_free(p2); -} - -/* Objects used by the overlap algorithm. */ -typedef struct GeoEvent GeoEvent; -typedef struct GeoSegment GeoSegment; -typedef struct GeoOverlap GeoOverlap; -struct GeoEvent { - double x; /* X coordinate at which event occurs */ - int eType; /* 0 for ADD, 1 for REMOVE */ - GeoSegment *pSeg; /* The segment to be added or removed */ - GeoEvent *pNext; /* Next event in the sorted list */ -}; -struct GeoSegment { - double C, B; /* y = C*x + B */ - double y; /* Current y value */ - float y0; /* Initial y value */ - unsigned char side; /* 1 for p1, 2 for p2 */ - unsigned int idx; /* Which segment within the side */ - GeoSegment *pNext; /* Next segment in a list sorted by y */ -}; -struct GeoOverlap { - GeoEvent *aEvent; /* Array of all events */ - GeoSegment *aSegment; /* Array of all segments */ - int nEvent; /* Number of events */ - int nSegment; /* Number of segments */ -}; - -/* -** Add a single segment and its associated events. -*/ -static void geopolyAddOneSegment( - GeoOverlap *p, - GeoCoord x0, - GeoCoord y0, - GeoCoord x1, - GeoCoord y1, - unsigned char side, - unsigned int idx -){ - GeoSegment *pSeg; - GeoEvent *pEvent; - if( x0==x1 ) return; /* Ignore vertical segments */ - if( x0>x1 ){ - GeoCoord t = x0; - x0 = x1; - x1 = t; - t = y0; - y0 = y1; - y1 = t; - } - pSeg = p->aSegment + p->nSegment; - p->nSegment++; - pSeg->C = (y1-y0)/(x1-x0); - pSeg->B = y1 - x1*pSeg->C; - pSeg->y0 = y0; - pSeg->side = side; - pSeg->idx = idx; - pEvent = p->aEvent + p->nEvent; - p->nEvent++; - pEvent->x = x0; - pEvent->eType = 0; - pEvent->pSeg = pSeg; - pEvent = p->aEvent + p->nEvent; - p->nEvent++; - pEvent->x = x1; - pEvent->eType = 1; - pEvent->pSeg = pSeg; -} - - - -/* -** Insert all segments and events for polygon pPoly. -*/ -static void geopolyAddSegments( - GeoOverlap *p, /* Add segments to this Overlap object */ - GeoPoly *pPoly, /* Take all segments from this polygon */ - unsigned char side /* The side of pPoly */ -){ - unsigned int i; - GeoCoord *x; - for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ - x = &GeoX(pPoly,i); - geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); - } - x = &GeoX(pPoly,i); - geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); -} - -/* -** Merge two lists of sorted events by X coordinate -*/ -static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ - GeoEvent head, *pLast; - head.pNext = 0; - pLast = &head; - while( pRight && pLeft ){ - if( pRight->x <= pLeft->x ){ - pLast->pNext = pRight; - pLast = pRight; - pRight = pRight->pNext; - }else{ - pLast->pNext = pLeft; - pLast = pLeft; - pLeft = pLeft->pNext; - } - } - pLast->pNext = pRight ? pRight : pLeft; - return head.pNext; -} - -/* -** Sort an array of nEvent event objects into a list. -*/ -static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ - int mx = 0; - int i, j; - GeoEvent *p; - GeoEvent *a[50]; - for(i=0; ipNext = 0; - for(j=0; j=mx ) mx = j+1; - } - p = 0; - for(i=0; iy - pLeft->y; - if( r==0.0 ) r = pRight->C - pLeft->C; - if( r<0.0 ){ - pLast->pNext = pRight; - pLast = pRight; - pRight = pRight->pNext; - }else{ - pLast->pNext = pLeft; - pLast = pLeft; - pLeft = pLeft->pNext; - } - } - pLast->pNext = pRight ? pRight : pLeft; - return head.pNext; -} - -/* -** Sort a list of GeoSegments in order of increasing Y and in the event of -** a tie, increasing C (slope). -*/ -static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ - int mx = 0; - int i; - GeoSegment *p; - GeoSegment *a[50]; - while( pList ){ - p = pList; - pList = pList->pNext; - p->pNext = 0; - for(i=0; i=mx ) mx = i+1; - } - p = 0; - for(i=0; inVertex + p2->nVertex + 2; - GeoOverlap *p; - sqlite3_int64 nByte; - GeoEvent *pThisEvent; - double rX; - int rc = 0; - int needSort = 0; - GeoSegment *pActive = 0; - GeoSegment *pSeg; - unsigned char aOverlap[4]; - - nByte = sizeof(GeoEvent)*nVertex*2 - + sizeof(GeoSegment)*nVertex - + sizeof(GeoOverlap); - p = sqlite3_malloc64( nByte ); - if( p==0 ) return -1; - p->aEvent = (GeoEvent*)&p[1]; - p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; - p->nEvent = p->nSegment = 0; - geopolyAddSegments(p, p1, 1); - geopolyAddSegments(p, p2, 2); - pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); - rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0; - memset(aOverlap, 0, sizeof(aOverlap)); - while( pThisEvent ){ - if( pThisEvent->x!=rX ){ - GeoSegment *pPrev = 0; - int iMask = 0; - GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); - rX = pThisEvent->x; - if( needSort ){ - GEODEBUG(("SORT\n")); - pActive = geopolySortSegmentsByYAndC(pActive); - needSort = 0; - } - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - if( pPrev ){ - if( pPrev->y!=pSeg->y ){ - GEODEBUG(("MASK: %d\n", iMask)); - aOverlap[iMask] = 1; - } - } - iMask ^= pSeg->side; - pPrev = pSeg; - } - pPrev = 0; - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - double y = pSeg->C*rX + pSeg->B; - GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); - pSeg->y = y; - if( pPrev ){ - if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ - rc = 1; - GEODEBUG(("Crossing: %d.%d and %d.%d\n", - pPrev->side, pPrev->idx, - pSeg->side, pSeg->idx)); - goto geopolyOverlapDone; - }else if( pPrev->y!=pSeg->y ){ - GEODEBUG(("MASK: %d\n", iMask)); - aOverlap[iMask] = 1; - } - } - iMask ^= pSeg->side; - pPrev = pSeg; - } - } - GEODEBUG(("%s %d.%d C=%g B=%g\n", - pThisEvent->eType ? "RM " : "ADD", - pThisEvent->pSeg->side, pThisEvent->pSeg->idx, - pThisEvent->pSeg->C, - pThisEvent->pSeg->B)); - if( pThisEvent->eType==0 ){ - /* Add a segment */ - pSeg = pThisEvent->pSeg; - pSeg->y = pSeg->y0; - pSeg->pNext = pActive; - pActive = pSeg; - needSort = 1; - }else{ - /* Remove a segment */ - if( pActive==pThisEvent->pSeg ){ - pActive = ALWAYS(pActive) ? pActive->pNext : 0; - }else{ - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - if( pSeg->pNext==pThisEvent->pSeg ){ - pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0; - break; - } - } - } - } - pThisEvent = pThisEvent->pNext; - } - if( aOverlap[3]==0 ){ - rc = 0; - }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ - rc = 3; - }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ - rc = 2; - }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ - rc = 4; - }else{ - rc = 1; - } - -geopolyOverlapDone: - sqlite3_free(p); - return rc; -} - -/* -** SQL function: geopoly_overlap(P1,P2) -** -** Determine whether or not P1 and P2 overlap. Return value: -** -** 0 The two polygons are disjoint -** 1 They overlap -** 2 P1 is completely contained within P2 -** 3 P2 is completely contained within P1 -** 4 P1 and P2 are the same polygon -** NULL Either P1 or P2 or both are not valid polygons -*/ -static void geopolyOverlapFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); - GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); - (void)argc; - if( p1 && p2 ){ - int x = geopolyOverlap(p1, p2); - if( x<0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_int(context, x); - } - } - sqlite3_free(p1); - sqlite3_free(p2); -} - -/* -** Enable or disable debugging output -*/ -static void geopolyDebugFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - (void)context; - (void)argc; -#ifdef GEOPOLY_ENABLE_DEBUG - geo_debug = sqlite3_value_int(argv[0]); -#else - (void)argv; -#endif -} - -/* -** This function is the implementation of both the xConnect and xCreate -** methods of the geopoly virtual table. -** -** argv[0] -> module name -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> column names... -*/ -static int geopolyInit( - sqlite3 *db, /* Database connection */ - void *pAux, /* One of the RTREE_COORD_* constants */ - int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ - sqlite3_vtab **ppVtab, /* OUT: New virtual table */ - char **pzErr, /* OUT: Error message, if any */ - int isCreate /* True for xCreate, false for xConnect */ -){ - int rc = SQLITE_OK; - Rtree *pRtree; - sqlite3_int64 nDb; /* Length of string argv[1] */ - sqlite3_int64 nName; /* Length of string argv[2] */ - sqlite3_str *pSql; - char *zSql; - int ii; - (void)pAux; - - sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - - /* Allocate the sqlite3_vtab structure */ - nDb = strlen(argv[1]); - nName = strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); - if( !pRtree ){ - return SQLITE_NOMEM; - } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); - pRtree->nBusy = 1; - pRtree->base.pModule = &rtreeModule; - pRtree->zDb = (char *)&pRtree[1]; - pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->zNodeName = &pRtree->zName[nName+1]; - pRtree->eCoordType = RTREE_COORD_REAL32; - pRtree->nDim = 2; - pRtree->nDim2 = 4; - memcpy(pRtree->zDb, argv[1], nDb); - memcpy(pRtree->zName, argv[2], nName); - memcpy(pRtree->zNodeName, argv[2], nName); - memcpy(&pRtree->zNodeName[nName], "_node", 6); - - - /* Create/Connect to the underlying relational database schema. If - ** that is successful, call sqlite3_declare_vtab() to configure - ** the r-tree table schema. - */ - pSql = sqlite3_str_new(db); - sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); - pRtree->nAux = 1; /* Add one for _shape */ - pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ - for(ii=3; iinAux++; - sqlite3_str_appendf(pSql, ",%s", argv[ii]); - } - sqlite3_str_appendf(pSql, ");"); - zSql = sqlite3_str_finish(pSql); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - sqlite3_free(zSql); - if( rc ) goto geopolyInit_fail; - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; - - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); - if( rc ) goto geopolyInit_fail; - rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); - if( rc ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - goto geopolyInit_fail; - } - - *ppVtab = (sqlite3_vtab *)pRtree; - return SQLITE_OK; - -geopolyInit_fail: - if( rc==SQLITE_OK ) rc = SQLITE_ERROR; - assert( *ppVtab==0 ); - assert( pRtree->nBusy==1 ); - rtreeRelease(pRtree); - return rc; -} - - -/* -** GEOPOLY virtual table module xCreate method. -*/ -static int geopolyCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); -} - -/* -** GEOPOLY virtual table module xConnect method. -*/ -static int geopolyConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); -} - - -/* -** GEOPOLY virtual table module xFilter method. -** -** Query plans: -** -** 1 rowid lookup -** 2 search for objects overlapping the same bounding box -** that contains polygon argv[0] -** 3 search for objects overlapping the same bounding box -** that contains polygon argv[0] -** 4 full table scan -*/ -static int geopolyFilter( - sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ - int idxNum, /* Query plan */ - const char *idxStr, /* Not Used */ - int argc, sqlite3_value **argv /* Parameters to the query plan */ -){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - RtreeNode *pRoot = 0; - int rc = SQLITE_OK; - int iCell = 0; - (void)idxStr; - - rtreeReference(pRtree); - - /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ - resetCursor(pCsr); - - pCsr->iStrategy = idxNum; - if( idxNum==1 ){ - /* Special case - lookup by rowid. */ - RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - RtreeSearchPoint *p; /* Search point for the leaf */ - i64 iRowid = sqlite3_value_int64(argv[0]); - i64 iNode = 0; - rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); - if( rc==SQLITE_OK && pLeaf!=0 ){ - p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); - assert( p!=0 ); /* Always returns pCsr->sPoint */ - pCsr->aNode[0] = pLeaf; - p->id = iNode; - p->eWithin = PARTLY_WITHIN; - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); - p->iCell = (u8)iCell; - RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); - }else{ - pCsr->atEOF = 1; - } - }else{ - /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array - ** with the configured constraints. - */ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - if( rc==SQLITE_OK && idxNum<=3 ){ - RtreeCoord bbox[4]; - RtreeConstraint *p; - assert( argc==1 ); - assert( argv[0]!=0 ); - geopolyBBox(0, argv[0], bbox, &rc); - if( rc ){ - goto geopoly_filter_end; - } - pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); - pCsr->nConstraint = 4; - if( p==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); - memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); - if( idxNum==2 ){ - /* Overlap query */ - p->op = 'B'; - p->iCoord = 0; - p->u.rValue = bbox[1].f; - p++; - p->op = 'D'; - p->iCoord = 1; - p->u.rValue = bbox[0].f; - p++; - p->op = 'B'; - p->iCoord = 2; - p->u.rValue = bbox[3].f; - p++; - p->op = 'D'; - p->iCoord = 3; - p->u.rValue = bbox[2].f; - }else{ - /* Within query */ - p->op = 'D'; - p->iCoord = 0; - p->u.rValue = bbox[0].f; - p++; - p->op = 'B'; - p->iCoord = 1; - p->u.rValue = bbox[1].f; - p++; - p->op = 'D'; - p->iCoord = 2; - p->u.rValue = bbox[2].f; - p++; - p->op = 'B'; - p->iCoord = 3; - p->u.rValue = bbox[3].f; - } - } - } - if( rc==SQLITE_OK ){ - RtreeSearchPoint *pNew; - pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - goto geopoly_filter_end; - } - pNew->id = 1; - pNew->iCell = 0; - pNew->eWithin = PARTLY_WITHIN; - assert( pCsr->bPoint==1 ); - pCsr->aNode[0] = pRoot; - pRoot = 0; - RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); - rc = rtreeStepToLeaf(pCsr); - } - } - -geopoly_filter_end: - nodeRelease(pRtree, pRoot); - rtreeRelease(pRtree); - return rc; -} - -/* -** Rtree virtual table module xBestIndex method. There are three -** table scan strategies to choose from (in order from most to -** least desirable): -** -** idxNum idxStr Strategy -** ------------------------------------------------ -** 1 "rowid" Direct lookup by rowid. -** 2 "rtree" R-tree overlap query using geopoly_overlap() -** 3 "rtree" R-tree within query using geopoly_within() -** 4 "fullscan" full-table scan. -** ------------------------------------------------ -*/ -static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int ii; - int iRowidTerm = -1; - int iFuncTerm = -1; - int idxNum = 0; - (void)tab; - - for(ii=0; iinConstraint; ii++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - if( !p->usable ) continue; - if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - iRowidTerm = ii; - break; - } - if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ - /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() - ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). - ** See geopolyFindFunction() */ - iFuncTerm = ii; - idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; - } - } - - if( iRowidTerm>=0 ){ - pIdxInfo->idxNum = 1; - pIdxInfo->idxStr = "rowid"; - pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; - pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; - pIdxInfo->estimatedCost = 30.0; - pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; - return SQLITE_OK; - } - if( iFuncTerm>=0 ){ - pIdxInfo->idxNum = idxNum; - pIdxInfo->idxStr = "rtree"; - pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; - pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; - pIdxInfo->estimatedCost = 300.0; - pIdxInfo->estimatedRows = 10; - return SQLITE_OK; - } - pIdxInfo->idxNum = 4; - pIdxInfo->idxStr = "fullscan"; - pIdxInfo->estimatedCost = 3000000.0; - pIdxInfo->estimatedRows = 100000; - return SQLITE_OK; -} - - -/* -** GEOPOLY virtual table module xColumn method. -*/ -static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - Rtree *pRtree = (Rtree *)cur->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)cur; - RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); - int rc = SQLITE_OK; - RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - - if( rc ) return rc; - if( p==0 ) return SQLITE_OK; - if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; - if( i<=pRtree->nAux ){ - if( !pCsr->bAuxValid ){ - if( pCsr->pReadAux==0 ){ - rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, - &pCsr->pReadAux, 0); - if( rc ) return rc; - } - sqlite3_bind_int64(pCsr->pReadAux, 1, - nodeGetRowid(pRtree, pNode, p->iCell)); - rc = sqlite3_step(pCsr->pReadAux); - if( rc==SQLITE_ROW ){ - pCsr->bAuxValid = 1; - }else{ - sqlite3_reset(pCsr->pReadAux); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - return rc; - } - } - sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); - } - return SQLITE_OK; -} - - -/* -** The xUpdate method for GEOPOLY module virtual tables. -** -** For DELETE: -** -** argv[0] = the rowid to be deleted -** -** For INSERT: -** -** argv[0] = SQL NULL -** argv[1] = rowid to insert, or an SQL NULL to select automatically -** argv[2] = _shape column -** argv[3] = first application-defined column.... -** -** For UPDATE: -** -** argv[0] = rowid to modify. Never NULL -** argv[1] = rowid after the change. Never NULL -** argv[2] = new value for _shape -** argv[3] = new value for first application-defined column.... -*/ -static int geopolyUpdate( - sqlite3_vtab *pVtab, - int nData, - sqlite3_value **aData, - sqlite_int64 *pRowid -){ - Rtree *pRtree = (Rtree *)pVtab; - int rc = SQLITE_OK; - RtreeCell cell; /* New cell to insert if nData>1 */ - i64 oldRowid; /* The old rowid */ - int oldRowidValid; /* True if oldRowid is valid */ - i64 newRowid; /* The new rowid */ - int newRowidValid; /* True if newRowid is valid */ - int coordChange = 0; /* Change in coordinates */ - - if( pRtree->nNodeRef ){ - /* Unable to write to the btree while another cursor is reading from it, - ** since the write might do a rebalance which would disrupt the read - ** cursor. */ - return SQLITE_LOCKED_VTAB; - } - rtreeReference(pRtree); - assert(nData>=1); - - oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; - oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; - newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; - newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; - cell.iRowid = newRowid; - - if( nData>1 /* not a DELETE */ - && (!oldRowidValid /* INSERT */ - || !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 ){ - pVtab->zErrMsg = - sqlite3_mprintf("_shape does not contain a valid polygon"); - } - goto geopoly_update_end; - } - coordChange = 1; - - /* If a rowid value was supplied, check if it is already present in - ** the table. If so, the constraint has failed. */ - if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ - int steprc; - sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); - steprc = sqlite3_step(pRtree->pReadRowid); - rc = sqlite3_reset(pRtree->pReadRowid); - if( SQLITE_ROW==steprc ){ - if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ - rc = rtreeDeleteRowid(pRtree, cell.iRowid); - }else{ - rc = rtreeConstraintError(pRtree, 0); - } - } - } - } - - /* If aData[0] is not an SQL NULL value, it is the rowid of a - ** record to delete from the r-tree table. The following block does - ** just that. - */ - if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ - rc = rtreeDeleteRowid(pRtree, oldRowid); - } - - /* If the aData[] array contains more than one element, elements - ** (aData[2]..aData[argc-1]) contain a new record to insert into - ** the r-tree structure. - */ - if( rc==SQLITE_OK && nData>1 && coordChange ){ - /* Insert the new record into the r-tree */ - RtreeNode *pLeaf = 0; - if( !newRowidValid ){ - rc = rtreeNewRowid(pRtree, &cell.iRowid); - } - *pRowid = cell.iRowid; - if( rc==SQLITE_OK ){ - rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); - } - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - /* Change the data */ - if( rc==SQLITE_OK && nData>1 ){ - sqlite3_stmt *pUp = pRtree->pWriteAux; - int jj; - int nChange = 0; - sqlite3_bind_int64(pUp, 1, cell.iRowid); - assert( pRtree->nAux>=1 ); - if( sqlite3_value_nochange(aData[2]) ){ - sqlite3_bind_null(pUp, 2); - }else{ - GeoPoly *p = 0; - if( sqlite3_value_type(aData[2])==SQLITE_TEXT - && (p = geopolyFuncParam(0, aData[2], &rc))!=0 - && rc==SQLITE_OK - ){ - sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); - }else{ - sqlite3_bind_value(pUp, 2, aData[2]); - } - sqlite3_free(p); - nChange = 1; - } - for(jj=1; jjxDestructor ) pInfo->xDestructor(pInfo->pContext); - sqlite3_free(p); -} - -/* -** This routine frees the BLOB that is returned by geomCallback(). -*/ -static void rtreeMatchArgFree(void *pArg){ - int i; - RtreeMatchArg *p = (RtreeMatchArg*)pArg; - for(i=0; inParam; i++){ - sqlite3_value_free(p->apSqlParam[i]); - } - sqlite3_free(p); -} - -/* -** Each call to sqlite3_rtree_geometry_callback() or -** sqlite3_rtree_query_callback() creates an ordinary SQLite -** scalar function that is implemented by this routine. -** -** All this function does is construct an RtreeMatchArg object that -** contains the geometry-checking callback routines and a list of -** parameters to this function, then return that RtreeMatchArg object -** as a BLOB. -** -** The R-Tree MATCH operator will read the returned BLOB, deserialize -** the RtreeMatchArg object, and use the RtreeMatchArg object to figure -** out which elements of the R-Tree should be returned by the query. -*/ -static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ - RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); - RtreeMatchArg *pBlob; - sqlite3_int64 nBlob; - int memErr = 0; - - nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*); - pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob); - if( !pBlob ){ - sqlite3_result_error_nomem(ctx); - }else{ - int i; - pBlob->iSize = nBlob; - pBlob->cb = pGeomCtx[0]; - pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; - pBlob->nParam = nArg; - for(i=0; iapSqlParam[i] = sqlite3_value_dup(aArg[i]); - if( pBlob->apSqlParam[i]==0 ) memErr = 1; -#ifdef SQLITE_RTREE_INT_ONLY - pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); -#else - pBlob->aParam[i] = sqlite3_value_double(aArg[i]); -#endif - } - if( memErr ){ - sqlite3_result_error_nomem(ctx); - rtreeMatchArgFree(pBlob); - }else{ - sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree); - } - } -} - -/* -** Register a new geometry function for use with the r-tree MATCH operator. -*/ -SQLITE_API int sqlite3_rtree_geometry_callback( - sqlite3 *db, /* Register SQL function on this connection */ - const char *zGeom, /* Name of the new SQL function */ - int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ - void *pContext /* Extra data associated with the callback */ -){ - RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ - - /* Allocate and populate the context object. */ - pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); - if( !pGeomCtx ) return SQLITE_NOMEM; - pGeomCtx->xGeom = xGeom; - pGeomCtx->xQueryFunc = 0; - pGeomCtx->xDestructor = 0; - pGeomCtx->pContext = pContext; - return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, - (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback - ); -} - -/* -** Register a new 2nd-generation geometry function for use with the -** r-tree MATCH operator. -*/ -SQLITE_API int sqlite3_rtree_query_callback( - sqlite3 *db, /* Register SQL function on this connection */ - const char *zQueryFunc, /* Name of new SQL function */ - int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ - void *pContext, /* Extra data passed into the callback */ - void (*xDestructor)(void*) /* Destructor for the extra data */ -){ - RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ - - /* Allocate and populate the context object. */ - pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); - if( !pGeomCtx ){ - if( xDestructor ) xDestructor(pContext); - return SQLITE_NOMEM; - } - pGeomCtx->xGeom = 0; - pGeomCtx->xQueryFunc = xQueryFunc; - pGeomCtx->xDestructor = xDestructor; - pGeomCtx->pContext = pContext; - return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, - (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback - ); -} - -#ifndef SQLITE_CORE -#ifdef _WIN32 -__declspec(dllexport) -#endif -SQLITE_API int sqlite3_rtree_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3RtreeInit(db); -} -#endif - -#endif - -/************** End of rtree.c ***********************************************/ -/************** Begin file icu.c *********************************************/ -/* -** 2007 May 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. -** -************************************************************************* -** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $ -** -** This file implements an integration between the ICU library -** ("International Components for Unicode", an open-source library -** for handling unicode data) and SQLite. The integration uses -** ICU to provide the following to SQLite: -** -** * An implementation of the SQL regexp() function (and hence REGEXP -** operator) using the ICU uregex_XX() APIs. -** -** * Implementations of the SQL scalar upper() and lower() functions -** for case mapping. -** -** * Integration of ICU and SQLite collation sequences. -** -** * An implementation of the LIKE operator that uses ICU to -** provide case-independent matching. -*/ - -#if !defined(SQLITE_CORE) \ - || defined(SQLITE_ENABLE_ICU) \ - || defined(SQLITE_ENABLE_ICU_COLLATIONS) - -/* Include ICU headers */ -#include -#include -#include -#include - -/* #include */ - -#ifndef SQLITE_CORE -/* #include "sqlite3ext.h" */ - SQLITE_EXTENSION_INIT1 -#else -/* #include "sqlite3.h" */ -#endif - -/* -** This function is called when an ICU function called from within -** the implementation of an SQL scalar function returns an error. -** -** The scalar function context passed as the first argument is -** loaded with an error message based on the following two args. -*/ -static void icuFunctionError( - sqlite3_context *pCtx, /* SQLite scalar function context */ - const char *zName, /* Name of ICU function that failed */ - UErrorCode e /* Error code returned by ICU function */ -){ - char zBuf[128]; - sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); - zBuf[127] = '\0'; - sqlite3_result_error(pCtx, zBuf, -1); -} - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) - -/* -** Maximum length (in bytes) of the pattern in a LIKE or GLOB -** operator. -*/ -#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH -# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 -#endif - -/* -** Version of sqlite3_free() that is always a function, never a macro. -*/ -static void xFree(void *p){ - sqlite3_free(p); -} - -/* -** This lookup table is used to help decode the first byte of -** a multi-byte UTF8 character. It is copied here from SQLite source -** code file utf8.c. -*/ -static const unsigned char icuUtf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - -#define SQLITE_ICU_READ_UTF8(zIn, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = icuUtf8Trans1[c-0xc0]; \ - while( (*zIn & 0xc0)==0x80 ){ \ - c = (c<<6) + (0x3f & *(zIn++)); \ - } \ - } - -#define SQLITE_ICU_SKIP_UTF8(zIn) \ - assert( *zIn ); \ - if( *(zIn++)>=0xc0 ){ \ - while( (*zIn & 0xc0)==0x80 ){zIn++;} \ - } - - -/* -** Compare two UTF-8 strings for equality where the first string is -** a "LIKE" expression. Return true (1) if they are the same and -** false (0) if they are different. -*/ -static int icuLikeCompare( - const uint8_t *zPattern, /* LIKE pattern */ - const uint8_t *zString, /* The UTF-8 string to compare against */ - const UChar32 uEsc /* The escape character */ -){ - static const uint32_t MATCH_ONE = (uint32_t)'_'; - static const uint32_t MATCH_ALL = (uint32_t)'%'; - - int prevEscape = 0; /* True if the previous character was uEsc */ - - while( 1 ){ - - /* Read (and consume) the next character from the input pattern. */ - uint32_t uPattern; - SQLITE_ICU_READ_UTF8(zPattern, uPattern); - if( uPattern==0 ) break; - - /* There are now 4 possibilities: - ** - ** 1. uPattern is an unescaped match-all character "%", - ** 2. uPattern is an unescaped match-one character "_", - ** 3. uPattern is an unescaped escape character, or - ** 4. uPattern is to be handled as an ordinary character - */ - if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){ - /* Case 1. */ - uint8_t c; - - /* Skip any MATCH_ALL or MATCH_ONE characters that follow a - ** MATCH_ALL. For each MATCH_ONE, skip one character in the - ** test string. - */ - while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){ - if( c==MATCH_ONE ){ - if( *zString==0 ) return 0; - SQLITE_ICU_SKIP_UTF8(zString); - } - zPattern++; - } - - if( *zPattern==0 ) return 1; - - while( *zString ){ - if( icuLikeCompare(zPattern, zString, uEsc) ){ - return 1; - } - SQLITE_ICU_SKIP_UTF8(zString); - } - return 0; - - }else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){ - /* Case 2. */ - if( *zString==0 ) return 0; - SQLITE_ICU_SKIP_UTF8(zString); - - }else if( uPattern==(uint32_t)uEsc && !prevEscape ){ - /* Case 3. */ - prevEscape = 1; - - }else{ - /* Case 4. */ - uint32_t uString; - SQLITE_ICU_READ_UTF8(zString, uString); - uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT); - uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT); - if( uString!=uPattern ){ - return 0; - } - prevEscape = 0; - } - } - - return *zString==0; -} - -/* -** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: -** -** A LIKE B -** -** is implemented as like(B, A). If there is an escape character E, -** -** A LIKE B ESCAPE E -** -** is mapped to like(B, A, E). -*/ -static void icuLikeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zA = sqlite3_value_text(argv[0]); - const unsigned char *zB = sqlite3_value_text(argv[1]); - UChar32 uEsc = 0; - - /* Limit the length of the LIKE or GLOB pattern to avoid problems - ** of deep recursion and N*N behavior in patternCompare(). - */ - if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ - sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); - return; - } - - - if( argc==3 ){ - /* The escape character string must consist of a single UTF-8 character. - ** Otherwise, return an error. - */ - int nE= sqlite3_value_bytes(argv[2]); - const unsigned char *zE = sqlite3_value_text(argv[2]); - int i = 0; - if( zE==0 ) return; - U8_NEXT(zE, i, nE, uEsc); - if( i!=nE){ - sqlite3_result_error(context, - "ESCAPE expression must be a single character", -1); - return; - } - } - - if( zA && zB ){ - sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc)); - } -} - -/* -** Function to delete compiled regexp objects. Registered as -** a destructor function with sqlite3_set_auxdata(). -*/ -static void icuRegexpDelete(void *p){ - URegularExpression *pExpr = (URegularExpression *)p; - uregex_close(pExpr); -} - -/* -** Implementation of SQLite REGEXP operator. This scalar function takes -** two arguments. The first is a regular expression pattern to compile -** the second is a string to match against that pattern. If either -** argument is an SQL NULL, then NULL Is returned. Otherwise, the result -** is 1 if the string matches the pattern, or 0 otherwise. -** -** SQLite maps the regexp() function to the regexp() operator such -** that the following two are equivalent: -** -** zString REGEXP zPattern -** regexp(zPattern, zString) -** -** Uses the following ICU regexp APIs: -** -** uregex_open() -** uregex_matches() -** uregex_close() -*/ -static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - UErrorCode status = U_ZERO_ERROR; - URegularExpression *pExpr; - UBool res; - const UChar *zString = sqlite3_value_text16(apArg[1]); - - (void)nArg; /* Unused parameter */ - - /* If the left hand side of the regexp operator is NULL, - ** then the result is also NULL. - */ - if( !zString ){ - return; - } - - pExpr = sqlite3_get_auxdata(p, 0); - if( !pExpr ){ - const UChar *zPattern = sqlite3_value_text16(apArg[0]); - if( !zPattern ){ - return; - } - pExpr = uregex_open(zPattern, -1, 0, 0, &status); - - if( U_SUCCESS(status) ){ - sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete); - pExpr = sqlite3_get_auxdata(p, 0); - } - if( !pExpr ){ - icuFunctionError(p, "uregex_open", status); - return; - } - } - - /* Configure the text that the regular expression operates on. */ - uregex_setText(pExpr, zString, -1, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_setText", status); - return; - } - - /* Attempt the match */ - res = uregex_matches(pExpr, 0, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_matches", status); - return; - } - - /* Set the text that the regular expression operates on to a NULL - ** pointer. This is not really necessary, but it is tidier than - ** leaving the regular expression object configured with an invalid - ** pointer after this function returns. - */ - uregex_setText(pExpr, 0, 0, &status); - - /* Return 1 or 0. */ - sqlite3_result_int(p, res ? 1 : 0); -} - -/* -** Implementations of scalar functions for case mapping - upper() and -** lower(). Function upper() converts its input to upper-case (ABC). -** Function lower() converts to lower-case (abc). -** -** ICU provides two types of case mapping, "general" case mapping and -** "language specific". Refer to ICU documentation for the differences -** between the two. -** -** To utilise "general" case mapping, the upper() or lower() scalar -** functions are invoked with one argument: -** -** upper('ABC') -> 'abc' -** lower('abc') -> 'ABC' -** -** To access ICU "language specific" case mapping, upper() or lower() -** should be invoked with two arguments. The second argument is the name -** of the locale to use. Passing an empty string ("") or SQL NULL value -** as the second argument is the same as invoking the 1 argument version -** of upper() or lower(). -** -** lower('I', 'en_us') -> 'i' -** lower('I', 'tr_tr') -> '\u131' (small dotless i) -** -** http://www.icu-project.org/userguide/posix.html#case_mappings -*/ -static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - const UChar *zInput; /* Pointer to input string */ - UChar *zOutput = 0; /* Pointer to output buffer */ - int nInput; /* Size of utf-16 input string in bytes */ - int nOut; /* Size of output buffer in bytes */ - int cnt; - int bToUpper; /* True for toupper(), false for tolower() */ - UErrorCode status; - const char *zLocale = 0; - - assert(nArg==1 || nArg==2); - bToUpper = (sqlite3_user_data(p)!=0); - if( nArg==2 ){ - zLocale = (const char *)sqlite3_value_text(apArg[1]); - } - - zInput = sqlite3_value_text16(apArg[0]); - if( !zInput ){ - return; - } - nOut = nInput = sqlite3_value_bytes16(apArg[0]); - if( nOut==0 ){ - sqlite3_result_text16(p, "", 0, SQLITE_STATIC); - return; - } - - for(cnt=0; cnt<2; cnt++){ - UChar *zNew = sqlite3_realloc(zOutput, nOut); - if( zNew==0 ){ - sqlite3_free(zOutput); - sqlite3_result_error_nomem(p); - return; - } - zOutput = zNew; - status = U_ZERO_ERROR; - if( bToUpper ){ - nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); - }else{ - nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); - } - - if( U_SUCCESS(status) ){ - sqlite3_result_text16(p, zOutput, nOut, xFree); - }else if( status==U_BUFFER_OVERFLOW_ERROR ){ - assert( cnt==0 ); - continue; - }else{ - icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status); - } - return; - } - assert( 0 ); /* Unreachable */ -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ - -/* -** Collation sequence destructor function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static void icuCollationDel(void *pCtx){ - UCollator *p = (UCollator *)pCtx; - ucol_close(p); -} - -/* -** Collation sequence comparison function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static int icuCollationColl( - void *pCtx, - int nLeft, - const void *zLeft, - int nRight, - const void *zRight -){ - UCollationResult res; - UCollator *p = (UCollator *)pCtx; - res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2); - switch( res ){ - case UCOL_LESS: return -1; - case UCOL_GREATER: return +1; - case UCOL_EQUAL: return 0; - } - assert(!"Unexpected return value from ucol_strcoll()"); - return 0; -} - -/* -** Implementation of the scalar function icu_load_collation(). -** -** This scalar function is used to add ICU collation based collation -** types to an SQLite database connection. It is intended to be called -** as follows: -** -** SELECT icu_load_collation(, ); -** -** Where is a string containing an ICU locale identifier (i.e. -** "en_AU", "tr_TR" etc.) and is the name of the -** collation sequence to create. -*/ -static void icuLoadCollation( - sqlite3_context *p, - int nArg, - sqlite3_value **apArg -){ - sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); - UErrorCode status = U_ZERO_ERROR; - const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ - const char *zName; /* SQL Collation sequence name (eg. "japanese") */ - UCollator *pUCollator; /* ICU library collation object */ - int rc; /* Return code from sqlite3_create_collation_x() */ - - assert(nArg==2 || nArg==3); - (void)nArg; /* Unused parameter */ - zLocale = (const char *)sqlite3_value_text(apArg[0]); - zName = (const char *)sqlite3_value_text(apArg[1]); - - if( !zLocale || !zName ){ - return; - } - - pUCollator = ucol_open(zLocale, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "ucol_open", status); - return; - } - assert(p); - if(nArg==3){ - const char *zOption = (const char*)sqlite3_value_text(apArg[2]); - static const struct { - const char *zName; - UColAttributeValue val; - } aStrength[] = { - { "PRIMARY", UCOL_PRIMARY }, - { "SECONDARY", UCOL_SECONDARY }, - { "TERTIARY", UCOL_TERTIARY }, - { "DEFAULT", UCOL_DEFAULT_STRENGTH }, - { "QUARTERNARY", UCOL_QUATERNARY }, - { "IDENTICAL", UCOL_IDENTICAL }, - }; - unsigned int i; - for(i=0; i=sizeof(aStrength)/sizeof(aStrength[0]) ){ - sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p)); - sqlite3_str_appendf(pStr, - "unknown collation strength \"%s\" - should be one of:", - zOption); - for(i=0; izName, p->nArg, p->enc, - p->iContext ? (void*)db : (void*)0, - p->xFunc, 0, 0 - ); - } - - return rc; -} - -#ifndef SQLITE_CORE -#ifdef _WIN32 -__declspec(dllexport) -#endif -SQLITE_API int sqlite3_icu_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3IcuInit(db); -} -#endif - -#endif - -/************** End of icu.c *************************************************/ -/************** Begin file fts3_icu.c ****************************************/ -/* -** 2007 June 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 implements a tokenizer for fts3 based on the ICU library. -*/ -/* #include "fts3Int.h" */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) -#ifdef SQLITE_ENABLE_ICU - -/* #include */ -/* #include */ -/* #include "fts3_tokenizer.h" */ - -#include -/* #include */ -/* #include */ -#include - -typedef struct IcuTokenizer IcuTokenizer; -typedef struct IcuCursor IcuCursor; - -struct IcuTokenizer { - sqlite3_tokenizer base; - char *zLocale; -}; - -struct IcuCursor { - sqlite3_tokenizer_cursor base; - - UBreakIterator *pIter; /* ICU break-iterator object */ - int nChar; /* Number of UChar elements in pInput */ - UChar *aChar; /* Copy of input using utf-16 encoding */ - int *aOffset; /* Offsets of each character in utf-8 input */ - - int nBuffer; - char *zBuffer; - - int iToken; -}; - -/* -** Create a new tokenizer instance. -*/ -static int icuCreate( - int argc, /* Number of entries in argv[] */ - const char * const *argv, /* Tokenizer creation arguments */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ -){ - IcuTokenizer *p; - int n = 0; - - if( argc>0 ){ - n = strlen(argv[0])+1; - } - p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n); - if( !p ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(IcuTokenizer)); - - if( n ){ - p->zLocale = (char *)&p[1]; - memcpy(p->zLocale, argv[0], n); - } - - *ppTokenizer = (sqlite3_tokenizer *)p; - - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int icuDestroy(sqlite3_tokenizer *pTokenizer){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int icuOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, /* Input string */ - int nInput, /* Length of zInput in bytes */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - IcuCursor *pCsr; - - const int32_t opt = U_FOLD_CASE_DEFAULT; - UErrorCode status = U_ZERO_ERROR; - int nChar; - - UChar32 c; - int iInput = 0; - int iOut = 0; - - *ppCursor = 0; - - if( zInput==0 ){ - nInput = 0; - zInput = ""; - }else if( nInput<0 ){ - nInput = strlen(zInput); - } - nChar = nInput+1; - pCsr = (IcuCursor *)sqlite3_malloc64( - sizeof(IcuCursor) + /* IcuCursor */ - ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ - (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ - ); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(IcuCursor)); - pCsr->aChar = (UChar *)&pCsr[1]; - pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; - - pCsr->aOffset[iOut] = iInput; - U8_NEXT(zInput, iInput, nInput, c); - while( c>0 ){ - int isError = 0; - c = u_foldCase(c, opt); - U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); - if( isError ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->aOffset[iOut] = iInput; - - if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); - if( !U_SUCCESS(status) ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->nChar = iOut; - - ubrk_first(pCsr->pIter); - *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to icuOpen(). -*/ -static int icuClose(sqlite3_tokenizer_cursor *pCursor){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - ubrk_close(pCsr->pIter); - sqlite3_free(pCsr->zBuffer); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. -*/ -static int icuNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - - int iStart = 0; - int iEnd = 0; - int nByte = 0; - - while( iStart==iEnd ){ - UChar32 c; - - iStart = ubrk_current(pCsr->pIter); - iEnd = ubrk_next(pCsr->pIter); - if( iEnd==UBRK_DONE ){ - return SQLITE_DONE; - } - - while( iStartaChar, iWhite, pCsr->nChar, c); - if( u_isspace(c) ){ - iStart = iWhite; - }else{ - break; - } - } - assert(iStart<=iEnd); - } - - do { - UErrorCode status = U_ZERO_ERROR; - if( nByte ){ - char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); - if( !zNew ){ - return SQLITE_NOMEM; - } - pCsr->zBuffer = zNew; - pCsr->nBuffer = nByte; - } - - u_strToUTF8( - pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ - &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ - &status /* Output success/failure */ - ); - } while( nByte>pCsr->nBuffer ); - - *ppToken = pCsr->zBuffer; - *pnBytes = nByte; - *piStartOffset = pCsr->aOffset[iStart]; - *piEndOffset = pCsr->aOffset[iEnd]; - *piPosition = pCsr->iToken++; - - return SQLITE_OK; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ - 0, /* xLanguageid */ -}; - -/* -** Set *ppModule to point at the implementation of the ICU tokenizer. -*/ -SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &icuTokenizerModule; -} - -#endif /* defined(SQLITE_ENABLE_ICU) */ -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_icu.c ********************************************/ -/************** Begin file sqlite3rbu.c **************************************/ -/* -** 2014 August 30 -** -** 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. -** -************************************************************************* -** -** -** OVERVIEW -** -** The RBU extension requires that the RBU update be packaged as an -** SQLite database. The tables it expects to find are described in -** sqlite3rbu.h. Essentially, for each table xyz in the target database -** that the user wishes to write to, a corresponding data_xyz table is -** created in the RBU database and populated with one row for each row to -** update, insert or delete from the target table. -** -** The update proceeds in three stages: -** -** 1) The database is updated. The modified database pages are written -** to a *-oal file. A *-oal file is just like a *-wal file, except -** that it is named "-oal" instead of "-wal". -** Because regular SQLite clients do not look for file named -** "-oal", they go on using the original database in -** rollback mode while the *-oal file is being generated. -** -** During this stage RBU does not update the database by writing -** directly to the target tables. Instead it creates "imposter" -** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses -** to update each b-tree individually. All updates required by each -** b-tree are completed before moving on to the next, and all -** updates are done in sorted key order. -** -** 2) The "-oal" file is moved to the equivalent "-wal" -** location using a call to rename(2). Before doing this the RBU -** module takes an EXCLUSIVE lock on the database file, ensuring -** that there are no other active readers. -** -** Once the EXCLUSIVE lock is released, any other database readers -** detect the new *-wal file and read the database in wal mode. At -** this point they see the new version of the database - including -** the updates made as part of the RBU update. -** -** 3) The new *-wal file is checkpointed. This proceeds in the same way -** as a regular database checkpoint, except that a single frame is -** checkpointed each time sqlite3rbu_step() is called. If the RBU -** handle is closed before the entire *-wal file is checkpointed, -** the checkpoint progress is saved in the RBU database and the -** checkpoint can be resumed by another RBU client at some point in -** the future. -** -** POTENTIAL PROBLEMS -** -** The rename() call might not be portable. And RBU is not currently -** syncing the directory after renaming the file. -** -** When state is saved, any commit to the *-oal file and the commit to -** the RBU update database are not atomic. So if the power fails at the -** wrong moment they might get out of sync. As the main database will be -** committed before the RBU update database this will likely either just -** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE -** constraint violations). -** -** If some client does modify the target database mid RBU update, or some -** other error occurs, the RBU extension will keep throwing errors. It's -** not really clear how to get out of this state. The system could just -** by delete the RBU update database and *-oal file and have the device -** download the update again and start over. -** -** At present, for an UPDATE, both the new.* and old.* records are -** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all -** fields are collected. This means we're probably writing a lot more -** data to disk when saving the state of an ongoing update to the RBU -** update database than is strictly necessary. -** -*/ - -/* #include */ -/* #include */ -/* #include */ - -/* #include "sqlite3.h" */ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) -/************** Include sqlite3rbu.h in the middle of sqlite3rbu.c ***********/ -/************** Begin file sqlite3rbu.h **************************************/ -/* -** 2014 August 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the public interface for the RBU extension. -*/ - -/* -** SUMMARY -** -** Writing a transaction containing a large number of operations on -** b-tree indexes that are collectively larger than the available cache -** memory can be very inefficient. -** -** The problem is that in order to update a b-tree, the leaf page (at least) -** containing the entry being inserted or deleted must be modified. If the -** working set of leaves is larger than the available cache memory, then a -** single leaf that is modified more than once as part of the transaction -** may be loaded from or written to the persistent media multiple times. -** Additionally, because the index updates are likely to be applied in -** random order, access to pages within the database is also likely to be in -** random order, which is itself quite inefficient. -** -** One way to improve the situation is to sort the operations on each index -** by index key before applying them to the b-tree. This leads to an IO -** pattern that resembles a single linear scan through the index b-tree, -** and all but guarantees each modified leaf page is loaded and stored -** exactly once. SQLite uses this trick to improve the performance of -** CREATE INDEX commands. This extension allows it to be used to improve -** the performance of large transactions on existing databases. -** -** Additionally, this extension allows the work involved in writing the -** large transaction to be broken down into sub-transactions performed -** sequentially by separate processes. This is useful if the system cannot -** guarantee that a single update process will run for long enough to apply -** the entire update, for example because the update is being applied on a -** mobile device that is frequently rebooted. Even after the writer process -** has committed one or more sub-transactions, other database clients continue -** to read from the original database snapshot. In other words, partially -** applied transactions are not visible to other clients. -** -** "RBU" stands for "Resumable Bulk Update". As in a large database update -** transmitted via a wireless network to a mobile device. A transaction -** applied using this extension is hence referred to as an "RBU update". -** -** -** LIMITATIONS -** -** An "RBU update" transaction is subject to the following limitations: -** -** * The transaction must consist of INSERT, UPDATE and DELETE operations -** only. -** -** * INSERT statements may not use any default values. -** -** * UPDATE and DELETE statements must identify their target rows by -** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY -** KEY fields may not be updated or deleted. If the table being written -** has no PRIMARY KEY, affected rows must be identified by rowid. -** -** * UPDATE statements may not modify PRIMARY KEY columns. -** -** * No triggers will be fired. -** -** * No foreign key violations are detected or reported. -** -** * CHECK constraints are not enforced. -** -** * No constraint handling mode except for "OR ROLLBACK" is supported. -** -** -** PREPARATION -** -** An "RBU update" is stored as a separate SQLite database. A database -** containing an RBU update is an "RBU database". For each table in the -** target database to be updated, the RBU database should contain a table -** named "data_" containing the same set of columns as the -** target table, and one more - "rbu_control". The data_% table should -** have no PRIMARY KEY or UNIQUE constraints, but each column should have -** the same type as the corresponding column in the target database. -** The "rbu_control" column should have no type at all. For example, if -** the target database contains: -** -** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE); -** -** Then the RBU database should contain: -** -** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control); -** -** The order of the columns in the data_% table does not matter. -** -** Instead of a regular table, the RBU database may also contain virtual -** tables or views named using the data_ naming scheme. -** -** Instead of the plain data_ naming scheme, RBU database tables -** may also be named data_, where is any sequence -** of zero or more numeric characters (0-9). This can be significant because -** tables within the RBU database are always processed in order sorted by -** name. By judicious selection of the portion of the names -** of the RBU tables the user can therefore control the order in which they -** are processed. This can be useful, for example, to ensure that "external -** content" FTS4 tables are updated before their underlying content tables. -** -** If the target database table is a virtual table or a table that has no -** PRIMARY KEY declaration, the data_% table must also contain a column -** named "rbu_rowid". This column is mapped to the table's implicit primary -** key column - "rowid". Virtual tables for which the "rowid" column does -** not function like a primary key value cannot be updated using RBU. For -** example, if the target db contains either of the following: -** -** CREATE VIRTUAL TABLE x1 USING fts3(a, b); -** CREATE TABLE x1(a, b) -** -** then the RBU database should contain: -** -** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control); -** -** All non-hidden columns (i.e. all columns matched by "SELECT *") of the -** target table must be present in the input table. For virtual tables, -** hidden columns are optional - they are updated by RBU if present in -** the input table, or not otherwise. For example, to write to an fts4 -** table with a hidden languageid column such as: -** -** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid'); -** -** Either of the following input table schemas may be used: -** -** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control); -** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control); -** -** For each row to INSERT into the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain integer value 0. The -** other columns should be set to the values that make up the new record -** to insert. -** -** If the target database table has an INTEGER PRIMARY KEY, it is not -** possible to insert a NULL value into the IPK column. Attempting to -** do so results in an SQLITE_MISMATCH error. -** -** For each row to DELETE from the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain integer value 1. The -** real primary key values of the row to delete should be stored in the -** corresponding columns of the data_% table. The values stored in the -** other columns are not used. -** -** For each row to UPDATE from the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain a value of type text. -** The real primary key values identifying the row to update should be -** stored in the corresponding columns of the data_% table row, as should -** the new values of all columns being update. The text value in the -** "rbu_control" column must contain the same number of characters as -** there are columns in the target database table, and must consist entirely -** of 'x' and '.' characters (or in some special cases 'd' - see below). For -** each column that is being updated, the corresponding character is set to -** 'x'. For those that remain as they are, the corresponding character of the -** rbu_control value should be set to '.'. For example, given the tables -** above, the update statement: -** -** UPDATE t1 SET c = 'usa' WHERE a = 4; -** -** is represented by the data_t1 row created by: -** -** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x'); -** -** Instead of an 'x' character, characters of the rbu_control value specified -** for UPDATEs may also be set to 'd'. In this case, instead of updating the -** target table with the value stored in the corresponding data_% column, the -** user-defined SQL function "rbu_delta()" is invoked and the result stored in -** the target table column. rbu_delta() is invoked with two arguments - the -** original value currently stored in the target table column and the -** value specified in the data_xxx table. -** -** For example, this row: -** -** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d'); -** -** is similar to an UPDATE statement such as: -** -** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4; -** -** Finally, if an 'f' character appears in place of a 'd' or 's' in an -** ota_control string, the contents of the data_xxx table column is assumed -** to be a "fossil delta" - a patch to be applied to a blob value in the -** format used by the fossil source-code management system. In this case -** the existing value within the target database table must be of type BLOB. -** It is replaced by the result of applying the specified fossil delta to -** itself. -** -** If the target database table is a virtual table or a table with no PRIMARY -** KEY, the rbu_control value should not include a character corresponding -** to the rbu_rowid value. For example, this: -** -** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) -** VALUES(NULL, 'usa', 12, '.x'); -** -** causes a result similar to: -** -** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; -** -** The data_xxx tables themselves should have no PRIMARY KEY declarations. -** However, RBU is more efficient if reading the rows in from each data_xxx -** table in "rowid" order is roughly the same as reading them sorted by -** the PRIMARY KEY of the corresponding target database table. In other -** words, rows should be sorted using the destination table PRIMARY KEY -** fields before they are inserted into the data_xxx tables. -** -** USAGE -** -** The API declared below allows an application to apply an RBU update -** stored on disk to an existing target database. Essentially, the -** application: -** -** 1) Opens an RBU handle using the sqlite3rbu_open() function. -** -** 2) Registers any required virtual table modules with the database -** handle returned by sqlite3rbu_db(). Also, if required, register -** the rbu_delta() implementation. -** -** 3) Calls the sqlite3rbu_step() function one or more times on -** the new handle. Each call to sqlite3rbu_step() performs a single -** b-tree operation, so thousands of calls may be required to apply -** a complete update. -** -** 4) Calls sqlite3rbu_close() to close the RBU update handle. If -** sqlite3rbu_step() has been called enough times to completely -** apply the update to the target database, then the RBU database -** is marked as fully applied. Otherwise, the state of the RBU -** update application is saved in the RBU database for later -** resumption. -** -** See comments below for more detail on APIs. -** -** If an update is only partially applied to the target database by the -** time sqlite3rbu_close() is called, various state information is saved -** within the RBU database. This allows subsequent processes to automatically -** resume the RBU update from where it left off. -** -** To remove all RBU extension state information, returning an RBU database -** to its original contents, it is sufficient to drop all tables that begin -** with the prefix "rbu_" -** -** DATABASE LOCKING -** -** An RBU update may not be applied to a database in WAL mode. Attempting -** to do so is an error (SQLITE_ERROR). -** -** While an RBU handle is open, a SHARED lock may be held on the target -** database file. This means it is possible for other clients to read the -** database, but not to write it. -** -** If an RBU update is started and then suspended before it is completed, -** then an external client writes to the database, then attempting to resume -** the suspended RBU update is also an error (SQLITE_BUSY). -*/ - -#ifndef _SQLITE3RBU_H -#define _SQLITE3RBU_H - -/* #include "sqlite3.h" ** Required for error code definitions ** */ - -#if 0 -extern "C" { -#endif - -typedef struct sqlite3rbu sqlite3rbu; - -/* -** Open an RBU handle. -** -** Argument zTarget is the path to the target database. Argument zRbu is -** the path to the RBU database. Each call to this function must be matched -** by a call to sqlite3rbu_close(). When opening the databases, RBU passes -** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget -** or zRbu begin with "file:", it will be interpreted as an SQLite -** database URI, not a regular file name. -** -** If the zState argument is passed a NULL value, the RBU extension stores -** the current state of the update (how many rows have been updated, which -** indexes are yet to be updated etc.) within the RBU database itself. This -** can be convenient, as it means that the RBU application does not need to -** organize removing a separate state file after the update is concluded. -** Or, if zState is non-NULL, it must be a path to a database file in which -** the RBU extension can store the state of the update. -** -** When resuming an RBU update, the zState argument must be passed the same -** value as when the RBU update was started. -** -** Once the RBU update is finished, the RBU extension does not -** automatically remove any zState database file, even if it created it. -** -** By default, RBU uses the default VFS to access the files on disk. To -** use a VFS other than the default, an SQLite "file:" URI containing a -** "vfs=..." option may be passed as the zTarget option. -** -** IMPORTANT NOTE FOR ZIPVFS USERS: The RBU extension works with all of -** SQLite's built-in VFSs, including the multiplexor VFS. However it does -** not work out of the box with zipvfs. Refer to the comment describing -** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. -*/ -SQLITE_API sqlite3rbu *sqlite3rbu_open( - const char *zTarget, - const char *zRbu, - const char *zState -); - -/* -** Open an RBU handle to perform an RBU vacuum on database file zTarget. -** An RBU vacuum is similar to SQLite's built-in VACUUM command, except -** that it can be suspended and resumed like an RBU update. -** -** The second argument to this function identifies a database in which -** to store the state of the RBU vacuum operation if it is suspended. The -** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum -** operation, the state database should either not exist or be empty -** (contain no tables). If an RBU vacuum is suspended by calling -** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has -** returned SQLITE_DONE, the vacuum state is stored in the state database. -** The vacuum can be resumed by calling this function to open a new RBU -** handle specifying the same target and state databases. -** -** If the second argument passed to this function is NULL, then the -** name of the state database is "-vacuum", where -** is the name of the target database file. In this case, on UNIX, if the -** state database is not already present in the file-system, it is created -** with the same permissions as the target db is made. -** -** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the -** state database ends with "-vactmp". This name is reserved for internal -** use. -** -** This function does not delete the state database after an RBU vacuum -** is completed, even if it created it. However, if the call to -** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents -** of the state tables within the state database are zeroed. This way, -** the next call to sqlite3rbu_vacuum() opens a handle that starts a -** new RBU vacuum operation. -** -** As with sqlite3rbu_open(), Zipvfs users should refer to the comment -** describing the sqlite3rbu_create_vfs() API function below for -** a description of the complications associated with using RBU with -** zipvfs databases. -*/ -SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( - const char *zTarget, - const char *zState -); - -/* -** Configure a limit for the amount of temp space that may be used by -** the RBU handle passed as the first argument. The new limit is specified -** in bytes by the second parameter. If it is positive, the limit is updated. -** If the second parameter to this function is passed zero, then the limit -** is removed entirely. If the second parameter is negative, the limit is -** not modified (this is useful for querying the current limit). -** -** In all cases the returned value is the current limit in bytes (zero -** indicates unlimited). -** -** If the temp space limit is exceeded during operation, an SQLITE_FULL -** error is returned. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64); - -/* -** Return the current amount of temp file space, in bytes, currently used by -** the RBU handle passed as the only argument. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*); - -/* -** Internally, each RBU connection uses a separate SQLite database -** connection to access the target and rbu update databases. This -** API allows the application direct access to these database handles. -** -** The first argument passed to this function must be a valid, open, RBU -** handle. The second argument should be passed zero to access the target -** database handle, or non-zero to access the rbu update database handle. -** Accessing the underlying database handles may be useful in the -** following scenarios: -** -** * If any target tables are virtual tables, it may be necessary to -** call sqlite3_create_module() on the target database handle to -** register the required virtual table implementations. -** -** * If the data_xxx tables in the RBU source database are virtual -** tables, the application may need to call sqlite3_create_module() on -** the rbu update db handle to any required virtual table -** implementations. -** -** * If the application uses the "rbu_delta()" feature described above, -** it must use sqlite3_create_function() or similar to register the -** rbu_delta() implementation with the target database handle. -** -** If an error has occurred, either while opening or stepping the RBU object, -** this function may return NULL. The error code and message may be collected -** when sqlite3rbu_close() is called. -** -** Database handles returned by this function remain valid until the next -** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db(). -*/ -SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu); - -/* -** Do some work towards applying the RBU update to the target db. -** -** Return SQLITE_DONE if the update has been completely applied, or -** SQLITE_OK if no error occurs but there remains work to do to apply -** the RBU update. If an error does occur, some other error code is -** returned. -** -** Once a call to sqlite3rbu_step() has returned a value other than -** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops -** that immediately return the same value. -*/ -SQLITE_API int sqlite3rbu_step(sqlite3rbu *pRbu); - -/* -** Force RBU to save its state to disk. -** -** If a power failure or application crash occurs during an update, following -** system recovery RBU may resume the update from the point at which the state -** was last saved. In other words, from the most recent successful call to -** sqlite3rbu_close() or this function. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu); - -/* -** Close an RBU handle. -** -** If the RBU update has been completely applied, mark the RBU database -** as fully applied. Otherwise, assuming no error has occurred, save the -** current state of the RBU update application to the RBU database. -** -** If an error has already occurred as part of an sqlite3rbu_step() -** or sqlite3rbu_open() call, or if one occurs within this function, an -** SQLite error code is returned. Additionally, if pzErrmsg is not NULL, -** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted -** English language error message. It is the responsibility of the caller to -** eventually free any such buffer using sqlite3_free(). -** -** Otherwise, if no error occurs, this function returns SQLITE_OK if the -** update has been partially applied, or SQLITE_DONE if it has been -** completely applied. -*/ -SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); - -/* -** Return the total number of key-value operations (inserts, deletes or -** updates) that have been performed on the target database since the -** current RBU update was started. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); - -/* -** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) -** progress indications for the two stages of an RBU update. This API may -** be useful for driving GUI progress indicators and similar. -** -** An RBU update is divided into two stages: -** -** * Stage 1, in which changes are accumulated in an oal/wal file, and -** * Stage 2, in which the contents of the wal file are copied into the -** main database. -** -** The update is visible to non-RBU clients during stage 2. During stage 1 -** non-RBU reader clients may see the original database. -** -** If this API is called during stage 2 of the update, output variable -** (*pnOne) is set to 10000 to indicate that stage 1 has finished and (*pnTwo) -** to a value between 0 and 10000 to indicate the permyriadage progress of -** stage 2. A value of 5000 indicates that stage 2 is half finished, -** 9000 indicates that it is 90% finished, and so on. -** -** If this API is called during stage 1 of the update, output variable -** (*pnTwo) is set to 0 to indicate that stage 2 has not yet started. The -** value to which (*pnOne) is set depends on whether or not the RBU -** database contains an "rbu_count" table. The rbu_count table, if it -** exists, must contain the same columns as the following: -** -** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; -** -** There must be one row in the table for each source (data_xxx) table within -** the RBU database. The 'tbl' column should contain the name of the source -** table. The 'cnt' column should contain the number of rows within the -** source table. -** -** If the rbu_count table is present and populated correctly and this -** API is called during stage 1, the *pnOne output variable is set to the -** permyriadage progress of the same stage. If the rbu_count table does -** not exist, then (*pnOne) is set to -1 during stage 1. If the rbu_count -** table exists but is not correctly populated, the value of the *pnOne -** output variable during stage 1 is undefined. -*/ -SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo); - -/* -** Obtain an indication as to the current stage of an RBU update or vacuum. -** This function always returns one of the SQLITE_RBU_STATE_XXX constants -** defined in this file. Return values should be interpreted as follows: -** -** SQLITE_RBU_STATE_OAL: -** RBU is currently building a *-oal file. The next call to sqlite3rbu_step() -** may either add further data to the *-oal file, or compute data that will -** be added by a subsequent call. -** -** SQLITE_RBU_STATE_MOVE: -** RBU has finished building the *-oal file. The next call to sqlite3rbu_step() -** will move the *-oal file to the equivalent *-wal path. If the current -** operation is an RBU update, then the updated version of the database -** file will become visible to ordinary SQLite clients following the next -** call to sqlite3rbu_step(). -** -** SQLITE_RBU_STATE_CHECKPOINT: -** RBU is currently performing an incremental checkpoint. The next call to -** sqlite3rbu_step() will copy a page of data from the *-wal file into -** the target database file. -** -** SQLITE_RBU_STATE_DONE: -** The RBU operation has finished. Any subsequent calls to sqlite3rbu_step() -** will immediately return SQLITE_DONE. -** -** SQLITE_RBU_STATE_ERROR: -** An error has occurred. Any subsequent calls to sqlite3rbu_step() will -** immediately return the SQLite error code associated with the error. -*/ -#define SQLITE_RBU_STATE_OAL 1 -#define SQLITE_RBU_STATE_MOVE 2 -#define SQLITE_RBU_STATE_CHECKPOINT 3 -#define SQLITE_RBU_STATE_DONE 4 -#define SQLITE_RBU_STATE_ERROR 5 - -SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu); - -/* -** As part of applying an RBU update or performing an RBU vacuum operation, -** the system must at one point move the *-oal file to the equivalent *-wal -** path. Normally, it does this by invoking POSIX function rename(2) directly. -** Except on WINCE platforms, where it uses win32 API MoveFileW(). This -** function may be used to register a callback that the RBU module will invoke -** instead of one of these APIs. -** -** If a callback is registered with an RBU handle, it invokes it instead -** of rename(2) when it needs to move a file within the file-system. The -** first argument passed to the xRename() callback is a copy of the second -** argument (pArg) passed to this function. The second is the full path -** to the file to move and the third the full path to which it should be -** moved. The callback function should return SQLITE_OK to indicate -** success. If an error occurs, it should return an SQLite error code. -** In this case the RBU operation will be abandoned and the error returned -** to the RBU user. -** -** Passing a NULL pointer in place of the xRename argument to this function -** restores the default behaviour. -*/ -SQLITE_API void sqlite3rbu_rename_handler( - sqlite3rbu *pRbu, - void *pArg, - int (*xRename)(void *pArg, const char *zOld, const char *zNew) -); - - -/* -** Create an RBU VFS named zName that accesses the underlying file-system -** via existing VFS zParent. Or, if the zParent parameter is passed NULL, -** then the new RBU VFS uses the default system VFS to access the file-system. -** The new object is registered as a non-default VFS with SQLite before -** returning. -** -** Part of the RBU implementation uses a custom VFS object. Usually, this -** object is created and deleted automatically by RBU. -** -** The exception is for applications that also use zipvfs. In this case, -** the custom VFS must be explicitly created by the user before the RBU -** handle is opened. The RBU VFS should be installed so that the zipvfs -** VFS uses the RBU VFS, which in turn uses any other VFS layers in use -** (for example multiplexor) to access the file-system. For example, -** to assemble an RBU enabled VFS stack that uses both zipvfs and -** multiplexor (error checking omitted): -** -** // Create a VFS named "multiplex" (not the default). -** sqlite3_multiplex_initialize(0, 0); -** -** // Create an rbu VFS named "rbu" that uses multiplexor. If the -** // second argument were replaced with NULL, the "rbu" VFS would -** // access the file-system via the system default VFS, bypassing the -** // multiplexor. -** sqlite3rbu_create_vfs("rbu", "multiplex"); -** -** // Create a zipvfs VFS named "zipvfs" that uses rbu. -** zipvfs_create_vfs_v3("zipvfs", "rbu", 0, xCompressorAlgorithmDetector); -** -** // Make zipvfs the default VFS. -** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); -** -** Because the default VFS created above includes a RBU functionality, it -** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack -** that does not include the RBU layer results in an error. -** -** The overhead of adding the "rbu" VFS to the system is negligible for -** non-RBU users. There is no harm in an application accessing the -** file-system via "rbu" all the time, even if it only uses RBU functionality -** occasionally. -*/ -SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent); - -/* -** Deregister and destroy an RBU vfs created by an earlier call to -** sqlite3rbu_create_vfs(). -** -** VFS objects are not reference counted. If a VFS object is destroyed -** before all database handles that use it have been closed, the results -** are undefined. -*/ -SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); - -#if 0 -} /* end of the 'extern "C"' block */ -#endif - -#endif /* _SQLITE3RBU_H */ - -/************** End of sqlite3rbu.h ******************************************/ -/************** Continuing where we left off in sqlite3rbu.c *****************/ - -#if defined(_WIN32_WCE) -/* #include "windows.h" */ -#endif - -/* Maximum number of prepared UPDATE statements held by this module */ -#define SQLITE_RBU_UPDATE_CACHESIZE 16 - -/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM -** to enable checksum verification. -*/ -#ifndef RBU_ENABLE_DELTA_CKSUM -# define RBU_ENABLE_DELTA_CKSUM 0 -#endif - -/* -** Swap two objects of type TYPE. -*/ -#if !defined(SQLITE_AMALGAMATION) -# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} -#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: -** -** RBU_STATE_STAGE: -** May be set to integer values 1, 2, 4 or 5. As follows: -** 1: the *-rbu file is currently under construction. -** 2: the *-rbu file has been constructed, but not yet moved -** to the *-wal path. -** 4: the checkpoint is underway. -** 5: the rbu update has been checkpointed. -** -** RBU_STATE_TBL: -** Only valid if STAGE==1. The target database name of the table -** currently being written. -** -** RBU_STATE_IDX: -** Only valid if STAGE==1. The target database name of the index -** currently being written, or NULL if the main table is currently being -** updated. -** -** RBU_STATE_ROW: -** Only valid if STAGE==1. Number of rows already processed for the current -** table/index. -** -** RBU_STATE_PROGRESS: -** Trbul number of sqlite3rbu_step() calls made so far as part of this -** rbu update. -** -** RBU_STATE_CKPT: -** Valid if STAGE==4. The 64-bit checksum associated with the wal-index -** header created by recovering the *-wal file. This is used to detect -** cases when another client appends frames to the *-wal file in the -** middle of an incremental checkpoint (an incremental checkpoint cannot -** be continued if this happens). -** -** RBU_STATE_COOKIE: -** Valid if STAGE==1. The current change-counter cookie value in the -** target db file. -** -** RBU_STATE_OALSZ: -** Valid if STAGE==1. The size in bytes of the *-oal file. -** -** RBU_STATE_DATATBL: -** Only valid if STAGE==1. The RBU database name of the table -** currently being read. -*/ -#define RBU_STATE_STAGE 1 -#define RBU_STATE_TBL 2 -#define RBU_STATE_IDX 3 -#define RBU_STATE_ROW 4 -#define RBU_STATE_PROGRESS 5 -#define RBU_STATE_CKPT 6 -#define RBU_STATE_COOKIE 7 -#define RBU_STATE_OALSZ 8 -#define RBU_STATE_PHASEONESTEP 9 -#define RBU_STATE_DATATBL 10 - -#define RBU_STAGE_OAL 1 -#define RBU_STAGE_MOVE 2 -#define RBU_STAGE_CAPTURE 3 -#define RBU_STAGE_CKPT 4 -#define RBU_STAGE_DONE 5 - - -#define RBU_CREATE_STATE \ - "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" - -typedef struct RbuFrame RbuFrame; -typedef struct RbuObjIter RbuObjIter; -typedef struct RbuState RbuState; -typedef struct RbuSpan RbuSpan; -typedef struct rbu_vfs rbu_vfs; -typedef struct rbu_file rbu_file; -typedef struct RbuUpdateStmt RbuUpdateStmt; - -#if !defined(SQLITE_AMALGAMATION) -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; -typedef sqlite3_int64 i64; -typedef sqlite3_uint64 u64; -#endif - -/* -** These values must match the values defined in wal.c for the equivalent -** locks. These are not magic numbers as they are part of the SQLite file -** format. -*/ -#define WAL_LOCK_WRITE 0 -#define WAL_LOCK_CKPT 1 -#define WAL_LOCK_READ0 3 - -#define SQLITE_FCNTL_RBUCNT 5149216 - -/* -** A structure to store values read from the rbu_state table in memory. -*/ -struct RbuState { - int eStage; - char *zTbl; - char *zDataTbl; - char *zIdx; - i64 iWalCksum; - int nRow; - i64 nProgress; - u32 iCookie; - i64 iOalSz; - i64 nPhaseOneStep; -}; - -struct RbuUpdateStmt { - char *zMask; /* Copy of update mask used with pUpdate */ - sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ - RbuUpdateStmt *pNext; -}; - -struct RbuSpan { - const char *zSpan; - int nSpan; -}; - -/* -** An iterator of this type is used to iterate through all objects in -** the target database that require updating. For each such table, the -** iterator visits, in order: -** -** * the table itself, -** * each index of the table (zero or more points to visit), and -** * a special "cleanup table" state. -** -** abIndexed: -** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, -** it points to an array of flags nTblCol elements in size. The flag is -** set for each column that is either a part of the PK or a part of an -** index. Or clear otherwise. -** -** If there are one or more partial indexes on the table, all fields of -** this array set set to 1. This is because in that case, the module has -** no way to tell which fields will be required to add and remove entries -** from the partial indexes. -** -*/ -struct RbuObjIter { - sqlite3_stmt *pTblIter; /* Iterate through tables */ - sqlite3_stmt *pIdxIter; /* Index iterator */ - int nTblCol; /* Size of azTblCol[] array */ - char **azTblCol; /* Array of unquoted target column names */ - char **azTblType; /* Array of target column types */ - int *aiSrcOrder; /* src table col -> target table col */ - u8 *abTblPk; /* Array of flags, set on target PK columns */ - u8 *abNotNull; /* Array of flags, set on NOT NULL columns */ - u8 *abIndexed; /* Array of flags, set on indexed & PK cols */ - int eType; /* Table type - an RBU_PK_XXX value */ - - /* Output variables. zTbl==0 implies EOF. */ - int bCleanup; /* True in "cleanup" state */ - const char *zTbl; /* Name of target db table */ - const char *zDataTbl; /* Name of rbu db table (or null) */ - const char *zIdx; /* Name of target db index (or null) */ - int iTnum; /* Root page of current object */ - int iPkTnum; /* If eType==EXTERNAL, root of PK index */ - int bUnique; /* Current index is unique */ - int nIndex; /* Number of aux. indexes on table zTbl */ - - /* Statements created by rbuObjIterPrepareAll() */ - int nCol; /* Number of columns in current object */ - sqlite3_stmt *pSelect; /* Source data */ - sqlite3_stmt *pInsert; /* Statement for INSERT operations */ - sqlite3_stmt *pDelete; /* Statement for DELETE ops */ - sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ - int nIdxCol; - RbuSpan *aIdxCol; - char *zIdxSql; - - /* Last UPDATE used (for PK b-tree updates only), or NULL. */ - RbuUpdateStmt *pRbuUpdate; -}; - -/* -** Values for RbuObjIter.eType -** -** 0: Table does not exist (error) -** 1: Table has an implicit rowid. -** 2: Table has an explicit IPK column. -** 3: Table has an external PK index. -** 4: Table is WITHOUT ROWID. -** 5: Table is a virtual table. -*/ -#define RBU_PK_NOTABLE 0 -#define RBU_PK_NONE 1 -#define RBU_PK_IPK 2 -#define RBU_PK_EXTERNAL 3 -#define RBU_PK_WITHOUT_ROWID 4 -#define RBU_PK_VTAB 5 - - -/* -** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs -** one of the following operations. -*/ -#define RBU_INSERT 1 /* Insert on a main table b-tree */ -#define RBU_DELETE 2 /* Delete a row from a main table b-tree */ -#define RBU_REPLACE 3 /* Delete and then insert a row */ -#define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */ -#define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */ - -#define RBU_UPDATE 6 /* Update a row in a main table b-tree */ - -/* -** A single step of an incremental checkpoint - frame iWalFrame of the wal -** file should be copied to page iDbPage of the database file. -*/ -struct RbuFrame { - u32 iDbPage; - u32 iWalFrame; -}; - -#ifndef UNUSED_PARAMETER -/* -** The following macros are used to suppress compiler warnings and to -** make it clear to human readers when a function parameter is deliberately -** left unused within the body of a function. This usually happens when -** a function is called via a function pointer. For example the -** implementation of an SQL aggregate step callback may not use the -** parameter indicating the number of arguments passed to the aggregate, -** if it knows that this is enforced elsewhere. -** -** When a function parameter is not used at all within the body of a function, -** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. -** However, these macros may also be used to suppress warnings related to -** parameters that may or may not be used depending on compilation options. -** For example those parameters only used in assert() statements. In these -** cases the parameters are named as per the usual conventions. -*/ -#define UNUSED_PARAMETER(x) (void)(x) -#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) -#endif - -/* -** RBU handle. -** -** nPhaseOneStep: -** If the RBU database contains an rbu_count table, this value is set to -** a running estimate of the number of b-tree operations required to -** finish populating the *-oal file. This allows the sqlite3_bp_progress() -** API to calculate the permyriadage progress of populating the *-oal file -** using the formula: -** -** permyriadage = (10000 * nProgress) / nPhaseOneStep -** -** nPhaseOneStep is initialized to the sum of: -** -** nRow * (nIndex + 1) -** -** for all source tables in the RBU database, where nRow is the number -** of rows in the source table and nIndex the number of indexes on the -** corresponding target database table. -** -** This estimate is accurate if the RBU update consists entirely of -** INSERT operations. However, it is inaccurate if: -** -** * the RBU update contains any UPDATE operations. If the PK specified -** for an UPDATE operation does not exist in the target table, then -** no b-tree operations are required on index b-trees. Or if the -** specified PK does exist, then (nIndex*2) such operations are -** required (one delete and one insert on each index b-tree). -** -** * the RBU update contains any DELETE operations for which the specified -** PK does not exist. In this case no operations are required on index -** b-trees. -** -** * the RBU update contains REPLACE operations. These are similar to -** UPDATE operations. -** -** nPhaseOneStep is updated to account for the conditions above during the -** first pass of each source table. The updated nPhaseOneStep value is -** stored in the rbu_state table if the RBU update is suspended. -*/ -struct sqlite3rbu { - int eStage; /* Value of RBU_STATE_STAGE field */ - sqlite3 *dbMain; /* target database handle */ - sqlite3 *dbRbu; /* rbu database handle */ - char *zTarget; /* Path to target db */ - char *zRbu; /* Path to rbu db */ - char *zState; /* Path to state db (or NULL if zRbu) */ - char zStateDb[5]; /* Db name for state ("stat" or "main") */ - int rc; /* Value returned by last rbu_step() call */ - char *zErrmsg; /* Error message if rc!=SQLITE_OK */ - int nStep; /* Rows processed for current object */ - sqlite3_int64 nProgress; /* Rows processed for all objects */ - RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ - const char *zVfsName; /* Name of automatically created rbu vfs */ - rbu_file *pTargetFd; /* File handle open on target db */ - int nPagePerSector; /* Pages per sector for pTargetFd */ - i64 iOalSz; - i64 nPhaseOneStep; - void *pRenameArg; - int (*xRename)(void*, const char*, const char*); - - /* The following state variables are used as part of the incremental - ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding - ** function rbuSetupCheckpoint() for details. */ - u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ - u32 mLock; - int nFrame; /* Entries in aFrame[] array */ - int nFrameAlloc; /* Allocated size of aFrame[] array */ - RbuFrame *aFrame; - int pgsz; - u8 *aBuf; - i64 iWalCksum; - i64 szTemp; /* Current size of all temp files in use */ - i64 szTempLimit; /* Total size limit for temp files */ - - /* Used in RBU vacuum mode only */ - int nRbu; /* Number of RBU VFS in the stack */ - rbu_file *pRbuFd; /* Fd for main db of dbRbu */ -}; - -/* -** An rbu VFS is implemented using an instance of this structure. -** -** Variable pRbu is only non-NULL for automatically created RBU VFS objects. -** It is NULL for RBU VFS objects created explicitly using -** sqlite3rbu_create_vfs(). It is used to track the total amount of temp -** space used by the RBU handle. -*/ -struct rbu_vfs { - sqlite3_vfs base; /* rbu VFS shim methods */ - sqlite3_vfs *pRealVfs; /* Underlying VFS */ - sqlite3_mutex *mutex; /* Mutex to protect pMain */ - sqlite3rbu *pRbu; /* Owner RBU object */ - rbu_file *pMain; /* List of main db files */ - rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ -}; - -/* -** Each file opened by an rbu VFS is represented by an instance of -** the following structure. -** -** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable -** "sz" is set to the current size of the database file. -*/ -struct rbu_file { - sqlite3_file base; /* sqlite3_file methods */ - sqlite3_file *pReal; /* Underlying file handle */ - rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ - sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ - i64 sz; /* Size of file in bytes (temp only) */ - - int openFlags; /* Flags this file was opened with */ - u32 iCookie; /* Cookie value for main db files */ - u8 iWriteVer; /* "write-version" value for main db files */ - u8 bNolock; /* True to fail EXCLUSIVE locks */ - - int nShm; /* Number of entries in apShm[] array */ - char **apShm; /* Array of mmap'd *-shm regions */ - char *zDel; /* Delete this when closing file */ - - const char *zWal; /* Wal filename for this main db file */ - rbu_file *pWalFd; /* Wal file descriptor for this main db */ - rbu_file *pMainNext; /* Next MAIN_DB file */ - rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ -}; - -/* -** True for an RBU vacuum handle, or false otherwise. -*/ -#define rbuIsVacuum(p) ((p)->zTarget==0) - - -/************************************************************************* -** The following three functions, found below: -** -** rbuDeltaGetInt() -** rbuDeltaChecksum() -** rbuDeltaApply() -** -** are lifted from the fossil source code (http://fossil-scm.org). They -** are used to implement the scalar SQL function rbu_fossil_delta(). -*/ - -/* -** Read bytes from *pz and convert them into a positive integer. When -** finished, leave *pz pointing to the first character past the end of -** the integer. The *pLen parameter holds the length of the string -** in *pz and is decremented once for each character in the integer. -*/ -static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){ - static const signed char zValue[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36, - -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1, - }; - unsigned int v = 0; - int c; - unsigned char *z = (unsigned char*)*pz; - unsigned char *zStart = z; - while( (c = zValue[0x7f&*(z++)])>=0 ){ - v = (v<<6) + c; - } - z--; - *pLen -= (int)(z - zStart); - *pz = (char*)z; - return v; -} - -#if RBU_ENABLE_DELTA_CKSUM -/* -** Compute a 32-bit checksum on the N-byte buffer. Return the result. -*/ -static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){ - const unsigned char *z = (const unsigned char *)zIn; - unsigned sum0 = 0; - unsigned sum1 = 0; - unsigned sum2 = 0; - unsigned sum3 = 0; - while(N >= 16){ - sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]); - sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]); - sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]); - sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]); - z += 16; - N -= 16; - } - while(N >= 4){ - sum0 += z[0]; - sum1 += z[1]; - sum2 += z[2]; - sum3 += z[3]; - z += 4; - N -= 4; - } - sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24); - switch(N){ - case 3: sum3 += (z[2] << 8); - case 2: sum3 += (z[1] << 16); - case 1: sum3 += (z[0] << 24); - default: ; - } - return sum3; -} -#endif - -/* -** Apply a delta. -** -** The output buffer should be big enough to hold the whole output -** file and a NUL terminator at the end. The delta_output_size() -** routine will determine this size for you. -** -** The delta string should be null-terminated. But the delta string -** may contain embedded NUL characters (if the input and output are -** binary files) so we also have to pass in the length of the delta in -** the lenDelta parameter. -** -** This function returns the size of the output file in bytes (excluding -** the final NUL terminator character). Except, if the delta string is -** malformed or intended for use with a source file other than zSrc, -** then this routine returns -1. -** -** Refer to the delta_create() documentation above for a description -** of the delta file format. -*/ -static int rbuDeltaApply( - const char *zSrc, /* The source or pattern file */ - int lenSrc, /* Length of the source file */ - const char *zDelta, /* Delta to apply to the pattern */ - int lenDelta, /* Length of the delta */ - char *zOut /* Write the output into this preallocated buffer */ -){ - unsigned int limit; - unsigned int total = 0; -#if RBU_ENABLE_DELTA_CKSUM - char *zOrigOut = zOut; -#endif - - limit = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - zDelta++; lenDelta--; - while( *zDelta && lenDelta>0 ){ - unsigned int cnt, ofst; - cnt = rbuDeltaGetInt(&zDelta, &lenDelta); - switch( zDelta[0] ){ - case '@': { - zDelta++; lenDelta--; - ofst = rbuDeltaGetInt(&zDelta, &lenDelta); - if( lenDelta>0 && zDelta[0]!=',' ){ - /* ERROR: copy command not terminated by ',' */ - return -1; - } - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: copy exceeds output file size */ - return -1; - } - if( (int)(ofst+cnt) > lenSrc ){ - /* ERROR: copy extends past end of input */ - return -1; - } - memcpy(zOut, &zSrc[ofst], cnt); - zOut += cnt; - break; - } - case ':': { - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: insert command gives an output larger than predicted */ - return -1; - } - if( (int)cnt>lenDelta ){ - /* ERROR: insert count exceeds size of delta */ - return -1; - } - memcpy(zOut, zDelta, cnt); - zOut += cnt; - zDelta += cnt; - lenDelta -= cnt; - break; - } - case ';': { - zDelta++; lenDelta--; - zOut[0] = 0; -#if RBU_ENABLE_DELTA_CKSUM - if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ - /* ERROR: bad checksum */ - return -1; - } -#endif - if( total!=limit ){ - /* ERROR: generated size does not match predicted size */ - return -1; - } - return total; - } - default: { - /* ERROR: unknown delta operator */ - return -1; - } - } - } - /* ERROR: unterminated delta */ - return -1; -} - -static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){ - int size; - size = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - return size; -} - -/* -** End of code taken from fossil. -*************************************************************************/ - -/* -** Implementation of SQL scalar function rbu_fossil_delta(). -** -** This function applies a fossil delta patch to a blob. Exactly two -** arguments must be passed to this function. The first is the blob to -** patch and the second the patch to apply. If no error occurs, this -** function returns the patched blob. -*/ -static void rbuFossilDeltaFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *aDelta; - int nDelta; - const char *aOrig; - int nOrig; - - int nOut; - int nOut2; - char *aOut; - - assert( argc==2 ); - UNUSED_PARAMETER(argc); - - nOrig = sqlite3_value_bytes(argv[0]); - aOrig = (const char*)sqlite3_value_blob(argv[0]); - nDelta = sqlite3_value_bytes(argv[1]); - aDelta = (const char*)sqlite3_value_blob(argv[1]); - - /* Figure out the size of the output */ - nOut = rbuDeltaOutputSize(aDelta, nDelta); - if( nOut<0 ){ - sqlite3_result_error(context, "corrupt fossil delta", -1); - return; - } - - aOut = sqlite3_malloc(nOut+1); - if( aOut==0 ){ - sqlite3_result_error_nomem(context); - }else{ - nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut); - if( nOut2!=nOut ){ - sqlite3_free(aOut); - sqlite3_result_error(context, "corrupt fossil delta", -1); - }else{ - sqlite3_result_blob(context, aOut, nOut, sqlite3_free); - } - } -} - - -/* -** Prepare the SQL statement in buffer zSql against database handle db. -** If successful, set *ppStmt to point to the new statement and return -** SQLITE_OK. -** -** Otherwise, if an error does occur, set *ppStmt to NULL and return -** an SQLite error code. Additionally, set output variable *pzErrmsg to -** point to a buffer containing an error message. It is the responsibility -** of the caller to (eventually) free this buffer using sqlite3_free(). -*/ -static int prepareAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - const char *zSql -){ - int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - *ppStmt = 0; - } - return rc; -} - -/* -** Reset the SQL statement passed as the first argument. Return a copy -** of the value returned by sqlite3_reset(). -** -** If an error has occurred, then set *pzErrmsg to point to a buffer -** containing an error message. It is the responsibility of the caller -** to eventually free this buffer using sqlite3_free(). -*/ -static int resetAndCollectError(sqlite3_stmt *pStmt, char **pzErrmsg){ - int rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt))); - } - return rc; -} - -/* -** Unless it is NULL, argument zSql points to a buffer allocated using -** sqlite3_malloc containing an SQL statement. This function prepares the SQL -** statement against database db and frees the buffer. If statement -** compilation is successful, *ppStmt is set to point to the new statement -** handle and SQLITE_OK is returned. -** -** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code -** returned. In this case, *pzErrmsg may also be set to point to an error -** message. It is the responsibility of the caller to free this error message -** buffer using sqlite3_free(). -** -** If argument zSql is NULL, this function assumes that an OOM has occurred. -** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL. -*/ -static int prepareFreeAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - char *zSql -){ - int rc; - assert( *pzErrmsg==0 ); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - *ppStmt = 0; - }else{ - rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); - sqlite3_free(zSql); - } - return rc; -} - -/* -** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated -** by an earlier call to rbuObjIterCacheTableInfo(). -*/ -static void rbuObjIterFreeCols(RbuObjIter *pIter){ - int i; - for(i=0; inTblCol; i++){ - sqlite3_free(pIter->azTblCol[i]); - sqlite3_free(pIter->azTblType[i]); - } - sqlite3_free(pIter->azTblCol); - pIter->azTblCol = 0; - pIter->azTblType = 0; - pIter->aiSrcOrder = 0; - pIter->abTblPk = 0; - pIter->abNotNull = 0; - pIter->nTblCol = 0; - pIter->eType = 0; /* Invalid value */ -} - -/* -** Finalize all statements and free all allocations that are specific to -** the current object (table/index pair). -*/ -static void rbuObjIterClearStatements(RbuObjIter *pIter){ - RbuUpdateStmt *pUp; - - sqlite3_finalize(pIter->pSelect); - sqlite3_finalize(pIter->pInsert); - sqlite3_finalize(pIter->pDelete); - sqlite3_finalize(pIter->pTmpInsert); - pUp = pIter->pRbuUpdate; - while( pUp ){ - RbuUpdateStmt *pTmp = pUp->pNext; - sqlite3_finalize(pUp->pUpdate); - sqlite3_free(pUp); - pUp = pTmp; - } - sqlite3_free(pIter->aIdxCol); - sqlite3_free(pIter->zIdxSql); - - pIter->pSelect = 0; - pIter->pInsert = 0; - pIter->pDelete = 0; - pIter->pRbuUpdate = 0; - pIter->pTmpInsert = 0; - pIter->nCol = 0; - pIter->nIdxCol = 0; - pIter->aIdxCol = 0; - pIter->zIdxSql = 0; -} - -/* -** Clean up any resources allocated as part of the iterator object passed -** as the only argument. -*/ -static void rbuObjIterFinalize(RbuObjIter *pIter){ - rbuObjIterClearStatements(pIter); - sqlite3_finalize(pIter->pTblIter); - sqlite3_finalize(pIter->pIdxIter); - rbuObjIterFreeCols(pIter); - memset(pIter, 0, sizeof(RbuObjIter)); -} - -/* -** Advance the iterator to the next position. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the next entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ - int rc = p->rc; - if( rc==SQLITE_OK ){ - - /* Free any SQLite statements used while processing the previous object */ - rbuObjIterClearStatements(pIter); - if( pIter->zIdx==0 ){ - rc = sqlite3_exec(p->dbMain, - "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update2_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_delete_tr;" - , 0, 0, &p->zErrmsg - ); - } - - if( rc==SQLITE_OK ){ - if( pIter->bCleanup ){ - rbuObjIterFreeCols(pIter); - pIter->bCleanup = 0; - rc = sqlite3_step(pIter->pTblIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); - pIter->zTbl = 0; - pIter->zDataTbl = 0; - }else{ - pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); - pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); - rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; - } - }else{ - if( pIter->zIdx==0 ){ - sqlite3_stmt *pIdx = pIter->pIdxIter; - rc = sqlite3_bind_text(pIdx, 1, pIter->zTbl, -1, SQLITE_STATIC); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_step(pIter->pIdxIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pIdxIter, &p->zErrmsg); - pIter->bCleanup = 1; - pIter->zIdx = 0; - }else{ - pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0); - pIter->iTnum = sqlite3_column_int(pIter->pIdxIter, 1); - pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2); - rc = pIter->zIdx ? SQLITE_OK : SQLITE_NOMEM; - } - } - } - } - } - - if( rc!=SQLITE_OK ){ - rbuObjIterFinalize(pIter); - p->rc = rc; - } - return rc; -} - - -/* -** The implementation of the rbu_target_name() SQL function. This function -** accepts one or two arguments. The first argument is the name of a table - -** the name of a table in the RBU database. The second, if it is present, is 1 -** for a view or 0 for a table. -** -** For a non-vacuum RBU handle, if the table name matches the pattern: -** -** data[0-9]_ -** -** where is any sequence of 1 or more characters, is returned. -** Otherwise, if the only argument does not match the above pattern, an SQL -** NULL is returned. -** -** "data_t1" -> "t1" -** "data0123_t2" -> "t2" -** "dataAB_t3" -> NULL -** -** For an rbu vacuum handle, a copy of the first argument is returned if -** the second argument is either missing or 0 (not a view). -*/ -static void rbuTargetNameFunc( - sqlite3_context *pCtx, - int argc, - sqlite3_value **argv -){ - sqlite3rbu *p = sqlite3_user_data(pCtx); - const char *zIn; - assert( argc==1 || argc==2 ); - - zIn = (const char*)sqlite3_value_text(argv[0]); - if( zIn ){ - if( rbuIsVacuum(p) ){ - assert( argc==2 || argc==1 ); - if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ - sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); - } - }else{ - if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ - int i; - for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); - if( zIn[i]=='_' && zIn[i+1] ){ - sqlite3_result_text(pCtx, &zIn[i+1], -1, SQLITE_STATIC); - } - } - } - } -} - -/* -** Initialize the iterator structure passed as the second argument. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the first entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ - int rc; - memset(pIter, 0, sizeof(RbuObjIter)); - - rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, - sqlite3_mprintf( - "SELECT rbu_target_name(name, type='view') AS target, name " - "FROM sqlite_schema " - "WHERE type IN ('table', 'view') AND target IS NOT NULL " - " %s " - "ORDER BY name" - , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : "")); - - if( rc==SQLITE_OK ){ - rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, - "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " - " FROM main.sqlite_schema " - " WHERE type='index' AND tbl_name = ?" - ); - } - - pIter->bCleanup = 1; - p->rc = rc; - return rbuObjIterNext(p, pIter); -} - -/* -** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, -** an error code is stored in the RBU handle passed as the first argument. -** -** If an error has already occurred (p->rc is already set to something other -** than SQLITE_OK), then this function returns NULL without modifying the -** stored error code. In this case it still calls sqlite3_free() on any -** printf() parameters associated with %z conversions. -*/ -static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ - char *zSql = 0; - va_list ap; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ) p->rc = SQLITE_NOMEM; - }else{ - sqlite3_free(zSql); - zSql = 0; - } - va_end(ap); - return zSql; -} - -/* -** Argument zFmt is a sqlite3_mprintf() style format string. The trailing -** arguments are the usual subsitution values. This function performs -** the printf() style substitutions and executes the result as an SQL -** statement on the RBU handles database. -** -** If an error occurs, an error code and error message is stored in the -** RBU handle. If an error has already occurred when this function is -** called, it is a no-op. -*/ -static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ - va_list ap; - char *zSql; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg); - } - } - sqlite3_free(zSql); - va_end(ap); - return p->rc; -} - -/* -** Attempt to allocate and return a pointer to a zeroed block of nByte -** bytes. -** -** If an error (i.e. an OOM condition) occurs, return NULL and leave an -** error code in the rbu handle passed as the first argument. Or, if an -** error has already occurred when this function is called, return NULL -** immediately without attempting the allocation or modifying the stored -** error code. -*/ -static void *rbuMalloc(sqlite3rbu *p, sqlite3_int64 nByte){ - void *pRet = 0; - if( p->rc==SQLITE_OK ){ - assert( nByte>0 ); - pRet = sqlite3_malloc64(nByte); - if( pRet==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - memset(pRet, 0, nByte); - } - } - return pRet; -} - - -/* -** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that -** there is room for at least nCol elements. If an OOM occurs, store an -** error code in the RBU handle passed as the first argument. -*/ -static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ - sqlite3_int64 nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; - char **azNew; - - azNew = (char**)rbuMalloc(p, nByte); - if( azNew ){ - pIter->azTblCol = azNew; - pIter->azTblType = &azNew[nCol]; - pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol]; - pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol]; - pIter->abNotNull = (u8*)&pIter->abTblPk[nCol]; - pIter->abIndexed = (u8*)&pIter->abNotNull[nCol]; - } -} - -/* -** The first argument must be a nul-terminated string. This function -** returns a copy of the string in memory obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free this memory -** using sqlite3_free(). -** -** If an OOM condition is encountered when attempting to allocate memory, -** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, -** if the allocation succeeds, (*pRc) is left unchanged. -*/ -static char *rbuStrndup(const char *zStr, int *pRc){ - char *zRet = 0; - - if( *pRc==SQLITE_OK ){ - if( zStr ){ - size_t nCopy = strlen(zStr) + 1; - zRet = (char*)sqlite3_malloc64(nCopy); - if( zRet ){ - memcpy(zRet, zStr, nCopy); - }else{ - *pRc = SQLITE_NOMEM; - } - } - } - - return zRet; -} - -/* -** Finalize the statement passed as the second argument. -** -** If the sqlite3_finalize() call indicates that an error occurs, and the -** rbu handle error code is not already set, set the error code and error -** message accordingly. -*/ -static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){ - sqlite3 *db = sqlite3_db_handle(pStmt); - int rc = sqlite3_finalize(pStmt); - if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){ - p->rc = rc; - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } -} - -/* Determine the type of a table. -** -** peType is of type (int*), a pointer to an output parameter of type -** (int). This call sets the output parameter as follows, depending -** on the type of the table specified by parameters dbName and zTbl. -** -** RBU_PK_NOTABLE: No such table. -** RBU_PK_NONE: Table has an implicit rowid. -** RBU_PK_IPK: Table has an explicit IPK column. -** RBU_PK_EXTERNAL: Table has an external PK index. -** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. -** RBU_PK_VTAB: Table is a virtual table. -** -** Argument *piPk is also of type (int*), and also points to an output -** parameter. Unless the table has an external primary key index -** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, -** if the table does have an external primary key index, then *piPk -** is set to the root page number of the primary key index before -** returning. -** -** ALGORITHM: -** -** if( no entry exists in sqlite_schema ){ -** return RBU_PK_NOTABLE -** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ -** return RBU_PK_VTAB -** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ -** if( the index that is the pk exists in sqlite_schema ){ -** *piPK = rootpage of that index. -** return RBU_PK_EXTERNAL -** }else{ -** return RBU_PK_WITHOUT_ROWID -** } -** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ -** return RBU_PK_IPK -** }else{ -** return RBU_PK_NONE -** } -*/ -static void rbuTableType( - sqlite3rbu *p, - const char *zTab, - int *peType, - int *piTnum, - int *piPk -){ - /* - ** 0) SELECT count(*) FROM sqlite_schema where name=%Q AND IsVirtual(%Q) - ** 1) PRAGMA index_list = ? - ** 2) SELECT count(*) FROM sqlite_schema where name=%Q - ** 3) PRAGMA table_info = ? - */ - sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; - - *peType = RBU_PK_NOTABLE; - *piPk = 0; - - assert( p->rc==SQLITE_OK ); - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, - sqlite3_mprintf( - "SELECT " - " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM')," - " rootpage" - " FROM sqlite_schema" - " WHERE name=%Q", zTab - )); - if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ - /* Either an error, or no such table. */ - goto rbuTableType_end; - } - if( sqlite3_column_int(aStmt[0], 0) ){ - *peType = RBU_PK_VTAB; /* virtual table */ - goto rbuTableType_end; - } - *piTnum = sqlite3_column_int(aStmt[0], 1); - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, - sqlite3_mprintf("PRAGMA index_list=%Q",zTab) - ); - if( p->rc ) goto rbuTableType_end; - while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ - const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); - const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); - if( zOrig && zIdx && zOrig[0]=='p' ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, - sqlite3_mprintf( - "SELECT rootpage FROM sqlite_schema WHERE name = %Q", zIdx - )); - if( p->rc==SQLITE_OK ){ - if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ - *piPk = sqlite3_column_int(aStmt[2], 0); - *peType = RBU_PK_EXTERNAL; - }else{ - *peType = RBU_PK_WITHOUT_ROWID; - } - } - goto rbuTableType_end; - } - } - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info=%Q",zTab) - ); - if( p->rc==SQLITE_OK ){ - while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ - if( sqlite3_column_int(aStmt[3],5)>0 ){ - *peType = RBU_PK_IPK; /* explicit IPK column */ - goto rbuTableType_end; - } - } - *peType = RBU_PK_NONE; - } - -rbuTableType_end: { - unsigned int i; - for(i=0; iabIndexed[] array. -*/ -static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ - sqlite3_stmt *pList = 0; - int bIndex = 0; - - if( p->rc==SQLITE_OK ){ - memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); - p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - } - - pIter->nIndex = 0; - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ - const char *zIdx = (const char*)sqlite3_column_text(pList, 1); - int bPartial = sqlite3_column_int(pList, 4); - sqlite3_stmt *pXInfo = 0; - if( zIdx==0 ) break; - if( bPartial ){ - memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); - } - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - if( iCid>=0 ) pIter->abIndexed[iCid] = 1; - if( iCid==-2 ){ - memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); - } - } - rbuFinalize(p, pXInfo); - bIndex = 1; - pIter->nIndex++; - } - - if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ - /* "PRAGMA index_list" includes the main PK b-tree */ - pIter->nIndex--; - } - - rbuFinalize(p, pList); - if( bIndex==0 ) pIter->abIndexed = 0; -} - - -/* -** If they are not already populated, populate the pIter->azTblCol[], -** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to -** the table (not index) that the iterator currently points to. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. If -** an error does occur, an error code and error message are also left in -** the RBU handle. -*/ -static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ - if( pIter->azTblCol==0 ){ - sqlite3_stmt *pStmt = 0; - int nCol = 0; - int i; /* for() loop iterator variable */ - int bRbuRowid = 0; /* If input table has column "rbu_rowid" */ - int iOrder = 0; - int iTnum = 0; - - /* Figure out the type of table this step will deal with. */ - assert( pIter->eType==0 ); - rbuTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_NOTABLE ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); - } - if( p->rc ) return p->rc; - if( pIter->zIdx==0 ) pIter->iTnum = iTnum; - - assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK - || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID - || pIter->eType==RBU_PK_VTAB - ); - - /* Populate the azTblCol[] and nTblCol variables based on the columns - ** of the input table. Ignore any input table columns that begin with - ** "rbu_". */ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT * FROM '%q'", pIter->zDataTbl) - ); - if( p->rc==SQLITE_OK ){ - nCol = sqlite3_column_count(pStmt); - rbuAllocateIterArrays(p, pIter, nCol); - } - for(i=0; p->rc==SQLITE_OK && irc); - pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol; - pIter->azTblCol[pIter->nTblCol++] = zCopy; - } - else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ - bRbuRowid = 1; - } - } - sqlite3_finalize(pStmt); - pStmt = 0; - - if( p->rc==SQLITE_OK - && rbuIsVacuum(p)==0 - && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) - ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf( - "table %q %s rbu_rowid column", pIter->zDataTbl, - (bRbuRowid ? "may not have" : "requires") - ); - } - - /* Check that all non-HIDDEN columns in the destination table are also - ** present in the input table. Populate the abTblPk[], azTblType[] and - ** aiTblOrder[] arrays at the same time. */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl) - ); - } - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zName = (const char*)sqlite3_column_text(pStmt, 1); - if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */ - for(i=iOrder; inTblCol; i++){ - if( 0==strcmp(zName, pIter->azTblCol[i]) ) break; - } - if( i==pIter->nTblCol ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("column missing from %q: %s", - pIter->zDataTbl, zName - ); - }else{ - int iPk = sqlite3_column_int(pStmt, 5); - int bNotNull = sqlite3_column_int(pStmt, 3); - const char *zType = (const char*)sqlite3_column_text(pStmt, 2); - - if( i!=iOrder ){ - SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); - SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); - } - - pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); - assert( iPk>=0 ); - pIter->abTblPk[iOrder] = (u8)iPk; - pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); - iOrder++; - } - } - - rbuFinalize(p, pStmt); - rbuObjIterCacheIndexedCols(p, pIter); - assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); - assert( pIter->eType!=RBU_PK_VTAB || pIter->nIndex==0 ); - } - - return p->rc; -} - -/* -** This function constructs and returns a pointer to a nul-terminated -** string containing some SQL clause or list based on one or more of the -** column names currently stored in the pIter->azTblCol[] array. -*/ -static char *rbuObjIterGetCollist( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter /* Object iterator for column names */ -){ - char *zList = 0; - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - const char *z = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z); - zSep = ", "; - } - return zList; -} - -/* -** Return a comma separated list of the quoted PRIMARY KEY column names, -** in order, for the current table. Before each column name, add the text -** zPre. After each column name, add the zPost text. Use zSeparator as -** the separator text (usually ", "). -*/ -static char *rbuObjIterGetPkList( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter, /* Object iterator for column names */ - const char *zPre, /* Before each quoted column name */ - const char *zSeparator, /* Separator to use between columns */ - const char *zPost /* After each quoted column name */ -){ - int iPk = 1; - char *zRet = 0; - const char *zSep = ""; - while( 1 ){ - int i; - for(i=0; inTblCol; i++){ - if( (int)pIter->abTblPk[i]==iPk ){ - const char *zCol = pIter->azTblCol[i]; - zRet = rbuMPrintf(p, "%z%s%s\"%w\"%s", zRet, zSep, zPre, zCol, zPost); - zSep = zSeparator; - break; - } - } - if( i==pIter->nTblCol ) break; - iPk++; - } - return zRet; -} - -/* -** This function is called as part of restarting an RBU vacuum within -** stage 1 of the process (while the *-oal file is being built) while -** updating a table (not an index). The table may be a rowid table or -** a WITHOUT ROWID table. It queries the target database to find the -** largest key that has already been written to the target table and -** constructs a WHERE clause that can be used to extract the remaining -** rows from the source table. For a rowid table, the WHERE clause -** is of the form: -** -** "WHERE _rowid_ > ?" -** -** and for WITHOUT ROWID tables: -** -** "WHERE (key1, key2) > (?, ?)" -** -** Instead of "?" placeholders, the actual WHERE clauses created by -** this function contain literal SQL values. -*/ -static char *rbuVacuumTableStart( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter, /* RBU iterator object */ - int bRowid, /* True for a rowid table */ - const char *zWrite /* Target table name prefix */ -){ - sqlite3_stmt *pMax = 0; - char *zRet = 0; - if( bRowid ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, - sqlite3_mprintf( - "SELECT max(_rowid_) FROM \"%s%w\"", zWrite, pIter->zTbl - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ - sqlite3_int64 iMax = sqlite3_column_int64(pMax, 0); - zRet = rbuMPrintf(p, " WHERE _rowid_ > %lld ", iMax); - } - rbuFinalize(p, pMax); - }else{ - char *zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", " DESC"); - char *zSelect = rbuObjIterGetPkList(p, pIter, "quote(", "||','||", ")"); - char *zList = rbuObjIterGetPkList(p, pIter, "", ", ", ""); - - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, - sqlite3_mprintf( - "SELECT %s FROM \"%s%w\" ORDER BY %s LIMIT 1", - zSelect, zWrite, pIter->zTbl, zOrder - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ - const char *zVal = (const char*)sqlite3_column_text(pMax, 0); - zRet = rbuMPrintf(p, " WHERE (%s) > (%s) ", zList, zVal); - } - rbuFinalize(p, pMax); - } - - sqlite3_free(zOrder); - sqlite3_free(zSelect); - sqlite3_free(zList); - } - return zRet; -} - -/* -** This function is called as part of restating an RBU vacuum when the -** current operation is writing content to an index. If possible, it -** queries the target index b-tree for the largest key already written to -** it, then composes and returns an expression that can be used in a WHERE -** clause to select the remaining required rows from the source table. -** It is only possible to return such an expression if: -** -** * The index contains no DESC columns, and -** * The last key written to the index before the operation was -** suspended does not contain any NULL values. -** -** The expression is of the form: -** -** (index-field1, index-field2, ...) > (?, ?, ...) -** -** except that the "?" placeholders are replaced with literal values. -** -** If the expression cannot be created, NULL is returned. In this case, -** 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. -*/ -static char *rbuVacuumIndexStart( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter /* RBU iterator object */ -){ - char *zOrder = 0; - char *zLhs = 0; - char *zSelect = 0; - char *zVector = 0; - char *zRet = 0; - int bFailed = 0; - const char *zSep = ""; - int iCol = 0; - sqlite3_stmt *pXInfo = 0; - - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol; - if( sqlite3_column_int(pXInfo, 3) ){ - bFailed = 1; - break; - } - - if( iCid<0 ){ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else{ - zCol = "_rowid_"; - } - }else{ - zCol = pIter->azTblCol[iCid]; - } - - zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q", - zLhs, zSep, zCol, zCollate - ); - zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC", - zOrder, zSep, iCol, zCol, zCollate - ); - zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")", - zSelect, zSep, iCol, zCol - ); - zSep = ", "; - iCol++; - } - rbuFinalize(p, pXInfo); - if( bFailed ) goto index_start_out; - - if( p->rc==SQLITE_OK ){ - sqlite3_stmt *pSel = 0; - - p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg, - sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1", - zSelect, pIter->zTbl, zOrder - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){ - zSep = ""; - for(iCol=0; iColnCol; iCol++){ - const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol); - if( zQuoted==0 ){ - p->rc = SQLITE_NOMEM; - }else if( zQuoted[0]=='N' ){ - bFailed = 1; - break; - } - zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted); - zSep = ", "; - } - - if( !bFailed ){ - zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector); - } - } - rbuFinalize(p, pSel); - } - - index_start_out: - sqlite3_free(zOrder); - sqlite3_free(zSelect); - sqlite3_free(zVector); - sqlite3_free(zLhs); - return zRet; -} - -/* -** This function is used to create a SELECT list (the list of SQL -** expressions that follows a SELECT keyword) for a SELECT statement -** used to read from an data_xxx or rbu_tmp_xxx table while updating the -** index object currently indicated by the iterator object passed as the -** second argument. A "PRAGMA index_xinfo = " statement is used -** to obtain the required information. -** -** If the index is of the following form: -** -** CREATE INDEX i1 ON t1(c, b COLLATE nocase); -** -** and "t1" is a table with an explicit INTEGER PRIMARY KEY column -** "ipk", the returned string is: -** -** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" -** -** As well as the returned string, three other malloc'd strings are -** returned via output parameters. As follows: -** -** pzImposterCols: ... -** pzImposterPk: ... -** pzWhere: ... -*/ -static char *rbuObjIterGetIndexCols( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter, /* Object iterator for column names */ - char **pzImposterCols, /* OUT: Columns for imposter table */ - char **pzImposterPk, /* OUT: Imposter PK clause */ - char **pzWhere, /* OUT: WHERE clause */ - int *pnBind /* OUT: Trbul number of columns */ -){ - int rc = p->rc; /* Error code */ - int rc2; /* sqlite3_finalize() return code */ - char *zRet = 0; /* String to return */ - char *zImpCols = 0; /* String to return via *pzImposterCols */ - char *zImpPK = 0; /* String to return via *pzImposterPK */ - char *zWhere = 0; /* String to return via *pzWhere */ - int nBind = 0; /* Value to return via *pnBind */ - const char *zCom = ""; /* Set to ", " later on */ - const char *zAnd = ""; /* Set to " AND " later on */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = ? */ - - if( rc==SQLITE_OK ){ - assert( p->zErrmsg==0 ); - rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) - ); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol = 0; - const char *zType; - - if( iCid==-2 ){ - int iSeq = sqlite3_column_int(pXInfo, 0); - zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom, - pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate - ); - zType = ""; - }else { - if( iCid<0 ){ - /* An integer primary key. If the table has an explicit IPK, use - ** its name. Otherwise, use "rbu_rowid". */ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else if( rbuIsVacuum(p) ){ - zCol = "_rowid_"; - }else{ - zCol = "rbu_rowid"; - } - zType = "INTEGER"; - }else{ - zCol = pIter->azTblCol[iCid]; - zType = pIter->azTblType[iCid]; - } - zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate); - } - - if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ - const char *zOrder = (bDesc ? " DESC" : ""); - zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", - zImpPK, zCom, nBind, zCol, zOrder - ); - } - zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", - zImpCols, zCom, nBind, zCol, zType, zCollate - ); - zWhere = sqlite3_mprintf( - "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol - ); - if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM; - zCom = ", "; - zAnd = " AND "; - nBind++; - } - - rc2 = sqlite3_finalize(pXInfo); - if( rc==SQLITE_OK ) rc = rc2; - - if( rc!=SQLITE_OK ){ - sqlite3_free(zRet); - sqlite3_free(zImpCols); - sqlite3_free(zImpPK); - sqlite3_free(zWhere); - zRet = 0; - zImpCols = 0; - zImpPK = 0; - zWhere = 0; - p->rc = rc; - } - - *pzImposterCols = zImpCols; - *pzImposterPk = zImpPK; - *pzWhere = zWhere; - *pnBind = nBind; - return zRet; -} - -/* -** Assuming the current table columns are "a", "b" and "c", and the zObj -** paramter is passed "old", return a string of the form: -** -** "old.a, old.b, old.b" -** -** With the column names escaped. -** -** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append -** the text ", old._rowid_" to the returned value. -*/ -static char *rbuObjIterGetOldlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zObj -){ - char *zList = 0; - if( p->rc==SQLITE_OK && pIter->abIndexed ){ - const char *zS = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abIndexed[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol); - }else{ - zList = sqlite3_mprintf("%z%sNULL", zList, zS); - } - zS = ", "; - if( zList==0 ){ - p->rc = SQLITE_NOMEM; - break; - } - } - - /* For a table with implicit rowids, append "old._rowid_" to the list. */ - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "%z, %s._rowid_", zList, zObj); - } - } - return zList; -} - -/* -** Return an expression that can be used in a WHERE clause to match the -** primary key of the current table. For example, if the table is: -** -** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)); -** -** Return the string: -** -** "b = ?1 AND c = ?2" -*/ -static char *rbuObjIterGetWhere( - sqlite3rbu *p, - RbuObjIter *pIter -){ - char *zList = 0; - if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); - }else if( pIter->eType==RBU_PK_EXTERNAL ){ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); - zSep = " AND "; - } - } - zList = rbuMPrintf(p, - "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList - ); - - }else{ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1); - zSep = " AND "; - } - } - } - return zList; -} - -/* -** The SELECT statement iterating through the keys for the current object -** (p->objiter.pSelect) currently points to a valid row. However, there -** is something wrong with the rbu_control value in the rbu_control value -** stored in the (p->nCol+1)'th column. Set the error code and error message -** of the RBU handle to something reflecting this. -*/ -static void rbuBadControlError(sqlite3rbu *p){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("invalid rbu_control value"); -} - - -/* -** Return a nul-terminated string containing the comma separated list of -** assignments that should be included following the "SET" keyword of -** an UPDATE statement used to update the table object that the iterator -** passed as the second argument currently points to if the rbu_control -** column of the data_xxx table entry is set to zMask. -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetSetlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zMask -){ - char *zList = 0; - if( p->rc==SQLITE_OK ){ - int i; - - if( (int)strlen(zMask)!=pIter->nTblCol ){ - rbuBadControlError(p); - }else{ - const char *zSep = ""; - for(i=0; inTblCol; i++){ - char c = zMask[pIter->aiSrcOrder[i]]; - if( c=='x' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", - zList, zSep, pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='d' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='f' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - } - } - } - return zList; -} - -/* -** Return a nul-terminated string consisting of nByte comma separated -** "?" expressions. For example, if nByte is 3, return a pointer to -** a buffer containing the string "?,?,?". -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ - char *zRet = 0; - sqlite3_int64 nByte = 2*(sqlite3_int64)nBind + 1; - - zRet = (char*)rbuMalloc(p, nByte); - if( zRet ){ - int i; - for(i=0; izIdx==0 ); - if( p->rc==SQLITE_OK ){ - const char *zSep = "PRIMARY KEY("; - sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = */ - - p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){ - const char *zOrig = (const char*)sqlite3_column_text(pXList,3); - if( zOrig && strcmp(zOrig, "pk")==0 ){ - const char *zIdx = (const char*)sqlite3_column_text(pXList,1); - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - break; - } - } - rbuFinalize(p, pXList); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - if( sqlite3_column_int(pXInfo, 5) ){ - /* int iCid = sqlite3_column_int(pXInfo, 0); */ - const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); - const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; - z = rbuMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); - zSep = ", "; - } - } - z = rbuMPrintf(p, "%z)", z); - rbuFinalize(p, pXInfo); - } - return z; -} - -/* -** This function creates the second imposter table used when writing to -** a table b-tree where the table has an external primary key. If the -** iterator passed as the second argument does not currently point to -** a table (not index) with an external primary key, this function is a -** no-op. -** -** Assuming the iterator does point to a table with an external PK, this -** function creates a WITHOUT ROWID imposter table named "rbu_imposter2" -** used to access that PK index. For example, if the target table is -** declared as follows: -** -** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c)); -** -** then the imposter table schema is: -** -** CREATE TABLE rbu_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID; -** -*/ -static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_EXTERNAL ){ - int tnum = pIter->iPkTnum; /* Root page of PK index */ - sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */ - const char *zIdx = 0; /* Name of PK index */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */ - const char *zComma = ""; - char *zCols = 0; /* Used to build up list of table cols */ - char *zPk = 0; /* Used to build up table PK declaration */ - - /* Figure out the name of the primary key index for the current table. - ** This is needed for the argument to "PRAGMA index_xinfo". Set - ** zIdx to point to a nul-terminated string containing this name. */ - p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, - "SELECT name FROM sqlite_schema WHERE rootpage = ?" - ); - if( p->rc==SQLITE_OK ){ - sqlite3_bind_int(pQuery, 1, tnum); - if( SQLITE_ROW==sqlite3_step(pQuery) ){ - zIdx = (const char*)sqlite3_column_text(pQuery, 0); - } - } - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - rbuFinalize(p, pQuery); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int bKey = sqlite3_column_int(pXInfo, 5); - if( bKey ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, - iCid, pIter->azTblType[iCid], zCollate - ); - zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); - zComma = ", "; - } - } - zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); - rbuFinalize(p, pXInfo); - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", - zCols, zPk - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** If an error has already occurred when this function is called, it -** immediately returns zero (without doing any work). Or, if an error -** occurs during the execution of this function, it sets the error code -** in the sqlite3rbu object indicated by the first argument and returns -** zero. -** -** The iterator passed as the second argument is guaranteed to point to -** a table (not an index) when this function is called. This function -** attempts to create any imposter table required to write to the main -** table b-tree of the table before returning. Non-zero is returned if -** an imposter table are created, or zero otherwise. -** -** An imposter table is required in all cases except RBU_PK_VTAB. Only -** virtual tables are written to directly. The imposter table has the -** same schema as the actual target table (less any UNIQUE constraints). -** More precisely, the "same schema" means the same columns, types, -** collation sequences. For tables that do not have an external PRIMARY -** KEY, it also means the same PRIMARY KEY declaration. -*/ -static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){ - int tnum = pIter->iTnum; - const char *zComma = ""; - char *zSql = 0; - int iCol; - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - - for(iCol=0; p->rc==SQLITE_OK && iColnTblCol; iCol++){ - const char *zPk = ""; - const char *zCol = pIter->azTblCol[iCol]; - const char *zColl = 0; - - p->rc = sqlite3_table_column_metadata( - p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0 - ); - - if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ - /* If the target table column is an "INTEGER PRIMARY KEY", add - ** "PRIMARY KEY" to the imposter table column declaration. */ - zPk = "PRIMARY KEY "; - } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", - zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, - (pIter->abNotNull[iCol] ? " NOT NULL" : "") - ); - zComma = ", "; - } - - if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ - char *zPk = rbuWithoutRowidPK(p, pIter); - if( zPk ){ - zSql = rbuMPrintf(p, "%z, %z", zSql, zPk); - } - } - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", - pIter->zTbl, zSql, - (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** Prepare a statement used to insert rows into the "rbu_tmp_xxx" table. -** Specifically a statement of the form: -** -** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...); -** -** The number of bound variables is equal to the number of columns in -** the target table, plus one (for the rbu_control column), plus one more -** (for the rbu_rowid column) if the target table is an implicit IPK or -** virtual table. -*/ -static void rbuObjIterPrepareTmpInsert( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zCollist, - const char *zRbuRowid -){ - int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE); - char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid); - if( zBind ){ - assert( pIter->pTmpInsert==0 ); - p->rc = prepareFreeAndCollectError( - p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( - "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", - p->zStateDb, pIter->zDataTbl, zCollist, zRbuRowid, zBind - )); - } -} - -static void rbuTmpInsertFunc( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - sqlite3rbu *p = sqlite3_user_data(pCtx); - int rc = SQLITE_OK; - int i; - - assert( sqlite3_value_int(apVal[0])!=0 - || p->objiter.eType==RBU_PK_EXTERNAL - || p->objiter.eType==RBU_PK_NONE - ); - if( sqlite3_value_int(apVal[0])!=0 ){ - p->nPhaseOneStep += p->objiter.nIndex; - } - - for(i=0; rc==SQLITE_OK && iobjiter.pTmpInsert, i+1, apVal[i]); - } - if( rc==SQLITE_OK ){ - sqlite3_step(p->objiter.pTmpInsert); - rc = sqlite3_reset(p->objiter.pTmpInsert); - } - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - } -} - -static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ - sqlite3_stmt *pStmt = 0; - int rc = p->rc; - char *zRet = 0; - - assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 ); - - if( rc==SQLITE_OK ){ - rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, - "SELECT trim(sql) FROM sqlite_schema WHERE type='index' AND name=?" - ); - } - if( rc==SQLITE_OK ){ - int rc2; - rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - char *zSql = (char*)sqlite3_column_text(pStmt, 0); - if( zSql ){ - pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc); - } - if( zSql ){ - int nParen = 0; /* Number of open parenthesis */ - int i; - int iIdxCol = 0; - int nIdxAlloc = 0; - for(i=0; zSql[i]; i++){ - char c = zSql[i]; - - /* If necessary, grow the pIter->aIdxCol[] array */ - if( iIdxCol==nIdxAlloc ){ - RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc( - pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan) - ); - if( aIdxCol==0 ){ - rc = SQLITE_NOMEM; - break; - } - pIter->aIdxCol = aIdxCol; - nIdxAlloc += 16; - } - - if( c=='(' ){ - if( nParen==0 ){ - assert( iIdxCol==0 ); - pIter->aIdxCol[0].zSpan = &zSql[i+1]; - } - nParen++; - } - else if( c==')' ){ - nParen--; - if( nParen==0 ){ - int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan); - pIter->aIdxCol[iIdxCol++].nSpan = nSpan; - i++; - break; - } - }else if( c==',' && nParen==1 ){ - int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan); - pIter->aIdxCol[iIdxCol++].nSpan = nSpan; - pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1]; - }else if( c=='"' || c=='\'' || c=='`' ){ - for(i++; 1; i++){ - if( zSql[i]==c ){ - if( zSql[i+1]!=c ) break; - i++; - } - } - }else if( c=='[' ){ - for(i++; 1; i++){ - if( zSql[i]==']' ) break; - } - }else if( c=='-' && zSql[i+1]=='-' ){ - for(i=i+2; zSql[i] && zSql[i]!='\n'; i++); - if( zSql[i]=='\0' ) break; - }else if( c=='/' && zSql[i+1]=='*' ){ - for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++); - if( zSql[i]=='\0' ) break; - i++; - } - } - if( zSql[i] ){ - zRet = rbuStrndup(&zSql[i], &rc); - } - pIter->nIdxCol = iIdxCol; - } - } - - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - } - - p->rc = rc; - return zRet; -} - -/* -** Ensure that the SQLite statement handles required to update the -** target database object currently indicated by the iterator passed -** as the second argument are available. -*/ -static int rbuObjIterPrepareAll( - sqlite3rbu *p, - RbuObjIter *pIter, - int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ -){ - assert( pIter->bCleanup==0 ); - if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ - const int tnum = pIter->iTnum; - char *zCollist = 0; /* List of indexed columns */ - char **pz = &p->zErrmsg; - const char *zIdx = pIter->zIdx; - char *zLimit = 0; - - if( nOffset ){ - zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset); - if( !zLimit ) p->rc = SQLITE_NOMEM; - } - - if( zIdx ){ - const char *zTbl = pIter->zTbl; - char *zImposterCols = 0; /* Columns for imposter table */ - char *zImposterPK = 0; /* Primary key declaration for imposter */ - char *zWhere = 0; /* WHERE clause on PK columns */ - char *zBind = 0; - char *zPart = 0; - int nBind = 0; - - assert( pIter->eType!=RBU_PK_VTAB ); - zPart = rbuObjIterGetIndexWhere(p, pIter); - zCollist = rbuObjIterGetIndexCols( - p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind - ); - zBind = rbuObjIterGetBindlist(p, nBind); - - /* Create the imposter table used to write to this index. */ - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE \"rbu_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID", - zTbl, zImposterCols, zImposterPK - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - - /* Create the statement to insert index entries */ - pIter->nCol = nBind; - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pInsert, &p->zErrmsg, - sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) - ); - } - - /* And to delete index entries */ - if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pDelete, &p->zErrmsg, - sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) - ); - } - - /* Create the SELECT statement to read keys in sorted order */ - if( p->rc==SQLITE_OK ){ - char *zSql; - if( rbuIsVacuum(p) ){ - char *zStart = 0; - if( nOffset ){ - zStart = rbuVacuumIndexStart(p, pIter); - if( zStart ){ - sqlite3_free(zLimit); - zLimit = 0; - } - } - - zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s", - zCollist, - pIter->zDataTbl, - zPart, - (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart, - zCollist, zLimit - ); - sqlite3_free(zStart); - }else - - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, - zPart, zCollist, zLimit - ); - }else{ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s " - "UNION ALL " - "SELECT %s, rbu_control FROM '%q' " - "%s %s typeof(rbu_control)='integer' AND rbu_control!=1 " - "ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, zPart, - zCollist, pIter->zDataTbl, - zPart, - (zPart ? "AND" : "WHERE"), - zCollist, zLimit - ); - } - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql); - }else{ - sqlite3_free(zSql); - } - } - - sqlite3_free(zImposterCols); - sqlite3_free(zImposterPK); - sqlite3_free(zWhere); - sqlite3_free(zBind); - sqlite3_free(zPart); - }else{ - int bRbuRowid = (pIter->eType==RBU_PK_VTAB) - ||(pIter->eType==RBU_PK_NONE) - ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)); - const char *zTbl = pIter->zTbl; /* Table this step applies to */ - const char *zWrite; /* Imposter table name */ - - char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); - char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); - - zCollist = rbuObjIterGetCollist(p, pIter); - pIter->nCol = pIter->nTblCol; - - /* Create the imposter table or tables (if required). */ - rbuCreateImposterTable(p, pIter); - rbuCreateImposterTable2(p, pIter); - zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); - - /* Create the INSERT statement to write to the target PK b-tree */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, - sqlite3_mprintf( - "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", - zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings - ) - ); - } - - /* Create the DELETE statement to write to the target PK b-tree. - ** Because it only performs INSERT operations, this is not required for - ** an rbu vacuum handle. */ - if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, - sqlite3_mprintf( - "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere - ) - ); - } - - if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ - const char *zRbuRowid = ""; - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zRbuRowid = ", rbu_rowid"; - } - - /* Create the rbu_tmp_xxx table and the triggers to populate it. */ - rbuMPrintfExec(p, p->dbRbu, - "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " - "SELECT *%s FROM '%q' WHERE 0;" - , p->zStateDb, pIter->zDataTbl - , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") - , pIter->zDataTbl - ); - - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(4, %s);" - "END;", - zWrite, zTbl, zOldlist, - zWrite, zTbl, zOldlist, - zWrite, zTbl, zNewlist - ); - - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(0, %s);" - "END;", - zWrite, zTbl, zNewlist - ); - } - - rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); - } - - /* Create the SELECT statement to read keys from data_xxx */ - if( p->rc==SQLITE_OK ){ - const char *zRbuRowid = ""; - char *zStart = 0; - char *zOrder = 0; - if( bRbuRowid ){ - zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; - } - - if( rbuIsVacuum(p) ){ - if( nOffset ){ - zStart = rbuVacuumTableStart(p, pIter, bRbuRowid, zWrite); - if( zStart ){ - sqlite3_free(zLimit); - zLimit = 0; - } - } - if( bRbuRowid ){ - zOrder = rbuMPrintf(p, "_rowid_"); - }else{ - zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", ""); - } - } - - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, - sqlite3_mprintf( - "SELECT %s,%s rbu_control%s FROM '%q'%s %s %s %s", - zCollist, - (rbuIsVacuum(p) ? "0 AS " : ""), - zRbuRowid, - pIter->zDataTbl, (zStart ? zStart : ""), - (zOrder ? "ORDER BY" : ""), zOrder, - zLimit - ) - ); - } - sqlite3_free(zStart); - sqlite3_free(zOrder); - } - - sqlite3_free(zWhere); - sqlite3_free(zOldlist); - sqlite3_free(zNewlist); - sqlite3_free(zBindings); - } - sqlite3_free(zCollist); - sqlite3_free(zLimit); - } - - return p->rc; -} - -/* -** Set output variable *ppStmt to point to an UPDATE statement that may -** be used to update the imposter table for the main table b-tree of the -** table object that pIter currently points to, assuming that the -** rbu_control column of the data_xyz table contains zMask. -** -** If the zMask string does not specify any columns to update, then this -** is not an error. Output variable *ppStmt is set to NULL in this case. -*/ -static int rbuGetUpdateStmt( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter, /* Object iterator */ - const char *zMask, /* rbu_control value ('x.x.') */ - sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */ -){ - RbuUpdateStmt **pp; - RbuUpdateStmt *pUp = 0; - int nUp = 0; - - /* In case an error occurs */ - *ppStmt = 0; - - /* Search for an existing statement. If one is found, shift it to the front - ** of the LRU queue and return immediately. Otherwise, leave nUp pointing - ** to the number of statements currently in the cache and pUp to the - ** last object in the list. */ - for(pp=&pIter->pRbuUpdate; *pp; pp=&((*pp)->pNext)){ - pUp = *pp; - if( strcmp(pUp->zMask, zMask)==0 ){ - *pp = pUp->pNext; - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - *ppStmt = pUp->pUpdate; - return SQLITE_OK; - } - nUp++; - } - assert( pUp==0 || pUp->pNext==0 ); - - if( nUp>=SQLITE_RBU_UPDATE_CACHESIZE ){ - for(pp=&pIter->pRbuUpdate; *pp!=pUp; pp=&((*pp)->pNext)); - *pp = 0; - sqlite3_finalize(pUp->pUpdate); - pUp->pUpdate = 0; - }else{ - pUp = (RbuUpdateStmt*)rbuMalloc(p, sizeof(RbuUpdateStmt)+pIter->nTblCol+1); - } - - if( pUp ){ - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zSet = rbuObjIterGetSetlist(p, pIter, zMask); - char *zUpdate = 0; - - pUp->zMask = (char*)&pUp[1]; - memcpy(pUp->zMask, zMask, pIter->nTblCol); - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - - if( zSet ){ - const char *zPrefix = ""; - - if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_"; - zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", - zPrefix, pIter->zTbl, zSet, zWhere - ); - p->rc = prepareFreeAndCollectError( - p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate - ); - *ppStmt = pUp->pUpdate; - } - sqlite3_free(zWhere); - sqlite3_free(zSet); - } - - return p->rc; -} - -static sqlite3 *rbuOpenDbhandle( - sqlite3rbu *p, - const char *zName, - int bUseVfs -){ - sqlite3 *db = 0; - if( p->rc==SQLITE_OK ){ - const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; - p->rc = sqlite3_open_v2(zName, &db, flags, bUseVfs ? p->zVfsName : 0); - if( p->rc ){ - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - sqlite3_close(db); - db = 0; - } - } - return db; -} - -/* -** Free an RbuState object allocated by rbuLoadState(). -*/ -static void rbuFreeState(RbuState *p){ - if( p ){ - sqlite3_free(p->zTbl); - sqlite3_free(p->zDataTbl); - sqlite3_free(p->zIdx); - sqlite3_free(p); - } -} - -/* -** Allocate an RbuState object and load the contents of the rbu_state -** table into it. Return a pointer to the new object. It is the -** responsibility of the caller to eventually free the object using -** sqlite3_free(). -** -** If an error occurs, leave an error code and message in the rbu handle -** and return NULL. -*/ -static RbuState *rbuLoadState(sqlite3rbu *p){ - RbuState *pRet = 0; - sqlite3_stmt *pStmt = 0; - int rc; - int rc2; - - pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); - if( pRet==0 ) return 0; - - rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - switch( sqlite3_column_int(pStmt, 0) ){ - case RBU_STATE_STAGE: - pRet->eStage = sqlite3_column_int(pStmt, 1); - if( pRet->eStage!=RBU_STAGE_OAL - && pRet->eStage!=RBU_STAGE_MOVE - && pRet->eStage!=RBU_STAGE_CKPT - ){ - p->rc = SQLITE_CORRUPT; - } - break; - - case RBU_STATE_TBL: - pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_IDX: - pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_ROW: - pRet->nRow = sqlite3_column_int(pStmt, 1); - break; - - case RBU_STATE_PROGRESS: - pRet->nProgress = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_CKPT: - pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_COOKIE: - pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_OALSZ: - pRet->iOalSz = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_PHASEONESTEP: - pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_DATATBL: - pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - default: - rc = SQLITE_CORRUPT; - break; - } - } - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - - p->rc = rc; - return pRet; -} - - -/* -** 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(sqlite3rbu *p, 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) ){ - sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); - if( p->zState==0 ){ - const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); - p->zState = rbuMPrintf(p, "file:///%s-vacuum?modeof=%s", zFile, zFile); - } - } - - /* If using separate RBU and state databases, attach the state database to - ** the RBU db handle now. */ - if( p->zState ){ - rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); - memcpy(p->zStateDb, "stat", 4); - }else{ - memcpy(p->zStateDb, "main", 4); - } - -#if 0 - if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ - p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, 0); - } -#endif - - /* If it has not already been created, create the rbu_state table */ - rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); - -#if 0 - if( rbuIsVacuum(p) ){ - if( p->rc==SQLITE_OK ){ - int rc2; - int bOk = 0; - sqlite3_stmt *pCnt = 0; - p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg, - "SELECT count(*) FROM stat.sqlite_schema" - ); - if( p->rc==SQLITE_OK - && sqlite3_step(pCnt)==SQLITE_ROW - && 1==sqlite3_column_int(pCnt, 0) - ){ - bOk = 1; - } - rc2 = sqlite3_finalize(pCnt); - if( p->rc==SQLITE_OK ) p->rc = rc2; - - if( p->rc==SQLITE_OK && bOk==0 ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("invalid state database"); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); - } - } - } -#endif - - if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ - int bOpen = 0; - int rc; - p->nRbu = 0; - p->pRbuFd = 0; - rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); - if( rc!=SQLITE_NOTFOUND ) p->rc = rc; - if( p->eStage>=RBU_STAGE_MOVE ){ - bOpen = 1; - }else{ - RbuState *pState = rbuLoadState(p); - if( pState ){ - bOpen = (pState->eStage>=RBU_STAGE_MOVE); - rbuFreeState(pState); - } - } - if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1); - } - - p->eStage = 0; - if( p->rc==SQLITE_OK && p->dbMain==0 ){ - if( !rbuIsVacuum(p) ){ - p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1); - }else if( p->pRbuFd->pWalFd ){ - if( pbRetry ){ - p->pRbuFd->bNolock = 0; - sqlite3_close(p->dbRbu); - sqlite3_close(p->dbMain); - p->dbMain = 0; - p->dbRbu = 0; - *pbRetry = 1; - return; - } - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database"); - }else{ - char *zTarget; - char *zExtra = 0; - if( strlen(p->zRbu)>=5 && 0==memcmp("file:", p->zRbu, 5) ){ - zExtra = &p->zRbu[5]; - while( *zExtra ){ - if( *zExtra++=='?' ) break; - } - if( *zExtra=='\0' ) zExtra = 0; - } - - zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s", - sqlite3_db_filename(p->dbRbu, "main"), - (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra) - ); - - if( zTarget==0 ){ - p->rc = SQLITE_NOMEM; - return; - } - p->dbMain = rbuOpenDbhandle(p, zTarget, p->nRbu<=1); - sqlite3_free(zTarget); - } - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbRbu, - "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_schema"); - - /* Mark the database file just opened as an RBU target database. If - ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. - ** This is an error. */ - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - - if( p->rc==SQLITE_NOTFOUND ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("rbu vfs not found"); - } -} - -/* -** This routine is a copy of the sqlite3FileSuffix3() routine from the core. -** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. -** -** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database -** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and -** if filename in z[] has a suffix (a.k.a. "extension") that is longer than -** three characters, then shorten the suffix on z[] to be the last three -** characters of the original suffix. -** -** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always -** do the suffix shortening regardless of URI parameter. -** -** Examples: -** -** test.db-journal => test.nal -** test.db-wal => test.wal -** test.db-shm => test.shm -** test.db-mj7f3319fa => test.9fa -*/ -static void rbuFileSuffix3(const char *zBase, char *z){ -#ifdef SQLITE_ENABLE_8_3_NAMES -#if SQLITE_ENABLE_8_3_NAMES<2 - if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) -#endif - { - int i, sz; - sz = (int)strlen(z)&0xffffff; - for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} - if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); - } -#else - UNUSED_PARAMETER2(zBase,z); -#endif -} - -/* -** Return the current wal-index header checksum for the target database -** as a 64-bit integer. -** -** The checksum is store in the first page of xShmMap memory as an 8-byte -** blob starting at byte offset 40. -*/ -static i64 rbuShmChecksum(sqlite3rbu *p){ - i64 iRet = 0; - if( p->rc==SQLITE_OK ){ - sqlite3_file *pDb = p->pTargetFd->pReal; - u32 volatile *ptr; - p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); - if( p->rc==SQLITE_OK ){ - iRet = (i64)(((u64)ptr[10] << 32) + ptr[11]); - } - } - return iRet; -} - -/* -** This function is called as part of initializing or reinitializing an -** incremental checkpoint. -** -** It populates the sqlite3rbu.aFrame[] array with the set of -** (wal frame -> db page) copy operations required to checkpoint the -** current wal file, and obtains the set of shm locks required to safely -** perform the copy operations directly on the file-system. -** -** If argument pState is not NULL, then the incremental checkpoint is -** being resumed. In this case, if the checksum of the wal-index-header -** following recovery is not the same as the checksum saved in the RbuState -** object, then the rbu handle is set to DONE state. This occurs if some -** other client appends a transaction to the wal file in the middle of -** an incremental checkpoint. -*/ -static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){ - - /* If pState is NULL, then the wal file may not have been opened and - ** recovered. Running a read-statement here to ensure that doing so - ** does not interfere with the "capture" process below. */ - if( pState==0 ){ - p->eStage = 0; - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_schema", 0, 0, 0); - } - } - - /* Assuming no error has occurred, run a "restart" checkpoint with the - ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following - ** special behaviour in the rbu VFS: - ** - ** * If the exclusive shm WRITER or READ0 lock cannot be obtained, - ** the checkpoint fails with SQLITE_BUSY (normally SQLite would - ** proceed with running a passive checkpoint instead of failing). - ** - ** * Attempts to read from the *-wal file or write to the database file - ** do not perform any IO. Instead, the frame/page combinations that - ** would be read/written are recorded in the sqlite3rbu.aFrame[] - ** array. - ** - ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, - ** READ0 and CHECKPOINT locks taken as part of the checkpoint are - ** no-ops. These locks will not be released until the connection - ** is closed. - ** - ** * Attempting to xSync() the database file causes an SQLITE_NOTICE - ** error. - ** - ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the - ** checkpoint below fails with SQLITE_NOTICE, and leaves the aFrame[] - ** array populated with a set of (frame -> page) mappings. Because the - ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy - ** data from the wal file into the database file according to the - ** contents of aFrame[]. - */ - if( p->rc==SQLITE_OK ){ - int rc2; - p->eStage = RBU_STAGE_CAPTURE; - rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); - if( rc2!=SQLITE_NOTICE ) p->rc = rc2; - } - - if( p->rc==SQLITE_OK && p->nFrame>0 ){ - p->eStage = RBU_STAGE_CKPT; - p->nStep = (pState ? pState->nRow : 0); - p->aBuf = rbuMalloc(p, p->pgsz); - p->iWalCksum = rbuShmChecksum(p); - } - - if( p->rc==SQLITE_OK ){ - if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ - p->rc = SQLITE_DONE; - p->eStage = RBU_STAGE_DONE; - }else{ - int nSectorSize; - sqlite3_file *pDb = p->pTargetFd->pReal; - sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; - assert( p->nPagePerSector==0 ); - nSectorSize = pDb->pMethods->xSectorSize(pDb); - if( nSectorSize>p->pgsz ){ - p->nPagePerSector = nSectorSize / p->pgsz; - }else{ - p->nPagePerSector = 1; - } - - /* Call xSync() on the wal file. This causes SQLite to sync the - ** directory in which the target database and the wal file reside, in - ** case it has not been synced since the rename() call in - ** rbuMoveOalFile(). */ - p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); - } - } -} - -/* -** Called when iAmt bytes are read from offset iOff of the wal file while -** the rbu object is in capture mode. Record the frame number of the frame -** being read in the aFrame[] array. -*/ -static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ - const u32 mReq = (1<mLock!=mReq ){ - pRbu->rc = SQLITE_BUSY; - return SQLITE_NOTICE_RBU; - } - - pRbu->pgsz = iAmt; - if( pRbu->nFrame==pRbu->nFrameAlloc ){ - int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; - RbuFrame *aNew; - aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame)); - if( aNew==0 ) return SQLITE_NOMEM; - pRbu->aFrame = aNew; - pRbu->nFrameAlloc = nNew; - } - - iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; - if( pRbu->iMaxFrame